From 615a576d01c8ae41813a5293bde10c68f6fbdc2a Mon Sep 17 00:00:00 2001 From: DWJ <130666881+DWJ-Squirtle@users.noreply.github.com> Date: Wed, 24 Jul 2024 15:46:50 +0800 Subject: [PATCH 01/45] chore: add check tls and uint testing (#7810) --- controllers/apps/transformer_component_tls.go | 7 ++- .../apps/transformer_component_tls_test.go | 45 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/controllers/apps/transformer_component_tls.go b/controllers/apps/transformer_component_tls.go index 109912e19dac..2b1ca1fc3fd4 100644 --- a/controllers/apps/transformer_component_tls.go +++ b/controllers/apps/transformer_component_tls.go @@ -25,6 +25,7 @@ import ( "strings" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" @@ -147,7 +148,11 @@ func buildTLSCert(ctx context.Context, cli client.Reader, synthesizedComp compon return err } case appsv1alpha1.IssuerKubeBlocks: - // TODO: (good-first-issue) should check if the secret exists, skip if already exists + secretName := plan.GenerateTLSSecretName(synthesizedComp.ClusterName, synthesizedComp.Name) + preSecret := &corev1.Secret{} + if err := cli.Get(ctx, types.NamespacedName{Namespace: synthesizedComp.Namespace, Name: secretName}, preSecret); !errors.IsNotFound(err) { + return err + } secret, err := plan.ComposeTLSSecret(synthesizedComp.Namespace, synthesizedComp.ClusterName, synthesizedComp.Name) if err != nil { return err diff --git a/controllers/apps/transformer_component_tls_test.go b/controllers/apps/transformer_component_tls_test.go index 98d33dd11e4c..850e245eec3f 100644 --- a/controllers/apps/transformer_component_tls_test.go +++ b/controllers/apps/transformer_component_tls_test.go @@ -35,6 +35,8 @@ import ( appsv1beta1 "github.com/apecloud/kubeblocks/apis/apps/v1beta1" cfgcore "github.com/apecloud/kubeblocks/pkg/configuration/core" "github.com/apecloud/kubeblocks/pkg/constant" + "github.com/apecloud/kubeblocks/pkg/controller/component" + "github.com/apecloud/kubeblocks/pkg/controller/graph" "github.com/apecloud/kubeblocks/pkg/controller/plan" "github.com/apecloud/kubeblocks/pkg/generics" testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" @@ -213,5 +215,48 @@ var _ = Describe("TLS self-signed cert function", func() { Eventually(testapps.CheckObjExists(&testCtx, clusterKey, &appsv1alpha1.Cluster{}, false)).Should(Succeed()) }) }) + Context("when issuer is KubeBlocks check secret exists or not", func() { + var ( + kbTLSSecretObj *corev1.Secret + synthesizedComp component.SynthesizedComponent + dag *graph.DAG + err error + ) + BeforeEach(func() { + synthesizedComp = component.SynthesizedComponent{ + Namespace: testCtx.DefaultNamespace, + ClusterName: "test-kb", + Name: "test-kb-tls", + TLSConfig: &appsv1alpha1.TLSConfig{ + Enable: true, + Issuer: &appsv1alpha1.Issuer{ + Name: appsv1alpha1.IssuerKubeBlocks, + }, + }, + } + dag = &graph.DAG{} + kbTLSSecretObj, err = plan.ComposeTLSSecret(testCtx.DefaultNamespace, synthesizedComp.ClusterName, synthesizedComp.Name) + Expect(err).Should(BeNil()) + Expect(k8sClient.Create(ctx, kbTLSSecretObj)).Should(Succeed()) + }) + AfterEach(func() { + // delete self provided tls certs secret + Expect(k8sClient.Delete(ctx, kbTLSSecretObj)).Should(Succeed()) + Eventually(func() bool { + err := k8sClient.Get(ctx, + client.ObjectKeyFromObject(kbTLSSecretObj), + kbTLSSecretObj) + return apierrors.IsNotFound(err) + }).Should(BeTrue()) + }) + It("should skip if the existence of the secret is confirmed", func() { + err := buildTLSCert(ctx, k8sClient, synthesizedComp, dag) + Expect(err).Should(BeNil()) + createdSecret := &corev1.Secret{} + err = k8sClient.Get(ctx, types.NamespacedName{Namespace: testCtx.DefaultNamespace, Name: kbTLSSecretObj.Name}, createdSecret) + Expect(err).Should(BeNil()) + Expect(createdSecret.Data).To(Equal(kbTLSSecretObj.Data)) + }) + }) }) }) From 666b99fe8ada9f9d152ac76ca71fd1b5486d3ada Mon Sep 17 00:00:00 2001 From: loomt Date: Wed, 24 Jul 2024 15:50:55 +0800 Subject: [PATCH 02/45] fix: use ca gen cert file insteat of selfsign ca (#7716) --- pkg/controller/plan/tls_utils.go | 34 ++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/pkg/controller/plan/tls_utils.go b/pkg/controller/plan/tls_utils.go index 9c2e1de04bc3..84fb2f0da0c0 100644 --- a/pkg/controller/plan/tls_utils.go +++ b/pkg/controller/plan/tls_utils.go @@ -22,6 +22,7 @@ package plan import ( "bytes" "context" + "fmt" "strings" "text/template" @@ -50,23 +51,30 @@ func ComposeTLSSecret(namespace, clusterName, componentName string) (*v1.Secret, SetStringData(map[string]string{}). GetObject() - const tpl = `{{- $cert := genCA "KubeBlocks" 36500 }} -{{ $cert.Cert }} -{{ $cert.Key }} -` - out, err := buildFromTemplate(tpl, nil) + // use ca gen cert + // IP: 127.0.0.1 and ::1 + // DNS: localhost and *.--headless..svc.cluster.local + const spliter = "___spliter___" + SignedCertTpl := fmt.Sprintf(` + {{- $ca := genCA "KubeBlocks" 36500 -}} + {{- $cert := genSignedCert "%s peer" (list "127.0.0.1" "::1") (list "localhost" "*.%s-%s-headless.%s.svc.cluster.local") 36500 $ca -}} + {{- $ca.Cert -}} + {{- print "%s" -}} + {{- $cert.Cert -}} + {{- print "%s" -}} + {{- $cert.Key -}} +`, componentName, clusterName, componentName, namespace, spliter, spliter) + out, err := buildFromTemplate(SignedCertTpl, nil) if err != nil { return nil, err } - index := strings.Index(out, "-----BEGIN RSA PRIVATE KEY-----") - if index < 0 { - return nil, errors.Errorf("wrong cert format: %s", out) + parts := strings.Split(out, spliter) + if len(parts) != 3 { + return nil, errors.Errorf("generate TLS certificates failed with cluster name %s, component name %s in namespace %s", clusterName, componentName, namespace) } - cert := out[:index] - key := out[index:] - secret.StringData[constant.CAName] = cert - secret.StringData[constant.CertName] = cert - secret.StringData[constant.KeyName] = key + secret.StringData[constant.CAName] = parts[0] + secret.StringData[constant.CertName] = parts[1] + secret.StringData[constant.KeyName] = parts[2] return secret, nil } From 06ef166282e72df2a8d7e117e4d12ded0ed000f0 Mon Sep 17 00:00:00 2001 From: xingran Date: Wed, 24 Jul 2024 17:56:47 +0800 Subject: [PATCH 03/45] chore: set component ownership independent when build component assistant object (#7864) --- controllers/apps/component_controller.go | 2 - .../apps/transformer_component_account.go | 12 ++-- .../apps/transformer_component_rbac.go | 19 ++++-- .../apps/transformer_component_restore.go | 3 +- .../apps/transformer_component_service.go | 7 ++- ...ship.go => transformer_component_utils.go} | 60 ++++--------------- .../apps/transformer_component_vars.go | 9 ++- .../apps/transformer_component_workload.go | 3 + 8 files changed, 50 insertions(+), 65 deletions(-) rename controllers/apps/{transformer_component_ownership.go => transformer_component_utils.go} (54%) diff --git a/controllers/apps/component_controller.go b/controllers/apps/component_controller.go index 212604aac456..8a7c15b7396b 100644 --- a/controllers/apps/component_controller.go +++ b/controllers/apps/component_controller.go @@ -184,8 +184,6 @@ func (r *ComponentReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( &componentWorkloadTransformer{Client: r.Client}, // handle RBAC for component workloads &componentRBACTransformer{}, - // add our finalizer to all objects - &componentOwnershipTransformer{}, // handle component postProvision lifecycle action &componentPostProvisionTransformer{}, // update component status diff --git a/controllers/apps/transformer_component_account.go b/controllers/apps/transformer_component_account.go index 95d647641cf1..5a42697c673f 100644 --- a/controllers/apps/transformer_component_account.go +++ b/controllers/apps/transformer_component_account.go @@ -103,7 +103,7 @@ func (t *componentAccountTransformer) buildAccountSecret(ctx *componentTransform default: password = t.buildPassword(ctx, account) } - return t.buildAccountSecretWithPassword(synthesizeComp, account, password), nil + return t.buildAccountSecretWithPassword(ctx, synthesizeComp, account, password) } func (t *componentAccountTransformer) getPasswordFromSecret(ctx graph.TransformContext, account appsv1alpha1.SystemAccount) ([]byte, error) { @@ -147,15 +147,19 @@ func (t *componentAccountTransformer) generatePassword(account appsv1alpha1.Syst return []byte(passwd) } -func (t *componentAccountTransformer) buildAccountSecretWithPassword(synthesizeComp *component.SynthesizedComponent, - account appsv1alpha1.SystemAccount, password []byte) *corev1.Secret { +func (t *componentAccountTransformer) buildAccountSecretWithPassword(ctx *componentTransformContext, + synthesizeComp *component.SynthesizedComponent, account appsv1alpha1.SystemAccount, password []byte) (*corev1.Secret, error) { secretName := constant.GenerateAccountSecretName(synthesizeComp.ClusterName, synthesizeComp.Name, account.Name) labels := constant.GetComponentWellKnownLabels(synthesizeComp.ClusterName, synthesizeComp.Name) - return builder.NewSecretBuilder(synthesizeComp.Namespace, secretName). + secret := builder.NewSecretBuilder(synthesizeComp.Namespace, secretName). AddLabelsInMap(labels). AddLabels(constant.ClusterAccountLabelKey, account.Name). PutData(constant.AccountNameForSecret, []byte(account.Name)). PutData(constant.AccountPasswdForSecret, password). SetImmutable(true). GetObject() + if err := setCompOwnershipNFinalizer(ctx.Component, secret); err != nil { + return nil, err + } + return secret, nil } diff --git a/controllers/apps/transformer_component_rbac.go b/controllers/apps/transformer_component_rbac.go index 0736d4bc324a..d3cd4cd5be49 100644 --- a/controllers/apps/transformer_component_rbac.go +++ b/controllers/apps/transformer_component_rbac.go @@ -80,7 +80,10 @@ func (t *componentRBACTransformer) Transform(ctx graph.TransformContext, dag *gr } var parent client.Object - rb := buildRoleBinding(transCtx.Cluster, serviceAccount.Name) + rb, err := buildRoleBinding(transCtx.Cluster, transCtx.Component, serviceAccount.Name) + if err != nil { + return err + } graphCli.Create(dag, rb, inDataContext4G()) parent = rb if needCRB { @@ -280,14 +283,20 @@ func buildServiceAccount(transCtx *componentTransformContext) (*corev1.ServiceAc } } - buildSa := factory.BuildServiceAccount(cluster, serviceAccountName) + saObj := factory.BuildServiceAccount(cluster, serviceAccountName) + if err := setCompOwnershipNFinalizer(comp, saObj); err != nil { + return nil, false, err + } // if volume protection is enabled, the service account needs to be bound to the clusterRoleBinding. - return buildSa, volumeProtectionEnable, nil + return saObj, volumeProtectionEnable, nil } -func buildRoleBinding(cluster *appsv1alpha1.Cluster, serviceAccountName string) *rbacv1.RoleBinding { +func buildRoleBinding(cluster *appsv1alpha1.Cluster, comp *appsv1alpha1.Component, serviceAccountName string) (*rbacv1.RoleBinding, error) { roleBinding := factory.BuildRoleBinding(cluster, serviceAccountName) - return roleBinding + if err := setCompOwnershipNFinalizer(comp, roleBinding); err != nil { + return nil, err + } + return roleBinding, nil } func createServiceAccount(serviceAccount *corev1.ServiceAccount, graphCli model.GraphClient, dag *graph.DAG, parent client.Object) { diff --git a/controllers/apps/transformer_component_restore.go b/controllers/apps/transformer_component_restore.go index 79b654e35b32..21232db9873e 100644 --- a/controllers/apps/transformer_component_restore.go +++ b/controllers/apps/transformer_component_restore.go @@ -41,7 +41,6 @@ var _ graph.Transformer = &componentRestoreTransformer{} func (t *componentRestoreTransformer) Transform(ctx graph.TransformContext, dag *graph.DAG) error { transCtx, _ := ctx.(*componentTransformContext) - graphCli, _ := transCtx.Client.(model.GraphClient) synthesizedComp := transCtx.SynthesizeComponent if synthesizedComp.Annotations[constant.RestoreFromBackupAnnotationKey] == "" { return nil @@ -54,7 +53,7 @@ func (t *componentRestoreTransformer) Transform(ctx graph.TransformContext, dag commitError := func(err error) error { if intctrlutil.IsTargetError(err, intctrlutil.ErrorTypeNeedWaiting) { transCtx.EventRecorder.Event(transCtx.Cluster, corev1.EventTypeNormal, string(intctrlutil.ErrorTypeNeedWaiting), err.Error()) - return errPrematureStopWithSetCompOwnership(transCtx.Component, dag, graphCli) + return graph.ErrPrematureStop } return err } diff --git a/controllers/apps/transformer_component_service.go b/controllers/apps/transformer_component_service.go index 5e866649f4b3..87aec4571f0a 100644 --- a/controllers/apps/transformer_component_service.go +++ b/controllers/apps/transformer_component_service.go @@ -211,7 +211,12 @@ func (t *componentServiceTransformer) buildService(comp *appsv1alpha1.Component, } builder.AddSelector(constant.RoleLabelKey, service.RoleSelector) } - return builder.GetObject(), nil + + svcObj := builder.GetObject() + if err := setCompOwnershipNFinalizer(comp, svcObj); err != nil { + return nil, err + } + return svcObj, nil } func (t *componentServiceTransformer) builtinSelector(comp *appsv1alpha1.Component) map[string]string { diff --git a/controllers/apps/transformer_component_ownership.go b/controllers/apps/transformer_component_utils.go similarity index 54% rename from controllers/apps/transformer_component_ownership.go rename to controllers/apps/transformer_component_utils.go index 247ad27f9655..e3f695648700 100644 --- a/controllers/apps/transformer_component_ownership.go +++ b/controllers/apps/transformer_component_utils.go @@ -30,44 +30,26 @@ import ( appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" "github.com/apecloud/kubeblocks/pkg/constant" - "github.com/apecloud/kubeblocks/pkg/controller/graph" - "github.com/apecloud/kubeblocks/pkg/controller/model" intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" ) -// componentOwnershipTransformer adds finalizer to all none component objects -type componentOwnershipTransformer struct{} - -var _ graph.Transformer = &componentOwnershipTransformer{} - -func (f *componentOwnershipTransformer) Transform(ctx graph.TransformContext, dag *graph.DAG) error { - transCtx, _ := ctx.(*componentTransformContext) - graphCli, _ := transCtx.Client.(model.GraphClient) - comp := transCtx.Component - return setCompOwnership(comp, dag, graphCli) -} - -func setCompOwnership(comp *appsv1alpha1.Component, dag *graph.DAG, graphCli model.GraphClient) error { - // find all objects that are not component and set ownership to the component - objects := graphCli.FindAll(dag, &appsv1alpha1.Component{}, &model.HaveDifferentTypeWithOption{}) - for _, object := range objects { - if skipSetCompOwnership(object) { - continue - } - // add finalizer to the object - addFinalizer(object, comp) - if err := intctrlutil.SetOwnership(comp, object, rscheme, ""); err != nil { - if _, ok := err.(*controllerutil.AlreadyOwnedError); ok { - continue - } - return err +func setCompOwnershipNFinalizer(comp *appsv1alpha1.Component, object client.Object) error { + if skipSetCompOwnershipNFinalizer(object) { + return nil + } + // add finalizer to the object + addFinalizer(object, comp) + if err := intctrlutil.SetOwnership(comp, object, rscheme, ""); err != nil { + if _, ok := err.(*controllerutil.AlreadyOwnedError); ok { + return nil } + return err } return nil } -// skipSetCompOwnership returns true if the object should not be set ownership to the component -func skipSetCompOwnership(obj client.Object) bool { +// skipSetCompOwnershipNFinalizer returns true if the object should not be set ownership to the component +func skipSetCompOwnershipNFinalizer(obj client.Object) bool { switch obj.(type) { case *rbacv1.ClusterRoleBinding, *corev1.PersistentVolume, *corev1.PersistentVolumeClaim, *corev1.Pod: return true @@ -102,21 +84,3 @@ func skipAddCompFinalizer(obj client.Object, comp *appsv1alpha1.Component) bool } return false } - -// errPrematureStopWithSetCompOwnership is a helper function that sets component ownership and returns graph.ErrPrematureStop -// TODO: remove this function to independent component transformer utils -func errPrematureStopWithSetCompOwnership(comp *appsv1alpha1.Component, dag *graph.DAG, graphCli model.GraphClient) error { - err := setCompOwnership(comp, dag, graphCli) - if err != nil { - return err - } - return graph.ErrPrematureStop -} - -// errWithSetCompOwnership is a helper function that sets component ownership before returns err -// TODO: refactor to set ownership information when creating each object, instead of setting it uniformly. -func errWithSetCompOwnership(comp *appsv1alpha1.Component, dag *graph.DAG, cli client.Reader, err error) error { - graphCli, _ := cli.(model.GraphClient) - _ = setCompOwnership(comp, dag, graphCli) - return err -} diff --git a/controllers/apps/transformer_component_vars.go b/controllers/apps/transformer_component_vars.go index 6df233ce0165..ea13a8fd64dd 100644 --- a/controllers/apps/transformer_component_vars.go +++ b/controllers/apps/transformer_component_vars.go @@ -62,7 +62,7 @@ func (t *componentVarsTransformer) Transform(ctx graph.TransformContext, dag *gr legacy, err := generatedComponent4LegacyCluster(transCtx) if err != nil { - return errWithSetCompOwnership(transCtx.Component, dag, graphCli, err) + return err } var templateVars map[string]any @@ -75,7 +75,7 @@ func (t *componentVarsTransformer) Transform(ctx graph.TransformContext, dag *gr synthesizedComp, transCtx.CompDef.Spec.Vars) } if err != nil { - return errWithSetCompOwnership(transCtx.Component, dag, graphCli, err) + return err } // pass all direct value env vars through CM @@ -83,7 +83,7 @@ func (t *componentVarsTransformer) Transform(ctx graph.TransformContext, dag *gr setTemplateNEnvVars(synthesizedComp, templateVars, envVars2, legacy) if err := createOrUpdateEnvConfigMap(ctx, dag, envData); err != nil { - return errWithSetCompOwnership(transCtx.Component, dag, graphCli, err) + return err } return nil } @@ -181,6 +181,9 @@ func createOrUpdateEnvConfigMap(ctx graph.TransformContext, dag *graph.DAG, data AddLabelsInMap(constant.GetComponentWellKnownLabels(synthesizedComp.ClusterName, synthesizedComp.Name)). SetData(data). GetObject() + if err := setCompOwnershipNFinalizer(transCtx.Component, obj); err != nil { + return err + } graphCli.Create(dag, obj, inDataContext4G()) } else if !reflect.DeepEqual(envObj.Data, data) { envObjCopy := envObj.DeepCopy() diff --git a/controllers/apps/transformer_component_workload.go b/controllers/apps/transformer_component_workload.go index 04fd69c40005..8bce908f9d5b 100644 --- a/controllers/apps/transformer_component_workload.go +++ b/controllers/apps/transformer_component_workload.go @@ -108,6 +108,9 @@ func (t *componentWorkloadTransformer) Transform(ctx graph.TransformContext, dag graphCli, _ := transCtx.Client.(model.GraphClient) if runningITS == nil { if protoITS != nil { + if err := setCompOwnershipNFinalizer(transCtx.Component, protoITS); err != nil { + return err + } graphCli.Create(dag, protoITS) return nil } From 9bd439faaaa2f4cabfa4ef98d5c4f8a031fb42eb Mon Sep 17 00:00:00 2001 From: wangyelei Date: Thu, 25 Jul 2024 15:46:27 +0800 Subject: [PATCH 04/45] fix: create multi pod failed when the pod selection strategy is All for custom ops (#7872) --- controllers/apps/operations/custom/action_workload.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/controllers/apps/operations/custom/action_workload.go b/controllers/apps/operations/custom/action_workload.go index d75ff9b2f117..bad7447c1267 100644 --- a/controllers/apps/operations/custom/action_workload.go +++ b/controllers/apps/operations/custom/action_workload.go @@ -95,7 +95,9 @@ func (w *WorkloadAction) Execute(actionCtx ActionContext) (*ActionStatus, error) } return actionStatus, err } + actionPodSpecCopy := actionCtx.Action.Workload.PodSpec.DeepCopy() for i := range targetPods { + actionCtx.Action.Workload.PodSpec = *actionPodSpecCopy actionTask, err := executeAction(podInfoExtractor, targetPods[i], i) if err != nil { return nil, err From 34ec2f20921ea945bf060df57d1ae037bcc7ac13 Mon Sep 17 00:00:00 2001 From: Liang Deng <283304489@qq.com> Date: Thu, 25 Jul 2024 17:41:02 +0800 Subject: [PATCH 05/45] fix: podUpdatePolicy update issue (#7873) Signed-off-by: Liang Deng <283304489@qq.com> --- controllers/apps/transformer_cluster_component.go | 1 + 1 file changed, 1 insertion(+) diff --git a/controllers/apps/transformer_cluster_component.go b/controllers/apps/transformer_cluster_component.go index a0b41d5e6612..1095e4ab990c 100644 --- a/controllers/apps/transformer_cluster_component.go +++ b/controllers/apps/transformer_cluster_component.go @@ -218,6 +218,7 @@ func copyAndMergeComponent(oldCompObj, newCompObj *appsv1alpha1.Component) *apps // compObjCopy.Spec.Monitor = compProto.Spec.Monitor compObjCopy.Spec.EnabledLogs = compProto.Spec.EnabledLogs compObjCopy.Spec.ServiceAccountName = compProto.Spec.ServiceAccountName + compObjCopy.Spec.PodUpdatePolicy = compProto.Spec.PodUpdatePolicy compObjCopy.Spec.Affinity = compProto.Spec.Affinity compObjCopy.Spec.Tolerations = compProto.Spec.Tolerations compObjCopy.Spec.TLSConfig = compProto.Spec.TLSConfig From 8bacb40adc2e50f8f71a90d2f30ab973d541485d Mon Sep 17 00:00:00 2001 From: Leon Date: Fri, 26 Jul 2024 10:30:47 +0800 Subject: [PATCH 06/45] chore: remove clusterdefinition.spec.type (#7764) --- apis/apps/v1alpha1/clusterdefinition_types.go | 12 -------- ...apps.kubeblocks.io_clusterdefinitions.yaml | 11 ------- ...apps.kubeblocks.io_clusterdefinitions.yaml | 11 ------- docs/developer_docs/api-reference/cluster.md | 30 ------------------- pkg/constant/labels.go | 9 ------ pkg/controller/factory/builder.go | 3 -- pkg/controller/factory/builder_test.go | 7 ----- 7 files changed, 83 deletions(-) diff --git a/apis/apps/v1alpha1/clusterdefinition_types.go b/apis/apps/v1alpha1/clusterdefinition_types.go index 4d3587a68c53..84c25e9bff58 100644 --- a/apis/apps/v1alpha1/clusterdefinition_types.go +++ b/apis/apps/v1alpha1/clusterdefinition_types.go @@ -29,18 +29,6 @@ import ( // ClusterDefinitionSpec defines the desired state of ClusterDefinition. type ClusterDefinitionSpec struct { - // Specifies the well-known database type, such as mysql, redis, or mongodb. - // - // Deprecated since v0.9. - // This field is maintained for backward compatibility and its use is discouraged. - // Existing usage should be updated to the current preferred approach to avoid compatibility issues in future releases. - // - // +kubebuilder:validation:MaxLength=24 - // +kubebuilder:validation:Pattern:=`^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$` - // +kubebuilder:deprecatedversion:warning="This field has been deprecated since 0.9.0" - // +optional - Type string `json:"type,omitempty"` - // Provides the definitions for the cluster components. // // Deprecated since v0.9. diff --git a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml index b4f5fced7d4f..75d39ec2fbf5 100644 --- a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml @@ -9775,17 +9775,6 @@ spec: maxItems: 128 minItems: 1 type: array - type: - description: |- - Specifies the well-known database type, such as mysql, redis, or mongodb. - - - Deprecated since v0.9. - This field is maintained for backward compatibility and its use is discouraged. - Existing usage should be updated to the current preferred approach to avoid compatibility issues in future releases. - maxLength: 24 - pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ - type: string type: object status: description: ClusterDefinitionStatus defines the observed state of ClusterDefinition diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml index b4f5fced7d4f..75d39ec2fbf5 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml @@ -9775,17 +9775,6 @@ spec: maxItems: 128 minItems: 1 type: array - type: - description: |- - Specifies the well-known database type, such as mysql, redis, or mongodb. - - - Deprecated since v0.9. - This field is maintained for backward compatibility and its use is discouraged. - Existing usage should be updated to the current preferred approach to avoid compatibility issues in future releases. - maxLength: 24 - pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ - type: string type: object status: description: ClusterDefinitionStatus defines the observed state of ClusterDefinition diff --git a/docs/developer_docs/api-reference/cluster.md b/docs/developer_docs/api-reference/cluster.md index 4089b2ab918b..f00ad9111054 100644 --- a/docs/developer_docs/api-reference/cluster.md +++ b/docs/developer_docs/api-reference/cluster.md @@ -514,21 +514,6 @@ ClusterDefinitionSpec - - - - - - - - - - - - - - - - - - - -
-type
- -string - -
-(Optional) -

Specifies the well-known database type, such as mysql, redis, or mongodb.

-

Deprecated since v0.9. -This field is maintained for backward compatibility and its use is discouraged. -Existing usage should be updated to the current preferred approach to avoid compatibility issues in future releases.

-
componentDefs
@@ -5724,21 +5709,6 @@ and will not affect the life cycle of the pod. default values are 60 seconds.

-type
- -string - -
-(Optional) -

Specifies the well-known database type, such as mysql, redis, or mongodb.

-

Deprecated since v0.9. -This field is maintained for backward compatibility and its use is discouraged. -Existing usage should be updated to the current preferred approach to avoid compatibility issues in future releases.

-
componentDefs
diff --git a/pkg/constant/labels.go b/pkg/constant/labels.go index a2d6a2ce8cf4..b1bccfbabe74 100644 --- a/pkg/constant/labels.go +++ b/pkg/constant/labels.go @@ -46,7 +46,6 @@ const ( KBAppComponentLabelKey = "apps.kubeblocks.io/component-name" KBAppShardingNameLabelKey = "apps.kubeblocks.io/sharding-name" KBAppComponentDefRefLabelKey = "apps.kubeblocks.io/component-def-ref" // refer clusterDefinition.Spec.ComponentDefs[*].Name before KubeBlocks Version 0.8.0 or refer ComponentDefinition.Name after KubeBlocks Version 0.8.0 - KBAppClusterDefTypeLabelKey = "apps.kubeblocks.io/cluster-type" // refer clusterDefinition.Spec.Type (deprecated) KBManagedByKey = "apps.kubeblocks.io/managed-by" // KBManagedByKey marks resources that auto created PVCNameLabelKey = "apps.kubeblocks.io/pvc-name" VolumeClaimTemplateNameLabelKey = "apps.kubeblocks.io/vct-name" @@ -142,14 +141,6 @@ func GetClusterCompDefLabel(clusterCompDefName string) map[string]string { } } -// GetClusterDefTypeLabel returns the label for ClusterDefinition type (refer clusterDefinition.Spec.Type) -// TODO:clusterDefType will be deprecated in the future -func GetClusterDefTypeLabel(clusterDefType string) map[string]string { - return map[string]string{ - KBAppClusterDefTypeLabelKey: clusterDefType, - } -} - // GetKBReservedLabelKeys returns the reserved label keys for KubeBlocks func GetKBReservedLabelKeys() []string { return []string{ diff --git a/pkg/controller/factory/builder.go b/pkg/controller/factory/builder.go index 4e32f2b5157b..17e61897f47e 100644 --- a/pkg/controller/factory/builder.go +++ b/pkg/controller/factory/builder.go @@ -219,9 +219,6 @@ func BuildConnCredential(clusterDefinition *appsv1alpha1.ClusterDefinition, clus credentialBuilder := builder.NewSecretBuilder(cluster.Namespace, constant.GenerateDefaultConnCredential(cluster.Name)). AddLabelsInMap(wellKnownLabels). SetStringData(clusterDefinition.Spec.ConnectionCredential) - if len(clusterDefinition.Spec.Type) > 0 { - credentialBuilder.AddLabelsInMap(constant.GetClusterDefTypeLabel(clusterDefinition.Spec.Type)) - } connCredential := credentialBuilder.GetObject() if len(connCredential.StringData) == 0 { diff --git a/pkg/controller/factory/builder_test.go b/pkg/controller/factory/builder_test.go index 506c1e74595f..e051b0059a3b 100644 --- a/pkg/controller/factory/builder_test.go +++ b/pkg/controller/factory/builder_test.go @@ -187,13 +187,6 @@ var _ = Describe("builder", func() { ) credential := BuildConnCredential(clusterDef, cluster, synthesizedComponent) Expect(credential).ShouldNot(BeNil()) - Expect(credential.Labels[constant.KBAppClusterDefTypeLabelKey]).Should(BeEmpty()) - By("setting type") - characterType := "test-character-type" - clusterDef.Spec.Type = characterType - credential = BuildConnCredential(clusterDef, cluster, synthesizedComponent) - Expect(credential).ShouldNot(BeNil()) - Expect(credential.Labels[constant.KBAppClusterDefTypeLabelKey]).Should(Equal(characterType)) // "username": "root", // "SVC_FQDN": "$(SVC_FQDN)", // "RANDOM_PASSWD": "$(RANDOM_PASSWD)", From 0467683986676cf33def226c642951333eff01a1 Mon Sep 17 00:00:00 2001 From: Leon Date: Fri, 26 Jul 2024 11:31:23 +0800 Subject: [PATCH 07/45] chore: remove exporter and monitor from clusterdefinition (#7766) --- apis/apps/v1alpha1/clusterdefinition_types.go | 39 ----- .../v1alpha1/componentdefinition_types.go | 7 - apis/apps/v1alpha1/zz_generated.deepcopy.go | 51 ------ ...apps.kubeblocks.io_clusterdefinitions.yaml | 59 ------- ...ps.kubeblocks.io_componentdefinitions.yaml | 34 ---- ...apps.kubeblocks.io_clusterdefinitions.yaml | 59 ------- ...ps.kubeblocks.io_componentdefinitions.yaml | 34 ---- docs/developer_docs/api-reference/cluster.md | 149 +----------------- pkg/controller/component/component.go | 13 +- .../component/definition_convertor.go | 11 +- 10 files changed, 3 insertions(+), 453 deletions(-) diff --git a/apis/apps/v1alpha1/clusterdefinition_types.go b/apis/apps/v1alpha1/clusterdefinition_types.go index 84c25e9bff58..d18c87055efd 100644 --- a/apis/apps/v1alpha1/clusterdefinition_types.go +++ b/apis/apps/v1alpha1/clusterdefinition_types.go @@ -480,33 +480,6 @@ type ServiceRefDeclarationSpec struct { ServiceVersion string `json:"serviceVersion"` } -type ExporterConfig struct { - // scrapePort is exporter port for Time Series Database to scrape metrics. - // +kubebuilder:validation:Required - // +kubebuilder:validation:XIntOrString - ScrapePort intstr.IntOrString `json:"scrapePort"` - - // scrapePath is exporter url path for Time Series Database to scrape metrics. - // +kubebuilder:validation:MaxLength=128 - // +kubebuilder:default="/metrics" - // +optional - ScrapePath string `json:"scrapePath,omitempty"` -} - -type MonitorConfig struct { - // builtIn is a switch to enable KubeBlocks builtIn monitoring. - // If BuiltIn is set to true, monitor metrics will be scraped automatically. - // If BuiltIn is set to false, the provider should set ExporterConfig and Sidecar container own. - // +kubebuilder:default=false - // +optional - BuiltIn bool `json:"builtIn,omitempty"` - - // exporterConfig provided by provider, which specify necessary information to Time Series Database. - // exporterConfig is valid when builtIn is false. - // +optional - Exporter *ExporterConfig `json:"exporterConfig,omitempty"` -} - // ClusterComponentDefinition defines a Component within a ClusterDefinition but is deprecated and // has been replaced by ComponentDefinition. // @@ -683,18 +656,6 @@ type ClusterComponentDefinition struct { // // +optional ServiceRefDeclarations []ServiceRefDeclaration `json:"serviceRefDeclarations,omitempty"` - - // Defines the metrics exporter. - // - // +optional - Exporter *Exporter `json:"exporter,omitempty"` - - // Deprecated since v0.9 - // monitor is monitoring config which provided by provider. - // - // +kubebuilder:deprecatedversion:warning="This field has been deprecated since 0.10.0" - // +optional - Monitor *MonitorConfig `json:"monitor,omitempty"` } func (r *ClusterComponentDefinition) GetStatefulSetWorkload() StatefulSetWorkload { diff --git a/apis/apps/v1alpha1/componentdefinition_types.go b/apis/apps/v1alpha1/componentdefinition_types.go index afa6eea1d262..8937495b652a 100644 --- a/apis/apps/v1alpha1/componentdefinition_types.go +++ b/apis/apps/v1alpha1/componentdefinition_types.go @@ -194,13 +194,6 @@ type ComponentDefinitionSpec struct { // +kubebuilder:validation:Required Runtime corev1.PodSpec `json:"runtime"` - // Deprecated since v0.9 - // monitor is monitoring config which provided by provider. - // - // +kubebuilder:deprecatedversion:warning="This field has been deprecated since 0.10.0" - // +optional - Monitor *MonitorConfig `json:"monitor,omitempty"` - // Defines the built-in metrics exporter container. // // +optional diff --git a/apis/apps/v1alpha1/zz_generated.deepcopy.go b/apis/apps/v1alpha1/zz_generated.deepcopy.go index 1885525ec4ef..1476969ed7bb 100644 --- a/apis/apps/v1alpha1/zz_generated.deepcopy.go +++ b/apis/apps/v1alpha1/zz_generated.deepcopy.go @@ -516,16 +516,6 @@ func (in *ClusterComponentDefinition) DeepCopyInto(out *ClusterComponentDefiniti (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.Exporter != nil { - in, out := &in.Exporter, &out.Exporter - *out = new(Exporter) - **out = **in - } - if in.Monitor != nil { - in, out := &in.Monitor, &out.Monitor - *out = new(MonitorConfig) - (*in).DeepCopyInto(*out) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterComponentDefinition. @@ -1629,11 +1619,6 @@ func (in *ComponentDefinitionList) DeepCopyObject() runtime.Object { func (in *ComponentDefinitionSpec) DeepCopyInto(out *ComponentDefinitionSpec) { *out = *in in.Runtime.DeepCopyInto(&out.Runtime) - if in.Monitor != nil { - in, out := &in.Monitor, &out.Monitor - *out = new(MonitorConfig) - (*in).DeepCopyInto(*out) - } if in.Exporter != nil { in, out := &in.Exporter, &out.Exporter *out = new(Exporter) @@ -3268,22 +3253,6 @@ func (in *Exporter) DeepCopy() *Exporter { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ExporterConfig) DeepCopyInto(out *ExporterConfig) { - *out = *in - out.ScrapePort = in.ScrapePort -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExporterConfig. -func (in *ExporterConfig) DeepCopy() *ExporterConfig { - if in == nil { - return nil - } - out := new(ExporterConfig) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Expose) DeepCopyInto(out *Expose) { *out = *in @@ -3810,26 +3779,6 @@ func (in *MatchExpressions) DeepCopy() *MatchExpressions { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MonitorConfig) DeepCopyInto(out *MonitorConfig) { - *out = *in - if in.Exporter != nil { - in, out := &in.Exporter, &out.Exporter - *out = new(ExporterConfig) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MonitorConfig. -func (in *MonitorConfig) DeepCopy() *MonitorConfig { - if in == nil { - return nil - } - out := new(MonitorConfig) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MultipleClusterObjectCombinedOption) DeepCopyInto(out *MultipleClusterObjectCombinedOption) { *out = *in diff --git a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml index 75d39ec2fbf5..6358358fe582 100644 --- a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml @@ -585,31 +585,6 @@ spec: description: description: Description of the component definition. type: string - exporter: - description: Defines the metrics exporter. - properties: - containerName: - description: Specifies the name of the built-in metrics - exporter container. - type: string - scrapePath: - description: |- - Specifies the http/https url path to scrape for metrics. - If empty, Prometheus uses the default value (e.g. `/metrics`). - type: string - scrapePort: - description: Specifies the port name to scrape for metrics. - type: string - scrapeScheme: - description: |- - Specifies the schema to use for scraping. - `http` and `https` are the expected values unless you rewrite the `__scheme__` label via relabeling. - If empty, Prometheus uses the default value `http`. - enum: - - http - - https - type: string - type: object horizontalScalePolicy: description: Defines the behavior of horizontal scale. properties: @@ -670,40 +645,6 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map - monitor: - description: |- - Deprecated since v0.9 - monitor is monitoring config which provided by provider. - properties: - builtIn: - default: false - description: |- - builtIn is a switch to enable KubeBlocks builtIn monitoring. - If BuiltIn is set to true, monitor metrics will be scraped automatically. - If BuiltIn is set to false, the provider should set ExporterConfig and Sidecar container own. - type: boolean - exporterConfig: - description: |- - exporterConfig provided by provider, which specify necessary information to Time Series Database. - exporterConfig is valid when builtIn is false. - properties: - scrapePath: - default: /metrics - description: scrapePath is exporter url path for Time - Series Database to scrape metrics. - maxLength: 128 - type: string - scrapePort: - anyOf: - - type: integer - - type: string - description: scrapePort is exporter port for Time Series - Database to scrape metrics. - x-kubernetes-int-or-string: true - required: - - scrapePort - type: object - type: object name: description: |- This name could be used as default name of `cluster.spec.componentSpecs.name`, and needs to conform with same diff --git a/config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml b/config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml index b9df187ebcf6..9dce8a05d401 100644 --- a/config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml +++ b/config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml @@ -5732,40 +5732,6 @@ spec: format: int32 minimum: 0 type: integer - monitor: - description: |- - Deprecated since v0.9 - monitor is monitoring config which provided by provider. - properties: - builtIn: - default: false - description: |- - builtIn is a switch to enable KubeBlocks builtIn monitoring. - If BuiltIn is set to true, monitor metrics will be scraped automatically. - If BuiltIn is set to false, the provider should set ExporterConfig and Sidecar container own. - type: boolean - exporterConfig: - description: |- - exporterConfig provided by provider, which specify necessary information to Time Series Database. - exporterConfig is valid when builtIn is false. - properties: - scrapePath: - default: /metrics - description: scrapePath is exporter url path for Time Series - Database to scrape metrics. - maxLength: 128 - type: string - scrapePort: - anyOf: - - type: integer - - type: string - description: scrapePort is exporter port for Time Series Database - to scrape metrics. - x-kubernetes-int-or-string: true - required: - - scrapePort - type: object - type: object podManagementPolicy: description: |- InstanceSet controls the creation of pods during initial scale up, replacement of pods on nodes, and scaling down. diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml index 75d39ec2fbf5..6358358fe582 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml @@ -585,31 +585,6 @@ spec: description: description: Description of the component definition. type: string - exporter: - description: Defines the metrics exporter. - properties: - containerName: - description: Specifies the name of the built-in metrics - exporter container. - type: string - scrapePath: - description: |- - Specifies the http/https url path to scrape for metrics. - If empty, Prometheus uses the default value (e.g. `/metrics`). - type: string - scrapePort: - description: Specifies the port name to scrape for metrics. - type: string - scrapeScheme: - description: |- - Specifies the schema to use for scraping. - `http` and `https` are the expected values unless you rewrite the `__scheme__` label via relabeling. - If empty, Prometheus uses the default value `http`. - enum: - - http - - https - type: string - type: object horizontalScalePolicy: description: Defines the behavior of horizontal scale. properties: @@ -670,40 +645,6 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map - monitor: - description: |- - Deprecated since v0.9 - monitor is monitoring config which provided by provider. - properties: - builtIn: - default: false - description: |- - builtIn is a switch to enable KubeBlocks builtIn monitoring. - If BuiltIn is set to true, monitor metrics will be scraped automatically. - If BuiltIn is set to false, the provider should set ExporterConfig and Sidecar container own. - type: boolean - exporterConfig: - description: |- - exporterConfig provided by provider, which specify necessary information to Time Series Database. - exporterConfig is valid when builtIn is false. - properties: - scrapePath: - default: /metrics - description: scrapePath is exporter url path for Time - Series Database to scrape metrics. - maxLength: 128 - type: string - scrapePort: - anyOf: - - type: integer - - type: string - description: scrapePort is exporter port for Time Series - Database to scrape metrics. - x-kubernetes-int-or-string: true - required: - - scrapePort - type: object - type: object name: description: |- This name could be used as default name of `cluster.spec.componentSpecs.name`, and needs to conform with same diff --git a/deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml b/deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml index b9df187ebcf6..9dce8a05d401 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml @@ -5732,40 +5732,6 @@ spec: format: int32 minimum: 0 type: integer - monitor: - description: |- - Deprecated since v0.9 - monitor is monitoring config which provided by provider. - properties: - builtIn: - default: false - description: |- - builtIn is a switch to enable KubeBlocks builtIn monitoring. - If BuiltIn is set to true, monitor metrics will be scraped automatically. - If BuiltIn is set to false, the provider should set ExporterConfig and Sidecar container own. - type: boolean - exporterConfig: - description: |- - exporterConfig provided by provider, which specify necessary information to Time Series Database. - exporterConfig is valid when builtIn is false. - properties: - scrapePath: - default: /metrics - description: scrapePath is exporter url path for Time Series - Database to scrape metrics. - maxLength: 128 - type: string - scrapePort: - anyOf: - - type: integer - - type: string - description: scrapePort is exporter port for Time Series Database - to scrape metrics. - x-kubernetes-int-or-string: true - required: - - scrapePort - type: object - type: object podManagementPolicy: description: |- InstanceSet controls the creation of pods during initial scale up, replacement of pods on nodes, and scaling down. diff --git a/docs/developer_docs/api-reference/cluster.md b/docs/developer_docs/api-reference/cluster.md index f00ad9111054..d1a11ff40b16 100644 --- a/docs/developer_docs/api-reference/cluster.md +++ b/docs/developer_docs/api-reference/cluster.md @@ -1415,21 +1415,6 @@ These instance-specific overrides can be specified in cluster.spec.compone
-monitor
- - -MonitorConfig - - -
-(Optional) -

Deprecated since v0.9 -monitor is monitoring config which provided by provider.

-
exporter
@@ -4498,35 +4483,6 @@ configmap and mounted to the current component.

Used to declare the service reference of the current component.

-exporter
- - -Exporter - - -
-(Optional) -

Defines the metrics exporter.

-
-monitor
- - -MonitorConfig - - -
-(Optional) -

Deprecated since v0.9 -monitor is monitoring config which provided by provider.

-

ClusterComponentPhase @@ -7481,21 +7437,6 @@ These instance-specific overrides can be specified in cluster.spec.compone -monitor
- - -MonitorConfig - - - - -(Optional) -

Deprecated since v0.9 -monitor is monitoring config which provided by provider.

- - - - exporter
@@ -11882,7 +11823,7 @@ If this field is not specified, the default behavior is to use the first contain

Exporter

-(Appears on:ClusterComponentDefinition, ComponentDefinitionSpec) +(Appears on:ComponentDefinitionSpec)

@@ -11949,48 +11890,6 @@ If empty, Prometheus uses the default value http.

-

ExporterConfig -

-

-(Appears on:MonitorConfig) -

-
-
- - - - - - - - - - - - - - - - - -
FieldDescription
-scrapePort
- - -Kubernetes api utils intstr.IntOrString - - -
-

scrapePort is exporter port for Time Series Database to scrape metrics.

-
-scrapePath
- -string - -
-(Optional) -

scrapePath is exporter url path for Time Series Database to scrape metrics.

-

Expose

@@ -13474,52 +13373,6 @@ for example, using ‘{{ eq .spec.replicas 1 }}’ -

MonitorConfig -

-

-(Appears on:ClusterComponentDefinition, ComponentDefinitionSpec) -

-
-
- - - - - - - - - - - - - - - - - -
FieldDescription
-builtIn
- -bool - -
-(Optional) -

builtIn is a switch to enable KubeBlocks builtIn monitoring. -If BuiltIn is set to true, monitor metrics will be scraped automatically. -If BuiltIn is set to false, the provider should set ExporterConfig and Sidecar container own.

-
-exporterConfig
- - -ExporterConfig - - -
-(Optional) -

exporterConfig provided by provider, which specify necessary information to Time Series Database. -exporterConfig is valid when builtIn is false.

-

MultipleClusterObjectCombinedOption

diff --git a/pkg/controller/component/component.go b/pkg/controller/component/component.go index 3cda008754d4..8891ac6957b4 100644 --- a/pkg/controller/component/component.go +++ b/pkg/controller/component/component.go @@ -284,16 +284,5 @@ func GetExporter(componentDef appsv1alpha1.ComponentDefinitionSpec) *common.Expo if componentDef.Exporter != nil { return &common.Exporter{Exporter: *componentDef.Exporter} } - - // Compatible with previous versions of kb - if componentDef.Monitor == nil || componentDef.Monitor.Exporter == nil { - return nil - } - - return &common.Exporter{ - TargetPort: &componentDef.Monitor.Exporter.ScrapePort, - Exporter: appsv1alpha1.Exporter{ - ScrapePath: componentDef.Monitor.Exporter.ScrapePath, - }, - } + return nil } diff --git a/pkg/controller/component/definition_convertor.go b/pkg/controller/component/definition_convertor.go index 636b9dcd41de..489a427edeaf 100644 --- a/pkg/controller/component/definition_convertor.go +++ b/pkg/controller/component/definition_convertor.go @@ -61,7 +61,6 @@ func buildComponentDefinitionByConversion(clusterCompDef *appsv1alpha1.ClusterCo "roles": &compDefRolesConvertor{}, "lifecycleactions": &compDefLifecycleActionsConvertor{}, "servicerefdeclarations": &compDefServiceRefDeclarationsConvertor{}, - "monitor": &compDefMonitorConvertor{}, "exporter": &compDefExporterConvertor{}, } compDef := &appsv1alpha1.ComponentDefinition{} @@ -683,16 +682,8 @@ func (c *compDefLifecycleActionsConvertor) convertSwitchover(switchover *appsv1a } } -type compDefMonitorConvertor struct{} - -func (c *compDefMonitorConvertor) convert(args ...any) (any, error) { - clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - return clusterCompDef.Monitor, nil -} - type compDefExporterConvertor struct{} func (c *compDefExporterConvertor) convert(args ...any) (any, error) { - clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - return clusterCompDef.Exporter, nil + return nil, nil } From b15b9808d3c0ff8161533ba93ecdbc0ee1fa8155 Mon Sep 17 00:00:00 2001 From: Liang Deng <283304489@qq.com> Date: Fri, 26 Jul 2024 15:07:00 +0800 Subject: [PATCH 08/45] chore: remove monitor from cmpdHash function (#7877) Signed-off-by: Liang Deng <283304489@qq.com> --- controllers/apps/componentdefinition_controller.go | 1 - 1 file changed, 1 deletion(-) diff --git a/controllers/apps/componentdefinition_controller.go b/controllers/apps/componentdefinition_controller.go index d5da445e5371..adec2693747e 100644 --- a/controllers/apps/componentdefinition_controller.go +++ b/controllers/apps/componentdefinition_controller.go @@ -435,7 +435,6 @@ func (r *ComponentDefinitionReconciler) cmpdHash(cmpd *appsv1alpha1.ComponentDef // reset all mutable fields objCopy.Spec.Provider = "" objCopy.Spec.Description = "" - objCopy.Spec.Monitor = nil objCopy.Spec.Exporter = nil objCopy.Spec.PodManagementPolicy = nil From 82e2f541a6c79b15562eee405bbb60763153131f Mon Sep 17 00:00:00 2001 From: Leon Date: Fri, 26 Jul 2024 15:27:11 +0800 Subject: [PATCH 09/45] chore: remove description and custom labels from cd (#7769) --- apis/apps/v1alpha1/clusterdefinition_types.go | 45 ------- apis/apps/v1alpha1/zz_generated.deepcopy.go | 51 -------- ...apps.kubeblocks.io_clusterdefinitions.yaml | 45 ------- ...apps.kubeblocks.io_clusterdefinitions.yaml | 45 ------- docs/developer_docs/api-reference/cluster.md | 122 ------------------ .../component/definition_convertor.go | 14 +- .../component/definition_convertor_test.go | 25 +--- 7 files changed, 4 insertions(+), 343 deletions(-) diff --git a/apis/apps/v1alpha1/clusterdefinition_types.go b/apis/apps/v1alpha1/clusterdefinition_types.go index d18c87055efd..b45e53788dce 100644 --- a/apis/apps/v1alpha1/clusterdefinition_types.go +++ b/apis/apps/v1alpha1/clusterdefinition_types.go @@ -496,11 +496,6 @@ type ClusterComponentDefinition struct { // +kubebuilder:validation:Pattern:=`^[a-z]([a-z0-9\-]*[a-z0-9])?$` Name string `json:"name"` - // Description of the component definition. - // - // +optional - Description string `json:"description,omitempty"` - // Defines the type of the workload. // // - `Stateless` describes stateless applications. @@ -617,13 +612,6 @@ type ClusterComponentDefinition struct { // +optional VolumeTypes []VolumeTypeSpec `json:"volumeTypes,omitempty"` - // Used for custom label tags which you want to add to the component resources. - // - // +listType=map - // +listMapKey=key - // +optional - CustomLabelSpecs []CustomLabelSpec `json:"customLabelSpecs,omitempty"` - // Defines command to do switchover. // In particular, when workloadType=Replication, the command defined in switchoverSpec will only be executed under // the condition of cluster.componentSpecs[x].SwitchPolicy.type=Noop. @@ -1191,39 +1179,6 @@ type CommandExecutorItem struct { Args []string `json:"args,omitempty"` } -// CustomLabelSpec is deprecated since v0.8. -type CustomLabelSpec struct { - // The key of the label. - // - // +kubebuilder:validation:Required - Key string `json:"key"` - - // The value of the label. - // - // +kubebuilder:validation:Required - Value string `json:"value"` - - // The resources that will be patched with the label. - // - // +kubebuilder:validation:Required - Resources []GVKResource `json:"resources,omitempty"` -} - -// GVKResource is deprecated since v0.8. -type GVKResource struct { - // Represents the GVK of a resource, such as "v1/Pod", "apps/v1/StatefulSet", etc. - // When a resource matching this is found by the selector, a custom label will be added if it doesn't already exist, - // or updated if it does. - // - // +kubebuilder:validation:Required - GVK string `json:"gvk"` - - // A label query used to filter a set of resources. - // - // +optional - Selector map[string]string `json:"selector,omitempty"` -} - // TODO(API): // 1. how to display the aggregated topologies and its service references line by line? // 2. the services and versions supported diff --git a/apis/apps/v1alpha1/zz_generated.deepcopy.go b/apis/apps/v1alpha1/zz_generated.deepcopy.go index 1476969ed7bb..d79b683b97a1 100644 --- a/apis/apps/v1alpha1/zz_generated.deepcopy.go +++ b/apis/apps/v1alpha1/zz_generated.deepcopy.go @@ -480,13 +480,6 @@ func (in *ClusterComponentDefinition) DeepCopyInto(out *ClusterComponentDefiniti *out = make([]VolumeTypeSpec, len(*in)) copy(*out, *in) } - if in.CustomLabelSpecs != nil { - in, out := &in.CustomLabelSpecs, &out.CustomLabelSpecs - *out = make([]CustomLabelSpec, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } if in.SwitchoverSpec != nil { in, out := &in.SwitchoverSpec, &out.SwitchoverSpec *out = new(SwitchoverSpec) @@ -3060,28 +3053,6 @@ func (in *CredentialVars) DeepCopy() *CredentialVars { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CustomLabelSpec) DeepCopyInto(out *CustomLabelSpec) { - *out = *in - if in.Resources != nil { - in, out := &in.Resources, &out.Resources - *out = make([]GVKResource, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomLabelSpec. -func (in *CustomLabelSpec) DeepCopy() *CustomLabelSpec { - if in == nil { - return nil - } - out := new(CustomLabelSpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CustomOps) DeepCopyInto(out *CustomOps) { *out = *in @@ -3275,28 +3246,6 @@ func (in *Expose) DeepCopy() *Expose { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GVKResource) DeepCopyInto(out *GVKResource) { - *out = *in - if in.Selector != nil { - in, out := &in.Selector, &out.Selector - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GVKResource. -func (in *GVKResource) DeepCopy() *GVKResource { - if in == nil { - return nil - } - out := new(GVKResource) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HTTPAction) DeepCopyInto(out *HTTPAction) { *out = *in diff --git a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml index 6358358fe582..c905dd54452e 100644 --- a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml @@ -540,51 +540,6 @@ spec: required: - leader type: object - customLabelSpecs: - description: Used for custom label tags which you want to add - to the component resources. - items: - description: CustomLabelSpec is deprecated since v0.8. - properties: - key: - description: The key of the label. - type: string - resources: - description: The resources that will be patched with the - label. - items: - description: GVKResource is deprecated since v0.8. - properties: - gvk: - description: |- - Represents the GVK of a resource, such as "v1/Pod", "apps/v1/StatefulSet", etc. - When a resource matching this is found by the selector, a custom label will be added if it doesn't already exist, - or updated if it does. - type: string - selector: - additionalProperties: - type: string - description: A label query used to filter a set - of resources. - type: object - required: - - gvk - type: object - type: array - value: - description: The value of the label. - type: string - required: - - key - - value - type: object - type: array - x-kubernetes-list-map-keys: - - key - x-kubernetes-list-type: map - description: - description: Description of the component definition. - type: string horizontalScalePolicy: description: Defines the behavior of horizontal scale. properties: diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml index 6358358fe582..c905dd54452e 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml @@ -540,51 +540,6 @@ spec: required: - leader type: object - customLabelSpecs: - description: Used for custom label tags which you want to add - to the component resources. - items: - description: CustomLabelSpec is deprecated since v0.8. - properties: - key: - description: The key of the label. - type: string - resources: - description: The resources that will be patched with the - label. - items: - description: GVKResource is deprecated since v0.8. - properties: - gvk: - description: |- - Represents the GVK of a resource, such as "v1/Pod", "apps/v1/StatefulSet", etc. - When a resource matching this is found by the selector, a custom label will be added if it doesn't already exist, - or updated if it does. - type: string - selector: - additionalProperties: - type: string - description: A label query used to filter a set - of resources. - type: object - required: - - gvk - type: object - type: array - value: - description: The value of the label. - type: string - required: - - key - - value - type: object - type: array - x-kubernetes-list-map-keys: - - key - x-kubernetes-list-type: map - description: - description: Description of the component definition. - type: string horizontalScalePolicy: description: Defines the behavior of horizontal scale. properties: diff --git a/docs/developer_docs/api-reference/cluster.md b/docs/developer_docs/api-reference/cluster.md index d1a11ff40b16..1ff3e9ff456c 100644 --- a/docs/developer_docs/api-reference/cluster.md +++ b/docs/developer_docs/api-reference/cluster.md @@ -4147,18 +4147,6 @@ This name will apply to cluster objects as the value of label “apps.kubebl -description
- -string - - - -(Optional) -

Description of the component definition.

- - - - workloadType
@@ -4397,20 +4385,6 @@ been specified.

-customLabelSpecs
- -
-[]CustomLabelSpec - - - - -(Optional) -

Used for custom label tags which you want to add to the component resources.

- - - - switchoverSpec
@@ -11295,59 +11269,6 @@ VarOption -

CustomLabelSpec -

-

-(Appears on:ClusterComponentDefinition) -

-
-

CustomLabelSpec is deprecated since v0.8.

-
- - - - - - - - - - - - - - - - - - - - - -
FieldDescription
-key
- -string - -
-

The key of the label.

-
-value
- -string - -
-

The value of the label.

-
-resources
- - -[]GVKResource - - -
-

The resources that will be patched with the label.

-

CustomOps

@@ -11994,49 +11915,6 @@ in each OpsService definition.

-

GVKResource -

-

-(Appears on:CustomLabelSpec) -

-
-

GVKResource is deprecated since v0.8.

-
- - - - - - - - - - - - - - - - - -
FieldDescription
-gvk
- -string - -
-

Represents the GVK of a resource, such as “v1/Pod”, “apps/v1/StatefulSet”, etc. -When a resource matching this is found by the selector, a custom label will be added if it doesn’t already exist, -or updated if it does.

-
-selector
- -map[string]string - -
-(Optional) -

A label query used to filter a set of resources.

-

HScaleDataClonePolicyType (string alias)

diff --git a/pkg/controller/component/definition_convertor.go b/pkg/controller/component/definition_convertor.go index 489a427edeaf..ebc3b5d22fb4 100644 --- a/pkg/controller/component/definition_convertor.go +++ b/pkg/controller/component/definition_convertor.go @@ -81,8 +81,7 @@ func (c *compDefProviderConvertor) convert(args ...any) (any, error) { type compDefDescriptionConvertor struct{} func (c *compDefDescriptionConvertor) convert(args ...any) (any, error) { - clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - return clusterCompDef.Description, nil + return "", nil } // compDefServiceKindConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.ServiceKind. @@ -328,16 +327,7 @@ func (c *compDefPolicyRulesConvertor) convert(args ...any) (any, error) { type compDefLabelsConvertor struct{} func (c *compDefLabelsConvertor) convert(args ...any) (any, error) { - clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - if clusterCompDef.CustomLabelSpecs == nil { - return nil, nil - } - - labels := make(map[string]string, 0) - for _, customLabel := range clusterCompDef.CustomLabelSpecs { - labels[customLabel.Key] = customLabel.Value - } - return labels, nil + return nil, nil } type compDefReplicasLimitConvertor struct{} diff --git a/pkg/controller/component/definition_convertor_test.go b/pkg/controller/component/definition_convertor_test.go index 3c89b1e362eb..1fa9290af77d 100644 --- a/pkg/controller/component/definition_convertor_test.go +++ b/pkg/controller/component/definition_convertor_test.go @@ -67,7 +67,6 @@ var _ = Describe("Component Definition Convertor", func() { BeforeEach(func() { clusterCompDef = &appsv1alpha1.ClusterComponentDefinition{ Name: "mysql", - Description: "component definition convertor", WorkloadType: appsv1alpha1.Consensus, CharacterType: "mysql", ConfigSpecs: []appsv1alpha1.ComponentConfigSpec{ @@ -255,20 +254,6 @@ var _ = Describe("Component Definition Convertor", func() { Type: appsv1alpha1.VolumeTypeLog, }, }, - CustomLabelSpecs: []appsv1alpha1.CustomLabelSpec{ - { - Key: "scope", - Value: "scope", - Resources: []appsv1alpha1.GVKResource{ - { - GVK: "v1/pod", - Selector: map[string]string{ - "managed-by": "kubeblocks", - }, - }, - }, - }, - }, SwitchoverSpec: &appsv1alpha1.SwitchoverSpec{}, VolumeProtectionSpec: &appsv1alpha1.VolumeProtectionSpec{ HighWatermark: defaultHighWatermark, @@ -295,7 +280,7 @@ var _ = Describe("Component Definition Convertor", func() { convertor := &compDefDescriptionConvertor{} res, err := convertor.convert(clusterCompDef) Expect(err).Should(Succeed()) - Expect(res).Should(Equal(clusterCompDef.Description)) + Expect(res).Should(BeEmpty()) }) It("service kind", func() { @@ -624,13 +609,7 @@ var _ = Describe("Component Definition Convertor", func() { convertor := &compDefLabelsConvertor{} res, err := convertor.convert(clusterCompDef) Expect(err).Should(Succeed()) - - labels := res.(map[string]string) - expectedLabels := map[string]string{} - for _, item := range clusterCompDef.CustomLabelSpecs { - expectedLabels[item.Key] = item.Value - } - Expect(labels).Should(BeEquivalentTo(expectedLabels)) + Expect(res).Should(BeNil()) }) Context("system accounts", func() { From 4be95f422ed4fa04038dd45d8aaac3cd8bfb805c Mon Sep 17 00:00:00 2001 From: Liang Deng <283304489@qq.com> Date: Fri, 26 Jul 2024 16:24:30 +0800 Subject: [PATCH 10/45] feat: Support setting ParallelPodManagement concurrency (#7830) Signed-off-by: Liang Deng <283304489@qq.com> --- apis/apps/v1alpha1/cluster_types.go | 8 ++ apis/apps/v1alpha1/component_types.go | 8 ++ apis/apps/v1alpha1/zz_generated.deepcopy.go | 11 ++ apis/workloads/v1alpha1/instanceset_types.go | 8 ++ .../v1alpha1/zz_generated.deepcopy.go | 6 + .../bases/apps.kubeblocks.io_clusters.yaml | 18 +++ .../bases/apps.kubeblocks.io_components.yaml | 9 ++ .../workloads.kubeblocks.io_instancesets.yaml | 9 ++ .../apps/transformer_cluster_component.go | 1 + .../apps/transformer_component_workload.go | 1 + .../crds/apps.kubeblocks.io_clusters.yaml | 18 +++ .../crds/apps.kubeblocks.io_components.yaml | 9 ++ .../workloads.kubeblocks.io_instancesets.yaml | 9 ++ pkg/controller/builder/builder_component.go | 6 + .../builder/builder_instance_set.go | 6 + .../builder/builder_instance_set_test.go | 3 + pkg/controller/component/component.go | 1 + pkg/controller/component/its_convertor.go | 40 +++++-- .../component/synthesize_component.go | 69 ++++++------ pkg/controller/component/type.go | 52 ++++----- .../reconciler_instance_alignment.go | 41 +++++-- .../reconciler_instance_alignment_test.go | 27 +++++ pkg/controller/instanceset/utils.go | 28 +++++ pkg/controller/instanceset/utils_test.go | 105 ++++++++++++++++++ 24 files changed, 411 insertions(+), 82 deletions(-) diff --git a/apis/apps/v1alpha1/cluster_types.go b/apis/apps/v1alpha1/cluster_types.go index 3a0da3150008..4fe8b6c0d12c 100644 --- a/apis/apps/v1alpha1/cluster_types.go +++ b/apis/apps/v1alpha1/cluster_types.go @@ -24,6 +24,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" dpv1alpha1 "github.com/apecloud/kubeblocks/apis/dataprotection/v1alpha1" workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" @@ -800,6 +801,13 @@ type ClusterComponentSpec struct { // +optional UpdateStrategy *UpdateStrategy `json:"updateStrategy,omitempty"` + // Controls the concurrency of pods during initial scale up, when replacing pods on nodes, + // or when scaling down. It only used when `PodManagementPolicy` is set to `Parallel`. + // The default Concurrency is 100%. + // + // +optional + ParallelPodManagementConcurrency *intstr.IntOrString `json:"parallelPodManagementConcurrency,omitempty"` + // PodUpdatePolicy indicates how pods should be updated // // - `StrictInPlace` indicates that only allows in-place upgrades. diff --git a/apis/apps/v1alpha1/component_types.go b/apis/apps/v1alpha1/component_types.go index 5ef1cf0226e4..f90aa925e01d 100644 --- a/apis/apps/v1alpha1/component_types.go +++ b/apis/apps/v1alpha1/component_types.go @@ -19,6 +19,7 @@ package v1alpha1 import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" ) @@ -162,6 +163,13 @@ type ComponentSpec struct { // +optional ServiceAccountName string `json:"serviceAccountName,omitempty"` + // Controls the concurrency of pods during initial scale up, when replacing pods on nodes, + // or when scaling down. It only used when `PodManagementPolicy` is set to `Parallel`. + // The default Concurrency is 100%. + // + // +optional + ParallelPodManagementConcurrency *intstr.IntOrString `json:"parallelPodManagementConcurrency,omitempty"` + // PodUpdatePolicy indicates how pods should be updated // // - `StrictInPlace` indicates that only allows in-place upgrades. diff --git a/apis/apps/v1alpha1/zz_generated.deepcopy.go b/apis/apps/v1alpha1/zz_generated.deepcopy.go index d79b683b97a1..abf4600fc837 100644 --- a/apis/apps/v1alpha1/zz_generated.deepcopy.go +++ b/apis/apps/v1alpha1/zz_generated.deepcopy.go @@ -31,6 +31,7 @@ import ( rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/intstr" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -652,6 +653,11 @@ func (in *ClusterComponentSpec) DeepCopyInto(out *ClusterComponentSpec) { *out = new(UpdateStrategy) **out = **in } + if in.ParallelPodManagementConcurrency != nil { + in, out := &in.ParallelPodManagementConcurrency, &out.ParallelPodManagementConcurrency + *out = new(intstr.IntOrString) + **out = **in + } if in.PodUpdatePolicy != nil { in, out := &in.PodUpdatePolicy, &out.PodUpdatePolicy *out = new(workloadsv1alpha1.PodUpdatePolicyType) @@ -2023,6 +2029,11 @@ func (in *ComponentSpec) DeepCopyInto(out *ComponentSpec) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.ParallelPodManagementConcurrency != nil { + in, out := &in.ParallelPodManagementConcurrency, &out.ParallelPodManagementConcurrency + *out = new(intstr.IntOrString) + **out = **in + } if in.PodUpdatePolicy != nil { in, out := &in.PodUpdatePolicy, &out.PodUpdatePolicy *out = new(workloadsv1alpha1.PodUpdatePolicyType) diff --git a/apis/workloads/v1alpha1/instanceset_types.go b/apis/workloads/v1alpha1/instanceset_types.go index ad0a91056d5d..c10cb08f8462 100644 --- a/apis/workloads/v1alpha1/instanceset_types.go +++ b/apis/workloads/v1alpha1/instanceset_types.go @@ -20,6 +20,7 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" ) // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! @@ -304,6 +305,13 @@ type InstanceSetSpec struct { // +optional PodManagementPolicy appsv1.PodManagementPolicyType `json:"podManagementPolicy,omitempty"` + // Controls the concurrency of pods during initial scale up, when replacing pods on nodes, + // or when scaling down. It only used when `PodManagementPolicy` is set to `Parallel`. + // The default Concurrency is 100%. + // + // +optional + ParallelPodManagementConcurrency *intstr.IntOrString `json:"parallelPodManagementConcurrency,omitempty"` + // PodUpdatePolicy indicates how pods should be updated // // - `StrictInPlace` indicates that only allows in-place upgrades. diff --git a/apis/workloads/v1alpha1/zz_generated.deepcopy.go b/apis/workloads/v1alpha1/zz_generated.deepcopy.go index 8138d02f5703..e8f6d3babb61 100644 --- a/apis/workloads/v1alpha1/zz_generated.deepcopy.go +++ b/apis/workloads/v1alpha1/zz_generated.deepcopy.go @@ -27,6 +27,7 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/intstr" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -189,6 +190,11 @@ func (in *InstanceSetSpec) DeepCopyInto(out *InstanceSetSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.ParallelPodManagementConcurrency != nil { + in, out := &in.ParallelPodManagementConcurrency, &out.ParallelPodManagementConcurrency + *out = new(intstr.IntOrString) + **out = **in + } in.UpdateStrategy.DeepCopyInto(&out.UpdateStrategy) if in.Roles != nil { in, out := &in.Roles, &out.Roles diff --git a/config/crd/bases/apps.kubeblocks.io_clusters.yaml b/config/crd/bases/apps.kubeblocks.io_clusters.yaml index 258a77a4534e..0abe99e9e9af 100644 --- a/config/crd/bases/apps.kubeblocks.io_clusters.yaml +++ b/config/crd/bases/apps.kubeblocks.io_clusters.yaml @@ -3869,6 +3869,15 @@ spec: items: type: string type: array + parallelPodManagementConcurrency: + anyOf: + - type: integer + - type: string + description: |- + Controls the concurrency of pods during initial scale up, when replacing pods on nodes, + or when scaling down. It only used when `PodManagementPolicy` is set to `Parallel`. + The default Concurrency is 100%. + x-kubernetes-int-or-string: true podUpdatePolicy: description: |- PodUpdatePolicy indicates how pods should be updated @@ -12549,6 +12558,15 @@ spec: items: type: string type: array + parallelPodManagementConcurrency: + anyOf: + - type: integer + - type: string + description: |- + Controls the concurrency of pods during initial scale up, when replacing pods on nodes, + or when scaling down. It only used when `PodManagementPolicy` is set to `Parallel`. + The default Concurrency is 100%. + x-kubernetes-int-or-string: true podUpdatePolicy: description: |- PodUpdatePolicy indicates how pods should be updated diff --git a/config/crd/bases/apps.kubeblocks.io_components.yaml b/config/crd/bases/apps.kubeblocks.io_components.yaml index e8df9e8ef4e5..f34bcbc6a439 100644 --- a/config/crd/bases/apps.kubeblocks.io_components.yaml +++ b/config/crd/bases/apps.kubeblocks.io_components.yaml @@ -3490,6 +3490,15 @@ spec: items: type: string type: array + parallelPodManagementConcurrency: + anyOf: + - type: integer + - type: string + description: |- + Controls the concurrency of pods during initial scale up, when replacing pods on nodes, + or when scaling down. It only used when `PodManagementPolicy` is set to `Parallel`. + The default Concurrency is 100%. + x-kubernetes-int-or-string: true podUpdatePolicy: description: |- PodUpdatePolicy indicates how pods should be updated diff --git a/config/crd/bases/workloads.kubeblocks.io_instancesets.yaml b/config/crd/bases/workloads.kubeblocks.io_instancesets.yaml index f876833df19f..3e86dca55a8d 100644 --- a/config/crd/bases/workloads.kubeblocks.io_instancesets.yaml +++ b/config/crd/bases/workloads.kubeblocks.io_instancesets.yaml @@ -3899,6 +3899,15 @@ spec: items: type: string type: array + parallelPodManagementConcurrency: + anyOf: + - type: integer + - type: string + description: |- + Controls the concurrency of pods during initial scale up, when replacing pods on nodes, + or when scaling down. It only used when `PodManagementPolicy` is set to `Parallel`. + The default Concurrency is 100%. + x-kubernetes-int-or-string: true paused: description: Indicates that the InstanceSet is paused, meaning the reconciliation of this InstanceSet object will be paused. diff --git a/controllers/apps/transformer_cluster_component.go b/controllers/apps/transformer_cluster_component.go index 1095e4ab990c..785fdfa93c25 100644 --- a/controllers/apps/transformer_cluster_component.go +++ b/controllers/apps/transformer_cluster_component.go @@ -218,6 +218,7 @@ func copyAndMergeComponent(oldCompObj, newCompObj *appsv1alpha1.Component) *apps // compObjCopy.Spec.Monitor = compProto.Spec.Monitor compObjCopy.Spec.EnabledLogs = compProto.Spec.EnabledLogs compObjCopy.Spec.ServiceAccountName = compProto.Spec.ServiceAccountName + compObjCopy.Spec.ParallelPodManagementConcurrency = compProto.Spec.ParallelPodManagementConcurrency compObjCopy.Spec.PodUpdatePolicy = compProto.Spec.PodUpdatePolicy compObjCopy.Spec.Affinity = compProto.Spec.Affinity compObjCopy.Spec.Tolerations = compProto.Spec.Tolerations diff --git a/controllers/apps/transformer_component_workload.go b/controllers/apps/transformer_component_workload.go index 8bce908f9d5b..22cf8f954644 100644 --- a/controllers/apps/transformer_component_workload.go +++ b/controllers/apps/transformer_component_workload.go @@ -330,6 +330,7 @@ func copyAndMergeITS(oldITS, newITS *workloads.InstanceSet, synthesizeComp *comp itsObjCopy.Spec.OfflineInstances = itsProto.Spec.OfflineInstances itsObjCopy.Spec.MinReadySeconds = itsProto.Spec.MinReadySeconds itsObjCopy.Spec.VolumeClaimTemplates = itsProto.Spec.VolumeClaimTemplates + itsObjCopy.Spec.ParallelPodManagementConcurrency = itsProto.Spec.ParallelPodManagementConcurrency if itsProto.Spec.UpdateStrategy.Type != "" || itsProto.Spec.UpdateStrategy.RollingUpdate != nil { updateUpdateStrategy(itsObjCopy, itsProto) diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml index 258a77a4534e..0abe99e9e9af 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml @@ -3869,6 +3869,15 @@ spec: items: type: string type: array + parallelPodManagementConcurrency: + anyOf: + - type: integer + - type: string + description: |- + Controls the concurrency of pods during initial scale up, when replacing pods on nodes, + or when scaling down. It only used when `PodManagementPolicy` is set to `Parallel`. + The default Concurrency is 100%. + x-kubernetes-int-or-string: true podUpdatePolicy: description: |- PodUpdatePolicy indicates how pods should be updated @@ -12549,6 +12558,15 @@ spec: items: type: string type: array + parallelPodManagementConcurrency: + anyOf: + - type: integer + - type: string + description: |- + Controls the concurrency of pods during initial scale up, when replacing pods on nodes, + or when scaling down. It only used when `PodManagementPolicy` is set to `Parallel`. + The default Concurrency is 100%. + x-kubernetes-int-or-string: true podUpdatePolicy: description: |- PodUpdatePolicy indicates how pods should be updated diff --git a/deploy/helm/crds/apps.kubeblocks.io_components.yaml b/deploy/helm/crds/apps.kubeblocks.io_components.yaml index e8df9e8ef4e5..f34bcbc6a439 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_components.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_components.yaml @@ -3490,6 +3490,15 @@ spec: items: type: string type: array + parallelPodManagementConcurrency: + anyOf: + - type: integer + - type: string + description: |- + Controls the concurrency of pods during initial scale up, when replacing pods on nodes, + or when scaling down. It only used when `PodManagementPolicy` is set to `Parallel`. + The default Concurrency is 100%. + x-kubernetes-int-or-string: true podUpdatePolicy: description: |- PodUpdatePolicy indicates how pods should be updated diff --git a/deploy/helm/crds/workloads.kubeblocks.io_instancesets.yaml b/deploy/helm/crds/workloads.kubeblocks.io_instancesets.yaml index f876833df19f..3e86dca55a8d 100644 --- a/deploy/helm/crds/workloads.kubeblocks.io_instancesets.yaml +++ b/deploy/helm/crds/workloads.kubeblocks.io_instancesets.yaml @@ -3899,6 +3899,15 @@ spec: items: type: string type: array + parallelPodManagementConcurrency: + anyOf: + - type: integer + - type: string + description: |- + Controls the concurrency of pods during initial scale up, when replacing pods on nodes, + or when scaling down. It only used when `PodManagementPolicy` is set to `Parallel`. + The default Concurrency is 100%. + x-kubernetes-int-or-string: true paused: description: Indicates that the InstanceSet is paused, meaning the reconciliation of this InstanceSet object will be paused. diff --git a/pkg/controller/builder/builder_component.go b/pkg/controller/builder/builder_component.go index d815e12fb4df..a4be30cc1112 100644 --- a/pkg/controller/builder/builder_component.go +++ b/pkg/controller/builder/builder_component.go @@ -21,6 +21,7 @@ package builder import ( corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/intstr" appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" @@ -81,6 +82,11 @@ func (builder *ComponentBuilder) SetServiceAccountName(serviceAccountName string return builder } +func (builder *ComponentBuilder) SetParallelPodManagementConcurrency(parallelPodManagementConcurrency *intstr.IntOrString) *ComponentBuilder { + builder.get().Spec.ParallelPodManagementConcurrency = parallelPodManagementConcurrency + return builder +} + func (builder *ComponentBuilder) SetPodUpdatePolicy(policy *workloads.PodUpdatePolicyType) *ComponentBuilder { builder.get().Spec.PodUpdatePolicy = policy return builder diff --git a/pkg/controller/builder/builder_instance_set.go b/pkg/controller/builder/builder_instance_set.go index 2465e3b8d17f..d05696011a88 100644 --- a/pkg/controller/builder/builder_instance_set.go +++ b/pkg/controller/builder/builder_instance_set.go @@ -23,6 +23,7 @@ import ( apps "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" ) @@ -107,6 +108,11 @@ func (builder *InstanceSetBuilder) SetPodManagementPolicy(policy apps.PodManagem return builder } +func (builder *InstanceSetBuilder) SetParallelPodManagementConcurrency(parallelPodManagementConcurrency *intstr.IntOrString) *InstanceSetBuilder { + builder.get().Spec.ParallelPodManagementConcurrency = parallelPodManagementConcurrency + return builder +} + func (builder *InstanceSetBuilder) SetPodUpdatePolicy(policy workloads.PodUpdatePolicyType) *InstanceSetBuilder { builder.get().Spec.PodUpdatePolicy = policy return builder diff --git a/pkg/controller/builder/builder_instance_set_test.go b/pkg/controller/builder/builder_instance_set_test.go index 8557e648f09e..cc1ddbc29284 100644 --- a/pkg/controller/builder/builder_instance_set_test.go +++ b/pkg/controller/builder/builder_instance_set_test.go @@ -47,6 +47,7 @@ var _ = Describe("instance_set builder", func() { policy = apps.OrderedReadyPodManagement podUpdatePolicy = workloads.PreferInPlacePodUpdatePolicyType ) + parallelPodManagementConcurrency := &intstr.IntOrString{Type: intstr.String, StrVal: "100%"} selectors := map[string]string{selectorKey4: selectorValue4} role := workloads.ReplicaRole{ Name: "foo", @@ -166,6 +167,7 @@ var _ = Describe("instance_set builder", func() { SetVolumeClaimTemplates(vcs...). AddVolumeClaimTemplates(vc). SetPodManagementPolicy(policy). + SetParallelPodManagementConcurrency(parallelPodManagementConcurrency). SetPodUpdatePolicy(podUpdatePolicy). SetUpdateStrategy(strategy). SetUpdateStrategyType(strategyType). @@ -198,6 +200,7 @@ var _ = Describe("instance_set builder", func() { Expect(its.Spec.VolumeClaimTemplates[0]).Should(Equal(vcs[0])) Expect(its.Spec.VolumeClaimTemplates[1]).Should(Equal(vc)) Expect(its.Spec.PodManagementPolicy).Should(Equal(policy)) + Expect(its.Spec.ParallelPodManagementConcurrency).Should(Equal(parallelPodManagementConcurrency)) Expect(its.Spec.PodUpdatePolicy).Should(Equal(podUpdatePolicy)) Expect(its.Spec.UpdateStrategy.Type).Should(Equal(strategyType)) Expect(its.Spec.UpdateStrategy.RollingUpdate).ShouldNot(BeNil()) diff --git a/pkg/controller/component/component.go b/pkg/controller/component/component.go index 8891ac6957b4..2e601c1d14d1 100644 --- a/pkg/controller/component/component.go +++ b/pkg/controller/component/component.go @@ -90,6 +90,7 @@ func BuildComponent(cluster *appsv1alpha1.Cluster, compSpec *appsv1alpha1.Cluste SetReplicas(compSpec.Replicas). SetResources(compSpec.Resources). SetServiceAccountName(compSpec.ServiceAccountName). + SetParallelPodManagementConcurrency(compSpec.ParallelPodManagementConcurrency). SetPodUpdatePolicy(compSpec.PodUpdatePolicy). SetVolumeClaimTemplates(compSpec.VolumeClaimTemplates). SetVolumes(compSpec.Volumes). diff --git a/pkg/controller/component/its_convertor.go b/pkg/controller/component/its_convertor.go index 25acb01dff9b..fe18b2ff8485 100644 --- a/pkg/controller/component/its_convertor.go +++ b/pkg/controller/component/its_convertor.go @@ -25,6 +25,7 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" @@ -40,18 +41,19 @@ func BuildWorkloadFrom(synthesizeComp *SynthesizedComponent, protoITS *workloads protoITS = &workloads.InstanceSet{} } convertors := map[string]convertor{ - "service": &itsServiceConvertor{}, - "alternativeservices": &itsAlternativeServicesConvertor{}, - "roles": &itsRolesConvertor{}, - "roleprobe": &itsRoleProbeConvertor{}, - "credential": &itsCredentialConvertor{}, - "membershipreconfiguration": &itsMembershipReconfigurationConvertor{}, - "memberupdatestrategy": &itsMemberUpdateStrategyConvertor{}, - "podmanagementpolicy": &itsPodManagementPolicyConvertor{}, - "podupdatepolicy": &itsPodUpdatePolicyConvertor{}, - "updatestrategy": &itsUpdateStrategyConvertor{}, - "instances": &itsInstancesConvertor{}, - "offlineinstances": &itsOfflineInstancesConvertor{}, + "service": &itsServiceConvertor{}, + "alternativeservices": &itsAlternativeServicesConvertor{}, + "roles": &itsRolesConvertor{}, + "roleprobe": &itsRoleProbeConvertor{}, + "credential": &itsCredentialConvertor{}, + "membershipreconfiguration": &itsMembershipReconfigurationConvertor{}, + "memberupdatestrategy": &itsMemberUpdateStrategyConvertor{}, + "podmanagementpolicy": &itsPodManagementPolicyConvertor{}, + "parallelpodmanagementconcurrency": &itsParallelPodManagementConcurrencyConvertor{}, + "podupdatepolicy": &itsPodUpdatePolicyConvertor{}, + "updatestrategy": &itsUpdateStrategyConvertor{}, + "instances": &itsInstancesConvertor{}, + "offlineinstances": &itsOfflineInstancesConvertor{}, } if err := covertObject(convertors, &protoITS.Spec, synthesizeComp); err != nil { return nil, err @@ -106,6 +108,20 @@ func (c *itsPodManagementPolicyConvertor) convert(args ...any) (any, error) { return appsv1.ParallelPodManagement, nil } +// itsParallelPodManagementConcurrencyConvertor is an implementation of the convertor interface, used to convert the given object into InstanceSet.Spec.ParallelPodManagementConcurrency. +type itsParallelPodManagementConcurrencyConvertor struct{} + +func (c *itsParallelPodManagementConcurrencyConvertor) convert(args ...any) (any, error) { + synthesizedComp, err := parseITSConvertorArgs(args...) + if err != nil { + return nil, err + } + if synthesizedComp.ParallelPodManagementConcurrency != nil { + return synthesizedComp.ParallelPodManagementConcurrency, nil + } + return &intstr.IntOrString{Type: intstr.String, StrVal: "100%"}, nil +} + // itsPodUpdatePolicyConvertor is an implementation of the convertor interface, used to convert the given object into InstanceSet.Spec.PodUpdatePolicy. type itsPodUpdatePolicyConvertor struct{} diff --git a/pkg/controller/component/synthesize_component.go b/pkg/controller/component/synthesize_component.go index 478235c812da..87be7d6fb24a 100644 --- a/pkg/controller/component/synthesize_component.go +++ b/pkg/controller/component/synthesize_component.go @@ -148,40 +148,41 @@ func buildSynthesizedComponent(reqCtx intctrlutil.RequestCtx, } compDefObj := compDef.DeepCopy() synthesizeComp := &SynthesizedComponent{ - Namespace: comp.Namespace, - ClusterName: clusterName, - ClusterUID: clusterUID, - Comp2CompDefs: comp2CompDef, - Name: compName, - FullCompName: comp.Name, - CompDefName: compDef.Name, - ServiceVersion: comp.Spec.ServiceVersion, - ClusterGeneration: clusterGeneration(cluster, comp), - UserDefinedLabels: comp.Spec.Labels, - UserDefinedAnnotations: comp.Spec.Annotations, - PodSpec: &compDef.Spec.Runtime, - HostNetwork: compDefObj.Spec.HostNetwork, - ComponentServices: compDefObj.Spec.Services, - LogConfigs: compDefObj.Spec.LogConfigs, - ConfigTemplates: compDefObj.Spec.Configs, - ScriptTemplates: compDefObj.Spec.Scripts, - Roles: compDefObj.Spec.Roles, - UpdateStrategy: compDefObj.Spec.UpdateStrategy, - MinReadySeconds: compDefObj.Spec.MinReadySeconds, - PolicyRules: compDefObj.Spec.PolicyRules, - LifecycleActions: compDefObj.Spec.LifecycleActions, - SystemAccounts: mergeSystemAccounts(compDefObj.Spec.SystemAccounts, comp.Spec.SystemAccounts), - Replicas: comp.Spec.Replicas, - Resources: comp.Spec.Resources, - TLSConfig: comp.Spec.TLSConfig, - ServiceAccountName: comp.Spec.ServiceAccountName, - Instances: comp.Spec.Instances, - OfflineInstances: comp.Spec.OfflineInstances, - DisableExporter: comp.Spec.DisableExporter, - Stop: comp.Spec.Stop, - PodManagementPolicy: compDef.Spec.PodManagementPolicy, - PodUpdatePolicy: comp.Spec.PodUpdatePolicy, - EnabledLogs: comp.Spec.EnabledLogs, + Namespace: comp.Namespace, + ClusterName: clusterName, + ClusterUID: clusterUID, + Comp2CompDefs: comp2CompDef, + Name: compName, + FullCompName: comp.Name, + CompDefName: compDef.Name, + ServiceVersion: comp.Spec.ServiceVersion, + ClusterGeneration: clusterGeneration(cluster, comp), + UserDefinedLabels: comp.Spec.Labels, + UserDefinedAnnotations: comp.Spec.Annotations, + PodSpec: &compDef.Spec.Runtime, + HostNetwork: compDefObj.Spec.HostNetwork, + ComponentServices: compDefObj.Spec.Services, + LogConfigs: compDefObj.Spec.LogConfigs, + ConfigTemplates: compDefObj.Spec.Configs, + ScriptTemplates: compDefObj.Spec.Scripts, + Roles: compDefObj.Spec.Roles, + UpdateStrategy: compDefObj.Spec.UpdateStrategy, + MinReadySeconds: compDefObj.Spec.MinReadySeconds, + PolicyRules: compDefObj.Spec.PolicyRules, + LifecycleActions: compDefObj.Spec.LifecycleActions, + SystemAccounts: mergeSystemAccounts(compDefObj.Spec.SystemAccounts, comp.Spec.SystemAccounts), + Replicas: comp.Spec.Replicas, + Resources: comp.Spec.Resources, + TLSConfig: comp.Spec.TLSConfig, + ServiceAccountName: comp.Spec.ServiceAccountName, + Instances: comp.Spec.Instances, + OfflineInstances: comp.Spec.OfflineInstances, + DisableExporter: comp.Spec.DisableExporter, + Stop: comp.Spec.Stop, + PodManagementPolicy: compDef.Spec.PodManagementPolicy, + ParallelPodManagementConcurrency: comp.Spec.ParallelPodManagementConcurrency, + PodUpdatePolicy: comp.Spec.PodUpdatePolicy, + EnabledLogs: comp.Spec.EnabledLogs, } // build backward compatible fields, including workload, services, componentRefEnvs, clusterDefName, clusterCompDefName, and clusterCompVer, etc. diff --git a/pkg/controller/component/type.go b/pkg/controller/component/type.go index 2115b76ccbb5..d0c348197810 100644 --- a/pkg/controller/component/type.go +++ b/pkg/controller/component/type.go @@ -23,6 +23,7 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" + "k8s.io/apimachinery/pkg/util/intstr" "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" @@ -48,31 +49,32 @@ type SynthesizedComponent struct { TLSConfig *v1alpha1.TLSConfig `json:"tlsConfig"` ServiceAccountName string `json:"serviceAccountName,omitempty"` // TODO: remove this later - ComponentRefEnvs []corev1.EnvVar `json:"componentRefEnvs,omitempty"` - ServiceReferences map[string]*v1alpha1.ServiceDescriptor `json:"serviceReferences,omitempty"` - UserDefinedLabels map[string]string - UserDefinedAnnotations map[string]string - TemplateVars map[string]any `json:"templateVars,omitempty"` - EnvVars []corev1.EnvVar `json:"envVars,omitempty"` - EnvFromSources []corev1.EnvFromSource `json:"envFromSources,omitempty"` - Instances []v1alpha1.InstanceTemplate `json:"instances,omitempty"` - OfflineInstances []string `json:"offlineInstances,omitempty"` - Roles []v1alpha1.ReplicaRole `json:"roles,omitempty"` - Labels map[string]string `json:"labels,omitempty"` - Annotations map[string]string `json:"annotations,omitempty"` - UpdateStrategy *v1alpha1.UpdateStrategy `json:"updateStrategy,omitempty"` - PodManagementPolicy *appsv1.PodManagementPolicyType `json:"podManagementPolicy,omitempty"` - PodUpdatePolicy *workloads.PodUpdatePolicyType `json:"podUpdatePolicy,omitempty"` - PolicyRules []rbacv1.PolicyRule `json:"policyRules,omitempty"` - LifecycleActions *v1alpha1.ComponentLifecycleActions `json:"lifecycleActions,omitempty"` - SystemAccounts []v1alpha1.SystemAccount `json:"systemAccounts,omitempty"` - Volumes []v1alpha1.ComponentVolume `json:"volumes,omitempty"` - HostNetwork *v1alpha1.HostNetwork `json:"hostNetwork,omitempty"` - ComponentServices []v1alpha1.ComponentService `json:"componentServices,omitempty"` - MinReadySeconds int32 `json:"minReadySeconds,omitempty"` - Sidecars []string `json:"sidecars,omitempty"` - DisableExporter *bool `json:"disableExporter,omitempty"` - Stop *bool + ComponentRefEnvs []corev1.EnvVar `json:"componentRefEnvs,omitempty"` + ServiceReferences map[string]*v1alpha1.ServiceDescriptor `json:"serviceReferences,omitempty"` + UserDefinedLabels map[string]string + UserDefinedAnnotations map[string]string + TemplateVars map[string]any `json:"templateVars,omitempty"` + EnvVars []corev1.EnvVar `json:"envVars,omitempty"` + EnvFromSources []corev1.EnvFromSource `json:"envFromSources,omitempty"` + Instances []v1alpha1.InstanceTemplate `json:"instances,omitempty"` + OfflineInstances []string `json:"offlineInstances,omitempty"` + Roles []v1alpha1.ReplicaRole `json:"roles,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + Annotations map[string]string `json:"annotations,omitempty"` + UpdateStrategy *v1alpha1.UpdateStrategy `json:"updateStrategy,omitempty"` + PodManagementPolicy *appsv1.PodManagementPolicyType `json:"podManagementPolicy,omitempty"` + ParallelPodManagementConcurrency *intstr.IntOrString `json:"parallelPodManagementConcurrency,omitempty"` + PodUpdatePolicy *workloads.PodUpdatePolicyType `json:"podUpdatePolicy,omitempty"` + PolicyRules []rbacv1.PolicyRule `json:"policyRules,omitempty"` + LifecycleActions *v1alpha1.ComponentLifecycleActions `json:"lifecycleActions,omitempty"` + SystemAccounts []v1alpha1.SystemAccount `json:"systemAccounts,omitempty"` + Volumes []v1alpha1.ComponentVolume `json:"volumes,omitempty"` + HostNetwork *v1alpha1.HostNetwork `json:"hostNetwork,omitempty"` + ComponentServices []v1alpha1.ComponentService `json:"componentServices,omitempty"` + MinReadySeconds int32 `json:"minReadySeconds,omitempty"` + Sidecars []string `json:"sidecars,omitempty"` + DisableExporter *bool `json:"disableExporter,omitempty"` + Stop *bool // TODO(xingran): The following fields will be deprecated after KubeBlocks version 0.8.0 ClusterDefName string `json:"clusterDefName,omitempty"` // the name of the clusterDefinition diff --git a/pkg/controller/instanceset/reconciler_instance_alignment.go b/pkg/controller/instanceset/reconciler_instance_alignment.go index 7c6398a15b45..7b277aa7aa4b 100644 --- a/pkg/controller/instanceset/reconciler_instance_alignment.go +++ b/pkg/controller/instanceset/reconciler_instance_alignment.go @@ -84,12 +84,14 @@ func (r *instanceAlignmentReconciler) Reconcile(tree *kubebuilderx.ObjectTree) ( deleteNameSet := oldNameSet.Difference(newNameSet) // default OrderedReady policy - createCount, deleteCount := 1, 1 - shouldReady := true + isOrderedReady := true + concurrency := 0 if its.Spec.PodManagementPolicy == appsv1.ParallelPodManagement { - createCount = len(createNameSet) - deleteCount = len(deleteNameSet) - shouldReady = false + concurrency, err = CalculateConcurrencyReplicas(its.Spec.ParallelPodManagementConcurrency, int(*its.Spec.Replicas)) + if err != nil { + return nil, err + } + isOrderedReady = false } // TODO(free6om): handle BestEffortParallel: always keep the majority available. @@ -105,17 +107,26 @@ func (r *instanceAlignmentReconciler) Reconcile(tree *kubebuilderx.ObjectTree) ( } return oldInstanceMap[newNameList[i-1]] } + if !isOrderedReady { + for _, name := range newNameList { + if _, ok := createNameSet[name]; !ok { + if !isHealthy(oldInstanceMap[name]) { + concurrency-- + } + } + } + } var currentAlignedNameList []string for i, name := range newNameList { if _, ok := createNameSet[name]; !ok { currentAlignedNameList = append(currentAlignedNameList, name) continue } - if createCount <= 0 { + if !isOrderedReady && concurrency <= 0 { break } predecessor := getPredecessor(i) - if shouldReady && predecessor != nil && !isHealthy(predecessor) { + if isOrderedReady && predecessor != nil && !isHealthy(predecessor) { break } inst, err := buildInstanceByTemplate(name, nameToTemplateMap[name], its, "") @@ -126,7 +137,11 @@ func (r *instanceAlignmentReconciler) Reconcile(tree *kubebuilderx.ObjectTree) ( return nil, err } currentAlignedNameList = append(currentAlignedNameList, name) - createCount-- + + if isOrderedReady { + break + } + concurrency-- } // create PVCs @@ -159,10 +174,10 @@ func (r *instanceAlignmentReconciler) Reconcile(tree *kubebuilderx.ObjectTree) ( if _, ok := deleteNameSet[pod.Name]; !ok { continue } - if deleteCount <= 0 { + if !isOrderedReady && concurrency <= 0 { break } - if shouldReady && !isRunningAndReady(pod) { + if isOrderedReady && !isRunningAndReady(pod) { tree.EventRecorder.Eventf(its, corev1.EventTypeWarning, "InstanceSet %s/%s is waiting for Pod %s to be Running and Ready", its.Namespace, its.Name, @@ -173,7 +188,11 @@ func (r *instanceAlignmentReconciler) Reconcile(tree *kubebuilderx.ObjectTree) ( } // TODO(free6om): handle pvc management policy // Retain by default. - deleteCount-- + + if isOrderedReady { + break + } + concurrency-- } return tree, nil diff --git a/pkg/controller/instanceset/reconciler_instance_alignment_test.go b/pkg/controller/instanceset/reconciler_instance_alignment_test.go index 509bf25209bd..c15f15bef0d2 100644 --- a/pkg/controller/instanceset/reconciler_instance_alignment_test.go +++ b/pkg/controller/instanceset/reconciler_instance_alignment_test.go @@ -28,6 +28,7 @@ import ( "golang.org/x/exp/slices" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/intstr" "sigs.k8s.io/controller-runtime/pkg/client" workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" @@ -130,6 +131,32 @@ var _ = Describe("replicas alignment reconciler test", func() { return expectedPVCName == item.GetName() })).Should(BeNumerically(">=", 0)) } + + By("do reconcile with Parallel policy, ParallelPodManagementConcurrency is 50%") + parallelTree, err = tree.DeepCopy() + Expect(err).Should(BeNil()) + parallelITS, ok = parallelTree.GetRoot().(*workloads.InstanceSet) + Expect(ok).Should(BeTrue()) + parallelITS.Spec.PodManagementPolicy = appsv1.ParallelPodManagement + parallelITS.Spec.ParallelPodManagementConcurrency = &intstr.IntOrString{Type: intstr.String, StrVal: "50%"} + newTree, err = reconciler.Reconcile(parallelTree) + Expect(err).Should(BeNil()) + // replicas is 7, ParallelPodManagementConcurrency is 50%, so concurrency is 4. + // since the original bar-1 and bar-foo-0 are not ready, only the new instances bar-0 and bar-2 will be added. + // desired: bar-0, bar-1, bar-2, bar-foo-0 + pods = newTree.List(&corev1.Pod{}) + Expect(pods).Should(HaveLen(4)) + pvcs = newTree.List(&corev1.PersistentVolumeClaim{}) + Expect(pvcs).Should(HaveLen(4)) + for _, object := range []client.Object{podFoo0, podBar0, podBar1, podBar2} { + Expect(slices.IndexFunc(pods, func(item client.Object) bool { + return item.GetName() == object.GetName() + })).Should(BeNumerically(">=", 0)) + Expect(slices.IndexFunc(pvcs, func(item client.Object) bool { + expectedPVCName := fmt.Sprintf("%s-%s", volumeClaimTemplates[0].Name, object.GetName()) + return expectedPVCName == item.GetName() + })).Should(BeNumerically(">=", 0)) + } }) }) }) diff --git a/pkg/controller/instanceset/utils.go b/pkg/controller/instanceset/utils.go index f27a987dcf52..8545bd4445cf 100644 --- a/pkg/controller/instanceset/utils.go +++ b/pkg/controller/instanceset/utils.go @@ -27,7 +27,9 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/utils/integer" workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" "github.com/apecloud/kubeblocks/pkg/constant" @@ -249,3 +251,29 @@ func GetPodNameSetFromInstanceSetCondition(its *workloads.InstanceSet, condition } return podSet } + +// CalculateConcurrencyReplicas returns absolute value of concurrency for workload. This func can solve some +// corner cases about percentage-type concurrency, such as: +// - if concurrency > "0%" and replicas > 0, it will ensure at least 1 pod is reserved. +// - if concurrency < "100%" and replicas > 1, it will ensure at least 1 pod is reserved. +// +// if concurrency is nil, concurrency will be treated as 100%. +func CalculateConcurrencyReplicas(concurrency *intstr.IntOrString, replicas int) (int, error) { + if concurrency == nil { + return replicas, nil + } + + // 'roundUp=true' will ensure at least 1 pod is reserved if concurrency > "0%" and replicas > 0. + pValue, err := intstr.GetScaledValueFromIntOrPercent(concurrency, replicas, true) + if err != nil { + return pValue, err + } + + // if concurrency < "100%" and replicas > 1, it will ensure at least 1 pod is reserved. + if replicas > 1 && pValue == replicas && concurrency.Type == intstr.String && concurrency.StrVal != "100%" { + pValue = replicas - 1 + } + + pValue = integer.IntMax(integer.IntMin(pValue, replicas), 0) + return pValue, nil +} diff --git a/pkg/controller/instanceset/utils_test.go b/pkg/controller/instanceset/utils_test.go index 6720c3ca6b50..3f161500693a 100644 --- a/pkg/controller/instanceset/utils_test.go +++ b/pkg/controller/instanceset/utils_test.go @@ -26,6 +26,7 @@ import ( . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/intstr" workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" "github.com/apecloud/kubeblocks/pkg/controller/builder" @@ -232,4 +233,108 @@ var _ = Describe("utils test", func() { Expect(IsInstanceSetReady(its)).Should(BeTrue()) }) }) + + Context("CalculateConcurrencyReplicas function", func() { + It("should work well", func() { + By("concurrency = 50%, replicas = 10") + concurrent := &intstr.IntOrString{Type: intstr.String, StrVal: "50%"} + replicas := 10 + concurrencyReplicas, err := CalculateConcurrencyReplicas(concurrent, replicas) + Expect(err).Should(BeNil()) + Expect(concurrencyReplicas).Should(Equal(5)) + + By("concurrency = 50%, replicas = 0") + concurrent = &intstr.IntOrString{Type: intstr.String, StrVal: "50%"} + replicas = 0 + concurrencyReplicas, err = CalculateConcurrencyReplicas(concurrent, replicas) + Expect(err).Should(BeNil()) + Expect(concurrencyReplicas).Should(Equal(0)) + + By("concurrency = 0%, replicas = 10") + concurrent = &intstr.IntOrString{Type: intstr.String, StrVal: "0%"} + replicas = 10 + concurrencyReplicas, err = CalculateConcurrencyReplicas(concurrent, replicas) + Expect(err).Should(BeNil()) + Expect(concurrencyReplicas).Should(Equal(0)) + + By("concurrency = 5, replicas = 10") + concurrent = &intstr.IntOrString{Type: intstr.Int, IntVal: 5} + replicas = 10 + concurrencyReplicas, err = CalculateConcurrencyReplicas(concurrent, replicas) + Expect(err).Should(BeNil()) + Expect(concurrencyReplicas).Should(Equal(5)) + + By("concurrency = 5, replicas = 0") + concurrent = &intstr.IntOrString{Type: intstr.Int, IntVal: 5} + replicas = 0 + concurrencyReplicas, err = CalculateConcurrencyReplicas(concurrent, replicas) + Expect(err).Should(BeNil()) + Expect(concurrencyReplicas).Should(Equal(0)) + + By("concurrency = 0, replicas = 10") + concurrent = &intstr.IntOrString{Type: intstr.Int, IntVal: 0} + replicas = 10 + concurrencyReplicas, err = CalculateConcurrencyReplicas(concurrent, replicas) + Expect(err).Should(BeNil()) + Expect(concurrencyReplicas).Should(Equal(0)) + + By("concurrency = 10%, replicas = 1") + concurrent = &intstr.IntOrString{Type: intstr.String, StrVal: "10%"} + replicas = 1 + concurrencyReplicas, err = CalculateConcurrencyReplicas(concurrent, replicas) + Expect(err).Should(BeNil()) + Expect(concurrencyReplicas).Should(Equal(1)) + + By("concurrency = 60%, replicas = 2") + concurrent = &intstr.IntOrString{Type: intstr.String, StrVal: "60%"} + replicas = 2 + concurrencyReplicas, err = CalculateConcurrencyReplicas(concurrent, replicas) + Expect(err).Should(BeNil()) + Expect(concurrencyReplicas).Should(Equal(1)) + + By("concurrency is nil") + replicas = 10 + concurrencyReplicas, err = CalculateConcurrencyReplicas(nil, replicas) + Expect(err).Should(BeNil()) + Expect(concurrencyReplicas).Should(Equal(10)) + + By("concurrency is a string but not a percentage") + replicas = 10 + concurrent = &intstr.IntOrString{Type: intstr.String, StrVal: "50"} + concurrencyReplicas, err = CalculateConcurrencyReplicas(concurrent, replicas) + ErrConcurrencyNotPercentage := fmt.Errorf("invalid value for IntOrString: invalid type: string is not a percentage") + Expect(err).Should(Equal(ErrConcurrencyNotPercentage)) + Expect(concurrencyReplicas).Should(Equal(0)) + + By("concurrency percentage < 0%") + replicas = 10 + concurrent = &intstr.IntOrString{Type: intstr.String, StrVal: "-50%"} + concurrencyReplicas, err = CalculateConcurrencyReplicas(concurrent, replicas) + Expect(err).Should(BeNil()) + Expect(concurrencyReplicas).Should(Equal(0)) + + By("concurrency percentage > 100%") + replicas = 10 + concurrent = &intstr.IntOrString{Type: intstr.String, StrVal: "150%"} + concurrencyReplicas, err = CalculateConcurrencyReplicas(concurrent, replicas) + Expect(err).Should(BeNil()) + Expect(concurrencyReplicas).Should(Equal(10)) + + By("concurrency type neither int nor percentage") + replicas = 10 + unknownType := intstr.Type(2) + concurrent = &intstr.IntOrString{Type: unknownType, StrVal: "50%"} + concurrencyReplicas, err = CalculateConcurrencyReplicas(concurrent, replicas) + ErrConcurrencyInvalidType := fmt.Errorf("invalid value for IntOrString: invalid type: neither int nor percentage") + Expect(err).Should(Equal(ErrConcurrencyInvalidType)) + Expect(concurrencyReplicas).Should(Equal(0)) + + By("concurrency > replicas") + replicas = 10 + concurrent = &intstr.IntOrString{Type: intstr.Int, IntVal: 15} + concurrencyReplicas, err = CalculateConcurrencyReplicas(concurrent, replicas) + Expect(err).Should(BeNil()) + Expect(concurrencyReplicas).Should(Equal(10)) + }) + }) }) From a84a121de97f43b30a27f545f8c3a0bbe85ca04b Mon Sep 17 00:00:00 2001 From: Liang Deng <283304489@qq.com> Date: Fri, 26 Jul 2024 16:58:20 +0800 Subject: [PATCH 11/45] fix: PodUpdatePolicy field cannot be synchronized from component to instanceSet (#7880) Signed-off-by: Liang Deng <283304489@qq.com> --- controllers/apps/transformer_component_workload.go | 1 + 1 file changed, 1 insertion(+) diff --git a/controllers/apps/transformer_component_workload.go b/controllers/apps/transformer_component_workload.go index 22cf8f954644..a1910d85f528 100644 --- a/controllers/apps/transformer_component_workload.go +++ b/controllers/apps/transformer_component_workload.go @@ -331,6 +331,7 @@ func copyAndMergeITS(oldITS, newITS *workloads.InstanceSet, synthesizeComp *comp itsObjCopy.Spec.MinReadySeconds = itsProto.Spec.MinReadySeconds itsObjCopy.Spec.VolumeClaimTemplates = itsProto.Spec.VolumeClaimTemplates itsObjCopy.Spec.ParallelPodManagementConcurrency = itsProto.Spec.ParallelPodManagementConcurrency + itsObjCopy.Spec.PodUpdatePolicy = itsProto.Spec.PodUpdatePolicy if itsProto.Spec.UpdateStrategy.Type != "" || itsProto.Spec.UpdateStrategy.RollingUpdate != nil { updateUpdateStrategy(itsObjCopy, itsProto) From bab7dff5add736c7302768f8e69be07344243a32 Mon Sep 17 00:00:00 2001 From: yuanyuan zhang <111744220+michelle-0808@users.noreply.github.com> Date: Mon, 29 Jul 2024 10:26:24 +0800 Subject: [PATCH 12/45] chore: update slack link (#7885) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b21577097d73..6aa901b53c7b 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ KubeCon 2024 in HongKong from 21-23 August 2024: [KuaiShou's 100% Resource Utili ## Community -- KubeBlocks [Slack Channel](https://join.slack.com/t/kubeblocks/shared_invite/zt-2lyc3cwsg-m07xaaN8Rle~ao3soPWKUw) +- KubeBlocks [Slack Channel](https://join.slack.com/t/kubeblocks/shared_invite/zt-2njvf6bxx-WwWIEH9MlWp5LrkS7h8qFQ) - KubeBlocks Github [Discussions](https://github.com/apecloud/kubeblocks/discussions) - KubeBlocks Wechat Account: wechat From 8a190b0ef9f6d0ef4e1a672ff88561e05f2e4ec6 Mon Sep 17 00:00:00 2001 From: wangyelei Date: Mon, 29 Jul 2024 11:03:33 +0800 Subject: [PATCH 13/45] fix: duplicate volume name when the pod selection strategy is All for custom ops (#7884) --- controllers/apps/operations/custom/action_workload.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/controllers/apps/operations/custom/action_workload.go b/controllers/apps/operations/custom/action_workload.go index bad7447c1267..f8fa6ed32b51 100644 --- a/controllers/apps/operations/custom/action_workload.go +++ b/controllers/apps/operations/custom/action_workload.go @@ -140,7 +140,7 @@ func (w *WorkloadAction) buildPodSpec(actionCtx ActionContext, var ( workloadAction = actionCtx.Action.Workload - podSpec = workloadAction.PodSpec + podSpec = workloadAction.PodSpec.DeepCopy() volumeMounts []corev1.VolumeMount env []corev1.EnvVar ) @@ -174,7 +174,7 @@ func (w *WorkloadAction) buildPodSpec(actionCtx ActionContext, intctrlutil.InjectZeroResourcesLimitsIfEmpty(&podSpec.Containers[i]) } // inject extras script. - w.injectOpsUtils(&podSpec) + w.injectOpsUtils(podSpec) for i := range podSpec.InitContainers { intctrlutil.InjectZeroResourcesLimitsIfEmpty(&podSpec.InitContainers[i]) } @@ -198,7 +198,7 @@ func (w *WorkloadAction) buildPodSpec(actionCtx ActionContext, podSpec.ServiceAccountName = saKey.Name } } - return &podSpec, nil + return podSpec, nil } func (w *WorkloadAction) injectOpsUtils(podSpec *corev1.PodSpec) { From 3639365acc653c97253e600a883f573e9724875f Mon Sep 17 00:00:00 2001 From: Leon Date: Mon, 29 Jul 2024 11:20:55 +0800 Subject: [PATCH 14/45] chore: handle update orders for stop (#7883) --- controllers/apps/component_controller_test.go | 2 +- .../apps/transformer_cluster_component.go | 37 +++--- .../transformer_cluster_component_test.go | 113 ++++++++++++++++-- 3 files changed, 128 insertions(+), 24 deletions(-) diff --git a/controllers/apps/component_controller_test.go b/controllers/apps/component_controller_test.go index 41a0fb2177f9..5971d7c33818 100644 --- a/controllers/apps/component_controller_test.go +++ b/controllers/apps/component_controller_test.go @@ -2269,7 +2269,7 @@ var _ = Describe("Component Controller", func() { replicationCompName: replicationCompDefName, } initialReplicas := int32(1) - updatedReplicas := int32(3) + updatedReplicas := int32(2) By("Creating a multi components cluster with VolumeClaimTemplate") pvcSpec := testapps.NewPVCSpec("1Gi") diff --git a/controllers/apps/transformer_cluster_component.go b/controllers/apps/transformer_cluster_component.go index 785fdfa93c25..bbdd59980750 100644 --- a/controllers/apps/transformer_cluster_component.go +++ b/controllers/apps/transformer_cluster_component.go @@ -135,22 +135,22 @@ func deleteCompsInOrder(transCtx *clusterTransformContext, dag *graph.DAG, delet func handleCompsInOrder(transCtx *clusterTransformContext, dag *graph.DAG, compNameSet sets.Set[string], handler compConditionalHandler) error { - var unmatched []string + unmatched := "" for _, compName := range handler.ordered(sets.List(compNameSet)) { ok, err := handler.match(transCtx, dag, compName) if err != nil { return err } - if ok { - if err = handler.handle(transCtx, dag, compName); err != nil { - return err - } - } else { - unmatched = append(unmatched, compName) + if !ok { + unmatched = compName + break + } + if err = handler.handle(transCtx, dag, compName); err != nil { + return err } } if len(unmatched) > 0 { - return ictrlutil.NewDelayedRequeueError(0, fmt.Sprintf("retry later: %s are not ready", strings.Join(unmatched, ","))) + return ictrlutil.NewDelayedRequeueError(0, fmt.Sprintf("retry later: %s are not ready", unmatched)) } return nil } @@ -306,6 +306,13 @@ func newParallelHandler(compSpecs map[string]*appsv1alpha1.ClusterComponentSpec, func newOrderedHandler(compSpecs map[string]*appsv1alpha1.ClusterComponentSpec, labels, annotations map[string]map[string]string, orders []string, op int) compConditionalHandler { + upworking := func(comp *appsv1alpha1.Component) bool { + target := appsv1alpha1.RunningClusterCompPhase + if comp.Spec.Stop != nil && *comp.Spec.Stop { + target = appsv1alpha1.StoppedClusterCompPhase + } + return comp.Status.Phase == target + } switch op { case createOp: return &orderedCreateCompHandler{ @@ -313,8 +320,8 @@ func newOrderedHandler(compSpecs map[string]*appsv1alpha1.ClusterComponentSpec, orders: orders, }, compPhasePrecondition: compPhasePrecondition{ - orders: orders, - expectedPhases: []appsv1alpha1.ClusterComponentPhase{appsv1alpha1.RunningClusterCompPhase}, + orders: orders, + phaseExpectation: upworking, }, createCompHandler: createCompHandler{ compSpecs: compSpecs, @@ -338,8 +345,8 @@ func newOrderedHandler(compSpecs map[string]*appsv1alpha1.ClusterComponentSpec, orders: orders, }, compPhasePrecondition: compPhasePrecondition{ - orders: orders, - expectedPhases: []appsv1alpha1.ClusterComponentPhase{appsv1alpha1.RunningClusterCompPhase}, + orders: orders, + phaseExpectation: upworking, }, updateCompHandler: updateCompHandler{ compSpecs: compSpecs, @@ -433,8 +440,8 @@ func (c *compNotExistPrecondition) match(transCtx *clusterTransformContext, dag } type compPhasePrecondition struct { - orders []string - expectedPhases []appsv1alpha1.ClusterComponentPhase + orders []string + phaseExpectation func(component2 *appsv1alpha1.Component) bool } func (c *compPhasePrecondition) match(transCtx *clusterTransformContext, dag *graph.DAG, compName string) (bool, error) { @@ -456,7 +463,7 @@ func (c *compPhasePrecondition) match(transCtx *clusterTransformContext, dag *gr if err := transCtx.Client.Get(transCtx.Context, compKey, comp); err != nil { return false, client.IgnoreNotFound(err) } - if comp.Generation != comp.Status.ObservedGeneration || slices.Index(c.expectedPhases, comp.Status.Phase) < 0 { + if comp.Generation != comp.Status.ObservedGeneration || !c.phaseExpectation(comp) { return false, nil } // create or update if exists in DAG diff --git a/controllers/apps/transformer_cluster_component_test.go b/controllers/apps/transformer_cluster_component_test.go index 77965f49e078..03b32dcb57d6 100644 --- a/controllers/apps/transformer_cluster_component_test.go +++ b/controllers/apps/transformer_cluster_component_test.go @@ -77,12 +77,14 @@ var _ = Describe("cluster component transformer test", func() { clusterTopologyDefault = "test-topology-default" clusterTopologyNoOrders = "test-topology-no-orders" clusterTopologyProvisionNUpdateOOD = "test-topology-ood" + clusterTopology4Stop = "test-topology-stop" compDefName = "test-compdef" clusterName = "test-cluster" comp1aName = "comp-1a" comp1bName = "comp-1b" comp2aName = "comp-2a" comp2bName = "comp-2b" + comp3aName = "comp-3a" ) var ( @@ -178,6 +180,26 @@ var _ = Describe("cluster component transformer test", func() { }, }, }). + AddClusterTopology(appsv1alpha1.ClusterTopology{ + Name: clusterTopology4Stop, + Components: []appsv1alpha1.ClusterTopologyComponent{ + { + Name: comp1aName, + CompDef: compDefName, + }, + { + Name: comp2aName, + CompDef: compDefName, + }, + { + Name: comp3aName, + CompDef: compDefName, + }, + }, + Orders: &appsv1alpha1.ClusterTopologyOrders{ + Update: []string{comp1aName, comp2aName, comp3aName}, + }, + }). GetObject() }) @@ -258,7 +280,7 @@ var _ = Describe("cluster component transformer test", func() { transformer, transCtx, dag := newTransformerNCtx(clusterTopologyDefault) err := transformer.Transform(transCtx, dag) Expect(err).ShouldNot(BeNil()) - Expect(err.Error()).Should(And(ContainSubstring("retry later"), ContainSubstring(comp2aName), ContainSubstring(comp2bName))) + Expect(err.Error()).Should(And(ContainSubstring("retry later"), ContainSubstring(comp2aName))) // check the first two components graphCli := transCtx.Client.(model.GraphClient) @@ -289,7 +311,7 @@ var _ = Describe("cluster component transformer test", func() { err := transformer.Transform(transCtx, dag) Expect(err).ShouldNot(BeNil()) - Expect(err.Error()).Should(And(ContainSubstring("retry later"), ContainSubstring(comp2aName), ContainSubstring(comp2bName))) + Expect(err.Error()).Should(And(ContainSubstring("retry later"), ContainSubstring(comp2aName))) // should have no components to update graphCli := transCtx.Client.(model.GraphClient) @@ -312,7 +334,7 @@ var _ = Describe("cluster component transformer test", func() { err := transformer.Transform(transCtx, dag) Expect(err).ShouldNot(BeNil()) - Expect(err.Error()).Should(And(ContainSubstring("retry later"), ContainSubstring(comp2aName), ContainSubstring(comp2bName))) + Expect(err.Error()).Should(And(ContainSubstring("retry later"), ContainSubstring(comp2aName))) // should have one component to create graphCli := transCtx.Client.(model.GraphClient) @@ -372,7 +394,7 @@ var _ = Describe("cluster component transformer test", func() { err := transformer.Transform(transCtx, dag) Expect(err).ShouldNot(BeNil()) - Expect(err.Error()).Should(And(ContainSubstring("retry later"), ContainSubstring(comp2aName), ContainSubstring(comp2bName))) + Expect(err.Error()).Should(And(ContainSubstring("retry later"), ContainSubstring(comp2aName))) // check the first component graphCli := transCtx.Client.(model.GraphClient) @@ -409,8 +431,7 @@ var _ = Describe("cluster component transformer test", func() { err := transformer.Transform(transCtx, dag) Expect(err).ShouldNot(BeNil()) - // TODO: should not contain comp2bName - Expect(err.Error()).Should(And(ContainSubstring("retry later"), ContainSubstring(comp2aName), ContainSubstring(comp2bName))) + Expect(err.Error()).Should(And(ContainSubstring("retry later"), ContainSubstring(comp2aName))) // should have no components to update graphCli := transCtx.Client.(model.GraphClient) @@ -445,8 +466,7 @@ var _ = Describe("cluster component transformer test", func() { err := transformer.Transform(transCtx, dag) Expect(err).ShouldNot(BeNil()) - // TODO: should not contain comp2bName - Expect(err.Error()).Should(And(ContainSubstring("retry later"), ContainSubstring(comp2aName), ContainSubstring(comp2bName))) + Expect(err.Error()).Should(And(ContainSubstring("retry later"), ContainSubstring(comp2aName))) // should have one component to update graphCli := transCtx.Client.(model.GraphClient) @@ -492,6 +512,83 @@ var _ = Describe("cluster component transformer test", func() { Expect(graphCli.IsAction(dag, comp, model.ActionUpdatePtr())).Should(BeTrue()) }) + It("w/ orders update - stop", func() { + transformer, transCtx, dag := newTransformerNCtx(clusterTopology4Stop) + + // mock to stop all components + reader := &mockReader{ + objs: []client.Object{ + mockCompObj(transCtx, comp1aName, func(comp *appsv1alpha1.Component) { + comp.Status.Phase = appsv1alpha1.RunningClusterCompPhase + }), + mockCompObj(transCtx, comp2aName, func(comp *appsv1alpha1.Component) { + comp.Status.Phase = appsv1alpha1.RunningClusterCompPhase + }), + mockCompObj(transCtx, comp3aName, func(comp *appsv1alpha1.Component) { + comp.Status.Phase = appsv1alpha1.RunningClusterCompPhase + }), + }, + } + transCtx.Client = model.NewGraphClient(reader) + for i := range transCtx.ComponentSpecs { + transCtx.ComponentSpecs[i].Stop = &[]bool{true}[0] + } + transCtx.OrigCluster.Generation += 1 // mock cluster spec update + + err := transformer.Transform(transCtx, dag) + Expect(err).ShouldNot(BeNil()) + Expect(err.Error()).Should(And(ContainSubstring("retry later"), ContainSubstring(comp2aName))) + + // should have the first component to update only + graphCli := transCtx.Client.(model.GraphClient) + objs := graphCli.FindAll(dag, &appsv1alpha1.Component{}) + Expect(len(objs)).Should(Equal(1)) + comp := objs[0].(*appsv1alpha1.Component) + Expect(component.ShortName(transCtx.Cluster.Name, comp.Name)).Should(Equal(comp1aName)) + Expect(graphCli.IsAction(dag, comp, model.ActionUpdatePtr())).Should(BeTrue()) + Expect(comp.Spec.Stop).ShouldNot(BeNil()) + Expect(*comp.Spec.Stop).Should(BeTrue()) + }) + + It("w/ orders update - stop the second component", func() { + transformer, transCtx, dag := newTransformerNCtx(clusterTopology4Stop) + + // mock to stop all components and the first component has been stopped + reader := &mockReader{ + objs: []client.Object{ + mockCompObj(transCtx, comp1aName, func(comp *appsv1alpha1.Component) { + comp.Spec.Stop = &[]bool{true}[0] + comp.Status.Phase = appsv1alpha1.StoppedClusterCompPhase + }), + mockCompObj(transCtx, comp2aName, func(comp *appsv1alpha1.Component) { + comp.Status.Phase = appsv1alpha1.RunningClusterCompPhase + }), + mockCompObj(transCtx, comp3aName, func(comp *appsv1alpha1.Component) { + comp.Status.Phase = appsv1alpha1.RunningClusterCompPhase + }), + }, + } + transCtx.Client = model.NewGraphClient(reader) + for i := range transCtx.ComponentSpecs { + transCtx.ComponentSpecs[i].Stop = &[]bool{true}[0] + } + transCtx.OrigCluster.Generation += 1 // mock cluster spec update + + err := transformer.Transform(transCtx, dag) + Expect(err).ShouldNot(BeNil()) + Expect(err.Error()).Should(And(ContainSubstring("retry later"), ContainSubstring(comp3aName))) + + // should have the second component to update only + graphCli := transCtx.Client.(model.GraphClient) + objs := graphCli.FindAll(dag, &appsv1alpha1.Component{}) + Expect(len(objs)).Should(Equal(1)) + comp := objs[0].(*appsv1alpha1.Component) + Expect(component.ShortName(transCtx.Cluster.Name, comp.Name)).Should(Equal(comp2aName)) + Expect(graphCli.IsAction(dag, comp, model.ActionUpdatePtr())).Should(BeTrue()) + Expect(comp.Spec.Stop).ShouldNot(BeNil()) + Expect(*comp.Spec.Stop).Should(BeTrue()) + }) + It("w/ orders provision & update - OOD", func() { transformer, transCtx, dag := newTransformerNCtx(clusterTopologyProvisionNUpdateOOD) From 90c10d890ac43378d42667cfd08637cd00ee075b Mon Sep 17 00:00:00 2001 From: Leon Date: Mon, 29 Jul 2024 12:18:50 +0800 Subject: [PATCH 15/45] chore: remove the HTTP action (#7878) --- .../v1alpha1/componentdefinition_types.go | 48 -- apis/apps/v1alpha1/zz_generated.deepcopy.go | 26 - ...ps.kubeblocks.io_componentdefinitions.yaml | 806 ------------------ ...ps.kubeblocks.io_componentdefinitions.yaml | 806 ------------------ docs/developer_docs/api-reference/cluster.md | 198 ++--- 5 files changed, 80 insertions(+), 1804 deletions(-) diff --git a/apis/apps/v1alpha1/componentdefinition_types.go b/apis/apps/v1alpha1/componentdefinition_types.go index 8937495b652a..d0e2150903f8 100644 --- a/apis/apps/v1alpha1/componentdefinition_types.go +++ b/apis/apps/v1alpha1/componentdefinition_types.go @@ -23,7 +23,6 @@ import ( corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" ) // +genclient @@ -697,44 +696,6 @@ const ( OrdinalSelector TargetPodSelector = "Ordinal" ) -// HTTPAction describes an Action that triggers HTTP requests. -// HTTPAction is to be implemented in future version. -type HTTPAction struct { - // Specifies the endpoint to be requested on the HTTP server. - // - // +optional - Path string `json:"path,omitempty"` - - // Specifies the target port for the HTTP request. - // It can be specified either as a numeric value in the range of 1 to 65535, - // or as a named port that meets the IANA_SVC_NAME specification. - Port intstr.IntOrString `json:"port"` - - // Indicates the server's domain name or IP address. Defaults to the Pod's IP. - // Prefer setting the "Host" header in httpHeaders when needed. - // - // +optional - Host string `json:"host,omitempty"` - - // Designates the protocol used to make the request, such as HTTP or HTTPS. - // If not specified, HTTP is used by default. - // - // +optional - Scheme corev1.URIScheme `json:"scheme,omitempty"` - - // Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - // If not specified, "GET" is the default method. - // - // +optional - Method string `json:"method,omitempty"` - - // Allows for the inclusion of custom headers in the request. - // HTTP permits the use of repeated headers. - // - // +optional - HTTPHeaders []corev1.HTTPHeader `json:"httpHeaders,omitempty"` -} - // ExecAction describes an Action that executes a command inside a container. // Which may run as a K8s job or be executed inside the Lorry sidecar container, depending on the implementation. // Future implementations will standardize execution within Lorry. @@ -894,15 +855,6 @@ type Action struct { // +optional Exec *ExecAction `json:"exec,omitempty"` - // Specifies the HTTP request to perform. - // - // This field cannot be updated. - // - // Note: HTTPAction is to be implemented in future version. - // - // +optional - HTTP *HTTPAction `json:"http,omitempty"` - // Specifies the maximum duration in seconds that the Action is allowed to run. // // If the Action does not complete within this time frame, it will be terminated. diff --git a/apis/apps/v1alpha1/zz_generated.deepcopy.go b/apis/apps/v1alpha1/zz_generated.deepcopy.go index abf4600fc837..abc2bf91c376 100644 --- a/apis/apps/v1alpha1/zz_generated.deepcopy.go +++ b/apis/apps/v1alpha1/zz_generated.deepcopy.go @@ -42,11 +42,6 @@ func (in *Action) DeepCopyInto(out *Action) { *out = new(ExecAction) (*in).DeepCopyInto(*out) } - if in.HTTP != nil { - in, out := &in.HTTP, &out.HTTP - *out = new(HTTPAction) - (*in).DeepCopyInto(*out) - } if in.RetryPolicy != nil { in, out := &in.RetryPolicy, &out.RetryPolicy *out = new(RetryPolicy) @@ -3257,27 +3252,6 @@ func (in *Expose) DeepCopy() *Expose { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPAction) DeepCopyInto(out *HTTPAction) { - *out = *in - out.Port = in.Port - if in.HTTPHeaders != nil { - in, out := &in.HTTPHeaders, &out.HTTPHeaders - *out = make([]v1.HTTPHeader, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPAction. -func (in *HTTPAction) DeepCopy() *HTTPAction { - if in == nil { - return nil - } - out := new(HTTPAction) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HorizontalScalePolicy) DeepCopyInto(out *HorizontalScalePolicy) { *out = *in diff --git a/config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml b/config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml index 9dce8a05d401..26f7abfb1a1f 100644 --- a/config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml +++ b/config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml @@ -690,68 +690,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -1100,68 +1038,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -1509,68 +1385,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -1926,68 +1740,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -2345,68 +2097,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -2776,68 +2466,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -3214,68 +2842,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -3626,68 +3192,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -4040,68 +3544,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -4438,68 +3880,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -4809,68 +4189,6 @@ spec: Defaults to 3. Minimum value is 1. format: int32 type: integer - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header to - be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested on - the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object initialDelaySeconds: description: |- Specifies the number of seconds to wait after the container has started before the RoleProbe @@ -5208,68 +4526,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -5542,68 +4798,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. diff --git a/deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml b/deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml index 9dce8a05d401..26f7abfb1a1f 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml @@ -690,68 +690,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -1100,68 +1038,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -1509,68 +1385,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -1926,68 +1740,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -2345,68 +2097,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -2776,68 +2466,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -3214,68 +2842,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -3626,68 +3192,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -4040,68 +3544,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -4438,68 +3880,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -4809,68 +4189,6 @@ spec: Defaults to 3. Minimum value is 1. format: int32 type: integer - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header to - be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested on - the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object initialDelaySeconds: description: |- Specifies the number of seconds to wait after the container has started before the RoleProbe @@ -5208,68 +4526,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -5542,68 +4798,6 @@ spec: - Ordinal type: string type: object - http: - description: |- - Specifies the HTTP request to perform. - - - This field cannot be updated. - - - Note: HTTPAction is to be implemented in future version. - properties: - host: - description: |- - Indicates the server's domain name or IP address. Defaults to the Pod's IP. - Prefer setting the "Host" header in httpHeaders when needed. - type: string - httpHeaders: - description: |- - Allows for the inclusion of custom headers in the request. - HTTP permits the use of repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - method: - description: |- - Represents the type of HTTP request to be made, such as "GET," "POST," "PUT," etc. - If not specified, "GET" is the default method. - type: string - path: - description: Specifies the endpoint to be requested - on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Specifies the target port for the HTTP request. - It can be specified either as a numeric value in the range of 1 to 65535, - or as a named port that meets the IANA_SVC_NAME specification. - x-kubernetes-int-or-string: true - scheme: - description: |- - Designates the protocol used to make the request, such as HTTP or HTTPS. - If not specified, HTTP is used by default. - type: string - required: - - port - type: object preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. diff --git a/docs/developer_docs/api-reference/cluster.md b/docs/developer_docs/api-reference/cluster.md index 1ff3e9ff456c..e9a1dbb81309 100644 --- a/docs/developer_docs/api-reference/cluster.md +++ b/docs/developer_docs/api-reference/cluster.md @@ -997,6 +997,22 @@ an existed ServiceAccount in this field.

+parallelPodManagementConcurrency
+ + +Kubernetes api utils intstr.IntOrString + + + + +(Optional) +

Controls the concurrency of pods during initial scale up, when replacing pods on nodes, +or when scaling down. It only used when PodManagementPolicy is set to Parallel. +The default Concurrency is 100%.

+ + + + podUpdatePolicy
@@ -3059,22 +3075,6 @@ ExecAction -http
- -
-HTTPAction - - - - -(Optional) -

Specifies the HTTP request to perform.

-

This field cannot be updated.

-

Note: HTTPAction is to be implemented in future version.

- - - - timeoutSeconds
int32 @@ -5001,6 +5001,22 @@ Existing usage should be updated to the current preferred approach to avoid comp +parallelPodManagementConcurrency
+ + +Kubernetes api utils intstr.IntOrString + + + + +(Optional) +

Controls the concurrency of pods during initial scale up, when replacing pods on nodes, +or when scaling down. It only used when PodManagementPolicy is set to Parallel. +The default Concurrency is 100%.

+ + + + podUpdatePolicy
@@ -8801,6 +8817,22 @@ an existed ServiceAccount in this field.

+parallelPodManagementConcurrency
+ +
+Kubernetes api utils intstr.IntOrString + + + + +(Optional) +

Controls the concurrency of pods during initial scale up, when replacing pods on nodes, +or when scaling down. It only used when PodManagementPolicy is set to Parallel. +The default Concurrency is 100%.

+ + + + podUpdatePolicy
@@ -11943,108 +11975,6 @@ The policy can be set to None, CloneVolume, or S -

HTTPAction -

-

-(Appears on:Action) -

-
-

HTTPAction describes an Action that triggers HTTP requests. -HTTPAction is to be implemented in future version.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FieldDescription
-path
- -string - -
-(Optional) -

Specifies the endpoint to be requested on the HTTP server.

-
-port
- - -Kubernetes api utils intstr.IntOrString - - -
-

Specifies the target port for the HTTP request. -It can be specified either as a numeric value in the range of 1 to 65535, -or as a named port that meets the IANA_SVC_NAME specification.

-
-host
- -string - -
-(Optional) -

Indicates the server’s domain name or IP address. Defaults to the Pod’s IP. -Prefer setting the “Host” header in httpHeaders when needed.

-
-scheme
- - -Kubernetes core/v1.URIScheme - - -
-(Optional) -

Designates the protocol used to make the request, such as HTTP or HTTPS. -If not specified, HTTP is used by default.

-
-method
- -string - -
-(Optional) -

Represents the type of HTTP request to be made, such as “GET,” “POST,” “PUT,” etc. -If not specified, “GET” is the default method.

-
-httpHeaders
- - -[]Kubernetes core/v1.HTTPHeader - - -
-(Optional) -

Allows for the inclusion of custom headers in the request. -HTTP permits the use of repeated headers.

-

HorizontalScalePolicy

@@ -22994,6 +22924,22 @@ all pods at once.

+parallelPodManagementConcurrency
+ + +Kubernetes api utils intstr.IntOrString + + + + +(Optional) +

Controls the concurrency of pods during initial scale up, when replacing pods on nodes, +or when scaling down. It only used when PodManagementPolicy is set to Parallel. +The default Concurrency is 100%.

+ + + + podUpdatePolicy
@@ -23526,6 +23472,22 @@ all pods at once.

+parallelPodManagementConcurrency
+ +
+Kubernetes api utils intstr.IntOrString + + + + +(Optional) +

Controls the concurrency of pods during initial scale up, when replacing pods on nodes, +or when scaling down. It only used when PodManagementPolicy is set to Parallel. +The default Concurrency is 100%.

+ + + + podUpdatePolicy
From e715d3a273f168e2b9d537f2115de2e4a5eb9dbd Mon Sep 17 00:00:00 2001 From: xuriwuyun Date: Mon, 29 Jul 2024 13:07:01 +0800 Subject: [PATCH 16/45] fix: do not call memberleave if the action is undefined (#7841) --- controllers/apps/component_controller_test.go | 16 ++++----- .../apps/transformer_component_workload.go | 34 +++++++++++-------- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/controllers/apps/component_controller_test.go b/controllers/apps/component_controller_test.go index 5971d7c33818..fa40ac39e771 100644 --- a/controllers/apps/component_controller_test.go +++ b/controllers/apps/component_controller_test.go @@ -242,7 +242,7 @@ var _ = Describe("Component Controller", func() { Create(&testCtx). GetObject() - By("Create a componentDefinition obj") + By("Create a componentVersion obj") compVerObj = testapps.NewComponentVersionFactory(compVerName). SetDefaultSpec(compDefName). Create(&testCtx). @@ -831,7 +831,7 @@ var _ = Describe("Component Controller", func() { dataClonePolicy appsv1alpha1.HScaleDataClonePolicyType) { By("Creating a single component cluster with VolumeClaimTemplate") pvcSpec := testapps.NewPVCSpec("1Gi") - createClusterObj(compName, compDefName, func(f *testapps.MockClusterFactory) { + createClusterObjV2(compName, compDefName, func(f *testapps.MockClusterFactory) { f.SetReplicas(initialReplicas). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). AddVolumeClaimTemplate(testapps.LogVolumeName, pvcSpec) @@ -2335,28 +2335,28 @@ var _ = Describe("Component Controller", func() { Context(fmt.Sprintf("[comp: %s] horizontal scale", compName), func() { It("scale-out from 1 to 3 with backup(snapshot) policy normally", func() { - testHorizontalScale(compName, compDefName, 1, 3, appsv1alpha1.HScaleDataClonePolicyCloneVolume) + testHorizontalScale(compName, compDefObj.Name, 1, 3, appsv1alpha1.HScaleDataClonePolicyCloneVolume) }) // TODO(component): events & conditions PIt("backup error at scale-out", func() { - testBackupError(compName, compDefName) + testBackupError(compName, compDefObj.Name) }) It("scale-out without data clone policy", func() { - testHorizontalScale(compName, compDefName, 1, 3, "") + testHorizontalScale(compName, compDefObj.Name, 1, 3, "") }) It("scale-in from 3 to 1", func() { - testHorizontalScale(compName, compDefName, 3, 1, appsv1alpha1.HScaleDataClonePolicyCloneVolume) + testHorizontalScale(compName, compDefObj.Name, 3, 1, appsv1alpha1.HScaleDataClonePolicyCloneVolume) }) It("scale-in to 0 and PVCs should not been deleted", func() { - testHorizontalScale(compName, compDefName, 3, 0, appsv1alpha1.HScaleDataClonePolicyCloneVolume) + testHorizontalScale(compName, compDefObj.Name, 3, 0, appsv1alpha1.HScaleDataClonePolicyCloneVolume) }) It("scale-out from 0 and should work well", func() { - testHorizontalScale(compName, compDefName, 0, 3, appsv1alpha1.HScaleDataClonePolicyCloneVolume) + testHorizontalScale(compName, compDefObj.Name, 0, 3, appsv1alpha1.HScaleDataClonePolicyCloneVolume) }) }) diff --git a/controllers/apps/transformer_component_workload.go b/controllers/apps/transformer_component_workload.go index a1910d85f528..98890ba9d1c4 100644 --- a/controllers/apps/transformer_component_workload.go +++ b/controllers/apps/transformer_component_workload.go @@ -579,25 +579,26 @@ func (r *componentWorkloadOps) leaveMember4ScaleIn() error { if err != nil { return err } - tryToSwitchover := func(lorryCli lorry.Client, pod *corev1.Pod) error { + isLeader := func(pod *corev1.Pod) bool { if pod == nil || len(pod.Labels) == 0 { - return nil + return false + } + roleName, ok := pod.Labels[constant.RoleLabelKey] + if !ok { + return false } - // if pod is not leader/primary, no need to switchover - isLeader := func() bool { - roleName, ok := pod.Labels[constant.RoleLabelKey] - if !ok { - return false - } - for _, replicaRole := range r.runningITS.Spec.Roles { - if roleName == replicaRole.Name && replicaRole.IsLeader { - return true - } + for _, replicaRole := range r.runningITS.Spec.Roles { + if roleName == replicaRole.Name && replicaRole.IsLeader { + return true } - return false } - if !isLeader() { + return false + } + + tryToSwitchover := func(lorryCli lorry.Client, pod *corev1.Pod) error { + // if pod is not leader/primary, no need to switchover + if !isLeader(pod) { return nil } // if HA functionality is not enabled, no need to switchover @@ -628,6 +629,11 @@ func (r *componentWorkloadOps) leaveMember4ScaleIn() error { podsToMemberLeave = append(podsToMemberLeave, pod) } for _, pod := range podsToMemberLeave { + if !(isLeader(pod) || // if the pod is leader, it needs to call switchover + (r.synthesizeComp.LifecycleActions != nil && r.synthesizeComp.LifecycleActions.MemberLeave != nil)) { // if the memberLeave action is defined, it needs to call it + continue + } + lorryCli, err1 := lorry.NewClient(*pod) if err1 != nil { if err == nil { From 390b4a7ec5d69d0061f39f82dfa6ccefd939bceb Mon Sep 17 00:00:00 2001 From: zjx20 Date: Mon, 29 Jul 2024 13:44:52 +0800 Subject: [PATCH 17/45] chore: add the region field to the minio StorageProvider (#7882) --- deploy/helm/templates/storageprovider/legacy.yaml | 10 +++++++++- deploy/helm/templates/storageprovider/minio.yaml | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/deploy/helm/templates/storageprovider/legacy.yaml b/deploy/helm/templates/storageprovider/legacy.yaml index 4dc7dc57e957..5699defc4972 100644 --- a/deploy/helm/templates/storageprovider/legacy.yaml +++ b/deploy/helm/templates/storageprovider/legacy.yaml @@ -258,8 +258,12 @@ spec: provisioner: ru.yandex.s3.csi parameters: mounter: geesefs + {{ `{{ $regionOption := "" }}` }} + {{ `{{ if .Parameters.region }}` }} + {{ `{{ $regionOption = (printf "--region %s" .Parameters.region) }}` }} + {{ `{{ end }}` }} # you can set mount options here, for example limit memory cache size (recommended) - options: {{ `{{ printf "--memory-limit %s --read-ahead-large %s --dir-mode 0777 --file-mode 0666 %s" .Parameters.geesefsMemoryLimit .Parameters.geesefsReadAheadLarge .Parameters.mountOptions }}` }} + options: {{ `{{ printf "--memory-limit %s --read-ahead-large %s --dir-mode 0777 --file-mode 0666 %s %s" .Parameters.geesefsMemoryLimit .Parameters.geesefsReadAheadLarge .Parameters.mountOptions $regionOption }}` }} bucket: {{ `{{ index .Parameters "bucket" }}` }} csi.storage.k8s.io/provisioner-secret-name: {{ `{{ .CSIDriverSecretRef.Name }}` }} csi.storage.k8s.io/provisioner-secret-namespace: {{ `{{ .CSIDriverSecretRef.Namespace }}` }} @@ -277,6 +281,7 @@ spec: env_auth = false access_key_id = {{ `{{ index .Parameters "accessKeyId" }}` }} secret_access_key = {{ `{{ index .Parameters "secretAccessKey" }}` }} + region = {{ `{{ index .Parameters "region" }}` }} endpoint = {{ `{{ index .Parameters "endpoint" }}` }} root = {{ `{{ index .Parameters "bucket" }}` }} no_check_certificate = {{ `{{ index .Parameters "insecure" }}` }} @@ -286,6 +291,9 @@ spec: openAPIV3Schema: type: "object" properties: + region: + type: string + description: "MinIO region (optional), e.g. us-west-1" bucket: type: string description: "MinIO bucket" diff --git a/deploy/helm/templates/storageprovider/minio.yaml b/deploy/helm/templates/storageprovider/minio.yaml index 95d899e441de..85d0d20f4770 100644 --- a/deploy/helm/templates/storageprovider/minio.yaml +++ b/deploy/helm/templates/storageprovider/minio.yaml @@ -15,8 +15,12 @@ spec: provisioner: ru.yandex.s3.csi parameters: mounter: geesefs + {{ `{{ $regionOption := "" }}` }} + {{ `{{ if .Parameters.region }}` }} + {{ `{{ $regionOption = (printf "--region %s" .Parameters.region) }}` }} + {{ `{{ end }}` }} # you can set mount options here, for example limit memory cache size (recommended) - options: {{ `{{ printf "--memory-limit %s --read-ahead-large %s --dir-mode 0777 --file-mode 0666 %s" .Parameters.geesefsMemoryLimit .Parameters.geesefsReadAheadLarge .Parameters.mountOptions }}` }} + options: {{ `{{ printf "--memory-limit %s --read-ahead-large %s --dir-mode 0777 --file-mode 0666 %s %s" .Parameters.geesefsMemoryLimit .Parameters.geesefsReadAheadLarge .Parameters.mountOptions $regionOption }}` }} bucket: {{ `{{ index .Parameters "bucket" }}` }} csi.storage.k8s.io/provisioner-secret-name: {{ `{{ .CSIDriverSecretRef.Name }}` }} csi.storage.k8s.io/provisioner-secret-namespace: {{ `{{ .CSIDriverSecretRef.Namespace }}` }} @@ -34,6 +38,7 @@ spec: env_auth = false access_key_id = {{ `{{ index .Parameters "accessKeyId" }}` }} secret_access_key = {{ `{{ index .Parameters "secretAccessKey" }}` }} + region = {{ `{{ index .Parameters "region" }}` }} endpoint = {{ `{{ index .Parameters "endpoint" }}` }} root = {{ `{{ index .Parameters "bucket" }}` }} no_check_certificate = {{ `{{ index .Parameters "insecure" }}` }} @@ -43,6 +48,9 @@ spec: openAPIV3Schema: type: "object" properties: + region: + type: string + description: "MinIO region (optional), e.g. us-west-1" bucket: type: string description: "MinIO bucket" From 1a068557c16cedbecde462fd27996ee97c3a2ed2 Mon Sep 17 00:00:00 2001 From: wangyelei Date: Mon, 29 Jul 2024 15:25:47 +0800 Subject: [PATCH 18/45] fix: cluster always is deleting (#7886) --- controllers/apps/component_controller_test.go | 18 +++++++++--------- controllers/apps/suite_test.go | 3 ++- .../apps/transformer_cluster_deletion.go | 1 + 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/controllers/apps/component_controller_test.go b/controllers/apps/component_controller_test.go index fa40ac39e771..dba8ba3f7f99 100644 --- a/controllers/apps/component_controller_test.go +++ b/controllers/apps/component_controller_test.go @@ -106,7 +106,7 @@ var mockLorryClient4HScale = func(clusterKey types.NamespacedName, compName stri constant.AppInstanceLabelKey: clusterKey.Name, constant.KBAppComponentLabelKey: compName, } - if err := testCtx.Cli.List(ctx, &podList, labels, client.InNamespace(clusterKey.Namespace)); err != nil { + if err := k8sClient.List(ctx, &podList, labels, client.InNamespace(clusterKey.Namespace)); err != nil { return err } for _, pod := range podList.Items { @@ -117,7 +117,7 @@ var mockLorryClient4HScale = func(clusterKey types.NamespacedName, compName stri continue } pod.Annotations[podAnnotationKey4Test] = fmt.Sprintf("%d", replicas) - if err := testCtx.Cli.Update(ctx, &pod); err != nil { + if err := k8sClient.Update(ctx, &pod); err != nil { return err } } @@ -690,7 +690,7 @@ var _ = Describe("Component Controller", func() { if updatedReplicas == 0 { Consistently(func(g Gomega) { pvcList := corev1.PersistentVolumeClaimList{} - g.Expect(testCtx.Cli.List(testCtx.Ctx, &pvcList, client.MatchingLabels{ + g.Expect(k8sClient.List(testCtx.Ctx, &pvcList, client.MatchingLabels{ constant.AppInstanceLabelKey: clusterKey.Name, constant.KBAppComponentLabelKey: comp.Name, })).Should(Succeed()) @@ -710,7 +710,7 @@ var _ = Describe("Component Controller", func() { By("Checking pvcs deleting") Eventually(func(g Gomega) { pvcList := corev1.PersistentVolumeClaimList{} - g.Expect(testCtx.Cli.List(testCtx.Ctx, &pvcList, client.MatchingLabels{ + g.Expect(k8sClient.List(testCtx.Ctx, &pvcList, client.MatchingLabels{ constant.AppInstanceLabelKey: clusterKey.Name, constant.KBAppComponentLabelKey: comp.Name, })).Should(Succeed()) @@ -726,7 +726,7 @@ var _ = Describe("Component Controller", func() { By("Checking pod's annotation should be updated consistently") Eventually(func(g Gomega) { podList := corev1.PodList{} - g.Expect(testCtx.Cli.List(testCtx.Ctx, &podList, client.MatchingLabels{ + g.Expect(k8sClient.List(testCtx.Ctx, &podList, client.MatchingLabels{ constant.AppInstanceLabelKey: clusterKey.Name, constant.KBAppComponentLabelKey: comp.Name, })).Should(Succeed()) @@ -794,7 +794,7 @@ var _ = Describe("Component Controller", func() { defer lorry.UnsetMockClient() cluster := &appsv1alpha1.Cluster{} - Expect(testCtx.Cli.Get(testCtx.Ctx, clusterKey, cluster)).Should(Succeed()) + Expect(k8sClient.Get(testCtx.Ctx, clusterKey, cluster)).Should(Succeed()) initialGeneration := int(cluster.Status.ObservedGeneration) setHorizontalScalePolicy(policyType, componentDefsWithHScalePolicy...) @@ -1990,7 +1990,7 @@ var _ = Describe("Component Controller", func() { By("Mocking backup status to failed") backupList := dpv1alpha1.BackupList{} - Expect(testCtx.Cli.List(testCtx.Ctx, &backupList, ml)).Should(Succeed()) + Expect(k8sClient.List(testCtx.Ctx, &backupList, ml)).Should(Succeed()) backupKey := types.NamespacedName{ Namespace: backupList.Items[0].Namespace, Name: backupList.Items[0].Name, @@ -2610,12 +2610,12 @@ var _ = Describe("Component Controller", func() { func mockRestoreCompleted(ml client.MatchingLabels) { restoreList := dpv1alpha1.RestoreList{} - Expect(testCtx.Cli.List(testCtx.Ctx, &restoreList, ml)).Should(Succeed()) + Expect(k8sClient.List(testCtx.Ctx, &restoreList, ml)).Should(Succeed()) for _, rs := range restoreList.Items { err := testapps.GetAndChangeObjStatus(&testCtx, client.ObjectKeyFromObject(&rs), func(res *dpv1alpha1.Restore) { res.Status.Phase = dpv1alpha1.RestorePhaseCompleted })() - Expect(client.IgnoreNotFound(err)).ShouldNot(HaveOccurred()) + Expect(err).ShouldNot(HaveOccurred()) } } diff --git a/controllers/apps/suite_test.go b/controllers/apps/suite_test.go index aee255037306..125d17ea2829 100644 --- a/controllers/apps/suite_test.go +++ b/controllers/apps/suite_test.go @@ -156,12 +156,13 @@ var _ = BeforeSuite(func() { Expect(k8sClient).NotTo(BeNil()) // run reconcile + unCachedObjs := intctrlutil.GetUncachedObjects() k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{ Scheme: scheme.Scheme, Metrics: server.Options{BindAddress: "0"}, Client: client.Options{ Cache: &client.CacheOptions{ - DisableFor: intctrlutil.GetUncachedObjects(), + DisableFor: append(unCachedObjs, &dpv1alpha1.Restore{}), }, }, }) diff --git a/controllers/apps/transformer_cluster_deletion.go b/controllers/apps/transformer_cluster_deletion.go index 7a7ac29cc678..27e445af50a1 100644 --- a/controllers/apps/transformer_cluster_deletion.go +++ b/controllers/apps/transformer_cluster_deletion.go @@ -154,6 +154,7 @@ func kindsForHalt() ([]client.ObjectList, []client.ObjectList) { namespacedKinds, nonNamespacedKinds := kindsForDoNotTerminate() namespacedKindsPlus := []client.ObjectList{ &appsv1alpha1.ComponentList{}, + &appsv1alpha1.OpsRequestList{}, &appsv1.StatefulSetList{}, // be compatible with 0.6 workloads. &policyv1.PodDisruptionBudgetList{}, // be compatible with 0.6 workloads. &corev1.ServiceList{}, From 873ad87fd361682783d182d49591fe1a5b7c7d42 Mon Sep 17 00:00:00 2001 From: wangyelei Date: Tue, 30 Jul 2024 14:10:11 +0800 Subject: [PATCH 19/45] fix: redis cluster phase is always empty (#7897) --- controllers/apps/transformer_cluster_backup_policy.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/controllers/apps/transformer_cluster_backup_policy.go b/controllers/apps/transformer_cluster_backup_policy.go index e530dc04d4e7..ff741bbf6ab5 100644 --- a/controllers/apps/transformer_cluster_backup_policy.go +++ b/controllers/apps/transformer_cluster_backup_policy.go @@ -673,6 +673,11 @@ func (r *clusterBackupPolicyTransformer) getClusterComponentItems() []componentI } } for i, v := range r.clusterTransformContext.Cluster.Spec.ShardingSpecs { + shardComponents, _ := intctrlutil.ListShardingComponents(r.Context, r.Client, r.Cluster, v.Name) + if len(shardComponents) == 0 { + // waiting for sharding component to be created + continue + } if matchedCompDef(v.Template) { compSpecItems = append(compSpecItems, componentItem{ compSpec: &r.clusterTransformContext.Cluster.Spec.ShardingSpecs[i].Template, From 1c81daf73a22805a993854f621ddbcfcab0e2b46 Mon Sep 17 00:00:00 2001 From: Liang Deng <283304489@qq.com> Date: Tue, 30 Jul 2024 14:53:15 +0800 Subject: [PATCH 20/45] fix: avoid concurrency is 0 (#7898) Signed-off-by: Liang Deng <283304489@qq.com> --- pkg/controller/instanceset/utils.go | 3 ++- pkg/controller/instanceset/utils_test.go | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pkg/controller/instanceset/utils.go b/pkg/controller/instanceset/utils.go index 8545bd4445cf..0b8c175346dd 100644 --- a/pkg/controller/instanceset/utils.go +++ b/pkg/controller/instanceset/utils.go @@ -274,6 +274,7 @@ func CalculateConcurrencyReplicas(concurrency *intstr.IntOrString, replicas int) pValue = replicas - 1 } - pValue = integer.IntMax(integer.IntMin(pValue, replicas), 0) + // if the calculated concurrency is 0, it will ensure the concurrency at least 1. + pValue = integer.IntMax(integer.IntMin(pValue, replicas), 1) return pValue, nil } diff --git a/pkg/controller/instanceset/utils_test.go b/pkg/controller/instanceset/utils_test.go index 3f161500693a..9f35bbea7f8f 100644 --- a/pkg/controller/instanceset/utils_test.go +++ b/pkg/controller/instanceset/utils_test.go @@ -248,14 +248,14 @@ var _ = Describe("utils test", func() { replicas = 0 concurrencyReplicas, err = CalculateConcurrencyReplicas(concurrent, replicas) Expect(err).Should(BeNil()) - Expect(concurrencyReplicas).Should(Equal(0)) + Expect(concurrencyReplicas).Should(Equal(1)) By("concurrency = 0%, replicas = 10") concurrent = &intstr.IntOrString{Type: intstr.String, StrVal: "0%"} replicas = 10 concurrencyReplicas, err = CalculateConcurrencyReplicas(concurrent, replicas) Expect(err).Should(BeNil()) - Expect(concurrencyReplicas).Should(Equal(0)) + Expect(concurrencyReplicas).Should(Equal(1)) By("concurrency = 5, replicas = 10") concurrent = &intstr.IntOrString{Type: intstr.Int, IntVal: 5} @@ -269,14 +269,14 @@ var _ = Describe("utils test", func() { replicas = 0 concurrencyReplicas, err = CalculateConcurrencyReplicas(concurrent, replicas) Expect(err).Should(BeNil()) - Expect(concurrencyReplicas).Should(Equal(0)) + Expect(concurrencyReplicas).Should(Equal(1)) By("concurrency = 0, replicas = 10") concurrent = &intstr.IntOrString{Type: intstr.Int, IntVal: 0} replicas = 10 concurrencyReplicas, err = CalculateConcurrencyReplicas(concurrent, replicas) Expect(err).Should(BeNil()) - Expect(concurrencyReplicas).Should(Equal(0)) + Expect(concurrencyReplicas).Should(Equal(1)) By("concurrency = 10%, replicas = 1") concurrent = &intstr.IntOrString{Type: intstr.String, StrVal: "10%"} @@ -311,7 +311,7 @@ var _ = Describe("utils test", func() { concurrent = &intstr.IntOrString{Type: intstr.String, StrVal: "-50%"} concurrencyReplicas, err = CalculateConcurrencyReplicas(concurrent, replicas) Expect(err).Should(BeNil()) - Expect(concurrencyReplicas).Should(Equal(0)) + Expect(concurrencyReplicas).Should(Equal(1)) By("concurrency percentage > 100%") replicas = 10 From 8bbb46b7df420183859712ad226a707f0bdfba06 Mon Sep 17 00:00:00 2001 From: free6om Date: Tue, 30 Jul 2024 15:49:34 +0800 Subject: [PATCH 21/45] chore: add Retry and Commit control methods to kubebuilderx (#7839) --- .../nodecountscaler_controller.go | 4 +- .../reconciler_scale_target_cluster.go | 14 ++-- .../reconciler_scale_target_cluster_test.go | 11 +-- .../experimental/reconciler_update_status.go | 8 +- .../reconciler_update_status_test.go | 12 +-- .../workloads/instanceset_controller.go | 16 ++-- .../instanceset/in_place_update_util_test.go | 11 ++- .../reconciler_assistant_object.go | 26 +++---- .../reconciler_assistant_object_test.go | 5 +- .../instanceset/reconciler_deletion.go | 12 +-- .../instanceset/reconciler_deletion_test.go | 14 ++-- .../instanceset/reconciler_fix_meta.go | 10 +-- .../instanceset/reconciler_fix_meta_test.go | 11 +-- .../reconciler_instance_alignment.go | 28 +++---- .../reconciler_instance_alignment_test.go | 23 +++--- .../instanceset/reconciler_revision_update.go | 22 +++--- .../reconciler_revision_update_test.go | 7 +- .../instanceset/reconciler_status.go | 20 ++--- .../instanceset/reconciler_status_test.go | 31 +++++--- .../instanceset/reconciler_update.go | 33 ++++---- .../instanceset/reconciler_update_test.go | 48 +++++++----- pkg/controller/kubebuilderx/controller.go | 75 +++++++++++-------- .../kubebuilderx/controller_test.go | 68 +++++++++++++---- pkg/controller/kubebuilderx/reconciler.go | 33 +++++++- 24 files changed, 321 insertions(+), 221 deletions(-) diff --git a/controllers/experimental/nodecountscaler_controller.go b/controllers/experimental/nodecountscaler_controller.go index 00b8db6bd58f..03be4aa43d7a 100644 --- a/controllers/experimental/nodecountscaler_controller.go +++ b/controllers/experimental/nodecountscaler_controller.go @@ -60,13 +60,11 @@ type NodeCountScalerReconciler struct { func (r *NodeCountScalerReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { logger := log.FromContext(ctx).WithValues("NodeCountScaler", req.NamespacedName) - err := kubebuilderx.NewController(ctx, r.Client, req, r.Recorder, logger). + return kubebuilderx.NewController(ctx, r.Client, req, r.Recorder, logger). Prepare(objectTree()). Do(scaleTargetCluster()). Do(updateStatus()). Commit() - - return ctrl.Result{}, err } // SetupWithManager sets up the controller with the Manager. diff --git a/controllers/experimental/reconciler_scale_target_cluster.go b/controllers/experimental/reconciler_scale_target_cluster.go index 0b8063dfa5eb..33b4f38d9a69 100644 --- a/controllers/experimental/reconciler_scale_target_cluster.go +++ b/controllers/experimental/reconciler_scale_target_cluster.go @@ -37,17 +37,17 @@ type scaleTargetClusterReconciler struct{} func (r *scaleTargetClusterReconciler) PreCondition(tree *kubebuilderx.ObjectTree) *kubebuilderx.CheckResult { if tree.GetRoot() == nil || model.IsObjectDeleting(tree.GetRoot()) { - return kubebuilderx.ResultUnsatisfied + return kubebuilderx.ConditionUnsatisfied } - return kubebuilderx.ResultSatisfied + return kubebuilderx.ConditionSatisfied } -func (r *scaleTargetClusterReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*kubebuilderx.ObjectTree, error) { +func (r *scaleTargetClusterReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (kubebuilderx.Result, error) { scaler, _ := tree.GetRoot().(*experimental.NodeCountScaler) clusterKey := builder.NewClusterBuilder(scaler.Namespace, scaler.Spec.TargetClusterName).GetObject() object, err := tree.Get(clusterKey) if err != nil { - return nil, err + return kubebuilderx.Continue, err } cluster, _ := object.(*appsv1alpha1.Cluster) nodes := tree.List(&corev1.Node{}) @@ -67,15 +67,15 @@ func (r *scaleTargetClusterReconciler) Reconcile(tree *kubebuilderx.ObjectTree) } } if !scaled { - return tree, nil + return kubebuilderx.Continue, nil } scaler.Status.LastScaleTime = metav1.Time{Time: time.Now()} if err = tree.Update(cluster); err != nil { - return nil, err + return kubebuilderx.Continue, err } - return tree, nil + return kubebuilderx.Continue, nil } func scaleTargetCluster() kubebuilderx.Reconciler { diff --git a/controllers/experimental/reconciler_scale_target_cluster_test.go b/controllers/experimental/reconciler_scale_target_cluster_test.go index 0c7e471a08fa..ae6420ee084a 100644 --- a/controllers/experimental/reconciler_scale_target_cluster_test.go +++ b/controllers/experimental/reconciler_scale_target_cluster_test.go @@ -41,20 +41,21 @@ var _ = Describe("scale target cluster reconciler test", func() { It("should work well", func() { By("PreCondition") reconciler := scaleTargetCluster() - Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ResultSatisfied)) + Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ConditionSatisfied)) By("Reconcile") beforeReconcile := metav1.Now() - newTree, err := reconciler.Reconcile(tree) + res, err := reconciler.Reconcile(tree) Expect(err).Should(BeNil()) - newNCS, ok := newTree.GetRoot().(*experimentalv1alpha1.NodeCountScaler) + Expect(res).Should(Equal(kubebuilderx.Continue)) + newNCS, ok := tree.GetRoot().(*experimentalv1alpha1.NodeCountScaler) Expect(ok).Should(BeTrue()) Expect(newNCS.Status.LastScaleTime.Compare(beforeReconcile.Time)).Should(BeNumerically(">=", 0)) - object, err := newTree.Get(builder.NewClusterBuilder(newNCS.Namespace, newNCS.Spec.TargetClusterName).GetObject()) + object, err := tree.Get(builder.NewClusterBuilder(newNCS.Namespace, newNCS.Spec.TargetClusterName).GetObject()) Expect(err).Should(BeNil()) newCluster, ok := object.(*appsv1alpha1.Cluster) Expect(ok).Should(BeTrue()) - nodes := newTree.List(&corev1.Node{}) + nodes := tree.List(&corev1.Node{}) desiredReplicas := int32(len(nodes)) Expect(newCluster.Spec.ComponentSpecs).Should(HaveLen(2)) Expect(newCluster.Spec.ComponentSpecs[0].Replicas).Should(Equal(desiredReplicas)) diff --git a/controllers/experimental/reconciler_update_status.go b/controllers/experimental/reconciler_update_status.go index 6c5c4c51e68a..d164b7dc87b7 100644 --- a/controllers/experimental/reconciler_update_status.go +++ b/controllers/experimental/reconciler_update_status.go @@ -41,12 +41,12 @@ type updateStatusReconciler struct{} func (r *updateStatusReconciler) PreCondition(tree *kubebuilderx.ObjectTree) *kubebuilderx.CheckResult { if tree.GetRoot() == nil || model.IsObjectDeleting(tree.GetRoot()) { - return kubebuilderx.ResultUnsatisfied + return kubebuilderx.ConditionUnsatisfied } - return kubebuilderx.ResultSatisfied + return kubebuilderx.ConditionSatisfied } -func (r *updateStatusReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*kubebuilderx.ObjectTree, error) { +func (r *updateStatusReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (kubebuilderx.Result, error) { scaler, _ := tree.GetRoot().(*experimental.NodeCountScaler) itsList := tree.List(&workloads.InstanceSet{}) nodes := tree.List(&corev1.Node{}) @@ -81,7 +81,7 @@ func (r *updateStatusReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*kube condition := buildScaleReadyCondition(scaler) meta.SetStatusCondition(&scaler.Status.Conditions, *condition) - return tree, nil + return kubebuilderx.Continue, nil } func buildScaleReadyCondition(scaler *experimental.NodeCountScaler) *metav1.Condition { diff --git a/controllers/experimental/reconciler_update_status_test.go b/controllers/experimental/reconciler_update_status_test.go index 93154daf45e7..a8838c6bd24b 100644 --- a/controllers/experimental/reconciler_update_status_test.go +++ b/controllers/experimental/reconciler_update_status_test.go @@ -42,9 +42,10 @@ var _ = Describe("update status reconciler test", func() { By("scale target cluster") reconciler = scaleTargetCluster() - Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ResultSatisfied)) - newTree, err := reconciler.Reconcile(tree) + Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ConditionSatisfied)) + res, err := reconciler.Reconcile(tree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) By("mock the workload to scale ready") nodes := tree.List(&corev1.Node{}) @@ -60,10 +61,11 @@ var _ = Describe("update status reconciler test", func() { By("update status") reconciler = updateStatus() - Expect(reconciler.PreCondition(newTree)).Should(Equal(kubebuilderx.ResultSatisfied)) - newTree, err = reconciler.Reconcile(tree) + Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ConditionSatisfied)) + res, err = reconciler.Reconcile(tree) Expect(err).Should(BeNil()) - newNCS, ok := newTree.GetRoot().(*experimentalv1alpha1.NodeCountScaler) + Expect(res).Should(Equal(kubebuilderx.Continue)) + newNCS, ok := tree.GetRoot().(*experimentalv1alpha1.NodeCountScaler) Expect(ok).Should(BeTrue()) Expect(newNCS.Status.ComponentStatuses).Should(HaveLen(2)) Expect(newNCS.Status.ComponentStatuses[0].CurrentReplicas).Should(Equal(desiredReplicas)) diff --git a/controllers/workloads/instanceset_controller.go b/controllers/workloads/instanceset_controller.go index 9fae154aa67d..e01e2e5176f5 100644 --- a/controllers/workloads/instanceset_controller.go +++ b/controllers/workloads/instanceset_controller.go @@ -24,7 +24,6 @@ import ( batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" @@ -80,7 +79,7 @@ type InstanceSetReconciler struct { func (r *InstanceSetReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { logger := log.FromContext(ctx).WithValues("InstanceSet", req.NamespacedName) - err := kubebuilderx.NewController(ctx, r.Client, req, r.Recorder, logger). + res, err := kubebuilderx.NewController(ctx, r.Client, req, r.Recorder, logger). Prepare(instanceset.NewTreeLoader()). Do(instanceset.NewFixMetaReconciler()). Do(instanceset.NewDeletionReconciler()). @@ -90,15 +89,10 @@ func (r *InstanceSetReconciler) Reconcile(ctx context.Context, req ctrl.Request) Do(instanceset.NewReplicasAlignmentReconciler()). Do(instanceset.NewUpdateReconciler()). Commit() - if re, ok := err.(intctrlutil.DelayedRequeueError); ok { - return intctrlutil.RequeueAfter(re.RequeueAfter(), logger, re.Reason()) - } - requeue := false - if apierrors.IsConflict(err) { - requeue = true - err = nil - } - return ctrl.Result{Requeue: requeue}, err + + // TODO(free6om): handle error based on ErrorCode (after defined) + + return res, err } // SetupWithManager sets up the controller with the Manager. diff --git a/pkg/controller/instanceset/in_place_update_util_test.go b/pkg/controller/instanceset/in_place_update_util_test.go index ff478a7167bd..b4fd74d08733 100644 --- a/pkg/controller/instanceset/in_place_update_util_test.go +++ b/pkg/controller/instanceset/in_place_update_util_test.go @@ -119,19 +119,22 @@ var _ = Describe("instance util test", func() { var reconciler kubebuilderx.Reconciler By("update revisions") reconciler = NewRevisionUpdateReconciler() - newTree, err := reconciler.Reconcile(tree) + res, err := reconciler.Reconcile(tree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) By("assistant object") reconciler = NewAssistantObjectReconciler() - newTree, err = reconciler.Reconcile(newTree) + res, err = reconciler.Reconcile(tree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) By("replicas alignment") reconciler = NewReplicasAlignmentReconciler() - newTree, err = reconciler.Reconcile(newTree) + res, err = reconciler.Reconcile(tree) Expect(err).Should(BeNil()) - objects := newTree.List(&corev1.Pod{}) + Expect(res).Should(Equal(kubebuilderx.Continue)) + objects := tree.List(&corev1.Pod{}) Expect(objects).Should(HaveLen(3)) pod1, ok := objects[0].(*corev1.Pod) Expect(ok).Should(BeTrue()) diff --git a/pkg/controller/instanceset/reconciler_assistant_object.go b/pkg/controller/instanceset/reconciler_assistant_object.go index 42bd3fb1249f..9a6ff87bc345 100644 --- a/pkg/controller/instanceset/reconciler_assistant_object.go +++ b/pkg/controller/instanceset/reconciler_assistant_object.go @@ -39,15 +39,15 @@ func NewAssistantObjectReconciler() kubebuilderx.Reconciler { func (a *assistantObjectReconciler) PreCondition(tree *kubebuilderx.ObjectTree) *kubebuilderx.CheckResult { if tree.GetRoot() == nil || model.IsObjectDeleting(tree.GetRoot()) { - return kubebuilderx.ResultUnsatisfied + return kubebuilderx.ConditionUnsatisfied } if model.IsReconciliationPaused(tree.GetRoot()) { - return kubebuilderx.ResultUnsatisfied + return kubebuilderx.ConditionUnsatisfied } - return kubebuilderx.ResultSatisfied + return kubebuilderx.ConditionSatisfied } -func (a *assistantObjectReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*kubebuilderx.ObjectTree, error) { +func (a *assistantObjectReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (kubebuilderx.Result, error) { its, _ := tree.GetRoot().(*workloads.InstanceSet) // generate objects by current spec @@ -59,7 +59,7 @@ func (a *assistantObjectReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*k headLessSvc := buildHeadlessSvc(*its, labels, headlessSelectors) envConfig, err := buildEnvConfigMap(*its, labels) if err != nil { - return nil, err + return kubebuilderx.Continue, err } var objects []client.Object if svc != nil { @@ -68,7 +68,7 @@ func (a *assistantObjectReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*k objects = append(objects, headLessSvc, envConfig) for _, object := range objects { if err := intctrlutil.SetOwnership(its, object, model.GetScheme(), finalizer); err != nil { - return nil, err + return kubebuilderx.Continue, err } } // compute create/update/delete set @@ -76,7 +76,7 @@ func (a *assistantObjectReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*k for _, object := range objects { name, err := model.GetGVKName(object) if err != nil { - return nil, err + return kubebuilderx.Continue, err } newSnapshot[*name] = object } @@ -85,13 +85,13 @@ func (a *assistantObjectReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*k cmList := tree.List(&corev1.ConfigMap{}) cmListFiltered, err := filterTemplate(cmList, its.Annotations) if err != nil { - return nil, err + return kubebuilderx.Continue, err } for _, objectList := range [][]client.Object{svcList, cmListFiltered} { for _, object := range objectList { name, err := model.GetGVKName(object) if err != nil { - return nil, err + return kubebuilderx.Continue, err } oldSnapshot[*name] = object } @@ -105,22 +105,22 @@ func (a *assistantObjectReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*k deleteSet := oldNameSet.Difference(newNameSet) for name := range createSet { if err := tree.Add(newSnapshot[name]); err != nil { - return nil, err + return kubebuilderx.Continue, err } } for name := range updateSet { oldObj := oldSnapshot[name] newObj := copyAndMerge(oldObj, newSnapshot[name]) if err := tree.Update(newObj); err != nil { - return nil, err + return kubebuilderx.Continue, err } } for name := range deleteSet { if err := tree.Delete(oldSnapshot[name]); err != nil { - return nil, err + return kubebuilderx.Continue, err } } - return tree, nil + return kubebuilderx.Continue, nil } func filterTemplate(cmList []client.Object, annotations map[string]string) ([]client.Object, error) { diff --git a/pkg/controller/instanceset/reconciler_assistant_object_test.go b/pkg/controller/instanceset/reconciler_assistant_object_test.go index c2bc574f89e3..825fec34f56c 100644 --- a/pkg/controller/instanceset/reconciler_assistant_object_test.go +++ b/pkg/controller/instanceset/reconciler_assistant_object_test.go @@ -49,11 +49,12 @@ var _ = Describe("assistant object reconciler test", func() { tree := kubebuilderx.NewObjectTree() tree.SetRoot(its) reconciler = NewAssistantObjectReconciler() - Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ResultSatisfied)) + Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ConditionSatisfied)) By("do reconcile") - _, err := reconciler.Reconcile(tree) + res, err := reconciler.Reconcile(tree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) // desired: svc: "bar-headless", cm: "bar" objects := tree.GetSecondaryObjects() Expect(objects).Should(HaveLen(2)) diff --git a/pkg/controller/instanceset/reconciler_deletion.go b/pkg/controller/instanceset/reconciler_deletion.go index fb075426ea39..e2362a8fc95c 100644 --- a/pkg/controller/instanceset/reconciler_deletion.go +++ b/pkg/controller/instanceset/reconciler_deletion.go @@ -32,27 +32,27 @@ type deletionReconciler struct{} func (r *deletionReconciler) PreCondition(tree *kubebuilderx.ObjectTree) *kubebuilderx.CheckResult { if tree.GetRoot() == nil || !model.IsObjectDeleting(tree.GetRoot()) { - return kubebuilderx.ResultUnsatisfied + return kubebuilderx.ConditionUnsatisfied } if model.IsReconciliationPaused(tree.GetRoot()) { - return kubebuilderx.ResultUnsatisfied + return kubebuilderx.ConditionUnsatisfied } - return kubebuilderx.ResultSatisfied + return kubebuilderx.ConditionSatisfied } -func (r *deletionReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*kubebuilderx.ObjectTree, error) { +func (r *deletionReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (kubebuilderx.Result, error) { // delete secondary objects first // retain all pvcs // TODO(free6om): respect PVCManagementPolicy allObjects := tree.GetSecondaryObjects() objects := filterByType[*corev1.PersistentVolumeClaim](allObjects) if len(objects) > 0 { - return tree, tree.Delete(objects...) + return kubebuilderx.Continue, tree.Delete(objects...) } // delete root object tree.DeleteRoot() - return tree, nil + return kubebuilderx.Continue, nil } func filterByType[T client.Object](snapshot model.ObjectSnapshot) []client.Object { diff --git a/pkg/controller/instanceset/reconciler_deletion_test.go b/pkg/controller/instanceset/reconciler_deletion_test.go index 4928640b353d..a8ee7f2bc1f4 100644 --- a/pkg/controller/instanceset/reconciler_deletion_test.go +++ b/pkg/controller/instanceset/reconciler_deletion_test.go @@ -39,20 +39,22 @@ var _ = Describe("deletion reconciler test", func() { tree := kubebuilderx.NewObjectTree() tree.SetRoot(its) reconciler := NewDeletionReconciler() - Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ResultUnsatisfied)) + Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ConditionUnsatisfied)) t := metav1.NewTime(time.Now()) its.SetDeletionTimestamp(&t) - Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ResultSatisfied)) + Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ConditionSatisfied)) By("Reconcile") pod := builder.NewPodBuilder(namespace, name+"0").GetObject() Expect(tree.Add(pod)).Should(Succeed()) - newTree, err := reconciler.Reconcile(tree) + res, err := reconciler.Reconcile(tree) Expect(err).Should(BeNil()) - Expect(newTree.GetRoot()).Should(Equal(its)) - newTree, err = reconciler.Reconcile(newTree) + Expect(res).Should(Equal(kubebuilderx.Continue)) + Expect(tree.GetRoot()).Should(Equal(its)) + res, err = reconciler.Reconcile(tree) Expect(err).Should(BeNil()) - Expect(newTree.GetRoot()).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) + Expect(tree.GetRoot()).Should(BeNil()) }) }) }) diff --git a/pkg/controller/instanceset/reconciler_fix_meta.go b/pkg/controller/instanceset/reconciler_fix_meta.go index 604f7ef53bcf..db057b23f032 100644 --- a/pkg/controller/instanceset/reconciler_fix_meta.go +++ b/pkg/controller/instanceset/reconciler_fix_meta.go @@ -30,22 +30,22 @@ type fixMetaReconciler struct{} func (r *fixMetaReconciler) PreCondition(tree *kubebuilderx.ObjectTree) *kubebuilderx.CheckResult { if tree.GetRoot() == nil || model.IsObjectDeleting(tree.GetRoot()) { - return kubebuilderx.ResultUnsatisfied + return kubebuilderx.ConditionUnsatisfied } if controllerutil.ContainsFinalizer(tree.GetRoot(), finalizer) { - return kubebuilderx.ResultUnsatisfied + return kubebuilderx.ConditionUnsatisfied } - return kubebuilderx.ResultSatisfied + return kubebuilderx.ConditionSatisfied } -func (r *fixMetaReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*kubebuilderx.ObjectTree, error) { +func (r *fixMetaReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (kubebuilderx.Result, error) { // The object is not being deleted, so if it does not have our finalizer, // then lets add the finalizer and update the object. This is equivalent // registering our finalizer. controllerutil.AddFinalizer(tree.GetRoot(), finalizer) - return tree, nil + return kubebuilderx.Commit, nil } func NewFixMetaReconciler() kubebuilderx.Reconciler { diff --git a/pkg/controller/instanceset/reconciler_fix_meta_test.go b/pkg/controller/instanceset/reconciler_fix_meta_test.go index 91a08f442fb2..6801c3abfef3 100644 --- a/pkg/controller/instanceset/reconciler_fix_meta_test.go +++ b/pkg/controller/instanceset/reconciler_fix_meta_test.go @@ -35,16 +35,17 @@ var _ = Describe("fix meta reconciler test", func() { tree := kubebuilderx.NewObjectTree() tree.SetRoot(its) reconciler := NewFixMetaReconciler() - Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ResultSatisfied)) + Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ConditionSatisfied)) By("Reconcile without finalizer") - newTree, err := reconciler.Reconcile(tree) + res, err := reconciler.Reconcile(tree) Expect(err).Should(BeNil()) - Expect(newTree.GetRoot().GetFinalizers()).Should(HaveLen(1)) - Expect(newTree.GetRoot().GetFinalizers()[0]).Should(Equal(finalizer)) + Expect(tree.GetRoot().GetFinalizers()).Should(HaveLen(1)) + Expect(tree.GetRoot().GetFinalizers()[0]).Should(Equal(finalizer)) + Expect(res).Should(Equal(kubebuilderx.Commit)) By("Reconcile with finalizer") - Expect(reconciler.PreCondition(newTree)).Should(Equal(kubebuilderx.ResultUnsatisfied)) + Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ConditionUnsatisfied)) }) }) }) diff --git a/pkg/controller/instanceset/reconciler_instance_alignment.go b/pkg/controller/instanceset/reconciler_instance_alignment.go index 7b277aa7aa4b..642ba794d086 100644 --- a/pkg/controller/instanceset/reconciler_instance_alignment.go +++ b/pkg/controller/instanceset/reconciler_instance_alignment.go @@ -42,29 +42,29 @@ func NewReplicasAlignmentReconciler() kubebuilderx.Reconciler { func (r *instanceAlignmentReconciler) PreCondition(tree *kubebuilderx.ObjectTree) *kubebuilderx.CheckResult { if tree.GetRoot() == nil || model.IsObjectDeleting(tree.GetRoot()) { - return kubebuilderx.ResultUnsatisfied + return kubebuilderx.ConditionUnsatisfied } if model.IsReconciliationPaused(tree.GetRoot()) { - return kubebuilderx.ResultUnsatisfied + return kubebuilderx.ConditionUnsatisfied } its, _ := tree.GetRoot().(*workloads.InstanceSet) if err := validateSpec(its, tree); err != nil { return kubebuilderx.CheckResultWithError(err) } - return kubebuilderx.ResultSatisfied + return kubebuilderx.ConditionSatisfied } -func (r *instanceAlignmentReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*kubebuilderx.ObjectTree, error) { +func (r *instanceAlignmentReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (kubebuilderx.Result, error) { its, _ := tree.GetRoot().(*workloads.InstanceSet) itsExt, err := buildInstanceSetExt(its, tree) if err != nil { - return nil, err + return kubebuilderx.Continue, err } // 1. build desired name to template map nameToTemplateMap, err := buildInstanceName2TemplateMap(itsExt) if err != nil { - return nil, err + return kubebuilderx.Continue, err } // 2. find the create and delete set @@ -89,7 +89,7 @@ func (r *instanceAlignmentReconciler) Reconcile(tree *kubebuilderx.ObjectTree) ( if its.Spec.PodManagementPolicy == appsv1.ParallelPodManagement { concurrency, err = CalculateConcurrencyReplicas(its.Spec.ParallelPodManagementConcurrency, int(*its.Spec.Replicas)) if err != nil { - return nil, err + return kubebuilderx.Continue, err } isOrderedReady = false } @@ -131,10 +131,10 @@ func (r *instanceAlignmentReconciler) Reconcile(tree *kubebuilderx.ObjectTree) ( } inst, err := buildInstanceByTemplate(name, nameToTemplateMap[name], its, "") if err != nil { - return nil, err + return kubebuilderx.Continue, err } if err := tree.Add(inst.pod); err != nil { - return nil, err + return kubebuilderx.Continue, err } currentAlignedNameList = append(currentAlignedNameList, name) @@ -150,16 +150,16 @@ func (r *instanceAlignmentReconciler) Reconcile(tree *kubebuilderx.ObjectTree) ( for _, pvc := range pvcs { switch oldPvc, err := tree.Get(pvc); { case err != nil: - return nil, err + return kubebuilderx.Continue, err case oldPvc == nil: if err = tree.Add(pvc); err != nil { - return nil, err + return kubebuilderx.Continue, err } default: pvcObj := copyAndMerge(oldPvc, pvc) if pvcObj != nil { if err = tree.Update(pvcObj); err != nil { - return nil, err + return kubebuilderx.Continue, err } } } @@ -184,7 +184,7 @@ func (r *instanceAlignmentReconciler) Reconcile(tree *kubebuilderx.ObjectTree) ( pod.Name) } if err := tree.Delete(pod); err != nil { - return nil, err + return kubebuilderx.Continue, err } // TODO(free6om): handle pvc management policy // Retain by default. @@ -195,7 +195,7 @@ func (r *instanceAlignmentReconciler) Reconcile(tree *kubebuilderx.ObjectTree) ( concurrency-- } - return tree, nil + return kubebuilderx.Continue, nil } var _ kubebuilderx.Reconciler = &instanceAlignmentReconciler{} diff --git a/pkg/controller/instanceset/reconciler_instance_alignment_test.go b/pkg/controller/instanceset/reconciler_instance_alignment_test.go index c15f15bef0d2..855516032915 100644 --- a/pkg/controller/instanceset/reconciler_instance_alignment_test.go +++ b/pkg/controller/instanceset/reconciler_instance_alignment_test.go @@ -54,7 +54,7 @@ var _ = Describe("replicas alignment reconciler test", func() { tree := kubebuilderx.NewObjectTree() tree.SetRoot(its) reconciler = NewReplicasAlignmentReconciler() - Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ResultSatisfied)) + Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ConditionSatisfied)) By("prepare current tree") // desired: bar-0, bar-1, bar-2, bar-3, bar-foo-0, bar-foo-1, bar-hello-0 @@ -87,12 +87,13 @@ var _ = Describe("replicas alignment reconciler test", func() { By("do reconcile with OrderedReady(Serial) policy") orderedReadyTree, err := tree.DeepCopy() Expect(err).Should(BeNil()) - newTree, err := reconciler.Reconcile(orderedReadyTree) + res, err := reconciler.Reconcile(orderedReadyTree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) // desired: bar-0, bar-1, bar-foo-0 - pods := newTree.List(&corev1.Pod{}) + pods := orderedReadyTree.List(&corev1.Pod{}) Expect(pods).Should(HaveLen(3)) - pvcs := newTree.List(&corev1.PersistentVolumeClaim{}) + pvcs := orderedReadyTree.List(&corev1.PersistentVolumeClaim{}) Expect(pvcs).Should(HaveLen(3)) podBar0 := builder.NewPodBuilder(namespace, "bar-0").GetObject() for _, object := range []client.Object{podFoo0, podBar0, podBar1} { @@ -111,12 +112,13 @@ var _ = Describe("replicas alignment reconciler test", func() { parallelITS, ok := parallelTree.GetRoot().(*workloads.InstanceSet) Expect(ok).Should(BeTrue()) parallelITS.Spec.PodManagementPolicy = appsv1.ParallelPodManagement - newTree, err = reconciler.Reconcile(parallelTree) + res, err = reconciler.Reconcile(parallelTree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) // desired: bar-0, bar-1, bar-2, bar-3, bar-foo-0, bar-foo-1, bar-hello-0 - pods = newTree.List(&corev1.Pod{}) + pods = parallelTree.List(&corev1.Pod{}) Expect(pods).Should(HaveLen(7)) - pvcs = newTree.List(&corev1.PersistentVolumeClaim{}) + pvcs = parallelTree.List(&corev1.PersistentVolumeClaim{}) Expect(pvcs).Should(HaveLen(7)) podHello := builder.NewPodBuilder(namespace, its.Name+"-hello-0").GetObject() podFoo1 := builder.NewPodBuilder(namespace, its.Name+"-foo-1").GetObject() @@ -139,14 +141,15 @@ var _ = Describe("replicas alignment reconciler test", func() { Expect(ok).Should(BeTrue()) parallelITS.Spec.PodManagementPolicy = appsv1.ParallelPodManagement parallelITS.Spec.ParallelPodManagementConcurrency = &intstr.IntOrString{Type: intstr.String, StrVal: "50%"} - newTree, err = reconciler.Reconcile(parallelTree) + res, err = reconciler.Reconcile(parallelTree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) // replicas is 7, ParallelPodManagementConcurrency is 50%, so concurrency is 4. // since the original bar-1 and bar-foo-0 are not ready, only the new instances bar-0 and bar-2 will be added. // desired: bar-0, bar-1, bar-2, bar-foo-0 - pods = newTree.List(&corev1.Pod{}) + pods = parallelTree.List(&corev1.Pod{}) Expect(pods).Should(HaveLen(4)) - pvcs = newTree.List(&corev1.PersistentVolumeClaim{}) + pvcs = parallelTree.List(&corev1.PersistentVolumeClaim{}) Expect(pvcs).Should(HaveLen(4)) for _, object := range []client.Object{podFoo0, podBar0, podBar1, podBar2} { Expect(slices.IndexFunc(pods, func(item client.Object) bool { diff --git a/pkg/controller/instanceset/reconciler_revision_update.go b/pkg/controller/instanceset/reconciler_revision_update.go index a719c749fec1..2408a4dc6bbc 100644 --- a/pkg/controller/instanceset/reconciler_revision_update.go +++ b/pkg/controller/instanceset/reconciler_revision_update.go @@ -42,20 +42,20 @@ func NewRevisionUpdateReconciler() kubebuilderx.Reconciler { func (r *revisionUpdateReconciler) PreCondition(tree *kubebuilderx.ObjectTree) *kubebuilderx.CheckResult { if tree.GetRoot() == nil || !model.IsObjectUpdating(tree.GetRoot()) { - return kubebuilderx.ResultUnsatisfied + return kubebuilderx.ConditionUnsatisfied } its, _ := tree.GetRoot().(*workloads.InstanceSet) if err := validateSpec(its, tree); err != nil { return kubebuilderx.CheckResultWithError(err) } - return kubebuilderx.ResultSatisfied + return kubebuilderx.ConditionSatisfied } -func (r *revisionUpdateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*kubebuilderx.ObjectTree, error) { +func (r *revisionUpdateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (kubebuilderx.Result, error) { its, _ := tree.GetRoot().(*workloads.InstanceSet) itsExt, err := buildInstanceSetExt(its, tree) if err != nil { - return nil, err + return kubebuilderx.Continue, err } // 1. build all templates by applying instance template overrides to default pod template @@ -66,15 +66,15 @@ func (r *revisionUpdateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*ku for _, template := range instanceTemplateList { ordinalList, err := GetOrdinalListByTemplateName(itsExt.its, template.Name) if err != nil { - return nil, err + return kubebuilderx.Continue, err } instanceNames, err := GenerateInstanceNamesFromTemplate(its.Name, template.Name, template.Replicas, itsExt.its.Spec.OfflineInstances, ordinalList) if err != nil { - return nil, err + return kubebuilderx.Continue, err } revision, err := BuildInstanceTemplateRevision(&template.PodTemplateSpec, its) if err != nil { - return nil, err + return kubebuilderx.Continue, err } for _, name := range instanceNames { instanceRevisionList = append(instanceRevisionList, instanceRevision{name: name, revision: revision}) @@ -85,7 +85,7 @@ func (r *revisionUpdateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*ku return r.name } if err := ValidateDupInstanceNames(instanceRevisionList, getNameFunc); err != nil { - return nil, err + return kubebuilderx.Continue, err } updatedRevisions := make(map[string]string, len(instanceRevisionList)) @@ -96,7 +96,7 @@ func (r *revisionUpdateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*ku // 3. persistent these revisions to status revisions, err := buildRevisions(updatedRevisions) if err != nil { - return nil, err + return kubebuilderx.Continue, err } its.Status.UpdateRevisions = revisions updateRevision := "" @@ -106,7 +106,7 @@ func (r *revisionUpdateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*ku its.Status.UpdateRevision = updateRevision updatedReplicas, err := calculateUpdatedReplicas(its, tree.List(&corev1.Pod{})) if err != nil { - return nil, err + return kubebuilderx.Continue, err } its.Status.UpdatedReplicas = updatedReplicas // The 'ObservedGeneration' field is used to indicate whether the revisions have been updated. @@ -114,7 +114,7 @@ func (r *revisionUpdateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*ku // performing the computation only when the 'spec' is updated. its.Status.ObservedGeneration = its.Generation - return tree, nil + return kubebuilderx.Continue, nil } func calculateUpdatedReplicas(its *workloads.InstanceSet, pods []client.Object) (int32, error) { diff --git a/pkg/controller/instanceset/reconciler_revision_update_test.go b/pkg/controller/instanceset/reconciler_revision_update_test.go index 2a921339d6b4..197006419c7b 100644 --- a/pkg/controller/instanceset/reconciler_revision_update_test.go +++ b/pkg/controller/instanceset/reconciler_revision_update_test.go @@ -48,12 +48,13 @@ var _ = Describe("revision update reconciler test", func() { tree := kubebuilderx.NewObjectTree() tree.SetRoot(its) reconciler := NewRevisionUpdateReconciler() - Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ResultSatisfied)) + Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ConditionSatisfied)) By("Reconcile") - newTree, err := reconciler.Reconcile(tree) + res, err := reconciler.Reconcile(tree) Expect(err).Should(BeNil()) - newITS, ok := newTree.GetRoot().(*workloads.InstanceSet) + Expect(res).Should(Equal(kubebuilderx.Continue)) + newITS, ok := tree.GetRoot().(*workloads.InstanceSet) Expect(ok).Should(BeTrue()) Expect(newITS.Status.ObservedGeneration).Should(Equal(its.Generation)) updateRevisions, err := GetRevisions(newITS.Status.UpdateRevisions) diff --git a/pkg/controller/instanceset/reconciler_status.go b/pkg/controller/instanceset/reconciler_status.go index 4a73f267a952..205bb57c4106 100644 --- a/pkg/controller/instanceset/reconciler_status.go +++ b/pkg/controller/instanceset/reconciler_status.go @@ -48,12 +48,12 @@ func NewStatusReconciler() kubebuilderx.Reconciler { func (r *statusReconciler) PreCondition(tree *kubebuilderx.ObjectTree) *kubebuilderx.CheckResult { if tree.GetRoot() == nil || !model.IsObjectStatusUpdating(tree.GetRoot()) { - return kubebuilderx.ResultUnsatisfied + return kubebuilderx.ConditionUnsatisfied } - return kubebuilderx.ResultSatisfied + return kubebuilderx.ConditionSatisfied } -func (r *statusReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*kubebuilderx.ObjectTree, error) { +func (r *statusReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (kubebuilderx.Result, error) { its, _ := tree.GetRoot().(*workloads.InstanceSet) // 1. get all pods pods := tree.List(&corev1.Pod{}) @@ -65,7 +65,7 @@ func (r *statusReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*kubebuilde // 2. calculate status summary updateRevisions, err := GetRevisions(its.Status.UpdateRevisions) if err != nil { - return nil, err + return kubebuilderx.Continue, err } replicas := int32(0) currentReplicas, updatedReplicas := int32(0), int32(0) @@ -115,7 +115,7 @@ func (r *statusReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*kubebuilde if isCreated(pod) && !isTerminating(pod) { isPodUpdated, err := IsPodUpdated(its, pod) if err != nil { - return nil, err + return kubebuilderx.Continue, err } switch _, ok := updateRevisions[pod.Name]; { case !ok, !isPodUpdated: @@ -152,20 +152,20 @@ func (r *statusReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*kubebuilde readyCondition, err := buildReadyCondition(its, readyReplicas >= replicas, notReadyNames) if err != nil { - return nil, err + return kubebuilderx.Continue, err } meta.SetStatusCondition(&its.Status.Conditions, *readyCondition) availableCondition, err := buildAvailableCondition(its, availableReplicas >= replicas, notAvailableNames) if err != nil { - return nil, err + return kubebuilderx.Continue, err } meta.SetStatusCondition(&its.Status.Conditions, *availableCondition) // 3. set InstanceFailure condition failureCondition, err := buildFailureCondition(its, podList) if err != nil { - return nil, err + return kubebuilderx.Continue, err } if failureCondition != nil { meta.SetStatusCondition(&its.Status.Conditions, *failureCondition) @@ -181,9 +181,9 @@ func (r *statusReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*kubebuilde setReadyWithPrimary(its, podList) if its.Spec.MinReadySeconds > 0 && availableReplicas != readyReplicas { - return tree, intctrlutil.NewDelayedRequeueError(time.Second, "requeue for right status update") + return kubebuilderx.RetryAfter(time.Second), nil } - return tree, nil + return kubebuilderx.Continue, nil } func buildConditionMessageWithNames(podNames []string) ([]byte, error) { diff --git a/pkg/controller/instanceset/reconciler_status_test.go b/pkg/controller/instanceset/reconciler_status_test.go index 6c97b392901d..89f2a7e60923 100644 --- a/pkg/controller/instanceset/reconciler_status_test.go +++ b/pkg/controller/instanceset/reconciler_status_test.go @@ -33,7 +33,6 @@ import ( workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" "github.com/apecloud/kubeblocks/pkg/controller/builder" "github.com/apecloud/kubeblocks/pkg/controller/kubebuilderx" - intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" ) var _ = Describe("status reconciler test", func() { @@ -77,29 +76,34 @@ var _ = Describe("status reconciler test", func() { // prepare for update By("fix meta") reconciler = NewFixMetaReconciler() - newTree, err := reconciler.Reconcile(tree) + res, err := reconciler.Reconcile(tree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Commit)) By("update revisions") reconciler = NewRevisionUpdateReconciler() - newTree, err = reconciler.Reconcile(newTree) + res, err = reconciler.Reconcile(tree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) By("assistant object") reconciler = NewAssistantObjectReconciler() - newTree, err = reconciler.Reconcile(newTree) + res, err = reconciler.Reconcile(tree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) By("replicas alignment") reconciler = NewReplicasAlignmentReconciler() - newTree, err = reconciler.Reconcile(newTree) + res, err = reconciler.Reconcile(tree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) By("all pods are not ready") reconciler = NewStatusReconciler() - Expect(reconciler.PreCondition(newTree)).Should(Equal(kubebuilderx.ResultSatisfied)) - _, err = reconciler.Reconcile(newTree) + Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ConditionSatisfied)) + res, err = reconciler.Reconcile(tree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) Expect(its.Status.Replicas).Should(BeEquivalentTo(0)) Expect(its.Status.ReadyReplicas).Should(BeEquivalentTo(0)) Expect(its.Status.AvailableReplicas).Should(BeEquivalentTo(0)) @@ -127,7 +131,7 @@ var _ = Describe("status reconciler test", func() { } pod.Status.Conditions = []corev1.PodCondition{condition} } - pods := newTree.List(&corev1.Pod{}) + pods := tree.List(&corev1.Pod{}) currentRevisionMap := map[string]string{} oldRevision := "old-revision" for _, object := range pods { @@ -136,8 +140,9 @@ var _ = Describe("status reconciler test", func() { makePodAvailableWithRevision(pod, oldRevision, false) currentRevisionMap[pod.Name] = oldRevision } - _, err = reconciler.Reconcile(newTree) - Expect(intctrlutil.IsDelayedRequeueError(err)).Should(BeTrue()) + res, err = reconciler.Reconcile(tree) + Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.RetryAfter(time.Second))) Expect(its.Status.Replicas).Should(BeEquivalentTo(replicas)) Expect(its.Status.ReadyReplicas).Should(BeEquivalentTo(replicas)) Expect(its.Status.AvailableReplicas).Should(BeEquivalentTo(0)) @@ -170,8 +175,9 @@ var _ = Describe("status reconciler test", func() { Expect(ok).Should(BeTrue()) makePodAvailableWithRevision(pod, updateRevisions[pod.Name], true) } - _, err = reconciler.Reconcile(newTree) + res, err = reconciler.Reconcile(tree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) Expect(its.Status.Replicas).Should(BeEquivalentTo(replicas)) Expect(its.Status.ReadyReplicas).Should(BeEquivalentTo(replicas)) Expect(its.Status.AvailableReplicas).Should(BeEquivalentTo(replicas)) @@ -204,8 +210,9 @@ var _ = Describe("status reconciler test", func() { Expect(ok).Should(BeTrue()) pod.Status.Phase = corev1.PodFailed } - _, err = reconciler.Reconcile(newTree) + res, err = reconciler.Reconcile(tree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) Expect(its.Status.Replicas).Should(BeEquivalentTo(replicas)) Expect(its.Status.ReadyReplicas).Should(BeEquivalentTo(0)) Expect(its.Status.AvailableReplicas).Should(BeEquivalentTo(0)) diff --git a/pkg/controller/instanceset/reconciler_update.go b/pkg/controller/instanceset/reconciler_update.go index e6417df70167..38d5a38d405e 100644 --- a/pkg/controller/instanceset/reconciler_update.go +++ b/pkg/controller/instanceset/reconciler_update.go @@ -46,29 +46,29 @@ func NewUpdateReconciler() kubebuilderx.Reconciler { func (r *updateReconciler) PreCondition(tree *kubebuilderx.ObjectTree) *kubebuilderx.CheckResult { if tree.GetRoot() == nil || model.IsObjectDeleting(tree.GetRoot()) { - return kubebuilderx.ResultUnsatisfied + return kubebuilderx.ConditionUnsatisfied } if model.IsReconciliationPaused(tree.GetRoot()) { - return kubebuilderx.ResultUnsatisfied + return kubebuilderx.ConditionUnsatisfied } its, _ := tree.GetRoot().(*workloads.InstanceSet) if err := validateSpec(its, tree); err != nil { return kubebuilderx.CheckResultWithError(err) } - return kubebuilderx.ResultSatisfied + return kubebuilderx.ConditionSatisfied } -func (r *updateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*kubebuilderx.ObjectTree, error) { +func (r *updateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (kubebuilderx.Result, error) { its, _ := tree.GetRoot().(*workloads.InstanceSet) itsExt, err := buildInstanceSetExt(its, tree) if err != nil { - return nil, err + return kubebuilderx.Continue, err } // 1. build desired name to template map nameToTemplateMap, err := buildInstanceName2TemplateMap(itsExt) if err != nil { - return nil, err + return kubebuilderx.Continue, err } // 2. validate the update set @@ -88,19 +88,19 @@ func (r *updateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*kubebuilde updateNameSet := oldNameSet.Intersection(newNameSet) if len(updateNameSet) != len(oldNameSet) || len(updateNameSet) != len(newNameSet) { tree.Logger.Info(fmt.Sprintf("InstanceSet %s/%s instances are not aligned", its.Namespace, its.Name)) - return tree, nil + return kubebuilderx.Continue, nil } // 3. do update // do nothing if UpdateStrategyType is 'OnDelete' if its.Spec.UpdateStrategy.Type == apps.OnDeleteStatefulSetStrategyType { - return tree, nil + return kubebuilderx.Continue, nil } // handle 'RollingUpdate' partition, maxUnavailable, err := parsePartitionNMaxUnavailable(its.Spec.UpdateStrategy.RollingUpdate, len(oldPodList)) if err != nil { - return nil, err + return kubebuilderx.Continue, err } currentUnavailable := 0 for _, pod := range oldPodList { @@ -116,7 +116,7 @@ func (r *updateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*kubebuilde plan := NewUpdatePlan(*itsForPlan, oldPodList, IsPodUpdated) podsToBeUpdated, err := plan.Execute() if err != nil { - return nil, err + return kubebuilderx.Continue, err } updateCount := len(podsToBeUpdated) @@ -137,13 +137,10 @@ func (r *updateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*kubebuilde tree.Logger.Info(fmt.Sprintf("InstanceSet %s/%s blocks on scale-in as the pod %s is not healthy", its.Namespace, its.Name, pod.Name)) break } - if err != nil { - return nil, err - } updatePolicy, err := getPodUpdatePolicy(its, pod) if err != nil { - return nil, err + return kubebuilderx.Continue, err } if its.Spec.PodUpdatePolicy == workloads.StrictInPlacePodUpdatePolicyType && updatePolicy == RecreatePolicy { message := fmt.Sprintf("InstanceSet %s/%s blocks on scale-in as the PodUpdatePolicy is %s and the pod %s can not inplace update", @@ -158,17 +155,17 @@ func (r *updateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*kubebuilde if updatePolicy == InPlaceUpdatePolicy { newInstance, err := buildInstanceByTemplate(pod.Name, nameToTemplateMap[pod.Name], its, getPodRevision(pod)) if err != nil { - return nil, err + return kubebuilderx.Continue, err } newPod := copyAndMerge(pod, newInstance.pod) if err = tree.Update(newPod); err != nil { - return nil, err + return kubebuilderx.Continue, err } updatingPods++ } else if updatePolicy == RecreatePolicy { if !isTerminating(pod) { if err = tree.Delete(pod); err != nil { - return nil, err + return kubebuilderx.Continue, err } } updatingPods++ @@ -178,7 +175,7 @@ func (r *updateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (*kubebuilde if !isBlocked { meta.RemoveStatusCondition(&its.Status.Conditions, string(workloads.InstanceUpdateRestricted)) } - return tree, nil + return kubebuilderx.Continue, nil } func buildBlockedCondition(its *workloads.InstanceSet, message string) *metav1.Condition { diff --git a/pkg/controller/instanceset/reconciler_update_test.go b/pkg/controller/instanceset/reconciler_update_test.go index 7ed864bfe2c1..8ed437941b19 100644 --- a/pkg/controller/instanceset/reconciler_update_test.go +++ b/pkg/controller/instanceset/reconciler_update_test.go @@ -57,7 +57,7 @@ var _ = Describe("update reconciler test", func() { tree := kubebuilderx.NewObjectTree() tree.SetRoot(its) reconciler = NewUpdateReconciler() - Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ResultSatisfied)) + Expect(reconciler.PreCondition(tree)).Should(Equal(kubebuilderx.ConditionSatisfied)) By("prepare current tree") // desired: bar-hello-0, bar-foo-1, bar-foo-0, bar-3, bar-2, bar-1, bar-0 @@ -80,26 +80,30 @@ var _ = Describe("update reconciler test", func() { // prepare for update By("fix meta") reconciler = NewFixMetaReconciler() - newTree, err := reconciler.Reconcile(tree) + res, err := reconciler.Reconcile(tree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Commit)) By("update revisions") reconciler = NewRevisionUpdateReconciler() - newTree, err = reconciler.Reconcile(newTree) + res, err = reconciler.Reconcile(tree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) By("assistant object") reconciler = NewAssistantObjectReconciler() - newTree, err = reconciler.Reconcile(newTree) + res, err = reconciler.Reconcile(tree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) By("replicas alignment") reconciler = NewReplicasAlignmentReconciler() - newTree, err = reconciler.Reconcile(newTree) + res, err = reconciler.Reconcile(tree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) By("update all pods to ready with outdated revision") - pods := newTree.List(&corev1.Pod{}) + pods := tree.List(&corev1.Pod{}) condition := corev1.PodCondition{ Type: corev1.PodReady, Status: corev1.ConditionTrue, @@ -139,14 +143,15 @@ var _ = Describe("update reconciler test", func() { By("reconcile with default UpdateStrategy(RollingUpdate, no partition, MaxUnavailable=1)") // order: bar-hello-0, bar-foo-1, bar-foo-0, bar-3, bar-2, bar-1, bar-0 // expected: bar-hello-0 being deleted - defaultTree, err := newTree.DeepCopy() + defaultTree, err := tree.DeepCopy() Expect(err).Should(BeNil()) - _, err = reconciler.Reconcile(defaultTree) + res, err = reconciler.Reconcile(defaultTree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) expectUpdatedPods(defaultTree, []string{"bar-hello-0"}) By("reconcile with Partition=50% and MaxUnavailable=2") - partitionTree, err := newTree.DeepCopy() + partitionTree, err := tree.DeepCopy() Expect(err).Should(BeNil()) root, ok := partitionTree.GetRoot().(*workloads.InstanceSet) Expect(ok).Should(BeTrue()) @@ -160,12 +165,13 @@ var _ = Describe("update reconciler test", func() { } // order: bar-hello-0, bar-foo-1, bar-foo-0, bar-3, bar-2, bar-1, bar-0 // expected: bar-hello-0, bar-foo-1 being deleted - _, err = reconciler.Reconcile(partitionTree) + res, err = reconciler.Reconcile(partitionTree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) expectUpdatedPods(partitionTree, []string{"bar-hello-0", "bar-foo-1"}) By("update revisions to the updated value") - partitionTree, err = newTree.DeepCopy() + partitionTree, err = tree.DeepCopy() Expect(err).Should(BeNil()) root, ok = partitionTree.GetRoot().(*workloads.InstanceSet) Expect(ok).Should(BeTrue()) @@ -183,41 +189,44 @@ var _ = Describe("update reconciler test", func() { Expect(ok).Should(BeTrue()) makePodLatestRevision(pod) } - _, err = reconciler.Reconcile(partitionTree) + res, err = reconciler.Reconcile(partitionTree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) expectUpdatedPods(partitionTree, []string{"bar-foo-0"}) By("reconcile with UpdateStrategy='OnDelete'") - onDeleteTree, err := newTree.DeepCopy() + onDeleteTree, err := tree.DeepCopy() Expect(err).Should(BeNil()) root, ok = onDeleteTree.GetRoot().(*workloads.InstanceSet) Expect(ok).Should(BeTrue()) root.Spec.UpdateStrategy.Type = appsv1.OnDeleteStatefulSetStrategyType - _, err = reconciler.Reconcile(onDeleteTree) + res, err = reconciler.Reconcile(onDeleteTree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) expectUpdatedPods(onDeleteTree, []string{}) // order: bar-hello-0, bar-foo-1, bar-foo-0, bar-3, bar-2, bar-1, bar-0 // expected: bar-hello-0 being deleted By("reconcile with PodUpdatePolicy='PreferInPlace'") - preferInPlaceTree, err := newTree.DeepCopy() + preferInPlaceTree, err := tree.DeepCopy() Expect(err).Should(BeNil()) root, ok = preferInPlaceTree.GetRoot().(*workloads.InstanceSet) Expect(ok).Should(BeTrue()) root.Spec.PodUpdatePolicy = workloads.PreferInPlacePodUpdatePolicyType - // try to add env to instanceHello to trigger the recreate + // try to add env to instanceHello to trigger the recreation root.Spec.Instances[0].Env = []corev1.EnvVar{ { Name: "foo", Value: "bar", }, } - _, err = reconciler.Reconcile(preferInPlaceTree) + res, err = reconciler.Reconcile(preferInPlaceTree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) expectUpdatedPods(preferInPlaceTree, []string{"bar-hello-0"}) By("reconcile with PodUpdatePolicy='StrictInPlace'") - strictInPlaceTree, err := newTree.DeepCopy() + strictInPlaceTree, err := tree.DeepCopy() Expect(err).Should(BeNil()) root, ok = strictInPlaceTree.GetRoot().(*workloads.InstanceSet) Expect(ok).Should(BeTrue()) @@ -229,8 +238,9 @@ var _ = Describe("update reconciler test", func() { Value: "bar", }, } - _, err = reconciler.Reconcile(strictInPlaceTree) + res, err = reconciler.Reconcile(strictInPlaceTree) Expect(err).Should(BeNil()) + Expect(res).Should(Equal(kubebuilderx.Continue)) expectUpdatedPods(strictInPlaceTree, []string{}) }) }) diff --git a/pkg/controller/kubebuilderx/controller.go b/pkg/controller/kubebuilderx/controller.go index 83d18a62d32a..938292b6e8d1 100644 --- a/pkg/controller/kubebuilderx/controller.go +++ b/pkg/controller/kubebuilderx/controller.go @@ -30,18 +30,17 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" - intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" + "github.com/apecloud/kubeblocks/pkg/controller/graph" ) // TODO(free6om): this is a new reconciler framework in the very early stage leaving the following tasks to do: -// 1. don't expose the client.Client to the Reconciler, to prevent write operation in Prepare and Do stages. -// 2. expose EventRecorder -// 3. expose Logger +// 1. expose EventRecorder & Logger +// 2. parallel workflow-style reconciler chain type Controller interface { Prepare(TreeLoader) Controller Do(...Reconciler) Controller - Commit() error + Commit() (ctrl.Result, error) } type controller struct { @@ -51,6 +50,7 @@ type controller struct { recorder record.EventRecorder logger logr.Logger + res Result err error oldTree *ObjectTree @@ -78,46 +78,58 @@ func (c *controller) Do(reconcilers ...Reconciler) Controller { if c.err != nil { return c } + if c.res.Next != cntn && c.res.Next != cmmt && c.res.Next != rtry { + c.err = fmt.Errorf("unexpected next action: %s. should be one of Continue, Commit or Retry", c.res.Next) + return c + } + if c.res.Next != cntn { + return c + } + if len(reconcilers) == 0 { + return c + } - for _, reconciler := range reconcilers { - switch result := reconciler.PreCondition(c.tree); { - case result.Err != nil: - c.err = result.Err - return c - case !result.Satisfied: - return c - } - - c.tree, c.err = reconciler.Reconcile(c.tree) - if c.err != nil { - return c - } + reconciler := reconcilers[0] + switch result := reconciler.PreCondition(c.tree); { + case result.Err != nil: + c.err = result.Err + return c + case !result.Satisfied: + return c } + c.res, c.err = reconciler.Reconcile(c.tree) - return c + return c.Do(reconcilers[1:]...) } -func (c *controller) Commit() error { +func (c *controller) Commit() (ctrl.Result, error) { defer c.emitFailureEvent() - if c.err != nil && !intctrlutil.IsDelayedRequeueError(c.err) { - return c.err + if c.err != nil { + return ctrl.Result{}, c.err } if c.oldTree.GetRoot() == nil { - return nil + return ctrl.Result{}, nil } builder := NewPlanBuilder(c.ctx, c.cli, c.oldTree, c.tree, c.recorder, c.logger) - if err := builder.Init(); err != nil { - return err + if c.err = builder.Init(); c.err != nil { + return ctrl.Result{}, c.err + } + var plan graph.Plan + plan, c.err = builder.Build() + if c.err != nil { + return ctrl.Result{}, c.err } - plan, err := builder.Build() - if err != nil { - return err + if c.err = plan.Execute(); c.err != nil { + if apierrors.IsConflict(c.err) { + return ctrl.Result{Requeue: true}, nil + } + return ctrl.Result{}, c.err } - if err = plan.Execute(); err != nil { - return err + if c.res.Next == rtry { + return ctrl.Result{Requeue: true, RequeueAfter: c.res.RetryAfter}, nil } - return c.err + return ctrl.Result{}, nil } func (c *controller) emitFailureEvent() { @@ -148,6 +160,7 @@ func NewController(ctx context.Context, cli client.Client, req ctrl.Request, rec req: req, recorder: recorder, logger: logger, + res: Continue, } } diff --git a/pkg/controller/kubebuilderx/controller_test.go b/pkg/controller/kubebuilderx/controller_test.go index cc69b6b066ae..98be22c723d7 100644 --- a/pkg/controller/kubebuilderx/controller_test.go +++ b/pkg/controller/kubebuilderx/controller_test.go @@ -22,6 +22,7 @@ package kubebuilderx import ( "context" "fmt" + "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -30,6 +31,7 @@ import ( "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/client/fake" "sigs.k8s.io/controller-runtime/pkg/log" "github.com/apecloud/kubeblocks/pkg/controller/builder" @@ -44,37 +46,71 @@ var _ = Describe("controller test", func() { Context("Dummy Controller", func() { It("should work well", func() { ctx := context.Background() + cli := fake.NewFakeClient() req := ctrl.Request{} logger := log.FromContext(ctx).WithValues("InstanceSet", "test") - controller := NewController(context.Background(), nil, req, nil, logger) + var controller Controller tree := NewObjectTree() By("Load tree and reconcile it with no error") - err := controller.Prepare(&dummyLoader{tree: tree}).Do(&dummyReconciler{}).Commit() + controller = NewController(ctx, cli, req, nil, logger) + res, err := controller.Prepare(&dummyLoader{tree: tree}).Do(&dummyReconciler{res: Commit}).Commit() Expect(err).Should(BeNil()) + Expect(res.Requeue).Should(BeFalse()) By("Load tree with error") + controller = NewController(ctx, cli, req, nil, logger) loadErr := fmt.Errorf("load tree failed") - err = controller.Prepare(&dummyLoader{err: loadErr}).Do(&dummyReconciler{}).Commit() + res, err = controller.Prepare(&dummyLoader{err: loadErr}).Do(&dummyReconciler{res: Commit}).Commit() Expect(err).Should(Equal(loadErr)) + Expect(res.Requeue).Should(BeFalse()) By("Reconcile with pre-condition error") + controller = NewController(ctx, cli, req, nil, logger) reconcileCondErr := fmt.Errorf("reconcile pre-condition failed") - err = controller.Prepare(&dummyLoader{tree: tree}).Do(&dummyReconciler{preErr: reconcileCondErr}).Commit() + res, err = controller.Prepare(&dummyLoader{tree: tree}).Do(&dummyReconciler{preErr: reconcileCondErr, res: Commit}).Commit() Expect(err).Should(Equal(reconcileCondErr)) + Expect(res.Requeue).Should(BeFalse()) By("Reconcile with pre-condition unsatisfied") - Expect(tree.Add(builder.NewPodBuilder(namespace, name).GetObject())).Should(Succeed()) - newTree, err := tree.DeepCopy() - Expect(err).Should(BeNil()) - err = controller.Prepare(&dummyLoader{tree: newTree}).Do(&dummyReconciler{unsatisfied: true}).Commit() + controller = NewController(ctx, cli, req, nil, logger) + root := builder.NewPodBuilder(namespace, name).GetObject() + tree.SetRoot(root) + Expect(cli.Create(ctx, root)).Should(Succeed()) + newTree := NewObjectTree() + newTree.SetRoot(root) + res, err = controller.Prepare(&dummyLoader{tree: newTree}).Do(&dummyReconciler{unsatisfied: true, res: Commit}).Commit() Expect(err).Should(BeNil()) + Expect(res.Requeue).Should(BeFalse()) Expect(newTree).Should(Equal(tree)) By("Reconcile with error") + controller = NewController(ctx, cli, req, nil, logger) reconcileErr := fmt.Errorf("reconcile with error") - err = controller.Prepare(&dummyLoader{tree: tree}).Do(&dummyReconciler{err: reconcileErr}).Commit() + res, err = controller.Prepare(&dummyLoader{tree: tree}).Do(&dummyReconciler{err: reconcileErr, res: Commit}).Commit() Expect(err).Should(Equal(reconcileErr)) + Expect(res.Requeue).Should(BeFalse()) + + By("Reconcile with Commit method") + controller = NewController(ctx, cli, req, nil, logger) + newTree = NewObjectTree() + Expect(cli.Get(ctx, client.ObjectKeyFromObject(root), root)).Should(Succeed()) + newTree.SetRoot(root) + res, err = controller.Prepare(&dummyLoader{tree: newTree}).Do(&dummyReconciler{res: Commit}).Commit() + Expect(err).Should(BeNil()) + Expect(res.Requeue).Should(BeFalse()) + Expect(newTree).Should(Equal(tree)) + + By("Reconcile with Retry method") + controller = NewController(ctx, cli, req, nil, logger) + newTree = NewObjectTree() + Expect(cli.Get(ctx, client.ObjectKeyFromObject(root), root)).Should(Succeed()) + newTree.SetRoot(root) + res, err = controller.Prepare(&dummyLoader{tree: newTree}).Do(&dummyReconciler{res: RetryAfter(time.Second)}).Commit() + Expect(err).Should(BeNil()) + Expect(res.Requeue).Should(BeTrue()) + Expect(res.RequeueAfter).Should(Equal(time.Second)) + Expect(newTree).Should(Equal(tree)) }) }) }) @@ -93,6 +129,7 @@ var _ TreeLoader = &dummyLoader{} type dummyReconciler struct { preErr error unsatisfied bool + res Result err error } @@ -101,18 +138,21 @@ func (d *dummyReconciler) PreCondition(tree *ObjectTree) *CheckResult { return CheckResultWithError(d.preErr) } if d.unsatisfied { - return ResultUnsatisfied + return ConditionUnsatisfied } - return ResultSatisfied + return ConditionSatisfied } -func (d *dummyReconciler) Reconcile(tree *ObjectTree) (*ObjectTree, error) { +func (d *dummyReconciler) Reconcile(tree *ObjectTree) (Result, error) { + if d.err != nil || d.res.Next != cntn { + return d.res, d.err + } if tree != nil { if err := tree.Add(builder.NewConfigMapBuilder("hello", "world").GetObject()); err != nil { - return nil, err + return Result{}, err } } - return tree, d.err + return d.res, d.err } var _ Reconciler = &dummyReconciler{} diff --git a/pkg/controller/kubebuilderx/reconciler.go b/pkg/controller/kubebuilderx/reconciler.go index d6271baab130..1926d1f146d1 100644 --- a/pkg/controller/kubebuilderx/reconciler.go +++ b/pkg/controller/kubebuilderx/reconciler.go @@ -23,6 +23,7 @@ import ( "context" "errors" "reflect" + "time" "github.com/go-logr/logr" "k8s.io/client-go/tools/record" @@ -53,20 +54,46 @@ type CheckResult struct { Err error } -var ResultUnsatisfied = &CheckResult{} -var ResultSatisfied = &CheckResult{Satisfied: true} +var ConditionUnsatisfied = &CheckResult{} +var ConditionSatisfied = &CheckResult{Satisfied: true} + +type controlMethod string + +const ( + // cntn tells the control flow to continue + cntn controlMethod = "Continue" + + // cmmt tells the control flow to stop and jump to the commit phase + cmmt controlMethod = "Commit" + + // rtry tells the control flow to stop, jump to the commit phase + // and retry from the beginning with a delay specified by Result.RetryAfter + rtry controlMethod = "Retry" +) + +type Result struct { + Next controlMethod + RetryAfter time.Duration +} + +var Continue = Result{Next: cntn} +var Commit = Result{Next: cmmt} var ErrDeepCopyFailed = errors.New("DeepCopyFailed") type Reconciler interface { PreCondition(*ObjectTree) *CheckResult - Reconcile(tree *ObjectTree) (*ObjectTree, error) + Reconcile(tree *ObjectTree) (Result, error) } func CheckResultWithError(err error) *CheckResult { return &CheckResult{Satisfied: false, Err: err} } +func RetryAfter(after time.Duration) Result { + return Result{Next: rtry, RetryAfter: after} +} + func (t *ObjectTree) DeepCopy() (*ObjectTree, error) { out := new(ObjectTree) if t.root != nil { From 469c4702689c410698f90bf6217b3d21a073df3f Mon Sep 17 00:00:00 2001 From: loomt Date: Wed, 31 Jul 2024 14:31:27 +0800 Subject: [PATCH 22/45] fix: avoid override original static env (#7896) --- pkg/controller/component/synthesize_component.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pkg/controller/component/synthesize_component.go b/pkg/controller/component/synthesize_component.go index 87be7d6fb24a..943e31c4b1fc 100644 --- a/pkg/controller/component/synthesize_component.go +++ b/pkg/controller/component/synthesize_component.go @@ -814,12 +814,8 @@ func ReplaceNamedVars(namedValuesMap map[string]string, targetVar string, limits func ReplaceSecretEnvVars(namedValuesMap map[string]string, envs []corev1.EnvVar) []corev1.EnvVar { newEnvs := make([]corev1.EnvVar, 0, len(envs)) for _, e := range envs { - if e.ValueFrom == nil || e.ValueFrom.SecretKeyRef == nil { - continue - } - name := ReplaceNamedVars(namedValuesMap, e.ValueFrom.SecretKeyRef.Name, 1, false) - if name != e.ValueFrom.SecretKeyRef.Name { - e.ValueFrom.SecretKeyRef.Name = name + if e.ValueFrom != nil && e.ValueFrom.SecretKeyRef != nil { + e.ValueFrom.SecretKeyRef.Name = ReplaceNamedVars(namedValuesMap, e.ValueFrom.SecretKeyRef.Name, 1, false) } newEnvs = append(newEnvs, e) } From 5c4f34155070a2eba3ff2d11070c053a38895954 Mon Sep 17 00:00:00 2001 From: free6om Date: Thu, 1 Aug 2024 11:10:25 +0800 Subject: [PATCH 23/45] feat: support FeatureGateComponentReplicasAnnotation feature gate (#7902) --- cmd/manager/main.go | 1 + deploy/helm/templates/deployment.yaml | 2 ++ deploy/helm/values.yaml | 2 ++ pkg/constant/flag.go | 3 +++ pkg/controller/factory/builder.go | 7 +++++-- 5 files changed, 13 insertions(+), 2 deletions(-) diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 679cb9f0cd10..f86b1c618f8a 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -145,6 +145,7 @@ func init() { viper.SetDefault(intctrlutil.FeatureGateEnableRuntimeMetrics, false) viper.SetDefault(constant.CfgKBReconcileWorkers, 8) viper.SetDefault(constant.FeatureGateIgnoreConfigTemplateDefaultMode, false) + viper.SetDefault(constant.FeatureGateComponentReplicasAnnotation, true) } type flagName string diff --git a/deploy/helm/templates/deployment.yaml b/deploy/helm/templates/deployment.yaml index 0bc9273a0307..59d1f81d174f 100644 --- a/deploy/helm/templates/deployment.yaml +++ b/deploy/helm/templates/deployment.yaml @@ -179,6 +179,8 @@ spec: - name: IGNORE_POD_VERTICAL_SCALING value: "true" {{- end }} + - name: COMPONENT_REPLICAS_ANNOTATION + value: {{ .Values.featureGates.componentReplicasAnnotation.enabled | quote }} {{- with .Values.securityContext }} securityContext: {{- toYaml . | nindent 12 }} diff --git a/deploy/helm/values.yaml b/deploy/helm/values.yaml index ecaebb91e8c5..f915a9eb105a 100644 --- a/deploy/helm/values.yaml +++ b/deploy/helm/values.yaml @@ -1923,6 +1923,8 @@ featureGates: enabled: false ignorePodVerticalScaling: enabled: false + componentReplicasAnnotation: + enabled: true vmagent: diff --git a/pkg/constant/flag.go b/pkg/constant/flag.go index dbd09ef03259..10cc739bc0c7 100644 --- a/pkg/constant/flag.go +++ b/pkg/constant/flag.go @@ -37,4 +37,7 @@ const ( // FeatureReconciliationInCompactModeAnnotationKey indicates that the controller should run in compact mode, // means to try the best to cutoff useless objects. FeatureReconciliationInCompactModeAnnotationKey = "kubeblocks.io/compact-mode" + + // FeatureGateComponentReplicasAnnotation tells whether to add and update the annotation "component-replicas" to all pods of a Component + FeatureGateComponentReplicasAnnotation = "COMPONENT_REPLICAS_ANNOTATION" ) diff --git a/pkg/controller/factory/builder.go b/pkg/controller/factory/builder.go index 17e61897f47e..f6c749e42c9a 100644 --- a/pkg/controller/factory/builder.go +++ b/pkg/controller/factory/builder.go @@ -80,7 +80,6 @@ func BuildInstanceSet(synthesizedComp *component.SynthesizedComponent, component synthesizedComp.Annotations, ) - replicasStr := strconv.Itoa(int(synthesizedComp.Replicas)) podBuilder := builder.NewPodBuilder("", ""). AddLabelsInMap(synthesizedComp.Labels). AddLabelsInMap(labels). @@ -88,8 +87,12 @@ func BuildInstanceSet(synthesizedComp *component.SynthesizedComponent, component AddLabelsInMap(constant.GetAppVersionLabel(compDefName)). AddLabelsInMap(synthesizedComp.UserDefinedLabels). AddLabelsInMap(constant.GetClusterWellKnownLabels(clusterName)). - AddAnnotations(constant.ComponentReplicasAnnotationKey, replicasStr). AddAnnotationsInMap(synthesizedComp.UserDefinedAnnotations) + if viper.GetBool(constant.FeatureGateComponentReplicasAnnotation) { + replicasStr := strconv.Itoa(int(synthesizedComp.Replicas)) + podBuilder.AddAnnotations(constant.ComponentReplicasAnnotationKey, replicasStr) + + } template := corev1.PodTemplateSpec{ ObjectMeta: podBuilder.GetObject().ObjectMeta, Spec: *synthesizedComp.PodSpec.DeepCopy(), From a8a785ed39813764911f0da9a548c4bb1aabfe7b Mon Sep 17 00:00:00 2001 From: yuanyuan zhang <111744220+michelle-0808@users.noreply.github.com> Date: Thu, 1 Aug 2024 14:09:37 +0800 Subject: [PATCH 24/45] docs: update hscale docs (#7871) --- .../cluster-management/expand-volume.md | 2 +- .../restart-apecloud-mysql-cluster.md | 2 +- .../scale-for-apecloud-mysql.md | 40 +- .../manage-elasticsearch.md | 44 ++- .../cluster-management/scale.md | 30 +- .../kubeblocks-for-milvus/manage-milvus.md | 2 +- .../cluster-management/scale-for-mongodb.md | 38 +- .../scale-for-mysql-community.md | 32 +- .../scale-for-a-postgresql-cluster.md | 40 +- .../cluster-management/scale-for-pulsar.md | 40 +- .../kubeblocks-for-qdrant/manage-qdrant.md | 48 ++- .../scale-for-a-redis-cluster.md | 38 +- .../manage-starrocks.md | 35 +- .../manage-weaviate.md | 40 +- .../manage-xinference.md | 2 +- .../maintenance/scale/horizontal-scale.md | 356 ++++++++++++++++++ .../scale/scale-for-specified-instance.md | 72 ---- .../scale/vertical-and-horizontal-scale.md | 286 -------------- .../maintenance/scale/vertical-scale.md | 130 +++++++ docs/user_docs/cli/_category_.yml | 2 +- .../scale-for-apecloud-mysql.md | 14 +- .../manage-elasticsearch.md | 9 +- .../cluster-management/scale.md | 13 +- .../cluster-management/scale-for-mongodb.md | 14 +- .../cluster-management/scale-for-mysql.md | 8 +- .../scale-for-a-postgresql-cluster.md | 14 +- .../cluster-management/scale-for-pulsar.md | 9 +- .../kubeblocks-for-qdrant/manage-qdrant.md | 10 +- .../scale-for-a-redis-cluster.md | 16 +- .../manage-starrocks.md | 7 + .../manage-weaviate.md | 9 +- .../backup-and-restore/_category_.yaml | 2 +- .../backup-and-restore/backup/_category_.yaml | 0 .../backup-and-restore/backup/backup-repo.md | 0 .../backup/configure-backuppolicy.md | 0 .../backup/on-demand-backup.md | 0 .../backup/scheduled-backup.md | 0 .../backup-and-restore/introduction.md | 0 .../restore/_category_.yaml | 0 .../backup-and-restore/restore/pitr.md | 0 .../restore/restore-data-from-backup-set.md | 0 .../resource-scheduling/_category_.yml | 2 +- .../resource-scheduling.md | 0 43 files changed, 893 insertions(+), 513 deletions(-) create mode 100644 docs/api_docs/maintenance/scale/horizontal-scale.md delete mode 100644 docs/api_docs/maintenance/scale/scale-for-specified-instance.md delete mode 100644 docs/api_docs/maintenance/scale/vertical-and-horizontal-scale.md create mode 100644 docs/api_docs/maintenance/scale/vertical-scale.md rename docs/user_docs/{ => maintaince}/backup-and-restore/_category_.yaml (83%) rename docs/user_docs/{ => maintaince}/backup-and-restore/backup/_category_.yaml (100%) rename docs/user_docs/{ => maintaince}/backup-and-restore/backup/backup-repo.md (100%) rename docs/user_docs/{ => maintaince}/backup-and-restore/backup/configure-backuppolicy.md (100%) rename docs/user_docs/{ => maintaince}/backup-and-restore/backup/on-demand-backup.md (100%) rename docs/user_docs/{ => maintaince}/backup-and-restore/backup/scheduled-backup.md (100%) rename docs/user_docs/{ => maintaince}/backup-and-restore/introduction.md (100%) rename docs/user_docs/{ => maintaince}/backup-and-restore/restore/_category_.yaml (100%) rename docs/user_docs/{ => maintaince}/backup-and-restore/restore/pitr.md (100%) rename docs/user_docs/{ => maintaince}/backup-and-restore/restore/restore-data-from-backup-set.md (100%) rename docs/user_docs/{ => maintaince}/resource-scheduling/_category_.yml (83%) rename docs/user_docs/{ => maintaince}/resource-scheduling/resource-scheduling.md (100%) diff --git a/docs/api_docs/kubeblocks-for-apecloud-mysql/cluster-management/expand-volume.md b/docs/api_docs/kubeblocks-for-apecloud-mysql/cluster-management/expand-volume.md index 0d0990a865aa..0bca71cbfef5 100644 --- a/docs/api_docs/kubeblocks-for-apecloud-mysql/cluster-management/expand-volume.md +++ b/docs/api_docs/kubeblocks-for-apecloud-mysql/cluster-management/expand-volume.md @@ -67,7 +67,7 @@ There are two ways to apply volume expansion. demo ops-volume-expansion VolumeExpansion mycluster Succeed 3/3 6m ``` - If an error occurs to the horizontal scaling operation, you can troubleshoot with `kubectl describe ops -n demo` command to view the events of this operation. + If an error occurs, you can troubleshoot with `kubectl describe ops -n demo` command to view the events of this operation. 3. Check whether the corresponding cluster resources change. diff --git a/docs/api_docs/kubeblocks-for-apecloud-mysql/cluster-management/restart-apecloud-mysql-cluster.md b/docs/api_docs/kubeblocks-for-apecloud-mysql/cluster-management/restart-apecloud-mysql-cluster.md index 07cda9ab8916..f6f87c23e553 100644 --- a/docs/api_docs/kubeblocks-for-apecloud-mysql/cluster-management/restart-apecloud-mysql-cluster.md +++ b/docs/api_docs/kubeblocks-for-apecloud-mysql/cluster-management/restart-apecloud-mysql-cluster.md @@ -56,4 +56,4 @@ All pods restart in the order of learner -> follower -> leader and the leader ma - STATUS=Terminating: it means the cluster restart is in progress. - STATUS=Running: it means the cluster has been restarted. - If an error occurs to the horizontal scaling operation, you can troubleshoot with `kubectl describe` command to view the events of this operation. + If an error occurs, you can troubleshoot with `kubectl describe` command to view the events of this operation. diff --git a/docs/api_docs/kubeblocks-for-apecloud-mysql/cluster-management/scale-for-apecloud-mysql.md b/docs/api_docs/kubeblocks-for-apecloud-mysql/cluster-management/scale-for-apecloud-mysql.md index c78dd66c1bca..9f02cea2bf90 100644 --- a/docs/api_docs/kubeblocks-for-apecloud-mysql/cluster-management/scale-for-apecloud-mysql.md +++ b/docs/api_docs/kubeblocks-for-apecloud-mysql/cluster-management/scale-for-apecloud-mysql.md @@ -23,12 +23,6 @@ After vertical scaling or horizontal scaling is performed, KubeBlocks automatica You can vertically scale a cluster by changing resource requirements and limits (e.g. CPU and storage). For example, you can change the resource class from 1C2G to 2C4G by performing vertical scaling. -:::note - -During the vertical scaling process, all pods restart in the order of learner -> follower -> leader and the leader pod may change after the restarting. - -::: - ### Before you start Check whether the cluster status is `Running`. Otherwise, the following operations may fail. @@ -80,7 +74,7 @@ There are two ways to apply vertical scaling. demo ops-vertical-scaling VerticalScaling mycluster Succeed 3/3 6m ``` - If an error occurs to the vertical scaling operation, you can troubleshoot with `kubectl describe ops -n demo` command to view the events of this operation. + If an error occurs, you can troubleshoot with `kubectl describe ops -n demo` command to view the events of this operation. 3. Check whether the corresponding resources change. @@ -139,7 +133,9 @@ There are two ways to apply vertical scaling. ## Horizontal scaling -Horizontal scaling changes the amount of pods. For example, you can apply horizontal scaling to scale pods up from three to five. The scaling process includes the backup and restore of data. +Horizontal scaling changes the amount of pods. For example, you can scale out replicas from three to five. The scaling process includes the backup and restore of data. + +From v0.9.0, besides replicas, KubeBlocks also supports scaling in and out instances, refer to [Horizontal Scale](./../../maintenance/scale/horizontal-scale.md) for more details and examples. ### Before you start @@ -162,6 +158,29 @@ There are two ways to apply horizontal scaling. 1. Apply an OpsRequest to a specified cluster. Configure the parameters according to your needs. + The example below means adding two replicas. + + ```bash + kubectl apply -f - < 1. Apply an OpsRequest to a specified cluster. Configure the parameters according to your needs. + + The example below means adding two replicas. + + ```bash + kubectl apply -f - < + + + +```yaml +kubectl apply -f - < + + + +You can also edit the cluster YAML file to scale in a specified instance. + +```yaml +kubectl edit cluster redis +> +apiVersion: apps.kubeblocks.io/v1alpha1 +kind: Cluster +metadata: + name: redis +spec: + componentSpecs: + - name: proxy + replicas: 9 + offlineInstances: ["redis-proxy-proxy-2c4g-2"] +# ... +``` + + + + +## ScaleOut + +The following examples illustrate scaling out both replicas and instances. If you only need to scale out replicas, just edit `replicaChanges`. For example, + +```yaml +kubectl apply -f - < -NAME CLUSTER-DEFINITION VERSION TERMINATION-POLICY STATUS AGE -mycluster mysql mysql-8.0.33 Delete Running 4d18h -``` - -### Steps - -There are two ways to apply vertical scaling. - - - - - -1. Apply an OpsRequest to the specified cluster. Configure the parameters according to your needs. - - ```bash - kubectl apply -f - < - NAMESPACE NAME TYPE CLUSTER STATUS PROGRESS AGE - demo ops-vertical-scaling VerticalScaling mycluster Succeed 3/3 6m - ``` - - If an error occurs to the vertical scaling operation, you can troubleshoot with `kubectl describe ops -n demo` command to view the events of this operation. - -3. Check whether the corresponding resources change. - - ```bash - kubectl describe cluster mycluster -n demo - ``` - - - - - -1. Change the configuration of `spec.componentSpecs.resources` in the YAML file. `spec.componentSpecs.resources` controls the requirement and limit of resources and changing them triggers a vertical scaling. - - ```yaml - kubectl edit cluster mycluster -n demo - > - apiVersion: apps.kubeblocks.io/v1alpha1 - kind: Cluster - metadata: - name: mycluster - namespace: demo - spec: - clusterDefinitionRef: apecloud-mysql - clusterVersionRef: ac-mysql-8.0.30 - componentSpecs: - - name: mysql - componentDefRef: mysql - replicas: 3 - resources: # Change the values of resources. - requests: - memory: "2Gi" - cpu: "1" - limits: - memory: "4Gi" - cpu: "2" - volumeClaimTemplates: - - name: data - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 20Gi - terminationPolicy: Delete - ``` - -2. Check whether the corresponding resources change. - - ```bash - kubectl describe cluster mycluster -n demo - ``` - - - - - -## Horizontal scaling - -Horizontal scaling changes the amount of pods. For example, you can apply horizontal scaling to scale pods up from three to five. The scaling process includes the backup and restore of data. - -### Before you start - -Check whether the cluster STATUS is `Running`. Otherwise, the following operations may fail. - -```bash -kubectl get cluster mycluster -> -NAME CLUSTER-DEFINITION VERSION TERMINATION-POLICY STATUS AGE -mycluster mysql mysql-8.0.33 Delete Running 4d19h - -``` - -### Steps - -There are two ways to apply horizontal scaling. - - - - - -1. Apply an OpsRequest to a specified cluster. Configure the parameters according to your needs. - - ```bash - kubectl apply -f - < - NAMESPACE NAME TYPE CLUSTER STATUS PROGRESS AGE - demo ops-horizontal-scaling HorizontalScaling mycluster Succeed 3/3 6m - ``` - - If an error occurs to the horizontal scaling operation, you can troubleshoot with `kubectl describe ops -n demo` command to view the events of this operation. - -3. Check whether the corresponding resources change. - - ```bash - kubectl describe cluster mycluster -n demo - ``` - - - - - -1. Change the value of `spec.componentSpecs.replicas` in the YAML file. - - `spec.componentSpecs.replicas` stands for the pod amount and changing this value triggers a horizontal scaling of a cluster. - - ```yaml - kubectl edit cluster mycluster -n demo - > - apiVersion: apps.kubeblocks.io/v1alpha1 - kind: Cluster - metadata: - name: mycluster - namespace: demo - spec: - clusterDefinitionRef: apecloud-mysql - clusterVersionRef: ac-mysql-8.0.30 - componentSpecs: - - name: mysql - componentDefRef: mysql - replicas: 1 # Change the amount - volumeClaimTemplates: - - name: data - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 20Gi - terminationPolicy: Delete - ``` - -2. Check whether the corresponding resources change. - - ```bash - kubectl describe cluster mycluster -n demo - ``` - - - - - -### Handle the snapshot exception - -If `STATUS=ConditionsError` occurs during the horizontal scaling process, you can find the cause from `cluster.status.condition.message` for troubleshooting. -In the example below, a snapshot exception occurs. - -```bash -Status: - conditions: - - lastTransitionTime: "2023-02-08T04:20:26Z" - message: VolumeSnapshot/mycluster-mysql-scaling-dbqgp: Failed to set default snapshot - class with error cannot find default snapshot class - reason: ApplyResourcesFailed - status: "False" - type: ApplyResources -``` - -***Reason*** - -This exception occurs because the `VolumeSnapshotClass` is not configured. This exception can be fixed after configuring `VolumeSnapshotClass`, but the horizontal scaling cannot continue to run. It is because the wrong backup (volumesnapshot is generated by backup) and volumesnapshot generated before still exist. First, delete these two wrong resources and then KubeBlocks re-generates new resources. - -***Steps:*** - -1. Configure the VolumeSnapshotClass by running the command below. - - ```bash - kubectl create -f - < +NAME CLUSTER-DEFINITION VERSION TERMINATION-POLICY STATUS AGE +mycluster mysql mysql-8.0.33 Delete Running 4d18h +``` + +## Steps + +There are two ways to apply vertical scaling. + + + + + +1. Apply an OpsRequest to the specified cluster. Configure the parameters according to your needs. + + ```bash + kubectl apply -f - < + NAMESPACE NAME TYPE CLUSTER STATUS PROGRESS AGE + demo ops-vertical-scaling VerticalScaling mycluster Succeed 3/3 6m + ``` + + If an error occurs, you can troubleshoot with `kubectl describe ops -n demo` command to view the events of this operation. + +3. Check whether the corresponding resources change. + + ```bash + kubectl describe cluster mycluster -n demo + ``` + + + + + +1. Change the configuration of `spec.componentSpecs.resources` in the YAML file. `spec.componentSpecs.resources` controls the requirement and limit of resources and changing them triggers a vertical scaling. + + ```yaml + kubectl edit cluster mycluster -n demo + > + apiVersion: apps.kubeblocks.io/v1alpha1 + kind: Cluster + metadata: + name: mycluster + namespace: demo + spec: + clusterDefinitionRef: apecloud-mysql + clusterVersionRef: ac-mysql-8.0.30 + componentSpecs: + - name: mysql + componentDefRef: mysql + replicas: 3 + resources: # Change the values of resources. + requests: + memory: "2Gi" + cpu: "1" + limits: + memory: "4Gi" + cpu: "2" + volumeClaimTemplates: + - name: data + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 20Gi + terminationPolicy: Delete + ``` + +2. Check whether the corresponding resources change. + + ```bash + kubectl describe cluster mycluster -n demo + ``` + + + + diff --git a/docs/user_docs/cli/_category_.yml b/docs/user_docs/cli/_category_.yml index 1fe806df7174..dff53aca862d 100644 --- a/docs/user_docs/cli/_category_.yml +++ b/docs/user_docs/cli/_category_.yml @@ -1,4 +1,4 @@ -position: 19 +position: 30 label: Command Line collapsible: true collapsed: true diff --git a/docs/user_docs/kubeblocks-for-apecloud-mysql/cluster-management/scale-for-apecloud-mysql.md b/docs/user_docs/kubeblocks-for-apecloud-mysql/cluster-management/scale-for-apecloud-mysql.md index bff9df6aebd3..476aec1d4457 100644 --- a/docs/user_docs/kubeblocks-for-apecloud-mysql/cluster-management/scale-for-apecloud-mysql.md +++ b/docs/user_docs/kubeblocks-for-apecloud-mysql/cluster-management/scale-for-apecloud-mysql.md @@ -17,13 +17,7 @@ After vertical scaling or horizontal scaling is performed, KubeBlocks automatica ## Vertical scaling -You can vertically scale a cluster by changing resource requirements and limits (CPU and storage). For example, if you need to change the resource class from 1C2G to 2C4G, vertical scaling is what you need. - -:::note - -During the vertical scaling process, all pods restart in the order of learner -> follower -> leader and the leader pod may change after the restarting. - -::: +You can vertically scale a cluster by changing resource requirements and limits (CPU and storage). For example, you can change the resource class from 1C2G to 2C4G by performing vertical scaling. ### Before you start @@ -75,7 +69,9 @@ mysql-cluster default apecloud-mysql ac-mysql-8.0.30 ## Horizontal scaling -Horizontal scaling changes the amount of pods. For example, you can apply horizontal scaling to scale pods up from three to five. The scaling process includes the backup and restore of data. +Horizontal scaling changes the amount of pods. For example, you can scale out replicas from three to five. The scaling process includes the backup and restore of data. + +From v0.9.0, besides replicas, KubeBlocks also supports scaling in and out instances, refer to [Horizontal Scale](./../../../api_docs/maintenance/scale/horizontal-scale.md) in API docs for more details and examples. ### Before you start @@ -100,7 +96,7 @@ mysql-cluster default apecloud-mysql ac-mysql-8.0.30 ``` - `--components` describes the component name ready for horizontal scaling. - - `--replicas` describes the replica amount of the specified components. + - `--replicas` describes the replica amount of the specified components. Edit the amount based on your demands to scale in or out replicas. 2. Validate the horizontal scaling operation. diff --git a/docs/user_docs/kubeblocks-for-elasticsearch/manage-elasticsearch.md b/docs/user_docs/kubeblocks-for-elasticsearch/manage-elasticsearch.md index 44daec68edee..1ff8d06df6b8 100644 --- a/docs/user_docs/kubeblocks-for-elasticsearch/manage-elasticsearch.md +++ b/docs/user_docs/kubeblocks-for-elasticsearch/manage-elasticsearch.md @@ -22,7 +22,7 @@ KubeBlocks supports the management of Elasticsearch. ***Steps*** -1. Execute the following command to create a cluster. You can change the `cluster-definition` value as any other databases supported. +1. Execute the following command to create a cluster. You can change the `cluster-definition` value as any other database supported. ```bash kbcli cluster create elasticsearch elasticsearch @@ -171,12 +171,19 @@ The scaling function for vector databases is also supported. ### Scale horizontally +Horizontal scaling changes the amount of pods. For example, you can scale out replicas from three to five. + +From v0.9.0, besides replicas, KubeBlocks also supports scaling in and out instances, refer to [Horizontal Scale](./../../api_docs/maintenance/scale/horizontal-scale.md) in API docs for more details and examples. + Use the following command to perform horizontal scaling. ```bash kbcli cluster hscale elasticsearch --replicas=2 --components=elasticsearch ``` +- `--components` describes the component name ready for horizontal scaling. +- `--replicas` describes the replica amount of the specified components. Edit the amount based on your demands to scale in or out replicas. + Please wait a few seconds until the scaling process is over. The `kbcli cluster hscale` command prints a command to help check the progress of scaling operations. diff --git a/docs/user_docs/kubeblocks-for-kafka/cluster-management/scale.md b/docs/user_docs/kubeblocks-for-kafka/cluster-management/scale.md index 502422b04ea9..34f8d3de4568 100644 --- a/docs/user_docs/kubeblocks-for-kafka/cluster-management/scale.md +++ b/docs/user_docs/kubeblocks-for-kafka/cluster-management/scale.md @@ -12,7 +12,7 @@ You can scale a Kafka cluster in two ways, vertical scaling and horizontal scali ## Vertical scaling -You can vertically scale a cluster by changing resource requirements and limits (CPU and storage). For example, if you need to change the resource class from 1C2G to 2C4G, vertical scaling is what you need. +You can vertically scale a cluster by changing resource requirements and limits (CPU and storage). For example, you can change the resource class from 1C2G to 2C4G by performing vertical scaling. ### Before you start @@ -69,7 +69,9 @@ kafka-cluster default kafka kafka-3.3.2 Delete ## Horizontal scaling -Horizontal scaling changes the amount of pods. For example, you can apply horizontal scaling to scale pods up from three to five. The scaling process includes the backup and restoration of data. +Horizontal scaling changes the amount of pods. For example, you can scale out replicas from three to five. + +From v0.9.0, besides replicas, KubeBlocks also supports scaling in and out instances, refer to [Horizontal Scale](./../../../api_docs/maintenance/scale/horizontal-scale.md) in API docs for more details and examples. ### Before you start @@ -95,11 +97,8 @@ Horizontal scaling changes the amount of pods. For example, you can apply horizo --components="broker" --replicas=3 ``` - - `--components` value can be `broker` or `controller`. - - broker: all nodes in the combined mode, or all the broker node in the separated node. - - controller: all the corresponding nodes in the separated mode. - - `--memory` describes the requested and limited size of the component memory. - - `--cpu` describes the requested and limited size of the component CPU. + - `--components` describes the component name ready for horizontal scaling. + - `--replicas` describes the replica amount of the specified components. Edit the amount based on your demands to scale in or out replicas. 2. Validate the horizontal scaling operation. diff --git a/docs/user_docs/kubeblocks-for-mongodb/cluster-management/scale-for-mongodb.md b/docs/user_docs/kubeblocks-for-mongodb/cluster-management/scale-for-mongodb.md index c1dc286fe9a5..6d0ae56541c0 100644 --- a/docs/user_docs/kubeblocks-for-mongodb/cluster-management/scale-for-mongodb.md +++ b/docs/user_docs/kubeblocks-for-mongodb/cluster-management/scale-for-mongodb.md @@ -12,13 +12,7 @@ You can scale a MongoDB cluster in two ways, vertical scaling and horizontal sca ## Vertical scaling -You can vertically scale a cluster by changing resource requirements and limits (CPU and storage). For example, if you need to change the resource demand from 1C2G to 2C4G, vertical scaling is what you need. - -:::note - -During the vertical scaling process, a restart is triggered and the primary pod may change after the restarting. - -::: +You can vertically scale a cluster by changing resource requirements and limits (CPU and storage). For example, you can change the resource class from 1C2G to 2C4G by performing vertical scaling. ### Before you start @@ -70,7 +64,9 @@ Vertical scaling does not synchronize parameters related to CPU and memory and i ## Horizontal scaling -Horizontal scaling changes the amount of pods. For example, you can apply horizontal scaling to scale pods up from one to two. The scaling process includes the backup and restore of data. +Horizontal scaling changes the amount of pods. For example, you can scale out replicas from three to five. + +From v0.9.0, besides replicas, KubeBlocks also supports scaling in and out instances, refer to [Horizontal Scale](./../../../api_docs/maintenance/scale/horizontal-scale.md) in API docs for more details and examples. ### Before you start @@ -95,7 +91,7 @@ mongodb-cluster default mongodb mongodb-5.0 Dele ``` - `--components` describes the component name ready for horizontal scaling. - - `--replicas` describes the replica amount of the specified components. + - `--replicas` describes the replica amount of the specified components. Edit the amount based on your demands to scale in or out replicas. 2. Validate the horizontal scaling operation. diff --git a/docs/user_docs/kubeblocks-for-mysql-community-edition/cluster-management/scale-for-mysql.md b/docs/user_docs/kubeblocks-for-mysql-community-edition/cluster-management/scale-for-mysql.md index 5c62eb879755..420e01103154 100644 --- a/docs/user_docs/kubeblocks-for-mysql-community-edition/cluster-management/scale-for-mysql.md +++ b/docs/user_docs/kubeblocks-for-mysql-community-edition/cluster-management/scale-for-mysql.md @@ -18,7 +18,7 @@ After vertical scaling or horizontal scaling is performed, KubeBlocks automatica ## Vertical scaling -You can vertically scale a cluster by changing resource requirements and limits (CPU and storage). For example, if you need to change the resource class from 1C2G to 2C4G, vertical scaling is what you need. +You can vertically scale a cluster by changing resource requirements and limits (CPU and storage). For example, you can change the resource class from 1C2G to 2C4G by performing vertical scaling. ### Before you start @@ -70,7 +70,9 @@ mycluster default mysql mysql-8.0.33 Delete ## Horizontal scaling -Horizontal scaling changes the amount of pods. For example, you can apply horizontal scaling to scale pods up from three to five. The scaling process includes the backup and restore of data. +Horizontal scaling changes the amount of pods. For example, you can scale out replicas from three to five. + +From v0.9.0, besides replicas, KubeBlocks also supports scaling in and out instances, refer to [Horizontal Scale](./../../../api_docs/maintenance/scale/horizontal-scale.md) in API docs for more details and examples. ### Before you start @@ -95,7 +97,7 @@ mycluster default mysql mysql-8.0.33 Delete ``` - `--components` describes the component name ready for horizontal scaling. - - `--replicas` describes the replica amount of the specified components. + - `--replicas` describes the replica amount of the specified components. Edit the amount based on your demands to scale in or out replicas. 2. Validate the horizontal scaling operation. diff --git a/docs/user_docs/kubeblocks-for-postgresql/cluster-management/scale-for-a-postgresql-cluster.md b/docs/user_docs/kubeblocks-for-postgresql/cluster-management/scale-for-a-postgresql-cluster.md index 0924434e4384..c6039782daa1 100644 --- a/docs/user_docs/kubeblocks-for-postgresql/cluster-management/scale-for-a-postgresql-cluster.md +++ b/docs/user_docs/kubeblocks-for-postgresql/cluster-management/scale-for-a-postgresql-cluster.md @@ -18,13 +18,7 @@ After vertical scaling or horizontal scaling is performed, KubeBlocks automatica ## Vertical scaling -You can vertically scale a cluster by changing resource requirements and limits (CPU and storage). For example, if you need to change the resource demand from 1C2G to 2C4G, vertical scaling is what you need. - -:::note - -During the vertical scaling process, all pods restart and the pod role may change after the restarting. - -::: +You can vertically scale a cluster by changing resource requirements and limits (CPU and storage). For example, you can change the resource class from 1C2G to 2C4G by performing vertical scaling. ### Before you start @@ -77,7 +71,9 @@ pg-cluster default postgresql postgresql-14.8.0 Delete ## Horizontal scaling -Horizontal scaling changes the amount of pods. For example, you can apply horizontal scaling to scale pods up from three to five. The scaling process includes the backup and restore of data. +Horizontal scaling changes the amount of pods. For example, you can scale out replicas from three to five. + +From v0.9.0, besides replicas, KubeBlocks also supports scaling in and out instances, refer to [Horizontal Scale](./../../../api_docs/maintenance/scale/horizontal-scale.md) in API docs for more details and examples. ### Before you start @@ -102,7 +98,7 @@ pg-cluster default postgreql postgresql-14.8.0 ``` - `--components` describes the component name ready for horizontal scaling. - - `--replicas` describes the replica amount of the specified components. + - `--replicas` describes the replica amount of the specified components. Edit the amount based on your demands to scale in or out replicas. 2. Validate the horizontal scaling operation. diff --git a/docs/user_docs/kubeblocks-for-pulsar/cluster-management/scale-for-pulsar.md b/docs/user_docs/kubeblocks-for-pulsar/cluster-management/scale-for-pulsar.md index ff703f1fb24d..e2ed9726ad97 100644 --- a/docs/user_docs/kubeblocks-for-pulsar/cluster-management/scale-for-pulsar.md +++ b/docs/user_docs/kubeblocks-for-pulsar/cluster-management/scale-for-pulsar.md @@ -10,7 +10,7 @@ sidebar_label: Scale ## Vertical scaling -You can vertically scale a cluster by changing resource requirements and limits (CPU and storage). For example, if you need to change the resource class from 1C2G to 2C4G, vertical scaling is what you need. +You can vertically scale a cluster by changing resource requirements and limits (CPU and storage). For example, you can change the resource class from 1C2G to 2C4G by performing vertical scaling. ### Before you start @@ -57,7 +57,9 @@ kbcli cluster list pulsar-cluster ## Horizontal scaling -Horizontal scaling changes the amount of pods. For example, you can apply horizontal scaling to scale pods up from three to five. The scaling process includes the backup and restoration of data. +Horizontal scaling changes the amount of pods. For example, you can scale out replicas from three to five. + +From v0.9.0, besides replicas, KubeBlocks also supports scaling in and out instances, refer to [Horizontal Scale](./../../../api_docs/maintenance/scale/horizontal-scale.md) in API docs for more details and examples. ### Before you start @@ -75,9 +77,8 @@ Horizontal scaling changes the amount of pods. For example, you can apply horizo ``` - `--components` describes the component name ready for horizontal scaling. - - `--replicas` describes the replicas with the specified components. + - `--replicas` describes the replica amount of the specified components. Edit the amount based on your demands to scale in or out replicas. - 2. Validate the horizontal scaling operation. Check the cluster STATUS to identify the horizontal scaling status. diff --git a/docs/user_docs/kubeblocks-for-qdrant/manage-qdrant.md b/docs/user_docs/kubeblocks-for-qdrant/manage-qdrant.md index 8b0568b3fb1e..146411fbd573 100644 --- a/docs/user_docs/kubeblocks-for-qdrant/manage-qdrant.md +++ b/docs/user_docs/kubeblocks-for-qdrant/manage-qdrant.md @@ -165,12 +165,19 @@ The scaling function for vector databases is also supported. ### Scale horizontally +Horizontal scaling changes the amount of pods. For example, you can scale out replicas from three to five. + +From v0.9.0, besides replicas, KubeBlocks also supports scaling in and out instances, refer to [Horizontal Scale](./../../api_docs/maintenance/scale/horizontal-scale.md) in API docs for more details and examples. + Use the following command to perform horizontal scaling. ```bash kbcli cluster hscale qdrant --replicas=5 --components=qdrant ``` +- `--components` describes the component name ready for horizontal scaling. +- `--replicas` describes the replica amount of the specified components. Edit the amount based on your demands to scale in or out replicas. + Please wait a few seconds until the scaling process is over. The `kbcli cluster hscale` command print the `opsname`, to check the progress of horizontal scaling, you can use the following command with the `opsname`. @@ -197,7 +204,8 @@ kbcli cluster vscale qdrant --cpu=0.5 --memory=512Mi --components=qdrant ``` Please wait a few seconds until the scaling process is over. -The `kbcli cluster vscale` command print the `opsname`, to check the progress of scaling, you can use the following command with the `opsname`. + +The `kbcli cluster vscale` command prints a command to help check the progress of scaling. ```bash kubectl get ops qdrant-verticalscaling-rpw2l diff --git a/docs/user_docs/kubeblocks-for-redis/cluster-management/scale-for-a-redis-cluster.md b/docs/user_docs/kubeblocks-for-redis/cluster-management/scale-for-a-redis-cluster.md index a175f52a38eb..300c2782a35a 100644 --- a/docs/user_docs/kubeblocks-for-redis/cluster-management/scale-for-a-redis-cluster.md +++ b/docs/user_docs/kubeblocks-for-redis/cluster-management/scale-for-a-redis-cluster.md @@ -12,13 +12,7 @@ You can scale Redis DB instances in two ways, vertical scaling and horizontal sc ## Vertical scaling -You can vertically scale a cluster by changing resource requirements and limits (CPU and storage). For example, if you need to change the resource demand from 1C2G to 2C4G, vertical scaling is what you need. - -:::note - -During the vertical scaling process, all pods restart and the pod role may change after the restarting. - -::: +You can vertically scale a cluster by changing resource requirements and limits (CPU and storage). For example, you can change the resource class from 1C2G to 2C4G by performing vertical scaling. ### Before you start @@ -77,7 +71,9 @@ redis-cluster default redis redis-7.0.6 ## Horizontal scaling -Horizontal scaling changes the amount of pods. For example, you can apply horizontal scaling to scale up from three pods to five pods. The scaling process includes the backup and restoration of data. +Horizontal scaling changes the amount of pods. For example, you can scale out replicas from three to five. + +From v0.9.0, besides replicas, KubeBlocks also supports scaling in and out instances, refer to [Horizontal Scale](./../../../api_docs/maintenance/scale/horizontal-scale.md) in API docs for more details and examples. ### Before you start @@ -101,8 +97,8 @@ redis-cluster default redis redis-7.0.6 --components="redis" --replicas=2 ``` - - `--components` describes the component name ready for vertical scaling. - - `--replicas` describes the replica amount of a specified component. + - `--components` describes the component name ready for horizontal scaling. + - `--replicas` describes the replica amount of the specified components. Edit the amount based on your demands to scale in or out replicas. 2. Validate the horizontal scaling operation. diff --git a/docs/user_docs/kubeblocks-for-starrocks/manage-starrocks.md b/docs/user_docs/kubeblocks-for-starrocks/manage-starrocks.md index 05807b05781c..e2f3378a0d19 100644 --- a/docs/user_docs/kubeblocks-for-starrocks/manage-starrocks.md +++ b/docs/user_docs/kubeblocks-for-starrocks/manage-starrocks.md @@ -110,12 +110,19 @@ kbcli cluster describe mycluster ### Scale horizontally +Horizontal scaling changes the amount of pods. For example, you can scale out replicas from three to five. + +From v0.9.0, besides replicas, KubeBlocks also supports scaling in and out instances, refer to [Horizontal Scale](./../../api_docs/maintenance/scale/horizontal-scale.md) in API docs for more details and examples. + Use the following command to perform horizontal scaling. ```bash kbcli cluster hscale mycluster --replicas=3 --components=be ``` +- `--components` describes the component name ready for horizontal scaling. +- `--replicas` describes the replica amount of the specified components. Edit the amount based on your demands to scale in or out replicas. + Please wait a few seconds until the scaling process is over. The `kbcli cluster hscale` command prints a command to help check the progress of scaling operations. diff --git a/docs/user_docs/kubeblocks-for-weaviate/manage-weaviate.md b/docs/user_docs/kubeblocks-for-weaviate/manage-weaviate.md index a6fe53ae3d7d..afc5367a8528 100644 --- a/docs/user_docs/kubeblocks-for-weaviate/manage-weaviate.md +++ b/docs/user_docs/kubeblocks-for-weaviate/manage-weaviate.md @@ -149,16 +149,21 @@ For the production environment, it is highly recommended to build your monitorin ## Scale -The scaling function for vector databases is also supported. - ### Scale horizontally +Horizontal scaling changes the amount of pods. For example, you can scale out replicas from three to five. + +From v0.9.0, besides replicas, KubeBlocks also supports scaling in and out instances, refer to [Horizontal Scale](./../../api_docs/maintenance/scale/horizontal-scale.md) in API docs for more details and examples. + Use the following command to perform horizontal scaling. ```bash kbcli cluster hscale weaviate --replicas=3 --components=weaviate ``` +- `--components` describes the component name ready for horizontal scaling. +- `--replicas` describes the replica amount of the specified components. Edit the amount based on your demands to scale in or out replicas. + Please wait a few seconds until the scaling process is over. The `kbcli cluster hscale` command prints a command to help check the progress of scaling operations. diff --git a/docs/user_docs/backup-and-restore/_category_.yaml b/docs/user_docs/maintaince/backup-and-restore/_category_.yaml similarity index 83% rename from docs/user_docs/backup-and-restore/_category_.yaml rename to docs/user_docs/maintaince/backup-and-restore/_category_.yaml index 8eac9fde3359..f3d397189b8a 100644 --- a/docs/user_docs/backup-and-restore/_category_.yaml +++ b/docs/user_docs/maintaince/backup-and-restore/_category_.yaml @@ -1,4 +1,4 @@ -position: 5 +position: 2 label: Backup and Restore collapsible: true collapsed: true \ No newline at end of file diff --git a/docs/user_docs/backup-and-restore/backup/_category_.yaml b/docs/user_docs/maintaince/backup-and-restore/backup/_category_.yaml similarity index 100% rename from docs/user_docs/backup-and-restore/backup/_category_.yaml rename to docs/user_docs/maintaince/backup-and-restore/backup/_category_.yaml diff --git a/docs/user_docs/backup-and-restore/backup/backup-repo.md b/docs/user_docs/maintaince/backup-and-restore/backup/backup-repo.md similarity index 100% rename from docs/user_docs/backup-and-restore/backup/backup-repo.md rename to docs/user_docs/maintaince/backup-and-restore/backup/backup-repo.md diff --git a/docs/user_docs/backup-and-restore/backup/configure-backuppolicy.md b/docs/user_docs/maintaince/backup-and-restore/backup/configure-backuppolicy.md similarity index 100% rename from docs/user_docs/backup-and-restore/backup/configure-backuppolicy.md rename to docs/user_docs/maintaince/backup-and-restore/backup/configure-backuppolicy.md diff --git a/docs/user_docs/backup-and-restore/backup/on-demand-backup.md b/docs/user_docs/maintaince/backup-and-restore/backup/on-demand-backup.md similarity index 100% rename from docs/user_docs/backup-and-restore/backup/on-demand-backup.md rename to docs/user_docs/maintaince/backup-and-restore/backup/on-demand-backup.md diff --git a/docs/user_docs/backup-and-restore/backup/scheduled-backup.md b/docs/user_docs/maintaince/backup-and-restore/backup/scheduled-backup.md similarity index 100% rename from docs/user_docs/backup-and-restore/backup/scheduled-backup.md rename to docs/user_docs/maintaince/backup-and-restore/backup/scheduled-backup.md diff --git a/docs/user_docs/backup-and-restore/introduction.md b/docs/user_docs/maintaince/backup-and-restore/introduction.md similarity index 100% rename from docs/user_docs/backup-and-restore/introduction.md rename to docs/user_docs/maintaince/backup-and-restore/introduction.md diff --git a/docs/user_docs/backup-and-restore/restore/_category_.yaml b/docs/user_docs/maintaince/backup-and-restore/restore/_category_.yaml similarity index 100% rename from docs/user_docs/backup-and-restore/restore/_category_.yaml rename to docs/user_docs/maintaince/backup-and-restore/restore/_category_.yaml diff --git a/docs/user_docs/backup-and-restore/restore/pitr.md b/docs/user_docs/maintaince/backup-and-restore/restore/pitr.md similarity index 100% rename from docs/user_docs/backup-and-restore/restore/pitr.md rename to docs/user_docs/maintaince/backup-and-restore/restore/pitr.md diff --git a/docs/user_docs/backup-and-restore/restore/restore-data-from-backup-set.md b/docs/user_docs/maintaince/backup-and-restore/restore/restore-data-from-backup-set.md similarity index 100% rename from docs/user_docs/backup-and-restore/restore/restore-data-from-backup-set.md rename to docs/user_docs/maintaince/backup-and-restore/restore/restore-data-from-backup-set.md diff --git a/docs/user_docs/resource-scheduling/_category_.yml b/docs/user_docs/maintaince/resource-scheduling/_category_.yml similarity index 83% rename from docs/user_docs/resource-scheduling/_category_.yml rename to docs/user_docs/maintaince/resource-scheduling/_category_.yml index 5e56e18e2ef7..e71247aacaac 100644 --- a/docs/user_docs/resource-scheduling/_category_.yml +++ b/docs/user_docs/maintaince/resource-scheduling/_category_.yml @@ -1,4 +1,4 @@ -position: 8 +position: 3 label: Resource Scheduling collapsible: true collapsed: true \ No newline at end of file diff --git a/docs/user_docs/resource-scheduling/resource-scheduling.md b/docs/user_docs/maintaince/resource-scheduling/resource-scheduling.md similarity index 100% rename from docs/user_docs/resource-scheduling/resource-scheduling.md rename to docs/user_docs/maintaince/resource-scheduling/resource-scheduling.md From 8a0243634bd8930535f61f221545c63639ab0e76 Mon Sep 17 00:00:00 2001 From: yuanyuan zhang <111744220+michelle-0808@users.noreply.github.com> Date: Thu, 1 Aug 2024 15:03:51 +0800 Subject: [PATCH 25/45] docs: fix image errors (#7909) --- .../high-availability/high-availability.md | 20 +++++----- .../proxy/apecloud-mysql-proxy.md | 2 +- .../manage-elasticsearch.md | 8 ++-- .../configuration/configuration.md | 37 +++++++++---------- docs/user_docs/maintenance/_category_.yaml | 4 ++ .../backup-and-restore/_category_.yaml | 0 .../backup-and-restore/backup/_category_.yaml | 0 .../backup-and-restore/backup/backup-repo.md | 6 +-- .../backup/configure-backuppolicy.md | 0 .../backup/on-demand-backup.md | 0 .../backup/scheduled-backup.md | 0 .../backup-and-restore/introduction.md | 0 .../restore/_category_.yaml | 0 .../backup-and-restore/restore/pitr.md | 0 .../restore/restore-data-from-backup-set.md | 0 .../resource-scheduling/_category_.yml | 0 .../resource-scheduling.md | 0 17 files changed, 39 insertions(+), 38 deletions(-) create mode 100644 docs/user_docs/maintenance/_category_.yaml rename docs/user_docs/{maintaince => maintenance}/backup-and-restore/_category_.yaml (100%) rename docs/user_docs/{maintaince => maintenance}/backup-and-restore/backup/_category_.yaml (100%) rename docs/user_docs/{maintaince => maintenance}/backup-and-restore/backup/backup-repo.md (97%) rename docs/user_docs/{maintaince => maintenance}/backup-and-restore/backup/configure-backuppolicy.md (100%) rename docs/user_docs/{maintaince => maintenance}/backup-and-restore/backup/on-demand-backup.md (100%) rename docs/user_docs/{maintaince => maintenance}/backup-and-restore/backup/scheduled-backup.md (100%) rename docs/user_docs/{maintaince => maintenance}/backup-and-restore/introduction.md (100%) rename docs/user_docs/{maintaince => maintenance}/backup-and-restore/restore/_category_.yaml (100%) rename docs/user_docs/{maintaince => maintenance}/backup-and-restore/restore/pitr.md (100%) rename docs/user_docs/{maintaince => maintenance}/backup-and-restore/restore/restore-data-from-backup-set.md (100%) rename docs/user_docs/{maintaince => maintenance}/resource-scheduling/_category_.yml (100%) rename docs/user_docs/{maintaince => maintenance}/resource-scheduling/resource-scheduling.md (100%) diff --git a/docs/api_docs/kubeblocks-for-apecloud-mysql/high-availability/high-availability.md b/docs/api_docs/kubeblocks-for-apecloud-mysql/high-availability/high-availability.md index 1f0e7ba4bb62..bb2d6a20da74 100644 --- a/docs/api_docs/kubeblocks-for-apecloud-mysql/high-availability/high-availability.md +++ b/docs/api_docs/kubeblocks-for-apecloud-mysql/high-availability/high-availability.md @@ -37,23 +37,23 @@ The faults here are all simulated by deleting pods. When there are sufficient re ***Steps:*** -1. View the pod role of the ApeCloud MySQL RaftGroup Cluster. In this example, the leader pod's name is `mysql-cluster-1`. +1. View the pod role of the ApeCloud MySQL RaftGroup Cluster. In this example, the leader pod's name is `mycluster-mysql-1`. ```bash kubectl get pods --show-labels -n demo | grep role ``` ![describe_pod](./../../../img/api-ha-grep-role.png) -2. Delete the leader pod `mysql-cluster-mysql-1` to simulate a pod fault. +2. Delete the leader pod `mycluster-mysql-1` to simulate a pod fault. ```bash - kubectl delete pod mysql-cluster-mysql-1 -n demo + kubectl delete pod mycluster-mysql-1 -n demo ``` ![delete_pod](./../../../img/api-ha-delete-leader-pod.png) 3. Check the status of the pods and RaftGroup Cluster connection. - The following example shows that the roles of pods have changed after the old leader pod was deleted and `mysql-cluster-mysql-0` is elected as the new leader pod. + The following example shows that the roles of pods have changed after the old leader pod was deleted and `mycluster-mysql-0` is elected as the new leader pod. ```bash kubectl get pods --show-labels -n demo | grep role @@ -81,27 +81,27 @@ The faults here are all simulated by deleting pods. When there are sufficient re ***How the automatic recovery works*** - After the leader pod is deleted, the ApeCloud MySQL RaftGroup Cluster elects a new leader. In this example, `mysql-cluster-mysql-0` is elected as the new leader. KubeBlocks detects that the leader has changed, and sends a notification to update the access link. The original exception node automatically rebuilds and recovers to the normal RaftGroup Cluster state. It normally takes 30 seconds from exception to recovery. + After the leader pod is deleted, the ApeCloud MySQL RaftGroup Cluster elects a new leader. In this example, `mycluster-mysql-0` is elected as the new leader. KubeBlocks detects that the leader has changed, and sends a notification to update the access link. The original exception node automatically rebuilds and recovers to the normal RaftGroup Cluster state. It normally takes 30 seconds from exception to recovery. ### Single follower pod exception ***Steps:*** -1. View the pod role again and in this example, the follower pods are `mysql-cluster-mysql-1` and `mysql-cluster-mysql-2`. +1. View the pod role again and in this example, the follower pods are `mycluster-mysql-1` and `mycluster-mysql-2`. ```bash kubectl get pods --show-labels -n demo | grep role ``` ![describe_cluster](./../../../img/api-ha-grep-role-single-follower-pod.png) -2. Delete the follower pod `mysql-cluster-mysql-1`. +2. Delete the follower pod `mycluster-mysql-1`. ```bash kubectl delete pod mycluster-mysql-1 -n demo ``` ![delete_follower_pod](./../../../img/api-ha-single-follower-pod-delete.png) -3. Open another terminal page and view the pod status. You can find the follower pod `mysql-cluster-mysql-1` is `Terminating`. +3. Open another terminal page and view the pod status. You can find the follower pod `mycluster-mysql-1` is `Terminating`. ```bash kubectl get pod -n demo @@ -135,7 +135,7 @@ In this way, whether exceptions occur to one leader and one follower or two foll ***Steps:*** -1. View the pod role again. In this example, the follower pods are `mysql-cluster-mysql-1` and `mysql-cluster-mysql-2`. +1. View the pod role again. In this example, the follower pods are `mycluster-mysql-1` and `mycluster-mysql-2`. ```bash kubectl get pods --show-labels -n demo | grep role @@ -149,7 +149,7 @@ In this way, whether exceptions occur to one leader and one follower or two foll ``` ![delete_two_pods](./../../../img/api-ha-two-pod-get-status.png) -3. Open another terminal page and view the pod status. You can find the follower pods `mysql-cluster-mysql-1` and `mysql-cluster-mysql-2` is `Terminating`. +3. Open another terminal page and view the pod status. You can find the follower pods `mycluster-mysql-1` and `mycluster-mysql-2` is `Terminating`. ```bash kubectl get pod -n demo diff --git a/docs/api_docs/kubeblocks-for-apecloud-mysql/proxy/apecloud-mysql-proxy.md b/docs/api_docs/kubeblocks-for-apecloud-mysql/proxy/apecloud-mysql-proxy.md index 026e33bef4f4..829412d137c6 100644 --- a/docs/api_docs/kubeblocks-for-apecloud-mysql/proxy/apecloud-mysql-proxy.md +++ b/docs/api_docs/kubeblocks-for-apecloud-mysql/proxy/apecloud-mysql-proxy.md @@ -330,7 +330,7 @@ kubectl exec -it myproxy-cluster-vtgate-8659d5db95-4dzt5 -- bash ls /vtdataroot ``` -Enter the container and view more logs of VTTable. +Enter the container and view more logs of VTTablet. ```bash kubectl exec -it myproxy-cluster-mysql-0 -c vttablet -- bash diff --git a/docs/api_docs/kubeblocks-for-elasticsearch/manage-elasticsearch.md b/docs/api_docs/kubeblocks-for-elasticsearch/manage-elasticsearch.md index 36556586ec02..2de7a9d8f385 100644 --- a/docs/api_docs/kubeblocks-for-elasticsearch/manage-elasticsearch.md +++ b/docs/api_docs/kubeblocks-for-elasticsearch/manage-elasticsearch.md @@ -126,8 +126,6 @@ curl http://127.0.0.1:9200/_cat/nodes?v ## Scaling -Scaling function for vector databases is also supported. - ### Scale horizontally Horizontal scaling changes the amount of pods. For example, you can scale out replicas from three to five. @@ -197,7 +195,7 @@ There are two ways to apply horizontal scaling. EOF ``` -2. Check the operation status to validate the horizontal scaling status. +2. Check the operation status to validate the horizontal scaling. ```bash kubectl get ops -n demo @@ -473,7 +471,7 @@ There are two ways to apply volume expansion. - + 1. Change the value of `spec.componentSpecs.volumeClaimTemplates.spec.resources` in the cluster YAML file. @@ -598,7 +596,7 @@ EOF - + Change replicas back to the original amount to start this cluster again. diff --git a/docs/api_docs/kubeblocks-for-kafka/configuration/configuration.md b/docs/api_docs/kubeblocks-for-kafka/configuration/configuration.md index a0643aa26ecd..4c8bbf3f0770 100644 --- a/docs/api_docs/kubeblocks-for-kafka/configuration/configuration.md +++ b/docs/api_docs/kubeblocks-for-kafka/configuration/configuration.md @@ -7,7 +7,7 @@ sidebar_position: 1 # Configure cluster parameters -This guide shows how to configure cluster parameters by creating an opsRequest. +This guide shows how to configure cluster parameters. ## Before you start @@ -19,7 +19,9 @@ This guide shows how to configure cluster parameters by creating an opsRequest. 1. Get the configuration file of this cluster. ```bash - kubectl edit configurations.apps.kubeblocks.io mycluster-kafka -n demo + kubectl get configurations.apps.kubeblocks.io -n demo + + kubectl edit configurations.apps.kubeblocks.io mycluster-kafka-combine -n demo ``` 2. Configure parameters according to your needs. The example below adds the `spec.configFileParams` part to configure `log.cleanup.policy`. @@ -30,18 +32,16 @@ This guide shows how to configure cluster parameters by creating an opsRequest. componentName: kafka configItemDetails: - configFileParams: - mongodb.cnf: + server.properties: parameters: - log.flush.interval.ms: "2000" + log.cleanup.policy: "compact" configSpec: - constraintRef: kafka-config-constraints - name: kafka-configuration + constraintRef: kafka-cc + name: kafka-configuration-tpl namespace: kb-system - templateRef: kafka3.3.2-config-template + templateRef: kafka-configuration-tpl volumeName: kafka-config - name: kafka-config - - configSpec: - defaultMode: 292 + name: kafka-configuration-tpl ``` 3. Connect to this cluster to verify whether the configuration takes effect as expected. @@ -55,7 +55,7 @@ This guide shows how to configure cluster parameters by creating an opsRequest. ## Configure cluster parameters with OpsRequest -1. Define an OpsRequest file and configure the parameters in the OpsRequest in a yaml file named `mycluster-configuring-demo.yaml`. In this example, `max_connections` is configured as `600`. +1. Define an OpsRequest file and configure the parameters in the OpsRequest in a yaml file named `mycluster-configuring-demo.yaml`. In this example, `log.cleanup.policy` is configured as `compact`. ```bash apiVersion: apps.kubeblocks.io/v1alpha1 @@ -71,8 +71,8 @@ This guide shows how to configure cluster parameters by creating an opsRequest. - keys: - key: server.properties parameters: - - key: log.flush.interval.ms - value: "2000" + - key: log.cleanup.policy + value: "compact" name: kafka-configuration-tpl preConditionDeadlineSeconds: 0 type: Reconfiguring @@ -100,13 +100,12 @@ This guide shows how to configure cluster parameters by creating an opsRequest. kubectl apply -f mycluster-configuring-demo.yaml ``` -3. Connect to this cluster to verify whether the configuration takes effect as expected. +3. Verify whether the configuration takes effect as expected. ```bash - kbcli cluster describe-config mykafka --show-detail | grep log.cleanup.policy + kbcli cluster describe-config mycluster --show-detail | grep log.cleanup.policy > log.cleanup.policy = compact - mykafka-reconfiguring-wvqns mykafka broker kafka-configuration-tpl server.properties Succeed restart 1/1 May 10,2024 16:28 UTC+0800 {"server.properties":"{\"log.cleanup.policy\":\"compact\"}"} ``` :::note @@ -136,7 +135,7 @@ You can also view the details of this configuration file and parameters. * View the user guide of a specified parameter. ```bash - kbcli cluster explain-config mykafka --param=log.cleanup.policy + kbcli cluster explain-config mycluster --param=log.cleanup.policy ``` `--config-specs` is required to specify a configuration template since ApeCloud MySQL currently supports multiple templates. You can run `kbcli cluster describe-config mycluster` to view the all template names. @@ -147,7 +146,7 @@ You can also view the details of this configuration file and parameters. ```bash template meta: - ConfigSpec: kafka-configuration-tpl ComponentName: broker ClusterName: mykafka + ConfigSpec: kafka-configuration-tpl ComponentName: kafka-combine ClusterName: mycluster Configure Constraint: Parameter Name: log.cleanup.policy @@ -155,7 +154,7 @@ You can also view the details of this configuration file and parameters. Scope: Global Dynamic: false Type: string - Description: The default cleanup policy for segments beyond the retention window. A comma separated list of valid policies. + Description: The default cleanup policy for segments beyond the retention window. A comma separated list of valid policies. ``` diff --git a/docs/user_docs/maintenance/_category_.yaml b/docs/user_docs/maintenance/_category_.yaml new file mode 100644 index 000000000000..38b1b1115079 --- /dev/null +++ b/docs/user_docs/maintenance/_category_.yaml @@ -0,0 +1,4 @@ +position: 5 +label: maintenance +collapsible: true +collapsed: true \ No newline at end of file diff --git a/docs/user_docs/maintaince/backup-and-restore/_category_.yaml b/docs/user_docs/maintenance/backup-and-restore/_category_.yaml similarity index 100% rename from docs/user_docs/maintaince/backup-and-restore/_category_.yaml rename to docs/user_docs/maintenance/backup-and-restore/_category_.yaml diff --git a/docs/user_docs/maintaince/backup-and-restore/backup/_category_.yaml b/docs/user_docs/maintenance/backup-and-restore/backup/_category_.yaml similarity index 100% rename from docs/user_docs/maintaince/backup-and-restore/backup/_category_.yaml rename to docs/user_docs/maintenance/backup-and-restore/backup/_category_.yaml diff --git a/docs/user_docs/maintaince/backup-and-restore/backup/backup-repo.md b/docs/user_docs/maintenance/backup-and-restore/backup/backup-repo.md similarity index 97% rename from docs/user_docs/maintaince/backup-and-restore/backup/backup-repo.md rename to docs/user_docs/maintenance/backup-and-restore/backup/backup-repo.md index 1a0dde660336..0470b4b12ec4 100644 --- a/docs/user_docs/maintaince/backup-and-restore/backup/backup-repo.md +++ b/docs/user_docs/maintenance/backup-and-restore/backup/backup-repo.md @@ -53,14 +53,14 @@ If you don't have an object storage service from a cloud provider, you can deplo Once you are logged in to the dashboard, you can generate an `access key` and `secret key`. - ![backup-and-restore-backup-repo-1](./../../../img/backup-and-restore-backup-repo-1.png) + ![backup-and-restore-backup-repo-1](./../../../../img/backup-and-restore-backup-repo-1.png) 3. Create a bucket. Create a bucket named `test-minio` for the test. - ![backup-and-restore-backup-repo-2](./../../../img/backup-and-restore-backup-repo-2.png) - ![backup-and-restore-backup-repo3](./../../../img/backup-and-restore-backup-repo-3.png) + ![backup-and-restore-backup-repo-2](./../../../../img/backup-and-restore-backup-repo-2.png) + ![backup-and-restore-backup-repo3](./../../../../img/backup-and-restore-backup-repo-3.png) :::note diff --git a/docs/user_docs/maintaince/backup-and-restore/backup/configure-backuppolicy.md b/docs/user_docs/maintenance/backup-and-restore/backup/configure-backuppolicy.md similarity index 100% rename from docs/user_docs/maintaince/backup-and-restore/backup/configure-backuppolicy.md rename to docs/user_docs/maintenance/backup-and-restore/backup/configure-backuppolicy.md diff --git a/docs/user_docs/maintaince/backup-and-restore/backup/on-demand-backup.md b/docs/user_docs/maintenance/backup-and-restore/backup/on-demand-backup.md similarity index 100% rename from docs/user_docs/maintaince/backup-and-restore/backup/on-demand-backup.md rename to docs/user_docs/maintenance/backup-and-restore/backup/on-demand-backup.md diff --git a/docs/user_docs/maintaince/backup-and-restore/backup/scheduled-backup.md b/docs/user_docs/maintenance/backup-and-restore/backup/scheduled-backup.md similarity index 100% rename from docs/user_docs/maintaince/backup-and-restore/backup/scheduled-backup.md rename to docs/user_docs/maintenance/backup-and-restore/backup/scheduled-backup.md diff --git a/docs/user_docs/maintaince/backup-and-restore/introduction.md b/docs/user_docs/maintenance/backup-and-restore/introduction.md similarity index 100% rename from docs/user_docs/maintaince/backup-and-restore/introduction.md rename to docs/user_docs/maintenance/backup-and-restore/introduction.md diff --git a/docs/user_docs/maintaince/backup-and-restore/restore/_category_.yaml b/docs/user_docs/maintenance/backup-and-restore/restore/_category_.yaml similarity index 100% rename from docs/user_docs/maintaince/backup-and-restore/restore/_category_.yaml rename to docs/user_docs/maintenance/backup-and-restore/restore/_category_.yaml diff --git a/docs/user_docs/maintaince/backup-and-restore/restore/pitr.md b/docs/user_docs/maintenance/backup-and-restore/restore/pitr.md similarity index 100% rename from docs/user_docs/maintaince/backup-and-restore/restore/pitr.md rename to docs/user_docs/maintenance/backup-and-restore/restore/pitr.md diff --git a/docs/user_docs/maintaince/backup-and-restore/restore/restore-data-from-backup-set.md b/docs/user_docs/maintenance/backup-and-restore/restore/restore-data-from-backup-set.md similarity index 100% rename from docs/user_docs/maintaince/backup-and-restore/restore/restore-data-from-backup-set.md rename to docs/user_docs/maintenance/backup-and-restore/restore/restore-data-from-backup-set.md diff --git a/docs/user_docs/maintaince/resource-scheduling/_category_.yml b/docs/user_docs/maintenance/resource-scheduling/_category_.yml similarity index 100% rename from docs/user_docs/maintaince/resource-scheduling/_category_.yml rename to docs/user_docs/maintenance/resource-scheduling/_category_.yml diff --git a/docs/user_docs/maintaince/resource-scheduling/resource-scheduling.md b/docs/user_docs/maintenance/resource-scheduling/resource-scheduling.md similarity index 100% rename from docs/user_docs/maintaince/resource-scheduling/resource-scheduling.md rename to docs/user_docs/maintenance/resource-scheduling/resource-scheduling.md From 0bbc36bdea0ecbafac06c46f1bd0fa1d6f29d411 Mon Sep 17 00:00:00 2001 From: "L.Dongming" Date: Thu, 1 Aug 2024 17:23:10 +0800 Subject: [PATCH 26/45] feat: set workload image pull secrets (#7891) --- cmd/dataprotection/main.go | 8 +++++ cmd/manager/main.go | 8 +++++ .../apps/operations/custom/action_exec.go | 3 +- controllers/apps/operations/datascript.go | 1 + .../operations/rebuild_instance_inplace.go | 3 +- controllers/dataprotection/utils.go | 2 ++ deploy/helm/templates/dataprotection.yaml | 2 ++ deploy/helm/templates/deployment.yaml | 2 ++ deploy/helm/templates/serviceaccount.yaml | 14 ++++++-- pkg/constant/const.go | 1 + pkg/controller/builder/builder_pod.go | 5 +++ .../builder/builder_service_account.go | 5 +++ pkg/controller/factory/builder.go | 1 + pkg/controllerutil/pod_utils.go | 15 ++++++++ pkg/controllerutil/pod_utils_test.go | 35 +++++++++++++++++++ 15 files changed, 101 insertions(+), 4 deletions(-) diff --git a/cmd/dataprotection/main.go b/cmd/dataprotection/main.go index 19474481a71b..73b1da57e891 100644 --- a/cmd/dataprotection/main.go +++ b/cmd/dataprotection/main.go @@ -446,5 +446,13 @@ func validateRequiredToParseConfigs() error { if err := validateWorkerServiceAccountAnnotations(viper.GetString(dptypes.CfgKeyWorkerServiceAccountAnnotations)); err != nil { return err } + + if imagePullSecrets := viper.GetString(constant.KBImagePullSecrets); imagePullSecrets != "" { + secrets := make([]corev1.LocalObjectReference, 0) + if err := json.Unmarshal([]byte(imagePullSecrets), &secrets); err != nil { + return err + } + } + return nil } diff --git a/cmd/manager/main.go b/cmd/manager/main.go index f86b1c618f8a..c9dc5026394e 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -254,6 +254,14 @@ func validateRequiredToParseConfigs() error { if err := validateAffinity(viper.GetString(constant.CfgKeyDataPlaneAffinity)); err != nil { return err } + + if imagePullSecrets := viper.GetString(constant.KBImagePullSecrets); imagePullSecrets != "" { + secrets := make([]corev1.LocalObjectReference, 0) + if err := json.Unmarshal([]byte(imagePullSecrets), &secrets); err != nil { + return err + } + } + return nil } diff --git a/controllers/apps/operations/custom/action_exec.go b/controllers/apps/operations/custom/action_exec.go index 006775ca436a..4feb1f0b3163 100644 --- a/controllers/apps/operations/custom/action_exec.go +++ b/controllers/apps/operations/custom/action_exec.go @@ -171,6 +171,7 @@ func (e *ExecAction) buildExecPodSpec(actionCtx ActionContext, return &corev1.PodSpec{ Containers: []corev1.Container{*container}, // tolerate all taints - Tolerations: e.Comp.Tolerations, + Tolerations: e.Comp.Tolerations, + ImagePullSecrets: intctrlutil.BuildImagePullSecrets(), }, nil } diff --git a/controllers/apps/operations/datascript.go b/controllers/apps/operations/datascript.go index c7920951faa5..127265862f16 100644 --- a/controllers/apps/operations/datascript.go +++ b/controllers/apps/operations/datascript.go @@ -328,6 +328,7 @@ func buildDataScriptJobs(reqCtx intctrlutil.RequestCtx, cli client.Client, clust job.Spec.BackoffLimit = pointer.Int32(0) job.Spec.Template.Spec.RestartPolicy = corev1.RestartPolicyNever job.Spec.Template.Spec.Containers = []corev1.Container{container} + job.Spec.Template.Spec.ImagePullSecrets = intctrlutil.BuildImagePullSecrets() // add labels job.Labels = getDataScriptJobLabels(cluster.Name, component.Name, ops.Name) diff --git a/controllers/apps/operations/rebuild_instance_inplace.go b/controllers/apps/operations/rebuild_instance_inplace.go index 3447fad8da62..fd71bc072e18 100644 --- a/controllers/apps/operations/rebuild_instance_inplace.go +++ b/controllers/apps/operations/rebuild_instance_inplace.go @@ -310,7 +310,8 @@ func (inPlaceHelper *inplaceRebuildHelper) createTmpPVCsAndPod(reqCtx intctrluti AddLabels(constant.OpsRequestNameLabelKey, opsRequest.Name). AddLabels(constant.OpsRequestNamespaceLabelKey, opsRequest.Namespace). SetTopologySpreadConstraints(inPlaceHelper.targetPod.Spec.TopologySpreadConstraints). - SetAffinity(inPlaceHelper.targetPod.Spec.Affinity) + SetAffinity(inPlaceHelper.targetPod.Spec.Affinity). + SetImagePullSecrets(intctrlutil.BuildImagePullSecrets()) if inPlaceHelper.instance.TargetNodeName != "" { rebuildPodBuilder.SetNodeSelector(map[string]string{ corev1.LabelHostname: inPlaceHelper.instance.TargetNodeName, diff --git a/controllers/dataprotection/utils.go b/controllers/dataprotection/utils.go index 836e117b656e..061c271f4027 100644 --- a/controllers/dataprotection/utils.go +++ b/controllers/dataprotection/utils.go @@ -383,6 +383,7 @@ func EnsureWorkerServiceAccount(reqCtx intctrlutil.RequestCtx, cli client.Client sa.Annotations[k] = v } } + sa.ImagePullSecrets = intctrlutil.BuildImagePullSecrets() if !reflect.DeepEqual(sa, saCopy) { err := cli.Patch(ctx, sa, client.MergeFrom(saCopy), multicluster.InUniversalContext()) if err != nil { @@ -418,6 +419,7 @@ func EnsureWorkerServiceAccount(reqCtx intctrlutil.RequestCtx, cli client.Client sa.Name = saName sa.Namespace = namespace sa.Annotations = extraAnnotations + sa.ImagePullSecrets = intctrlutil.BuildImagePullSecrets() if err := cli.Create(ctx, sa, multicluster.InUniversalContext()); err != nil { return client.IgnoreAlreadyExists(err) } diff --git a/deploy/helm/templates/dataprotection.yaml b/deploy/helm/templates/dataprotection.yaml index adf8e305e1be..3abf6ffa732f 100644 --- a/deploy/helm/templates/dataprotection.yaml +++ b/deploy/helm/templates/dataprotection.yaml @@ -96,6 +96,8 @@ spec: {{- end }} - name: KUBEBLOCKS_IMAGE_PULL_POLICY value: {{ .Values.dataProtection.image.pullPolicy }} + - name: KUBEBLOCKS_IMAGE_PULL_SECRETS + value: {{ .Values.dataProtection.image.imagePullSecrets | toJson | quote }} - name: KUBEBLOCKS_TOOLS_IMAGE value: "{{ .Values.image.registry | default "docker.io" }}/{{ .Values.image.tools.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - name: KUBEBLOCKS_SERVICEACCOUNT_NAME diff --git a/deploy/helm/templates/deployment.yaml b/deploy/helm/templates/deployment.yaml index 59d1f81d174f..f603fc178ba1 100644 --- a/deploy/helm/templates/deployment.yaml +++ b/deploy/helm/templates/deployment.yaml @@ -116,6 +116,8 @@ spec: {{- end }} - name: KUBEBLOCKS_IMAGE_PULL_POLICY value: {{ .Values.image.pullPolicy }} + - name: KUBEBLOCKS_IMAGE_PULL_SECRETS + value: {{ .Values.image.imagePullSecrets | toJson | quote }} - name: KUBEBLOCKS_TOOLS_IMAGE value: "{{ .Values.image.registry | default "docker.io" }}/{{ .Values.image.tools.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - name: KUBEBLOCKS_DATASCRIPT_CLIENTS_IMAGE diff --git a/deploy/helm/templates/serviceaccount.yaml b/deploy/helm/templates/serviceaccount.yaml index 228495988c56..016c5be4d5bc 100644 --- a/deploy/helm/templates/serviceaccount.yaml +++ b/deploy/helm/templates/serviceaccount.yaml @@ -9,7 +9,12 @@ metadata: annotations: {{- toYaml . | nindent 4 }} {{- end }} - {{- if ( include "kubeblocks.addonControllerEnabled" . ) | deepEqual "true" }} + {{- with .Values.image.imagePullSecrets }} +imagePullSecrets: + {{- toYaml . | nindent 2 }} + {{- end }} + +{{- if ( include "kubeblocks.addonControllerEnabled" . ) | deepEqual "true" }} --- apiVersion: v1 kind: ServiceAccount @@ -25,7 +30,6 @@ metadata: imagePullSecrets: {{- toYaml . | nindent 2 }} {{- end }} - {{- end }} {{- end }} {{- if and .Values.dataProtection.enabled }} @@ -36,4 +40,10 @@ metadata: name: {{ include "dataprotection.execWorkerSAName" . }} labels: {{- include "kubeblocks.labels" . | nindent 4 }} + {{- with .Values.image.imagePullSecrets }} +imagePullSecrets: + {{- toYaml . | nindent 2 }} + {{- end }} {{- end }} + +{{- end }} \ No newline at end of file diff --git a/pkg/constant/const.go b/pkg/constant/const.go index 21878fdfcc58..37758effadde 100644 --- a/pkg/constant/const.go +++ b/pkg/constant/const.go @@ -38,6 +38,7 @@ const ( KBServiceAccountName = "KUBEBLOCKS_SERVICEACCOUNT_NAME" KBToolsImage = "KUBEBLOCKS_TOOLS_IMAGE" KBImagePullPolicy = "KUBEBLOCKS_IMAGE_PULL_POLICY" + KBImagePullSecrets = "KUBEBLOCKS_IMAGE_PULL_SECRETS" KBDataScriptClientsImage = "KUBEBLOCKS_DATASCRIPT_CLIENTS_IMAGE" ) diff --git a/pkg/controller/builder/builder_pod.go b/pkg/controller/builder/builder_pod.go index 5ac686eb4cff..192e3d196c16 100644 --- a/pkg/controller/builder/builder_pod.go +++ b/pkg/controller/builder/builder_pod.go @@ -117,3 +117,8 @@ func (builder *PodBuilder) SetActiveDeadlineSeconds(activeDeadline *int64) *PodB builder.get().Spec.ActiveDeadlineSeconds = activeDeadline return builder } + +func (builder *PodBuilder) SetImagePullSecrets(secrets []corev1.LocalObjectReference) *PodBuilder { + builder.get().Spec.ImagePullSecrets = secrets + return builder +} diff --git a/pkg/controller/builder/builder_service_account.go b/pkg/controller/builder/builder_service_account.go index 352ae75e0247..17d6d756d60e 100644 --- a/pkg/controller/builder/builder_service_account.go +++ b/pkg/controller/builder/builder_service_account.go @@ -32,3 +32,8 @@ func NewServiceAccountBuilder(namespace, name string) *ServiceAccountBuilder { builder.init(namespace, name, &corev1.ServiceAccount{}, builder) return builder } + +func (b *ServiceAccountBuilder) SetImagePullSecrets(secrets []corev1.LocalObjectReference) *ServiceAccountBuilder { + b.get().ImagePullSecrets = secrets + return b +} diff --git a/pkg/controller/factory/builder.go b/pkg/controller/factory/builder.go index f6c749e42c9a..f594e4ec0632 100644 --- a/pkg/controller/factory/builder.go +++ b/pkg/controller/factory/builder.go @@ -505,6 +505,7 @@ func BuildServiceAccount(cluster *appsv1alpha1.Cluster, saName string) *corev1.S wellKnownLabels := constant.GetKBWellKnownLabels(cluster.Spec.ClusterDefRef, cluster.Name, "") return builder.NewServiceAccountBuilder(cluster.Namespace, saName). AddLabelsInMap(wellKnownLabels). + SetImagePullSecrets(intctrlutil.BuildImagePullSecrets()). GetObject() } diff --git a/pkg/controllerutil/pod_utils.go b/pkg/controllerutil/pod_utils.go index 0cceb37210a5..be2d4c9efaa8 100644 --- a/pkg/controllerutil/pod_utils.go +++ b/pkg/controllerutil/pod_utils.go @@ -20,6 +20,7 @@ along with this program. If not, see . package controllerutil import ( + "encoding/json" "fmt" "strconv" "strings" @@ -33,6 +34,7 @@ import ( appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" "github.com/apecloud/kubeblocks/pkg/constant" + viper "github.com/apecloud/kubeblocks/pkg/viperx" ) const ( @@ -582,3 +584,16 @@ func isContainerFailedAndTimedOut(pod *corev1.Pod, podConditionType corev1.PodCo } return time.Now().After(containerReadyCondition.LastTransitionTime.Add(PodContainerFailedTimeout)) } + +func BuildImagePullSecrets() []corev1.LocalObjectReference { + secrets := make([]corev1.LocalObjectReference, 0) + secretsVal := viper.GetString(constant.KBImagePullSecrets) + if secretsVal == "" { + return secrets + } + + // we already validate the value of KBImagePullSecrets when start server, + // so we can ignore the error here + _ = json.Unmarshal([]byte(secretsVal), &secrets) + return secrets +} diff --git a/pkg/controllerutil/pod_utils_test.go b/pkg/controllerutil/pod_utils_test.go index f3c49eff9928..447dc4da6410 100644 --- a/pkg/controllerutil/pod_utils_test.go +++ b/pkg/controllerutil/pod_utils_test.go @@ -38,6 +38,7 @@ import ( appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" "github.com/apecloud/kubeblocks/pkg/constant" testk8s "github.com/apecloud/kubeblocks/pkg/testutil/k8s" + viper "github.com/apecloud/kubeblocks/pkg/viperx" ) type TestResourceUnit struct { @@ -607,3 +608,37 @@ var _ = Describe("pod utils", func() { }) }) }) + +func TestBuildImagePullSecretsByEnv(t *testing.T) { + tests := []struct { + value string + expected []corev1.LocalObjectReference + }{ + { + value: "", + expected: nil, + }, + { + value: "[{\"name\":\"test\"}]", + expected: []corev1.LocalObjectReference{ + { + Name: "test", + }, + }, + }, + } + + Context("test BuildImagePullSecrets", func() { + It("Should succeed with no error", func() { + for _, t := range tests { + viper.Set(constant.KBImagePullSecrets, t.value) + secrets := BuildImagePullSecrets() + if t.value == "" { + Expect(len(secrets)).To(Equal(0)) + } else { + Expect(secrets).To(Equal(t.expected)) + } + } + }) + }) +} From 49be5b6af1cc5c61f7f5b7f1a34f8185a72f2084 Mon Sep 17 00:00:00 2001 From: Leon Date: Fri, 2 Aug 2024 14:20:47 +0800 Subject: [PATCH 27/45] chore: remove cluster version crd (#7026) --- .../v1alpha1/backuppolicytemplate_types.go | 3 +- apis/apps/v1alpha1/cluster_types_test.go | 1 - apis/apps/v1alpha1/clusterversion_types.go | 243 -- .../v1alpha1/clusterversion_types_test.go | 153 - apis/apps/v1alpha1/configconstraint_types.go | 2 +- apis/apps/v1alpha1/opsrequest_conditions.go | 2 +- apis/apps/v1alpha1/opsrequest_validation.go | 7 +- apis/apps/v1alpha1/type.go | 3 +- apis/apps/v1alpha1/zz_generated.deepcopy.go | 198 - apis/apps/v1beta1/configconstraint_types.go | 2 +- cmd/manager/main.go | 9 - ...s.kubeblocks.io_backuppolicytemplates.yaml | 6 +- .../apps.kubeblocks.io_clusterversions.yaml | 3279 ----------------- .../apps.kubeblocks.io_configconstraints.yaml | 4 +- config/crd/kustomization.yaml | 3 - .../cainjection_in_apps_clusterversions.yaml | 7 - .../webhook_in_apps_clusterversions.yaml | 16 - .../rbac/apps_clusterversion_editor_role.yaml | 24 - .../rbac/apps_clusterversion_viewer_role.yaml | 20 - config/rbac/role.yaml | 26 - .../ops/mysql_clusterversion_upgrade.yaml | 12 - controllers/apps/cluster_controller_test.go | 129 +- controllers/apps/cluster_plan_builder.go | 1 - controllers/apps/cluster_plan_builder_test.go | 12 +- .../apps/clusterdefinition_controller.go | 13 +- .../apps/clusterdefinition_controller_test.go | 59 +- controllers/apps/clusterversion_controller.go | 229 -- .../apps/clusterversion_controller_test.go | 83 - controllers/apps/component_controller_test.go | 68 +- .../apps/component_plan_builder_test.go | 2 +- controllers/apps/component_utils_test.go | 13 +- controllers/apps/configuration/config_util.go | 14 +- .../apps/configuration/config_util_test.go | 83 - .../configconstraint_controller.go | 5 +- .../configconstraint_controller_test.go | 13 +- .../apps/configuration/configuration_test.go | 13 +- controllers/apps/const.go | 1 - controllers/apps/operations/backup_test.go | 5 +- controllers/apps/operations/custom_test.go | 5 +- .../apps/operations/datascript_test.go | 7 +- controllers/apps/operations/expose_test.go | 7 +- .../operations/horizontal_scaling_test.go | 16 +- .../apps/operations/ops_progress_util_test.go | 7 +- controllers/apps/operations/ops_util_test.go | 14 +- .../apps/operations/rebuild_instance_test.go | 8 +- .../apps/operations/reconfigure_test.go | 5 +- controllers/apps/operations/restart_test.go | 5 +- controllers/apps/operations/restore_test.go | 5 +- controllers/apps/operations/start_test.go | 5 +- controllers/apps/operations/stop_test.go | 5 +- controllers/apps/operations/suite_test.go | 8 +- .../apps/operations/switchover_test.go | 21 +- .../apps/operations/switchover_util_test.go | 26 +- controllers/apps/operations/upgrade.go | 55 +- controllers/apps/operations/upgrade_test.go | 67 +- .../apps/operations/util/common_util_test.go | 3 +- .../apps/operations/vertical_scaling_test.go | 9 +- .../apps/operations/volume_expansion_test.go | 7 +- .../apps/opsrequest_controller_test.go | 28 +- .../apps/servicedescriptor_controller_test.go | 4 +- controllers/apps/suite_test.go | 7 - .../transformer_cluster_api_normalization.go | 2 +- .../apps/transformer_cluster_backup_policy.go | 9 - .../transformer_cluster_component_test.go | 2 +- .../apps/transformer_cluster_deletion_test.go | 2 +- .../transformer_cluster_halt_recovering.go | 11 - .../transformer_cluster_load_resources.go | 30 - controllers/apps/transformer_cluster_meta.go | 6 +- .../apps/transformer_component_rbac_test.go | 2 +- .../apps/transformer_component_tls_test.go | 13 +- .../extensions/addon_controller_test.go | 12 +- controllers/k8score/event_controller_test.go | 4 +- deploy/helm/config/rbac/role.yaml | 26 - ...s.kubeblocks.io_backuppolicytemplates.yaml | 6 +- .../apps.kubeblocks.io_clusterversions.yaml | 3279 ----------------- .../apps.kubeblocks.io_configconstraints.yaml | 4 +- .../admission/webhookconfiguration.yaml | 24 - .../rbac/apps_clusterversion_editor_role.yaml | 26 - .../rbac/apps_clusterversion_viewer_role.yaml | 22 - docs/developer_docs/api-reference/cluster.md | 436 +-- .../typed/apps/v1alpha1/apps_client.go | 5 - .../typed/apps/v1alpha1/clusterversion.go | 184 - .../apps/v1alpha1/fake/fake_apps_client.go | 4 - .../apps/v1alpha1/fake/fake_clusterversion.go | 132 - .../apps/v1alpha1/generated_expansion.go | 2 - .../apps/v1alpha1/clusterversion.go | 89 - .../apps/v1alpha1/interface.go | 7 - .../informers/externalversions/generic.go | 2 - .../listers/apps/v1alpha1/clusterversion.go | 68 - .../apps/v1alpha1/expansion_generated.go | 4 - pkg/configuration/core/configtemplate_util.go | 57 +- .../core/configtemplate_util_test.go | 238 +- pkg/configuration/core/type.go | 1 - pkg/constant/annotations.go | 1 - pkg/constant/config.go | 2 +- pkg/constant/labels.go | 1 - .../component/action_post_provision_test.go | 22 +- .../component/action_pre_terminate_test.go | 22 +- pkg/controller/component/action_utils_test.go | 22 +- pkg/controller/component/component.go | 40 +- pkg/controller/component/component_test.go | 57 +- .../component/definition_convertor.go | 40 +- .../component/definition_convertor_test.go | 88 +- .../component/fieldref_util_test.go | 5 +- .../service_descriptor_utils_test.go | 25 +- .../component/service_reference_test.go | 13 +- .../component/synthesize_component.go | 114 +- .../configuration/configuration_test.go | 33 +- .../configuration/envfrom_utils_test.go | 19 +- pkg/controller/configuration/operator.go | 2 - pkg/controller/configuration/operator_test.go | 8 +- pkg/controller/configuration/pipeline_test.go | 7 +- .../configuration/resource_wrapper.go | 18 - .../configuration/resource_wrapper_test.go | 21 +- .../configuration/template_wrapper_test.go | 6 +- .../configuration/tool_image_builder_test.go | 6 +- pkg/controller/factory/builder_test.go | 45 +- pkg/controller/job/job_utils_test.go | 23 +- pkg/controller/plan/prepare_test.go | 28 +- pkg/controller/plan/restore_test.go | 28 +- .../scheduling/scheduling_utils_test.go | 3 +- pkg/controllerutil/cluster_utils_test.go | 15 +- pkg/controllerutil/sharding_utils_test.go | 15 +- pkg/generics/type.go | 2 - .../apps/backuppolicytemplate_factory.go | 18 +- pkg/testutil/apps/cluster_factory.go | 3 +- .../apps/cluster_instance_set_test_util.go | 19 +- pkg/testutil/apps/cluster_util.go | 14 +- pkg/testutil/apps/clusterversion_factory.go | 106 - pkg/testutil/apps/common_util.go | 13 +- pkg/testutil/apps/constant.go | 3 - pkg/testutil/dataprotection/backup_utils.go | 3 +- test/e2e/testdata/config/postgresql_cv.yaml | 23 - 133 files changed, 425 insertions(+), 10304 deletions(-) delete mode 100644 apis/apps/v1alpha1/clusterversion_types.go delete mode 100644 apis/apps/v1alpha1/clusterversion_types_test.go delete mode 100644 config/crd/bases/apps.kubeblocks.io_clusterversions.yaml delete mode 100644 config/crd/patches/cainjection_in_apps_clusterversions.yaml delete mode 100644 config/crd/patches/webhook_in_apps_clusterversions.yaml delete mode 100644 config/rbac/apps_clusterversion_editor_role.yaml delete mode 100644 config/rbac/apps_clusterversion_viewer_role.yaml delete mode 100644 config/samples/ops/mysql_clusterversion_upgrade.yaml delete mode 100644 controllers/apps/clusterversion_controller.go delete mode 100644 controllers/apps/clusterversion_controller_test.go delete mode 100644 deploy/helm/crds/apps.kubeblocks.io_clusterversions.yaml delete mode 100644 deploy/helm/templates/rbac/apps_clusterversion_editor_role.yaml delete mode 100644 deploy/helm/templates/rbac/apps_clusterversion_viewer_role.yaml delete mode 100644 pkg/client/clientset/versioned/typed/apps/v1alpha1/clusterversion.go delete mode 100644 pkg/client/clientset/versioned/typed/apps/v1alpha1/fake/fake_clusterversion.go delete mode 100644 pkg/client/informers/externalversions/apps/v1alpha1/clusterversion.go delete mode 100644 pkg/client/listers/apps/v1alpha1/clusterversion.go delete mode 100644 pkg/testutil/apps/clusterversion_factory.go delete mode 100644 test/e2e/testdata/config/postgresql_cv.yaml diff --git a/apis/apps/v1alpha1/backuppolicytemplate_types.go b/apis/apps/v1alpha1/backuppolicytemplate_types.go index c35ddb3d63cb..acd19f3f1051 100644 --- a/apis/apps/v1alpha1/backuppolicytemplate_types.go +++ b/apis/apps/v1alpha1/backuppolicytemplate_types.go @@ -149,8 +149,7 @@ type ValueFrom struct { } type ValueMapping struct { - // Represents an array of names of ClusterVersion or ComponentDefinition that can be mapped to - // the appropriate version of the backup tool image. + // Represents an array of names of ComponentDefinition that can be mapped to the appropriate version of the backup tool image. // // This mapping allows different versions of component images to correspond to specific versions of backup tool images. // diff --git a/apis/apps/v1alpha1/cluster_types_test.go b/apis/apps/v1alpha1/cluster_types_test.go index 06a8f7915665..701772ba09de 100644 --- a/apis/apps/v1alpha1/cluster_types_test.go +++ b/apis/apps/v1alpha1/cluster_types_test.go @@ -217,7 +217,6 @@ kind: Cluster metadata: name: wesql spec: - clusterVersionRef: cluster-version-consensus clusterDefinitionRef: cluster-definition-consensus componentSpecs: - name: wesql-test diff --git a/apis/apps/v1alpha1/clusterversion_types.go b/apis/apps/v1alpha1/clusterversion_types.go deleted file mode 100644 index 29379fc9191c..000000000000 --- a/apis/apps/v1alpha1/clusterversion_types.go +++ /dev/null @@ -1,243 +0,0 @@ -/* -Copyright (C) 2022-2024 ApeCloud Co., Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha1 - -import ( - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// ClusterVersionSpec defines the desired state of ClusterVersion. -// -// Deprecated since v0.9. -// This struct is maintained for backward compatibility and its use is discouraged. -type ClusterVersionSpec struct { - // Specifies a reference to the ClusterDefinition. - // - // +kubebuilder:validation:Required - // +kubebuilder:validation:Pattern:=`^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$` - ClusterDefinitionRef string `json:"clusterDefinitionRef"` - - // Contains a list of versioning contexts for the components' containers. - // - // +kubebuilder:validation:Required - // +kubebuilder:validation:MinItems=1 - // +patchMergeKey=componentDefRef - // +patchStrategy=merge,retainKeys - // +listType=map - // +listMapKey=componentDefRef - ComponentVersions []ClusterComponentVersion `json:"componentVersions" patchStrategy:"merge,retainKeys" patchMergeKey:"componentDefRef"` -} - -// ClusterVersionStatus defines the observed state of ClusterVersion. -// -// Deprecated since v0.9. -// This struct is maintained for backward compatibility and its use is discouraged. -type ClusterVersionStatus struct { - // The current phase of the ClusterVersion. - // - // +optional - Phase Phase `json:"phase,omitempty"` - - // Provides additional information about the current phase. - // - // +optional - Message string `json:"message,omitempty"` - - // The generation number that has been observed by the controller. - // - // +optional - ObservedGeneration int64 `json:"observedGeneration,omitempty"` - - // The generation number of the ClusterDefinition that is currently being referenced. - // - // +optional - ClusterDefGeneration int64 `json:"clusterDefGeneration,omitempty"` -} - -func (r ClusterVersionStatus) GetTerminalPhases() []Phase { - return []Phase{AvailablePhase} -} - -// ClusterComponentVersion is an application version component spec. -// -// Deprecated since v0.9. -// This struct is maintained for backward compatibility and its use is discouraged. -type ClusterComponentVersion struct { - // Specifies a reference to one of the cluster component definition names in the ClusterDefinition API (spec.componentDefs.name). - // - // +kubebuilder:validation:Required - // +kubebuilder:validation:MaxLength=63 - // +kubebuilder:validation:Pattern:=`^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$` - ComponentDefRef string `json:"componentDefRef"` - - // Defines a configuration extension mechanism to handle configuration differences between versions. - // The configTemplateRefs field, in conjunction with the configTemplateRefs in the ClusterDefinition, determines - // the final configuration file. - // - // +patchMergeKey=name - // +patchStrategy=merge,retainKeys - // +listType=map - // +listMapKey=name - // +optional - ConfigSpecs []ComponentConfigSpec `json:"configSpecs,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"name"` - - // Defines the image for the component to connect to databases or engines. - // This overrides the `image` and `env` attributes defined in clusterDefinition.spec.componentDefs.systemAccountSpec.cmdExecutorConfig. - // To clear default environment settings, set systemAccountSpec.cmdExecutorConfig.env to an empty list. - // - // +optional - SystemAccountSpec *SystemAccountShortSpec `json:"systemAccountSpec,omitempty"` - - // Defines the context for container images for component versions. - // This value replaces the values in clusterDefinition.spec.componentDefs.podSpec.[initContainers | containers]. - VersionsCtx VersionsContext `json:"versionsContext"` - - // Defines the images for the component to perform a switchover. - // This overrides the image and env attributes defined in clusterDefinition.spec.componentDefs.SwitchoverSpec.CommandExecutorEnvItem. - // - // +optional - SwitchoverSpec *SwitchoverShortSpec `json:"switchoverSpec,omitempty"` -} - -// SystemAccountShortSpec represents a condensed version of the SystemAccountSpec. -// -// Deprecated since v0.9. -// This struct is maintained for backward compatibility and its use is discouraged. -type SystemAccountShortSpec struct { - // Configures the method for obtaining the client SDK and executing statements. - // - // +kubebuilder:validation:Required - CmdExecutorConfig *CommandExecutorEnvItem `json:"cmdExecutorConfig"` -} - -// SwitchoverShortSpec represents a condensed version of the SwitchoverSpec. -// -// Deprecated since v0.9. -// This struct is maintained for backward compatibility and its use is discouraged. -type SwitchoverShortSpec struct { - // Represents the configuration for the command executor. - // - // +kubebuilder:validation:Required - CmdExecutorConfig *CommandExecutorEnvItem `json:"cmdExecutorConfig"` -} - -// VersionsContext is deprecated since v0.9. -// This struct is maintained for backward compatibility and its use is discouraged. -type VersionsContext struct { - // Provides override values for ClusterDefinition.spec.componentDefs.podSpec.initContainers. - // Typically used in scenarios such as updating application container images. - // - // +kubebuilder:pruning:PreserveUnknownFields - // +patchMergeKey=name - // +patchStrategy=merge - // +listType=map - // +listMapKey=name - // +optional - InitContainers []corev1.Container `json:"initContainers,omitempty"` - - // Provides override values for ClusterDefinition.spec.componentDefs.podSpec.containers. - // Typically used in scenarios such as updating application container images. - // - // +kubebuilder:pruning:PreserveUnknownFields - // +patchMergeKey=name - // +patchStrategy=merge - // +listType=map - // +listMapKey=name - // +optional - Containers []corev1.Container `json:"containers,omitempty"` -} - -// +genclient -// +genclient:nonNamespaced -// +k8s:openapi-gen=true -// +kubebuilder:object:root=true -// +kubebuilder:subresource:status -// +kubebuilder:resource:categories={kubeblocks},scope=Cluster,shortName=cv -// +kubebuilder:printcolumn:name="CLUSTER-DEFINITION",type="string",JSONPath=".spec.clusterDefinitionRef",description="ClusterDefinition referenced by cluster." -// +kubebuilder:printcolumn:name="STATUS",type="string",JSONPath=".status.phase",description="status phase" -// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" -// +kubebuilder:deprecatedversion:warning="The ClusterVersion CRD has been deprecated since 0.9.0" - -// ClusterVersion is the Schema for the ClusterVersions API. -// -// Deprecated: ClusterVersion has been replaced by ComponentVersion since v0.9. -// This struct is maintained for backward compatibility and its use is discouraged. -type ClusterVersion struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec ClusterVersionSpec `json:"spec,omitempty"` - Status ClusterVersionStatus `json:"status,omitempty"` -} - -// +kubebuilder:object:root=true - -// ClusterVersionList contains a list of ClusterVersion. -type ClusterVersionList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []ClusterVersion `json:"items"` -} - -func init() { - SchemeBuilder.Register(&ClusterVersion{}, &ClusterVersionList{}) -} - -// GetDefNameMappingComponents returns ComponentDefRef name mapping ClusterComponentVersion. -func (r ClusterVersionSpec) GetDefNameMappingComponents() map[string]*ClusterComponentVersion { - m := map[string]*ClusterComponentVersion{} - for i, c := range r.ComponentVersions { - m[c.ComponentDefRef] = &r.ComponentVersions[i] - } - return m -} - -// GetInconsistentComponentsInfo get clusterVersion invalid component name and no containers component compared with clusterDefinitionDef -func (r *ClusterVersion) GetInconsistentComponentsInfo(clusterDef *ClusterDefinition) ([]string, []string) { - - var ( - // clusterDefinition components to map. the value of map represents whether there is a default containers - componentMap = map[string]bool{} - notFoundComponentDefNames = make([]string, 0) - noContainersComponent = make([]string, 0) - ) - - for _, v := range clusterDef.Spec.ComponentDefs { - if v.PodSpec == nil || v.PodSpec.Containers == nil || len(v.PodSpec.Containers) == 0 { - componentMap[v.Name] = false - } else { - componentMap[v.Name] = true - } - } - // get not found component name in clusterDefinition - for _, v := range r.Spec.ComponentVersions { - if _, ok := componentMap[v.ComponentDefRef]; !ok { - notFoundComponentDefNames = append(notFoundComponentDefNames, v.ComponentDefRef) - } else if (len(v.VersionsCtx.Containers) > 0) || - (len(v.VersionsCtx.InitContainers) > 0) { - componentMap[v.ComponentDefRef] = true - } - } - // get no containers components in clusterDefinition and clusterVersion - for k, v := range componentMap { - if !v { - noContainersComponent = append(noContainersComponent, k) - } - } - return notFoundComponentDefNames, noContainersComponent -} diff --git a/apis/apps/v1alpha1/clusterversion_types_test.go b/apis/apps/v1alpha1/clusterversion_types_test.go deleted file mode 100644 index a3d820ce67b7..000000000000 --- a/apis/apps/v1alpha1/clusterversion_types_test.go +++ /dev/null @@ -1,153 +0,0 @@ -/* -Copyright (C) 2022-2024 ApeCloud Co., Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha1 - -import ( - "testing" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - "k8s.io/apimachinery/pkg/util/yaml" -) - -func TestGetInconsistentComponentsInfoWithoutResult(t *testing.T) { - g := NewGomegaWithT(t) - - // init ClusterVersion - clusterVersion := &ClusterVersion{} - clusterVersionYaml := ` -apiVersion: apps.kubeblocks.io/v1alpha1 -kind: ClusterVersion -metadata: - name: clusterversion-1 -spec: - clusterDefinitionRef: cluster-definition-1 - componentVersions: - - componentDefRef: component1 - versionsContext: - containers: - - name: container1.a - - name: container1.b - - componentDefRef: component2 - versionsContext: - containers: - - name: container2 - - componentDefRef: component3 - versionsContext: - containers: -` - g.Expect(yaml.Unmarshal([]byte(clusterVersionYaml), clusterVersion)).To(Succeed()) - - // init clusterDef - clusterDef := &ClusterDefinition{} - clusterDefYaml := ` -apiVersion: apps.kubeblocks.io/v1alpha1 -kind: ClusterDefinition -metadata: - name: cluster-definition-1 -spec: - componentDefs: - - name: component1 - podSpec: - containers: - - name: container1.c - - name: component2 - podSpec: - containers: - - name: component3 - podSpec: - containers: - - name: container3 -` - g.Expect(yaml.Unmarshal([]byte(clusterDefYaml), clusterDef)).To(Succeed()) - - notFoundComponentDefNames, noContainersComponents := clusterVersion.GetInconsistentComponentsInfo(clusterDef) - g.Expect(len(notFoundComponentDefNames)).To(Equal(0)) - g.Expect(len(noContainersComponents)).To(Equal(0)) -} - -func TestGetInconsistentComponentsInfoWithResults(t *testing.T) { - g := NewGomegaWithT(t) - - // init clusterVersion - clusterVersion := &ClusterVersion{} - clusterVersionYaml := ` -apiVersion: apps.kubeblocks.io/v1alpha1 -kind: ClusterVersion -metadata: - name: clusterversion-2 -spec: - clusterDefinitionRef: cluster-definition-2 - componentVersions: - - componentDefRef: component1 - versionsContext: - containers: - - name: container1 - - componentDefRef: component2 - versionsContext: - containers: - - componentDefRef: component3 - versionsContext: - containers: - - name: container3 -` - g.Expect(yaml.Unmarshal([]byte(clusterVersionYaml), clusterVersion)).To(Succeed()) - - // init clusterDef - clusterDef := &ClusterDefinition{} - clusterDefYaml := ` -apiVersion: apps.kubeblocks.io/v1alpha1 -kind: ClusterDefinition -metadata: - name: cluster-definition-2 -spec: - componentDefs: - - name: component1 - podSpec: - containers: - - name: container1 - - name: component2 - podSpec: -` - g.Expect(yaml.Unmarshal([]byte(clusterDefYaml), clusterDef)).To(Succeed()) - - notFoundComponentDefNames, noContainersComponents := clusterVersion.GetInconsistentComponentsInfo(clusterDef) - g.Expect(len(notFoundComponentDefNames)).To(Equal(1)) - g.Expect(notFoundComponentDefNames[0]).To(Equal("component3")) - g.Expect(len(noContainersComponents)).To(Equal(1)) - g.Expect(noContainersComponents[0]).To(Equal("component2")) -} - -var _ = Describe("", func() { - - It("test GetTerminalPhases", func() { - r := ClusterVersionStatus{} - Expect(r.GetTerminalPhases()).Should(ContainElement(AvailablePhase)) - }) - - It("test GetDefNameMappingComponents", func() { - r := ClusterVersionSpec{} - compDefRef := "test-comp-def" - r.ComponentVersions = []ClusterComponentVersion{ - { - ComponentDefRef: compDefRef, - }, - } - Expect(r.GetDefNameMappingComponents()[compDefRef]).ShouldNot(BeNil()) - }) -}) diff --git a/apis/apps/v1alpha1/configconstraint_types.go b/apis/apps/v1alpha1/configconstraint_types.go index fc7bf1683cac..beba03a03e16 100644 --- a/apis/apps/v1alpha1/configconstraint_types.go +++ b/apis/apps/v1alpha1/configconstraint_types.go @@ -177,7 +177,7 @@ type ConfigConstraintSpec struct { type ConfigConstraintStatus struct { // Specifies the status of the configuration template. - // When set to CCAvailablePhase, the ConfigConstraint can be referenced by ClusterDefinition or ClusterVersion. + // When set to CCAvailablePhase, the ConfigConstraint can be referenced by ClusterDefinition. // // +optional Phase appsv1beta1.ConfigConstraintPhase `json:"phase,omitempty"` diff --git a/apis/apps/v1alpha1/opsrequest_conditions.go b/apis/apps/v1alpha1/opsrequest_conditions.go index 5003479aeac7..8de6aafec0a5 100644 --- a/apis/apps/v1alpha1/opsrequest_conditions.go +++ b/apis/apps/v1alpha1/opsrequest_conditions.go @@ -258,7 +258,7 @@ func NewExposingCondition(ops *OpsRequest) *metav1.Condition { } } -// NewUpgradingCondition creates a condition that the OpsRequest starts to upgrade the cluster version +// NewUpgradingCondition creates a condition that the OpsRequest starts to upgrade the version func NewUpgradingCondition(ops *OpsRequest) *metav1.Condition { return &metav1.Condition{ Type: ConditionTypeVersionUpgrading, diff --git a/apis/apps/v1alpha1/opsrequest_validation.go b/apis/apps/v1alpha1/opsrequest_validation.go index 46978a1634a9..d1d6d9e6de92 100644 --- a/apis/apps/v1alpha1/opsrequest_validation.go +++ b/apis/apps/v1alpha1/opsrequest_validation.go @@ -197,16 +197,13 @@ func (r *OpsRequest) validateRestart(cluster *Cluster) error { } // validateUpgrade validates spec.clusterOps.upgrade -func (r *OpsRequest) validateUpgrade(ctx context.Context, - k8sClient client.Client, - cluster *Cluster) error { +func (r *OpsRequest) validateUpgrade(ctx context.Context, k8sClient client.Client, cluster *Cluster) error { upgrade := r.Spec.Upgrade if upgrade == nil { return notEmptyError("spec.upgrade") } if upgrade.ClusterVersionRef != nil && *upgrade.ClusterVersionRef != "" { - // TODO: remove this deprecated api after v0.9 - return k8sClient.Get(ctx, types.NamespacedName{Name: *upgrade.ClusterVersionRef}, &ClusterVersion{}) + return fmt.Errorf("not supported") } if len(r.Spec.Upgrade.Components) == 0 { return notEmptyError("spec.upgrade.components") diff --git a/apis/apps/v1alpha1/type.go b/apis/apps/v1alpha1/type.go index 92679dc6d107..69a8589ce940 100644 --- a/apis/apps/v1alpha1/type.go +++ b/apis/apps/v1alpha1/type.go @@ -26,7 +26,6 @@ import ( const ( APIVersion = "apps.kubeblocks.io/v1alpha1" - ClusterVersionKind = "ClusterVersion" ClusterDefinitionKind = "ClusterDefinition" ClusterKind = "Cluster" ComponentKind = "Component" @@ -307,7 +306,7 @@ const ( ConditionTypeSwitchoverPrefix = "Switchover-" // ConditionTypeSwitchoverPrefix component status condition of switchover ) -// Phase represents the current status of the ClusterDefinition and ClusterVersion CR. +// Phase represents the current status of the ClusterDefinition CR. // // +enum // +kubebuilder:validation:Enum={Available,Unavailable} diff --git a/apis/apps/v1alpha1/zz_generated.deepcopy.go b/apis/apps/v1alpha1/zz_generated.deepcopy.go index abc2bf91c376..d44c760e027d 100644 --- a/apis/apps/v1alpha1/zz_generated.deepcopy.go +++ b/apis/apps/v1alpha1/zz_generated.deepcopy.go @@ -740,39 +740,6 @@ func (in *ClusterComponentStatus) DeepCopy() *ClusterComponentStatus { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterComponentVersion) DeepCopyInto(out *ClusterComponentVersion) { - *out = *in - if in.ConfigSpecs != nil { - in, out := &in.ConfigSpecs, &out.ConfigSpecs - *out = make([]ComponentConfigSpec, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.SystemAccountSpec != nil { - in, out := &in.SystemAccountSpec, &out.SystemAccountSpec - *out = new(SystemAccountShortSpec) - (*in).DeepCopyInto(*out) - } - in.VersionsCtx.DeepCopyInto(&out.VersionsCtx) - if in.SwitchoverSpec != nil { - in, out := &in.SwitchoverSpec, &out.SwitchoverSpec - *out = new(SwitchoverShortSpec) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterComponentVersion. -func (in *ClusterComponentVersion) DeepCopy() *ClusterComponentVersion { - if in == nil { - return nil - } - out := new(ClusterComponentVersion) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClusterComponentVolumeClaimTemplate) DeepCopyInto(out *ClusterComponentVolumeClaimTemplate) { *out = *in @@ -1284,102 +1251,6 @@ func (in *ClusterTopologyOrders) DeepCopy() *ClusterTopologyOrders { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterVersion) DeepCopyInto(out *ClusterVersion) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - out.Status = in.Status -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterVersion. -func (in *ClusterVersion) DeepCopy() *ClusterVersion { - if in == nil { - return nil - } - out := new(ClusterVersion) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ClusterVersion) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterVersionList) DeepCopyInto(out *ClusterVersionList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]ClusterVersion, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterVersionList. -func (in *ClusterVersionList) DeepCopy() *ClusterVersionList { - if in == nil { - return nil - } - out := new(ClusterVersionList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ClusterVersionList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterVersionSpec) DeepCopyInto(out *ClusterVersionSpec) { - *out = *in - if in.ComponentVersions != nil { - in, out := &in.ComponentVersions, &out.ComponentVersions - *out = make([]ClusterComponentVersion, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterVersionSpec. -func (in *ClusterVersionSpec) DeepCopy() *ClusterVersionSpec { - if in == nil { - return nil - } - out := new(ClusterVersionSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterVersionStatus) DeepCopyInto(out *ClusterVersionStatus) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterVersionStatus. -func (in *ClusterVersionStatus) DeepCopy() *ClusterVersionStatus { - if in == nil { - return nil - } - out := new(ClusterVersionStatus) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CmdExecutorConfig) DeepCopyInto(out *CmdExecutorConfig) { *out = *in @@ -5870,26 +5741,6 @@ func (in *SwitchoverAction) DeepCopy() *SwitchoverAction { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SwitchoverShortSpec) DeepCopyInto(out *SwitchoverShortSpec) { - *out = *in - if in.CmdExecutorConfig != nil { - in, out := &in.CmdExecutorConfig, &out.CmdExecutorConfig - *out = new(CommandExecutorEnvItem) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SwitchoverShortSpec. -func (in *SwitchoverShortSpec) DeepCopy() *SwitchoverShortSpec { - if in == nil { - return nil - } - out := new(SwitchoverShortSpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SwitchoverSpec) DeepCopyInto(out *SwitchoverSpec) { *out = *in @@ -5952,26 +5803,6 @@ func (in *SystemAccountConfig) DeepCopy() *SystemAccountConfig { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SystemAccountShortSpec) DeepCopyInto(out *SystemAccountShortSpec) { - *out = *in - if in.CmdExecutorConfig != nil { - in, out := &in.CmdExecutorConfig, &out.CmdExecutorConfig - *out = new(CommandExecutorEnvItem) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SystemAccountShortSpec. -func (in *SystemAccountShortSpec) DeepCopy() *SystemAccountShortSpec { - if in == nil { - return nil - } - out := new(SystemAccountShortSpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SystemAccountSpec) DeepCopyInto(out *SystemAccountSpec) { *out = *in @@ -6288,35 +6119,6 @@ func (in *VarSource) DeepCopy() *VarSource { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VersionsContext) DeepCopyInto(out *VersionsContext) { - *out = *in - if in.InitContainers != nil { - in, out := &in.InitContainers, &out.InitContainers - *out = make([]v1.Container, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Containers != nil { - in, out := &in.Containers, &out.Containers - *out = make([]v1.Container, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VersionsContext. -func (in *VersionsContext) DeepCopy() *VersionsContext { - if in == nil { - return nil - } - out := new(VersionsContext) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VerticalScaling) DeepCopyInto(out *VerticalScaling) { *out = *in diff --git a/apis/apps/v1beta1/configconstraint_types.go b/apis/apps/v1beta1/configconstraint_types.go index e353424a2c2b..feb69b3f9130 100644 --- a/apis/apps/v1beta1/configconstraint_types.go +++ b/apis/apps/v1beta1/configconstraint_types.go @@ -138,7 +138,7 @@ type ConfigConstraintSpec struct { type ConfigConstraintStatus struct { // Specifies the status of the configuration template. - // When set to CCAvailablePhase, the ConfigConstraint can be referenced by ClusterDefinition or ClusterVersion. + // When set to CCAvailablePhase, the ConfigConstraint can be referenced by ClusterDefinition. // // +optional Phase ConfigConstraintPhase `json:"phase,omitempty"` diff --git a/cmd/manager/main.go b/cmd/manager/main.go index c9dc5026394e..c7f0a003954e 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -392,15 +392,6 @@ func main() { os.Exit(1) } - if err = (&appscontrollers.ClusterVersionReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - Recorder: mgr.GetEventRecorderFor("cluster-version-controller"), - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "ClusterVersion") - os.Exit(1) - } - if err = (&appscontrollers.ComponentReconciler{ Client: client, Scheme: mgr.GetScheme(), diff --git a/config/crd/bases/apps.kubeblocks.io_backuppolicytemplates.yaml b/config/crd/bases/apps.kubeblocks.io_backuppolicytemplates.yaml index 5b572f216162..4f0ae6e1b580 100644 --- a/config/crd/bases/apps.kubeblocks.io_backuppolicytemplates.yaml +++ b/config/crd/bases/apps.kubeblocks.io_backuppolicytemplates.yaml @@ -231,8 +231,7 @@ spec: type: string names: description: |- - Represents an array of names of ClusterVersion or ComponentDefinition that can be mapped to - the appropriate version of the backup tool image. + Represents an array of names of ComponentDefinition that can be mapped to the appropriate version of the backup tool image. This mapping allows different versions of component images to correspond to specific versions of backup tool images. @@ -255,8 +254,7 @@ spec: type: string names: description: |- - Represents an array of names of ClusterVersion or ComponentDefinition that can be mapped to - the appropriate version of the backup tool image. + Represents an array of names of ComponentDefinition that can be mapped to the appropriate version of the backup tool image. This mapping allows different versions of component images to correspond to specific versions of backup tool images. diff --git a/config/crd/bases/apps.kubeblocks.io_clusterversions.yaml b/config/crd/bases/apps.kubeblocks.io_clusterversions.yaml deleted file mode 100644 index 9b85a09b815d..000000000000 --- a/config/crd/bases/apps.kubeblocks.io_clusterversions.yaml +++ /dev/null @@ -1,3279 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - labels: - app.kubernetes.io/name: kubeblocks - name: clusterversions.apps.kubeblocks.io -spec: - group: apps.kubeblocks.io - names: - categories: - - kubeblocks - kind: ClusterVersion - listKind: ClusterVersionList - plural: clusterversions - shortNames: - - cv - singular: clusterversion - scope: Cluster - versions: - - additionalPrinterColumns: - - description: ClusterDefinition referenced by cluster. - jsonPath: .spec.clusterDefinitionRef - name: CLUSTER-DEFINITION - type: string - - description: status phase - jsonPath: .status.phase - name: STATUS - type: string - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - deprecated: true - deprecationWarning: The ClusterVersion CRD has been deprecated since 0.9.0 - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ClusterVersion is the Schema for the ClusterVersions API. - - - Deprecated: ClusterVersion has been replaced by ComponentVersion since v0.9. - This struct is maintained for backward compatibility and its use is discouraged. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: |- - ClusterVersionSpec defines the desired state of ClusterVersion. - - - Deprecated since v0.9. - This struct is maintained for backward compatibility and its use is discouraged. - properties: - clusterDefinitionRef: - description: Specifies a reference to the ClusterDefinition. - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - componentVersions: - description: Contains a list of versioning contexts for the components' - containers. - items: - description: |- - ClusterComponentVersion is an application version component spec. - - - Deprecated since v0.9. - This struct is maintained for backward compatibility and its use is discouraged. - properties: - componentDefRef: - description: Specifies a reference to one of the cluster component - definition names in the ClusterDefinition API (spec.componentDefs.name). - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - configSpecs: - description: |- - Defines a configuration extension mechanism to handle configuration differences between versions. - The configTemplateRefs field, in conjunction with the configTemplateRefs in the ClusterDefinition, determines - the final configuration file. - items: - properties: - asEnvFrom: - description: |- - Specifies the containers to inject the ConfigMap parameters as environment variables. - - - This is useful when application images accept parameters through environment variables and - generate the final configuration file in the startup script based on these variables. - - - This field allows users to specify a list of container names, and KubeBlocks will inject the environment - variables converted from the ConfigMap into these designated containers. This provides a flexible way to - pass the configuration items from the ConfigMap to the container without modifying the image. - - - Deprecated: `asEnvFrom` has been deprecated since 0.9.0 and will be removed in 0.10.0. - Use `injectEnvTo` instead. - items: - type: string - type: array - x-kubernetes-list-type: set - constraintRef: - description: Specifies the name of the referenced configuration - constraints object. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - defaultMode: - description: |- - The operator attempts to set default file permissions for scripts (0555) and configurations (0444). - However, certain database engines may require different file permissions. - You can specify the desired file permissions here. - - - Must be specified as an octal value between 0000 and 0777 (inclusive), - or as a decimal value between 0 and 511 (inclusive). - YAML supports both octal and decimal values for file permissions. - - - Please note that this setting only affects the permissions of the files themselves. - Directories within the specified path are not impacted by this setting. - It's important to be aware that this setting might conflict with other options - that influence the file mode, such as fsGroup. - In such cases, the resulting file mode may have additional bits set. - Refers to documents of k8s.ConfigMapVolumeSource.defaultMode for more information. - format: int32 - type: integer - injectEnvTo: - description: |- - Specifies the containers to inject the ConfigMap parameters as environment variables. - - - This is useful when application images accept parameters through environment variables and - generate the final configuration file in the startup script based on these variables. - - - This field allows users to specify a list of container names, and KubeBlocks will inject the environment - variables converted from the ConfigMap into these designated containers. This provides a flexible way to - pass the configuration items from the ConfigMap to the container without modifying the image. - items: - type: string - type: array - x-kubernetes-list-type: set - keys: - description: |- - Specifies the configuration files within the ConfigMap that support dynamic updates. - - - A configuration template (provided in the form of a ConfigMap) may contain templates for multiple - configuration files. - Each configuration file corresponds to a key in the ConfigMap. - Some of these configuration files may support dynamic modification and reloading without requiring - a pod restart. - - - If empty or omitted, all configuration files in the ConfigMap are assumed to support dynamic updates, - and ConfigConstraint applies to all keys. - items: - type: string - type: array - x-kubernetes-list-type: set - legacyRenderedConfigSpec: - description: |- - Specifies the secondary rendered config spec for pod-specific customization. - - - The template is rendered inside the pod (by the "config-manager" sidecar container) and merged with the main - template's render result to generate the final configuration file. - - - This field is intended to handle scenarios where different pods within the same Component have - varying configurations. It allows for pod-specific customization of the configuration. - - - Note: This field will be deprecated in future versions, and the functionality will be moved to - `cluster.spec.componentSpecs[*].instances[*]`. - properties: - namespace: - default: default - description: |- - Specifies the namespace of the referenced configuration template ConfigMap object. - An empty namespace is equivalent to the "default" namespace. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ - type: string - policy: - default: none - description: Defines the strategy for merging externally - imported templates into component templates. - enum: - - patch - - replace - - none - type: string - templateRef: - description: Specifies the name of the referenced - configuration template ConfigMap object. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - required: - - templateRef - type: object - name: - description: Specifies the name of the configuration template. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - namespace: - default: default - description: |- - Specifies the namespace of the referenced configuration template ConfigMap object. - An empty namespace is equivalent to the "default" namespace. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ - type: string - reRenderResourceTypes: - description: |- - Specifies whether the configuration needs to be re-rendered after v-scale or h-scale operations to reflect changes. - - - In some scenarios, the configuration may need to be updated to reflect the changes in resource allocation - or cluster topology. Examples: - - - - Redis: adjust maxmemory after v-scale operation. - - MySQL: increase max connections after v-scale operation. - - Zookeeper: update zoo.cfg with new node addresses after h-scale operation. - items: - description: RerenderResourceType defines the resource - requirements for a component. - enum: - - vscale - - hscale - - tls - type: string - type: array - x-kubernetes-list-type: set - templateRef: - description: Specifies the name of the referenced configuration - template ConfigMap object. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - volumeName: - description: |- - Refers to the volume name of PodTemplate. The configuration file produced through the configuration - template will be mounted to the corresponding volume. Must be a DNS_LABEL name. - The volume name must be defined in podSpec.containers[*].volumeMounts. - maxLength: 63 - pattern: ^[a-z]([a-z0-9\-]*[a-z0-9])?$ - type: string - required: - - name - - volumeName - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - switchoverSpec: - description: |- - Defines the images for the component to perform a switchover. - This overrides the image and env attributes defined in clusterDefinition.spec.componentDefs.SwitchoverSpec.CommandExecutorEnvItem. - properties: - cmdExecutorConfig: - description: Represents the configuration for the command - executor. - properties: - env: - description: A list of environment variables that will - be injected into the command execution context. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, defaults - to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults to - "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-preserve-unknown-fields: true - image: - description: Specifies the image used to execute the - command. - type: string - required: - - image - type: object - required: - - cmdExecutorConfig - type: object - systemAccountSpec: - description: |- - Defines the image for the component to connect to databases or engines. - This overrides the `image` and `env` attributes defined in clusterDefinition.spec.componentDefs.systemAccountSpec.cmdExecutorConfig. - To clear default environment settings, set systemAccountSpec.cmdExecutorConfig.env to an empty list. - properties: - cmdExecutorConfig: - description: Configures the method for obtaining the client - SDK and executing statements. - properties: - env: - description: A list of environment variables that will - be injected into the command execution context. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, defaults - to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults to - "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-preserve-unknown-fields: true - image: - description: Specifies the image used to execute the - command. - type: string - required: - - image - type: object - required: - - cmdExecutorConfig - type: object - versionsContext: - description: |- - Defines the context for container images for component versions. - This value replaces the values in clusterDefinition.spec.componentDefs.podSpec.[initContainers | containers]. - properties: - containers: - description: |- - Provides override values for ClusterDefinition.spec.componentDefs.podSpec.containers. - Typically used in scenarios such as updating application container images. - items: - description: A single application container that you want - to run within a pod. - properties: - args: - description: |- - Arguments to the entrypoint. - The container image's CMD is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - command: - description: |- - Entrypoint array. Not executed within a shell. - The container image's ENTRYPOINT is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - env: - description: |- - List of environment variables to set in the container. - Cannot be updated. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, - defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults - to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - description: |- - List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple - sources, the value associated with the last source will take precedence. - Values defined by an Env with a duplicate key will take precedence. - Cannot be updated. - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - lifecycle: - description: |- - Actions that the management system should take in response to container lifecycle events. - Cannot be updated. - properties: - postStart: - description: |- - PostStart is called immediately after a container is created. If the handler fails, - the container is terminated and restarted according to its restart policy. - Other management of the container blocks until the hook completes. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: |- - PreStop is called immediately before a container is terminated due to an - API request or management event such as liveness/startup probe failure, - preemption, resource contention, etc. The handler is not called if the - container crashes or exits. The Pod's termination grace period countdown begins before the - PreStop hook is executed. Regardless of the outcome of the handler, the - container will eventually terminate within the Pod's termination grace - period (unless delayed by finalizers). Other management of the container blocks until the hook completes - or until the termination grace period is reached. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: |- - Periodic probe of container liveness. - Container will be restarted if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - name: - description: |- - Name of the container specified as a DNS_LABEL. - Each container in a pod must have a unique name (DNS_LABEL). - Cannot be updated. - type: string - ports: - description: |- - List of ports to expose from the container. Not specifying a port here - DOES NOT prevent that port from being exposed. Any port which is - listening on the default "0.0.0.0" address inside a container will be - accessible from the network. - Modifying this array with strategic merge patch may corrupt the data. - For more information See https://github.com/kubernetes/kubernetes/issues/108255. - Cannot be updated. - items: - description: ContainerPort represents a network - port in a single container. - properties: - containerPort: - description: |- - Number of port to expose on the pod's IP address. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external - port to. - type: string - hostPort: - description: |- - Number of port to expose on the host. - If specified, this must be a valid port number, 0 < x < 65536. - If HostNetwork is specified, this must match ContainerPort. - Most containers do not need this. - format: int32 - type: integer - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - protocol: - default: TCP - description: |- - Protocol for port. Must be UDP, TCP, or SCTP. - Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: |- - Periodic probe of container service readiness. - Container will be removed from service endpoints if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - resizePolicy: - description: Resources resize policy for the container. - items: - description: ContainerResizePolicy represents resource - resize policy for the container. - properties: - resourceName: - description: |- - Name of the resource to which this resource resize policy applies. - Supported values: cpu, memory. - type: string - restartPolicy: - description: |- - Restart policy to apply when specified resource is resized. - If not specified, it defaults to NotRequired. - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Compute Resources required by this container. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - restartPolicy: - description: |- - RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, - the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: - this init container will be continually restarted on - exit until all regular containers have terminated. Once all regular - containers have completed, all init containers with restartPolicy "Always" - will be shut down. This lifecycle differs from normal init containers and - is often referred to as a "sidecar" container. Although this init - container still starts in the init container sequence, it does not wait - for the container to complete before proceeding to the next init - container. Instead, the next init container starts immediately after this - init container is started, or after any startupProbe has successfully - completed. - type: string - securityContext: - description: |- - SecurityContext defines the security options the container should be run with. - If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - properties: - allowPrivilegeEscalation: - description: |- - AllowPrivilegeEscalation controls whether a process can gain more - privileges than its parent process. This bool directly controls if - the no_new_privs flag will be set on the container process. - AllowPrivilegeEscalation is true always when the container is: - 1) run as Privileged - 2) has CAP_SYS_ADMIN - Note that this field cannot be set when spec.os.name is windows. - type: boolean - capabilities: - description: |- - The capabilities to add/drop when running containers. - Defaults to the default set of capabilities granted by the container runtime. - Note that this field cannot be set when spec.os.name is windows. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - drop: - description: Removed capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - type: object - privileged: - description: |- - Run container in privileged mode. - Processes in privileged containers are essentially equivalent to root on the host. - Defaults to false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - procMount: - description: |- - procMount denotes the type of proc mount to use for the containers. - The default is DefaultProcMount which uses the container runtime defaults for - readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. - Note that this field cannot be set when spec.os.name is windows. - type: string - readOnlyRootFilesystem: - description: |- - Whether this container has a read-only root filesystem. - Default is false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to the container. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label - that applies to the container. - type: string - role: - description: Role is a SELinux role label - that applies to the container. - type: string - type: - description: Type is a SELinux type label - that applies to the container. - type: string - user: - description: User is a SELinux user label - that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by this container. If seccomp options are - provided at both the pod & container level, the container options - override the pod options. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options from the PodSecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the - name of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: |- - StartupProbe indicates that the Pod has successfully initialized. - If specified, no other probes are executed until this completes successfully. - If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. - This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, - when it might take a long time to load data or warm a cache, than during steady-state operation. - This cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - stdin: - description: |- - Whether this container should allocate a buffer for stdin in the container runtime. If this - is not set, reads from stdin in the container will always result in EOF. - Default is false. - type: boolean - stdinOnce: - description: |- - Whether the container runtime should close the stdin channel after it has been opened by - a single attach. When stdin is true the stdin stream will remain open across multiple attach - sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - first client attaches to stdin, and then remains open and accepts data until the client disconnects, - at which time stdin is closed and remains closed until the container is restarted. If this - flag is false, a container processes that reads from stdin will never receive an EOF. - Default is false - type: boolean - terminationMessagePath: - description: |- - Optional: Path at which the file to which the container's termination message - will be written is mounted into the container's filesystem. - Message written is intended to be brief final status, such as an assertion failure message. - Will be truncated by the node if greater than 4096 bytes. The total message length across - all containers will be limited to 12kb. - Defaults to /dev/termination-log. - Cannot be updated. - type: string - terminationMessagePolicy: - description: |- - Indicate how the termination message should be populated. File will use the contents of - terminationMessagePath to populate the container status message on both success and failure. - FallbackToLogsOnError will use the last chunk of container log output if the termination - message file is empty and the container exited with an error. - The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - Defaults to File. - Cannot be updated. - type: string - tty: - description: |- - Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices - to be used by the container. - items: - description: volumeDevice describes a mapping of - a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside of - the container that the device will be mapped - to. - type: string - name: - description: name must match the name of a persistentVolumeClaim - in the pod - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - description: |- - Pod volumes to mount into the container's filesystem. - Cannot be updated. - items: - description: VolumeMount describes a mounting of - a Volume within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - workingDir: - description: |- - Container's working directory. - If not specified, the container runtime's default will be used, which - might be configured in the container image. - Cannot be updated. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - x-kubernetes-preserve-unknown-fields: true - initContainers: - description: |- - Provides override values for ClusterDefinition.spec.componentDefs.podSpec.initContainers. - Typically used in scenarios such as updating application container images. - items: - description: A single application container that you want - to run within a pod. - properties: - args: - description: |- - Arguments to the entrypoint. - The container image's CMD is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - command: - description: |- - Entrypoint array. Not executed within a shell. - The container image's ENTRYPOINT is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - env: - description: |- - List of environment variables to set in the container. - Cannot be updated. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, - defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults - to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - description: |- - List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple - sources, the value associated with the last source will take precedence. - Values defined by an Env with a duplicate key will take precedence. - Cannot be updated. - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - lifecycle: - description: |- - Actions that the management system should take in response to container lifecycle events. - Cannot be updated. - properties: - postStart: - description: |- - PostStart is called immediately after a container is created. If the handler fails, - the container is terminated and restarted according to its restart policy. - Other management of the container blocks until the hook completes. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: |- - PreStop is called immediately before a container is terminated due to an - API request or management event such as liveness/startup probe failure, - preemption, resource contention, etc. The handler is not called if the - container crashes or exits. The Pod's termination grace period countdown begins before the - PreStop hook is executed. Regardless of the outcome of the handler, the - container will eventually terminate within the Pod's termination grace - period (unless delayed by finalizers). Other management of the container blocks until the hook completes - or until the termination grace period is reached. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: |- - Periodic probe of container liveness. - Container will be restarted if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - name: - description: |- - Name of the container specified as a DNS_LABEL. - Each container in a pod must have a unique name (DNS_LABEL). - Cannot be updated. - type: string - ports: - description: |- - List of ports to expose from the container. Not specifying a port here - DOES NOT prevent that port from being exposed. Any port which is - listening on the default "0.0.0.0" address inside a container will be - accessible from the network. - Modifying this array with strategic merge patch may corrupt the data. - For more information See https://github.com/kubernetes/kubernetes/issues/108255. - Cannot be updated. - items: - description: ContainerPort represents a network - port in a single container. - properties: - containerPort: - description: |- - Number of port to expose on the pod's IP address. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external - port to. - type: string - hostPort: - description: |- - Number of port to expose on the host. - If specified, this must be a valid port number, 0 < x < 65536. - If HostNetwork is specified, this must match ContainerPort. - Most containers do not need this. - format: int32 - type: integer - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - protocol: - default: TCP - description: |- - Protocol for port. Must be UDP, TCP, or SCTP. - Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: |- - Periodic probe of container service readiness. - Container will be removed from service endpoints if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - resizePolicy: - description: Resources resize policy for the container. - items: - description: ContainerResizePolicy represents resource - resize policy for the container. - properties: - resourceName: - description: |- - Name of the resource to which this resource resize policy applies. - Supported values: cpu, memory. - type: string - restartPolicy: - description: |- - Restart policy to apply when specified resource is resized. - If not specified, it defaults to NotRequired. - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Compute Resources required by this container. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - restartPolicy: - description: |- - RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, - the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: - this init container will be continually restarted on - exit until all regular containers have terminated. Once all regular - containers have completed, all init containers with restartPolicy "Always" - will be shut down. This lifecycle differs from normal init containers and - is often referred to as a "sidecar" container. Although this init - container still starts in the init container sequence, it does not wait - for the container to complete before proceeding to the next init - container. Instead, the next init container starts immediately after this - init container is started, or after any startupProbe has successfully - completed. - type: string - securityContext: - description: |- - SecurityContext defines the security options the container should be run with. - If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - properties: - allowPrivilegeEscalation: - description: |- - AllowPrivilegeEscalation controls whether a process can gain more - privileges than its parent process. This bool directly controls if - the no_new_privs flag will be set on the container process. - AllowPrivilegeEscalation is true always when the container is: - 1) run as Privileged - 2) has CAP_SYS_ADMIN - Note that this field cannot be set when spec.os.name is windows. - type: boolean - capabilities: - description: |- - The capabilities to add/drop when running containers. - Defaults to the default set of capabilities granted by the container runtime. - Note that this field cannot be set when spec.os.name is windows. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - drop: - description: Removed capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - type: object - privileged: - description: |- - Run container in privileged mode. - Processes in privileged containers are essentially equivalent to root on the host. - Defaults to false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - procMount: - description: |- - procMount denotes the type of proc mount to use for the containers. - The default is DefaultProcMount which uses the container runtime defaults for - readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. - Note that this field cannot be set when spec.os.name is windows. - type: string - readOnlyRootFilesystem: - description: |- - Whether this container has a read-only root filesystem. - Default is false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to the container. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label - that applies to the container. - type: string - role: - description: Role is a SELinux role label - that applies to the container. - type: string - type: - description: Type is a SELinux type label - that applies to the container. - type: string - user: - description: User is a SELinux user label - that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by this container. If seccomp options are - provided at both the pod & container level, the container options - override the pod options. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options from the PodSecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the - name of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: |- - StartupProbe indicates that the Pod has successfully initialized. - If specified, no other probes are executed until this completes successfully. - If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. - This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, - when it might take a long time to load data or warm a cache, than during steady-state operation. - This cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - stdin: - description: |- - Whether this container should allocate a buffer for stdin in the container runtime. If this - is not set, reads from stdin in the container will always result in EOF. - Default is false. - type: boolean - stdinOnce: - description: |- - Whether the container runtime should close the stdin channel after it has been opened by - a single attach. When stdin is true the stdin stream will remain open across multiple attach - sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - first client attaches to stdin, and then remains open and accepts data until the client disconnects, - at which time stdin is closed and remains closed until the container is restarted. If this - flag is false, a container processes that reads from stdin will never receive an EOF. - Default is false - type: boolean - terminationMessagePath: - description: |- - Optional: Path at which the file to which the container's termination message - will be written is mounted into the container's filesystem. - Message written is intended to be brief final status, such as an assertion failure message. - Will be truncated by the node if greater than 4096 bytes. The total message length across - all containers will be limited to 12kb. - Defaults to /dev/termination-log. - Cannot be updated. - type: string - terminationMessagePolicy: - description: |- - Indicate how the termination message should be populated. File will use the contents of - terminationMessagePath to populate the container status message on both success and failure. - FallbackToLogsOnError will use the last chunk of container log output if the termination - message file is empty and the container exited with an error. - The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - Defaults to File. - Cannot be updated. - type: string - tty: - description: |- - Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices - to be used by the container. - items: - description: volumeDevice describes a mapping of - a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside of - the container that the device will be mapped - to. - type: string - name: - description: name must match the name of a persistentVolumeClaim - in the pod - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - description: |- - Pod volumes to mount into the container's filesystem. - Cannot be updated. - items: - description: VolumeMount describes a mounting of - a Volume within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - workingDir: - description: |- - Container's working directory. - If not specified, the container runtime's default will be used, which - might be configured in the container image. - Cannot be updated. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - componentDefRef - - versionsContext - type: object - minItems: 1 - type: array - x-kubernetes-list-map-keys: - - componentDefRef - x-kubernetes-list-type: map - required: - - clusterDefinitionRef - - componentVersions - type: object - status: - description: |- - ClusterVersionStatus defines the observed state of ClusterVersion. - - - Deprecated since v0.9. - This struct is maintained for backward compatibility and its use is discouraged. - properties: - clusterDefGeneration: - description: The generation number of the ClusterDefinition that is - currently being referenced. - format: int64 - type: integer - message: - description: Provides additional information about the current phase. - type: string - observedGeneration: - description: The generation number that has been observed by the controller. - format: int64 - type: integer - phase: - description: The current phase of the ClusterVersion. - enum: - - Available - - Unavailable - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/config/crd/bases/apps.kubeblocks.io_configconstraints.yaml b/config/crd/bases/apps.kubeblocks.io_configconstraints.yaml index 50a118ff6c81..ad8198789bf4 100644 --- a/config/crd/bases/apps.kubeblocks.io_configconstraints.yaml +++ b/config/crd/bases/apps.kubeblocks.io_configconstraints.yaml @@ -758,7 +758,7 @@ spec: phase: description: |- Specifies the status of the configuration template. - When set to CCAvailablePhase, the ConfigConstraint can be referenced by ClusterDefinition or ClusterVersion. + When set to CCAvailablePhase, the ConfigConstraint can be referenced by ClusterDefinition. enum: - Available - Unavailable @@ -1418,7 +1418,7 @@ spec: phase: description: |- Specifies the status of the configuration template. - When set to CCAvailablePhase, the ConfigConstraint can be referenced by ClusterDefinition or ClusterVersion. + When set to CCAvailablePhase, the ConfigConstraint can be referenced by ClusterDefinition. enum: - Available - Unavailable diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 1a5378fdb522..6feecab5b323 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -5,7 +5,6 @@ resources: - bases/apps.kubeblocks.io_backuppolicytemplates.yaml - bases/apps.kubeblocks.io_clusters.yaml - bases/apps.kubeblocks.io_clusterdefinitions.yaml -- bases/apps.kubeblocks.io_clusterversions.yaml - bases/apps.kubeblocks.io_configconstraints.yaml - bases/apps.kubeblocks.io_opsrequests.yaml - bases/dataprotection.kubeblocks.io_actionsets.yaml @@ -32,7 +31,6 @@ patchesStrategicMerge: # patches here are for enabling the conversion webhook for each CRD #- patches/webhook_in_clusters.yaml #- patches/webhook_in_clusterdefinitions.yaml -#- patches/webhook_in_clusterversions.yaml #- patches/webhook_in_backuptools.yaml #- patches/webhook_in_backuppolicies.yaml #- patches/webhook_in_backups.yaml @@ -60,7 +58,6 @@ patchesStrategicMerge: # patches here are for enabling the CA injection for each CRD #- patches/cainjection_in_clusters.yaml #- patches/cainjection_in_clusterdefinitions.yaml -#- patches/cainjection_in_clusterversions.yaml #- patches/cainjection_in_backuptools.yaml #- patches/cainjection_in_backuppolicies.yaml #- patches/cainjection_in_backups.yaml diff --git a/config/crd/patches/cainjection_in_apps_clusterversions.yaml b/config/crd/patches/cainjection_in_apps_clusterversions.yaml deleted file mode 100644 index 15da1d8d9ab3..000000000000 --- a/config/crd/patches/cainjection_in_apps_clusterversions.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# The following patch adds a directive for certmanager to inject CA into the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) - name: clusterversions.apps.kubeblocks.io diff --git a/config/crd/patches/webhook_in_apps_clusterversions.yaml b/config/crd/patches/webhook_in_apps_clusterversions.yaml deleted file mode 100644 index 4851527b361f..000000000000 --- a/config/crd/patches/webhook_in_apps_clusterversions.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# The following patch enables a conversion webhook for the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: clusterversions.apps.kubeblocks.io -spec: - conversion: - strategy: Webhook - webhook: - clientConfig: - service: - namespace: system - name: webhook-service - path: /convert - conversionReviewVersions: - - v1 diff --git a/config/rbac/apps_clusterversion_editor_role.yaml b/config/rbac/apps_clusterversion_editor_role.yaml deleted file mode 100644 index 5e3973b4c022..000000000000 --- a/config/rbac/apps_clusterversion_editor_role.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# permissions for end users to edit clusterversions. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: clusterversion-editor-role -rules: -- apiGroups: - - apps.kubeblocks.io - resources: - - clusterversions - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - apps.kubeblocks.io - resources: - - clusterversions/status - verbs: - - get diff --git a/config/rbac/apps_clusterversion_viewer_role.yaml b/config/rbac/apps_clusterversion_viewer_role.yaml deleted file mode 100644 index c8066a7a4b2b..000000000000 --- a/config/rbac/apps_clusterversion_viewer_role.yaml +++ /dev/null @@ -1,20 +0,0 @@ -# permissions for end users to view clusterversions. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: clusterversion-viewer-role -rules: -- apiGroups: - - apps.kubeblocks.io - resources: - - clusterversions - verbs: - - get - - list - - watch -- apiGroups: - - apps.kubeblocks.io - resources: - - clusterversions/status - verbs: - - get diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 8f6b142af93b..aac6ca93aabf 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -122,32 +122,6 @@ rules: - get - patch - update -- apiGroups: - - apps.kubeblocks.io - resources: - - clusterversions - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - apps.kubeblocks.io - resources: - - clusterversions/finalizers - verbs: - - update -- apiGroups: - - apps.kubeblocks.io - resources: - - clusterversions/status - verbs: - - get - - patch - - update - apiGroups: - apps.kubeblocks.io resources: diff --git a/config/samples/ops/mysql_clusterversion_upgrade.yaml b/config/samples/ops/mysql_clusterversion_upgrade.yaml deleted file mode 100644 index 1c1fd3c83cf4..000000000000 --- a/config/samples/ops/mysql_clusterversion_upgrade.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: apps.kubeblocks.io/v1alpha1 -kind: ClusterVersion -metadata: - name: wesql-8.0.32 -spec: - clusterDefinitionRef: wesql - components: - - type: replicasets - versionsContext: - containers: - - name: mysql - image: docker.io/apecloud/apecloud-mysql-server:latest diff --git a/controllers/apps/cluster_controller_test.go b/controllers/apps/cluster_controller_test.go index 57b4a2d07200..e27356d2c56f 100644 --- a/controllers/apps/cluster_controller_test.go +++ b/controllers/apps/cluster_controller_test.go @@ -49,7 +49,6 @@ import ( var _ = Describe("Cluster Controller", func() { const ( clusterDefName = "test-clusterdef" - clusterVersionName = "test-clusterversion" compDefName = "test-compdef" compVersionName = "test-compversion" clusterName = "test-cluster" // this become cluster prefix name if used with testapps.NewClusterFactory().WithRandomName() @@ -62,14 +61,13 @@ var _ = Describe("Cluster Controller", func() { ) var ( - clusterDefObj *appsv1alpha1.ClusterDefinition - clusterVersionObj *appsv1alpha1.ClusterVersion - compDefObj *appsv1alpha1.ComponentDefinition - compVersionObj *appsv1alpha1.ComponentVersion - clusterObj *appsv1alpha1.Cluster - clusterKey types.NamespacedName - allSettings map[string]interface{} - defaultTopology = appsv1alpha1.ClusterTopology{ + clusterDefObj *appsv1alpha1.ClusterDefinition + compDefObj *appsv1alpha1.ComponentDefinition + compVersionObj *appsv1alpha1.ComponentVersion + clusterObj *appsv1alpha1.Cluster + clusterKey types.NamespacedName + allSettings map[string]interface{} + defaultTopology = appsv1alpha1.ClusterTopology{ Name: "default", Default: true, Components: []appsv1alpha1.ClusterTopologyComponent{ @@ -90,7 +88,6 @@ var _ = Describe("Cluster Controller", func() { resetTestContext := func() { clusterDefObj = nil - clusterVersionObj = nil clusterObj = nil resetViperCfg() } @@ -103,7 +100,7 @@ var _ = Describe("Cluster Controller", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest mocked objects @@ -146,13 +143,6 @@ var _ = Describe("Cluster Controller", func() { Create(&testCtx). GetObject() - By("Create a clusterVersion obj") - clusterVersionObj = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefObj.GetName()). - AddComponentVersion(consensusCompDefName). - AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - Create(&testCtx). - GetObject() - By("Create a componentDefinition obj") compDefObj = testapps.NewComponentDefinitionFactory(compDefName). WithRandomName(). @@ -161,7 +151,7 @@ var _ = Describe("Cluster Controller", func() { GetObject() By("Create a bpt obj") - createBackupPolicyTpl(clusterDefObj, compDefObj.Name, clusterVersionName) + createBackupPolicyTpl(clusterDefObj, compDefObj.Name) By("Create a componentVersion obj") compVersionObj = testapps.NewComponentVersionFactory(compVersionName). @@ -200,11 +190,6 @@ var _ = Describe("Cluster Controller", func() { g.Expect(clusterDef.Status.ObservedGeneration).Should(Equal(clusterDef.Generation)) g.Expect(clusterDef.Status.Phase).Should(Equal(appsv1alpha1.AvailablePhase)) })).Should(Succeed()) - Eventually(testapps.CheckObj(&testCtx, client.ObjectKeyFromObject(clusterVersionObj), - func(g Gomega, clusterVersion *appsv1alpha1.ClusterVersion) { - g.Expect(clusterVersion.Status.ObservedGeneration).Should(Equal(clusterVersion.Generation)) - g.Expect(clusterVersion.Status.Phase).Should(Equal(appsv1alpha1.AvailablePhase)) - })).Should(Succeed()) Eventually(testapps.CheckObj(&testCtx, client.ObjectKeyFromObject(compDefObj), func(g Gomega, compDef *appsv1alpha1.ComponentDefinition) { g.Expect(compDef.Status.ObservedGeneration).Should(Equal(compDef.Generation)) @@ -232,8 +217,8 @@ var _ = Describe("Cluster Controller", func() { } } - createClusterObjNoWait := func(clusterDefName, clusterVerName string, processor ...func(*testapps.MockClusterFactory)) { - f := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefName, clusterVerName). + createClusterObjNoWait := func(clusterDefName string, processor ...func(*testapps.MockClusterFactory)) { + f := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefName). WithRandomName() for _, p := range processor { if p != nil { @@ -287,7 +272,7 @@ var _ = Describe("Cluster Controller", func() { createClusterObj := func(compName, compDefName string, processor func(*testapps.MockClusterFactory)) { By("Creating a cluster with new component definition") - createClusterObjNoWait("", "", componentProcessorWrapper(false, compName, compDefName, processor)) + createClusterObjNoWait("", componentProcessorWrapper(false, compName, compDefName, processor)) By("Waiting for the cluster enter Creating phase") Eventually(testapps.GetClusterObservedGeneration(&testCtx, clusterKey)).Should(BeEquivalentTo(1)) @@ -304,7 +289,7 @@ var _ = Describe("Cluster Controller", func() { createClusterObjWithTopology := func(topology, compName string, processor func(*testapps.MockClusterFactory)) { By("Creating a cluster with new component definition") setTopology := func(f *testapps.MockClusterFactory) { f.SetTopology(topology) } - createClusterObjNoWait(clusterDefObj.Name, "", componentProcessorWrapper(false, compName, "", setTopology, processor)) + createClusterObjNoWait(clusterDefObj.Name, componentProcessorWrapper(false, compName, "", setTopology, processor)) By("Waiting for the cluster enter Creating phase") Eventually(testapps.GetClusterObservedGeneration(&testCtx, clusterKey)).Should(BeEquivalentTo(1)) @@ -320,7 +305,7 @@ var _ = Describe("Cluster Controller", func() { createLegacyClusterObj := func(compName, compDefName string, processor func(*testapps.MockClusterFactory)) { By("Creating a cluster") - createClusterObjNoWait(clusterDefObj.Name, clusterVersionObj.Name, componentProcessorWrapper(true, compName, compDefName, processor)) + createClusterObjNoWait(clusterDefObj.Name, componentProcessorWrapper(true, compName, compDefName, processor)) By("Waiting for the cluster enter Creating phase") Eventually(testapps.GetClusterObservedGeneration(&testCtx, clusterKey)).Should(BeEquivalentTo(1)) @@ -336,7 +321,7 @@ var _ = Describe("Cluster Controller", func() { createClusterObjWithSharding := func(compTplName, compDefName string, processor func(*testapps.MockClusterFactory)) { By("Creating a cluster with new component definition") - createClusterObjNoWait("", "", shardingComponentProcessorWrapper(false, compTplName, compDefName, processor)) + createClusterObjNoWait("", shardingComponentProcessorWrapper(false, compTplName, compDefName, processor)) By("Waiting for the cluster enter Creating phase") Eventually(testapps.GetClusterObservedGeneration(&testCtx, clusterKey)).Should(BeEquivalentTo(1)) @@ -366,8 +351,7 @@ var _ = Describe("Cluster Controller", func() { createLegacyClusterObjWithSharding := func(compTplName, compDefName string, processor func(*testapps.MockClusterFactory)) { By("Creating a cluster") - createClusterObjNoWait(clusterDefObj.Name, clusterVersionObj.Name, - shardingComponentProcessorWrapper(true, compTplName, compDefName, processor)) + createClusterObjNoWait(clusterDefObj.Name, shardingComponentProcessorWrapper(true, compTplName, compDefName, processor)) By("Waiting for the cluster enter Creating phase") Eventually(testapps.GetClusterObservedGeneration(&testCtx, clusterKey)).Should(BeEquivalentTo(1)) @@ -384,7 +368,7 @@ var _ = Describe("Cluster Controller", func() { createClusterObjWithMultipleTemplates := func(compName, compDefName string, processor func(*testapps.MockClusterFactory)) { By("Creating a cluster with new component definition") - createClusterObjNoWait("", "", multipleTemplateComponentProcessorWrapper(compName, compDefName, processor)) + createClusterObjNoWait("", multipleTemplateComponentProcessorWrapper(compName, compDefName, processor)) By("Waiting for the cluster enter Creating phase") Eventually(testapps.GetClusterObservedGeneration(&testCtx, clusterKey)).Should(BeEquivalentTo(1)) @@ -408,9 +392,8 @@ var _ = Describe("Cluster Controller", func() { })).Should(Succeed()) } - testClusterWithoutClusterVersion := func(compName, compDefName string) { - By("creating a cluster w/o cluster version") - clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name, ""). + testCluster := func(compName, compDefName string) { + clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). AddComponent(consensusCompName, consensusCompDefName).SetReplicas(3). WithRandomName(). Create(&testCtx). @@ -484,7 +467,7 @@ var _ = Describe("Cluster Controller", func() { testClusterComponentScaleIn := func(compName, compDefName string) { By("creating and checking a cluster with multi component") - clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name, ""). + clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). AddComponent(compName, compDefName).SetReplicas(3). AddComponent(multiConsensusCompName, compDefName).SetReplicas(3). WithRandomName(). @@ -1096,8 +1079,8 @@ var _ = Describe("Cluster Controller", func() { cleanEnv() }) - It("create cluster w/o cluster version", func() { - testClusterWithoutClusterVersion(consensusCompName, consensusCompDefName) + It("create cluster", func() { + testCluster(consensusCompName, consensusCompDefName) }) It("create cluster with legacy component", func() { @@ -1219,8 +1202,7 @@ var _ = Describe("Cluster Controller", func() { It("test cluster conditions when cluster definition non-exist", func() { By("create a cluster with cluster definition non-exist") mockCompDefName := fmt.Sprintf("%s-%s", consensusCompDefName, testCtx.GetRandomStr()) - createClusterObjNoWait(clusterDefObj.Name, clusterVersionObj.Name, - componentProcessorWrapper(true, consensusCompName, mockCompDefName)) + createClusterObjNoWait(clusterDefObj.Name, componentProcessorWrapper(true, consensusCompName, mockCompDefName)) By("check conditions") Eventually(testapps.CheckObj(&testCtx, clusterKey, func(g Gomega, cluster *appsv1alpha1.Cluster) { @@ -1230,53 +1212,6 @@ var _ = Describe("Cluster Controller", func() { g.Expect(condition.Reason).Should(BeEquivalentTo(ReasonPreCheckFailed)) })).Should(Succeed()) }) - - It("test cluster conditions when cluster version unavailable", func() { - By("mock cluster version unavailable") - mockCompDefName := "random-comp-def" - clusterVersionKey := client.ObjectKeyFromObject(clusterVersionObj) - Expect(testapps.GetAndChangeObj(&testCtx, clusterVersionKey, func(clusterVersion *appsv1alpha1.ClusterVersion) { - for i, comp := range clusterVersion.Spec.ComponentVersions { - if comp.ComponentDefRef == consensusCompDefName { - clusterVersion.Spec.ComponentVersions[i].ComponentDefRef = mockCompDefName - break - } - } - })()).ShouldNot(HaveOccurred()) - Eventually(testapps.CheckObj(&testCtx, clusterVersionKey, func(g Gomega, clusterVersion *appsv1alpha1.ClusterVersion) { - g.Expect(clusterVersion.Status.Phase).Should(Equal(appsv1alpha1.UnavailablePhase)) - })).Should(Succeed()) - - By("create a cluster with the unavailable cluster version") - createClusterObjNoWait(clusterDefObj.Name, clusterVersionObj.Name, - componentProcessorWrapper(true, consensusCompName, consensusCompDefName)) - - By("expect the cluster provisioning condition as pre-check failed") - Eventually(testapps.CheckObj(&testCtx, clusterKey, func(g Gomega, cluster *appsv1alpha1.Cluster) { - g.Expect(cluster.Status.ObservedGeneration).Should(BeZero()) - condition := meta.FindStatusCondition(cluster.Status.Conditions, appsv1alpha1.ConditionTypeProvisioningStarted) - g.Expect(condition).ShouldNot(BeNil()) - g.Expect(condition.Reason).Should(BeEquivalentTo(ReasonPreCheckFailed)) - })).Should(Succeed()) - - By("reset cluster version to Available") - Expect(testapps.GetAndChangeObj(&testCtx, clusterVersionKey, func(clusterVersion *appsv1alpha1.ClusterVersion) { - for i, comp := range clusterVersion.Spec.ComponentVersions { - if comp.ComponentDefRef == mockCompDefName { - clusterVersion.Spec.ComponentVersions[i].ComponentDefRef = consensusCompDefName - break - } - } - })()).ShouldNot(HaveOccurred()) - Eventually(testapps.CheckObj(&testCtx, clusterVersionKey, func(g Gomega, clusterVersion *appsv1alpha1.ClusterVersion) { - g.Expect(clusterVersion.Status.Phase).Should(Equal(appsv1alpha1.AvailablePhase)) - })).Should(Succeed()) - - By("expect the cluster phase transit to Creating") - Eventually(testapps.CheckObj(&testCtx, clusterKey, func(g Gomega, cluster *appsv1alpha1.Cluster) { - g.Expect(cluster.Status.Phase).Should(Equal(appsv1alpha1.CreatingClusterPhase)) - })).Should(Succeed()) - }) }) Context("cluster with backup", func() { @@ -1294,8 +1229,7 @@ var _ = Describe("Cluster Controller", func() { createClusterWithBackup := func(backup *appsv1alpha1.ClusterBackup) { By("Creating a cluster") - clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDefObj.Name, clusterVersionObj.Name). + clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). AddComponent(compName, compDefName).WithRandomName().SetBackup(backup). Create(&testCtx).GetObject() clusterKey = client.ObjectKeyFromObject(clusterObj) @@ -1404,17 +1338,6 @@ var _ = Describe("Cluster Controller", func() { g.Expect(*policy.Spec.BackupRepoName).Should(BeEquivalentTo(backup.RepoName)) } g.Expect(policy.Spec.BackupMethods).ShouldNot(BeEmpty()) - // expect for image tag env in backupMethod - var existImageTagEnv bool - for _, v := range policy.Spec.BackupMethods { - for _, e := range v.Env { - if e.Name == testapps.EnvKeyImageTag && e.Value == testapps.DefaultImageTag { - existImageTagEnv = true - break - } - } - } - g.Expect(existImageTagEnv).Should(BeTrue()) } By("checking backup policy") @@ -1561,7 +1484,7 @@ var _ = Describe("Cluster Controller", func() { }) }) -func createBackupPolicyTpl(clusterDefObj *appsv1alpha1.ClusterDefinition, compDef string, mappingClusterVersions ...string) { +func createBackupPolicyTpl(clusterDefObj *appsv1alpha1.ClusterDefinition, compDef string) { By("create actionSet") fakeActionSet(clusterDefObj.Name) @@ -1573,7 +1496,7 @@ func createBackupPolicyTpl(clusterDefObj *appsv1alpha1.ClusterDefinition, compDe ttl := "7d" for _, v := range clusterDefObj.Spec.ComponentDefs { bpt = bpt.AddBackupPolicy(v.Name). - AddBackupMethod(backupMethodName, false, actionSetName, mappingClusterVersions...). + AddBackupMethod(backupMethodName, false, actionSetName). SetComponentDef(compDef). SetBackupMethodVolumeMounts("data", "/data"). AddBackupMethod(vsBackupMethodName, true, ""). diff --git a/controllers/apps/cluster_plan_builder.go b/controllers/apps/cluster_plan_builder.go index 55398eba8713..898743ee14ab 100644 --- a/controllers/apps/cluster_plan_builder.go +++ b/controllers/apps/cluster_plan_builder.go @@ -64,7 +64,6 @@ type clusterTransformContext struct { Cluster *appsv1alpha1.Cluster OrigCluster *appsv1alpha1.Cluster ClusterDef *appsv1alpha1.ClusterDefinition - ClusterVer *appsv1alpha1.ClusterVersion ComponentDefs map[string]*appsv1alpha1.ComponentDefinition // ComponentSpecs includes all cluster component specs generated from ComponentSpecs and ShardingSpecs ComponentSpecs []*appsv1alpha1.ClusterComponentSpec diff --git a/controllers/apps/cluster_plan_builder_test.go b/controllers/apps/cluster_plan_builder_test.go index bd1444664c5a..6699ff5875ef 100644 --- a/controllers/apps/cluster_plan_builder_test.go +++ b/controllers/apps/cluster_plan_builder_test.go @@ -35,9 +35,8 @@ import ( var _ = Describe("cluster plan builder test", func() { const ( - clusterDefName = "test-clusterdef" - clusterVersionName = "test-clusterversion" - clusterName = "test-cluster" // this become cluster prefix name if used with testapps.NewClusterFactory().WithRandomName() + clusterDefName = "test-clusterdef" + clusterName = "test-cluster" // this become cluster prefix name if used with testapps.NewClusterFactory().WithRandomName() ) // Cleanups @@ -48,7 +47,7 @@ var _ = Describe("cluster plan builder test", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest mocked objects @@ -76,8 +75,9 @@ var _ = Describe("cluster plan builder test", func() { Context("test init", func() { It("should init successfully", func() { - clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDefName, clusterVersionName).WithRandomName().GetObject() + clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefName). + WithRandomName(). + GetObject() Expect(testCtx.Cli.Create(testCtx.Ctx, clusterObj)).Should(Succeed()) clusterKey := client.ObjectKeyFromObject(clusterObj) Eventually(testapps.CheckObjExists(&testCtx, clusterKey, &appsv1alpha1.Cluster{}, true)).Should(Succeed()) diff --git a/controllers/apps/clusterdefinition_controller.go b/controllers/apps/clusterdefinition_controller.go index 13bbfb067e17..40a3f924501b 100644 --- a/controllers/apps/clusterdefinition_controller.go +++ b/controllers/apps/clusterdefinition_controller.go @@ -50,8 +50,6 @@ type ClusterDefinitionReconciler struct { Recorder record.EventRecorder } -var clusterDefUpdateHandlers = map[string]func(client client.Client, ctx context.Context, clusterDef *appsv1alpha1.ClusterDefinition) error{} - // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. // @@ -107,10 +105,10 @@ func (r *ClusterDefinitionReconciler) deletionHandler(rctx intctrlutil.RequestCt return func() (*ctrl.Result, error) { recordEvent := func() { r.Recorder.Event(clusterDef, corev1.EventTypeWarning, "ExistsReferencedResources", - "cannot be deleted because of existing referencing Cluster or ClusterVersion") + "cannot be deleted because of existing referencing Cluster") } if res, err := intctrlutil.ValidateReferenceCR(rctx, r.Client, clusterDef, constant.ClusterDefLabelKey, - recordEvent, &appsv1alpha1.ClusterList{}, &appsv1alpha1.ClusterVersionList{}); res != nil || err != nil { + recordEvent, &appsv1alpha1.ClusterList{}); res != nil || err != nil { return res, err } return nil, r.deleteExternalResources(rctx, clusterDef) @@ -171,13 +169,6 @@ func (r *ClusterDefinitionReconciler) reconcile(rctx intctrlutil.RequestCtx, clu res, err1 := intctrlutil.RequeueAfter(time.Second, rctx.Log, err.Error()) return &res, err1 } - - for _, handler := range clusterDefUpdateHandlers { - if err := handler(r.Client, rctx.Ctx, clusterDef); err != nil { - res, err1 := intctrlutil.CheckedRequeueWithError(err, rctx.Log, "") - return &res, err1 - } - } return nil, nil } diff --git a/controllers/apps/clusterdefinition_controller_test.go b/controllers/apps/clusterdefinition_controller_test.go index 9640f541e3ad..454f95aa46c7 100644 --- a/controllers/apps/clusterdefinition_controller_test.go +++ b/controllers/apps/clusterdefinition_controller_test.go @@ -41,7 +41,6 @@ import ( var _ = Describe("ClusterDefinition Controller", func() { const ( clusterDefName = "test-clusterdef" - clusterVersionName = "test-clusterversion" compDefinitionName = "test-component-definition" statefulCompDefName = "replicasets" @@ -51,8 +50,7 @@ var _ = Describe("ClusterDefinition Controller", func() { ) var ( - clusterDefObj *appsv1alpha1.ClusterDefinition - clusterVersionObj *appsv1alpha1.ClusterVersion + clusterDefObj *appsv1alpha1.ClusterDefinition ) cleanEnv := func() { @@ -67,7 +65,6 @@ var _ = Describe("ClusterDefinition Controller", func() { // resources should be released in following order // non-namespaced - testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, intctrlutil.ClusterVersionSignature, true, ml) testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, intctrlutil.ClusterDefinitionSignature, true, ml) testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, intctrlutil.ComponentDefinitionSignature, true, ml) testapps.ClearResources(&testCtx, intctrlutil.ConfigConstraintSignature, ml) @@ -98,55 +95,6 @@ var _ = Describe("ClusterDefinition Controller", func() { return cm } - Context("with no ConfigSpec", func() { - BeforeEach(func() { - By("Create a clusterDefinition obj") - clusterDefObj = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatefulMySQLComponent, statefulCompDefName). - Create(&testCtx).GetObject() - - By("Create a clusterVersion obj") - clusterVersionObj = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefObj.GetName()). - AddComponentVersion(statefulCompDefName).AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - Create(&testCtx).GetObject() - }) - - It("should update status of clusterVersion at the same time when updating clusterDefinition", func() { - By("Check reconciled finalizer and status of ClusterDefinition") - var cdGen int64 - Eventually(testapps.CheckObj(&testCtx, client.ObjectKeyFromObject(clusterDefObj), - func(g Gomega, cd *appsv1alpha1.ClusterDefinition) { - g.Expect(cd.Finalizers).NotTo(BeEmpty()) - g.Expect(cd.Status.ObservedGeneration).To(BeEquivalentTo(1)) - cdGen = cd.Status.ObservedGeneration - })).Should(Succeed()) - - By("Check reconciled finalizer and status of ClusterVersion") - Eventually(testapps.CheckObj(&testCtx, client.ObjectKeyFromObject(clusterVersionObj), - func(g Gomega, cv *appsv1alpha1.ClusterVersion) { - g.Expect(cv.Finalizers).NotTo(BeEmpty()) - g.Expect(cv.Status.ObservedGeneration).To(BeEquivalentTo(1)) - g.Expect(cv.Status.ClusterDefGeneration).To(Equal(cdGen)) - })).Should(Succeed()) - - By("updating clusterDefinition's spec which then update clusterVersion's status") - Eventually(testapps.GetAndChangeObj(&testCtx, client.ObjectKeyFromObject(clusterDefObj), - func(cd *appsv1alpha1.ClusterDefinition) { - cd.Spec.ConnectionCredential["root"] = "password" - })).Should(Succeed()) - - By("Check ClusterVersion.Status as updated") - Eventually(testapps.CheckObj(&testCtx, client.ObjectKeyFromObject(clusterVersionObj), - func(g Gomega, cv *appsv1alpha1.ClusterVersion) { - g.Expect(cv.Status.Phase).To(Equal(appsv1alpha1.AvailablePhase)) - g.Expect(cv.Status.Message).To(Equal("")) - g.Expect(cv.Status.ClusterDefGeneration > cdGen).To(BeTrue()) - })).Should(Succeed()) - - // TODO: update components to break @validateClusterVersion, and transit ClusterVersion.Status.Phase to UnavailablePhase - }) - }) - Context("with ConfigSpec", func() { BeforeEach(func() { By("Create a clusterDefinition obj") @@ -154,11 +102,6 @@ var _ = Describe("ClusterDefinition Controller", func() { AddComponentDef(testapps.StatefulMySQLComponent, statefulCompDefName). AddConfigTemplate(cmName, cmName, cmName, testCtx.DefaultNamespace, configVolumeName). Create(&testCtx).GetObject() - - By("Create a clusterVersion obj") - clusterVersionObj = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefObj.GetName()). - AddComponentVersion(statefulCompDefName).AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - Create(&testCtx).GetObject() }) It("should stop proceeding the status of clusterDefinition if configmap is invalid or doesn't exist", func() { diff --git a/controllers/apps/clusterversion_controller.go b/controllers/apps/clusterversion_controller.go deleted file mode 100644 index 4513a4c69d8d..000000000000 --- a/controllers/apps/clusterversion_controller.go +++ /dev/null @@ -1,229 +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 apps - -import ( - "context" - "fmt" - "strings" - "time" - - "golang.org/x/exp/slices" - corev1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/labels" - k8sruntime "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - "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/log" - - appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" - appsconfig "github.com/apecloud/kubeblocks/controllers/apps/configuration" - "github.com/apecloud/kubeblocks/pkg/constant" - intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" -) - -// +kubebuilder:rbac:groups=apps.kubeblocks.io,resources=clusterversions,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=apps.kubeblocks.io,resources=clusterversions/status,verbs=get;update;patch -// +kubebuilder:rbac:groups=apps.kubeblocks.io,resources=clusterversions/finalizers,verbs=update - -// ClusterVersionReconciler reconciles a ClusterVersion object -type ClusterVersionReconciler struct { - client.Client - Scheme *k8sruntime.Scheme - Recorder record.EventRecorder -} - -func init() { - clusterDefUpdateHandlers["clusterVersion"] = clusterVersionUpdateHandler -} - -// Reconcile is part of the main kubernetes reconciliation loop which aims to -// move the current state of the cluster closer to the desired state. -// -// For more details, check Reconcile and its Result here: -// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.14.4/pkg/reconcile -func (r *ClusterVersionReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - reqCtx := intctrlutil.RequestCtx{ - Ctx: ctx, - Req: req, - Log: log.FromContext(ctx).WithValues("clusterDefinition", req.NamespacedName), - Recorder: r.Recorder, - } - - clusterVersion := &appsv1alpha1.ClusterVersion{} - if err := r.Client.Get(reqCtx.Ctx, reqCtx.Req.NamespacedName, clusterVersion); err != nil { - return intctrlutil.CheckedRequeueWithError(err, reqCtx.Log, "") - } - - res, err := intctrlutil.HandleCRDeletion(reqCtx, r, clusterVersion, clusterVersionFinalizerName, func() (*ctrl.Result, error) { - recordEvent := func() { - r.Recorder.Event(clusterVersion, corev1.EventTypeWarning, constant.ReasonRefCRUnavailable, - "cannot be deleted because of existing referencing Cluster.") - } - if res, err := intctrlutil.ValidateReferenceCR(reqCtx, r.Client, clusterVersion, - constant.ClusterVerLabelKey, recordEvent, &appsv1alpha1.ClusterList{}); res != nil || err != nil { - return res, err - } - return nil, r.deleteExternalResources(reqCtx, clusterVersion) - }) - if res != nil { - return *res, err - } - - if clusterVersion.Status.ObservedGeneration == clusterVersion.Generation && - slices.Contains(clusterVersion.Status.GetTerminalPhases(), clusterVersion.Status.Phase) { - return intctrlutil.Reconciled() - } - - clusterdefinition := &appsv1alpha1.ClusterDefinition{} - if err := r.Client.Get(reqCtx.Ctx, types.NamespacedName{ - Name: clusterVersion.Spec.ClusterDefinitionRef, - }, clusterdefinition); err != nil { - if apierrors.IsNotFound(err) { - if res, patchErr := r.patchClusterDefLabel(reqCtx, clusterVersion); res != nil { - return *res, patchErr - } - if err = r.handleClusterDefNotFound(reqCtx, clusterVersion, err.Error()); err != nil { - return intctrlutil.RequeueWithErrorAndRecordEvent(clusterVersion, r.Recorder, err, reqCtx.Log) - } - return intctrlutil.Reconciled() - } - return intctrlutil.RequeueWithErrorAndRecordEvent(clusterVersion, r.Recorder, err, reqCtx.Log) - } - - patchStatus := func(phase appsv1alpha1.Phase, message string) error { - patch := client.MergeFrom(clusterVersion.DeepCopy()) - clusterVersion.Status.Phase = phase - clusterVersion.Status.Message = message - clusterVersion.Status.ObservedGeneration = clusterVersion.Generation - clusterVersion.Status.ClusterDefGeneration = clusterdefinition.Generation - return r.Client.Status().Patch(ctx, clusterVersion, patch) - } - - if statusMsg := validateClusterVersion(clusterVersion, clusterdefinition); statusMsg != "" { - if err := patchStatus(appsv1alpha1.UnavailablePhase, statusMsg); err != nil { - return intctrlutil.CheckedRequeueWithError(err, reqCtx.Log, "") - } - return intctrlutil.Reconciled() - } - - if err = appsconfig.ReconcileConfigSpecsForReferencedCR(r.Client, reqCtx, clusterVersion); err != nil { - return intctrlutil.RequeueAfter(time.Second, reqCtx.Log, err.Error()) - } - - if res, err = r.patchClusterDefLabel(reqCtx, clusterVersion); res != nil { - return *res, err - } - - if err = patchStatus(appsv1alpha1.AvailablePhase, ""); err != nil { - return intctrlutil.CheckedRequeueWithError(err, reqCtx.Log, "") - } - intctrlutil.RecordCreatedEvent(r.Recorder, clusterVersion) - return intctrlutil.Reconciled() -} - -// SetupWithManager sets up the controller with the Manager. -func (r *ClusterVersionReconciler) SetupWithManager(mgr ctrl.Manager) error { - return intctrlutil.NewNamespacedControllerManagedBy(mgr). - For(&appsv1alpha1.ClusterVersion{}). - Complete(r) -} - -func (r *ClusterVersionReconciler) patchClusterDefLabel(reqCtx intctrlutil.RequestCtx, - clusterVersion *appsv1alpha1.ClusterVersion) (*ctrl.Result, error) { - if v, ok := clusterVersion.ObjectMeta.Labels[constant.ClusterDefLabelKey]; !ok || v != clusterVersion.Spec.ClusterDefinitionRef { - patch := client.MergeFrom(clusterVersion.DeepCopy()) - if clusterVersion.ObjectMeta.Labels == nil { - clusterVersion.ObjectMeta.Labels = map[string]string{} - } - clusterVersion.ObjectMeta.Labels[constant.ClusterDefLabelKey] = clusterVersion.Spec.ClusterDefinitionRef - if err := r.Client.Patch(reqCtx.Ctx, clusterVersion, patch); err != nil { - return intctrlutil.ResultToP(intctrlutil.CheckedRequeueWithError(err, reqCtx.Log, "")) - } - return intctrlutil.ResultToP(intctrlutil.Reconciled()) - } - return nil, nil -} - -// handleClusterDefNotFound handles clusterVersion status when clusterDefinition not found. -func (r *ClusterVersionReconciler) handleClusterDefNotFound(reqCtx intctrlutil.RequestCtx, - clusterVersion *appsv1alpha1.ClusterVersion, message string) error { - if clusterVersion.Status.Message == message { - return nil - } - patch := client.MergeFrom(clusterVersion.DeepCopy()) - clusterVersion.Status.Phase = appsv1alpha1.UnavailablePhase - clusterVersion.Status.Message = message - return r.Client.Status().Patch(reqCtx.Ctx, clusterVersion, patch) -} - -func validateClusterVersion(clusterVersion *appsv1alpha1.ClusterVersion, clusterDef *appsv1alpha1.ClusterDefinition) string { - notFoundComponentDefNames, noContainersComponents := clusterVersion.GetInconsistentComponentsInfo(clusterDef) - var statusMsgs []string - if len(notFoundComponentDefNames) > 0 { - statusMsgs = append(statusMsgs, fmt.Sprintf("spec.componentSpecs[*].componentDefRef %v not found in ClusterDefinition.spec.componentDefs[*].name", notFoundComponentDefNames)) - } else if len(noContainersComponents) > 0 { - statusMsgs = append(statusMsgs, fmt.Sprintf("spec.componentSpecs[*].componentDefRef %v missing spec.componentSpecs[*].containers in ClusterDefinition.spec.componentDefs[*] and ClusterVersion.spec.componentVersions[*]", noContainersComponents)) - } - return strings.Join(statusMsgs, ";") -} - -func (r *ClusterVersionReconciler) deleteExternalResources(reqCtx intctrlutil.RequestCtx, clusterVersion *appsv1alpha1.ClusterVersion) error { - // - // delete any external resources associated with the cronJob - // - // Ensure that delete implementation is idempotent and safe to invoke - // multiple times for same object. - return appsconfig.DeleteConfigMapFinalizer(r.Client, reqCtx, clusterVersion) -} - -func clusterVersionUpdateHandler(cli client.Client, ctx context.Context, clusterDef *appsv1alpha1.ClusterDefinition) error { - labelSelector, err := labels.Parse(constant.ClusterDefLabelKey + "=" + clusterDef.GetName()) - if err != nil { - return err - } - o := &client.ListOptions{LabelSelector: labelSelector} - - list := &appsv1alpha1.ClusterVersionList{} - if err := cli.List(ctx, list, o); err != nil { - return err - } - for _, item := range list.Items { - if item.Status.ClusterDefGeneration != clusterDef.Generation { - patch := client.MergeFrom(item.DeepCopy()) - if statusMsg := validateClusterVersion(&item, clusterDef); statusMsg != "" { - item.Status.Phase = appsv1alpha1.UnavailablePhase - item.Status.Message = statusMsg - } else { - item.Status.Phase = appsv1alpha1.AvailablePhase - item.Status.Message = "" - item.Status.ClusterDefGeneration = clusterDef.Generation - } - if err = cli.Status().Patch(ctx, &item, patch); err != nil { - return err - } - } - } - - return nil -} diff --git a/controllers/apps/clusterversion_controller_test.go b/controllers/apps/clusterversion_controller_test.go deleted file mode 100644 index bb67ade93961..000000000000 --- a/controllers/apps/clusterversion_controller_test.go +++ /dev/null @@ -1,83 +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 apps - -import ( - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - "sigs.k8s.io/controller-runtime/pkg/client" - - appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" - testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" -) - -var _ = Describe("test clusterVersion controller", func() { - - var ( - randomStr = testCtx.GetRandomStr() - clusterVersionName = "mysql-version-" + randomStr - clusterDefName = "mysql-definition-" + randomStr - ) - - const statefulCompDefName = "stateful" - - 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, - // in race conditions, it will find the existence of old objects, resulting failure to - // create the new objects. - By("clean resources") - - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef - testapps.ClearClusterResources(&testCtx) - } - BeforeEach(cleanEnv) - - AfterEach(cleanEnv) - - Context("test clusterVersion controller", func() { - It("test clusterVersion controller", func() { - By("create a clusterVersion obj") - clusterVersionObj := testapps.NewClusterVersionFactory(clusterVersionName, clusterDefName). - AddComponentVersion(statefulCompDefName).AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - Create(&testCtx).GetObject() - - By("wait for clusterVersion phase is unavailable when clusterDef is not found") - Eventually(testapps.CheckObj(&testCtx, client.ObjectKeyFromObject(clusterVersionObj), - func(g Gomega, tmpCV *appsv1alpha1.ClusterVersion) { - g.Expect(tmpCV.Status.Phase).Should(Equal(appsv1alpha1.UnavailablePhase)) - })).Should(Succeed()) - - By("create a clusterDefinition obj") - testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatefulMySQLComponent, statefulCompDefName). - Create(&testCtx).GetObject() - - By("wait for clusterVersion phase is available") - Eventually(testapps.CheckObj(&testCtx, - client.ObjectKeyFromObject(clusterVersionObj), - func(g Gomega, tmpCV *appsv1alpha1.ClusterVersion) { - g.Expect(tmpCV.Status.Phase).Should(Equal(appsv1alpha1.AvailablePhase)) - })).Should(Succeed()) - }) - }) - -}) diff --git a/controllers/apps/component_controller_test.go b/controllers/apps/component_controller_test.go index dba8ba3f7f99..1beeb8fc3189 100644 --- a/controllers/apps/component_controller_test.go +++ b/controllers/apps/component_controller_test.go @@ -129,13 +129,12 @@ var mockLorryClient4HScale = func(clusterKey types.NamespacedName, compName stri var _ = Describe("Component Controller", func() { const ( - clusterDefName = "test-clusterdef" - clusterVersionName = "test-clusterversion" - compDefName = "test-compdef" - compVerName = "test-compver" - clusterName = "test-cluster" // this become cluster prefix name if used with testapps.NewClusterFactory().WithRandomName() - leader = "leader" - follower = "follower" + clusterDefName = "test-clusterdef" + compDefName = "test-compdef" + compVerName = "test-compver" + clusterName = "test-cluster" // this become cluster prefix name if used with testapps.NewClusterFactory().WithRandomName() + leader = "leader" + follower = "follower" // REVIEW: // - setup componentName and componentDefName as map entry pair statefulCompName = "stateful" @@ -148,15 +147,14 @@ var _ = Describe("Component Controller", func() { ) var ( - clusterDefObj *appsv1alpha1.ClusterDefinition - clusterVersionObj *appsv1alpha1.ClusterVersion - compDefObj *appsv1alpha1.ComponentDefinition - compVerObj *appsv1alpha1.ComponentVersion - clusterObj *appsv1alpha1.Cluster - clusterKey types.NamespacedName - compObj *appsv1alpha1.Component - compKey types.NamespacedName - allSettings map[string]interface{} + clusterDefObj *appsv1alpha1.ClusterDefinition + compDefObj *appsv1alpha1.ComponentDefinition + compVerObj *appsv1alpha1.ComponentVersion + clusterObj *appsv1alpha1.Cluster + clusterKey types.NamespacedName + compObj *appsv1alpha1.Component + compKey types.NamespacedName + allSettings map[string]interface{} ) resetViperCfg := func() { @@ -168,7 +166,6 @@ var _ = Describe("Component Controller", func() { resetTestContext := func() { clusterDefObj = nil - clusterVersionObj = nil clusterObj = nil resetViperCfg() } @@ -181,7 +178,7 @@ var _ = Describe("Component Controller", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest mocked objects @@ -216,7 +213,7 @@ var _ = Describe("Component Controller", func() { } // test function helpers - createAllWorkloadTypesClusterDef := func(noCreateAssociateCV ...bool) { + createAllWorkloadTypesClusterDef := func() { By("Create a clusterDefinition obj") clusterDefObj = testapps.NewClusterDefFactory(clusterDefName). AddComponentDef(testapps.StatefulMySQLComponent, statefulCompDefName). @@ -224,16 +221,6 @@ var _ = Describe("Component Controller", func() { AddComponentDef(testapps.ReplicationRedisComponent, replicationCompDefName). Create(&testCtx).GetObject() - if len(noCreateAssociateCV) > 0 && noCreateAssociateCV[0] { - return - } - By("Create a clusterVersion obj") - clusterVersionObj = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefObj.GetName()). - AddComponentVersion(statefulCompDefName).AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - AddComponentVersion(consensusCompDefName).AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - AddComponentVersion(replicationCompDefName).AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - Create(&testCtx).GetObject() - By("Create a componentDefinition obj") compDefObj = testapps.NewComponentDefinitionFactory(compDefName). WithRandomName(). @@ -267,9 +254,9 @@ var _ = Describe("Component Controller", func() { } } - createClusterObjVx := func(clusterDefName, clusterVerName, compName, compDefName string, v2 bool, + createClusterObjVx := func(clusterDefName, compName, compDefName string, v2 bool, processor func(*testapps.MockClusterFactory), phase *appsv1alpha1.ClusterPhase) { - factory := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefName, clusterVerName). + factory := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefName). WithRandomName() if !v2 { factory.AddComponent(compName, compDefName).SetReplicas(1) @@ -305,17 +292,17 @@ var _ = Describe("Component Controller", func() { createClusterObj := func(compName, compDefName string, processor func(*testapps.MockClusterFactory)) { By("Creating a cluster") - createClusterObjVx(clusterDefObj.Name, clusterVersionObj.Name, compName, compDefName, false, processor, nil) + createClusterObjVx(clusterDefObj.Name, compName, compDefName, false, processor, nil) } createClusterObjV2 := func(compName, compDefName string, processor func(*testapps.MockClusterFactory)) { By("Creating a cluster with new component definition") - createClusterObjVx("", "", compName, compDefName, true, processor, nil) + createClusterObjVx("", compName, compDefName, true, processor, nil) } createClusterObjV2WithPhase := func(compName, compDefName string, processor func(*testapps.MockClusterFactory), phase appsv1alpha1.ClusterPhase) { By("Creating a cluster with new component definition") - createClusterObjVx("", "", compName, compDefName, true, processor, &phase) + createClusterObjVx("", compName, compDefName, true, processor, &phase) } mockCompRunning := func(compName string) { @@ -1747,8 +1734,8 @@ var _ = Describe("Component Controller", func() { testReplicationWorkloadRunning := func(compName, compDefName string) { By("Mock a cluster obj with replication componentDefRef.") pvcSpec := testapps.NewPVCSpec("1Gi") - clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDefObj.Name, clusterVersionObj.Name).WithRandomName(). + clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). + WithRandomName(). AddComponent(compName, compDefName). SetReplicas(testapps.DefaultReplicationReplicas). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). @@ -1773,8 +1760,8 @@ var _ = Describe("Component Controller", func() { By("Mock a cluster obj") pvcSpec := testapps.NewPVCSpec("1Gi") - clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDefObj.Name, clusterVersionObj.Name).WithRandomName(). + clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). + WithRandomName(). AddComponent(compName, compDefName). SetReplicas(replicas).AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). Create(&testCtx).GetObject() @@ -1896,7 +1883,7 @@ var _ = Describe("Component Controller", func() { restoreFromBackup := fmt.Sprintf(`{"%s":{"name":"%s"}}`, compName, backupName) pvcSpec := testapps.NewPVCSpec("1Gi") replicas := 3 - clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name, clusterVersionObj.Name). + clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). WithRandomName(). AddComponent(compName, compDefName). SetReplicas(int32(replicas)). @@ -2241,8 +2228,7 @@ var _ = Describe("Component Controller", func() { Expect(components).ShouldNot(BeEmpty()) By("Creating a cluster") - clusterBuilder := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDefObj.Name, clusterVersionObj.Name) + clusterBuilder := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name) compNames := make([]string, 0, len(components)) for compName, compDefName := range components { diff --git a/controllers/apps/component_plan_builder_test.go b/controllers/apps/component_plan_builder_test.go index f20d418287ee..bf6539ba7ea9 100644 --- a/controllers/apps/component_plan_builder_test.go +++ b/controllers/apps/component_plan_builder_test.go @@ -47,7 +47,7 @@ var _ = Describe("component plan builder test", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest mocked objects diff --git a/controllers/apps/component_utils_test.go b/controllers/apps/component_utils_test.go index c4265608f38a..76d1c031b798 100644 --- a/controllers/apps/component_utils_test.go +++ b/controllers/apps/component_utils_test.go @@ -39,10 +39,9 @@ import ( var _ = Describe("Component Utils", func() { var ( - randomStr = testCtx.GetRandomStr() - clusterDefName = "mysql-clusterdef-" + randomStr - clusterVersionName = "mysql-clusterversion-" + randomStr - clusterName = "mysql-" + randomStr + randomStr = testCtx.GetRandomStr() + clusterDefName = "mysql-clusterdef-" + randomStr + clusterName = "mysql-" + randomStr ) const ( @@ -56,7 +55,7 @@ var _ = Describe("Component Utils", func() { // in race conditions, it will find the existence of old objects, resulting failure to // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // clear rest resources @@ -74,8 +73,8 @@ var _ = Describe("Component Utils", func() { Context("Component test", func() { It("Component test", func() { By(" init cluster, instanceSet, pods") - _, _, cluster := testapps.InitClusterWithHybridComps(&testCtx, clusterDefName, - clusterVersionName, clusterName, statelessCompName, "stateful", consensusCompName) + _, cluster := testapps.InitClusterWithHybridComps(&testCtx, clusterDefName, + clusterName, statelessCompName, "stateful", consensusCompName) its := testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusCompName) _ = testapps.MockInstanceSetPods(&testCtx, its, cluster, consensusCompName) diff --git a/controllers/apps/configuration/config_util.go b/controllers/apps/configuration/config_util.go index 09c5f1dfc312..5361f0f91152 100644 --- a/controllers/apps/configuration/config_util.go +++ b/controllers/apps/configuration/config_util.go @@ -160,7 +160,7 @@ func batchDeleteConfigMapFinalizer(cli client.Client, ctx intctrlutil.RequestCtx labels := client.MatchingLabels{ core.GenerateTPLUniqLabelKeyWithConfig(configSpec.Name): configSpec.TemplateRef, } - if ok, err := validateConfigMapOwners(cli, ctx, labels, validator, &appsv1alpha1.ClusterVersionList{}, &appsv1alpha1.ClusterDefinitionList{}, &appsv1alpha1.ComponentDefinitionList{}); err != nil { + if ok, err := validateConfigMapOwners(cli, ctx, labels, validator, &appsv1alpha1.ClusterDefinitionList{}, &appsv1alpha1.ComponentDefinitionList{}); err != nil { return err } else if !ok { continue @@ -244,8 +244,6 @@ func handleConfigTemplate(object client.Object, handler ConfigTemplateHandler, h switch cr := object.(type) { case *appsv1alpha1.ClusterDefinition: configTemplates, err = getConfigTemplateFromCD(cr, handler2...) - case *appsv1alpha1.ClusterVersion: - configTemplates = getConfigTemplateFromCV(cr) case *appsv1alpha1.ComponentDefinition: configTemplates = getConfigTemplateFromComponentDef(cr) default: @@ -262,16 +260,6 @@ func handleConfigTemplate(object client.Object, handler ConfigTemplateHandler, h } } -func getConfigTemplateFromCV(appVer *appsv1alpha1.ClusterVersion) []appsv1alpha1.ComponentConfigSpec { - configTemplates := make([]appsv1alpha1.ComponentConfigSpec, 0) - for _, component := range appVer.Spec.ComponentVersions { - if len(component.ConfigSpecs) > 0 { - configTemplates = append(configTemplates, component.ConfigSpecs...) - } - } - return configTemplates -} - func getConfigTemplateFromCD(clusterDef *appsv1alpha1.ClusterDefinition, validators ...ComponentValidateHandler) ([]appsv1alpha1.ComponentConfigSpec, error) { configTemplates := make([]appsv1alpha1.ComponentConfigSpec, 0) for _, component := range clusterDef.Spec.ComponentDefs { diff --git a/controllers/apps/configuration/config_util_test.go b/controllers/apps/configuration/config_util_test.go index ecafcfe78832..fb6da10d08c7 100644 --- a/controllers/apps/configuration/config_util_test.go +++ b/controllers/apps/configuration/config_util_test.go @@ -38,7 +38,6 @@ import ( var _ = Describe("ConfigWrapper util test", func() { const clusterDefName = "test-clusterdef" - const clusterVersionName = "test-clusterversion" const statefulCompDefName = "replicasets" const configSpecName = "mysql-config-tpl" const configVolumeName = "mysql-config" @@ -58,7 +57,6 @@ var _ = Describe("ConfigWrapper util test", func() { configMapObj *corev1.ConfigMap configConstraintObj *appsv1beta1.ConfigConstraint clusterDefObj *appsv1alpha1.ClusterDefinition - clusterVersionObj *appsv1alpha1.ClusterVersion ) cleanEnv := func() { @@ -74,7 +72,6 @@ var _ = Describe("ConfigWrapper util test", func() { // namespaced testapps.ClearResources(&testCtx, generics.ConfigMapSignature, inNS, ml) // non-namespaced - testapps.ClearResources(&testCtx, generics.ClusterVersionSignature, ml) testapps.ClearResources(&testCtx, generics.ClusterDefinitionSignature, ml) testapps.ClearResources(&testCtx, generics.ConfigConstraintSignature, ml) } @@ -99,11 +96,6 @@ var _ = Describe("ConfigWrapper util test", func() { AddComponentDef(testapps.StatefulMySQLComponent, statefulCompDefName). AddConfigTemplate(configSpecName, configMapObj.Name, configConstraintObj.Name, testCtx.DefaultNamespace, configVolumeName). Create(&testCtx).GetObject() - - By("Create a clusterVersion obj") - clusterVersionObj = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefObj.GetName()). - AddComponentVersion(statefulCompDefName). - Create(&testCtx).GetObject() }) AfterEach(func() { @@ -210,79 +202,4 @@ var _ = Describe("ConfigWrapper util test", func() { Expect(ok).Should(BeTrue()) }) }) - - updateAVTemplates := func() { - var tpls []appsv1alpha1.ComponentConfigSpec - _, err := handleConfigTemplate(clusterDefObj, func(templates []appsv1alpha1.ComponentConfigSpec) (bool, error) { - tpls = templates - return true, nil - }) - Expect(err).Should(Succeed()) - - if len(clusterVersionObj.Spec.ComponentVersions) == 0 { - return - } - - // mock clusterVersionObj config templates - clusterVersionObj.Spec.ComponentVersions[0].ConfigSpecs = tpls - } - - Context("clusterversion CR test", func() { - It("Should success without error", func() { - updateAVTemplates() - availableTPL := configConstraintObj.DeepCopy() - availableTPL.Status.Phase = appsv1beta1.CCAvailablePhase - - k8sMockClient.MockPatchMethod(testutil.WithSucceed()) - k8sMockClient.MockListMethod(testutil.WithSucceed()) - k8sMockClient.MockGetMethod(testutil.WithGetReturned(testutil.WithConstructSequenceResult( - map[client.ObjectKey][]testutil.MockGetReturned{ - client.ObjectKeyFromObject(configMapObj): {{ - Object: nil, - Err: cfgcore.MakeError("failed to get cc object"), - }, { - Object: configMapObj, - Err: nil, - }}, - client.ObjectKeyFromObject(configConstraintObj): {{ - Object: nil, - Err: cfgcore.MakeError("failed to get cc object"), - }, { - Object: configConstraintObj, - Err: nil, - }, { - Object: availableTPL, - Err: nil, - }}, - }, - ), testutil.WithAnyTimes())) - - _, err := checkConfigTemplate(k8sMockClient.Client(), reqCtx, clusterVersionObj) - Expect(err).ShouldNot(Succeed()) - Expect(err.Error()).Should(ContainSubstring("failed to get cc object")) - - _, err = checkConfigTemplate(k8sMockClient.Client(), reqCtx, clusterVersionObj) - Expect(err).ShouldNot(Succeed()) - Expect(err.Error()).Should(ContainSubstring("failed to get cc object")) - - _, err = checkConfigTemplate(k8sMockClient.Client(), reqCtx, clusterVersionObj) - Expect(err).ShouldNot(Succeed()) - Expect(err.Error()).Should(ContainSubstring("status not ready")) - - ok, err := checkConfigTemplate(k8sMockClient.Client(), reqCtx, clusterVersionObj) - Expect(err).Should(Succeed()) - Expect(ok).Should(BeTrue()) - - ok, err = updateLabelsByConfigSpec(k8sMockClient.Client(), reqCtx, clusterVersionObj) - Expect(err).Should(Succeed()) - Expect(ok).Should(BeTrue()) - - _, err = updateLabelsByConfigSpec(k8sMockClient.Client(), reqCtx, clusterVersionObj) - Expect(err).Should(Succeed()) - - err = DeleteConfigMapFinalizer(k8sMockClient.Client(), reqCtx, clusterVersionObj) - Expect(err).Should(Succeed()) - }) - }) - }) diff --git a/controllers/apps/configuration/configconstraint_controller.go b/controllers/apps/configuration/configconstraint_controller.go index 43704d40134d..cd6f0a45d1e6 100644 --- a/controllers/apps/configuration/configconstraint_controller.go +++ b/controllers/apps/configuration/configconstraint_controller.go @@ -73,7 +73,7 @@ func (r *ConfigConstraintReconciler) Reconcile(ctx context.Context, req ctrl.Req res, err := intctrlutil.HandleCRDeletion(reqCtx, r, configConstraint, constant.ConfigFinalizerName, func() (*ctrl.Result, error) { recordEvent := func() { r.Recorder.Event(configConstraint, corev1.EventTypeWarning, "ExistsReferencedResources", - "cannot be deleted because of existing referencing of ClusterDefinition or ClusterVersion.") + "cannot be deleted because of existing referencing of ClusterDefinition.") } if configConstraint.Status.Phase != appsv1beta1.CCDeletingPhase { err := updateConfigConstraintStatus(r.Client, reqCtx, configConstraint, appsv1beta1.CCDeletingPhase) @@ -85,8 +85,7 @@ func (r *ConfigConstraintReconciler) Reconcile(ctx context.Context, req ctrl.Req } if res, err := intctrlutil.ValidateReferenceCR(reqCtx, r.Client, configConstraint, cfgcore.GenerateConstraintsUniqLabelKeyWithConfig(configConstraint.GetName()), - recordEvent, &appsv1alpha1.ClusterDefinitionList{}, - &appsv1alpha1.ClusterVersionList{}); res != nil || err != nil { + recordEvent, &appsv1alpha1.ClusterDefinitionList{}); res != nil || err != nil { return res, err } return nil, nil diff --git a/controllers/apps/configuration/configconstraint_controller_test.go b/controllers/apps/configuration/configconstraint_controller_test.go index 8082e55a7aa1..0d6881f5a3a0 100644 --- a/controllers/apps/configuration/configconstraint_controller_test.go +++ b/controllers/apps/configuration/configconstraint_controller_test.go @@ -39,7 +39,6 @@ import ( var _ = Describe("ConfigConstraint Controller", func() { const clusterDefName = "test-clusterdef" - const clusterVersionName = "test-clusterversion" const statefulCompDefName = "replicasets" const configSpecName = "mysql-config-tpl" const configVolumeName = "mysql-config" @@ -51,7 +50,7 @@ var _ = Describe("ConfigConstraint Controller", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) // delete rest mocked objects @@ -88,13 +87,6 @@ var _ = Describe("ConfigConstraint Controller", func() { cfgcore.GenerateConstraintsUniqLabelKeyWithConfig(constraint.Name), constraint.Name). Create(&testCtx).GetObject() - By("Create a clusterVersion obj") - clusterVersionObj := testapps.NewClusterVersionFactory(clusterVersionName, clusterDefObj.GetName()). - AddComponentVersion(statefulCompDefName). - AddLabels(cfgcore.GenerateTPLUniqLabelKeyWithConfig(configSpecName), configmap.Name, - cfgcore.GenerateConstraintsUniqLabelKeyWithConfig(constraint.Name), constraint.Name). - Create(&testCtx).GetObject() - By("check ConfigConstraint(template) status and finalizer") Eventually(testapps.CheckObj(&testCtx, constraintKey, func(g Gomega, tpl *appsv1beta1.ConfigConstraint) { @@ -115,8 +107,7 @@ var _ = Describe("ConfigConstraint Controller", func() { g.Expect(tpl.Status.Phase).To(BeEquivalentTo(appsv1beta1.CCDeletingPhase)) })).Should(Succeed()) - By("By delete referencing clusterdefinition and clusterversion") - Expect(k8sClient.Delete(testCtx.Ctx, clusterVersionObj)).Should(Succeed()) + By("By delete referencing clusterdefinition") Expect(k8sClient.Delete(testCtx.Ctx, clusterDefObj)).Should(Succeed()) By("check ConfigConstraint should be deleted") diff --git a/controllers/apps/configuration/configuration_test.go b/controllers/apps/configuration/configuration_test.go index eea0170a3ee4..ee2ce05709a6 100644 --- a/controllers/apps/configuration/configuration_test.go +++ b/controllers/apps/configuration/configuration_test.go @@ -43,7 +43,6 @@ import ( ) const clusterDefName = "test-clusterdef" -const clusterVersionName = "test-clusterversion" const clusterName = "test-cluster" const statefulCompDefName = "replicasets" const statefulCompName = "mysql" @@ -112,16 +111,8 @@ func mockReconcileResource() (*corev1.ConfigMap, *appsv1beta1.ConfigConstraint, core.GenerateConstraintsUniqLabelKeyWithConfig(constraint.Name), constraint.Name). Create(&testCtx).GetObject() - By("Create a clusterVersion obj") - clusterVersionObj := testapps.NewClusterVersionFactory(clusterVersionName, clusterDefObj.GetName()). - AddComponentVersion(statefulCompDefName). - AddLabels(core.GenerateTPLUniqLabelKeyWithConfig(configSpecName), configmap.Name, - core.GenerateConstraintsUniqLabelKeyWithConfig(constraint.Name), constraint.Name). - Create(&testCtx).GetObject() - By("Creating a cluster") - clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDefObj.Name, clusterVersionObj.Name). + clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). AddComponent(statefulCompName, statefulCompDefName).Create(&testCtx).GetObject() By("Create a component definition obj and mock to available") @@ -191,7 +182,7 @@ func cleanEnv() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) // delete rest mocked objects diff --git a/controllers/apps/const.go b/controllers/apps/const.go index ab6c37cb5556..b23e75f52edf 100644 --- a/controllers/apps/const.go +++ b/controllers/apps/const.go @@ -22,7 +22,6 @@ package apps const ( // name of our custom finalizer clusterDefinitionFinalizerName = "clusterdefinition.kubeblocks.io/finalizer" - clusterVersionFinalizerName = "clusterversion.kubeblocks.io/finalizer" opsDefinitionFinalizerName = "opsdefinition.kubeblocks.io/finalizer" componentDefinitionFinalizerName = "componentdefinition.kubeblocks.io/finalizer" componentVersionFinalizerName = "componentversion.kubeblocks.io/finalizer" diff --git a/controllers/apps/operations/backup_test.go b/controllers/apps/operations/backup_test.go index ed0134621f69..02326b6378da 100644 --- a/controllers/apps/operations/backup_test.go +++ b/controllers/apps/operations/backup_test.go @@ -36,7 +36,6 @@ var _ = Describe("Backup OpsRequest", func() { var ( randomStr = testCtx.GetRandomStr() clusterDefinitionName = "cluster-definition-for-ops-" + randomStr //nolint:goconst - clusterVersionName = "clusterversion-for-ops-" + randomStr //nolint:goconst clusterName = "cluster-for-ops-" + randomStr //nolint:goconst ) @@ -47,7 +46,7 @@ var _ = Describe("Backup OpsRequest", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) // delete rest resources @@ -68,7 +67,7 @@ var _ = Describe("Backup OpsRequest", func() { ) BeforeEach(func() { By("init operations resources ") - opsRes, _, _ = initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + opsRes, _, _ = initOperationsResources(clusterDefinitionName, clusterName) reqCtx = intctrlutil.RequestCtx{Ctx: testCtx.Ctx} }) diff --git a/controllers/apps/operations/custom_test.go b/controllers/apps/operations/custom_test.go index 37f26325b55b..05f11782c3b1 100644 --- a/controllers/apps/operations/custom_test.go +++ b/controllers/apps/operations/custom_test.go @@ -38,7 +38,6 @@ var _ = Describe("CustomOps", func() { var ( randomStr = testCtx.GetRandomStr() clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterVersionName = "clusterversion-for-ops-" + randomStr clusterName = "cluster-for-ops-" + randomStr compDefName = "apecloud-mysql" opsResource *OpsResource @@ -55,7 +54,7 @@ var _ = Describe("CustomOps", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) // delete rest resources @@ -104,7 +103,7 @@ var _ = Describe("CustomOps", func() { Create(&testCtx). GetObject() - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefinitionName, clusterVersionName). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefinitionName). WithRandomName().AddComponentV2(consensusComp, componentDefObj.Name).SetReplicas(1).Create(&testCtx).GetObject() fullCompName := constant.GenerateClusterComponentName(cluster.Name, consensusComp) diff --git a/controllers/apps/operations/datascript_test.go b/controllers/apps/operations/datascript_test.go index 59719ed7097e..d9b9452ac8f0 100644 --- a/controllers/apps/operations/datascript_test.go +++ b/controllers/apps/operations/datascript_test.go @@ -44,7 +44,6 @@ var _ = Describe("DataScriptOps", func() { var ( randomStr = testCtx.GetRandomStr() clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterVersionName = "clusterversion-for-ops-" + randomStr clusterName = "cluster-for-ops-" + randomStr clusterObj *appsv1alpha1.Cluster @@ -63,7 +62,7 @@ var _ = Describe("DataScriptOps", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) // delete rest resources @@ -140,8 +139,8 @@ var _ = Describe("DataScriptOps", func() { Context("with Cluster which has MySQL ConsensusSet", func() { BeforeEach(func() { By("mock cluster") - _, _, clusterObj = testapps.InitClusterWithHybridComps(&testCtx, clusterDefinitionName, - clusterVersionName, clusterName, statelessComp, statefulComp, consensusComp) + _, clusterObj = testapps.InitClusterWithHybridComps(&testCtx, clusterDefinitionName, + clusterName, statelessComp, statefulComp, consensusComp) By("init opsResource") opsResource = &OpsResource{ diff --git a/controllers/apps/operations/expose_test.go b/controllers/apps/operations/expose_test.go index bcbeb84ae54d..1bec9b64082b 100644 --- a/controllers/apps/operations/expose_test.go +++ b/controllers/apps/operations/expose_test.go @@ -38,7 +38,6 @@ var _ = Describe("", func() { var ( randomStr = testCtx.GetRandomStr() clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterVersionName = "clusterversion-for-ops-" + randomStr clusterName = "cluster-for-ops-" + randomStr ) @@ -53,7 +52,7 @@ var _ = Describe("", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) // delete rest resources @@ -70,7 +69,7 @@ var _ = Describe("", func() { Context("Test OpsRequest", func() { It("Test expose OpsRequest", func() { reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx} - opsRes, _, clusterObject := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + opsRes, _, clusterObject := initOperationsResources(clusterDefinitionName, clusterName) By("create Expose opsRequest") ops := testapps.NewOpsRequestObj("expose-expose-"+randomStr, testCtx.DefaultNamespace, @@ -108,7 +107,7 @@ var _ = Describe("", func() { It("Test expose OpsRequest with empty ComponentName", func() { reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx} - opsRes, _, clusterObject := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + opsRes, _, clusterObject := initOperationsResources(clusterDefinitionName, clusterName) By("create Expose opsRequest") ops := testapps.NewOpsRequestObj("expose-expose-"+randomStr, testCtx.DefaultNamespace, diff --git a/controllers/apps/operations/horizontal_scaling_test.go b/controllers/apps/operations/horizontal_scaling_test.go index 57b05ac17d05..1cfe932e67d3 100644 --- a/controllers/apps/operations/horizontal_scaling_test.go +++ b/controllers/apps/operations/horizontal_scaling_test.go @@ -25,6 +25,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" @@ -45,7 +46,6 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { var ( randomStr = testCtx.GetRandomStr() clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterVersionName = "clusterversion-for-ops-" + randomStr clusterName = "cluster-for-ops-" + randomStr insTplName = "foo" ) @@ -57,7 +57,7 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) // delete rest resources @@ -85,8 +85,8 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { commonHScaleConsensusCompTest := func(reqCtx intctrlutil.RequestCtx, changeClusterSpec func(cluster *appsv1alpha1.Cluster), horizontalScaling appsv1alpha1.HorizontalScaling) (*OpsResource, []*corev1.Pod) { - By("init operations resources with CLusterDefinition/ClusterVersion/Hybrid components Cluster/consensus Pods") - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + By("init operations resources with CLusterDefinition/Hybrid components Cluster/consensus Pods") + opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) its := testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) if changeClusterSpec != nil { Expect(testapps.ChangeObj(&testCtx, opsRes.Cluster, func(cluster *appsv1alpha1.Cluster) { @@ -481,8 +481,8 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { } It("test offline the specified pod but it is not online", func() { - By("init operations resources with CLusterDefinition/ClusterVersion/Hybrid components Cluster/consensus Pods") - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + By("init operations resources with CLusterDefinition/Hybrid components Cluster/consensus Pods") + opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) reqCtx := intctrlutil.RequestCtx{Ctx: ctx} @@ -501,8 +501,8 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { }) It("test run multi horizontalScaling opsRequest with force flag", func() { - By("init operations resources with CLusterDefinition/ClusterVersion/Hybrid components Cluster/consensus Pods") - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + By("init operations resources with CLusterDefinition/Hybrid components Cluster/consensus Pods") + opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) reqCtx := intctrlutil.RequestCtx{Ctx: ctx} By("create first opsRequest to add 1 replicas with `scaleOut` field and expect replicas to 4") diff --git a/controllers/apps/operations/ops_progress_util_test.go b/controllers/apps/operations/ops_progress_util_test.go index 08a4cf522e41..fb71b78062d7 100644 --- a/controllers/apps/operations/ops_progress_util_test.go +++ b/controllers/apps/operations/ops_progress_util_test.go @@ -42,7 +42,6 @@ var _ = Describe("Ops ProgressDetails", func() { var ( randomStr = testCtx.GetRandomStr() clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterVersionName = "clusterversion-for-ops-" + randomStr clusterName = "cluster-for-ops-" + randomStr ) @@ -53,7 +52,7 @@ var _ = Describe("Ops ProgressDetails", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) // delete rest resources @@ -96,7 +95,7 @@ var _ = Describe("Ops ProgressDetails", func() { It("Test Ops ProgressDetails for rolling update", func() { By("init operations resources ") reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx} - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) By("create restart ops and pods of consensus component") opsRes.OpsRequest = createRestartOpsObj(clusterName, "restart-"+randomStr) @@ -115,7 +114,7 @@ var _ = Describe("Ops ProgressDetails", func() { It("Test Ops ProgressDetails with horizontally scaling replicas", func() { By("init operations resources ") reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx} - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) its := testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) podList := testapps.MockInstanceSetPods(&testCtx, its, opsRes.Cluster, consensusComp) diff --git a/controllers/apps/operations/ops_util_test.go b/controllers/apps/operations/ops_util_test.go index ee4d1b1ace82..d1bba1cc2dca 100644 --- a/controllers/apps/operations/ops_util_test.go +++ b/controllers/apps/operations/ops_util_test.go @@ -24,6 +24,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/pointer" @@ -43,7 +44,6 @@ var _ = Describe("OpsUtil functions", func() { var ( randomStr = testCtx.GetRandomStr() clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterVersionName = "clusterversion-for-ops-" + randomStr clusterName = "cluster-for-ops-" + randomStr ) @@ -54,7 +54,7 @@ var _ = Describe("OpsUtil functions", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) // delete rest resources @@ -74,7 +74,7 @@ var _ = Describe("OpsUtil functions", func() { Context("Test ops_util functions", func() { It("Test ops_util functions", func() { By("init operations resources ") - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) By("Test the functions in ops_util.go") @@ -90,7 +90,7 @@ var _ = Describe("OpsUtil functions", func() { It("Test opsRequest failed cases", func() { By("init operations resources ") - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) pods := testapps.MockInstanceSetPods(&testCtx, nil, opsRes.Cluster, consensusComp) time.Sleep(time.Second) @@ -141,7 +141,7 @@ var _ = Describe("OpsUtil functions", func() { It("Test opsRequest with disable ha", func() { By("init operations resources ") - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) By("Test the functions in ops_util.go") ops := testapps.NewOpsRequestObj("restart-ops-"+randomStr, testCtx.DefaultNamespace, @@ -193,7 +193,7 @@ var _ = Describe("OpsUtil functions", func() { It("Test opsRequest Queue functions", func() { By("init operations resources ") reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx} - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) runHscaleOps := func(expectPhase appsv1alpha1.OpsPhase) *appsv1alpha1.OpsRequest { ops := createHorizontalScaling(clusterName, appsv1alpha1.HorizontalScaling{ @@ -248,7 +248,7 @@ var _ = Describe("OpsUtil functions", func() { It("Test opsRequest dependency", func() { By("init operations resources ") reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx} - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) By("create a first horizontal opsRequest") ops1 := createHorizontalScaling(clusterName, appsv1alpha1.HorizontalScaling{ diff --git a/controllers/apps/operations/rebuild_instance_test.go b/controllers/apps/operations/rebuild_instance_test.go index 503c4099401f..3673d3dfa6a3 100644 --- a/controllers/apps/operations/rebuild_instance_test.go +++ b/controllers/apps/operations/rebuild_instance_test.go @@ -24,6 +24,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + "golang.org/x/exp/slices" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -46,7 +47,6 @@ var _ = Describe("OpsUtil functions", func() { var ( randomStr = testCtx.GetRandomStr() clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterVersionName = "clusterversion-for-ops-" + randomStr clusterName = "cluster-for-ops-" + randomStr rebuildInstanceCount = 2 ) @@ -58,7 +58,7 @@ var _ = Describe("OpsUtil functions", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) // delete rest resources @@ -104,7 +104,7 @@ var _ = Describe("OpsUtil functions", func() { } prepareOpsRes := func(backupName string, inPlace bool) *OpsResource { - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) podList := initInstanceSetPods(ctx, k8sClient, opsRes) // fake to create the source pvc. @@ -377,7 +377,7 @@ var _ = Describe("OpsUtil functions", func() { It("rebuild instance with horizontal scaling", func() { By("init operations resources ") - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) its := testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) podList := testapps.MockInstanceSetPods(&testCtx, its, opsRes.Cluster, consensusComp) opsRes.OpsRequest = createRebuildInstanceOps("", false, podList[1].Name, podList[2].Name) diff --git a/controllers/apps/operations/reconfigure_test.go b/controllers/apps/operations/reconfigure_test.go index 881a9c5382bd..8b80237c18e2 100644 --- a/controllers/apps/operations/reconfigure_test.go +++ b/controllers/apps/operations/reconfigure_test.go @@ -47,7 +47,6 @@ var _ = Describe("Reconfigure OpsRequest", func() { var ( randomStr = testCtx.GetRandomStr() clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterVersionName = "clusterversion-for-ops-" + randomStr clusterName = "cluster-for-ops-" + randomStr ) @@ -58,7 +57,7 @@ var _ = Describe("Reconfigure OpsRequest", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) // delete rest resources @@ -144,7 +143,7 @@ var _ = Describe("Reconfigure OpsRequest", func() { assureMockReconfigureData := func(policyName string) (*OpsResource, *appsv1alpha1.Configuration, *corev1.ConfigMap) { By("init operations resources ") - opsRes, clusterDef, clusterObject := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + opsRes, clusterDef, clusterObject := initOperationsResources(clusterDefinitionName, clusterName) var ( cfgObj *corev1.ConfigMap diff --git a/controllers/apps/operations/restart_test.go b/controllers/apps/operations/restart_test.go index 20b6bd911612..99eb5e6dcc70 100644 --- a/controllers/apps/operations/restart_test.go +++ b/controllers/apps/operations/restart_test.go @@ -36,7 +36,6 @@ var _ = Describe("Restart OpsRequest", func() { var ( randomStr = testCtx.GetRandomStr() clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterVersionName = "clusterversion-for-ops-" + randomStr clusterName = "cluster-for-ops-" + randomStr ) @@ -47,7 +46,7 @@ var _ = Describe("Restart OpsRequest", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) // delete rest resources @@ -69,7 +68,7 @@ var _ = Describe("Restart OpsRequest", func() { ) BeforeEach(func() { By("init operations resources ") - opsRes, _, cluster = initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + opsRes, _, cluster = initOperationsResources(clusterDefinitionName, clusterName) reqCtx = intctrlutil.RequestCtx{Ctx: testCtx.Ctx} }) diff --git a/controllers/apps/operations/restore_test.go b/controllers/apps/operations/restore_test.go index 97b987ccaa64..aead8ad2c315 100644 --- a/controllers/apps/operations/restore_test.go +++ b/controllers/apps/operations/restore_test.go @@ -43,7 +43,6 @@ var _ = Describe("Restore OpsRequest", func() { var ( randomStr = testCtx.GetRandomStr() clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterVersionName = "clusterversion-for-ops-" + randomStr clusterName = "cluster-for-ops-" + randomStr restoreClusterName = "restore-cluster" backupName = "backup-for-ops-" + randomStr @@ -57,7 +56,7 @@ var _ = Describe("Restore OpsRequest", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) // delete rest resources @@ -80,7 +79,7 @@ var _ = Describe("Restore OpsRequest", func() { ) BeforeEach(func() { By("init operations resources ") - opsRes, _, _ = initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + opsRes, _, _ = initOperationsResources(clusterDefinitionName, clusterName) reqCtx = intctrlutil.RequestCtx{Ctx: testCtx.Ctx} By("create Backup") diff --git a/controllers/apps/operations/start_test.go b/controllers/apps/operations/start_test.go index e421a7015e27..09754d4bc9e6 100644 --- a/controllers/apps/operations/start_test.go +++ b/controllers/apps/operations/start_test.go @@ -36,7 +36,6 @@ var _ = Describe("Start OpsRequest", func() { var ( randomStr = testCtx.GetRandomStr() clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterVersionName = "clusterversion-for-ops-" + randomStr clusterName = "cluster-for-ops-" + randomStr ) @@ -47,7 +46,7 @@ var _ = Describe("Start OpsRequest", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) // delete rest resources @@ -66,7 +65,7 @@ var _ = Describe("Start OpsRequest", func() { It("Test start OpsRequest", func() { By("init operations resources ") reqCtx := intctrlutil.RequestCtx{Ctx: ctx} - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) testapps.MockInstanceSetComponent(&testCtx, clusterName, statelessComp) testapps.MockInstanceSetComponent(&testCtx, clusterName, statefulComp) diff --git a/controllers/apps/operations/stop_test.go b/controllers/apps/operations/stop_test.go index 5b43d075942c..494fe371be78 100644 --- a/controllers/apps/operations/stop_test.go +++ b/controllers/apps/operations/stop_test.go @@ -35,7 +35,6 @@ var _ = Describe("Stop OpsRequest", func() { var ( randomStr = testCtx.GetRandomStr() clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterVersionName = "clusterversion-for-ops-" + randomStr clusterName = "cluster-for-ops-" + randomStr ) @@ -46,7 +45,7 @@ var _ = Describe("Stop OpsRequest", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) // delete rest resources @@ -64,7 +63,7 @@ var _ = Describe("Stop OpsRequest", func() { Context("Test OpsRequest", func() { It("Test stop OpsRequest", func() { reqCtx := intctrlutil.RequestCtx{Ctx: ctx} - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) testapps.MockInstanceSetComponent(&testCtx, clusterName, statelessComp) testapps.MockInstanceSetComponent(&testCtx, clusterName, statefulComp) diff --git a/controllers/apps/operations/suite_test.go b/controllers/apps/operations/suite_test.go index c9a2716f90c2..37e2e881c638 100644 --- a/controllers/apps/operations/suite_test.go +++ b/controllers/apps/operations/suite_test.go @@ -149,11 +149,9 @@ var _ = AfterSuite(func() { }) // initOperationsResources inits the operations resources. -func initOperationsResources(clusterDefinitionName, - clusterVersionName, - clusterName string) (*OpsResource, *appsv1alpha1.ClusterDefinition, *appsv1alpha1.Cluster) { - clusterDef, _, clusterObject := testapps.InitClusterWithHybridComps(&testCtx, clusterDefinitionName, - clusterVersionName, clusterName, statelessComp, statefulComp, consensusComp) +func initOperationsResources(clusterDefinitionName, clusterName string) (*OpsResource, *appsv1alpha1.ClusterDefinition, *appsv1alpha1.Cluster) { + clusterDef, clusterObject := testapps.InitClusterWithHybridComps(&testCtx, clusterDefinitionName, + clusterName, statelessComp, statefulComp, consensusComp) opsRes := &OpsResource{ Cluster: clusterObject, Recorder: k8sManager.GetEventRecorderFor("opsrequest-controller"), diff --git a/controllers/apps/operations/switchover_test.go b/controllers/apps/operations/switchover_test.go index fea740feeff6..d6f58963ba8a 100644 --- a/controllers/apps/operations/switchover_test.go +++ b/controllers/apps/operations/switchover_test.go @@ -38,16 +38,14 @@ import ( ) var ( - clusterDefObj *appsv1alpha1.ClusterDefinition - clusterVersionObj *appsv1alpha1.ClusterVersion - clusterObj *appsv1alpha1.Cluster + clusterDefObj *appsv1alpha1.ClusterDefinition + clusterObj *appsv1alpha1.Cluster ) var _ = Describe("", func() { var ( - randomStr = testCtx.GetRandomStr() - clusterVersionName = "cluster-version-for-ops-" + randomStr - clusterName = "cluster-for-ops-" + randomStr + randomStr = testCtx.GetRandomStr() + clusterName = "cluster-for-ops-" + randomStr ) defaultRole := func(index int32) string { @@ -80,7 +78,7 @@ var _ = Describe("", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) // delete rest resources @@ -122,11 +120,6 @@ var _ = Describe("", func() { AddComponentDef(testapps.ConsensusMySQLComponent, consensusComp). AddSwitchoverSpec(switchoverSpec). Create(&testCtx).GetObject() - - By("Create a clusterVersion obj with replication workloadType.") - clusterVersionObj = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefObj.GetName()). - AddComponentVersion(consensusComp).AddContainerShort(testapps.DefaultMySQLContainerName, testapps.ApeCloudMySQLImage). - Create(&testCtx).GetObject() }) It("Test switchover OpsRequest", func() { @@ -135,8 +128,8 @@ var _ = Describe("", func() { Recorder: k8sManager.GetEventRecorderFor("opsrequest-controller"), } By("Creating a cluster with consensus .") - clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDefObj.Name, clusterVersionObj.Name).WithRandomName(). + clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). + WithRandomName(). AddComponent(consensusComp, consensusComp). SetReplicas(2). Create(&testCtx).GetObject() diff --git a/controllers/apps/operations/switchover_util_test.go b/controllers/apps/operations/switchover_util_test.go index c023f8496dbc..ee27b520eab3 100644 --- a/controllers/apps/operations/switchover_util_test.go +++ b/controllers/apps/operations/switchover_util_test.go @@ -39,15 +39,13 @@ import ( var _ = Describe("Switchover Util", func() { var ( - clusterName = "test-cluster-repl" - clusterDefName = "test-cluster-def-repl" - clusterVersionName = "test-cluster-version-repl" + clusterName = "test-cluster-repl" + clusterDefName = "test-cluster-def-repl" ) var ( - clusterDefObj *appsv1alpha1.ClusterDefinition - clusterVersionObj *appsv1alpha1.ClusterVersion - clusterObj *appsv1alpha1.Cluster + clusterDefObj *appsv1alpha1.ClusterDefinition + clusterObj *appsv1alpha1.Cluster ) defaultRole := func(index int32) string { @@ -64,7 +62,7 @@ var _ = Describe("Switchover Util", func() { // in race conditions, it will find the existence of old objects, resulting failure to // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) // clear rest resources @@ -81,8 +79,8 @@ var _ = Describe("Switchover Util", func() { testNeedDoSwitchover := func() { By("Creating a cluster with replication workloadType.") - clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDefObj.Name, clusterVersionObj.Name).WithRandomName(). + clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). + WithRandomName(). AddComponent(testapps.DefaultRedisCompSpecName, testapps.DefaultRedisCompDefName). SetReplicas(testapps.DefaultReplicationReplicas). Create(&testCtx).GetObject() @@ -145,8 +143,8 @@ var _ = Describe("Switchover Util", func() { testDoSwitchover := func() { By("Creating a cluster with replication workloadType.") - clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDefObj.Name, clusterVersionObj.Name).WithRandomName(). + clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). + WithRandomName(). AddComponent(testapps.DefaultRedisCompSpecName, testapps.DefaultRedisCompDefName). SetReplicas(testapps.DefaultReplicationReplicas). Create(&testCtx).GetObject() @@ -231,12 +229,6 @@ var _ = Describe("Switchover Util", func() { AddComponentDef(testapps.ReplicationRedisComponent, testapps.DefaultRedisCompDefName). AddSwitchoverSpec(switchoverSpec). Create(&testCtx).GetObject() - - By("Create a clusterVersion obj with replication workloadType.") - clusterVersionObj = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefObj.GetName()). - AddComponentVersion(testapps.DefaultRedisCompDefName).AddContainerShort(testapps.DefaultRedisContainerName, testapps.DefaultRedisImageName). - Create(&testCtx).GetObject() - }) It("Test needDoSwitchover with different conditions", func() { diff --git a/controllers/apps/operations/upgrade.go b/controllers/apps/operations/upgrade.go index ae4606e069f3..ec3a5e51157d 100644 --- a/controllers/apps/operations/upgrade.go +++ b/controllers/apps/operations/upgrade.go @@ -20,7 +20,6 @@ along with this program. If not, see . package operations import ( - "context" "fmt" "time" @@ -55,13 +54,11 @@ func (u upgradeOpsHandler) ActionStartedCondition(reqCtx intctrlutil.RequestCtx, return appsv1alpha1.NewHorizontalScalingCondition(opsRes.OpsRequest), nil } -// Action modifies Cluster.spec.clusterVersionRef with opsRequest.spec.upgrade.clusterVersionRef func (u upgradeOpsHandler) Action(reqCtx intctrlutil.RequestCtx, cli client.Client, opsRes *OpsResource) error { var compOpsHelper componentOpsHelper upgradeSpec := opsRes.OpsRequest.Spec.Upgrade if u.existClusterVersion(opsRes.OpsRequest) { - // TODO: remove this deprecated API after v0.9 - opsRes.Cluster.Spec.ClusterVersionRef = *opsRes.OpsRequest.Spec.Upgrade.ClusterVersionRef + return fmt.Errorf("not implemented") } else { compOpsHelper = newComponentOpsHelper(upgradeSpec.Components) if err := compOpsHelper.updateClusterComponentsAndShardings(opsRes.Cluster, func(compSpec *appsv1alpha1.ClusterComponentSpec, obj ComponentOpsInterface) error { @@ -101,17 +98,12 @@ func (u upgradeOpsHandler) Action(reqCtx intctrlutil.RequestCtx, cli client.Clie func (u upgradeOpsHandler) ReconcileAction(reqCtx intctrlutil.RequestCtx, cli client.Client, opsRes *OpsResource) (appsv1alpha1.OpsPhase, time.Duration, error) { upgradeSpec := opsRes.OpsRequest.Spec.Upgrade var ( - compOpsHelper componentOpsHelper - componentDefMap map[string]*appsv1alpha1.ComponentDefinition - componentVersionMap map[string]appsv1alpha1.ClusterComponentVersion - err error + compOpsHelper componentOpsHelper + componentDefMap map[string]*appsv1alpha1.ComponentDefinition + err error ) if u.existClusterVersion(opsRes.OpsRequest) { - // TODO: remove this deprecated API after v0.9 - compOpsHelper = newComponentOpsHelper(u.getCompOpsListForClusterVersion(opsRes)) - if componentVersionMap, err = u.getClusterComponentVersionMap(reqCtx.Ctx, cli, *upgradeSpec.ClusterVersionRef); err != nil { - return opsRes.OpsRequest.Status.Phase, 0, err - } + return appsv1alpha1.OpsFailedPhase, 0, fmt.Errorf("not implemented") } else { compOpsHelper = newComponentOpsHelper(upgradeSpec.Components) if componentDefMap, err = u.getComponentDefMapWithUpdatedImages(reqCtx, cli, opsRes); err != nil { @@ -136,16 +128,7 @@ func (u upgradeOpsHandler) ReconcileAction(reqCtx intctrlutil.RequestCtx, cli cl compOps ComponentOpsInterface, insTemplateName string) bool { if u.existClusterVersion(opsRes.OpsRequest) { - // TODO: remove this deprecated API after v0.9 - compSpec := getComponentSpecOrShardingTemplate(opsRes.Cluster, compOps.GetComponentName()) - if compSpec == nil { - return true - } - compVersion, ok := componentVersionMap[compSpec.ComponentDefRef] - if !ok { - return true - } - return u.podImageApplied(pod, compVersion.VersionsCtx.Containers) + return false } upgradeComponent := compOps.(appsv1alpha1.UpgradeComponent) lastCompConfiguration := opsRes.OpsRequest.Status.LastConfiguration.Components[compOps.GetComponentName()] @@ -171,7 +154,6 @@ func (u upgradeOpsHandler) ReconcileAction(reqCtx intctrlutil.RequestCtx, cli cl // SaveLastConfiguration records last configuration to the OpsRequest.status.lastConfiguration func (u upgradeOpsHandler) SaveLastConfiguration(reqCtx intctrlutil.RequestCtx, cli client.Client, opsRes *OpsResource) error { - opsRes.OpsRequest.Status.LastConfiguration.ClusterVersionRef = opsRes.Cluster.Spec.ClusterVersionRef compOpsHelper := newComponentOpsHelper(opsRes.OpsRequest.Spec.Upgrade.Components) compOpsHelper.saveLastConfigurations(opsRes, func(compSpec appsv1alpha1.ClusterComponentSpec, comOps ComponentOpsInterface) appsv1alpha1.LastComponentConfiguration { return appsv1alpha1.LastComponentConfiguration{ @@ -182,31 +164,6 @@ func (u upgradeOpsHandler) SaveLastConfiguration(reqCtx intctrlutil.RequestCtx, return nil } -// getClusterComponentVersionMap gets the components of ClusterVersion and converts the component list to map. -func (u upgradeOpsHandler) getClusterComponentVersionMap(ctx context.Context, - cli client.Client, clusterVersionName string) (map[string]appsv1alpha1.ClusterComponentVersion, error) { - clusterVersion := &appsv1alpha1.ClusterVersion{} - if err := cli.Get(ctx, client.ObjectKey{Name: clusterVersionName}, clusterVersion); err != nil { - return nil, client.IgnoreNotFound(err) - } - components := map[string]appsv1alpha1.ClusterComponentVersion{} - for _, v := range clusterVersion.Spec.ComponentVersions { - components[v.ComponentDefRef] = v - } - return components, nil -} - -func (u upgradeOpsHandler) getCompOpsListForClusterVersion(opsRes *OpsResource) []appsv1alpha1.ComponentOps { - var compOpsList []appsv1alpha1.ComponentOps - for _, v := range opsRes.Cluster.Spec.ComponentSpecs { - compOpsList = append(compOpsList, appsv1alpha1.ComponentOps{ComponentName: v.Name}) - } - for _, v := range opsRes.Cluster.Spec.ShardingSpecs { - compOpsList = append(compOpsList, appsv1alpha1.ComponentOps{ComponentName: v.Name}) - } - return compOpsList -} - // getComponentDefMapWithUpdatedImages gets the desired componentDefinition map // that is updated with the corresponding images of the ComponentDefinition and service version. func (u upgradeOpsHandler) getComponentDefMapWithUpdatedImages(reqCtx intctrlutil.RequestCtx, diff --git a/controllers/apps/operations/upgrade_test.go b/controllers/apps/operations/upgrade_test.go index 61f3b45a9f3e..0e363b95e638 100644 --- a/controllers/apps/operations/upgrade_test.go +++ b/controllers/apps/operations/upgrade_test.go @@ -20,10 +20,9 @@ along with this program. If not, see . package operations import ( - "fmt" - . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" "k8s.io/utils/pointer" "sigs.k8s.io/controller-runtime/pkg/client" @@ -37,20 +36,17 @@ import ( var _ = Describe("Upgrade OpsRequest", func() { var ( - randomStr = testCtx.GetRandomStr() - clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterVersionName = "clusterversion-for-ops-" + randomStr - clusterName = "cluster-for-ops-" + randomStr - serviceVer0 = testapps.ServiceVersion("v0") - serviceVer1 = testapps.ServiceVersion("v1") - serviceVer2 = testapps.ServiceVersion("v2") - release0 = testapps.ReleaseID("r0") - release1 = testapps.ReleaseID("r1") - release2 = testapps.ReleaseID("r2") - release3 = testapps.ReleaseID("r3") - release4 = testapps.ReleaseID("r4") + randomStr = testCtx.GetRandomStr() + clusterName = "cluster-for-ops-" + randomStr + serviceVer0 = testapps.ServiceVersion("v0") + serviceVer1 = testapps.ServiceVersion("v1") + serviceVer2 = testapps.ServiceVersion("v2") + release0 = testapps.ReleaseID("r0") + release1 = testapps.ReleaseID("r1") + release2 = testapps.ReleaseID("r2") + release3 = testapps.ReleaseID("r3") + release4 = testapps.ReleaseID("r4") ) - const mysqlImageForUpdate = "docker.io/apecloud/apecloud-mysql-server:8.0.30" 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, @@ -58,7 +54,7 @@ var _ = Describe("Upgrade OpsRequest", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) // delete rest resources @@ -187,7 +183,7 @@ var _ = Describe("Upgrade OpsRequest", func() { })).Should(Succeed()) } // create the cluster with no clusterDefinition - clusterObject := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, "", ""). + clusterObject := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). AddComponentV2(consensusComp, compDef1.Name). SetServiceVersion(testapps.ServiceVersion("v0")). SetReplicas(int32(3)).Create(&testCtx).GetObject() @@ -239,43 +235,6 @@ var _ = Describe("Upgrade OpsRequest", func() { } Context("Test OpsRequest", func() { - It("Test upgrade OpsRequest with ClusterVersion", func() { - By("init operations resources ") - reqCtx := intctrlutil.RequestCtx{Ctx: ctx} - opsRes, _, clusterObject := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) - - By("create Upgrade Ops") - newClusterVersionName := "clusterversion-upgrade-" + randomStr - _ = testapps.NewClusterVersionFactory(newClusterVersionName, clusterDefinitionName). - AddComponentVersion(consensusComp).AddContainerShort(testapps.DefaultMySQLContainerName, mysqlImageForUpdate). - Create(&testCtx).GetObject() - opsRes.OpsRequest = createUpgradeOpsRequest(clusterObject, appsv1alpha1.Upgrade{ClusterVersionRef: &newClusterVersionName}) - - By("mock upgrade OpsRequest phase is Running") - makeUpgradeOpsIsRunning(reqCtx, opsRes) - - By("expect upgrade successfully") - _ = testapps.MockInstanceSetPod(&testCtx, nil, clusterName, statelessComp, fmt.Sprintf(clusterName+"-"+statelessComp+"-0"), "", "") - _ = testapps.MockInstanceSetPods(&testCtx, nil, clusterObject, statefulComp) - pods := testapps.MockInstanceSetPods(&testCtx, nil, clusterObject, consensusComp) - for i := range pods { - pod := pods[i] - Expect(testapps.ChangeObj(&testCtx, pod, func(pod *corev1.Pod) { - pod.Spec.Containers[0].Image = mysqlImageForUpdate - })).Should(Succeed()) - Expect(testapps.ChangeObjStatus(&testCtx, pod, func() { - pod.Status.ContainerStatuses = []corev1.ContainerStatus{ - { - Name: testapps.DefaultMySQLContainerName, - Image: mysqlImageForUpdate, - }, - } - })).Should(Succeed()) - } - // mock component to running - expectOpsSucceed(reqCtx, opsRes, consensusComp, statelessComp, statefulComp) - }) - It("Test upgrade OpsRequest with ComponentDef and no ComponentVersion", func() { By("init operations resources ") compDef1, compDef2, opsRes := initOpsResWithComponentDef(false) diff --git a/controllers/apps/operations/util/common_util_test.go b/controllers/apps/operations/util/common_util_test.go index 4e2cd7e75dac..d87c54aa02a9 100644 --- a/controllers/apps/operations/util/common_util_test.go +++ b/controllers/apps/operations/util/common_util_test.go @@ -36,7 +36,6 @@ var _ = Describe("OpsRequest Controller", func() { var ( randomStr = testCtx.GetRandomStr() clusterDefinitionName = "cluster-definition-" + randomStr - clusterVersionName = "clusterversion-" + randomStr clusterName = "cluster-" + randomStr consensusCompName = "consensus" ) @@ -61,7 +60,7 @@ var _ = Describe("OpsRequest Controller", func() { Context("Test OpsRequest", func() { It("Should Test all OpsRequest", func() { cluster := testapps.CreateConsensusMysqlCluster(&testCtx, clusterDefinitionName, - clusterVersionName, clusterName, "consensus", consensusCompName) + clusterName, "consensus", consensusCompName) By("init restart OpsRequest") testOpsName := "restart-" + randomStr ops := testapps.NewOpsRequestObj(testOpsName, testCtx.DefaultNamespace, diff --git a/controllers/apps/operations/vertical_scaling_test.go b/controllers/apps/operations/vertical_scaling_test.go index 43a52123f477..becba4bda50d 100644 --- a/controllers/apps/operations/vertical_scaling_test.go +++ b/controllers/apps/operations/vertical_scaling_test.go @@ -44,7 +44,6 @@ var _ = Describe("VerticalScaling OpsRequest", func() { var ( randomStr = testCtx.GetRandomStr() clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterVersionName = "clusterversion-for-ops-" + randomStr clusterName = "cluster-for-ops-" + randomStr reqCtx intctrlutil.RequestCtx ) @@ -55,7 +54,7 @@ var _ = Describe("VerticalScaling OpsRequest", func() { // in race conditions, it will find the existence of old objects, resulting failure to // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) // delete rest resources @@ -73,7 +72,7 @@ var _ = Describe("VerticalScaling OpsRequest", func() { testVerticalScaling := func(verticalScaling []appsv1alpha1.VerticalScaling) *OpsResource { By("init operations resources ") - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) By("create VerticalScaling ops") ops := testapps.NewOpsRequestObj("vertical-scaling-ops-"+randomStr, testCtx.DefaultNamespace, @@ -117,9 +116,9 @@ var _ = Describe("VerticalScaling OpsRequest", func() { }) It("cancel vertical scaling opsRequest", func() { - By("init operations resources with CLusterDefinition/ClusterVersion/Hybrid components Cluster/consensus Pods") + By("init operations resources with CLusterDefinition/Hybrid components Cluster/consensus Pods") reqCtx := intctrlutil.RequestCtx{Ctx: ctx} - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterVersionName, clusterName) + opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) podList := initInstanceSetPods(ctx, k8sClient, opsRes) By("create VerticalScaling ops") diff --git a/controllers/apps/operations/volume_expansion_test.go b/controllers/apps/operations/volume_expansion_test.go index 2aead9931e27..7da6f5ce5301 100644 --- a/controllers/apps/operations/volume_expansion_test.go +++ b/controllers/apps/operations/volume_expansion_test.go @@ -45,7 +45,6 @@ var _ = Describe("OpsRequest Controller Volume Expansion Handler", func() { // waitDuration = time.Second * 3 randomStr = testCtx.GetRandomStr() clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterVersionName = "clusterversion-for-ops-" + randomStr clusterName = "cluster-for-ops-" + randomStr storageClassName = "csi-hostpath-sc-" + randomStr ) @@ -62,7 +61,7 @@ var _ = Describe("OpsRequest Controller Volume Expansion Handler", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) // delete rest resources @@ -219,8 +218,8 @@ var _ = Describe("OpsRequest Controller Volume Expansion Handler", func() { Context("Test VolumeExpansion", func() { It("VolumeExpansion should work", func() { reqCtx := intctrlutil.RequestCtx{Ctx: ctx} - _, _, clusterObject := testapps.InitConsensusMysql(&testCtx, clusterDefinitionName, - clusterVersionName, clusterName, "consensus", consensusCompName) + _, clusterObject := testapps.InitConsensusMysql(&testCtx, clusterDefinitionName, + clusterName, "consensus", consensusCompName) // init storageClass sc := testapps.CreateStorageClass(&testCtx, storageClassName, true) Expect(testapps.ChangeObj(&testCtx, sc, func(lsc *storagev1.StorageClass) { diff --git a/controllers/apps/opsrequest_controller_test.go b/controllers/apps/opsrequest_controller_test.go index 522122dab7f9..3e49d66a7186 100644 --- a/controllers/apps/opsrequest_controller_test.go +++ b/controllers/apps/opsrequest_controller_test.go @@ -53,7 +53,6 @@ import ( var _ = Describe("OpsRequest Controller", func() { const clusterDefName = "test-clusterdef" - const clusterVersionName = "test-clusterversion" const clusterNamePrefix = "test-cluster" const mysqlCompDefName = "mysql" const mysqlCompName = "mysql" @@ -84,7 +83,7 @@ var _ = Describe("OpsRequest Controller", func() { testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, intctrlutil.OpsRequestSignature, true, inNS, ml) testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, intctrlutil.VolumeSnapshotSignature, true, inNS) - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition // TODO(review): why finalizers not removed testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) testapps.ClearResources(&testCtx, intctrlutil.StorageClassSignature, ml) @@ -102,10 +101,9 @@ var _ = Describe("OpsRequest Controller", func() { }) var ( - clusterDefObj *appsv1alpha1.ClusterDefinition - clusterVersionObj *appsv1alpha1.ClusterVersion - clusterObj *appsv1alpha1.Cluster - clusterKey types.NamespacedName + clusterDefObj *appsv1alpha1.ClusterDefinition + clusterObj *appsv1alpha1.Cluster + clusterKey types.NamespacedName ) mockSetClusterStatusPhaseToRunning := func(namespacedName types.NamespacedName) { @@ -139,8 +137,8 @@ var _ = Describe("OpsRequest Controller", func() { const opsName = "mysql-verticalscaling" By("Create a cluster obj") - clusterFactory := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterNamePrefix, - clusterDefObj.Name, clusterVersionObj.Name).WithRandomName(). + clusterFactory := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterNamePrefix, clusterDefObj.Name). + WithRandomName(). AddComponent(mysqlCompName, mysqlCompDefName). SetReplicas(1). SetResources(scalingCtx.source) @@ -241,11 +239,6 @@ var _ = Describe("OpsRequest Controller", func() { clusterDefObj = testapps.NewClusterDefFactory(clusterDefName). AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). Create(&testCtx).GetObject() - - By("Create a clusterVersion obj") - clusterVersionObj = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefObj.GetName()). - AddComponentVersion(mysqlCompDefName).AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - Create(&testCtx).GetObject() }) It("create cluster by resource, vertical scaling by resource", func() { @@ -268,11 +261,6 @@ var _ = Describe("OpsRequest Controller", func() { BackupPolicyTemplateName: backupPolicyTPLName, }).Create(&testCtx).GetObject() - By("Create a clusterVersion obj") - clusterVersionObj = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefObj.GetName()). - AddComponentVersion(mysqlCompDefName).AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - Create(&testCtx).GetObject() - By("Mock lorry client for the default transformer of system accounts provision") mockLorryClientDefault() }) @@ -331,8 +319,8 @@ var _ = Describe("OpsRequest Controller", func() { })()).ShouldNot(HaveOccurred()) } pvcSpec := testapps.NewPVCSpec("1Gi") - clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterNamePrefix, - clusterDefObj.Name, clusterVersionObj.Name).WithRandomName(). + clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterNamePrefix, clusterDefObj.Name). + WithRandomName(). AddComponent(mysqlCompName, mysqlCompDefName). SetReplicas(replicas). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). diff --git a/controllers/apps/servicedescriptor_controller_test.go b/controllers/apps/servicedescriptor_controller_test.go index 43e1fa5fa113..7603fd10c00d 100644 --- a/controllers/apps/servicedescriptor_controller_test.go +++ b/controllers/apps/servicedescriptor_controller_test.go @@ -31,7 +31,7 @@ import ( testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" ) -var _ = Describe("test clusterVersion controller", func() { +var _ = Describe("test ServiceDescriptor controller", func() { var ( randomStr = testCtx.GetRandomStr() @@ -45,7 +45,7 @@ var _ = Describe("test clusterVersion controller", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) } BeforeEach(cleanEnv) diff --git a/controllers/apps/suite_test.go b/controllers/apps/suite_test.go index 125d17ea2829..2d7b04cca72f 100644 --- a/controllers/apps/suite_test.go +++ b/controllers/apps/suite_test.go @@ -194,13 +194,6 @@ var _ = BeforeSuite(func() { }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) - err = (&ClusterVersionReconciler{ - Client: k8sManager.GetClient(), - Scheme: k8sManager.GetScheme(), - Recorder: k8sManager.GetEventRecorderFor("cluster-version-controller"), - }).SetupWithManager(k8sManager) - Expect(err).ToNot(HaveOccurred()) - err = (&ComponentReconciler{ Client: k8sManager.GetClient(), Scheme: k8sManager.GetScheme(), diff --git a/controllers/apps/transformer_cluster_api_normalization.go b/controllers/apps/transformer_cluster_api_normalization.go index 11bc39404db0..48c442414711 100644 --- a/controllers/apps/transformer_cluster_api_normalization.go +++ b/controllers/apps/transformer_cluster_api_normalization.go @@ -236,7 +236,7 @@ func (t *ClusterAPINormalizationTransformer) resolveCompDefinitionNServiceVersio func (t *ClusterAPINormalizationTransformer) buildCompDefinition4Legacy(transCtx *clusterTransformContext, compSpec *appsv1alpha1.ClusterComponentSpec) (*appsv1alpha1.ComponentDefinition, error) { - compDef, err := component.BuildComponentDefinition(transCtx.ClusterDef, transCtx.ClusterVer, compSpec) + compDef, err := component.BuildComponentDefinition(transCtx.ClusterDef, compSpec) if err != nil { return nil, err } diff --git a/controllers/apps/transformer_cluster_backup_policy.go b/controllers/apps/transformer_cluster_backup_policy.go index ff741bbf6ab5..b708ba1c75ca 100644 --- a/controllers/apps/transformer_cluster_backup_policy.go +++ b/controllers/apps/transformer_cluster_backup_policy.go @@ -443,15 +443,6 @@ func (r *clusterBackupPolicyTransformer) syncBackupMethods(backupPolicy *dpv1alp func (r *clusterBackupPolicyTransformer) doEnvMapping(comp *appsv1alpha1.ClusterComponentSpec, envMapping []appsv1alpha1.EnvMappingVar) []corev1.EnvVar { var env []corev1.EnvVar for _, v := range envMapping { - for _, cv := range v.ValueFrom.ClusterVersionRef { - if !slices.Contains(cv.Names, r.Cluster.Spec.ClusterVersionRef) { - continue - } - env = append(env, corev1.EnvVar{ - Name: v.Key, - Value: cv.MappingValue, - }) - } for _, cm := range v.ValueFrom.ComponentDef { if !slices.Contains(cm.Names, comp.ComponentDef) { continue diff --git a/controllers/apps/transformer_cluster_component_test.go b/controllers/apps/transformer_cluster_component_test.go index 03b32dcb57d6..2f474599a5be 100644 --- a/controllers/apps/transformer_cluster_component_test.go +++ b/controllers/apps/transformer_cluster_component_test.go @@ -241,7 +241,7 @@ var _ = Describe("cluster component transformer test", func() { } newTransformerNCtx := func(topology string) (graph.Transformer, *clusterTransformContext, *graph.DAG) { - cluster := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefName, ""). + cluster := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefName). WithRandomName(). SetTopology(topology). SetReplicas(1). diff --git a/controllers/apps/transformer_cluster_deletion_test.go b/controllers/apps/transformer_cluster_deletion_test.go index 63252f719277..8c07e29ac3d0 100644 --- a/controllers/apps/transformer_cluster_deletion_test.go +++ b/controllers/apps/transformer_cluster_deletion_test.go @@ -66,7 +66,7 @@ var _ = Describe("clusterDeletionTransformer", func() { GetObject() clusterDef.Status.Phase = appsv1alpha1.AvailablePhase - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, "test-cluster", clusterDef.Name, ""). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, "test-cluster", clusterDef.Name). SetTopology(clusterDef.Spec.Topologies[0].Name). AddComponentV2("comp1", "compdef1"). AddComponentV2("comp2", "compdef2"). diff --git a/controllers/apps/transformer_cluster_halt_recovering.go b/controllers/apps/transformer_cluster_halt_recovering.go index d4c0b45f3b7d..bd1a4df0c543 100644 --- a/controllers/apps/transformer_cluster_halt_recovering.go +++ b/controllers/apps/transformer_cluster_halt_recovering.go @@ -107,17 +107,6 @@ func (t *clusterHaltRecoveryTransformer) Transform(ctx graph.TransformContext, d }) } - // check clusterVersionRef equality but allow clusters.apps.kubeblocks.io/allow-inconsistent-cv=true annotation override - if cluster.Spec.ClusterVersionRef != lc.Spec.ClusterVersionRef && - cluster.Annotations[constant.HaltRecoveryAllowInconsistentCVAnnotKey] != trueVal { - return emitError(metav1.Condition{ - Type: appsv1alpha1.ConditionTypeHaltRecovery, - Reason: "HaltRecoveryFailed", - Message: fmt.Sprintf("not equal to last applied cluster.spec.clusterVersionRef %s; add '%s=true' annotation if void this check", - lc.Spec.ClusterVersionRef, constant.HaltRecoveryAllowInconsistentCVAnnotKey), - }) - } - // check component len equality if l := len(lc.Spec.ComponentSpecs); l != len(cluster.Spec.ComponentSpecs) { return emitError(metav1.Condition{ diff --git a/controllers/apps/transformer_cluster_load_resources.go b/controllers/apps/transformer_cluster_load_resources.go index 2e0a6de7a1f0..a3c9ce3a7bfa 100644 --- a/controllers/apps/transformer_cluster_load_resources.go +++ b/controllers/apps/transformer_cluster_load_resources.go @@ -54,10 +54,6 @@ func (t *clusterLoadRefResourcesTransformer) Transform(ctx graph.TransformContex return newRequeueError(requeueDuration, err.Error()) } - if err = loadNCheckClusterVersion(transCtx, cluster); err != nil { - return newRequeueError(requeueDuration, err.Error()) - } - if withClusterTopology(cluster) { // check again with cluster definition loaded, // and update topology to cluster spec in case the default topology changed. @@ -126,32 +122,6 @@ func loadNCheckClusterDefinition(transCtx *clusterTransformContext, cluster *app return nil } -func loadNCheckClusterVersion(transCtx *clusterTransformContext, cluster *appsv1alpha1.Cluster) error { - var cv *appsv1alpha1.ClusterVersion - if len(cluster.Spec.ClusterVersionRef) > 0 { - cv = &appsv1alpha1.ClusterVersion{} - key := types.NamespacedName{Name: cluster.Spec.ClusterVersionRef} - if err := transCtx.Client.Get(transCtx.Context, key, cv); err != nil { - return err - } - } - - if cv != nil { - if cv.Generation != cv.Status.ObservedGeneration { - return fmt.Errorf("the referenced ClusterVersion is not up to date: %s", cv.Name) - } - if cv.Status.Phase != appsv1alpha1.AvailablePhase { - return fmt.Errorf("the referenced ClusterVersion is unavailable: %s", cv.Name) - } - } - - if cv == nil { - cv = &appsv1alpha1.ClusterVersion{} - } - transCtx.ClusterVer = cv - return nil -} - func withClusterTopology(cluster *appsv1alpha1.Cluster) bool { return len(cluster.Spec.ClusterDefRef) > 0 && legacyClusterCompCnt(cluster) == 0 && !compatibleUserDefinedInNewAPI(cluster) } diff --git a/controllers/apps/transformer_cluster_meta.go b/controllers/apps/transformer_cluster_meta.go index 992bcf88427e..1848b40565ef 100644 --- a/controllers/apps/transformer_cluster_meta.go +++ b/controllers/apps/transformer_cluster_meta.go @@ -47,13 +47,11 @@ func (t *clusterAssureMetaTransformer) Transform(ctx graph.TransformContext, dag labels = map[string]string{} } cdLabelName := labels[constant.ClusterDefLabelKey] - cvLabelName := labels[constant.ClusterVerLabelKey] - cdName, cvName := cluster.Spec.ClusterDefRef, cluster.Spec.ClusterVersionRef - if cdLabelName == cdName && cvLabelName == cvName { + cdName := cluster.Spec.ClusterDefRef + if cdLabelName == cdName { return nil } labels[constant.ClusterDefLabelKey] = cdName - labels[constant.ClusterVerLabelKey] = cvName cluster.Labels = labels return nil diff --git a/controllers/apps/transformer_component_rbac_test.go b/controllers/apps/transformer_component_rbac_test.go index 0b26d740b5cd..fe461c83c35b 100644 --- a/controllers/apps/transformer_component_rbac_test.go +++ b/controllers/apps/transformer_component_rbac_test.go @@ -63,7 +63,7 @@ var _ = Describe("object rbac transformer test.", func() { GetObject() By("Creating a cluster") - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, "", ""). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). WithRandomName(). AddComponentV2(compName, compDefName). SetReplicas(1). diff --git a/controllers/apps/transformer_component_tls_test.go b/controllers/apps/transformer_component_tls_test.go index 850e245eec3f..a21df0c8cbaf 100644 --- a/controllers/apps/transformer_component_tls_test.go +++ b/controllers/apps/transformer_component_tls_test.go @@ -46,7 +46,6 @@ import ( var _ = Describe("TLS self-signed cert function", func() { const ( clusterDefName = "test-clusterdef-tls" - clusterVersionName = "test-clusterversion-tls" clusterNamePrefix = "test-cluster" statefulCompDefName = "mysql" statefulCompName = "mysql" @@ -65,7 +64,7 @@ var _ = Describe("TLS self-signed cert function", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest configurations @@ -98,12 +97,6 @@ var _ = Describe("TLS self-signed cert function", func() { AddConfigTemplate(configSpecName, configMapObj.Name, configConstraintObj.Name, testCtx.DefaultNamespace, testapps.ConfVolumeName). AddContainerEnv(mysqlContainerName, corev1.EnvVar{Name: "MYSQL_ALLOW_EMPTY_PASSWORD", Value: "yes"}). CheckedCreate(&testCtx).GetObject() - - By("Create a clusterVersion obj") - testapps.NewClusterVersionFactory(clusterVersionName, clusterDefName). - AddComponentVersion(statefulCompDefName).AddContainerShort(mysqlContainerName, testapps.ApeCloudMySQLImage). - CheckedCreate(&testCtx).GetObject() - }) Context("when issuer is UserProvided", func() { @@ -137,7 +130,7 @@ var _ = Describe("TLS self-signed cert function", func() { }, } By("create cluster obj") - clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterNamePrefix, clusterDefName, clusterVersionName). + clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterNamePrefix, clusterDefName). WithRandomName(). AddComponent(statefulCompName, statefulCompDefName). SetReplicas(3). @@ -155,7 +148,7 @@ var _ = Describe("TLS self-signed cert function", func() { Context("when switch between disabled and enabled", func() { It("should handle tls settings properly", func() { By("create cluster with tls disabled") - clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterNamePrefix, clusterDefName, clusterVersionName). + clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterNamePrefix, clusterDefName). WithRandomName(). AddComponent(statefulCompName, statefulCompDefName). SetReplicas(3). diff --git a/controllers/extensions/addon_controller_test.go b/controllers/extensions/addon_controller_test.go index d8d7c8922584..d44b1029c9ca 100644 --- a/controllers/extensions/addon_controller_test.go +++ b/controllers/extensions/addon_controller_test.go @@ -53,11 +53,7 @@ import ( var _ = Describe("Addon controller", func() { const ( - clusterDefName = "test-clusterdef" - clusterVersionName = "test-clusterversion" - compDefName = "test-compdef" - compVersionName = "test-compversion" - clusterName = "test-cluster" + clusterName = "test-cluster" ) cleanEnv := func() { // must wait till resources deleted and no longer existed before the testcases start, @@ -843,8 +839,7 @@ var _ = Describe("Addon controller", func() { fakeInstallationCompletedJob(2) By("By creating cluster with addon") - clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - "test-cd", "test-cv"). + clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, "test-cd"). AddComponent(addon.Name, addon.Name).SetReplicas(1). WithRandomName(). AddLabels(constant.ClusterDefLabelKey, addon.Name). @@ -884,8 +879,7 @@ var _ = Describe("Addon controller", func() { fakeInstallationCompletedJob(2) By("By creating cluster with addon") - clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - "test-cd", "test-cv"). + clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, "test-cd"). AddComponent(addon.Name, addon.Name).SetReplicas(1). WithRandomName(). AddLabels(constant.ClusterDefLabelKey, addon.Name). diff --git a/controllers/k8score/event_controller_test.go b/controllers/k8score/event_controller_test.go index c9ac185f55ac..6020aedaa4d6 100644 --- a/controllers/k8score/event_controller_test.go +++ b/controllers/k8score/event_controller_test.go @@ -125,8 +125,8 @@ var _ = Describe("Event Controller", func() { clusterDefObj := testapps.NewClusterDefFactory(clusterDefName). AddComponentDef(testapps.ConsensusMySQLComponent, consensusCompDefName). Create(&testCtx).GetObject() - clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, "", - clusterDefObj.Name, "").WithRandomName(). + clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, "", clusterDefObj.Name). + WithRandomName(). AddComponent(consensusCompName, consensusCompDefName). Create(&testCtx).GetObject() Eventually(testapps.CheckObjExists(&testCtx, client.ObjectKeyFromObject(clusterObj), &appsv1alpha1.Cluster{}, true)).Should(Succeed()) diff --git a/deploy/helm/config/rbac/role.yaml b/deploy/helm/config/rbac/role.yaml index 8f6b142af93b..aac6ca93aabf 100644 --- a/deploy/helm/config/rbac/role.yaml +++ b/deploy/helm/config/rbac/role.yaml @@ -122,32 +122,6 @@ rules: - get - patch - update -- apiGroups: - - apps.kubeblocks.io - resources: - - clusterversions - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - apps.kubeblocks.io - resources: - - clusterversions/finalizers - verbs: - - update -- apiGroups: - - apps.kubeblocks.io - resources: - - clusterversions/status - verbs: - - get - - patch - - update - apiGroups: - apps.kubeblocks.io resources: diff --git a/deploy/helm/crds/apps.kubeblocks.io_backuppolicytemplates.yaml b/deploy/helm/crds/apps.kubeblocks.io_backuppolicytemplates.yaml index 5b572f216162..4f0ae6e1b580 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_backuppolicytemplates.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_backuppolicytemplates.yaml @@ -231,8 +231,7 @@ spec: type: string names: description: |- - Represents an array of names of ClusterVersion or ComponentDefinition that can be mapped to - the appropriate version of the backup tool image. + Represents an array of names of ComponentDefinition that can be mapped to the appropriate version of the backup tool image. This mapping allows different versions of component images to correspond to specific versions of backup tool images. @@ -255,8 +254,7 @@ spec: type: string names: description: |- - Represents an array of names of ClusterVersion or ComponentDefinition that can be mapped to - the appropriate version of the backup tool image. + Represents an array of names of ComponentDefinition that can be mapped to the appropriate version of the backup tool image. This mapping allows different versions of component images to correspond to specific versions of backup tool images. diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusterversions.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusterversions.yaml deleted file mode 100644 index 9b85a09b815d..000000000000 --- a/deploy/helm/crds/apps.kubeblocks.io_clusterversions.yaml +++ /dev/null @@ -1,3279 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.14.0 - labels: - app.kubernetes.io/name: kubeblocks - name: clusterversions.apps.kubeblocks.io -spec: - group: apps.kubeblocks.io - names: - categories: - - kubeblocks - kind: ClusterVersion - listKind: ClusterVersionList - plural: clusterversions - shortNames: - - cv - singular: clusterversion - scope: Cluster - versions: - - additionalPrinterColumns: - - description: ClusterDefinition referenced by cluster. - jsonPath: .spec.clusterDefinitionRef - name: CLUSTER-DEFINITION - type: string - - description: status phase - jsonPath: .status.phase - name: STATUS - type: string - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - deprecated: true - deprecationWarning: The ClusterVersion CRD has been deprecated since 0.9.0 - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ClusterVersion is the Schema for the ClusterVersions API. - - - Deprecated: ClusterVersion has been replaced by ComponentVersion since v0.9. - This struct is maintained for backward compatibility and its use is discouraged. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: |- - ClusterVersionSpec defines the desired state of ClusterVersion. - - - Deprecated since v0.9. - This struct is maintained for backward compatibility and its use is discouraged. - properties: - clusterDefinitionRef: - description: Specifies a reference to the ClusterDefinition. - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - componentVersions: - description: Contains a list of versioning contexts for the components' - containers. - items: - description: |- - ClusterComponentVersion is an application version component spec. - - - Deprecated since v0.9. - This struct is maintained for backward compatibility and its use is discouraged. - properties: - componentDefRef: - description: Specifies a reference to one of the cluster component - definition names in the ClusterDefinition API (spec.componentDefs.name). - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - configSpecs: - description: |- - Defines a configuration extension mechanism to handle configuration differences between versions. - The configTemplateRefs field, in conjunction with the configTemplateRefs in the ClusterDefinition, determines - the final configuration file. - items: - properties: - asEnvFrom: - description: |- - Specifies the containers to inject the ConfigMap parameters as environment variables. - - - This is useful when application images accept parameters through environment variables and - generate the final configuration file in the startup script based on these variables. - - - This field allows users to specify a list of container names, and KubeBlocks will inject the environment - variables converted from the ConfigMap into these designated containers. This provides a flexible way to - pass the configuration items from the ConfigMap to the container without modifying the image. - - - Deprecated: `asEnvFrom` has been deprecated since 0.9.0 and will be removed in 0.10.0. - Use `injectEnvTo` instead. - items: - type: string - type: array - x-kubernetes-list-type: set - constraintRef: - description: Specifies the name of the referenced configuration - constraints object. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - defaultMode: - description: |- - The operator attempts to set default file permissions for scripts (0555) and configurations (0444). - However, certain database engines may require different file permissions. - You can specify the desired file permissions here. - - - Must be specified as an octal value between 0000 and 0777 (inclusive), - or as a decimal value between 0 and 511 (inclusive). - YAML supports both octal and decimal values for file permissions. - - - Please note that this setting only affects the permissions of the files themselves. - Directories within the specified path are not impacted by this setting. - It's important to be aware that this setting might conflict with other options - that influence the file mode, such as fsGroup. - In such cases, the resulting file mode may have additional bits set. - Refers to documents of k8s.ConfigMapVolumeSource.defaultMode for more information. - format: int32 - type: integer - injectEnvTo: - description: |- - Specifies the containers to inject the ConfigMap parameters as environment variables. - - - This is useful when application images accept parameters through environment variables and - generate the final configuration file in the startup script based on these variables. - - - This field allows users to specify a list of container names, and KubeBlocks will inject the environment - variables converted from the ConfigMap into these designated containers. This provides a flexible way to - pass the configuration items from the ConfigMap to the container without modifying the image. - items: - type: string - type: array - x-kubernetes-list-type: set - keys: - description: |- - Specifies the configuration files within the ConfigMap that support dynamic updates. - - - A configuration template (provided in the form of a ConfigMap) may contain templates for multiple - configuration files. - Each configuration file corresponds to a key in the ConfigMap. - Some of these configuration files may support dynamic modification and reloading without requiring - a pod restart. - - - If empty or omitted, all configuration files in the ConfigMap are assumed to support dynamic updates, - and ConfigConstraint applies to all keys. - items: - type: string - type: array - x-kubernetes-list-type: set - legacyRenderedConfigSpec: - description: |- - Specifies the secondary rendered config spec for pod-specific customization. - - - The template is rendered inside the pod (by the "config-manager" sidecar container) and merged with the main - template's render result to generate the final configuration file. - - - This field is intended to handle scenarios where different pods within the same Component have - varying configurations. It allows for pod-specific customization of the configuration. - - - Note: This field will be deprecated in future versions, and the functionality will be moved to - `cluster.spec.componentSpecs[*].instances[*]`. - properties: - namespace: - default: default - description: |- - Specifies the namespace of the referenced configuration template ConfigMap object. - An empty namespace is equivalent to the "default" namespace. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ - type: string - policy: - default: none - description: Defines the strategy for merging externally - imported templates into component templates. - enum: - - patch - - replace - - none - type: string - templateRef: - description: Specifies the name of the referenced - configuration template ConfigMap object. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - required: - - templateRef - type: object - name: - description: Specifies the name of the configuration template. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - namespace: - default: default - description: |- - Specifies the namespace of the referenced configuration template ConfigMap object. - An empty namespace is equivalent to the "default" namespace. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ - type: string - reRenderResourceTypes: - description: |- - Specifies whether the configuration needs to be re-rendered after v-scale or h-scale operations to reflect changes. - - - In some scenarios, the configuration may need to be updated to reflect the changes in resource allocation - or cluster topology. Examples: - - - - Redis: adjust maxmemory after v-scale operation. - - MySQL: increase max connections after v-scale operation. - - Zookeeper: update zoo.cfg with new node addresses after h-scale operation. - items: - description: RerenderResourceType defines the resource - requirements for a component. - enum: - - vscale - - hscale - - tls - type: string - type: array - x-kubernetes-list-type: set - templateRef: - description: Specifies the name of the referenced configuration - template ConfigMap object. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - volumeName: - description: |- - Refers to the volume name of PodTemplate. The configuration file produced through the configuration - template will be mounted to the corresponding volume. Must be a DNS_LABEL name. - The volume name must be defined in podSpec.containers[*].volumeMounts. - maxLength: 63 - pattern: ^[a-z]([a-z0-9\-]*[a-z0-9])?$ - type: string - required: - - name - - volumeName - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - switchoverSpec: - description: |- - Defines the images for the component to perform a switchover. - This overrides the image and env attributes defined in clusterDefinition.spec.componentDefs.SwitchoverSpec.CommandExecutorEnvItem. - properties: - cmdExecutorConfig: - description: Represents the configuration for the command - executor. - properties: - env: - description: A list of environment variables that will - be injected into the command execution context. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, defaults - to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults to - "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-preserve-unknown-fields: true - image: - description: Specifies the image used to execute the - command. - type: string - required: - - image - type: object - required: - - cmdExecutorConfig - type: object - systemAccountSpec: - description: |- - Defines the image for the component to connect to databases or engines. - This overrides the `image` and `env` attributes defined in clusterDefinition.spec.componentDefs.systemAccountSpec.cmdExecutorConfig. - To clear default environment settings, set systemAccountSpec.cmdExecutorConfig.env to an empty list. - properties: - cmdExecutorConfig: - description: Configures the method for obtaining the client - SDK and executing statements. - properties: - env: - description: A list of environment variables that will - be injected into the command execution context. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, defaults - to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults to - "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-preserve-unknown-fields: true - image: - description: Specifies the image used to execute the - command. - type: string - required: - - image - type: object - required: - - cmdExecutorConfig - type: object - versionsContext: - description: |- - Defines the context for container images for component versions. - This value replaces the values in clusterDefinition.spec.componentDefs.podSpec.[initContainers | containers]. - properties: - containers: - description: |- - Provides override values for ClusterDefinition.spec.componentDefs.podSpec.containers. - Typically used in scenarios such as updating application container images. - items: - description: A single application container that you want - to run within a pod. - properties: - args: - description: |- - Arguments to the entrypoint. - The container image's CMD is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - command: - description: |- - Entrypoint array. Not executed within a shell. - The container image's ENTRYPOINT is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - env: - description: |- - List of environment variables to set in the container. - Cannot be updated. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, - defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults - to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - description: |- - List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple - sources, the value associated with the last source will take precedence. - Values defined by an Env with a duplicate key will take precedence. - Cannot be updated. - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - lifecycle: - description: |- - Actions that the management system should take in response to container lifecycle events. - Cannot be updated. - properties: - postStart: - description: |- - PostStart is called immediately after a container is created. If the handler fails, - the container is terminated and restarted according to its restart policy. - Other management of the container blocks until the hook completes. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: |- - PreStop is called immediately before a container is terminated due to an - API request or management event such as liveness/startup probe failure, - preemption, resource contention, etc. The handler is not called if the - container crashes or exits. The Pod's termination grace period countdown begins before the - PreStop hook is executed. Regardless of the outcome of the handler, the - container will eventually terminate within the Pod's termination grace - period (unless delayed by finalizers). Other management of the container blocks until the hook completes - or until the termination grace period is reached. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: |- - Periodic probe of container liveness. - Container will be restarted if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - name: - description: |- - Name of the container specified as a DNS_LABEL. - Each container in a pod must have a unique name (DNS_LABEL). - Cannot be updated. - type: string - ports: - description: |- - List of ports to expose from the container. Not specifying a port here - DOES NOT prevent that port from being exposed. Any port which is - listening on the default "0.0.0.0" address inside a container will be - accessible from the network. - Modifying this array with strategic merge patch may corrupt the data. - For more information See https://github.com/kubernetes/kubernetes/issues/108255. - Cannot be updated. - items: - description: ContainerPort represents a network - port in a single container. - properties: - containerPort: - description: |- - Number of port to expose on the pod's IP address. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external - port to. - type: string - hostPort: - description: |- - Number of port to expose on the host. - If specified, this must be a valid port number, 0 < x < 65536. - If HostNetwork is specified, this must match ContainerPort. - Most containers do not need this. - format: int32 - type: integer - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - protocol: - default: TCP - description: |- - Protocol for port. Must be UDP, TCP, or SCTP. - Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: |- - Periodic probe of container service readiness. - Container will be removed from service endpoints if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - resizePolicy: - description: Resources resize policy for the container. - items: - description: ContainerResizePolicy represents resource - resize policy for the container. - properties: - resourceName: - description: |- - Name of the resource to which this resource resize policy applies. - Supported values: cpu, memory. - type: string - restartPolicy: - description: |- - Restart policy to apply when specified resource is resized. - If not specified, it defaults to NotRequired. - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Compute Resources required by this container. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - restartPolicy: - description: |- - RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, - the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: - this init container will be continually restarted on - exit until all regular containers have terminated. Once all regular - containers have completed, all init containers with restartPolicy "Always" - will be shut down. This lifecycle differs from normal init containers and - is often referred to as a "sidecar" container. Although this init - container still starts in the init container sequence, it does not wait - for the container to complete before proceeding to the next init - container. Instead, the next init container starts immediately after this - init container is started, or after any startupProbe has successfully - completed. - type: string - securityContext: - description: |- - SecurityContext defines the security options the container should be run with. - If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - properties: - allowPrivilegeEscalation: - description: |- - AllowPrivilegeEscalation controls whether a process can gain more - privileges than its parent process. This bool directly controls if - the no_new_privs flag will be set on the container process. - AllowPrivilegeEscalation is true always when the container is: - 1) run as Privileged - 2) has CAP_SYS_ADMIN - Note that this field cannot be set when spec.os.name is windows. - type: boolean - capabilities: - description: |- - The capabilities to add/drop when running containers. - Defaults to the default set of capabilities granted by the container runtime. - Note that this field cannot be set when spec.os.name is windows. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - drop: - description: Removed capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - type: object - privileged: - description: |- - Run container in privileged mode. - Processes in privileged containers are essentially equivalent to root on the host. - Defaults to false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - procMount: - description: |- - procMount denotes the type of proc mount to use for the containers. - The default is DefaultProcMount which uses the container runtime defaults for - readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. - Note that this field cannot be set when spec.os.name is windows. - type: string - readOnlyRootFilesystem: - description: |- - Whether this container has a read-only root filesystem. - Default is false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to the container. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label - that applies to the container. - type: string - role: - description: Role is a SELinux role label - that applies to the container. - type: string - type: - description: Type is a SELinux type label - that applies to the container. - type: string - user: - description: User is a SELinux user label - that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by this container. If seccomp options are - provided at both the pod & container level, the container options - override the pod options. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options from the PodSecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the - name of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: |- - StartupProbe indicates that the Pod has successfully initialized. - If specified, no other probes are executed until this completes successfully. - If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. - This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, - when it might take a long time to load data or warm a cache, than during steady-state operation. - This cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - stdin: - description: |- - Whether this container should allocate a buffer for stdin in the container runtime. If this - is not set, reads from stdin in the container will always result in EOF. - Default is false. - type: boolean - stdinOnce: - description: |- - Whether the container runtime should close the stdin channel after it has been opened by - a single attach. When stdin is true the stdin stream will remain open across multiple attach - sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - first client attaches to stdin, and then remains open and accepts data until the client disconnects, - at which time stdin is closed and remains closed until the container is restarted. If this - flag is false, a container processes that reads from stdin will never receive an EOF. - Default is false - type: boolean - terminationMessagePath: - description: |- - Optional: Path at which the file to which the container's termination message - will be written is mounted into the container's filesystem. - Message written is intended to be brief final status, such as an assertion failure message. - Will be truncated by the node if greater than 4096 bytes. The total message length across - all containers will be limited to 12kb. - Defaults to /dev/termination-log. - Cannot be updated. - type: string - terminationMessagePolicy: - description: |- - Indicate how the termination message should be populated. File will use the contents of - terminationMessagePath to populate the container status message on both success and failure. - FallbackToLogsOnError will use the last chunk of container log output if the termination - message file is empty and the container exited with an error. - The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - Defaults to File. - Cannot be updated. - type: string - tty: - description: |- - Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices - to be used by the container. - items: - description: volumeDevice describes a mapping of - a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside of - the container that the device will be mapped - to. - type: string - name: - description: name must match the name of a persistentVolumeClaim - in the pod - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - description: |- - Pod volumes to mount into the container's filesystem. - Cannot be updated. - items: - description: VolumeMount describes a mounting of - a Volume within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - workingDir: - description: |- - Container's working directory. - If not specified, the container runtime's default will be used, which - might be configured in the container image. - Cannot be updated. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - x-kubernetes-preserve-unknown-fields: true - initContainers: - description: |- - Provides override values for ClusterDefinition.spec.componentDefs.podSpec.initContainers. - Typically used in scenarios such as updating application container images. - items: - description: A single application container that you want - to run within a pod. - properties: - args: - description: |- - Arguments to the entrypoint. - The container image's CMD is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - command: - description: |- - Entrypoint array. Not executed within a shell. - The container image's ENTRYPOINT is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - env: - description: |- - List of environment variables to set in the container. - Cannot be updated. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, - defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults - to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - description: |- - List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple - sources, the value associated with the last source will take precedence. - Values defined by an Env with a duplicate key will take precedence. - Cannot be updated. - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - lifecycle: - description: |- - Actions that the management system should take in response to container lifecycle events. - Cannot be updated. - properties: - postStart: - description: |- - PostStart is called immediately after a container is created. If the handler fails, - the container is terminated and restarted according to its restart policy. - Other management of the container blocks until the hook completes. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: |- - PreStop is called immediately before a container is terminated due to an - API request or management event such as liveness/startup probe failure, - preemption, resource contention, etc. The handler is not called if the - container crashes or exits. The Pod's termination grace period countdown begins before the - PreStop hook is executed. Regardless of the outcome of the handler, the - container will eventually terminate within the Pod's termination grace - period (unless delayed by finalizers). Other management of the container blocks until the hook completes - or until the termination grace period is reached. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: |- - Periodic probe of container liveness. - Container will be restarted if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - name: - description: |- - Name of the container specified as a DNS_LABEL. - Each container in a pod must have a unique name (DNS_LABEL). - Cannot be updated. - type: string - ports: - description: |- - List of ports to expose from the container. Not specifying a port here - DOES NOT prevent that port from being exposed. Any port which is - listening on the default "0.0.0.0" address inside a container will be - accessible from the network. - Modifying this array with strategic merge patch may corrupt the data. - For more information See https://github.com/kubernetes/kubernetes/issues/108255. - Cannot be updated. - items: - description: ContainerPort represents a network - port in a single container. - properties: - containerPort: - description: |- - Number of port to expose on the pod's IP address. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external - port to. - type: string - hostPort: - description: |- - Number of port to expose on the host. - If specified, this must be a valid port number, 0 < x < 65536. - If HostNetwork is specified, this must match ContainerPort. - Most containers do not need this. - format: int32 - type: integer - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - protocol: - default: TCP - description: |- - Protocol for port. Must be UDP, TCP, or SCTP. - Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: |- - Periodic probe of container service readiness. - Container will be removed from service endpoints if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - resizePolicy: - description: Resources resize policy for the container. - items: - description: ContainerResizePolicy represents resource - resize policy for the container. - properties: - resourceName: - description: |- - Name of the resource to which this resource resize policy applies. - Supported values: cpu, memory. - type: string - restartPolicy: - description: |- - Restart policy to apply when specified resource is resized. - If not specified, it defaults to NotRequired. - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Compute Resources required by this container. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - restartPolicy: - description: |- - RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, - the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: - this init container will be continually restarted on - exit until all regular containers have terminated. Once all regular - containers have completed, all init containers with restartPolicy "Always" - will be shut down. This lifecycle differs from normal init containers and - is often referred to as a "sidecar" container. Although this init - container still starts in the init container sequence, it does not wait - for the container to complete before proceeding to the next init - container. Instead, the next init container starts immediately after this - init container is started, or after any startupProbe has successfully - completed. - type: string - securityContext: - description: |- - SecurityContext defines the security options the container should be run with. - If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - properties: - allowPrivilegeEscalation: - description: |- - AllowPrivilegeEscalation controls whether a process can gain more - privileges than its parent process. This bool directly controls if - the no_new_privs flag will be set on the container process. - AllowPrivilegeEscalation is true always when the container is: - 1) run as Privileged - 2) has CAP_SYS_ADMIN - Note that this field cannot be set when spec.os.name is windows. - type: boolean - capabilities: - description: |- - The capabilities to add/drop when running containers. - Defaults to the default set of capabilities granted by the container runtime. - Note that this field cannot be set when spec.os.name is windows. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - drop: - description: Removed capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - type: object - privileged: - description: |- - Run container in privileged mode. - Processes in privileged containers are essentially equivalent to root on the host. - Defaults to false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - procMount: - description: |- - procMount denotes the type of proc mount to use for the containers. - The default is DefaultProcMount which uses the container runtime defaults for - readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. - Note that this field cannot be set when spec.os.name is windows. - type: string - readOnlyRootFilesystem: - description: |- - Whether this container has a read-only root filesystem. - Default is false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to the container. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label - that applies to the container. - type: string - role: - description: Role is a SELinux role label - that applies to the container. - type: string - type: - description: Type is a SELinux type label - that applies to the container. - type: string - user: - description: User is a SELinux user label - that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by this container. If seccomp options are - provided at both the pod & container level, the container options - override the pod options. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options from the PodSecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the - name of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: |- - StartupProbe indicates that the Pod has successfully initialized. - If specified, no other probes are executed until this completes successfully. - If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. - This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, - when it might take a long time to load data or warm a cache, than during steady-state operation. - This cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - stdin: - description: |- - Whether this container should allocate a buffer for stdin in the container runtime. If this - is not set, reads from stdin in the container will always result in EOF. - Default is false. - type: boolean - stdinOnce: - description: |- - Whether the container runtime should close the stdin channel after it has been opened by - a single attach. When stdin is true the stdin stream will remain open across multiple attach - sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - first client attaches to stdin, and then remains open and accepts data until the client disconnects, - at which time stdin is closed and remains closed until the container is restarted. If this - flag is false, a container processes that reads from stdin will never receive an EOF. - Default is false - type: boolean - terminationMessagePath: - description: |- - Optional: Path at which the file to which the container's termination message - will be written is mounted into the container's filesystem. - Message written is intended to be brief final status, such as an assertion failure message. - Will be truncated by the node if greater than 4096 bytes. The total message length across - all containers will be limited to 12kb. - Defaults to /dev/termination-log. - Cannot be updated. - type: string - terminationMessagePolicy: - description: |- - Indicate how the termination message should be populated. File will use the contents of - terminationMessagePath to populate the container status message on both success and failure. - FallbackToLogsOnError will use the last chunk of container log output if the termination - message file is empty and the container exited with an error. - The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - Defaults to File. - Cannot be updated. - type: string - tty: - description: |- - Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices - to be used by the container. - items: - description: volumeDevice describes a mapping of - a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside of - the container that the device will be mapped - to. - type: string - name: - description: name must match the name of a persistentVolumeClaim - in the pod - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - description: |- - Pod volumes to mount into the container's filesystem. - Cannot be updated. - items: - description: VolumeMount describes a mounting of - a Volume within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - workingDir: - description: |- - Container's working directory. - If not specified, the container runtime's default will be used, which - might be configured in the container image. - Cannot be updated. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - x-kubernetes-preserve-unknown-fields: true - type: object - required: - - componentDefRef - - versionsContext - type: object - minItems: 1 - type: array - x-kubernetes-list-map-keys: - - componentDefRef - x-kubernetes-list-type: map - required: - - clusterDefinitionRef - - componentVersions - type: object - status: - description: |- - ClusterVersionStatus defines the observed state of ClusterVersion. - - - Deprecated since v0.9. - This struct is maintained for backward compatibility and its use is discouraged. - properties: - clusterDefGeneration: - description: The generation number of the ClusterDefinition that is - currently being referenced. - format: int64 - type: integer - message: - description: Provides additional information about the current phase. - type: string - observedGeneration: - description: The generation number that has been observed by the controller. - format: int64 - type: integer - phase: - description: The current phase of the ClusterVersion. - enum: - - Available - - Unavailable - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/deploy/helm/crds/apps.kubeblocks.io_configconstraints.yaml b/deploy/helm/crds/apps.kubeblocks.io_configconstraints.yaml index 50a118ff6c81..ad8198789bf4 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_configconstraints.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_configconstraints.yaml @@ -758,7 +758,7 @@ spec: phase: description: |- Specifies the status of the configuration template. - When set to CCAvailablePhase, the ConfigConstraint can be referenced by ClusterDefinition or ClusterVersion. + When set to CCAvailablePhase, the ConfigConstraint can be referenced by ClusterDefinition. enum: - Available - Unavailable @@ -1418,7 +1418,7 @@ spec: phase: description: |- Specifies the status of the configuration template. - When set to CCAvailablePhase, the ConfigConstraint can be referenced by ClusterDefinition or ClusterVersion. + When set to CCAvailablePhase, the ConfigConstraint can be referenced by ClusterDefinition. enum: - Available - Unavailable diff --git a/deploy/helm/templates/admission/webhookconfiguration.yaml b/deploy/helm/templates/admission/webhookconfiguration.yaml index bddc16a0630a..f91c9c5ad76c 100644 --- a/deploy/helm/templates/admission/webhookconfiguration.yaml +++ b/deploy/helm/templates/admission/webhookconfiguration.yaml @@ -123,30 +123,6 @@ metadata: labels: {{- include "kubeblocks.labels" . | nindent 4 }} webhooks: -- admissionReviewVersions: - - v1 - clientConfig: - service: - name: {{ include "kubeblocks.svcName" . }} - namespace: {{ .Release.Namespace }} - path: /validate-apps-kubeblocks-io-v1alpha1-clusterversion - port: {{ .Values.service.port }} - {{- if .Values.admissionWebhooks.createSelfSignedCert }} - caBundle: {{ $ca.Cert | b64enc }} - {{- end }} - failurePolicy: Fail - name: vclusterversion.kb.io - rules: - - apiGroups: - - apps.kubeblocks.io - apiVersions: - - v1alpha1 - operations: - - CREATE - - UPDATE - resources: - - clusterversions - sideEffects: None - admissionReviewVersions: - v1 clientConfig: diff --git a/deploy/helm/templates/rbac/apps_clusterversion_editor_role.yaml b/deploy/helm/templates/rbac/apps_clusterversion_editor_role.yaml deleted file mode 100644 index fb50b1c6a564..000000000000 --- a/deploy/helm/templates/rbac/apps_clusterversion_editor_role.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# permissions for end users to edit clusterversions. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ include "kubeblocks.fullname" . }}-clusterversion-editor-role - labels: - {{- include "kubeblocks.labels" . | nindent 4 }} -rules: -- apiGroups: - - apps.kubeblocks.io - resources: - - clusterversions - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - apps.kubeblocks.io - resources: - - clusterversions/status - verbs: - - get diff --git a/deploy/helm/templates/rbac/apps_clusterversion_viewer_role.yaml b/deploy/helm/templates/rbac/apps_clusterversion_viewer_role.yaml deleted file mode 100644 index 6cee39f7c484..000000000000 --- a/deploy/helm/templates/rbac/apps_clusterversion_viewer_role.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# permissions for end users to view clusterversions. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ include "kubeblocks.fullname" . }}-clusterversion-viewer-role - labels: - {{- include "kubeblocks.labels" . | nindent 4 }} -rules: -- apiGroups: - - apps.kubeblocks.io - resources: - - clusterversions - verbs: - - get - - list - - watch -- apiGroups: - - apps.kubeblocks.io - resources: - - clusterversions/status - verbs: - - get diff --git a/docs/developer_docs/api-reference/cluster.md b/docs/developer_docs/api-reference/cluster.md index e9a1dbb81309..fd5677d7f389 100644 --- a/docs/developer_docs/api-reference/cluster.md +++ b/docs/developer_docs/api-reference/cluster.md @@ -27,8 +27,6 @@ Resource Types:
  • ClusterDefinition
  • -ClusterVersion -
  • Component
  • ComponentDefinition @@ -593,104 +591,6 @@ ClusterDefinitionStatus -

    ClusterVersion -

    -
    -

    ClusterVersion is the Schema for the ClusterVersions API.

    -

    Deprecated: ClusterVersion has been replaced by ComponentVersion since v0.9. -This struct is maintained for backward compatibility and its use is discouraged.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -apiVersion
    -string
    -apps.kubeblocks.io/v1alpha1 -
    -kind
    -string -
    ClusterVersion
    -metadata
    - - -Kubernetes meta/v1.ObjectMeta - - -
    -Refer to the Kubernetes API documentation for the fields of the -metadata field. -
    -spec
    - - -ClusterVersionSpec - - -
    -
    -
    - - - - - - - - - -
    -clusterDefinitionRef
    - -string - -
    -

    Specifies a reference to the ClusterDefinition.

    -
    -componentVersions
    - - -[]ClusterComponentVersion - - -
    -

    Contains a list of versioning contexts for the components’ containers.

    -
    -
    -status
    - - -ClusterVersionStatus - - -
    -

    Component

    @@ -5248,98 +5148,6 @@ This is the readiness time of the last Component Pod.

    -

    ClusterComponentVersion -

    -

    -(Appears on:ClusterVersionSpec) -

    -
    -

    ClusterComponentVersion is an application version component spec.

    -

    Deprecated since v0.9. -This struct is maintained for backward compatibility and its use is discouraged.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -componentDefRef
    - -string - -
    -

    Specifies a reference to one of the cluster component definition names in the ClusterDefinition API (spec.componentDefs.name).

    -
    -configSpecs
    - - -[]ComponentConfigSpec - - -
    -(Optional) -

    Defines a configuration extension mechanism to handle configuration differences between versions. -The configTemplateRefs field, in conjunction with the configTemplateRefs in the ClusterDefinition, determines -the final configuration file.

    -
    -systemAccountSpec
    - - -SystemAccountShortSpec - - -
    -(Optional) -

    Defines the image for the component to connect to databases or engines. -This overrides the image and env attributes defined in clusterDefinition.spec.componentDefs.systemAccountSpec.cmdExecutorConfig. -To clear default environment settings, set systemAccountSpec.cmdExecutorConfig.env to an empty list.

    -
    -versionsContext
    - - -VersionsContext - - -
    -

    Defines the context for container images for component versions. -This value replaces the values in clusterDefinition.spec.componentDefs.podSpec.[initContainers | containers].

    -
    -switchoverSpec
    - - -SwitchoverShortSpec - - -
    -(Optional) -

    Defines the images for the component to perform a switchover. -This overrides the image and env attributes defined in clusterDefinition.spec.componentDefs.SwitchoverSpec.CommandExecutorEnvItem.

    -

    ClusterComponentVolumeClaimTemplate

    @@ -6759,120 +6567,6 @@ separated by commas.

    -

    ClusterVersionSpec -

    -

    -(Appears on:ClusterVersion) -

    -
    -

    ClusterVersionSpec defines the desired state of ClusterVersion.

    -

    Deprecated since v0.9. -This struct is maintained for backward compatibility and its use is discouraged.

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -clusterDefinitionRef
    - -string - -
    -

    Specifies a reference to the ClusterDefinition.

    -
    -componentVersions
    - - -[]ClusterComponentVersion - - -
    -

    Contains a list of versioning contexts for the components’ containers.

    -
    -

    ClusterVersionStatus -

    -

    -(Appears on:ClusterVersion) -

    -
    -

    ClusterVersionStatus defines the observed state of ClusterVersion.

    -

    Deprecated since v0.9. -This struct is maintained for backward compatibility and its use is discouraged.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -phase
    - - -Phase - - -
    -(Optional) -

    The current phase of the ClusterVersion.

    -
    -message
    - -string - -
    -(Optional) -

    Provides additional information about the current phase.

    -
    -observedGeneration
    - -int64 - -
    -(Optional) -

    The generation number that has been observed by the controller.

    -
    -clusterDefGeneration
    - -int64 - -
    -(Optional) -

    The generation number of the ClusterDefinition that is currently being referenced.

    -

    CmdExecutorConfig

    @@ -6925,7 +6619,7 @@ CommandExecutorItem

    CommandExecutorEnvItem

    -(Appears on:CmdExecutorConfig, SwitchoverShortSpec, SystemAccountShortSpec) +(Appears on:CmdExecutorConfig)

    CommandExecutorEnvItem is deprecated since v0.8.

    @@ -7078,7 +6772,7 @@ MatchExpressions

    ComponentConfigSpec

    -(Appears on:ClusterComponentDefinition, ClusterComponentVersion, ComponentDefinitionSpec, ConfigurationItemDetail) +(Appears on:ClusterComponentDefinition, ComponentDefinitionSpec, ConfigurationItemDetail)

    @@ -10122,7 +9816,7 @@ ConfigConstraintPhase (Optional)

    Specifies the status of the configuration template. -When set to CCAvailablePhase, the ConfigConstraint can be referenced by ClusterDefinition or ClusterVersion.

    +When set to CCAvailablePhase, the ConfigConstraint can be referenced by ClusterDefinition.

    @@ -15259,10 +14953,10 @@ Kubernetes core/v1.PersistentVolumeMode

    Phase (string alias)

    -(Appears on:ClusterDefinitionStatus, ClusterVersionStatus, ComponentDefinitionStatus, ComponentVersionStatus, OpsDefinitionStatus, ServiceDescriptorStatus) +(Appears on:ClusterDefinitionStatus, ComponentDefinitionStatus, ComponentVersionStatus, OpsDefinitionStatus, ServiceDescriptorStatus)

    -

    Phase represents the current status of the ClusterDefinition and ClusterVersion CR.

    +

    Phase represents the current status of the ClusterDefinition CR.

    @@ -19725,39 +19419,6 @@ When defined, the scripts defined in scriptSpecs can be referenced within the Sw
    -

    SwitchoverShortSpec -

    -

    -(Appears on:ClusterComponentVersion) -

    -
    -

    SwitchoverShortSpec represents a condensed version of the SwitchoverSpec.

    -

    Deprecated since v0.9. -This struct is maintained for backward compatibility and its use is discouraged.

    -
    - - - - - - - - - - - - - -
    FieldDescription
    -cmdExecutorConfig
    - - -CommandExecutorEnvItem - - -
    -

    Represents the configuration for the command executor.

    -

    SwitchoverSpec

    @@ -19934,39 +19595,6 @@ ProvisionPolicy -

    SystemAccountShortSpec -

    -

    -(Appears on:ClusterComponentVersion) -

    -
    -

    SystemAccountShortSpec represents a condensed version of the SystemAccountSpec.

    -

    Deprecated since v0.9. -This struct is maintained for backward compatibility and its use is discouraged.

    -
    - - - - - - - - - - - - - -
    FieldDescription
    -cmdExecutorConfig
    - - -CommandExecutorEnvItem - - -
    -

    Configures the method for obtaining the client SDK and executing statements.

    -

    SystemAccountSpec

    @@ -20711,8 +20339,7 @@ use the latest available version in ComponentVersion.

    -

    Represents an array of names of ClusterVersion or ComponentDefinition that can be mapped to -the appropriate version of the backup tool image.

    +

    Represents an array of names of ComponentDefinition that can be mapped to the appropriate version of the backup tool image.

    This mapping allows different versions of component images to correspond to specific versions of backup tool images.

    @@ -20853,55 +20480,6 @@ ComponentVarSelector -

    VersionsContext -

    -

    -(Appears on:ClusterComponentVersion) -

    -
    -

    VersionsContext is deprecated since v0.9. -This struct is maintained for backward compatibility and its use is discouraged.

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -initContainers
    - - -[]Kubernetes core/v1.Container - - -
    -(Optional) -

    Provides override values for ClusterDefinition.spec.componentDefs.podSpec.initContainers. -Typically used in scenarios such as updating application container images.

    -
    -containers
    - - -[]Kubernetes core/v1.Container - - -
    -(Optional) -

    Provides override values for ClusterDefinition.spec.componentDefs.podSpec.containers. -Typically used in scenarios such as updating application container images.

    -

    VerticalScaling

    @@ -21738,7 +21316,7 @@ ConfigConstraintPhase (Optional)

    Specifies the status of the configuration template. -When set to CCAvailablePhase, the ConfigConstraint can be referenced by ClusterDefinition or ClusterVersion.

    +When set to CCAvailablePhase, the ConfigConstraint can be referenced by ClusterDefinition.

    diff --git a/pkg/client/clientset/versioned/typed/apps/v1alpha1/apps_client.go b/pkg/client/clientset/versioned/typed/apps/v1alpha1/apps_client.go index 0515c6b576fc..4baf1af6aad1 100644 --- a/pkg/client/clientset/versioned/typed/apps/v1alpha1/apps_client.go +++ b/pkg/client/clientset/versioned/typed/apps/v1alpha1/apps_client.go @@ -31,7 +31,6 @@ type AppsV1alpha1Interface interface { BackupPolicyTemplatesGetter ClustersGetter ClusterDefinitionsGetter - ClusterVersionsGetter ComponentsGetter ComponentDefinitionsGetter ComponentVersionsGetter @@ -58,10 +57,6 @@ func (c *AppsV1alpha1Client) ClusterDefinitions() ClusterDefinitionInterface { return newClusterDefinitions(c) } -func (c *AppsV1alpha1Client) ClusterVersions() ClusterVersionInterface { - return newClusterVersions(c) -} - func (c *AppsV1alpha1Client) Components(namespace string) ComponentInterface { return newComponents(c, namespace) } diff --git a/pkg/client/clientset/versioned/typed/apps/v1alpha1/clusterversion.go b/pkg/client/clientset/versioned/typed/apps/v1alpha1/clusterversion.go deleted file mode 100644 index 8965b99ba112..000000000000 --- a/pkg/client/clientset/versioned/typed/apps/v1alpha1/clusterversion.go +++ /dev/null @@ -1,184 +0,0 @@ -/* -Copyright (C) 2022-2024 ApeCloud Co., Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by client-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - "context" - "time" - - v1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" - scheme "github.com/apecloud/kubeblocks/pkg/client/clientset/versioned/scheme" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - rest "k8s.io/client-go/rest" -) - -// ClusterVersionsGetter has a method to return a ClusterVersionInterface. -// A group's client should implement this interface. -type ClusterVersionsGetter interface { - ClusterVersions() ClusterVersionInterface -} - -// ClusterVersionInterface has methods to work with ClusterVersion resources. -type ClusterVersionInterface interface { - Create(ctx context.Context, clusterVersion *v1alpha1.ClusterVersion, opts v1.CreateOptions) (*v1alpha1.ClusterVersion, error) - Update(ctx context.Context, clusterVersion *v1alpha1.ClusterVersion, opts v1.UpdateOptions) (*v1alpha1.ClusterVersion, error) - UpdateStatus(ctx context.Context, clusterVersion *v1alpha1.ClusterVersion, opts v1.UpdateOptions) (*v1alpha1.ClusterVersion, error) - Delete(ctx context.Context, name string, opts v1.DeleteOptions) error - DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error - Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ClusterVersion, error) - List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ClusterVersionList, error) - Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) - Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ClusterVersion, err error) - ClusterVersionExpansion -} - -// clusterVersions implements ClusterVersionInterface -type clusterVersions struct { - client rest.Interface -} - -// newClusterVersions returns a ClusterVersions -func newClusterVersions(c *AppsV1alpha1Client) *clusterVersions { - return &clusterVersions{ - client: c.RESTClient(), - } -} - -// Get takes name of the clusterVersion, and returns the corresponding clusterVersion object, and an error if there is any. -func (c *clusterVersions) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ClusterVersion, err error) { - result = &v1alpha1.ClusterVersion{} - err = c.client.Get(). - Resource("clusterversions"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(ctx). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of ClusterVersions that match those selectors. -func (c *clusterVersions) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ClusterVersionList, err error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - result = &v1alpha1.ClusterVersionList{} - err = c.client.Get(). - Resource("clusterversions"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Do(ctx). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested clusterVersions. -func (c *clusterVersions) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - opts.Watch = true - return c.client.Get(). - Resource("clusterversions"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Watch(ctx) -} - -// Create takes the representation of a clusterVersion and creates it. Returns the server's representation of the clusterVersion, and an error, if there is any. -func (c *clusterVersions) Create(ctx context.Context, clusterVersion *v1alpha1.ClusterVersion, opts v1.CreateOptions) (result *v1alpha1.ClusterVersion, err error) { - result = &v1alpha1.ClusterVersion{} - err = c.client.Post(). - Resource("clusterversions"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(clusterVersion). - Do(ctx). - Into(result) - return -} - -// Update takes the representation of a clusterVersion and updates it. Returns the server's representation of the clusterVersion, and an error, if there is any. -func (c *clusterVersions) Update(ctx context.Context, clusterVersion *v1alpha1.ClusterVersion, opts v1.UpdateOptions) (result *v1alpha1.ClusterVersion, err error) { - result = &v1alpha1.ClusterVersion{} - err = c.client.Put(). - Resource("clusterversions"). - Name(clusterVersion.Name). - VersionedParams(&opts, scheme.ParameterCodec). - Body(clusterVersion). - Do(ctx). - Into(result) - return -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *clusterVersions) UpdateStatus(ctx context.Context, clusterVersion *v1alpha1.ClusterVersion, opts v1.UpdateOptions) (result *v1alpha1.ClusterVersion, err error) { - result = &v1alpha1.ClusterVersion{} - err = c.client.Put(). - Resource("clusterversions"). - Name(clusterVersion.Name). - SubResource("status"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(clusterVersion). - Do(ctx). - Into(result) - return -} - -// Delete takes name of the clusterVersion and deletes it. Returns an error if one occurs. -func (c *clusterVersions) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - return c.client.Delete(). - Resource("clusterversions"). - Name(name). - Body(&opts). - Do(ctx). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *clusterVersions) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - var timeout time.Duration - if listOpts.TimeoutSeconds != nil { - timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second - } - return c.client.Delete(). - Resource("clusterversions"). - VersionedParams(&listOpts, scheme.ParameterCodec). - Timeout(timeout). - Body(&opts). - Do(ctx). - Error() -} - -// Patch applies the patch and returns the patched clusterVersion. -func (c *clusterVersions) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ClusterVersion, err error) { - result = &v1alpha1.ClusterVersion{} - err = c.client.Patch(pt). - Resource("clusterversions"). - Name(name). - SubResource(subresources...). - VersionedParams(&opts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} diff --git a/pkg/client/clientset/versioned/typed/apps/v1alpha1/fake/fake_apps_client.go b/pkg/client/clientset/versioned/typed/apps/v1alpha1/fake/fake_apps_client.go index e346ebf0785e..6b9372e765a9 100644 --- a/pkg/client/clientset/versioned/typed/apps/v1alpha1/fake/fake_apps_client.go +++ b/pkg/client/clientset/versioned/typed/apps/v1alpha1/fake/fake_apps_client.go @@ -40,10 +40,6 @@ func (c *FakeAppsV1alpha1) ClusterDefinitions() v1alpha1.ClusterDefinitionInterf return &FakeClusterDefinitions{c} } -func (c *FakeAppsV1alpha1) ClusterVersions() v1alpha1.ClusterVersionInterface { - return &FakeClusterVersions{c} -} - func (c *FakeAppsV1alpha1) Components(namespace string) v1alpha1.ComponentInterface { return &FakeComponents{c, namespace} } diff --git a/pkg/client/clientset/versioned/typed/apps/v1alpha1/fake/fake_clusterversion.go b/pkg/client/clientset/versioned/typed/apps/v1alpha1/fake/fake_clusterversion.go deleted file mode 100644 index ab13d9c01757..000000000000 --- a/pkg/client/clientset/versioned/typed/apps/v1alpha1/fake/fake_clusterversion.go +++ /dev/null @@ -1,132 +0,0 @@ -/* -Copyright (C) 2022-2024 ApeCloud Co., Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - "context" - - v1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - testing "k8s.io/client-go/testing" -) - -// FakeClusterVersions implements ClusterVersionInterface -type FakeClusterVersions struct { - Fake *FakeAppsV1alpha1 -} - -var clusterversionsResource = v1alpha1.SchemeGroupVersion.WithResource("clusterversions") - -var clusterversionsKind = v1alpha1.SchemeGroupVersion.WithKind("ClusterVersion") - -// Get takes name of the clusterVersion, and returns the corresponding clusterVersion object, and an error if there is any. -func (c *FakeClusterVersions) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ClusterVersion, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootGetAction(clusterversionsResource, name), &v1alpha1.ClusterVersion{}) - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ClusterVersion), err -} - -// List takes label and field selectors, and returns the list of ClusterVersions that match those selectors. -func (c *FakeClusterVersions) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ClusterVersionList, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootListAction(clusterversionsResource, clusterversionsKind, opts), &v1alpha1.ClusterVersionList{}) - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &v1alpha1.ClusterVersionList{ListMeta: obj.(*v1alpha1.ClusterVersionList).ListMeta} - for _, item := range obj.(*v1alpha1.ClusterVersionList).Items { - if label.Matches(labels.Set(item.Labels)) { - list.Items = append(list.Items, item) - } - } - return list, err -} - -// Watch returns a watch.Interface that watches the requested clusterVersions. -func (c *FakeClusterVersions) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(testing.NewRootWatchAction(clusterversionsResource, opts)) -} - -// Create takes the representation of a clusterVersion and creates it. Returns the server's representation of the clusterVersion, and an error, if there is any. -func (c *FakeClusterVersions) Create(ctx context.Context, clusterVersion *v1alpha1.ClusterVersion, opts v1.CreateOptions) (result *v1alpha1.ClusterVersion, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootCreateAction(clusterversionsResource, clusterVersion), &v1alpha1.ClusterVersion{}) - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ClusterVersion), err -} - -// Update takes the representation of a clusterVersion and updates it. Returns the server's representation of the clusterVersion, and an error, if there is any. -func (c *FakeClusterVersions) Update(ctx context.Context, clusterVersion *v1alpha1.ClusterVersion, opts v1.UpdateOptions) (result *v1alpha1.ClusterVersion, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootUpdateAction(clusterversionsResource, clusterVersion), &v1alpha1.ClusterVersion{}) - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ClusterVersion), err -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *FakeClusterVersions) UpdateStatus(ctx context.Context, clusterVersion *v1alpha1.ClusterVersion, opts v1.UpdateOptions) (*v1alpha1.ClusterVersion, error) { - obj, err := c.Fake. - Invokes(testing.NewRootUpdateSubresourceAction(clusterversionsResource, "status", clusterVersion), &v1alpha1.ClusterVersion{}) - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ClusterVersion), err -} - -// Delete takes name of the clusterVersion and deletes it. Returns an error if one occurs. -func (c *FakeClusterVersions) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - _, err := c.Fake. - Invokes(testing.NewRootDeleteActionWithOptions(clusterversionsResource, name, opts), &v1alpha1.ClusterVersion{}) - return err -} - -// DeleteCollection deletes a collection of objects. -func (c *FakeClusterVersions) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - action := testing.NewRootDeleteCollectionAction(clusterversionsResource, listOpts) - - _, err := c.Fake.Invokes(action, &v1alpha1.ClusterVersionList{}) - return err -} - -// Patch applies the patch and returns the patched clusterVersion. -func (c *FakeClusterVersions) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ClusterVersion, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(clusterversionsResource, name, pt, data, subresources...), &v1alpha1.ClusterVersion{}) - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ClusterVersion), err -} diff --git a/pkg/client/clientset/versioned/typed/apps/v1alpha1/generated_expansion.go b/pkg/client/clientset/versioned/typed/apps/v1alpha1/generated_expansion.go index 885da06ef987..0f8d6ecbd662 100644 --- a/pkg/client/clientset/versioned/typed/apps/v1alpha1/generated_expansion.go +++ b/pkg/client/clientset/versioned/typed/apps/v1alpha1/generated_expansion.go @@ -24,8 +24,6 @@ type ClusterExpansion interface{} type ClusterDefinitionExpansion interface{} -type ClusterVersionExpansion interface{} - type ComponentExpansion interface{} type ComponentDefinitionExpansion interface{} diff --git a/pkg/client/informers/externalversions/apps/v1alpha1/clusterversion.go b/pkg/client/informers/externalversions/apps/v1alpha1/clusterversion.go deleted file mode 100644 index 376af5430946..000000000000 --- a/pkg/client/informers/externalversions/apps/v1alpha1/clusterversion.go +++ /dev/null @@ -1,89 +0,0 @@ -/* -Copyright (C) 2022-2024 ApeCloud Co., Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by informer-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - "context" - time "time" - - appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" - versioned "github.com/apecloud/kubeblocks/pkg/client/clientset/versioned" - internalinterfaces "github.com/apecloud/kubeblocks/pkg/client/informers/externalversions/internalinterfaces" - v1alpha1 "github.com/apecloud/kubeblocks/pkg/client/listers/apps/v1alpha1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" - watch "k8s.io/apimachinery/pkg/watch" - cache "k8s.io/client-go/tools/cache" -) - -// ClusterVersionInformer provides access to a shared informer and lister for -// ClusterVersions. -type ClusterVersionInformer interface { - Informer() cache.SharedIndexInformer - Lister() v1alpha1.ClusterVersionLister -} - -type clusterVersionInformer struct { - factory internalinterfaces.SharedInformerFactory - tweakListOptions internalinterfaces.TweakListOptionsFunc -} - -// NewClusterVersionInformer constructs a new informer for ClusterVersion type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewClusterVersionInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredClusterVersionInformer(client, resyncPeriod, indexers, nil) -} - -// NewFilteredClusterVersionInformer constructs a new informer for ClusterVersion type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewFilteredClusterVersionInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { - return cache.NewSharedIndexInformer( - &cache.ListWatch{ - ListFunc: func(options v1.ListOptions) (runtime.Object, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.AppsV1alpha1().ClusterVersions().List(context.TODO(), options) - }, - WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.AppsV1alpha1().ClusterVersions().Watch(context.TODO(), options) - }, - }, - &appsv1alpha1.ClusterVersion{}, - resyncPeriod, - indexers, - ) -} - -func (f *clusterVersionInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredClusterVersionInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) -} - -func (f *clusterVersionInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&appsv1alpha1.ClusterVersion{}, f.defaultInformer) -} - -func (f *clusterVersionInformer) Lister() v1alpha1.ClusterVersionLister { - return v1alpha1.NewClusterVersionLister(f.Informer().GetIndexer()) -} diff --git a/pkg/client/informers/externalversions/apps/v1alpha1/interface.go b/pkg/client/informers/externalversions/apps/v1alpha1/interface.go index 1680292398e7..8d937199cec7 100644 --- a/pkg/client/informers/externalversions/apps/v1alpha1/interface.go +++ b/pkg/client/informers/externalversions/apps/v1alpha1/interface.go @@ -30,8 +30,6 @@ type Interface interface { Clusters() ClusterInformer // ClusterDefinitions returns a ClusterDefinitionInformer. ClusterDefinitions() ClusterDefinitionInformer - // ClusterVersions returns a ClusterVersionInformer. - ClusterVersions() ClusterVersionInformer // Components returns a ComponentInformer. Components() ComponentInformer // ComponentDefinitions returns a ComponentDefinitionInformer. @@ -74,11 +72,6 @@ func (v *version) ClusterDefinitions() ClusterDefinitionInformer { return &clusterDefinitionInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} } -// ClusterVersions returns a ClusterVersionInformer. -func (v *version) ClusterVersions() ClusterVersionInformer { - return &clusterVersionInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} -} - // Components returns a ComponentInformer. func (v *version) Components() ComponentInformer { return &componentInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index dedb7e215564..1d66d96e47e2 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -64,8 +64,6 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Apps().V1alpha1().Clusters().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("clusterdefinitions"): return &genericInformer{resource: resource.GroupResource(), informer: f.Apps().V1alpha1().ClusterDefinitions().Informer()}, nil - case v1alpha1.SchemeGroupVersion.WithResource("clusterversions"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Apps().V1alpha1().ClusterVersions().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("components"): return &genericInformer{resource: resource.GroupResource(), informer: f.Apps().V1alpha1().Components().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("componentdefinitions"): diff --git a/pkg/client/listers/apps/v1alpha1/clusterversion.go b/pkg/client/listers/apps/v1alpha1/clusterversion.go deleted file mode 100644 index 59761daae40b..000000000000 --- a/pkg/client/listers/apps/v1alpha1/clusterversion.go +++ /dev/null @@ -1,68 +0,0 @@ -/* -Copyright (C) 2022-2024 ApeCloud Co., Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by lister-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - v1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/tools/cache" -) - -// ClusterVersionLister helps list ClusterVersions. -// All objects returned here must be treated as read-only. -type ClusterVersionLister interface { - // List lists all ClusterVersions in the indexer. - // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*v1alpha1.ClusterVersion, err error) - // Get retrieves the ClusterVersion from the index for a given name. - // Objects returned here must be treated as read-only. - Get(name string) (*v1alpha1.ClusterVersion, error) - ClusterVersionListerExpansion -} - -// clusterVersionLister implements the ClusterVersionLister interface. -type clusterVersionLister struct { - indexer cache.Indexer -} - -// NewClusterVersionLister returns a new ClusterVersionLister. -func NewClusterVersionLister(indexer cache.Indexer) ClusterVersionLister { - return &clusterVersionLister{indexer: indexer} -} - -// List lists all ClusterVersions in the indexer. -func (s *clusterVersionLister) List(selector labels.Selector) (ret []*v1alpha1.ClusterVersion, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.ClusterVersion)) - }) - return ret, err -} - -// Get retrieves the ClusterVersion from the index for a given name. -func (s *clusterVersionLister) Get(name string) (*v1alpha1.ClusterVersion, error) { - obj, exists, err := s.indexer.GetByKey(name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(v1alpha1.Resource("clusterversion"), name) - } - return obj.(*v1alpha1.ClusterVersion), nil -} diff --git a/pkg/client/listers/apps/v1alpha1/expansion_generated.go b/pkg/client/listers/apps/v1alpha1/expansion_generated.go index 0f577dba1c35..277b9e9cc69a 100644 --- a/pkg/client/listers/apps/v1alpha1/expansion_generated.go +++ b/pkg/client/listers/apps/v1alpha1/expansion_generated.go @@ -34,10 +34,6 @@ type ClusterNamespaceListerExpansion interface{} // ClusterDefinitionLister. type ClusterDefinitionListerExpansion interface{} -// ClusterVersionListerExpansion allows custom methods to be added to -// ClusterVersionLister. -type ClusterVersionListerExpansion interface{} - // ComponentListerExpansion allows custom methods to be added to // ComponentLister. type ComponentListerExpansion interface{} diff --git a/pkg/configuration/core/configtemplate_util.go b/pkg/configuration/core/configtemplate_util.go index 13301dfeba78..080eaa3bcecf 100644 --- a/pkg/configuration/core/configtemplate_util.go +++ b/pkg/configuration/core/configtemplate_util.go @@ -21,11 +21,10 @@ package core import ( appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" - "github.com/apecloud/kubeblocks/pkg/common" ) type ComponentsType interface { - appsv1alpha1.ClusterComponentVersion | appsv1alpha1.ClusterComponentDefinition | appsv1alpha1.ClusterComponentSpec + appsv1alpha1.ClusterComponentDefinition | appsv1alpha1.ClusterComponentSpec } type filterFn[T ComponentsType] func(o T) bool @@ -43,7 +42,6 @@ func filter[T ComponentsType](components []T, f filterFn[T]) *T { func GetConfigTemplatesFromComponent( cComponents []appsv1alpha1.ClusterComponentSpec, dComponents []appsv1alpha1.ClusterComponentDefinition, - aComponents []appsv1alpha1.ClusterComponentVersion, componentName string) ([]appsv1alpha1.ComponentConfigSpec, error) { findCompTypeByName := func(comName string) *appsv1alpha1.ClusterComponentSpec { return filter(cComponents, func(o appsv1alpha1.ClusterComponentSpec) bool { @@ -55,63 +53,14 @@ func GetConfigTemplatesFromComponent( if cCom == nil { return nil, MakeError("failed to find component[%s]", componentName) } - aCom := filter(aComponents, func(o appsv1alpha1.ClusterComponentVersion) bool { - return o.ComponentDefRef == cCom.ComponentDefRef - }) dCom := filter(dComponents, func(o appsv1alpha1.ClusterComponentDefinition) bool { return o.Name == cCom.ComponentDefRef }) - var ( - cvConfigSpecs []appsv1alpha1.ComponentConfigSpec - cdConfigSpecs []appsv1alpha1.ComponentConfigSpec - ) - - if aCom != nil { - cvConfigSpecs = aCom.ConfigSpecs - } if dCom != nil { - cdConfigSpecs = dCom.ConfigSpecs - } - - return MergeConfigTemplates(cvConfigSpecs, cdConfigSpecs), nil -} - -// MergeConfigTemplates merges ClusterVersion.ComponentDefs[*].ConfigTemplateRefs and ClusterDefinition.ComponentDefs[*].ConfigTemplateRefs -func MergeConfigTemplates(cvConfigSpecs []appsv1alpha1.ComponentConfigSpec, - cdConfigSpecs []appsv1alpha1.ComponentConfigSpec) []appsv1alpha1.ComponentConfigSpec { - if len(cvConfigSpecs) == 0 { - return cdConfigSpecs - } - - if len(cdConfigSpecs) == 0 { - return cvConfigSpecs + return dCom.ConfigSpecs, nil } - - mergedCfgTpl := make([]appsv1alpha1.ComponentConfigSpec, 0, common.SafeAddInt(len(cvConfigSpecs), len(cdConfigSpecs))) - mergedTplMap := make(map[string]struct{}, cap(mergedCfgTpl)) - - for _, configSpec := range cvConfigSpecs { - tplName := configSpec.Name - if _, ok := (mergedTplMap)[tplName]; ok { - // It's been checked in validation webhook - continue - } - mergedCfgTpl = append(mergedCfgTpl, configSpec) - mergedTplMap[tplName] = struct{}{} - } - - for _, configSpec := range cdConfigSpecs { - // ClusterVersion replaces clusterDefinition - tplName := configSpec.Name - if _, ok := (mergedTplMap)[tplName]; ok { - continue - } - mergedCfgTpl = append(mergedCfgTpl, configSpec) - mergedTplMap[tplName] = struct{}{} - } - - return mergedCfgTpl + return nil, nil } func IsSupportConfigFileReconfigure(configTemplateSpec appsv1alpha1.ComponentConfigSpec, configFileKey string) bool { diff --git a/pkg/configuration/core/configtemplate_util_test.go b/pkg/configuration/core/configtemplate_util_test.go index 4e77fd76a105..18f514229917 100644 --- a/pkg/configuration/core/configtemplate_util_test.go +++ b/pkg/configuration/core/configtemplate_util_test.go @@ -27,155 +27,28 @@ import ( appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" ) -func TestMergeConfigTemplates(t *testing.T) { - type args struct { - cvTpl []appsv1alpha1.ComponentConfigSpec - cdTpl []appsv1alpha1.ComponentConfigSpec - } - tests := []struct { - name string - args args - want []appsv1alpha1.ComponentConfigSpec - }{{ - name: "merge_configtpl_test", - args: args{ - cvTpl: nil, - cdTpl: nil, - }, - want: nil, - }, { - name: "merge_configtpl_test", - args: args{ - cvTpl: []appsv1alpha1.ComponentConfigSpec{{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "test1", - TemplateRef: "tpl1", - VolumeName: "test1", - }}, { - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "test2", - TemplateRef: "tpl2", - VolumeName: "test2", - }}}, - cdTpl: nil, - }, - want: []appsv1alpha1.ComponentConfigSpec{{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "test1", - TemplateRef: "tpl1", - VolumeName: "test1", - }}, { - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "test2", - TemplateRef: "tpl2", - VolumeName: "test2", - }}}, - }, { - name: "merge_configtpl_test", - args: args{ - cvTpl: nil, - cdTpl: []appsv1alpha1.ComponentConfigSpec{{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "test1", - TemplateRef: "tpl1", - VolumeName: "test1", - }}, { - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "test2", - TemplateRef: "tpl2", - VolumeName: "test2", - }}}, - }, - want: []appsv1alpha1.ComponentConfigSpec{{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "test1", - TemplateRef: "tpl1", - VolumeName: "test1", - }}, { - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "test2", - TemplateRef: "tpl2", - VolumeName: "test2", - }}}, - }, { - name: "merge_configtpl_test", - args: args{ - cvTpl: []appsv1alpha1.ComponentConfigSpec{{ - // update volume - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "tpl1", - TemplateRef: "config1_new", - VolumeName: "volume1", - }}, { - // add volume - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "tpl2", - TemplateRef: "config2_new", - VolumeName: "volume2", - }}}, - cdTpl: []appsv1alpha1.ComponentConfigSpec{{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "tpl1", - TemplateRef: "config1", - VolumeName: "volume1", - }}, { - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "tpl3", - TemplateRef: "config3", - VolumeName: "volume3", - }}}, - }, - want: []appsv1alpha1.ComponentConfigSpec{ - { - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "tpl1", - TemplateRef: "config1_new", - VolumeName: "volume1", - }}, { - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "tpl2", - TemplateRef: "config2_new", - VolumeName: "volume2", - }}, { - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "tpl3", - TemplateRef: "config3", - VolumeName: "volume3", - }}}, - }} - - for _, tt := range tests { - got := MergeConfigTemplates(tt.args.cvTpl, tt.args.cdTpl) - require.EqualValues(t, tt.want, got) - } -} - func TestGetConfigTemplatesFromComponent(t *testing.T) { var ( comName = "replicats_name" comType = "replicats" - cComponents = []appsv1alpha1.ClusterComponentSpec{{ - Name: comName, - ComponentDefRef: comType, - }} - tpl1 = appsv1alpha1.ComponentConfigSpec{ + cComponents = []appsv1alpha1.ClusterComponentSpec{ + { + Name: comName, + ComponentDefRef: comType, + }, + } + tpl = appsv1alpha1.ComponentConfigSpec{ ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ Name: "tpl1", TemplateRef: "cm1", VolumeName: "volum1", - }} - tpl2 = appsv1alpha1.ComponentConfigSpec{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "tpl2", - TemplateRef: "cm2", - VolumeName: "volum2", - }} + }, + } ) type args struct { cComponents []appsv1alpha1.ClusterComponentSpec dComponents []appsv1alpha1.ClusterComponentDefinition - aComponents []appsv1alpha1.ClusterComponentVersion comName string } tests := []struct { @@ -183,66 +56,55 @@ func TestGetConfigTemplatesFromComponent(t *testing.T) { args args want []appsv1alpha1.ComponentConfigSpec wantErr bool - }{{ - name: "normal_test", - args: args{ - comName: comName, - cComponents: cComponents, - dComponents: []appsv1alpha1.ClusterComponentDefinition{{ - Name: comType, - ConfigSpecs: []appsv1alpha1.ComponentConfigSpec{tpl1}, - }}, - aComponents: []appsv1alpha1.ClusterComponentVersion{{ - ComponentDefRef: comType, - ConfigSpecs: []appsv1alpha1.ComponentConfigSpec{tpl2}, - }}, - }, - want: []appsv1alpha1.ComponentConfigSpec{ - tpl2, - tpl1, - }, - wantErr: false, - }, { - name: "failed_test", - args: args{ - comName: "not exist component", - cComponents: cComponents, - dComponents: []appsv1alpha1.ClusterComponentDefinition{{ - Name: comType, - ConfigSpecs: []appsv1alpha1.ComponentConfigSpec{tpl1}, - }}, - aComponents: []appsv1alpha1.ClusterComponentVersion{{ - ComponentDefRef: comType, - ConfigSpecs: []appsv1alpha1.ComponentConfigSpec{tpl2}, - }}, + }{ + { + name: "normal_test", + args: args{ + comName: comName, + cComponents: cComponents, + dComponents: []appsv1alpha1.ClusterComponentDefinition{{ + Name: comType, + ConfigSpecs: []appsv1alpha1.ComponentConfigSpec{tpl}, + }}, + }, + want: []appsv1alpha1.ComponentConfigSpec{ + tpl, + }, + wantErr: false, }, - want: nil, - wantErr: true, - }, { - name: "not_exist_and_not_failed", - args: args{ - comName: comName, - cComponents: cComponents, - dComponents: []appsv1alpha1.ClusterComponentDefinition{{ - Name: comType, - ConfigSpecs: []appsv1alpha1.ComponentConfigSpec{tpl1}, - }}, - aComponents: []appsv1alpha1.ClusterComponentVersion{{ - ComponentDefRef: "not exist", - ConfigSpecs: []appsv1alpha1.ComponentConfigSpec{tpl2}, + { + name: "failed_test", + args: args{ + comName: "not exist component", + cComponents: cComponents, + dComponents: []appsv1alpha1.ClusterComponentDefinition{{ + Name: comType, + ConfigSpecs: []appsv1alpha1.ComponentConfigSpec{tpl}, + }}, + }, + want: nil, + wantErr: true, + }, { + name: "not_exist_and_not_failed", + args: args{ + comName: comName, + cComponents: cComponents, + dComponents: []appsv1alpha1.ClusterComponentDefinition{{ + Name: comType, + ConfigSpecs: []appsv1alpha1.ComponentConfigSpec{tpl}, + }}, }, - }}, - want: []appsv1alpha1.ComponentConfigSpec{ - tpl1, + want: []appsv1alpha1.ComponentConfigSpec{ + tpl, + }, + wantErr: false, }, - wantErr: false, - }} + } for _, tt := range tests { got, err := GetConfigTemplatesFromComponent( tt.args.cComponents, tt.args.dComponents, - tt.args.aComponents, tt.args.comName) require.Equal(t, err != nil, tt.wantErr) require.EqualValues(t, got, tt.want) diff --git a/pkg/configuration/core/type.go b/pkg/configuration/core/type.go index 83a729413128..468e6f6b4fdc 100644 --- a/pkg/configuration/core/type.go +++ b/pkg/configuration/core/type.go @@ -163,7 +163,6 @@ func GenerateConstraintsUniqLabelKeyWithConfig(configKey string) string { return GenerateUniqKeyWithConfig(constant.ConfigurationConstraintsLabelPrefixKey, configKey) } -// GetInstanceCMName {{statefulset.Name}}-{{clusterVersion.Name}}-{{tpl.Name}}-"config" func GetInstanceCMName(obj client.Object, tpl *appsv1alpha1.ComponentTemplateSpec) string { return getInstanceCfgCMName(obj.GetName(), tpl.Name) } diff --git a/pkg/constant/annotations.go b/pkg/constant/annotations.go index 3385c5662197..f80ed4313125 100644 --- a/pkg/constant/annotations.go +++ b/pkg/constant/annotations.go @@ -37,7 +37,6 @@ const ( BackupPolicyTemplateAnnotationKey = "apps.kubeblocks.io/backup-policy-template" LastAppliedClusterAnnotationKey = "apps.kubeblocks.io/last-applied-cluster" PVLastClaimPolicyAnnotationKey = "apps.kubeblocks.io/pv-last-claim-policy" - HaltRecoveryAllowInconsistentCVAnnotKey = "clusters.apps.kubeblocks.io/allow-inconsistent-cv" HaltRecoveryAllowInconsistentResAnnotKey = "clusters.apps.kubeblocks.io/allow-inconsistent-resource" KubeBlocksGenerationKey = "kubeblocks.io/generation" ExtraEnvAnnotationKey = "kubeblocks.io/extra-env" diff --git a/pkg/constant/config.go b/pkg/constant/config.go index 8df6197812fd..cfc81b2fa321 100644 --- a/pkg/constant/config.go +++ b/pkg/constant/config.go @@ -20,7 +20,7 @@ const ( TPLRenderToolPath = "/bin/config_render" ConfigManagerToolPath = "/bin/reloader" - // ConfigurationTplLabelPrefixKey clusterVersion or clusterdefinition using tpl + // ConfigurationTplLabelPrefixKey clusterdefinition using tpl ConfigurationTplLabelPrefixKey = "config.kubeblocks.io/tpl" ConfigurationConstraintsLabelPrefixKey = "config.kubeblocks.io/constraints" diff --git a/pkg/constant/labels.go b/pkg/constant/labels.go index b1bccfbabe74..83bde789e266 100644 --- a/pkg/constant/labels.go +++ b/pkg/constant/labels.go @@ -54,7 +54,6 @@ const ( WorkloadTypeLabelKey = "apps.kubeblocks.io/workload-type" KBAppPodNameLabelKey = "apps.kubeblocks.io/pod-name" ClusterDefLabelKey = "clusterdefinition.kubeblocks.io/name" - ClusterVerLabelKey = "clusterversion.kubeblocks.io/name" ComponentDefinitionLabelKey = "componentdefinition.kubeblocks.io/name" ComponentVersionLabelKey = "componentversion.kubeblocks.io/name" ConsensusSetAccessModeLabelKey = "cs.apps.kubeblocks.io/access-mode" diff --git a/pkg/controller/component/action_post_provision_test.go b/pkg/controller/component/action_post_provision_test.go index 3f044c074b22..cc6f2b02bd3f 100644 --- a/pkg/controller/component/action_post_provision_test.go +++ b/pkg/controller/component/action_post_provision_test.go @@ -41,30 +41,23 @@ import ( var _ = Describe("Component PostProvision Test", func() { Context("has the BuildComponent function", func() { const ( - clusterDefName = "test-clusterdef" - clusterVersionName = "test-clusterversion" - clusterName = "test-cluster" - mysqlCompDefName = "replicasets" - mysqlCompName = "mysql" + clusterDefName = "test-clusterdef" + clusterName = "test-cluster" + mysqlCompDefName = "replicasets" + mysqlCompName = "mysql" ) var ( - clusterDef *appsv1alpha1.ClusterDefinition - clusterVersion *appsv1alpha1.ClusterVersion - cluster *appsv1alpha1.Cluster + clusterDef *appsv1alpha1.ClusterDefinition + cluster *appsv1alpha1.Cluster ) BeforeEach(func() { clusterDef = testapps.NewClusterDefFactory(clusterDefName). AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). GetObject() - clusterVersion = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefName). - AddComponentVersion(mysqlCompDefName). - AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - GetObject() pvcSpec := testapps.NewPVCSpec("1Gi") - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDef.Name, clusterVersion.Name). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). SetUID(clusterName). AddComponent(mysqlCompName, mysqlCompDefName). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). @@ -112,7 +105,6 @@ var _ = Describe("Component PostProvision Test", func() { reqCtx, testCtx.Cli, clusterDef, - clusterVersion, cluster, &cluster.Spec.ComponentSpecs[0]) Expect(err).Should(Succeed()) diff --git a/pkg/controller/component/action_pre_terminate_test.go b/pkg/controller/component/action_pre_terminate_test.go index 110781a0a868..a8c7f5cc8c56 100644 --- a/pkg/controller/component/action_pre_terminate_test.go +++ b/pkg/controller/component/action_pre_terminate_test.go @@ -41,30 +41,23 @@ import ( var _ = Describe("Component PreTerminate Test", func() { Context("has the BuildComponent function", func() { const ( - clusterDefName = "test-clusterdef" - clusterVersionName = "test-clusterversion" - clusterName = "test-cluster" - mysqlCompDefName = "replicasets" - mysqlCompName = "mysql" + clusterDefName = "test-clusterdef" + clusterName = "test-cluster" + mysqlCompDefName = "replicasets" + mysqlCompName = "mysql" ) var ( - clusterDef *appsv1alpha1.ClusterDefinition - clusterVersion *appsv1alpha1.ClusterVersion - cluster *appsv1alpha1.Cluster + clusterDef *appsv1alpha1.ClusterDefinition + cluster *appsv1alpha1.Cluster ) BeforeEach(func() { clusterDef = testapps.NewClusterDefFactory(clusterDefName). AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). GetObject() - clusterVersion = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefName). - AddComponentVersion(mysqlCompDefName). - AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - GetObject() pvcSpec := testapps.NewPVCSpec("1Gi") - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDef.Name, clusterVersion.Name). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). SetUID(clusterName). AddComponent(mysqlCompName, mysqlCompDefName). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). @@ -112,7 +105,6 @@ var _ = Describe("Component PreTerminate Test", func() { reqCtx, testCtx.Cli, clusterDef, - clusterVersion, cluster, &cluster.Spec.ComponentSpecs[0]) Expect(err).Should(Succeed()) diff --git a/pkg/controller/component/action_utils_test.go b/pkg/controller/component/action_utils_test.go index 2b4bba48137e..7a204e100d60 100644 --- a/pkg/controller/component/action_utils_test.go +++ b/pkg/controller/component/action_utils_test.go @@ -43,30 +43,23 @@ var tlog = ctrl.Log.WithName("component_testing") var _ = Describe("Component LifeCycle Action Utils Test", func() { Context("has the BuildComponent function", func() { const ( - clusterDefName = "test-clusterdef" - clusterVersionName = "test-clusterversion" - clusterName = "test-cluster" - mysqlCompDefName = "replicasets" - mysqlCompName = "mysql" + clusterDefName = "test-clusterdef" + clusterName = "test-cluster" + mysqlCompDefName = "replicasets" + mysqlCompName = "mysql" ) var ( - clusterDef *appsv1alpha1.ClusterDefinition - clusterVersion *appsv1alpha1.ClusterVersion - cluster *appsv1alpha1.Cluster + clusterDef *appsv1alpha1.ClusterDefinition + cluster *appsv1alpha1.Cluster ) BeforeEach(func() { clusterDef = testapps.NewClusterDefFactory(clusterDefName). AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). GetObject() - clusterVersion = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefName). - AddComponentVersion(mysqlCompDefName). - AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - GetObject() pvcSpec := testapps.NewPVCSpec("1Gi") - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDef.Name, clusterVersion.Name). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). SetUID(clusterName). AddComponent(mysqlCompName, mysqlCompDefName). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). @@ -114,7 +107,6 @@ var _ = Describe("Component LifeCycle Action Utils Test", func() { reqCtx, testCtx.Cli, clusterDef, - clusterVersion, cluster, &cluster.Spec.ComponentSpecs[0]) Expect(err).Should(Succeed()) diff --git a/pkg/controller/component/component.go b/pkg/controller/component/component.go index 2e601c1d14d1..705086b597c4 100644 --- a/pkg/controller/component/component.go +++ b/pkg/controller/component/component.go @@ -122,13 +122,12 @@ func BuildComponent(cluster *appsv1alpha1.Cluster, compSpec *appsv1alpha1.Cluste } func BuildComponentDefinition(clusterDef *appsv1alpha1.ClusterDefinition, - clusterVer *appsv1alpha1.ClusterVersion, clusterCompSpec *appsv1alpha1.ClusterComponentSpec) (*appsv1alpha1.ComponentDefinition, error) { - clusterCompDef, clusterCompVer, err := getClusterCompDefAndVersion(clusterDef, clusterVer, clusterCompSpec) + clusterCompDef, err := getClusterCompDef(clusterDef, clusterCompSpec) if err != nil { return nil, err } - compDef, err := buildComponentDefinitionByConversion(clusterCompDef, clusterCompVer) + compDef, err := buildComponentDefinitionByConversion(clusterCompDef) if err != nil { return nil, err } @@ -137,11 +136,10 @@ func BuildComponentDefinition(clusterDef *appsv1alpha1.ClusterDefinition, func getOrBuildComponentDefinition(ctx context.Context, cli client.Reader, clusterDef *appsv1alpha1.ClusterDefinition, - clusterVer *appsv1alpha1.ClusterVersion, cluster *appsv1alpha1.Cluster, clusterCompSpec *appsv1alpha1.ClusterComponentSpec) (*appsv1alpha1.ComponentDefinition, error) { if len(cluster.Spec.ClusterDefRef) > 0 && len(clusterCompSpec.ComponentDefRef) > 0 { - return BuildComponentDefinition(clusterDef, clusterVer, clusterCompSpec) + return BuildComponentDefinition(clusterDef, clusterCompSpec) } if len(clusterCompSpec.ComponentDef) > 0 { compDef := &appsv1alpha1.ComponentDefinition{} @@ -154,48 +152,36 @@ func getOrBuildComponentDefinition(ctx context.Context, cli client.Reader, } func getClusterReferencedResources(ctx context.Context, cli client.Reader, - cluster *appsv1alpha1.Cluster) (*appsv1alpha1.ClusterDefinition, *appsv1alpha1.ClusterVersion, error) { + cluster *appsv1alpha1.Cluster) (*appsv1alpha1.ClusterDefinition, error) { var ( clusterDef *appsv1alpha1.ClusterDefinition - clusterVer *appsv1alpha1.ClusterVersion ) if len(cluster.Spec.ClusterDefRef) > 0 { clusterDef = &appsv1alpha1.ClusterDefinition{} if err := cli.Get(ctx, types.NamespacedName{Name: cluster.Spec.ClusterDefRef}, clusterDef); err != nil { - return nil, nil, err - } - } - if len(cluster.Spec.ClusterVersionRef) > 0 { - clusterVer = &appsv1alpha1.ClusterVersion{} - if err := cli.Get(ctx, types.NamespacedName{Name: cluster.Spec.ClusterVersionRef}, clusterVer); err != nil { - return nil, nil, err + return nil, err } } if clusterDef == nil { if len(cluster.Spec.ClusterDefRef) == 0 { - return nil, nil, fmt.Errorf("cluster definition is needed for generated component") + return nil, fmt.Errorf("cluster definition is needed for generated component") } else { - return nil, nil, fmt.Errorf("referenced cluster definition is not found: %s", cluster.Spec.ClusterDefRef) + return nil, fmt.Errorf("referenced cluster definition is not found: %s", cluster.Spec.ClusterDefRef) } } - return clusterDef, clusterVer, nil + return clusterDef, nil } -func getClusterCompDefAndVersion(clusterDef *appsv1alpha1.ClusterDefinition, - clusterVer *appsv1alpha1.ClusterVersion, - clusterCompSpec *appsv1alpha1.ClusterComponentSpec) (*appsv1alpha1.ClusterComponentDefinition, *appsv1alpha1.ClusterComponentVersion, error) { +func getClusterCompDef(clusterDef *appsv1alpha1.ClusterDefinition, + clusterCompSpec *appsv1alpha1.ClusterComponentSpec) (*appsv1alpha1.ClusterComponentDefinition, error) { if len(clusterCompSpec.ComponentDefRef) == 0 { - return nil, nil, fmt.Errorf("cluster component definition ref is empty: %s", clusterCompSpec.Name) + return nil, fmt.Errorf("cluster component definition ref is empty: %s", clusterCompSpec.Name) } clusterCompDef := clusterDef.GetComponentDefByName(clusterCompSpec.ComponentDefRef) if clusterCompDef == nil { - return nil, nil, fmt.Errorf("referenced cluster component definition is not defined: %s", clusterCompSpec.ComponentDefRef) - } - var clusterCompVer *appsv1alpha1.ClusterComponentVersion - if clusterVer != nil { - clusterCompVer = clusterVer.Spec.GetDefNameMappingComponents()[clusterCompSpec.ComponentDefRef] + return nil, fmt.Errorf("referenced cluster component definition is not defined: %s", clusterCompSpec.ComponentDefRef) } - return clusterCompDef, clusterCompVer, nil + return clusterCompDef, nil } func getClusterCompSpec4Component(ctx context.Context, cli client.Reader, diff --git a/pkg/controller/component/component_test.go b/pkg/controller/component/component_test.go index d9618277fa34..2a019739a6da 100644 --- a/pkg/controller/component/component_test.go +++ b/pkg/controller/component/component_test.go @@ -42,7 +42,6 @@ var _ = Describe("Component", func() { Context("has the BuildComponent function", func() { const ( clusterDefName = "test-clusterdef" - clusterVersionName = "test-clusterversion" clusterName = "test-cluster" mysqlCompDefName = "replicasets" mysqlCompName = "mysql" @@ -53,9 +52,8 @@ var _ = Describe("Component", func() { ) var ( - clusterDef *appsv1alpha1.ClusterDefinition - clusterVersion *appsv1alpha1.ClusterVersion - cluster *appsv1alpha1.Cluster + clusterDef *appsv1alpha1.ClusterDefinition + cluster *appsv1alpha1.Cluster ) BeforeEach(func() { @@ -63,49 +61,14 @@ var _ = Describe("Component", func() { AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). AddComponentDef(testapps.StatelessNginxComponent, proxyCompDefName). GetObject() - clusterVersion = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefName). - AddComponentVersion(mysqlCompDefName). - AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - AddComponentVersion(proxyCompDefName). - AddInitContainerShort("nginx-init", testapps.NginxImage). - AddContainerShort("nginx", testapps.NginxImage). - GetObject() pvcSpec := testapps.NewPVCSpec("1Gi") - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name, clusterVersion.Name). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). AddComponent(mysqlCompName, mysqlCompDefName). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). AddComponent(proxyCompName, proxyCompDefName). GetObject() }) - It("should work as expected with various inputs", func() { - By("assign every available fields") - reqCtx := intctrlutil.RequestCtx{ - Ctx: ctx, - Log: logger, - } - component, err := BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, clusterVersion, cluster, &cluster.Spec.ComponentSpecs[0]) - Expect(err).Should(Succeed()) - Expect(component).ShouldNot(BeNil()) - - By("leave clusterVersion.versionCtx empty initContains and containers") - clusterVersion.Spec.ComponentVersions[0].VersionsCtx.Containers = nil - clusterVersion.Spec.ComponentVersions[0].VersionsCtx.InitContainers = nil - component, err = BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, clusterVersion, cluster, &cluster.Spec.ComponentSpecs[0]) - Expect(err).Should(Succeed()) - Expect(component).ShouldNot(BeNil()) - - By("new container in clusterVersion not in clusterDefinition") - component, err = BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, clusterVersion, cluster, &cluster.Spec.ComponentSpecs[0]) - Expect(err).Should(Succeed()) - Expect(len(component.PodSpec.Containers) >= 2).Should(BeTrue()) - - By("new init container in clusterVersion not in clusterDefinition") - component, err = BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, clusterVersion, cluster, &cluster.Spec.ComponentSpecs[1]) - Expect(err).Should(Succeed()) - Expect(len(component.PodSpec.InitContainers)).Should(Equal(1)) - }) - It("should auto fill first component if it's empty", func() { reqCtx := intctrlutil.RequestCtx{ Ctx: ctx, @@ -123,7 +86,7 @@ var _ = Describe("Component", func() { cluster.Spec.ComponentSpecs = nil By("build first component from simplified fields") - synthesizeComp, err := BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, clusterVersion, cluster, nil) + synthesizeComp, err := BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, cluster, nil) Expect(err).Should(Succeed()) Expect(synthesizeComp).ShouldNot(BeNil()) Expect(synthesizeComp.Replicas).Should(Equal(*cluster.Spec.Replicas)) @@ -141,7 +104,7 @@ var _ = Describe("Component", func() { By("clear cluster's component spec") cluster.Spec.ComponentSpecs = nil By("call build") - synthesizeComp, err := BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, clusterVersion, cluster, nil) + synthesizeComp, err := BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, cluster, nil) Expect(err).Should(Succeed()) Expect(synthesizeComp).ShouldNot(BeNil()) Expect(synthesizeComp.PodSpec.Affinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution[0].PodAffinityTerm.TopologyKey).Should(Equal("topology.kubernetes.io/zone")) @@ -163,7 +126,7 @@ var _ = Describe("Component", func() { By("clear cluster's component spec") cluster.Spec.ComponentSpecs = nil By("call build") - synthesizeComp, err := BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, clusterVersion, cluster, nil) + synthesizeComp, err := BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, cluster, nil) Expect(err).Should(Succeed()) Expect(synthesizeComp).ShouldNot(BeNil()) Expect(synthesizeComp.ComponentServices).Should(HaveLen(2)) @@ -216,7 +179,7 @@ var _ = Describe("Component", func() { By("clear cluster's component spec") cluster.Spec.ComponentSpecs = nil By("call build") - synthesizeComp, err := BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, clusterVersion, cluster, nil) + synthesizeComp, err := BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, cluster, nil) Expect(err).Should(Succeed()) Expect(synthesizeComp).Should(BeNil()) }) @@ -247,7 +210,7 @@ var _ = Describe("Component", func() { testapps.NginxImage: serviceDescriptor, } By("call build") - synthesizeComp, err := BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, clusterVersion, cluster, &cluster.Spec.ComponentSpecs[0]) + synthesizeComp, err := BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, cluster, &cluster.Spec.ComponentSpecs[0]) Expect(err).Should(Succeed()) Expect(synthesizeComp).ShouldNot(BeNil()) Expect(synthesizeComp.ServiceReferences).ShouldNot(BeNil()) @@ -314,7 +277,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 := BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, nil, cluster, &cluster.Spec.ComponentSpecs[0]) + comp, err := BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, cluster, &cluster.Spec.ComponentSpecs[0]) Expect(err).Should(Succeed()) Expect(comp).ShouldNot(BeNil()) for _, vol := range comp.PodSpec.Volumes { @@ -335,7 +298,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 = BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, nil, cluster, &cluster.Spec.ComponentSpecs[0]) + comp, err = BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, cluster, &cluster.Spec.ComponentSpecs[0]) Expect(err).Should(Succeed()) Expect(comp).ShouldNot(BeNil()) for _, vol := range comp.PodSpec.Volumes { diff --git a/pkg/controller/component/definition_convertor.go b/pkg/controller/component/definition_convertor.go index ebc3b5d22fb4..90fb6355adb4 100644 --- a/pkg/controller/component/definition_convertor.go +++ b/pkg/controller/component/definition_convertor.go @@ -27,7 +27,6 @@ import ( appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" "github.com/apecloud/kubeblocks/pkg/apiutil" - cfgcore "github.com/apecloud/kubeblocks/pkg/configuration/core" "github.com/apecloud/kubeblocks/pkg/constant" "github.com/apecloud/kubeblocks/pkg/controller/builder" ) @@ -35,8 +34,7 @@ import ( // TODO(component): type check // buildComponentDefinitionByConversion builds a ComponentDefinition from a ClusterComponentDefinition and a ClusterComponentVersion. -func buildComponentDefinitionByConversion(clusterCompDef *appsv1alpha1.ClusterComponentDefinition, - clusterCompVer *appsv1alpha1.ClusterComponentVersion) (*appsv1alpha1.ComponentDefinition, error) { +func buildComponentDefinitionByConversion(clusterCompDef *appsv1alpha1.ClusterComponentDefinition) (*appsv1alpha1.ComponentDefinition, error) { if clusterCompDef == nil { return nil, nil } @@ -64,7 +62,7 @@ func buildComponentDefinitionByConversion(clusterCompDef *appsv1alpha1.ClusterCo "exporter": &compDefExporterConvertor{}, } compDef := &appsv1alpha1.ComponentDefinition{} - if err := covertObject(convertors, &compDef.Spec, clusterCompDef, clusterCompVer); err != nil { + if err := covertObject(convertors, &compDef.Spec, clusterCompDef); err != nil { return nil, err } return compDef, nil @@ -104,23 +102,10 @@ type compDefRuntimeConvertor struct{} func (c *compDefRuntimeConvertor) convert(args ...any) (any, error) { clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - var clusterCompVer *appsv1alpha1.ClusterComponentVersion - if len(args) > 1 { - clusterCompVer = args[1].(*appsv1alpha1.ClusterComponentVersion) - } if clusterCompDef.PodSpec == nil { return nil, fmt.Errorf("no pod spec") } - podSpec := clusterCompDef.PodSpec.DeepCopy() - if clusterCompVer != nil { - for _, container := range clusterCompVer.VersionsCtx.InitContainers { - podSpec.InitContainers = appendOrOverrideContainerAttr(podSpec.InitContainers, container) - } - for _, container := range clusterCompVer.VersionsCtx.Containers { - podSpec.Containers = appendOrOverrideContainerAttr(podSpec.Containers, container) - } - } return *podSpec, nil } @@ -290,14 +275,7 @@ type compDefConfigsConvertor struct{} func (c *compDefConfigsConvertor) convert(args ...any) (any, error) { clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - var clusterCompVer *appsv1alpha1.ClusterComponentVersion - if len(args) > 1 { - clusterCompVer = args[1].(*appsv1alpha1.ClusterComponentVersion) - } - if clusterCompVer == nil { - return clusterCompDef.ConfigSpecs, nil - } - return cfgcore.MergeConfigTemplates(clusterCompVer.ConfigSpecs, clusterCompDef.ConfigSpecs), nil + return clusterCompDef.ConfigSpecs, nil } // compDefLogConfigsConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.LogConfigs. @@ -487,10 +465,6 @@ type compDefLifecycleActionsConvertor struct{} func (c *compDefLifecycleActionsConvertor) convert(args ...any) (any, error) { clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - var clusterCompVer *appsv1alpha1.ClusterComponentVersion - if len(args) > 1 { - clusterCompVer = args[1].(*appsv1alpha1.ClusterComponentVersion) - } lifecycleActions := &appsv1alpha1.ComponentLifecycleActions{} @@ -500,7 +474,7 @@ func (c *compDefLifecycleActionsConvertor) convert(args ...any) (any, error) { } if clusterCompDef.SwitchoverSpec != nil { - lifecycleActions.Switchover = c.convertSwitchover(clusterCompDef.SwitchoverSpec, clusterCompVer) + lifecycleActions.Switchover = c.convertSwitchover(clusterCompDef.SwitchoverSpec) } if clusterCompDef.PostStartSpec != nil { @@ -613,12 +587,8 @@ func (c *compDefLifecycleActionsConvertor) convertPostProvision(postStart *appsv } } -func (c *compDefLifecycleActionsConvertor) convertSwitchover(switchover *appsv1alpha1.SwitchoverSpec, - clusterCompVer *appsv1alpha1.ClusterComponentVersion) *appsv1alpha1.ComponentSwitchover { +func (c *compDefLifecycleActionsConvertor) convertSwitchover(switchover *appsv1alpha1.SwitchoverSpec) *appsv1alpha1.ComponentSwitchover { spec := *switchover - if clusterCompVer != nil { - overrideSwitchoverSpecAttr(&spec, clusterCompVer.SwitchoverSpec) - } if spec.WithCandidate == nil && spec.WithoutCandidate == nil { return nil } diff --git a/pkg/controller/component/definition_convertor_test.go b/pkg/controller/component/definition_convertor_test.go index 1fa9290af77d..7c64ab03c18f 100644 --- a/pkg/controller/component/definition_convertor_test.go +++ b/pkg/controller/component/definition_convertor_test.go @@ -307,43 +307,6 @@ var _ = Describe("Component Definition Convertor", func() { Expect(err).Should(HaveOccurred()) Expect(res).Should(BeNil()) }) - - It("w/o comp version", func() { - convertor := &compDefRuntimeConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).Should(BeEquivalentTo(*clusterCompDef.PodSpec)) - }) - - It("w/ comp version", func() { - clusterCompVer := &appsv1alpha1.ClusterComponentVersion{ - VersionsCtx: appsv1alpha1.VersionsContext{ - InitContainers: []corev1.Container{ - { - Name: "init", - Image: "init", - }, - }, - Containers: []corev1.Container{ - { - Name: "mysql", - Image: "image", - }, - }, - }, - } - - convertor := &compDefRuntimeConvertor{} - res, err := convertor.convert(clusterCompDef, clusterCompVer) - Expect(err).Should(Succeed()) - - expectedPodSpec := clusterCompDef.PodSpec - Expect(expectedPodSpec.Containers[0].Image).Should(BeEmpty()) - Expect(expectedPodSpec.InitContainers).Should(HaveLen(0)) - expectedPodSpec.Containers[0].Image = clusterCompVer.VersionsCtx.Containers[0].Image - expectedPodSpec.InitContainers = clusterCompVer.VersionsCtx.InitContainers - Expect(res).Should(BeEquivalentTo(*expectedPodSpec)) - }) }) Context("vars", func() { @@ -547,37 +510,11 @@ var _ = Describe("Component Definition Convertor", func() { }) }) - Context("configs", func() { - It("w/o comp version", func() { - convertor := &compDefConfigsConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).Should(BeEquivalentTo(clusterCompDef.ConfigSpecs)) - }) - - It("w/ comp version", func() { - clusterCompVer := &appsv1alpha1.ClusterComponentVersion{ - ConfigSpecs: []appsv1alpha1.ComponentConfigSpec{ - { - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "agamotto-config", - TemplateRef: "agamotto-config-template", - VolumeName: "agamotto-config", - DefaultMode: &defaultVolumeMode, - }, - }, - }, - } - - convertor := &compDefConfigsConvertor{} - res, err := convertor.convert(clusterCompDef, clusterCompVer) - Expect(err).Should(Succeed()) - - expectedConfigs := make([]appsv1alpha1.ComponentConfigSpec, 0) - expectedConfigs = append(expectedConfigs, clusterCompVer.ConfigSpecs...) - expectedConfigs = append(expectedConfigs, clusterCompDef.ConfigSpecs...) - Expect(res).Should(BeEquivalentTo(expectedConfigs)) - }) + It("configs", func() { + convertor := &compDefConfigsConvertor{} + res, err := convertor.convert(clusterCompDef) + Expect(err).Should(Succeed()) + Expect(res).Should(BeEquivalentTo(clusterCompDef.ConfigSpecs)) }) It("log configs", func() { @@ -752,7 +689,7 @@ var _ = Describe("Component Definition Convertor", func() { }) Context("lifecycle actions", func() { - It("w/o comp version", func() { + It("ok", func() { clusterCompDef.Probes.RoleProbe = nil convertor := &compDefLifecycleActionsConvertor{} @@ -764,19 +701,6 @@ var _ = Describe("Component Definition Convertor", func() { Expect(*actions).Should(BeEquivalentTo(*expectedActions)) }) - It("w/ comp version", func() { - clusterCompDef.Probes.RoleProbe = nil - clusterCompVer := &appsv1alpha1.ClusterComponentVersion{} - - convertor := &compDefLifecycleActionsConvertor{} - res, err := convertor.convert(clusterCompDef, clusterCompVer) - Expect(err).Should(Succeed()) - - actions := res.(*appsv1alpha1.ComponentLifecycleActions) - expectedActions := &appsv1alpha1.ComponentLifecycleActions{} - Expect(*actions).Should(BeEquivalentTo(*expectedActions)) - }) - It("switchover", func() { clusterCompDef.Probes.RoleProbe = nil convertor := &compDefLifecycleActionsConvertor{} diff --git a/pkg/controller/component/fieldref_util_test.go b/pkg/controller/component/fieldref_util_test.go index 1589cacb471f..47e9d49cef09 100644 --- a/pkg/controller/component/fieldref_util_test.go +++ b/pkg/controller/component/fieldref_util_test.go @@ -33,7 +33,6 @@ import ( var _ = Describe("ComponentRef Fields Tests", func() { const clusterDefName = "test-clusterdef" const clusterName = "test-cluster" - const clusterVersionName = "test-clusterversion" const clusterNamespace = "test-compref" const mysqlCompDefName = "mysql-def" const referredCompDefName = "maxscale-def" @@ -54,8 +53,8 @@ var _ = Describe("ComponentRef Fields Tests", func() { // add one mysql component clusterDefBuilder = clusterDefBuilder.AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName) - By("create cluste builder") - clusterBuilder = testapps.NewClusterFactory(clusterNamespace, clusterName, clusterDefName, clusterVersionName) + By("create cluster builder") + clusterBuilder = testapps.NewClusterFactory(clusterNamespace, clusterName, clusterDefName) }) It("test fieldref", func() { diff --git a/pkg/controller/component/service_descriptor_utils_test.go b/pkg/controller/component/service_descriptor_utils_test.go index fe37c4321168..991142b60a1e 100644 --- a/pkg/controller/component/service_descriptor_utils_test.go +++ b/pkg/controller/component/service_descriptor_utils_test.go @@ -52,7 +52,6 @@ var _ = Describe("build service references", func() { // resources should be released in following order // non-namespaced - testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.ClusterVersionSignature, true, ml) testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.ClusterDefinitionSignature, true, ml) testapps.ClearResources(&testCtx, generics.ConfigConstraintSignature, ml) @@ -63,7 +62,6 @@ var _ = Describe("build service references", func() { var ( mockClient *testutil.K8sClientMockHelper clusterDef *appsv1alpha1.ClusterDefinition - clusterVersion *appsv1alpha1.ClusterVersion cluster *appsv1alpha1.Cluster beReferencedCluster *appsv1alpha1.Cluster ) @@ -73,7 +71,6 @@ var _ = Describe("build service references", func() { clusterName = "cluster" beReferencedClusterName = "cluster-be-referenced" clusterDefName = "test-cd" - clusterVersionName = "test-cv" nginxCompName = "nginx" nginxCompDefName = "nginx" mysqlCompName = "mysql" @@ -101,7 +98,6 @@ var _ = Describe("build service references", func() { buildServiceReferences4Test := func(ctx context.Context, cli client.Reader, clusterDef *appsv1alpha1.ClusterDefinition, - clusterVer *appsv1alpha1.ClusterVersion, cluster *appsv1alpha1.Cluster, clusterCompSpec *appsv1alpha1.ClusterComponentSpec) (map[string]*appsv1alpha1.ServiceDescriptor, error) { var ( @@ -109,7 +105,7 @@ var _ = Describe("build service references", func() { comp *appsv1alpha1.Component err error ) - if compDef, err = BuildComponentDefinition(clusterDef, clusterVer, clusterCompSpec); err != nil { + if compDef, err = BuildComponentDefinition(clusterDef, clusterCompSpec); err != nil { return nil, err } if comp, err = BuildComponent(cluster, clusterCompSpec, nil, nil); err != nil { @@ -152,11 +148,6 @@ var _ = Describe("build service references", func() { AddComponentDef(testapps.StatelessNginxComponent, nginxCompDefName). AddServiceRefDeclarations(serviceRefDeclarations). Create(&testCtx).GetObject() - clusterVersion = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefName). - AddComponentVersion(nginxCompDefName). - AddInitContainerShort("nginx-init", testapps.NginxImage). - AddContainerShort("nginx", testapps.NginxImage). - Create(&testCtx).GetObject() }) It("serviceRefDeclaration serviceVersion regex validation test", func() { @@ -226,8 +217,7 @@ var _ = Describe("build service references", func() { It("generate service descriptor test", func() { By("Create cluster and beReferencedCluster object") - beReferencedCluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, beReferencedClusterName, - clusterDef.Name, clusterVersion.Name). + beReferencedCluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, beReferencedClusterName, clusterDef.Name). AddComponent(mysqlCompName, mysqlCompDefName). Create(&testCtx).GetObject() @@ -241,14 +231,13 @@ var _ = Describe("build service references", func() { Cluster: beReferencedCluster.Name, }, } - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDef.Name, clusterVersion.Name). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). AddComponent(nginxCompName, nginxCompDefName). SetServiceRefs(serviceRefs). Create(&testCtx).GetObject() By("GenServiceReferences failed because external service descriptor not found") - serviceReferences, err := buildServiceReferences4Test(testCtx.Ctx, testCtx.Cli, clusterDef, nil, cluster, &cluster.Spec.ComponentSpecs[0]) + serviceReferences, err := buildServiceReferences4Test(testCtx.Ctx, testCtx.Cli, clusterDef, cluster, &cluster.Spec.ComponentSpecs[0]) Expect(err).ShouldNot(Succeed()) Expect(apierrors.IsNotFound(err)).Should(BeTrue()) Expect(serviceReferences).Should(BeNil()) @@ -279,7 +268,7 @@ var _ = Describe("build service references", func() { Create(&testCtx).GetObject() By("GenServiceReferences failed because external service descriptor status is not available") - serviceReferences, err = buildServiceReferences4Test(testCtx.Ctx, testCtx.Cli, clusterDef, nil, cluster, &cluster.Spec.ComponentSpecs[0]) + serviceReferences, err = buildServiceReferences4Test(testCtx.Ctx, testCtx.Cli, clusterDef, cluster, &cluster.Spec.ComponentSpecs[0]) Expect(err).ShouldNot(Succeed()) Expect(err.Error()).Should(ContainSubstring("status is not available")) Expect(serviceReferences).Should(BeNil()) @@ -290,7 +279,7 @@ var _ = Describe("build service references", func() { })).Should(Succeed()) By("GenServiceReferences failed because external service descriptor kind and version not match") - serviceReferences, err = buildServiceReferences4Test(testCtx.Ctx, testCtx.Cli, clusterDef, nil, cluster, &cluster.Spec.ComponentSpecs[0]) + serviceReferences, err = buildServiceReferences4Test(testCtx.Ctx, testCtx.Cli, clusterDef, cluster, &cluster.Spec.ComponentSpecs[0]) Expect(err).ShouldNot(Succeed()) Expect(err.Error()).Should(ContainSubstring("kind or version is not match with")) Expect(serviceReferences).Should(BeNil()) @@ -318,7 +307,7 @@ var _ = Describe("build service references", func() { Expect(testCtx.CheckedCreateObj(ctx, secret)).Should(Succeed()) Expect(k8sClient.Get(context.Background(), client.ObjectKey{Name: secret.Name, Namespace: secret.Namespace}, secret)).Should(Succeed()) - serviceReferences, err = buildServiceReferences4Test(testCtx.Ctx, testCtx.Cli, clusterDef, nil, cluster, &cluster.Spec.ComponentSpecs[0]) + serviceReferences, err = buildServiceReferences4Test(testCtx.Ctx, testCtx.Cli, clusterDef, cluster, &cluster.Spec.ComponentSpecs[0]) Expect(err).Should(Succeed()) Expect(serviceReferences).ShouldNot(BeNil()) Expect(len(serviceReferences)).Should(Equal(2)) diff --git a/pkg/controller/component/service_reference_test.go b/pkg/controller/component/service_reference_test.go index c9b0c0661815..d444ff697b96 100644 --- a/pkg/controller/component/service_reference_test.go +++ b/pkg/controller/component/service_reference_test.go @@ -51,7 +51,6 @@ var _ = Describe("service reference", func() { // resources should be released in following order // non-namespaced testapps.ClearResources(&testCtx, generics.ConfigConstraintSignature, ml) - testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.ClusterVersionSignature, true, ml) testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.ClusterDefinitionSignature, true, ml) // namespaced @@ -62,7 +61,6 @@ var _ = Describe("service reference", func() { var ( mockClient *testutil.K8sClientMockHelper clusterDef *appsv1alpha1.ClusterDefinition - clusterVersion *appsv1alpha1.ClusterVersion cluster *appsv1alpha1.Cluster beReferencedCluster *appsv1alpha1.Cluster beReferencedServiceDescriptor *appsv1alpha1.ServiceDescriptor @@ -73,7 +71,6 @@ var _ = Describe("service reference", func() { clusterName = "mycluster" beReferencedClusterName = "mycluster-be-referenced" clusterDefName = "test-clusterdef" - clusterVersionName = "test-clusterversion" nginxCompName = "nginx" nginxCompDefName = "nginx" mysqlCompName = "mysql" @@ -120,11 +117,6 @@ var _ = Describe("service reference", func() { AddComponentDef(testapps.StatelessNginxComponent, nginxCompDefName). AddServiceRefDeclarations(serviceRefDeclarations). Create(&testCtx).GetObject() - clusterVersion = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefName). - AddComponentVersion(nginxCompDefName). - AddInitContainerShort("nginx-init", testapps.NginxImage). - AddContainerShort("nginx", testapps.NginxImage). - Create(&testCtx).GetObject() By("mock a service descriptor and the configmap referenced") configMap := &corev1.ConfigMap{ @@ -218,7 +210,7 @@ var _ = Describe("service reference", func() { }, } Expect(testCtx.CheckedCreateObj(ctx, secret)).Should(Succeed()) - beReferencedCluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, beReferencedClusterName, clusterDef.Name, clusterVersion.Name). + beReferencedCluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, beReferencedClusterName, clusterDef.Name). AddComponent(mysqlCompName, mysqlCompDefName). Create(&testCtx). GetObject() @@ -233,8 +225,7 @@ var _ = Describe("service reference", func() { Cluster: beReferencedCluster.Name, }, } - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDef.Name, clusterVersion.Name). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). AddComponent(nginxCompName, nginxCompDefName). SetServiceRefs(serviceRefs). Create(&testCtx).GetObject() diff --git a/pkg/controller/component/synthesize_component.go b/pkg/controller/component/synthesize_component.go index 943e31c4b1fc..d56e1ccf561c 100644 --- a/pkg/controller/component/synthesize_component.go +++ b/pkg/controller/component/synthesize_component.go @@ -57,7 +57,7 @@ func BuildSynthesizedComponent4Generated(reqCtx intctrlutil.RequestCtx, cli client.Reader, cluster *appsv1alpha1.Cluster, comp *appsv1alpha1.Component) (*appsv1alpha1.ComponentDefinition, *SynthesizedComponent, error) { - clusterDef, clusterVer, err := getClusterReferencedResources(reqCtx.Ctx, cli, cluster) + clusterDef, err := getClusterReferencedResources(reqCtx.Ctx, cli, cluster) if err != nil { return nil, nil, err } @@ -68,7 +68,7 @@ func BuildSynthesizedComponent4Generated(reqCtx intctrlutil.RequestCtx, if clusterCompSpec == nil { return nil, nil, fmt.Errorf("cluster component spec is not found: %s", comp.Name) } - compDef, err := getOrBuildComponentDefinition(reqCtx.Ctx, cli, clusterDef, clusterVer, cluster, clusterCompSpec) + compDef, err := getOrBuildComponentDefinition(reqCtx.Ctx, cli, clusterDef, cluster, clusterCompSpec) if err != nil { return nil, nil, err } @@ -85,18 +85,17 @@ func BuildSynthesizedComponentWrapper(reqCtx intctrlutil.RequestCtx, cli client.Reader, cluster *appsv1alpha1.Cluster, clusterCompSpec *appsv1alpha1.ClusterComponentSpec) (*SynthesizedComponent, error) { - clusterDef, clusterVer, err := getClusterReferencedResources(reqCtx.Ctx, cli, cluster) + clusterDef, err := getClusterReferencedResources(reqCtx.Ctx, cli, cluster) if err != nil { return nil, err } - return BuildSynthesizedComponentWrapper4Test(reqCtx, cli, clusterDef, clusterVer, cluster, clusterCompSpec) + return BuildSynthesizedComponentWrapper4Test(reqCtx, cli, clusterDef, cluster, clusterCompSpec) } // BuildSynthesizedComponentWrapper4Test builds a new SynthesizedComponent object with a given ClusterComponentSpec. func BuildSynthesizedComponentWrapper4Test(reqCtx intctrlutil.RequestCtx, cli client.Reader, clusterDef *appsv1alpha1.ClusterDefinition, - clusterVer *appsv1alpha1.ClusterVersion, cluster *appsv1alpha1.Cluster, clusterCompSpec *appsv1alpha1.ClusterComponentSpec) (*SynthesizedComponent, error) { if clusterCompSpec == nil { @@ -105,7 +104,7 @@ func BuildSynthesizedComponentWrapper4Test(reqCtx intctrlutil.RequestCtx, if clusterCompSpec == nil { return nil, nil } - compDef, err := getOrBuildComponentDefinition(reqCtx.Ctx, cli, clusterDef, clusterVer, cluster, clusterCompSpec) + compDef, err := getOrBuildComponentDefinition(reqCtx.Ctx, cli, clusterDef, cluster, clusterCompSpec) if err != nil { return nil, err } @@ -117,7 +116,7 @@ func BuildSynthesizedComponentWrapper4Test(reqCtx intctrlutil.RequestCtx, } // buildSynthesizedComponent builds a new SynthesizedComponent object, which is a mixture of component-related configs from ComponentDefinition and Component. -// !!! Do not use @clusterDef, @clusterVer, @cluster and @clusterCompSpec since they are used for the backward compatibility only. +// !!! 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, @@ -185,8 +184,8 @@ func buildSynthesizedComponent(reqCtx intctrlutil.RequestCtx, EnabledLogs: comp.Spec.EnabledLogs, } - // build backward compatible fields, including workload, services, componentRefEnvs, clusterDefName, clusterCompDefName, and clusterCompVer, etc. - // if cluster referenced a clusterDefinition and clusterVersion, for backward compatibility, we need to merge the clusterDefinition and clusterVersion into the component + // build backward compatible fields, including workload, services, componentRefEnvs, clusterDefName, clusterCompDefName, etc. + // if cluster referenced a clusterDefinition, for backward compatibility, we need to merge the clusterDefinition into the component // TODO(xingran): it will be removed in the future if clusterDef != nil && cluster != nil && clusterCompSpec != nil { if err = buildBackwardCompatibleFields(reqCtx, clusterDef, cluster, clusterCompSpec, synthesizeComp); err != nil { @@ -690,79 +689,6 @@ func buildCompatibleHorizontalScalePolicy(compDef *appsv1alpha1.ComponentDefinit } } -// appendOrOverrideContainerAttr appends targetContainer to compContainers or overrides the attributes of compContainers with a given targetContainer, -// if targetContainer does not exist in compContainers, it will be appended. otherwise it will be updated with the attributes of the target container. -func appendOrOverrideContainerAttr(compContainers []corev1.Container, targetContainer corev1.Container) []corev1.Container { - index, compContainer := intctrlutil.GetContainerByName(compContainers, targetContainer.Name) - if compContainer == nil { - compContainers = append(compContainers, targetContainer) - } else { - doContainerAttrOverride(&compContainers[index], targetContainer) - } - return compContainers -} - -// doContainerAttrOverride overrides the attributes in compContainer with the attributes in container. -func doContainerAttrOverride(compContainer *corev1.Container, container corev1.Container) { - if compContainer == nil { - return - } - if container.Image != "" { - compContainer.Image = container.Image - } - if len(container.Command) != 0 { - compContainer.Command = container.Command - } - if len(container.Args) != 0 { - compContainer.Args = container.Args - } - if container.WorkingDir != "" { - compContainer.WorkingDir = container.WorkingDir - } - if len(container.Ports) != 0 { - compContainer.Ports = container.Ports - } - if len(container.EnvFrom) != 0 { - compContainer.EnvFrom = container.EnvFrom - } - if len(container.Env) != 0 { - compContainer.Env = container.Env - } - if container.Resources.Limits != nil || container.Resources.Requests != nil { - compContainer.Resources = container.Resources - } - if len(container.VolumeMounts) != 0 { - compContainer.VolumeMounts = container.VolumeMounts - } - if len(container.VolumeDevices) != 0 { - compContainer.VolumeDevices = container.VolumeDevices - } - if container.LivenessProbe != nil { - compContainer.LivenessProbe = container.LivenessProbe - } - if container.ReadinessProbe != nil { - compContainer.ReadinessProbe = container.ReadinessProbe - } - if container.StartupProbe != nil { - compContainer.StartupProbe = container.StartupProbe - } - if container.Lifecycle != nil { - compContainer.Lifecycle = container.Lifecycle - } - if container.TerminationMessagePath != "" { - compContainer.TerminationMessagePath = container.TerminationMessagePath - } - if container.TerminationMessagePolicy != "" { - compContainer.TerminationMessagePolicy = container.TerminationMessagePolicy - } - if container.ImagePullPolicy != "" { - compContainer.ImagePullPolicy = container.ImagePullPolicy - } - if container.SecurityContext != nil { - compContainer.SecurityContext = container.SecurityContext - } -} - // GetEnvReplacementMapForConnCredential gets the replacement map for connect credential // TODO: deprecated, will be removed later. func GetEnvReplacementMapForConnCredential(clusterName string) map[string]string { @@ -822,30 +748,6 @@ func ReplaceSecretEnvVars(namedValuesMap map[string]string, envs []corev1.EnvVar return newEnvs } -// overrideSwitchoverSpecAttr overrides the attributes in switchoverSpec with the attributes of SwitchoverShortSpec in clusterVersion. -func overrideSwitchoverSpecAttr(switchoverSpec *appsv1alpha1.SwitchoverSpec, cvSwitchoverSpec *appsv1alpha1.SwitchoverShortSpec) { - if switchoverSpec == nil || cvSwitchoverSpec == nil || cvSwitchoverSpec.CmdExecutorConfig == nil { - return - } - applyCmdExecutorConfig := func(cmdExecutorConfig *appsv1alpha1.CmdExecutorConfig) { - if cmdExecutorConfig == nil { - return - } - if len(cvSwitchoverSpec.CmdExecutorConfig.Image) > 0 { - cmdExecutorConfig.Image = cvSwitchoverSpec.CmdExecutorConfig.Image - } - if len(cvSwitchoverSpec.CmdExecutorConfig.Env) > 0 { - cmdExecutorConfig.Env = cvSwitchoverSpec.CmdExecutorConfig.Env - } - } - if switchoverSpec.WithCandidate != nil { - applyCmdExecutorConfig(switchoverSpec.WithCandidate.CmdExecutorConfig) - } - if switchoverSpec.WithoutCandidate != nil { - applyCmdExecutorConfig(switchoverSpec.WithoutCandidate.CmdExecutorConfig) - } -} - func GetConfigSpecByName(synthesizedComp *SynthesizedComponent, configSpec string) *appsv1alpha1.ComponentConfigSpec { for i := range synthesizedComp.ConfigTemplates { template := &synthesizedComp.ConfigTemplates[i] diff --git a/pkg/controller/configuration/configuration_test.go b/pkg/controller/configuration/configuration_test.go index 92626977008a..eb1033ca338f 100644 --- a/pkg/controller/configuration/configuration_test.go +++ b/pkg/controller/configuration/configuration_test.go @@ -33,7 +33,6 @@ import ( ) const clusterDefName = "test-clusterdef" -const clusterVersionName = "test-clusterversion" const clusterName = "test-cluster" const mysqlCompDefName = "replicasets" const scriptConfigName = "test-script-config" @@ -56,32 +55,13 @@ func allFieldsClusterDefObj(needCreate bool) *appsv1alpha1.ClusterDefinition { return clusterDefObj } -func allFieldsClusterVersionObj(needCreate bool) *appsv1alpha1.ClusterVersion { - clusterVersionObj := testapps.NewClusterVersionFactory(clusterVersionName, clusterDefName). - AddComponentVersion(mysqlCompDefName). - AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - GetObject() - if needCreate { - Expect(testCtx.CreateObj(testCtx.Ctx, clusterVersionObj)).Should(Succeed()) - } - return clusterVersionObj -} - -func newAllFieldsClusterObj( - clusterDefObj *appsv1alpha1.ClusterDefinition, - clusterVersionObj *appsv1alpha1.ClusterVersion, - needCreate bool, -) (*appsv1alpha1.Cluster, *appsv1alpha1.ClusterDefinition, *appsv1alpha1.ClusterVersion, types.NamespacedName) { - // setup Cluster obj requires default ClusterDefinition and ClusterVersion objects +func newAllFieldsClusterObj(clusterDefObj *appsv1alpha1.ClusterDefinition, needCreate bool) (*appsv1alpha1.Cluster, *appsv1alpha1.ClusterDefinition, types.NamespacedName) { + // setup Cluster obj requires default ClusterDefinition object if clusterDefObj == nil { clusterDefObj = allFieldsClusterDefObj(needCreate) } - if clusterVersionObj == nil { - clusterVersionObj = allFieldsClusterVersionObj(needCreate) - } pvcSpec := testapps.NewPVCSpec("1Gi") - clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDefObj.Name, clusterVersionObj.Name). + clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). AddComponent(mysqlCompName, mysqlCompDefName).SetReplicas(1). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). AddComponentService(testapps.ServiceVPCName, corev1.ServiceTypeLoadBalancer). @@ -91,16 +71,15 @@ func newAllFieldsClusterObj( if needCreate { Expect(testCtx.CreateObj(testCtx.Ctx, clusterObj)).Should(Succeed()) } - return clusterObj, clusterDefObj, clusterVersionObj, key + return clusterObj, clusterDefObj, key } -func newAllFieldsSynthesizedComponent(clusterDef *appsv1alpha1.ClusterDefinition, - clusterVer *appsv1alpha1.ClusterVersion, cluster *appsv1alpha1.Cluster) *component.SynthesizedComponent { +func newAllFieldsSynthesizedComponent(clusterDef *appsv1alpha1.ClusterDefinition, cluster *appsv1alpha1.Cluster) *component.SynthesizedComponent { reqCtx := intctrlutil.RequestCtx{ Ctx: testCtx.Ctx, Log: logger, } - synthesizeComp, err := component.BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, clusterVer, cluster, &cluster.Spec.ComponentSpecs[0]) + synthesizeComp, err := component.BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, cluster, &cluster.Spec.ComponentSpecs[0]) 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 1c0d2841cdd1..ef2a4b17ea88 100644 --- a/pkg/controller/configuration/envfrom_utils_test.go +++ b/pkg/controller/configuration/envfrom_utils_test.go @@ -38,17 +38,15 @@ import ( var _ = Describe("ConfigEnvFrom test", func() { const ( - clusterDefName = "test-clusterdef" - clusterVersionName = "test-clusterversion" - clusterName = "test-cluster" + clusterDefName = "test-clusterdef" + clusterName = "test-cluster" mysqlCompDefName = "replicasets" mysqlCompName = "mysql" ) var ( - clusterDef *appsv1alpha1.ClusterDefinition - clusterVersion *appsv1alpha1.ClusterVersion - cluster *appsv1alpha1.Cluster + clusterDef *appsv1alpha1.ClusterDefinition + cluster *appsv1alpha1.Cluster k8sMockClient *testutil.K8sClientMockHelper origCMObject *corev1.ConfigMap @@ -68,13 +66,8 @@ var _ = Describe("ConfigEnvFrom test", func() { AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). AddConfigTemplate(cm.Name, cm.Name, configConstraint.Name, testCtx.DefaultNamespace, "mysql-config", testapps.DefaultMySQLContainerName). GetObject() - clusterVersion = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefName). - AddComponentVersion(mysqlCompDefName). - AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - GetObject() pvcSpec := testapps.NewPVCSpec("1Gi") - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDef.Name, clusterVersion.Name). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). AddComponent(mysqlCompName, mysqlCompDefName). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). GetObject() @@ -93,7 +86,7 @@ var _ = Describe("ConfigEnvFrom test", func() { Ctx: ctx, Log: logger, } - synthesizeComp, err := component.BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, clusterVersion, cluster, &cluster.Spec.ComponentSpecs[0]) + synthesizeComp, err := component.BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, cluster, &cluster.Spec.ComponentSpecs[0]) Expect(err).Should(Succeed()) podSpec := &corev1.PodSpec{ diff --git a/pkg/controller/configuration/operator.go b/pkg/controller/configuration/operator.go index 1e83824f45eb..1cbffd7bf9c0 100644 --- a/pkg/controller/configuration/operator.go +++ b/pkg/controller/configuration/operator.go @@ -53,8 +53,6 @@ func NewConfigReconcileTask(resourceCtx *ResourceCtx, func (c *configOperator) Reconcile() error { var synthesizedComponent = c.SynthesizedComponent - // Need to Merge configTemplateRef of ClusterVersion.Components[*].ConfigTemplateRefs and - // ClusterDefinition.Components[*].ConfigTemplateRefs if len(synthesizedComponent.ConfigTemplates) == 0 && len(synthesizedComponent.ScriptTemplates) == 0 { return c.UpdateConfiguration() } diff --git a/pkg/controller/configuration/operator_test.go b/pkg/controller/configuration/operator_test.go index 37dd8a8db83c..82747e53d8ed 100644 --- a/pkg/controller/configuration/operator_test.go +++ b/pkg/controller/configuration/operator_test.go @@ -39,9 +39,7 @@ import ( ) var _ = Describe("ConfigurationOperatorTest", func() { - var clusterObj *appsv1alpha1.Cluster - var clusterVersionObj *appsv1alpha1.ClusterVersion var clusterDefObj *appsv1alpha1.ClusterDefinition var componentObj *appsv1alpha1.Component var synthesizedComponent *component.SynthesizedComponent @@ -70,8 +68,8 @@ var _ = Describe("ConfigurationOperatorTest", func() { BeforeEach(func() { // Add any setup steps that needs to be executed before each test k8sMockClient = testutil.NewK8sMockClient() - clusterObj, clusterDefObj, clusterVersionObj, _ = newAllFieldsClusterObj(nil, nil, false) - synthesizedComponent = newAllFieldsSynthesizedComponent(clusterDefObj, clusterVersionObj, clusterObj) + clusterObj, clusterDefObj, _ = newAllFieldsClusterObj(nil, false) + synthesizedComponent = newAllFieldsSynthesizedComponent(clusterDefObj, clusterObj) componentObj = newAllFieldsComponent(clusterObj) configMapObj = testapps.NewConfigMap("default", mysqlConfigName, testapps.SetConfigMapData("test", "test")) @@ -114,7 +112,6 @@ var _ = Describe("ConfigurationOperatorTest", func() { k8sMockClient.MockGetMethod(testutil.WithGetReturned(testutil.WithConstructSimpleGetResult( []client.Object{ clusterDefObj, - clusterVersionObj, clusterObj, clusterObj, scriptsObj, @@ -151,7 +148,6 @@ var _ = Describe("ConfigurationOperatorTest", func() { k8sMockClient.MockGetMethod(testutil.WithGetReturned(testutil.WithConstructSimpleGetResult( []client.Object{ clusterDefObj, - clusterVersionObj, clusterObj, clusterObj, }, diff --git a/pkg/controller/configuration/pipeline_test.go b/pkg/controller/configuration/pipeline_test.go index b75a831d30a5..341468f51e07 100644 --- a/pkg/controller/configuration/pipeline_test.go +++ b/pkg/controller/configuration/pipeline_test.go @@ -42,12 +42,10 @@ import ( ) var _ = Describe("ConfigurationPipelineTest", func() { - const testConfigFile = "postgresql.conf" var clusterObj *appsv1alpha1.Cluster var componentObj *appsv1alpha1.Component - var clusterVersionObj *appsv1alpha1.ClusterVersion var clusterDefObj *appsv1alpha1.ClusterDefinition var synthesizedComponent *component.SynthesizedComponent var configMapObj *corev1.ConfigMap @@ -59,7 +57,6 @@ var _ = Describe("ConfigurationPipelineTest", func() { k8sMockClient.MockGetMethod(testutil.WithGetReturned(testutil.WithConstructSimpleGetResult( []client.Object{ clusterDefObj, - clusterVersionObj, clusterObj, clusterObj, configMapObj, @@ -94,9 +91,9 @@ var _ = Describe("ConfigurationPipelineTest", func() { BeforeEach(func() { // Add any setup steps that needs to be executed before each test k8sMockClient = testutil.NewK8sMockClient() - clusterObj, clusterDefObj, clusterVersionObj, _ = newAllFieldsClusterObj(nil, nil, false) + clusterObj, clusterDefObj, _ = newAllFieldsClusterObj(nil, false) componentObj = newAllFieldsComponent(clusterObj) - synthesizedComponent = newAllFieldsSynthesizedComponent(clusterDefObj, clusterVersionObj, clusterObj) + synthesizedComponent = newAllFieldsSynthesizedComponent(clusterDefObj, clusterObj) configMapObj = testapps.NewConfigMap("default", mysqlConfigName, testapps.SetConfigMapData(testConfigFile, ` bgwriter_delay = '200ms' diff --git a/pkg/controller/configuration/resource_wrapper.go b/pkg/controller/configuration/resource_wrapper.go index 926bb4f3a4d6..0dd0f4bd944f 100644 --- a/pkg/controller/configuration/resource_wrapper.go +++ b/pkg/controller/configuration/resource_wrapper.go @@ -57,8 +57,6 @@ type ResourceFetcher[T any] struct { // Deprecated: this API will be removed from version 0.9.0 ClusterDefObj *appsv1alpha1.ClusterDefinition - // Deprecated: use ComponentDefinition instead - ClusterVerObj *appsv1alpha1.ClusterVersion ConfigMapObj *corev1.ConfigMap ConfigurationObj *appsv1alpha1.Configuration @@ -136,22 +134,6 @@ func (r *ResourceFetcher[T]) ClusterDef() *T { }) } -// ClusterVer get clusterVersion cr -// Deprecated: this API will be removed from version 0.9.0 -func (r *ResourceFetcher[T]) ClusterVer() *T { - clusterVerKey := client.ObjectKey{ - Namespace: "", - Name: r.ClusterObj.Spec.ClusterVersionRef, - } - return r.Wrap(func() error { - if clusterVerKey.Name == "" { - return nil - } - r.ClusterVerObj = &appsv1alpha1.ClusterVersion{} - return r.Client.Get(r.Context, clusterVerKey, r.ClusterVerObj) - }) -} - 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) diff --git a/pkg/controller/configuration/resource_wrapper_test.go b/pkg/controller/configuration/resource_wrapper_test.go index 509e0875b63a..2a88bf3d620e 100644 --- a/pkg/controller/configuration/resource_wrapper_test.go +++ b/pkg/controller/configuration/resource_wrapper_test.go @@ -37,9 +37,8 @@ import ( var _ = Describe("resource Fetcher", func() { const ( - clusterDefName = "test-clusterdef" - clusterVersionName = "test-clusterversion" - clusterName = "test-cluster" + clusterDefName = "test-clusterdef" + clusterName = "test-cluster" mysqlCompDefName = "replicasets" mysqlCompName = "mysql" @@ -48,10 +47,9 @@ var _ = Describe("resource Fetcher", func() { ) var ( - k8sMockClient *testutil.K8sClientMockHelper - clusterDef *appsv1alpha1.ClusterDefinition - clusterVersion *appsv1alpha1.ClusterVersion - cluster *appsv1alpha1.Cluster + k8sMockClient *testutil.K8sClientMockHelper + clusterDef *appsv1alpha1.ClusterDefinition + cluster *appsv1alpha1.Cluster ) BeforeEach(func() { @@ -60,13 +58,8 @@ var _ = Describe("resource Fetcher", func() { AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). AddConfigTemplate(mysqlConfigName, mysqlConfigName, mysqlConfigName, "default", mysqlVolumeName). GetObject() - clusterVersion = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefName). - AddComponentVersion(mysqlCompDefName). - AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - GetObject() pvcSpec := testapps.NewPVCSpec("1Gi") - cluster = testapps.NewClusterFactory("default", clusterName, - clusterDef.Name, clusterVersion.Name). + cluster = testapps.NewClusterFactory("default", clusterName, clusterDef.Name). AddComponent(mysqlCompName, mysqlCompDefName). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). GetObject() @@ -81,7 +74,6 @@ var _ = Describe("resource Fetcher", func() { k8sMockClient.MockGetMethod(testutil.WithGetReturned(testutil.WithConstructSimpleGetResult( []client.Object{ clusterDef, - clusterVersion, cluster, testapps.NewConfigMap("default", cfgcore.GetComponentCfgName(clusterName, mysqlCompName, mysqlConfigName)), &appsv1beta1.ConfigConstraint{ @@ -94,7 +86,6 @@ var _ = Describe("resource Fetcher", func() { err := NewTest(k8sMockClient.Client(), ctx). Cluster(). ClusterDef(). - ClusterVer(). ComponentSpec(). ConfigMap(mysqlConfigName). ConfigConstraints(mysqlConfigName). diff --git a/pkg/controller/configuration/template_wrapper_test.go b/pkg/controller/configuration/template_wrapper_test.go index d74a76c20b4a..0bf686a143c6 100644 --- a/pkg/controller/configuration/template_wrapper_test.go +++ b/pkg/controller/configuration/template_wrapper_test.go @@ -36,11 +36,9 @@ import ( ) var _ = Describe("TemplateWrapperTest", func() { - var mockK8sCli *testutil.K8sClientMockHelper var clusterObj *appsv1alpha1.Cluster var componentObj *appsv1alpha1.Component - var clusterVersionObj *appsv1alpha1.ClusterVersion var clusterDefObj *appsv1alpha1.ClusterDefinition var clusterComponent *component.SynthesizedComponent @@ -54,8 +52,8 @@ var _ = Describe("TemplateWrapperTest", func() { // Add any setup steps that needs to be executed before each test mockK8sCli = testutil.NewK8sMockClient() - clusterObj, clusterDefObj, clusterVersionObj, _ = newAllFieldsClusterObj(nil, nil, false) - clusterComponent = newAllFieldsSynthesizedComponent(clusterDefObj, clusterVersionObj, clusterObj) + clusterObj, clusterDefObj, _ = newAllFieldsClusterObj(nil, false) + clusterComponent = newAllFieldsSynthesizedComponent(clusterDefObj, clusterObj) componentObj = newAllFieldsComponent(clusterObj) }) diff --git a/pkg/controller/configuration/tool_image_builder_test.go b/pkg/controller/configuration/tool_image_builder_test.go index d2c45316c363..1f9f54478db6 100644 --- a/pkg/controller/configuration/tool_image_builder_test.go +++ b/pkg/controller/configuration/tool_image_builder_test.go @@ -35,19 +35,17 @@ import ( ) var _ = Describe("ToolsImageBuilderTest", func() { - const kbToolsImage = "apecloud/kubeblocks-tools:latest" var noneCommand = []string{"/bin/true"} var clusterObj *appsv1alpha1.Cluster - var clusterVersionObj *appsv1alpha1.ClusterVersion var ClusterDefObj *appsv1alpha1.ClusterDefinition var clusterComponent *component.SynthesizedComponent BeforeEach(func() { // Add any setup steps that needs to be executed before each test - clusterObj, ClusterDefObj, clusterVersionObj, _ = newAllFieldsClusterObj(nil, nil, false) - clusterComponent = newAllFieldsSynthesizedComponent(ClusterDefObj, clusterVersionObj, clusterObj) + clusterObj, ClusterDefObj, _ = newAllFieldsClusterObj(nil, false) + clusterComponent = newAllFieldsSynthesizedComponent(ClusterDefObj, clusterObj) viper.SetDefault(constant.KBToolsImage, kbToolsImage) }) diff --git a/pkg/controller/factory/builder_test.go b/pkg/controller/factory/builder_test.go index e051b0059a3b..7d80a2a6ce96 100644 --- a/pkg/controller/factory/builder_test.go +++ b/pkg/controller/factory/builder_test.go @@ -45,7 +45,6 @@ import ( var _ = Describe("builder", func() { const clusterDefName = "test-clusterdef" - const clusterVersionName = "test-clusterversion" const clusterName = "test-cluster" const mysqlCompDefName = "replicasets" const proxyCompDefName = "proxy" @@ -64,21 +63,6 @@ var _ = Describe("builder", func() { return clusterDefObj } - allFieldsClusterVersionObj := func(needCreate bool) *appsv1alpha1.ClusterVersion { - By("By assure an clusterVersion obj") - clusterVersionObj := testapps.NewClusterVersionFactory(clusterVersionName, clusterDefName). - AddComponentVersion(mysqlCompDefName). - AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - AddComponentVersion(proxyCompDefName). - AddInitContainerShort("nginx-init", testapps.NginxImage). - AddContainerShort("nginx", testapps.NginxImage). - GetObject() - if needCreate { - Expect(testCtx.CreateObj(testCtx.Ctx, clusterVersionObj)).Should(Succeed()) - } - return clusterVersionObj - } - newExtraEnvs := func() map[string]string { jsonStr, _ := json.Marshal(map[string]string{ "mock-key": "mock-value", @@ -88,21 +72,13 @@ var _ = Describe("builder", func() { } } - newAllFieldsClusterObj := func( - clusterDefObj *appsv1alpha1.ClusterDefinition, - clusterVersionObj *appsv1alpha1.ClusterVersion, - needCreate bool, - ) (*appsv1alpha1.Cluster, *appsv1alpha1.ClusterDefinition, *appsv1alpha1.ClusterVersion, types.NamespacedName) { - // setup Cluster obj requires default ClusterDefinition and ClusterVersion objects + newAllFieldsClusterObj := func(clusterDefObj *appsv1alpha1.ClusterDefinition, needCreate bool) (*appsv1alpha1.Cluster, *appsv1alpha1.ClusterDefinition, types.NamespacedName) { + // setup Cluster obj requires default ClusterDefinition object if clusterDefObj == nil { clusterDefObj = allFieldsClusterDefObj(needCreate) } - if clusterVersionObj == nil { - clusterVersionObj = allFieldsClusterVersionObj(needCreate) - } pvcSpec := testapps.NewPVCSpec("1Gi") - clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDefObj.Name, clusterVersionObj.Name). + clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). AddAnnotationsInMap(newExtraEnvs()). AddComponent(mysqlCompName, mysqlCompDefName).SetReplicas(1). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). @@ -113,7 +89,7 @@ var _ = Describe("builder", func() { if needCreate { Expect(testCtx.CreateObj(testCtx.Ctx, clusterObj)).Should(Succeed()) } - return clusterObj, clusterDefObj, clusterVersionObj, key + return clusterObj, clusterDefObj, key } newItsObj := func() *workloads.InstanceSet { @@ -142,12 +118,11 @@ var _ = Describe("builder", func() { } return reqCtx } - newAllFieldsSynthesizedComponent := func(clusterDef *appsv1alpha1.ClusterDefinition, - clusterVer *appsv1alpha1.ClusterVersion, cluster *appsv1alpha1.Cluster) *component.SynthesizedComponent { + newAllFieldsSynthesizedComponent := func(clusterDef *appsv1alpha1.ClusterDefinition, cluster *appsv1alpha1.Cluster) *component.SynthesizedComponent { reqCtx := newReqCtx() By("assign every available fields") synthesizeComp, err := component.BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, - clusterDef, clusterVer, cluster, &cluster.Spec.ComponentSpecs[0]) + clusterDef, cluster, &cluster.Spec.ComponentSpecs[0]) Expect(err).Should(Succeed()) Expect(synthesizeComp).ShouldNot(BeNil()) // to resolve and inject env vars @@ -158,8 +133,8 @@ var _ = Describe("builder", func() { return synthesizeComp } newClusterObjs := func(clusterDefObj *appsv1alpha1.ClusterDefinition) (*appsv1alpha1.ClusterDefinition, *appsv1alpha1.Cluster, *component.SynthesizedComponent) { - cluster, clusterDef, clusterVersion, _ := newAllFieldsClusterObj(clusterDefObj, nil, false) - synthesizedComponent := newAllFieldsSynthesizedComponent(clusterDef, clusterVersion, cluster) + cluster, clusterDef, _ := newAllFieldsClusterObj(clusterDefObj, false) + synthesizedComponent := newAllFieldsSynthesizedComponent(clusterDef, cluster) return clusterDef, cluster, synthesizedComponent } @@ -272,7 +247,7 @@ var _ = Describe("builder", func() { }, } cluster.Spec.ComponentSpecs[0].Replicas = 2 - replComponent := newAllFieldsSynthesizedComponent(clusterDef, nil, cluster) + replComponent := newAllFieldsSynthesizedComponent(clusterDef, cluster) its, err = BuildInstanceSet(replComponent, nil) Expect(err).Should(BeNil()) Expect(its).ShouldNot(BeNil()) @@ -311,7 +286,7 @@ var _ = Describe("builder", func() { clusterDef.Spec.ComponentDefs[0].ConsensusSpec = appsv1alpha1.NewConsensusSetSpec() clusterDef.Spec.ComponentDefs[0].ConsensusSpec.UpdateStrategy = appsv1alpha1.BestEffortParallelStrategy cluster.Spec.ComponentSpecs[0].Replicas = 3 - csComponent := newAllFieldsSynthesizedComponent(clusterDef, nil, cluster) + csComponent := newAllFieldsSynthesizedComponent(clusterDef, cluster) its, err = BuildInstanceSet(csComponent, nil) Expect(err).Should(BeNil()) Expect(its).ShouldNot(BeNil()) diff --git a/pkg/controller/job/job_utils_test.go b/pkg/controller/job/job_utils_test.go index e9d5dd7aafff..4d7e71f00257 100644 --- a/pkg/controller/job/job_utils_test.go +++ b/pkg/controller/job/job_utils_test.go @@ -37,18 +37,16 @@ var _ = Describe("Job Utils Test", func() { Context("Job Utils Test function", func() { const ( - clusterDefName = "test-clusterdef" - clusterVersionName = "test-clusterversion" - clusterName = "test-cluster" - mysqlCompDefName = "replicasets" - mysqlCompName = "mysql" - labelKey = "test-label" + clusterDefName = "test-clusterdef" + clusterName = "test-cluster" + mysqlCompDefName = "replicasets" + mysqlCompName = "mysql" + labelKey = "test-label" ) var ( - clusterDef *appsv1alpha1.ClusterDefinition - clusterVersion *appsv1alpha1.ClusterVersion - cluster *appsv1alpha1.Cluster + clusterDef *appsv1alpha1.ClusterDefinition + cluster *appsv1alpha1.Cluster ) createJob := func(name string, keys ...string) *batchv1.Job { @@ -82,12 +80,7 @@ var _ = Describe("Job Utils Test", func() { clusterDef = testapps.NewClusterDefFactory(clusterDefName). AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). GetObject() - clusterVersion = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefName). - AddComponentVersion(mysqlCompDefName). - AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - GetObject() - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDef.Name, clusterVersion.Name). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). AddComponent(mysqlCompName, mysqlCompDefName). GetObject() }) diff --git a/pkg/controller/plan/prepare_test.go b/pkg/controller/plan/prepare_test.go index ea18b9605b2a..19e7e59a17e2 100644 --- a/pkg/controller/plan/prepare_test.go +++ b/pkg/controller/plan/prepare_test.go @@ -64,38 +64,28 @@ var _ = Describe("Prepare Test", func() { }) const ( - clusterDefName = "test-clusterdef" - clusterVersionName = "test-clusterversion" - clusterName = "test-cluster" + clusterDefName = "test-clusterdef" + clusterName = "test-cluster" mysqlClusterCompDefName = "mysql-cluster-comp-def" mysqlCompDefName = "mysql-comp-def" mysqlCompName = "mysql" ) var ( - clusterDefObj *appsv1alpha1.ClusterDefinition - clusterVersionObj *appsv1alpha1.ClusterVersion - compDefObj *appsv1alpha1.ComponentDefinition - cluster *appsv1alpha1.Cluster - comp *appsv1alpha1.Component - configSpecName string + clusterDefObj *appsv1alpha1.ClusterDefinition + compDefObj *appsv1alpha1.ComponentDefinition + cluster *appsv1alpha1.Cluster + comp *appsv1alpha1.Component + configSpecName string ) Context("create cluster with component and component definition API, testing render configuration", func() { - createAllWorkloadTypesClusterDef := func(noCreateAssociateCV ...bool) { + createAllWorkloadTypesClusterDef := func() { By("Create a clusterDefinition obj") clusterDefObj = testapps.NewClusterDefFactory(clusterDefName). AddComponentDef(testapps.ConsensusMySQLComponent, mysqlClusterCompDefName). Create(&testCtx).GetObject() - if len(noCreateAssociateCV) > 0 && noCreateAssociateCV[0] { - return - } - By("Create a clusterVersion obj") - clusterVersionObj = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefObj.GetName()). - AddComponentVersion(mysqlClusterCompDefName).AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - Create(&testCtx).GetObject() - By("Create a componentDefinition obj") compDefObj = testapps.NewComponentDefinitionFactory(mysqlCompDefName). WithRandomName(). @@ -115,7 +105,7 @@ var _ = Describe("Prepare Test", func() { configSpecName = tpl.Name pvcSpec := testapps.NewPVCSpec("1Gi") - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name, clusterVersionObj.Name). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). AddComponentV2(mysqlCompName, compDefObj.Name). SetReplicas(1). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). diff --git a/pkg/controller/plan/restore_test.go b/pkg/controller/plan/restore_test.go index 32753c696aab..0feb996628ae 100644 --- a/pkg/controller/plan/restore_test.go +++ b/pkg/controller/plan/restore_test.go @@ -61,7 +61,7 @@ var _ = Describe("Restore", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResources(&testCtx) inNS := client.InNamespace(testCtx.DefaultNamespace) ml := client.HasLabels{testCtx.TestObjLabelKey} @@ -91,19 +91,17 @@ var _ = Describe("Restore", func() { Context("Cluster Restore", func() { const ( - clusterDefName = "test-clusterdef" - clusterVersionName = "test-clusterversion" - mysqlCompType = "replicasets" - mysqlCompName = "mysql" - nginxCompType = "proxy" - topologyKey = "testTopologyKey" - labelKey = "testNodeLabelKey" - labelValue = "testLabelValue" + clusterDefName = "test-clusterdef" + mysqlCompType = "replicasets" + mysqlCompName = "mysql" + nginxCompType = "proxy" + topologyKey = "testTopologyKey" + labelKey = "testNodeLabelKey" + labelValue = "testLabelValue" ) var ( clusterDef *appsv1alpha1.ClusterDefinition - clusterVersion *appsv1alpha1.ClusterVersion cluster *appsv1alpha1.Cluster synthesizedComponent *component.SynthesizedComponent compObj *appsv1alpha1.Component @@ -118,16 +116,8 @@ var _ = Describe("Restore", func() { AddComponentDef(testapps.ConsensusMySQLComponent, mysqlCompType). AddComponentDef(testapps.StatelessNginxComponent, nginxCompType). Create(&testCtx).GetObject() - clusterVersion = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefName). - AddComponentVersion(mysqlCompType). - AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - AddComponentVersion(nginxCompType). - AddInitContainerShort("nginx-init", testapps.NginxImage). - AddContainerShort("nginx", testapps.NginxImage). - Create(&testCtx).GetObject() pvcSpec := testapps.NewPVCSpec("1Gi") - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDef.Name, clusterVersion.Name). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). AddComponent(mysqlCompName, mysqlCompType). SetReplicas(3). SetClusterAffinity(&appsv1alpha1.Affinity{ diff --git a/pkg/controller/scheduling/scheduling_utils_test.go b/pkg/controller/scheduling/scheduling_utils_test.go index 29474ae841e1..effe72347e14 100644 --- a/pkg/controller/scheduling/scheduling_utils_test.go +++ b/pkg/controller/scheduling/scheduling_utils_test.go @@ -62,13 +62,12 @@ var _ = Describe("affinity utils", func() { Effect: corev1.TaintEffectNoExecute, } - clusterObj = testapps.NewClusterFactory("default", clusterName, "", ""). + clusterObj = testapps.NewClusterFactory("default", clusterName, ""). AddComponent(compName, ""). SetClusterAffinity(affinity). AddClusterToleration(toleration). GetObject() compSpec = &clusterObj.Spec.ComponentSpecs[0] - } ) diff --git a/pkg/controllerutil/cluster_utils_test.go b/pkg/controllerutil/cluster_utils_test.go index 2d96fc0bb0f3..e900cbdd1ab6 100644 --- a/pkg/controllerutil/cluster_utils_test.go +++ b/pkg/controllerutil/cluster_utils_test.go @@ -41,7 +41,7 @@ var _ = Describe("cluster utils test", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest mocked objects @@ -56,7 +56,6 @@ var _ = Describe("cluster utils test", func() { Context("cluster utils test", func() { const ( clusterDefName = "test-clusterdef" - clusterVersionName = "test-clusterversion" clusterName = "test-cls" mysqlCompDefName = "replicasets" mysqlCompName = "mysql" @@ -65,9 +64,8 @@ var _ = Describe("cluster utils test", func() { ) var ( - clusterDef *appsv1alpha1.ClusterDefinition - clusterVersion *appsv1alpha1.ClusterVersion - cluster *appsv1alpha1.Cluster + clusterDef *appsv1alpha1.ClusterDefinition + cluster *appsv1alpha1.Cluster ) BeforeEach(func() { @@ -76,12 +74,7 @@ var _ = Describe("cluster utils test", func() { clusterDef = testapps.NewClusterDefFactory(clusterDefName). AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). GetObject() - clusterVersion = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefName). - AddComponentVersion(mysqlCompDefName). - AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - GetObject() - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDef.Name, clusterVersion.Name). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). SetUID(clusterName). AddComponent(mysqlCompName, mysqlCompDefName). AddShardingSpecV2(mysqlShardingName, mysqlCompDefName). diff --git a/pkg/controllerutil/sharding_utils_test.go b/pkg/controllerutil/sharding_utils_test.go index 014e990f5b18..d43b8a71f1b0 100644 --- a/pkg/controllerutil/sharding_utils_test.go +++ b/pkg/controllerutil/sharding_utils_test.go @@ -41,7 +41,7 @@ var _ = Describe("cluster shard component", func() { // create the new objects. By("clean resources") - // delete cluster(and all dependent sub-resources), clusterversion and clusterdef + // delete cluster(and all dependent sub-resources), cluster definition testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest mocked objects @@ -56,7 +56,6 @@ var _ = Describe("cluster shard component", func() { Context("cluster shard component", func() { const ( clusterDefName = "test-clusterdef" - clusterVersionName = "test-clusterversion" clusterName = "test-cluster" mysqlCompDefName = "replicasets" mysqlCompName = "mysql" @@ -65,9 +64,8 @@ var _ = Describe("cluster shard component", func() { ) var ( - clusterDef *appsv1alpha1.ClusterDefinition - clusterVersion *appsv1alpha1.ClusterVersion - cluster *appsv1alpha1.Cluster + clusterDef *appsv1alpha1.ClusterDefinition + cluster *appsv1alpha1.Cluster ) BeforeEach(func() { @@ -76,12 +74,7 @@ var _ = Describe("cluster shard component", func() { clusterDef = testapps.NewClusterDefFactory(clusterDefName). AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). GetObject() - clusterVersion = testapps.NewClusterVersionFactory(clusterVersionName, clusterDefName). - AddComponentVersion(mysqlCompDefName). - AddContainerShort("mysql", testapps.ApeCloudMySQLImage). - GetObject() - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, - clusterDef.Name, clusterVersion.Name). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). SetUID(clusterName). AddComponent(mysqlCompName, mysqlCompDefName). AddShardingSpecV2(mysqlShardingName, mysqlCompDefName). diff --git a/pkg/generics/type.go b/pkg/generics/type.go index 1d7797bd12e9..ddc697e53102 100644 --- a/pkg/generics/type.go +++ b/pkg/generics/type.go @@ -88,8 +88,6 @@ var VolumeSnapshotClassSignature = func(_ snapshotv1.VolumeSnapshotClass, _ *sna var ClusterSignature = func(_ appsv1alpha1.Cluster, _ *appsv1alpha1.Cluster, _ appsv1alpha1.ClusterList, _ *appsv1alpha1.ClusterList) { } -var ClusterVersionSignature = func(_ appsv1alpha1.ClusterVersion, _ *appsv1alpha1.ClusterVersion, _ appsv1alpha1.ClusterVersionList, _ *appsv1alpha1.ClusterVersionList) { -} var ClusterDefinitionSignature = func(_ appsv1alpha1.ClusterDefinition, _ *appsv1alpha1.ClusterDefinition, _ appsv1alpha1.ClusterDefinitionList, _ *appsv1alpha1.ClusterDefinitionList) { } var ComponentSignature = func(appsv1alpha1.Component, *appsv1alpha1.Component, appsv1alpha1.ComponentList, *appsv1alpha1.ComponentList) { diff --git a/pkg/testutil/apps/backuppolicytemplate_factory.go b/pkg/testutil/apps/backuppolicytemplate_factory.go index 460088011604..1e6eb97fc06b 100644 --- a/pkg/testutil/apps/backuppolicytemplate_factory.go +++ b/pkg/testutil/apps/backuppolicytemplate_factory.go @@ -90,8 +90,7 @@ func (f *MockBackupPolicyTemplateFactory) AddSchedule(method, schedule, retentio return f } -func (f *MockBackupPolicyTemplateFactory) AddBackupMethod(name string, - snapshotVolumes bool, actionSetName string, mappingEnvWithClusterVersion ...string) *MockBackupPolicyTemplateFactory { +func (f *MockBackupPolicyTemplateFactory) AddBackupMethod(name string, snapshotVolumes bool, actionSetName string) *MockBackupPolicyTemplateFactory { backupPolicy := f.getLastBackupPolicy() backupMethod := appsv1alpha1.BackupMethod{ BackupMethod: dpv1alpha1.BackupMethod{ @@ -100,21 +99,6 @@ func (f *MockBackupPolicyTemplateFactory) AddBackupMethod(name string, ActionSetName: actionSetName, TargetVolumes: &dpv1alpha1.TargetVolumeInfo{}, }} - if len(mappingEnvWithClusterVersion) > 0 { - backupMethod.EnvMapping = []appsv1alpha1.EnvMappingVar{ - { - Key: EnvKeyImageTag, - ValueFrom: appsv1alpha1.ValueFrom{ - ClusterVersionRef: []appsv1alpha1.ValueMapping{ - { - Names: mappingEnvWithClusterVersion, - MappingValue: DefaultImageTag, - }, - }, - }, - }, - } - } backupPolicy.BackupMethods = append(backupPolicy.BackupMethods, backupMethod) return f } diff --git a/pkg/testutil/apps/cluster_factory.go b/pkg/testutil/apps/cluster_factory.go index 16b6306927b4..d1fe15aeaca7 100644 --- a/pkg/testutil/apps/cluster_factory.go +++ b/pkg/testutil/apps/cluster_factory.go @@ -29,13 +29,12 @@ type MockClusterFactory struct { BaseFactory[appsv1alpha1.Cluster, *appsv1alpha1.Cluster, MockClusterFactory] } -func NewClusterFactory(namespace, name, cdRef, cvRef string) *MockClusterFactory { +func NewClusterFactory(namespace, name, cdRef string) *MockClusterFactory { f := &MockClusterFactory{} f.Init(namespace, name, &appsv1alpha1.Cluster{ Spec: appsv1alpha1.ClusterSpec{ ClusterDefRef: cdRef, - ClusterVersionRef: cvRef, ComponentSpecs: []appsv1alpha1.ClusterComponentSpec{}, TerminationPolicy: appsv1alpha1.WipeOut, }, diff --git a/pkg/testutil/apps/cluster_instance_set_test_util.go b/pkg/testutil/apps/cluster_instance_set_test_util.go index 068c54042002..6922c83559e6 100644 --- a/pkg/testutil/apps/cluster_instance_set_test_util.go +++ b/pkg/testutil/apps/cluster_instance_set_test_util.go @@ -45,24 +45,21 @@ const ( ) // InitConsensusMysql initializes a cluster environment which only contains a component of ConsensusSet type for testing, -// includes ClusterDefinition/ClusterVersion/Cluster resources. +// includes ClusterDefinition/Cluster resources. func InitConsensusMysql(testCtx *testutil.TestContext, clusterDefName, - clusterVersionName, clusterName, consensusCompType, - consensusCompName string) (*appsv1alpha1.ClusterDefinition, *appsv1alpha1.ClusterVersion, *appsv1alpha1.Cluster) { + consensusCompName string) (*appsv1alpha1.ClusterDefinition, *appsv1alpha1.Cluster) { clusterDef := CreateConsensusMysqlClusterDef(testCtx, clusterDefName, consensusCompType) - clusterVersion := CreateConsensusMysqlClusterVersion(testCtx, clusterDefName, clusterVersionName, consensusCompType) - cluster := CreateConsensusMysqlCluster(testCtx, clusterDefName, clusterVersionName, clusterName, consensusCompType, consensusCompName) - return clusterDef, clusterVersion, cluster + cluster := CreateConsensusMysqlCluster(testCtx, clusterDefName, clusterName, consensusCompType, consensusCompName) + return clusterDef, cluster } // CreateConsensusMysqlCluster creates a mysql cluster with a component of ConsensusSet type. func CreateConsensusMysqlCluster( testCtx *testutil.TestContext, clusterDefName, - clusterVersionName, clusterName, workloadType, consensusCompName string, pvcSize ...string) *appsv1alpha1.Cluster { @@ -71,7 +68,7 @@ func CreateConsensusMysqlCluster( size = pvcSize[0] } pvcSpec := NewPVCSpec(size) - return NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefName, clusterVersionName). + return NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefName). AddComponent(consensusCompName, workloadType).SetReplicas(ConsensusReplicas).SetEnabledLogs(errorLogName). AddVolumeClaimTemplate("data", pvcSpec).Create(testCtx).GetObject() } @@ -83,12 +80,6 @@ func CreateConsensusMysqlClusterDef(testCtx *testutil.TestContext, clusterDefNam AddLogConfig(errorLogName, filePathPattern).Create(testCtx).GetObject() } -// CreateConsensusMysqlClusterVersion creates a mysql clusterVersion with a component of ConsensusSet type. -func CreateConsensusMysqlClusterVersion(testCtx *testutil.TestContext, clusterDefName, clusterVersionName, workloadType string) *appsv1alpha1.ClusterVersion { - return NewClusterVersionFactory(clusterVersionName, clusterDefName).AddComponentVersion(workloadType).AddContainerShort("mysql", ApeCloudMySQLImage). - Create(testCtx).GetObject() -} - // MockInstanceSetComponent mocks the ITS component, just using in envTest func MockInstanceSetComponent( testCtx *testutil.TestContext, diff --git a/pkg/testutil/apps/cluster_util.go b/pkg/testutil/apps/cluster_util.go index b461c94473e2..14304eb5cdba 100644 --- a/pkg/testutil/apps/cluster_util.go +++ b/pkg/testutil/apps/cluster_util.go @@ -32,34 +32,28 @@ import ( "github.com/apecloud/kubeblocks/pkg/testutil" ) -// InitClusterWithHybridComps initializes a cluster environment for testing, includes ClusterDefinition/ClusterVersion/Cluster resources. +// InitClusterWithHybridComps initializes a cluster environment for testing, includes ClusterDefinition/Cluster resources. func InitClusterWithHybridComps( testCtx *testutil.TestContext, clusterDefName, - clusterVersionName, clusterName, statelessCompDefName, statefulCompDefName, - consensusCompDefName string) (*appsv1alpha1.ClusterDefinition, *appsv1alpha1.ClusterVersion, *appsv1alpha1.Cluster) { + consensusCompDefName string) (*appsv1alpha1.ClusterDefinition, *appsv1alpha1.Cluster) { clusterDef := NewClusterDefFactory(clusterDefName). AddComponentDef(StatelessNginxComponent, statelessCompDefName). AddComponentDef(ConsensusMySQLComponent, consensusCompDefName). AddComponentDef(StatefulMySQLComponent, statefulCompDefName). Create(testCtx).GetObject() - clusterVersion := NewClusterVersionFactory(clusterVersionName, clusterDefName). - AddComponentVersion(statelessCompDefName).AddContainerShort(DefaultNginxContainerName, NginxImage). - AddComponentVersion(consensusCompDefName).AddContainerShort(DefaultMySQLContainerName, NginxImage). - AddComponentVersion(statefulCompDefName).AddContainerShort(DefaultMySQLContainerName, NginxImage). - Create(testCtx).GetObject() pvcSpec := NewPVCSpec("1Gi") - cluster := NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefName, clusterVersionName). + cluster := NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefName). AddComponent(statelessCompDefName, statelessCompDefName).SetReplicas(1). AddComponent(consensusCompDefName, consensusCompDefName).SetReplicas(3). AddVolumeClaimTemplate(DataVolumeName, pvcSpec). AddComponent(statefulCompDefName, statefulCompDefName).SetReplicas(3). AddVolumeClaimTemplate(DataVolumeName, pvcSpec). Create(testCtx).GetObject() - return clusterDef, clusterVersion, cluster + return clusterDef, cluster } func CreateK8sResource(testCtx *testutil.TestContext, obj client.Object) client.Object { diff --git a/pkg/testutil/apps/clusterversion_factory.go b/pkg/testutil/apps/clusterversion_factory.go deleted file mode 100644 index f93b27e8e093..000000000000 --- a/pkg/testutil/apps/clusterversion_factory.go +++ /dev/null @@ -1,106 +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 apps - -import ( - corev1 "k8s.io/api/core/v1" - - appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" -) - -type MockClusterVersionFactory struct { - BaseFactory[appsv1alpha1.ClusterVersion, *appsv1alpha1.ClusterVersion, MockClusterVersionFactory] -} - -func NewClusterVersionFactory(name, cdRef string) *MockClusterVersionFactory { - f := &MockClusterVersionFactory{} - f.Init("", name, - &appsv1alpha1.ClusterVersion{ - Spec: appsv1alpha1.ClusterVersionSpec{ - ClusterDefinitionRef: cdRef, - ComponentVersions: []appsv1alpha1.ClusterComponentVersion{}, - }, - }, f) - return f -} - -func (factory *MockClusterVersionFactory) AddComponentVersion(compDefName string) *MockClusterVersionFactory { - comp := appsv1alpha1.ClusterComponentVersion{ - ComponentDefRef: compDefName, - } - factory.Get().Spec.ComponentVersions = append(factory.Get().Spec.ComponentVersions, comp) - return factory -} - -func (factory *MockClusterVersionFactory) AddInitContainer(container corev1.Container) *MockClusterVersionFactory { - comps := factory.Get().Spec.ComponentVersions - if len(comps) > 0 { - comp := comps[len(comps)-1] - comp.VersionsCtx.InitContainers = append(comp.VersionsCtx.InitContainers, container) - comps[len(comps)-1] = comp - } - factory.Get().Spec.ComponentVersions = comps - return factory -} - -func (factory *MockClusterVersionFactory) AddInitContainerShort(name string, image string) *MockClusterVersionFactory { - return factory.AddInitContainer(corev1.Container{ - Name: name, - Image: image, - }) -} - -func (factory *MockClusterVersionFactory) AddContainer(container corev1.Container) *MockClusterVersionFactory { - comps := factory.Get().Spec.ComponentVersions - if len(comps) > 0 { - comp := comps[len(comps)-1] - comp.VersionsCtx.Containers = append(comp.VersionsCtx.Containers, container) - comps[len(comps)-1] = comp - } - factory.Get().Spec.ComponentVersions = comps - return factory -} - -func (factory *MockClusterVersionFactory) AddContainerShort(name string, image string) *MockClusterVersionFactory { - return factory.AddContainer(corev1.Container{ - Name: name, - Image: image, - }) -} - -func (factory *MockClusterVersionFactory) AddConfigTemplate(name string, - configTemplateRef string, configConstraintRef string, volumeName string) *MockClusterVersionFactory { - comps := factory.Get().Spec.ComponentVersions - if len(comps) > 0 { - comp := comps[len(comps)-1] - comp.ConfigSpecs = append(comp.ConfigSpecs, - appsv1alpha1.ComponentConfigSpec{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: name, - TemplateRef: configTemplateRef, - VolumeName: volumeName, - }, - ConfigConstraintRef: configConstraintRef, - }) - comps[len(comps)-1] = comp - } - factory.Get().Spec.ComponentVersions = comps - return factory -} diff --git a/pkg/testutil/apps/common_util.go b/pkg/testutil/apps/common_util.go index 743f8f01a5ea..32e4e9ecc2f5 100644 --- a/pkg/testutil/apps/common_util.go +++ b/pkg/testutil/apps/common_util.go @@ -355,13 +355,9 @@ func ClearResourcesWithRemoveFinalizerOption[T intctrlutil.Object, PT intctrluti // environment without UseExistingCluster set, where garbage collection lacks. func ClearClusterResources(testCtx *testutil.TestContext) { inNS := client.InNamespace(testCtx.DefaultNamespace) - ClearResources(testCtx, intctrlutil.ClusterSignature, inNS, - client.HasLabels{testCtx.TestObjLabelKey}) - // finalizer of ConfigMap are deleted in ClusterDef&ClusterVersion controller - ClearResources(testCtx, intctrlutil.ClusterVersionSignature, - client.HasLabels{testCtx.TestObjLabelKey}) - ClearResources(testCtx, intctrlutil.ClusterDefinitionSignature, - client.HasLabels{testCtx.TestObjLabelKey}) + ClearResources(testCtx, intctrlutil.ClusterSignature, inNS, client.HasLabels{testCtx.TestObjLabelKey}) + // finalizer of ConfigMap are deleted in ClusterDefinition controller + ClearResources(testCtx, intctrlutil.ClusterDefinitionSignature, client.HasLabels{testCtx.TestObjLabelKey}) } // ClearClusterResourcesWithRemoveFinalizerOption clears all dependent resources belonging to existing clusters. @@ -369,8 +365,7 @@ func ClearClusterResourcesWithRemoveFinalizerOption(testCtx *testutil.TestContex inNs := client.InNamespace(testCtx.DefaultNamespace) hasLabels := client.HasLabels{testCtx.TestObjLabelKey} ClearResourcesWithRemoveFinalizerOption(testCtx, intctrlutil.ClusterSignature, true, inNs, hasLabels) - // finalizer of ConfigMap are deleted in ClusterDef & ClusterVersion controller - ClearResourcesWithRemoveFinalizerOption(testCtx, intctrlutil.ClusterVersionSignature, true, hasLabels) + // finalizer of ConfigMap are deleted in ClusterDefinition controller ClearResourcesWithRemoveFinalizerOption(testCtx, intctrlutil.ClusterDefinitionSignature, true, hasLabels) ClearResourcesWithRemoveFinalizerOption(testCtx, intctrlutil.ComponentDefinitionSignature, true, hasLabels) ClearResourcesWithRemoveFinalizerOption(testCtx, intctrlutil.ComponentVersionSignature, true, hasLabels) diff --git a/pkg/testutil/apps/constant.go b/pkg/testutil/apps/constant.go index d534ec936198..c97c6e3be807 100644 --- a/pkg/testutil/apps/constant.go +++ b/pkg/testutil/apps/constant.go @@ -54,9 +54,6 @@ const ( DefaultRedisContainerName = "redis" DefaultRedisInitContainerName = "redis-init-container" - EnvKeyImageTag = "IMAGE_TAG" - DefaultImageTag = "test" - DefaultConfigSpecName = "config-cm" DefaultConfigSpecTplRef = "env-from-config-tpl" DefaultConfigSpecVolumeName = "volume" diff --git a/pkg/testutil/dataprotection/backup_utils.go b/pkg/testutil/dataprotection/backup_utils.go index 2aaa330bd847..8deed3a928ab 100644 --- a/pkg/testutil/dataprotection/backup_utils.go +++ b/pkg/testutil/dataprotection/backup_utils.go @@ -177,8 +177,7 @@ func NewFakeCluster(testCtx *testutil.TestContext) *BackupClusterInfo { } By("mocking a cluster") - cluster := testapps.NewClusterFactory(testCtx.DefaultNamespace, ClusterName, - "test-cd", "test-cv"). + cluster := testapps.NewClusterFactory(testCtx.DefaultNamespace, ClusterName, "test-cd"). AddLabels(constant.AppInstanceLabelKey, ClusterName). AddComponent("test-cmp", "test-cmpd").AddSystemAccount("test-account", nil, nil). Create(testCtx).GetObject() diff --git a/test/e2e/testdata/config/postgresql_cv.yaml b/test/e2e/testdata/config/postgresql_cv.yaml deleted file mode 100644 index a41f87089171..000000000000 --- a/test/e2e/testdata/config/postgresql_cv.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: apps.kubeblocks.io/v1alpha1 -kind: ClusterVersion -metadata: - name: postgresql-14.7.2-latest -spec: - clusterDefinitionRef: postgresql - componentVersions: - - componentDefRef: postgresql - versionsContext: - containers: - - name: postgresql - image: apecloud-registry.cn-zhangjiakou.cr.aliyuncs.com/apecloud/spilo:14.7.2 - - name: pgbouncer - image: apecloud-registry.cn-zhangjiakou.cr.aliyuncs.com/apecloud/pgbouncer:1.19.0 - initContainers: - - image: apecloud-registry.cn-zhangjiakou.cr.aliyuncs.com/apecloud/spilo:14.7.2 - name: pg-init-container - systemAccountSpec: - cmdExecutorConfig: - image: apecloud-registry.cn-zhangjiakou.cr.aliyuncs.com/apecloud/spilo:14.7.2 - switchoverSpec: - cmdExecutorConfig: - image: apecloud-registry.cn-zhangjiakou.cr.aliyuncs.com/apecloud/spilo:14.7.2 \ No newline at end of file From 07e620f0735b57259136a4f41a59a0a34b4b9929 Mon Sep 17 00:00:00 2001 From: Leon Date: Fri, 2 Aug 2024 14:42:10 +0800 Subject: [PATCH 28/45] chore: disable zero replicas by default (#7788) --- controllers/apps/component_controller_test.go | 47 ++++--------------- .../apps/transformer_component_validation.go | 42 ++++------------- 2 files changed, 20 insertions(+), 69 deletions(-) diff --git a/controllers/apps/component_controller_test.go b/controllers/apps/component_controller_test.go index 1beeb8fc3189..b322172620f5 100644 --- a/controllers/apps/component_controller_test.go +++ b/controllers/apps/component_controller_test.go @@ -380,32 +380,6 @@ var _ = Describe("Component Controller", func() { } } - testChangeReplicasFromZero := func(compName, compDefName string) { - var ( - init = int32(0) - target = int32(3) - ) - - createClusterObjV2(compName, compDefObj.Name, func(f *testapps.MockClusterFactory) { - f.SetReplicas(init) - }) - - By(fmt.Sprintf("change replicas to %d", target)) - changeComponentReplicas(clusterKey, target) - - By("checking the number of replicas in component and ITS as expected") - Eventually(testapps.CheckObj(&testCtx, compKey, func(g Gomega, comp *appsv1alpha1.Component) { - g.Expect(comp.Spec.Replicas).Should(Equal(target)) - g.Expect(comp.Generation).Should(Equal(comp.Status.ObservedGeneration)) - })).Should(Succeed()) - - By("checking the number of replicas in ITS as expected") - itsKey := compKey - Eventually(testapps.CheckObj(&testCtx, itsKey, func(g Gomega, its *workloads.InstanceSet) { - g.Expect(*its.Spec.Replicas).Should(Equal(target)) - })).Should(Succeed()) - } - testChangeReplicasToZero := func(compName, compDefName string) { var ( init = int32(3) @@ -2134,9 +2108,16 @@ var _ = Describe("Component Controller", func() { }) It("with component zero replicas", func() { - createClusterObjV2(defaultCompName, compDefName, func(f *testapps.MockClusterFactory) { - f.SetReplicas(0) - }) + phase := appsv1alpha1.ClusterPhase("") + createClusterObjVx("", defaultCompName, compDefName, true, + func(f *testapps.MockClusterFactory) { + f.SetReplicas(0) + }, &phase) + + By("checking the component status can't be reconciled well") + Eventually(testapps.CheckObj(&testCtx, compKey, func(g Gomega, comp *appsv1alpha1.Component) { + g.Expect(comp.Generation > comp.Status.ObservedGeneration).Should(BeTrue()) + })).Should(Succeed()) }) It("with component services", func() { @@ -2202,10 +2183,6 @@ var _ = Describe("Component Controller", func() { testChangeReplicas(replicationCompName, replicationCompDefName) }) - It("scale-out from 0", func() { - testChangeReplicasFromZero(replicationCompName, replicationCompDefName) - }) - It("scale-in to 0", func() { testChangeReplicasToZero(replicationCompName, replicationCompDefName) }) @@ -2340,10 +2317,6 @@ var _ = Describe("Component Controller", func() { It("scale-in to 0 and PVCs should not been deleted", func() { testHorizontalScale(compName, compDefObj.Name, 3, 0, appsv1alpha1.HScaleDataClonePolicyCloneVolume) }) - - It("scale-out from 0 and should work well", func() { - testHorizontalScale(compName, compDefObj.Name, 0, 3, appsv1alpha1.HScaleDataClonePolicyCloneVolume) - }) }) Context(fmt.Sprintf("[comp: %s] scale-out after volume expansion", compName), func() { diff --git a/controllers/apps/transformer_component_validation.go b/controllers/apps/transformer_component_validation.go index 127ea77005d6..6f1abbcf1849 100644 --- a/controllers/apps/transformer_component_validation.go +++ b/controllers/apps/transformer_component_validation.go @@ -21,14 +21,17 @@ package apps import ( "fmt" + "math" appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" "github.com/apecloud/kubeblocks/pkg/controller/graph" ) -const ( - defaultMinReplicas int32 = 0 - defaultMinReplicas4ScaleIn int32 = 1 +var ( + defaultReplicasLimit = appsv1alpha1.ReplicasLimit{ + MinReplicas: 1, + MaxReplicas: math.MaxInt32, + } ) // componentValidationTransformer validates the consistency between spec & definition. @@ -86,44 +89,19 @@ func validateEnabledLogConfigs(compDef *appsv1alpha1.ComponentDefinition, enable } func validateCompReplicas(comp *appsv1alpha1.Component, compDef *appsv1alpha1.ComponentDefinition) error { - if err := validateCompReplicasGeneral(comp, compDef); err != nil { - return err + replicasLimit := &defaultReplicasLimit + // always respect the replicas limit if set. + if compDef.Spec.ReplicasLimit != nil { + replicasLimit = compDef.Spec.ReplicasLimit } - return validateCompReplicas4Runtime(comp, compDef) -} -func validateCompReplicasGeneral(comp *appsv1alpha1.Component, compDef *appsv1alpha1.ComponentDefinition) error { - if compDef.Spec.ReplicasLimit == nil { - return nil - } replicas := comp.Spec.Replicas - replicasLimit := compDef.Spec.ReplicasLimit if replicas >= replicasLimit.MinReplicas && replicas <= replicasLimit.MaxReplicas { return nil } return replicasOutOfLimitError(replicas, *replicasLimit) } -func validateCompReplicas4Runtime(comp *appsv1alpha1.Component, compDef *appsv1alpha1.ComponentDefinition) error { - minReplicas := func() int32 { - // always respect the replicas limit if it is set. - if compDef.Spec.ReplicasLimit != nil { - return compDef.Spec.ReplicasLimit.MinReplicas - } - // HACK: take observedGeneration == 0 as the provisioning. - if comp.Status.ObservedGeneration == 0 { - return defaultMinReplicas - } - return min(comp.Spec.Replicas, defaultMinReplicas4ScaleIn) - }() - - replicas := comp.Spec.Replicas - if replicas < minReplicas { - return fmt.Errorf("replicas %d is less than required min replicas %d", replicas, minReplicas) - } - return nil -} - func replicasOutOfLimitError(replicas int32, replicasLimit appsv1alpha1.ReplicasLimit) error { return fmt.Errorf("replicas %d out-of-limit [%d, %d]", replicas, replicasLimit.MinReplicas, replicasLimit.MaxReplicas) } From 4f4265fbf31f450890402c8cd9099e68afe36774 Mon Sep 17 00:00:00 2001 From: zhangtao <111836083+sophon-zt@users.noreply.github.com> Date: Fri, 2 Aug 2024 16:13:12 +0800 Subject: [PATCH 29/45] chore: Removed name length limit for config template (#7915) --- apis/apps/v1alpha1/type.go | 2 -- config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml | 2 -- config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml | 2 -- config/crd/bases/apps.kubeblocks.io_configurations.yaml | 4 ---- deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml | 2 -- deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml | 2 -- deploy/helm/crds/apps.kubeblocks.io_configurations.yaml | 4 ---- 7 files changed, 18 deletions(-) diff --git a/apis/apps/v1alpha1/type.go b/apis/apps/v1alpha1/type.go index 69a8589ce940..a1b7db7a83f4 100644 --- a/apis/apps/v1alpha1/type.go +++ b/apis/apps/v1alpha1/type.go @@ -90,7 +90,6 @@ type ConfigTemplateExtension struct { // Specifies the name of the referenced configuration template ConfigMap object. // // +kubebuilder:validation:Required - // +kubebuilder:validation:MaxLength=63 // +kubebuilder:validation:Pattern:=`^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$` TemplateRef string `json:"templateRef"` @@ -98,7 +97,6 @@ type ConfigTemplateExtension struct { // An empty namespace is equivalent to the "default" namespace. // // +kubebuilder:default="default" - // +kubebuilder:validation:MaxLength=63 // +kubebuilder:validation:Pattern:=`^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$` // +optional Namespace string `json:"namespace,omitempty"` diff --git a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml index c905dd54452e..b902ff95ab16 100644 --- a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml @@ -301,7 +301,6 @@ spec: description: |- Specifies the namespace of the referenced configuration template ConfigMap object. An empty namespace is equivalent to the "default" namespace. - maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ type: string policy: @@ -316,7 +315,6 @@ spec: templateRef: description: Specifies the name of the referenced configuration template ConfigMap object. - maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ type: string required: diff --git a/config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml b/config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml index 26f7abfb1a1f..c714cf2fbfb5 100644 --- a/config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml +++ b/config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml @@ -219,7 +219,6 @@ spec: description: |- Specifies the namespace of the referenced configuration template ConfigMap object. An empty namespace is equivalent to the "default" namespace. - maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ type: string policy: @@ -234,7 +233,6 @@ spec: templateRef: description: Specifies the name of the referenced configuration template ConfigMap object. - maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ type: string required: diff --git a/config/crd/bases/apps.kubeblocks.io_configurations.yaml b/config/crd/bases/apps.kubeblocks.io_configurations.yaml index cba96560c738..861788bc31a1 100644 --- a/config/crd/bases/apps.kubeblocks.io_configurations.yaml +++ b/config/crd/bases/apps.kubeblocks.io_configurations.yaml @@ -216,7 +216,6 @@ spec: description: |- Specifies the namespace of the referenced configuration template ConfigMap object. An empty namespace is equivalent to the "default" namespace. - maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ type: string policy: @@ -231,7 +230,6 @@ spec: templateRef: description: Specifies the name of the referenced configuration template ConfigMap object. - maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ type: string required: @@ -304,7 +302,6 @@ spec: description: |- Specifies the namespace of the referenced configuration template ConfigMap object. An empty namespace is equivalent to the "default" namespace. - maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ type: string policy: @@ -319,7 +316,6 @@ spec: templateRef: description: Specifies the name of the referenced configuration template ConfigMap object. - maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ type: string required: diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml index c905dd54452e..b902ff95ab16 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml @@ -301,7 +301,6 @@ spec: description: |- Specifies the namespace of the referenced configuration template ConfigMap object. An empty namespace is equivalent to the "default" namespace. - maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ type: string policy: @@ -316,7 +315,6 @@ spec: templateRef: description: Specifies the name of the referenced configuration template ConfigMap object. - maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ type: string required: diff --git a/deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml b/deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml index 26f7abfb1a1f..c714cf2fbfb5 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml @@ -219,7 +219,6 @@ spec: description: |- Specifies the namespace of the referenced configuration template ConfigMap object. An empty namespace is equivalent to the "default" namespace. - maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ type: string policy: @@ -234,7 +233,6 @@ spec: templateRef: description: Specifies the name of the referenced configuration template ConfigMap object. - maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ type: string required: diff --git a/deploy/helm/crds/apps.kubeblocks.io_configurations.yaml b/deploy/helm/crds/apps.kubeblocks.io_configurations.yaml index cba96560c738..861788bc31a1 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_configurations.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_configurations.yaml @@ -216,7 +216,6 @@ spec: description: |- Specifies the namespace of the referenced configuration template ConfigMap object. An empty namespace is equivalent to the "default" namespace. - maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ type: string policy: @@ -231,7 +230,6 @@ spec: templateRef: description: Specifies the name of the referenced configuration template ConfigMap object. - maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ type: string required: @@ -304,7 +302,6 @@ spec: description: |- Specifies the namespace of the referenced configuration template ConfigMap object. An empty namespace is equivalent to the "default" namespace. - maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ type: string policy: @@ -319,7 +316,6 @@ spec: templateRef: description: Specifies the name of the referenced configuration template ConfigMap object. - maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ type: string required: From f7ddcb1b21329546b4aeee4a2e8564169a5b3175 Mon Sep 17 00:00:00 2001 From: Leon Date: Mon, 5 Aug 2024 10:08:35 +0800 Subject: [PATCH 30/45] chore: remove volumes from cd (#7775) --- apis/apps/v1alpha1/clusterdefinition_types.go | 36 ------ apis/apps/v1alpha1/type.go | 16 --- apis/apps/v1alpha1/zz_generated.deepcopy.go | 25 ---- ...apps.kubeblocks.io_clusterdefinitions.yaml | 71 ------------ .../apps/component_hscale_volume_populator.go | 4 +- ...apps.kubeblocks.io_clusterdefinitions.yaml | 71 ------------ docs/developer_docs/api-reference/cluster.md | 108 ------------------ pkg/constant/labels.go | 1 - .../apiconversion/simplified_cluster_api.go | 5 - .../component/definition_convertor.go | 34 +----- .../component/definition_convertor_test.go | 66 +---------- .../component/synthesize_component.go | 1 - pkg/controller/component/type.go | 1 - pkg/controller/factory/builder.go | 7 -- pkg/controller/factory/builder_test.go | 3 - pkg/controller/plan/restore_test.go | 1 - pkg/testutil/apps/constant.go | 26 +---- pkg/testutil/apps/pvc_factoy.go | 1 - 18 files changed, 10 insertions(+), 467 deletions(-) diff --git a/apis/apps/v1alpha1/clusterdefinition_types.go b/apis/apps/v1alpha1/clusterdefinition_types.go index b45e53788dce..9d65fd7cf95f 100644 --- a/apis/apps/v1alpha1/clusterdefinition_types.go +++ b/apis/apps/v1alpha1/clusterdefinition_types.go @@ -375,20 +375,6 @@ type LogConfig struct { FilePathPattern string `json:"filePathPattern"` } -// VolumeTypeSpec is deprecated since v0.9, replaced with ComponentVolume. -type VolumeTypeSpec struct { - // Corresponds to the name of the VolumeMounts field in PodSpec.Container. - // - // +kubebuilder:validation:Required - // +kubebuilder:validation:Pattern:=`^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$` - Name string `json:"name"` - - // Type of data the volume will persistent. - // - // +optional - Type VolumeType `json:"type,omitempty"` -} - // VolumeProtectionSpec is deprecated since v0.9, replaced with ComponentVolume.HighWatermark. type VolumeProtectionSpec struct { // The high watermark threshold for volume space usage. @@ -595,23 +581,6 @@ type ClusterComponentDefinition struct { // +optional SystemAccounts *SystemAccountSpec `json:"systemAccounts,omitempty"` - // Used to describe the purpose of the volumes mapping the name of the VolumeMounts in the PodSpec.Container field, - // such as data volume, log volume, etc. When backing up the volume, the volume can be correctly backed up according - // to the volumeType. - // - // For example: - // - // - `name: data, type: data` means that the volume named `data` is used to store `data`. - // - `name: binlog, type: log` means that the volume named `binlog` is used to store `log`. - // - // NOTE: When volumeTypes is not defined, the backup function will not be supported, even if a persistent volume has - // been specified. - // - // +listType=map - // +listMapKey=name - // +optional - VolumeTypes []VolumeTypeSpec `json:"volumeTypes,omitempty"` - // Defines command to do switchover. // In particular, when workloadType=Replication, the command defined in switchoverSpec will only be executed under // the condition of cluster.componentSpecs[x].SwitchPolicy.type=Noop. @@ -625,11 +594,6 @@ type ClusterComponentDefinition struct { // +optional PostStartSpec *PostStartAction `json:"postStartSpec,omitempty"` - // Defines settings to do volume protect. - // - // +optional - VolumeProtectionSpec *VolumeProtectionSpec `json:"volumeProtectionSpec,omitempty"` - // Used to inject values from other components into the current component. Values will be saved and updated in a // configmap and mounted to the current component. // diff --git a/apis/apps/v1alpha1/type.go b/apis/apps/v1alpha1/type.go index a1b7db7a83f4..2a96db615974 100644 --- a/apis/apps/v1alpha1/type.go +++ b/apis/apps/v1alpha1/type.go @@ -725,22 +725,6 @@ const ( Noop SwitchPolicyType = "Noop" ) -// VolumeType defines the type of volume, specifically distinguishing between volumes used for backup data and those used for logs. -// -// +enum -// +kubebuilder:validation:Enum={data,log} -type VolumeType string - -const ( - // VolumeTypeData indicates a volume designated for storing backup data. This type of volume is optimized for the - // storage and retrieval of data backups, ensuring data persistence and reliability. - VolumeTypeData VolumeType = "data" - - // VolumeTypeLog indicates a volume designated for storing logs. This type of volume is optimized for log data, - // facilitating efficient log storage, retrieval, and management. - VolumeTypeLog VolumeType = "log" -) - // BaseBackupType the base backup type, keep synchronized with the BaseBackupType of the data protection API. // // +enum diff --git a/apis/apps/v1alpha1/zz_generated.deepcopy.go b/apis/apps/v1alpha1/zz_generated.deepcopy.go index d44c760e027d..db91aabc8394 100644 --- a/apis/apps/v1alpha1/zz_generated.deepcopy.go +++ b/apis/apps/v1alpha1/zz_generated.deepcopy.go @@ -471,11 +471,6 @@ func (in *ClusterComponentDefinition) DeepCopyInto(out *ClusterComponentDefiniti *out = new(SystemAccountSpec) (*in).DeepCopyInto(*out) } - if in.VolumeTypes != nil { - in, out := &in.VolumeTypes, &out.VolumeTypes - *out = make([]VolumeTypeSpec, len(*in)) - copy(*out, *in) - } if in.SwitchoverSpec != nil { in, out := &in.SwitchoverSpec, &out.SwitchoverSpec *out = new(SwitchoverSpec) @@ -486,11 +481,6 @@ func (in *ClusterComponentDefinition) DeepCopyInto(out *ClusterComponentDefiniti *out = new(PostStartAction) (*in).DeepCopyInto(*out) } - if in.VolumeProtectionSpec != nil { - in, out := &in.VolumeProtectionSpec, &out.VolumeProtectionSpec - *out = new(VolumeProtectionSpec) - (*in).DeepCopyInto(*out) - } if in.ComponentDefRef != nil { in, out := &in.ComponentDefRef, &out.ComponentDefRef *out = make([]ComponentDefRef, len(*in)) @@ -6194,18 +6184,3 @@ func (in *VolumeProtectionSpec) DeepCopy() *VolumeProtectionSpec { in.DeepCopyInto(out) return out } - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VolumeTypeSpec) DeepCopyInto(out *VolumeTypeSpec) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeTypeSpec. -func (in *VolumeTypeSpec) DeepCopy() *VolumeTypeSpec { - if in == nil { - return nil - } - out := new(VolumeTypeSpec) - in.DeepCopyInto(out) - return out -} diff --git a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml index b902ff95ab16..f191a94ca575 100644 --- a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml @@ -9433,77 +9433,6 @@ spec: - cmdExecutorConfig - passwordConfig type: object - volumeProtectionSpec: - description: Defines settings to do volume protect. - properties: - highWatermark: - default: 90 - description: |- - The high watermark threshold for volume space usage. - If there is any specified volumes who's space usage is over the threshold, the pre-defined "LOCK" action - will be triggered to degrade the service to protect volume from space exhaustion, such as to set the instance - as read-only. And after that, if all volumes' space usage drops under the threshold later, the pre-defined - "UNLOCK" action will be performed to recover the service normally. - maximum: 100 - minimum: 0 - type: integer - volumes: - description: The Volumes to be protected. - items: - description: ProtectedVolume is deprecated since v0.9, - replaced with ComponentVolume.HighWatermark. - properties: - highWatermark: - description: |- - Defines the high watermark threshold for the volume, it will override the component level threshold. - If the value is invalid, it will be ignored and the component level threshold will be used. - maximum: 100 - minimum: 0 - type: integer - name: - description: The Name of the volume to protect. - type: string - type: object - type: array - type: object - volumeTypes: - description: |- - Used to describe the purpose of the volumes mapping the name of the VolumeMounts in the PodSpec.Container field, - such as data volume, log volume, etc. When backing up the volume, the volume can be correctly backed up according - to the volumeType. - - - For example: - - - - `name: data, type: data` means that the volume named `data` is used to store `data`. - - `name: binlog, type: log` means that the volume named `binlog` is used to store `log`. - - - NOTE: When volumeTypes is not defined, the backup function will not be supported, even if a persistent volume has - been specified. - items: - description: VolumeTypeSpec is deprecated since v0.9, replaced - with ComponentVolume. - properties: - name: - description: Corresponds to the name of the VolumeMounts - field in PodSpec.Container. - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - type: - description: Type of data the volume will persistent. - enum: - - data - - log - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map workloadType: description: |- Defines the type of the workload. diff --git a/controllers/apps/component_hscale_volume_populator.go b/controllers/apps/component_hscale_volume_populator.go index c0c7cd8d34f6..dcb07ab40026 100644 --- a/controllers/apps/component_hscale_volume_populator.go +++ b/controllers/apps/component_hscale_volume_populator.go @@ -475,8 +475,8 @@ func backupVCT(component *component.SynthesizedComponent) *corev1.PersistentVolu } vct := component.VolumeClaimTemplates[0] for _, tmpVct := range component.VolumeClaimTemplates { - for _, volumeType := range component.VolumeTypes { - if volumeType.Type == appsv1alpha1.VolumeTypeData && volumeType.Name == tmpVct.Name { + for _, volume := range component.Volumes { + if volume.NeedSnapshot && volume.Name == tmpVct.Name { vct = tmpVct break } diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml index b902ff95ab16..f191a94ca575 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml @@ -9433,77 +9433,6 @@ spec: - cmdExecutorConfig - passwordConfig type: object - volumeProtectionSpec: - description: Defines settings to do volume protect. - properties: - highWatermark: - default: 90 - description: |- - The high watermark threshold for volume space usage. - If there is any specified volumes who's space usage is over the threshold, the pre-defined "LOCK" action - will be triggered to degrade the service to protect volume from space exhaustion, such as to set the instance - as read-only. And after that, if all volumes' space usage drops under the threshold later, the pre-defined - "UNLOCK" action will be performed to recover the service normally. - maximum: 100 - minimum: 0 - type: integer - volumes: - description: The Volumes to be protected. - items: - description: ProtectedVolume is deprecated since v0.9, - replaced with ComponentVolume.HighWatermark. - properties: - highWatermark: - description: |- - Defines the high watermark threshold for the volume, it will override the component level threshold. - If the value is invalid, it will be ignored and the component level threshold will be used. - maximum: 100 - minimum: 0 - type: integer - name: - description: The Name of the volume to protect. - type: string - type: object - type: array - type: object - volumeTypes: - description: |- - Used to describe the purpose of the volumes mapping the name of the VolumeMounts in the PodSpec.Container field, - such as data volume, log volume, etc. When backing up the volume, the volume can be correctly backed up according - to the volumeType. - - - For example: - - - - `name: data, type: data` means that the volume named `data` is used to store `data`. - - `name: binlog, type: log` means that the volume named `binlog` is used to store `log`. - - - NOTE: When volumeTypes is not defined, the backup function will not be supported, even if a persistent volume has - been specified. - items: - description: VolumeTypeSpec is deprecated since v0.9, replaced - with ComponentVolume. - properties: - name: - description: Corresponds to the name of the VolumeMounts - field in PodSpec.Container. - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - type: - description: Type of data the volume will persistent. - enum: - - data - - log - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map workloadType: description: |- Defines the type of the workload. diff --git a/docs/developer_docs/api-reference/cluster.md b/docs/developer_docs/api-reference/cluster.md index fd5677d7f389..342160e32e8b 100644 --- a/docs/developer_docs/api-reference/cluster.md +++ b/docs/developer_docs/api-reference/cluster.md @@ -4262,29 +4262,6 @@ SystemAccountSpec -volumeTypes
    - - -[]VolumeTypeSpec - - - - -(Optional) -

    Used to describe the purpose of the volumes mapping the name of the VolumeMounts in the PodSpec.Container field, -such as data volume, log volume, etc. When backing up the volume, the volume can be correctly backed up according -to the volumeType.

    -

    For example:

    -
      -
    • name: data, type: data means that the volume named data is used to store data.
    • -
    • name: binlog, type: log means that the volume named binlog is used to store log.
    • -
    -

    NOTE: When volumeTypes is not defined, the backup function will not be supported, even if a persistent volume has -been specified.

    - - - - switchoverSpec
    @@ -4316,20 +4293,6 @@ the component becomes ready.

    -volumeProtectionSpec
    - -
    -VolumeProtectionSpec - - - - -(Optional) -

    Defines settings to do volume protect.

    - - - - componentDefRef
    @@ -20609,9 +20572,6 @@ that are used to expand the storage and the desired storage size for each one.

    VolumeProtectionSpec

    -

    -(Appears on:ClusterComponentDefinition) -

    VolumeProtectionSpec is deprecated since v0.9, replaced with ComponentVolume.HighWatermark.

    @@ -20655,74 +20615,6 @@ as read-only. And after that, if all volumes’ space usage drops under the -

    VolumeType -(string alias)

    -

    -(Appears on:VolumeTypeSpec) -

    -
    -

    VolumeType defines the type of volume, specifically distinguishing between volumes used for backup data and those used for logs.

    -
    - - - - - - - - - - - - -
    ValueDescription

    "data"

    VolumeTypeData indicates a volume designated for storing backup data. This type of volume is optimized for the -storage and retrieval of data backups, ensuring data persistence and reliability.

    -

    "log"

    VolumeTypeLog indicates a volume designated for storing logs. This type of volume is optimized for log data, -facilitating efficient log storage, retrieval, and management.

    -
    -

    VolumeTypeSpec -

    -

    -(Appears on:ClusterComponentDefinition) -

    -
    -

    VolumeTypeSpec is deprecated since v0.9, replaced with ComponentVolume.

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -name
    - -string - -
    -

    Corresponds to the name of the VolumeMounts field in PodSpec.Container.

    -
    -type
    - - -VolumeType - - -
    -(Optional) -

    Type of data the volume will persistent.

    -

    WorkloadType (string alias)

    diff --git a/pkg/constant/labels.go b/pkg/constant/labels.go index 83bde789e266..ebe156088d00 100644 --- a/pkg/constant/labels.go +++ b/pkg/constant/labels.go @@ -40,7 +40,6 @@ const ( RoleLabelKey = "kubeblocks.io/role" // RoleLabelKey consensusSet and replicationSet role label key AccessModeLabelKey = "workloads.kubeblocks.io/access-mode" ReadyWithoutPrimaryKey = "kubeblocks.io/ready-without-primary" - VolumeTypeLabelKey = "kubeblocks.io/volume-type" ClusterAccountLabelKey = "account.kubeblocks.io/name" KBAppClusterUIDLabelKey = "apps.kubeblocks.io/cluster-uid" KBAppComponentLabelKey = "apps.kubeblocks.io/component-name" diff --git a/pkg/controller/apiconversion/simplified_cluster_api.go b/pkg/controller/apiconversion/simplified_cluster_api.go index 3f47ee525d70..4eeeec23c660 100644 --- a/pkg/controller/apiconversion/simplified_cluster_api.go +++ b/pkg/controller/apiconversion/simplified_cluster_api.go @@ -68,11 +68,6 @@ func fillSimplifiedClusterAPI(cluster *appsv1alpha1.Cluster, clusterCompDef *app clusterCompSpec.Replicas = *cluster.Spec.Replicas } dataVolumeName := "data" - for _, v := range clusterCompDef.VolumeTypes { - if v.Type == appsv1alpha1.VolumeTypeData { - dataVolumeName = v.Name - } - } if !cluster.Spec.Resources.CPU.IsZero() || !cluster.Spec.Resources.Memory.IsZero() { clusterCompSpec.Resources.Limits = corev1.ResourceList{} } diff --git a/pkg/controller/component/definition_convertor.go b/pkg/controller/component/definition_convertor.go index 90fb6355adb4..4d0c6e96261c 100644 --- a/pkg/controller/component/definition_convertor.go +++ b/pkg/controller/component/definition_convertor.go @@ -152,39 +152,7 @@ func (c *compDefVarsConvertor) convertHostNetworkVars(clusterCompDef *appsv1alph type compDefVolumesConvertor struct{} func (c *compDefVolumesConvertor) convert(args ...any) (any, error) { - clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - if clusterCompDef.VolumeTypes == nil { - return nil, nil - } - - volumes := make([]appsv1alpha1.ComponentVolume, 0) - for _, vol := range clusterCompDef.VolumeTypes { - volumes = append(volumes, appsv1alpha1.ComponentVolume{ - Name: vol.Name, - }) - } - - if clusterCompDef.VolumeProtectionSpec != nil { - defaultHighWatermark := clusterCompDef.VolumeProtectionSpec.HighWatermark - highWatermark := func(v appsv1alpha1.ProtectedVolume) int { - if v.HighWatermark != nil { - return *v.HighWatermark - } - return defaultHighWatermark - } - setHighWatermark := func(protectedVol appsv1alpha1.ProtectedVolume) { - for i, v := range volumes { - if v.Name == protectedVol.Name { - volumes[i].HighWatermark = highWatermark(protectedVol) - break - } - } - } - for _, v := range clusterCompDef.VolumeProtectionSpec.Volumes { - setHighWatermark(v) - } - } - return volumes, nil + return nil, nil } // compDefHostNetworkConvertor converts the given object into ComponentDefinition.Spec.HostNetwork. diff --git a/pkg/controller/component/definition_convertor_test.go b/pkg/controller/component/definition_convertor_test.go index 7c64ab03c18f..c92bb304914f 100644 --- a/pkg/controller/component/definition_convertor_test.go +++ b/pkg/controller/component/definition_convertor_test.go @@ -40,10 +40,8 @@ var _ = Describe("Component Definition Convertor", func() { clusterName = "mysql-test" - defaultHighWatermark = 90 - lowerHighWatermark = 85 - dataVolumeName = "data" - logVolumeName = "log" + dataVolumeName = "data" + logVolumeName = "log" defaultVolumeMode = int32(0555) @@ -244,26 +242,7 @@ var _ = Describe("Component Definition Convertor", func() { }, }, }, - VolumeTypes: []appsv1alpha1.VolumeTypeSpec{ - { - Name: dataVolumeName, - Type: appsv1alpha1.VolumeTypeData, - }, - { - Name: logVolumeName, - Type: appsv1alpha1.VolumeTypeLog, - }, - }, - SwitchoverSpec: &appsv1alpha1.SwitchoverSpec{}, - VolumeProtectionSpec: &appsv1alpha1.VolumeProtectionSpec{ - HighWatermark: defaultHighWatermark, - Volumes: []appsv1alpha1.ProtectedVolume{ - { - Name: logVolumeName, - HighWatermark: &lowerHighWatermark, - }, - }, - }, + SwitchoverSpec: &appsv1alpha1.SwitchoverSpec{}, ComponentDefRef: []appsv1alpha1.ComponentDefRef{}, ServiceRefDeclarations: []appsv1alpha1.ServiceRefDeclaration{}, } @@ -349,48 +328,11 @@ var _ = Describe("Component Definition Convertor", func() { }) Context("volumes", func() { - It("w/o volume types", func() { - clusterCompDefCopy := clusterCompDef.DeepCopy() - clusterCompDefCopy.VolumeTypes = nil - - convertor := &compDefVolumesConvertor{} - res, err := convertor.convert(clusterCompDefCopy) - Expect(err).Should(Succeed()) - Expect(res).Should(BeNil()) - }) - - It("w/o volume protection", func() { - clusterCompDefCopy := clusterCompDef.DeepCopy() - clusterCompDefCopy.VolumeProtectionSpec = nil - - convertor := &compDefVolumesConvertor{} - res, err := convertor.convert(clusterCompDefCopy) - Expect(err).Should(Succeed()) - - expectedVolumes := make([]appsv1alpha1.ComponentVolume, 0) - for _, vol := range clusterCompDef.VolumeTypes { - expectedVolumes = append(expectedVolumes, appsv1alpha1.ComponentVolume{Name: vol.Name}) - } - Expect(res).Should(BeEquivalentTo(expectedVolumes)) - }) - It("ok", func() { convertor := &compDefVolumesConvertor{} res, err := convertor.convert(clusterCompDef) Expect(err).Should(Succeed()) - - expectedVolumes := make([]appsv1alpha1.ComponentVolume, 0) - for _, vol := range clusterCompDef.VolumeTypes { - highWatermark := 0 - if vol.Name == logVolumeName { - highWatermark = lowerHighWatermark - } - expectedVolumes = append(expectedVolumes, appsv1alpha1.ComponentVolume{ - Name: vol.Name, - HighWatermark: highWatermark, - }) - } - Expect(res).Should(BeEquivalentTo(expectedVolumes)) + Expect(res).Should(BeNil()) }) }) diff --git a/pkg/controller/component/synthesize_component.go b/pkg/controller/component/synthesize_component.go index d56e1ccf561c..b13c58da3b46 100644 --- a/pkg/controller/component/synthesize_component.go +++ b/pkg/controller/component/synthesize_component.go @@ -625,7 +625,6 @@ func buildBackwardCompatibleFields(reqCtx intctrlutil.RequestCtx, synthesizeComp.ClusterCompDefName = clusterCompDef.Name synthesizeComp.CharacterType = clusterCompDef.CharacterType synthesizeComp.HorizontalScalePolicy = clusterCompDef.HorizontalScalePolicy - synthesizeComp.VolumeTypes = clusterCompDef.VolumeTypes } buildClusterCompServices := func() { diff --git a/pkg/controller/component/type.go b/pkg/controller/component/type.go index d0c348197810..dfe03057bb4c 100644 --- a/pkg/controller/component/type.go +++ b/pkg/controller/component/type.go @@ -81,6 +81,5 @@ type SynthesizedComponent struct { ClusterCompDefName string `json:"clusterCompDefName,omitempty"` // the name of the clusterDefinition.Spec.ComponentDefs[*].Name CharacterType string `json:"characterType,omitempty"` HorizontalScalePolicy *v1alpha1.HorizontalScalePolicy `json:"horizontalScalePolicy,omitempty"` - VolumeTypes []v1alpha1.VolumeTypeSpec `json:"volumeTypes,omitempty"` // The VolumeTypes will be replaced with Volumes in the future. EnabledLogs []string `json:"enabledLogs,omitempty"` } diff --git a/pkg/controller/factory/builder.go b/pkg/controller/factory/builder.go index f594e4ec0632..1c91381f35ea 100644 --- a/pkg/controller/factory/builder.go +++ b/pkg/controller/factory/builder.go @@ -194,13 +194,6 @@ func BuildPersistentVolumeClaimLabels(component *component.SynthesizedComponent, pvc.Labels = make(map[string]string) } pvc.Labels[constant.VolumeClaimTemplateNameLabelKey] = pvcTplName - - for _, t := range component.VolumeTypes { - if t.Name == pvcTplName { - pvc.Labels[constant.VolumeTypeLabelKey] = string(t.Type) - break - } - } if templateName != "" { pvc.Labels[constant.KBAppComponentInstanceTemplateLabelKey] = templateName } diff --git a/pkg/controller/factory/builder_test.go b/pkg/controller/factory/builder_test.go index 7d80a2a6ce96..afb141f9b393 100644 --- a/pkg/controller/factory/builder_test.go +++ b/pkg/controller/factory/builder_test.go @@ -152,7 +152,6 @@ var _ = Describe("builder", func() { Expect(pvc.Spec.AccessModes).Should(Equal(its.Spec.VolumeClaimTemplates[0].Spec.AccessModes)) Expect(pvc.Spec.Resources).Should(Equal(synthesizedComponent.VolumeClaimTemplates[0].Spec.Resources)) Expect(pvc.Spec.StorageClassName).Should(Equal(synthesizedComponent.VolumeClaimTemplates[0].Spec.StorageClassName)) - Expect(pvc.Labels[constant.VolumeTypeLabelKey]).ShouldNot(BeEmpty()) }) It("builds Conn. Credential correctly", func() { @@ -236,8 +235,6 @@ var _ = Describe("builder", func() { Expect(err).Should(BeNil()) Expect(its).ShouldNot(BeNil()) Expect(*its.Spec.Replicas).Should(Equal(int32(0))) - Expect(its.Spec.VolumeClaimTemplates[0].Labels[constant.VolumeTypeLabelKey]). - Should(Equal(string(appsv1alpha1.VolumeTypeData))) By("set workload type to Replication") clusterDef.Spec.ComponentDefs[0].WorkloadType = appsv1alpha1.Replication diff --git a/pkg/controller/plan/restore_test.go b/pkg/controller/plan/restore_test.go index 0feb996628ae..c18f4e671300 100644 --- a/pkg/controller/plan/restore_test.go +++ b/pkg/controller/plan/restore_test.go @@ -171,7 +171,6 @@ var _ = Describe("Restore", func() { HorizontalScalePolicy: clusterCompDefObj.HorizontalScalePolicy, VolumeClaimTemplates: cluster.Spec.ComponentSpecs[0].ToVolumeClaimTemplates(), Name: mysqlCompName, - VolumeTypes: []appsv1alpha1.VolumeTypeSpec{{Name: testapps.DataVolumeName, Type: appsv1alpha1.VolumeTypeData}}, Replicas: 1, Roles: []appsv1alpha1.ReplicaRole{ { diff --git a/pkg/testutil/apps/constant.go b/pkg/testutil/apps/constant.go index c97c6e3be807..499534d921fc 100644 --- a/pkg/testutil/apps/constant.go +++ b/pkg/testutil/apps/constant.go @@ -86,7 +86,6 @@ var ( TimeoutSeconds: 5, }, }, - VolumeProtectionSpec: &appsv1alpha1.VolumeProtectionSpec{}, PodSpec: &corev1.PodSpec{ Containers: []corev1.Container{{ Name: DefaultNginxContainerName, @@ -170,19 +169,12 @@ var ( TimeoutSeconds: 5, }, }, - VolumeProtectionSpec: &appsv1alpha1.VolumeProtectionSpec{}, - Service: &defaultMySQLService, + Service: &defaultMySQLService, PodSpec: &corev1.PodSpec{ Containers: []corev1.Container{ defaultMySQLContainer, }, }, - VolumeTypes: []appsv1alpha1.VolumeTypeSpec{ - { - Name: DataVolumeName, - Type: appsv1alpha1.VolumeTypeData, - }, - }, } defaultConsensusSpec = appsv1alpha1.ConsensusSetSpec{ @@ -218,19 +210,12 @@ var ( TimeoutSeconds: 5, }, }, - VolumeProtectionSpec: &appsv1alpha1.VolumeProtectionSpec{}, - Service: &defaultMySQLService, + Service: &defaultMySQLService, PodSpec: &corev1.PodSpec{ Containers: []corev1.Container{ defaultMySQLContainer, }, }, - VolumeTypes: []appsv1alpha1.VolumeTypeSpec{ - { - Name: DataVolumeName, - Type: appsv1alpha1.VolumeTypeData, - }, - }, } defaultComponentDefSpec = appsv1alpha1.ComponentDefinitionSpec{ @@ -449,12 +434,7 @@ var ( TimeoutSeconds: 5, }, }, - VolumeProtectionSpec: &appsv1alpha1.VolumeProtectionSpec{}, - Service: &defaultRedisService, - VolumeTypes: []appsv1alpha1.VolumeTypeSpec{{ - Name: DataVolumeName, - Type: appsv1alpha1.VolumeTypeData, - }}, + Service: &defaultRedisService, PodSpec: &corev1.PodSpec{ Volumes: []corev1.Volume{ { diff --git a/pkg/testutil/apps/pvc_factoy.go b/pkg/testutil/apps/pvc_factoy.go index 8aaf60686251..055025ccf4e9 100644 --- a/pkg/testutil/apps/pvc_factoy.go +++ b/pkg/testutil/apps/pvc_factoy.go @@ -43,7 +43,6 @@ func NewPersistentVolumeClaimFactory(namespace, name, clusterName, componentName constant.KBAppComponentLabelKey: componentName, constant.AppManagedByLabelKey: constant.AppName, constant.VolumeClaimTemplateNameLabelKey: vctName, - constant.VolumeTypeLabelKey: vctName, }, Annotations: map[string]string{ kube.KubeAnnBindCompleted: "yes", From 6fc256cd90d83a92f0304810fbea9535907f6a76 Mon Sep 17 00:00:00 2001 From: Leon Date: Mon, 5 Aug 2024 10:09:00 +0800 Subject: [PATCH 31/45] chore: remove the character-type (#7767) --- apis/apps/v1alpha1/clusterdefinition_types.go | 5 -- ...apps.kubeblocks.io_clusterdefinitions.yaml | 4 -- controllers/apps/operations/datascript.go | 3 +- controllers/apps/transformer_component_tls.go | 3 +- .../apps/transformer_component_tls_test.go | 52 +++++++++++-------- ...apps.kubeblocks.io_clusterdefinitions.yaml | 4 -- docs/developer_docs/api-reference/cluster.md | 12 ----- pkg/constant/lorry.go | 14 ----- .../component/definition_convertor.go | 35 +------------ .../component/definition_convertor_test.go | 16 +++--- pkg/controller/component/lorry_utils_test.go | 1 - .../component/synthesize_component.go | 2 +- pkg/controller/component/type.go | 18 +++---- pkg/controller/factory/builder_test.go | 2 - pkg/controller/plan/tls_utils.go | 4 +- .../apps/componentdefinition_factory.go | 5 ++ pkg/testutil/apps/constant.go | 10 ++-- 17 files changed, 64 insertions(+), 126 deletions(-) diff --git a/apis/apps/v1alpha1/clusterdefinition_types.go b/apis/apps/v1alpha1/clusterdefinition_types.go index 9d65fd7cf95f..e97934889d10 100644 --- a/apis/apps/v1alpha1/clusterdefinition_types.go +++ b/apis/apps/v1alpha1/clusterdefinition_types.go @@ -492,11 +492,6 @@ type ClusterComponentDefinition struct { // +kubebuilder:validation:Required WorkloadType WorkloadType `json:"workloadType"` - // Defines well-known database component name, such as mongos(mongodb), proxy(redis), mariadb(mysql). - // - // +optional - CharacterType string `json:"characterType,omitempty"` - // Defines the template of configurations. // // +patchMergeKey=name diff --git a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml index f191a94ca575..97d6a3fce778 100644 --- a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml @@ -89,10 +89,6 @@ spec: Deprecated: Use ComponentDefinition instead. This type is deprecated as of version 0.8. properties: - characterType: - description: Defines well-known database component name, such - as mongos(mongodb), proxy(redis), mariadb(mysql). - type: string componentDefRef: description: |- Used to inject values from other components into the current component. Values will be saved and updated in a diff --git a/controllers/apps/operations/datascript.go b/controllers/apps/operations/datascript.go index 127265862f16..2193b0619025 100644 --- a/controllers/apps/operations/datascript.go +++ b/controllers/apps/operations/datascript.go @@ -89,7 +89,8 @@ func (o DataScriptOpsHandler) Action(reqCtx intctrlutil.RequestCtx, cli client.C // create jobs var jobs []*batchv1.Job - if jobs, err = buildDataScriptJobs(reqCtx, cli, opsResource.Cluster, component, opsRequest, componentDef.CharacterType); err != nil { + // TODO(v1.0): character-type + if jobs, err = buildDataScriptJobs(reqCtx, cli, opsResource.Cluster, component, opsRequest, ""); err != nil { return err } for _, job := range jobs { diff --git a/controllers/apps/transformer_component_tls.go b/controllers/apps/transformer_component_tls.go index 2b1ca1fc3fd4..72aaa246e45c 100644 --- a/controllers/apps/transformer_component_tls.go +++ b/controllers/apps/transformer_component_tls.go @@ -75,7 +75,8 @@ func checkAndTriggerReRender(ctx context.Context, synthesizedComp component.Synt } // TODO: (good-first-issue) don't hard code the tls keyword - tlsKeyword := plan.GetTLSKeyWord(synthesizedComp.CharacterType) + // TODO(v1.0): character-type + tlsKeyword := plan.GetTLSKeyWord(synthesizedComp.ServiceKind) if tlsKeyword == "unsupported-character-type" { return nil } diff --git a/controllers/apps/transformer_component_tls_test.go b/controllers/apps/transformer_component_tls_test.go index a21df0c8cbaf..c1d3c8c775c3 100644 --- a/controllers/apps/transformer_component_tls_test.go +++ b/controllers/apps/transformer_component_tls_test.go @@ -45,12 +45,15 @@ import ( var _ = Describe("TLS self-signed cert function", func() { const ( - clusterDefName = "test-clusterdef-tls" - clusterNamePrefix = "test-cluster" - statefulCompDefName = "mysql" - statefulCompName = "mysql" - mysqlContainerName = "mysql" - configSpecName = "mysql-config-tpl" + compDefName = "test-compdef" + clusterNamePrefix = "test-cluster" + serviceKind = "mysql" + defaultCompName = "mysql" + configTemplateName = "mysql-config-tpl" + ) + + var ( + compDefObj *appsv1alpha1.ComponentDefinition ) ctx := context.Background() @@ -90,13 +93,16 @@ var _ = Describe("TLS self-signed cert function", func() { "resources/mysql-config-constraint.yaml", &appsv1beta1.ConfigConstraint{}) - By("Create a clusterDef obj") - testapps.NewClusterDefFactory(clusterDefName). - SetConnectionCredential(map[string]string{"username": "root", "password": ""}, nil). - AddComponentDef(testapps.ConsensusMySQLComponent, statefulCompDefName). - AddConfigTemplate(configSpecName, configMapObj.Name, configConstraintObj.Name, testCtx.DefaultNamespace, testapps.ConfVolumeName). - AddContainerEnv(mysqlContainerName, corev1.EnvVar{Name: "MYSQL_ALLOW_EMPTY_PASSWORD", Value: "yes"}). - CheckedCreate(&testCtx).GetObject() + By("Create a componentDefinition obj") + compDefObj = testapps.NewComponentDefinitionFactory(compDefName). + WithRandomName(). + AddAnnotations(constant.SkipImmutableCheckAnnotationKey, "true"). + SetDefaultSpec(). + SetServiceKind(serviceKind). + AddConfigTemplate(configTemplateName, configMapObj.Name, configConstraintObj.Name, testCtx.DefaultNamespace, testapps.ConfVolumeName). + AddEnv(testapps.DefaultMySQLContainerName, corev1.EnvVar{Name: "MYSQL_ALLOW_EMPTY_PASSWORD", Value: "yes"}). + Create(&testCtx). + GetObject() }) Context("when issuer is UserProvided", func() { @@ -109,6 +115,7 @@ var _ = Describe("TLS self-signed cert function", func() { Expect(err).Should(BeNil()) Expect(k8sClient.Create(ctx, userProvidedTLSSecretObj)).Should(Succeed()) }) + AfterEach(func() { // delete self provided tls certs secret Expect(k8sClient.Delete(ctx, userProvidedTLSSecretObj)).Should(Succeed()) @@ -119,6 +126,7 @@ var _ = Describe("TLS self-signed cert function", func() { return apierrors.IsNotFound(err) }).Should(BeTrue()) }) + It("should create the cluster when secret referenced exist", func() { tlsIssuer := &appsv1alpha1.Issuer{ Name: appsv1alpha1.IssuerUserProvided, @@ -130,9 +138,9 @@ var _ = Describe("TLS self-signed cert function", func() { }, } By("create cluster obj") - clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterNamePrefix, clusterDefName). + clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterNamePrefix, ""). WithRandomName(). - AddComponent(statefulCompName, statefulCompDefName). + AddComponentV2(defaultCompName, compDefObj.Name). SetReplicas(3). SetTLS(true). SetIssuer(tlsIssuer). @@ -148,9 +156,9 @@ var _ = Describe("TLS self-signed cert function", func() { Context("when switch between disabled and enabled", func() { It("should handle tls settings properly", func() { By("create cluster with tls disabled") - clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterNamePrefix, clusterDefName). + clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterNamePrefix, ""). WithRandomName(). - AddComponent(statefulCompName, statefulCompDefName). + AddComponentV2(defaultCompName, compDefObj.Name). SetReplicas(3). SetTLS(false). Create(&testCtx). @@ -162,14 +170,12 @@ var _ = Describe("TLS self-signed cert function", func() { itsList := testk8s.ListAndCheckInstanceSet(&testCtx, clusterKey) its := itsList.Items[0] - cd := &appsv1alpha1.ClusterDefinition{} - Expect(k8sClient.Get(ctx, types.NamespacedName{Name: clusterDefName, Namespace: testCtx.DefaultNamespace}, cd)).Should(Succeed()) - cmName := cfgcore.GetInstanceCMName(&its, &cd.Spec.ComponentDefs[0].ConfigSpecs[0].ComponentTemplateSpec) + cmName := cfgcore.GetInstanceCMName(&its, &compDefObj.Spec.Configs[0].ComponentTemplateSpec) cmKey := client.ObjectKey{Namespace: its.Namespace, Name: cmName} hasTLSSettings := func() bool { cm := &corev1.ConfigMap{} Expect(k8sClient.Get(ctx, cmKey, cm)).Should(Succeed()) - tlsKeyWord := plan.GetTLSKeyWord("mysql") + tlsKeyWord := plan.GetTLSKeyWord(serviceKind) for _, cfgFile := range cm.Data { index := strings.Index(cfgFile, tlsKeyWord) if index >= 0 { @@ -208,6 +214,7 @@ var _ = Describe("TLS self-signed cert function", func() { Eventually(testapps.CheckObjExists(&testCtx, clusterKey, &appsv1alpha1.Cluster{}, false)).Should(Succeed()) }) }) + Context("when issuer is KubeBlocks check secret exists or not", func() { var ( kbTLSSecretObj *corev1.Secret @@ -215,6 +222,7 @@ var _ = Describe("TLS self-signed cert function", func() { dag *graph.DAG err error ) + BeforeEach(func() { synthesizedComp = component.SynthesizedComponent{ Namespace: testCtx.DefaultNamespace, @@ -232,6 +240,7 @@ var _ = Describe("TLS self-signed cert function", func() { Expect(err).Should(BeNil()) Expect(k8sClient.Create(ctx, kbTLSSecretObj)).Should(Succeed()) }) + AfterEach(func() { // delete self provided tls certs secret Expect(k8sClient.Delete(ctx, kbTLSSecretObj)).Should(Succeed()) @@ -242,6 +251,7 @@ var _ = Describe("TLS self-signed cert function", func() { return apierrors.IsNotFound(err) }).Should(BeTrue()) }) + It("should skip if the existence of the secret is confirmed", func() { err := buildTLSCert(ctx, k8sClient, synthesizedComp, dag) Expect(err).Should(BeNil()) diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml index f191a94ca575..97d6a3fce778 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml @@ -89,10 +89,6 @@ spec: Deprecated: Use ComponentDefinition instead. This type is deprecated as of version 0.8. properties: - characterType: - description: Defines well-known database component name, such - as mongos(mongodb), proxy(redis), mariadb(mysql). - type: string componentDefRef: description: |- Used to inject values from other components into the current component. Values will be saved and updated in a diff --git a/docs/developer_docs/api-reference/cluster.md b/docs/developer_docs/api-reference/cluster.md index 342160e32e8b..662c938c79a1 100644 --- a/docs/developer_docs/api-reference/cluster.md +++ b/docs/developer_docs/api-reference/cluster.md @@ -4066,18 +4066,6 @@ WorkloadType -characterType
    - -string - - - -(Optional) -

    Defines well-known database component name, such as mongos(mongodb), proxy(redis), mariadb(mysql).

    - - - - configSpecs
    diff --git a/pkg/constant/lorry.go b/pkg/constant/lorry.go index 63e1561d280b..834aca324822 100644 --- a/pkg/constant/lorry.go +++ b/pkg/constant/lorry.go @@ -25,22 +25,11 @@ const ( LorryContainerName = "lorry" LorryInitContainerName = "init-lorry" RoleProbeContainerName = "kb-checkrole" - StatusProbeContainerName = "kb-checkstatus" - RunningProbeContainerName = "kb-checkrunning" VolumeProtectionProbeContainerName = "kb-volume-protection" LorryRoleProbePath = "/v1.0/checkrole" LorryVolumeProtectPath = "/v1.0/volumeprotection" ) -const ( - PostgreSQLCharacterType = "postgresql" - MySQLCharacterType = "mysql" - RedisCharacterType = "redis" - MongoDBCharacterType = "mongodb" - ETCDCharacterType = "etcd" - PolarDBXCharacterType = "polardbx" -) - // action keys const ( RoleProbeAction = "roleProbe" @@ -56,6 +45,3 @@ const ( DataDumpAction = "dataDump" DataLoadAction = "dataLoad" ) - -// action envs -const () diff --git a/pkg/controller/component/definition_convertor.go b/pkg/controller/component/definition_convertor.go index 4d0c6e96261c..618ad016574c 100644 --- a/pkg/controller/component/definition_convertor.go +++ b/pkg/controller/component/definition_convertor.go @@ -86,8 +86,7 @@ func (c *compDefDescriptionConvertor) convert(args ...any) (any, error) { type compDefServiceKindConvertor struct{} func (c *compDefServiceKindConvertor) convert(args ...any) (any, error) { - clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - return clusterCompDef.CharacterType, nil + return "", nil } // compDefServiceVersionConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.ServiceVersion. @@ -462,38 +461,8 @@ func (c *compDefLifecycleActionsConvertor) convert(args ...any) (any, error) { return lifecycleActions, nil // TODO } -func (c *compDefLifecycleActionsConvertor) convertBuiltinActionHandler(clusterCompDef *appsv1alpha1.ClusterComponentDefinition) appsv1alpha1.BuiltinActionHandlerType { - if clusterCompDef == nil || clusterCompDef.CharacterType == "" { - return appsv1alpha1.UnknownBuiltinActionHandler - } - switch clusterCompDef.CharacterType { - case constant.MySQLCharacterType: - if clusterCompDef.WorkloadType == appsv1alpha1.Consensus { - return appsv1alpha1.WeSQLBuiltinActionHandler - } else { - return appsv1alpha1.MySQLBuiltinActionHandler - } - case constant.PostgreSQLCharacterType: - if clusterCompDef.WorkloadType == appsv1alpha1.Consensus { - return appsv1alpha1.ApeCloudPostgresqlBuiltinActionHandler - } else { - return appsv1alpha1.PostgresqlBuiltinActionHandler - } - case constant.RedisCharacterType: - return appsv1alpha1.RedisBuiltinActionHandler - case constant.MongoDBCharacterType: - return appsv1alpha1.MongoDBBuiltinActionHandler - case constant.ETCDCharacterType: - return appsv1alpha1.ETCDBuiltinActionHandler - case constant.PolarDBXCharacterType: - return appsv1alpha1.PolarDBXBuiltinActionHandler - default: - return appsv1alpha1.UnknownBuiltinActionHandler - } -} - func (c *compDefLifecycleActionsConvertor) convertRoleProbe(clusterCompDef *appsv1alpha1.ClusterComponentDefinition) *appsv1alpha1.Probe { - builtinHandler := c.convertBuiltinActionHandler(clusterCompDef) + builtinHandler := appsv1alpha1.UnknownBuiltinActionHandler // if RSMSpec has role probe CustomHandler, use it first. if clusterCompDef.RSMSpec != nil && clusterCompDef.RSMSpec.RoleProbe != nil && len(clusterCompDef.RSMSpec.RoleProbe.CustomHandler) > 0 { // TODO(xingran): RSMSpec.RoleProbe.CustomHandler support multiple images and commands, but ComponentDefinition.LifeCycleAction.RoleProbe only support one image and command now. diff --git a/pkg/controller/component/definition_convertor_test.go b/pkg/controller/component/definition_convertor_test.go index c92bb304914f..d07e0bc314cc 100644 --- a/pkg/controller/component/definition_convertor_test.go +++ b/pkg/controller/component/definition_convertor_test.go @@ -64,9 +64,8 @@ var _ = Describe("Component Definition Convertor", func() { BeforeEach(func() { clusterCompDef = &appsv1alpha1.ClusterComponentDefinition{ - Name: "mysql", - WorkloadType: appsv1alpha1.Consensus, - CharacterType: "mysql", + Name: "mysql", + WorkloadType: appsv1alpha1.Consensus, ConfigSpecs: []appsv1alpha1.ComponentConfigSpec{ { ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ @@ -266,7 +265,7 @@ var _ = Describe("Component Definition Convertor", func() { convertor := &compDefServiceKindConvertor{} res, err := convertor.convert(clusterCompDef) Expect(err).Should(Succeed()) - Expect(res).Should(Equal(clusterCompDef.CharacterType)) + Expect(res).Should(BeEmpty()) }) It("service version", func() { @@ -718,13 +717,12 @@ var _ = Describe("Component Definition Convertor", func() { Expect(err).Should(Succeed()) actions := res.(*appsv1alpha1.ComponentLifecycleActions) - // mysql + consensus -> wesql - wesqlBuiltinHandler := func() *appsv1alpha1.BuiltinActionHandlerType { - handler := appsv1alpha1.WeSQLBuiltinActionHandler + builtinHandler := func() *appsv1alpha1.BuiltinActionHandlerType { + handler := appsv1alpha1.UnknownBuiltinActionHandler return &handler } expectedRoleProbe := &appsv1alpha1.Probe{ - BuiltinHandler: wesqlBuiltinHandler(), + BuiltinHandler: builtinHandler(), Action: appsv1alpha1.Action{ TimeoutSeconds: clusterCompDef.Probes.RoleProbe.TimeoutSeconds, }, @@ -758,7 +756,7 @@ var _ = Describe("Component Definition Convertor", func() { actions := res.(*appsv1alpha1.ComponentLifecycleActions) Expect(actions.RoleProbe).ShouldNot(BeNil()) - Expect(*actions.RoleProbe.BuiltinHandler).Should(BeEquivalentTo(appsv1alpha1.WeSQLBuiltinActionHandler)) + Expect(*actions.RoleProbe.BuiltinHandler).Should(BeEquivalentTo(appsv1alpha1.UnknownBuiltinActionHandler)) Expect(actions.RoleProbe.Exec).ShouldNot(BeNil()) Expect(actions.RoleProbe.Exec.Image).Should(BeEquivalentTo("mock-its-role-probe-image")) Expect(actions.RoleProbe.Exec.Command).Should(BeEquivalentTo(mockCommand)) diff --git a/pkg/controller/component/lorry_utils_test.go b/pkg/controller/component/lorry_utils_test.go index 10125cd25c91..ab6686f35da0 100644 --- a/pkg/controller/component/lorry_utils_test.go +++ b/pkg/controller/component/lorry_utils_test.go @@ -47,7 +47,6 @@ var _ = Describe("Lorry Utils", func() { lorryGRPCPort = 50001 component = &SynthesizedComponent{} - component.CharacterType = "mysql" component.ComponentServices = append(component.ComponentServices, appsv1alpha1.ComponentService{ Service: appsv1alpha1.Service{ Spec: corev1.ServiceSpec{ diff --git a/pkg/controller/component/synthesize_component.go b/pkg/controller/component/synthesize_component.go index b13c58da3b46..ffdedc689c63 100644 --- a/pkg/controller/component/synthesize_component.go +++ b/pkg/controller/component/synthesize_component.go @@ -154,6 +154,7 @@ func buildSynthesizedComponent(reqCtx intctrlutil.RequestCtx, Name: compName, FullCompName: comp.Name, CompDefName: compDef.Name, + ServiceKind: compDefObj.Spec.ServiceKind, ServiceVersion: comp.Spec.ServiceVersion, ClusterGeneration: clusterGeneration(cluster, comp), UserDefinedLabels: comp.Spec.Labels, @@ -623,7 +624,6 @@ func buildBackwardCompatibleFields(reqCtx intctrlutil.RequestCtx, buildWorkload := func() { synthesizeComp.ClusterDefName = clusterDef.Name synthesizeComp.ClusterCompDefName = clusterCompDef.Name - synthesizeComp.CharacterType = clusterCompDef.CharacterType synthesizeComp.HorizontalScalePolicy = clusterCompDef.HorizontalScalePolicy } diff --git a/pkg/controller/component/type.go b/pkg/controller/component/type.go index dfe03057bb4c..9eb5cc488b04 100644 --- a/pkg/controller/component/type.go +++ b/pkg/controller/component/type.go @@ -30,14 +30,15 @@ import ( ) type SynthesizedComponent struct { - Namespace string `json:"namespace,omitempty"` - ClusterName string `json:"clusterName,omitempty"` - ClusterUID string `json:"clusterUID,omitempty"` - ClusterGeneration string `json:"clusterGeneration,omitempty"` - Comp2CompDefs map[string]string `json:"comp2CompDefs,omitempty"` // {compName: compDefName} - Name string `json:"name,omitempty"` // the name of the component w/o clusterName prefix - FullCompName string `json:"fullCompName,omitempty"` // the full name of the component w/ clusterName prefix - CompDefName string `json:"compDefName,omitempty"` // the name of the componentDefinition + Namespace string `json:"namespace,omitempty"` + ClusterName string `json:"clusterName,omitempty"` + ClusterUID string `json:"clusterUID,omitempty"` + ClusterGeneration string `json:"clusterGeneration,omitempty"` + Comp2CompDefs map[string]string `json:"comp2CompDefs,omitempty"` // {compName: compDefName} + Name string `json:"name,omitempty"` // the name of the component w/o clusterName prefix + FullCompName string `json:"fullCompName,omitempty"` // the full name of the component w/ clusterName prefix + CompDefName string `json:"compDefName,omitempty"` // the name of the componentDefinition + ServiceKind string ServiceVersion string `json:"serviceVersion,omitempty"` Replicas int32 `json:"replicas"` Resources corev1.ResourceRequirements `json:"resources,omitempty"` @@ -79,7 +80,6 @@ type SynthesizedComponent struct { // TODO(xingran): The following fields will be deprecated after KubeBlocks version 0.8.0 ClusterDefName string `json:"clusterDefName,omitempty"` // the name of the clusterDefinition ClusterCompDefName string `json:"clusterCompDefName,omitempty"` // the name of the clusterDefinition.Spec.ComponentDefs[*].Name - CharacterType string `json:"characterType,omitempty"` HorizontalScalePolicy *v1alpha1.HorizontalScalePolicy `json:"horizontalScalePolicy,omitempty"` EnabledLogs []string `json:"enabledLogs,omitempty"` } diff --git a/pkg/controller/factory/builder_test.go b/pkg/controller/factory/builder_test.go index afb141f9b393..902a7e80eaa7 100644 --- a/pkg/controller/factory/builder_test.go +++ b/pkg/controller/factory/builder_test.go @@ -49,7 +49,6 @@ var _ = Describe("builder", func() { const mysqlCompDefName = "replicasets" const proxyCompDefName = "proxy" const mysqlCompName = "mysql" - const mysqlCharacterType = "mysql" allFieldsClusterDefObj := func(needCreate bool) *appsv1alpha1.ClusterDefinition { By("By assure an clusterDefinition obj") @@ -279,7 +278,6 @@ var _ = Describe("builder", func() { By("set workload type to Consensus") clusterDef.Spec.ComponentDefs[0].WorkloadType = appsv1alpha1.Consensus - clusterDef.Spec.ComponentDefs[0].CharacterType = mysqlCharacterType clusterDef.Spec.ComponentDefs[0].ConsensusSpec = appsv1alpha1.NewConsensusSetSpec() clusterDef.Spec.ComponentDefs[0].ConsensusSpec.UpdateStrategy = appsv1alpha1.BestEffortParallelStrategy cluster.Spec.ComponentSpecs[0].Replicas = 3 diff --git a/pkg/controller/plan/tls_utils.go b/pkg/controller/plan/tls_utils.go index 84fb2f0da0c0..6fff1a84a612 100644 --- a/pkg/controller/plan/tls_utils.go +++ b/pkg/controller/plan/tls_utils.go @@ -115,8 +115,8 @@ func CheckTLSSecretRef(ctx context.Context, cli client.Reader, namespace string, return nil } -func GetTLSKeyWord(cType string) string { - switch cType { +func GetTLSKeyWord(kind string) string { + switch strings.ToLower(kind) { case "mysql": return "ssl_cert" case "postgresql": diff --git a/pkg/testutil/apps/componentdefinition_factory.go b/pkg/testutil/apps/componentdefinition_factory.go index fdd05a97fe04..78af67ccc69c 100644 --- a/pkg/testutil/apps/componentdefinition_factory.go +++ b/pkg/testutil/apps/componentdefinition_factory.go @@ -57,6 +57,11 @@ func (f *MockComponentDefinitionFactory) SetDescription(description string) *Moc return f } +func (f *MockComponentDefinitionFactory) SetServiceKind(serviceKind string) *MockComponentDefinitionFactory { + f.Get().Spec.ServiceKind = serviceKind + return f +} + func (f *MockComponentDefinitionFactory) SetServiceVersion(serviceVersion string) *MockComponentDefinitionFactory { f.Get().Spec.ServiceVersion = serviceVersion return f diff --git a/pkg/testutil/apps/constant.go b/pkg/testutil/apps/constant.go index 499534d921fc..6d134e8660f0 100644 --- a/pkg/testutil/apps/constant.go +++ b/pkg/testutil/apps/constant.go @@ -77,8 +77,7 @@ var ( } statelessNginxComponent = appsv1alpha1.ClusterComponentDefinition{ - WorkloadType: appsv1alpha1.Stateless, - CharacterType: "stateless", + WorkloadType: appsv1alpha1.Stateless, Probes: &appsv1alpha1.ClusterDefinitionProbes{ RoleProbe: &appsv1alpha1.ClusterDefinitionProbe{ FailureThreshold: 3, @@ -160,8 +159,7 @@ var ( } statefulMySQLComponent = appsv1alpha1.ClusterComponentDefinition{ - WorkloadType: appsv1alpha1.Stateful, - CharacterType: "mysql", + WorkloadType: appsv1alpha1.Stateful, Probes: &appsv1alpha1.ClusterDefinitionProbes{ RoleProbe: &appsv1alpha1.ClusterDefinitionProbe{ FailureThreshold: 3, @@ -201,7 +199,6 @@ var ( consensusMySQLComponent = appsv1alpha1.ClusterComponentDefinition{ WorkloadType: appsv1alpha1.Consensus, - CharacterType: "mysql", ConsensusSpec: &defaultConsensusSpec, Probes: &appsv1alpha1.ClusterDefinitionProbes{ RoleProbe: &appsv1alpha1.ClusterDefinitionProbe{ @@ -425,8 +422,7 @@ var ( } replicationRedisComponent = appsv1alpha1.ClusterComponentDefinition{ - WorkloadType: appsv1alpha1.Replication, - CharacterType: "redis", + WorkloadType: appsv1alpha1.Replication, Probes: &appsv1alpha1.ClusterDefinitionProbes{ RoleProbe: &appsv1alpha1.ClusterDefinitionProbe{ FailureThreshold: 3, From 23d1defc1f682c5ea7b0733777091cc6edea2148 Mon Sep 17 00:00:00 2001 From: Leon Date: Mon, 5 Aug 2024 11:14:25 +0800 Subject: [PATCH 32/45] chore: remove comp and service reference from cd (#7768) --- apis/apps/v1alpha1/cluster_types.go | 11 - apis/apps/v1alpha1/cluster_types_test.go | 9 - apis/apps/v1alpha1/clusterdefinition_types.go | 115 ------- apis/apps/v1alpha1/zz_generated.deepcopy.go | 71 ----- ...apps.kubeblocks.io_clusterdefinitions.yaml | 169 ----------- .../apps/transformer_component_vars.go | 5 - ...apps.kubeblocks.io_clusterdefinitions.yaml | 169 ----------- docs/developer_docs/api-reference/cluster.md | 252 +--------------- .../component/definition_convertor.go | 3 +- .../component/definition_convertor_test.go | 5 +- pkg/controller/component/fieldref_util.go | 177 ----------- .../component/fieldref_util_test.go | 194 ------------ .../service_descriptor_utils_test.go | 219 +------------- .../component/service_reference_test.go | 280 ------------------ .../component/synthesize_component.go | 6 - pkg/controller/component/type.go | 40 ++- pkg/testutil/apps/clusterdef_factory.go | 21 -- 17 files changed, 27 insertions(+), 1719 deletions(-) delete mode 100644 pkg/controller/component/fieldref_util.go delete mode 100644 pkg/controller/component/fieldref_util_test.go delete mode 100644 pkg/controller/component/service_reference_test.go diff --git a/apis/apps/v1alpha1/cluster_types.go b/apis/apps/v1alpha1/cluster_types.go index 4fe8b6c0d12c..c1c49e02baee 100644 --- a/apis/apps/v1alpha1/cluster_types.go +++ b/apis/apps/v1alpha1/cluster_types.go @@ -1600,17 +1600,6 @@ func (r ClusterSpec) ValidateEnabledLogs(cd *ClusterDefinition) error { return nil } -// GetDefNameMappingComponents returns ComponentDefRef name mapping ClusterComponentSpec. -func (r ClusterSpec) GetDefNameMappingComponents() map[string][]ClusterComponentSpec { - m := map[string][]ClusterComponentSpec{} - for _, c := range r.ComponentSpecs { - v := m[c.ComponentDefRef] - v = append(v, c) - m[c.ComponentDefRef] = v - } - return m -} - // GetMessage gets message map deep copy object. func (r ClusterComponentStatus) GetMessage() ComponentMessageMap { messageMap := map[string]string{} diff --git a/apis/apps/v1alpha1/cluster_types_test.go b/apis/apps/v1alpha1/cluster_types_test.go index 701772ba09de..ee6b15946cf4 100644 --- a/apis/apps/v1alpha1/cluster_types_test.go +++ b/apis/apps/v1alpha1/cluster_types_test.go @@ -136,15 +136,6 @@ var _ = Describe("", func() { Expect(r.GetVolumeClaimNames(compName)).Should(ContainElement(fmt.Sprintf("%s-%s-%s-%d", compName, r.Name, compName, 0))) }) - It("test GetDefNameMappingComponents", func() { - r := ClusterSpec{} - key := "comp-def-ref" - comp := ClusterComponentSpec{} - comp.ComponentDefRef = key - r.ComponentSpecs = []ClusterComponentSpec{comp} - Expect(r.GetDefNameMappingComponents()[key]).Should(ContainElement(comp)) - }) - It("test SetComponentStatus", func() { r := ClusterStatus{} status := ClusterComponentStatus{} diff --git a/apis/apps/v1alpha1/clusterdefinition_types.go b/apis/apps/v1alpha1/clusterdefinition_types.go index e97934889d10..5f1d19ef4627 100644 --- a/apis/apps/v1alpha1/clusterdefinition_types.go +++ b/apis/apps/v1alpha1/clusterdefinition_types.go @@ -588,21 +588,6 @@ type ClusterComponentDefinition struct { // // +optional PostStartSpec *PostStartAction `json:"postStartSpec,omitempty"` - - // Used to inject values from other components into the current component. Values will be saved and updated in a - // configmap and mounted to the current component. - // - // +patchMergeKey=componentDefName - // +patchStrategy=merge,retainKeys - // +listType=map - // +listMapKey=componentDefName - // +optional - ComponentDefRef []ComponentDefRef `json:"componentDefRef,omitempty" patchStrategy:"merge" patchMergeKey:"componentDefName"` - - // Used to declare the service reference of the current component. - // - // +optional - ServiceRefDeclarations []ServiceRefDeclaration `json:"serviceRefDeclarations,omitempty"` } func (r *ClusterComponentDefinition) GetStatefulSetWorkload() StatefulSetWorkload { @@ -1229,103 +1214,3 @@ const ( // FailurePolicyFail means that an error will be reported. FailurePolicyFail FailurePolicyType = "Fail" ) - -// ComponentValueFromType specifies the type of component value from which the data is derived. -// -// Deprecated since v0.8. -// -// +enum -// +kubebuilder:validation:Enum={FieldRef,ServiceRef,HeadlessServiceRef} -type ComponentValueFromType string - -const ( - // FromFieldRef refers to the value of a specific field in the object. - FromFieldRef ComponentValueFromType = "FieldRef" - // FromServiceRef refers to a service within the same namespace as the object. - FromServiceRef ComponentValueFromType = "ServiceRef" - // FromHeadlessServiceRef refers to a headless service within the same namespace as the object. - FromHeadlessServiceRef ComponentValueFromType = "HeadlessServiceRef" -) - -// ComponentDefRef is used to select the component and its fields to be referenced. -// -// Deprecated since v0.8. -type ComponentDefRef struct { - // The name of the componentDef to be selected. - // - // +kubebuilder:validation:Required - ComponentDefName string `json:"componentDefName"` - - // Defines the policy to be followed in case of a failure in finding the component. - // - // +kubebuilder:validation:Enum={Ignore,Fail} - // +default="Ignore" - // +optional - FailurePolicy FailurePolicyType `json:"failurePolicy,omitempty"` - - // The values that are to be injected as environment variables into each component. - // - // +kbubebuilder:validation:Required - // +patchMergeKey=name - // +patchStrategy=merge,retainKeys - // +listType=map - // +listMapKey=name - // +optional - ComponentRefEnvs []ComponentRefEnv `json:"componentRefEnv" patchStrategy:"merge" patchMergeKey:"name"` -} - -// ComponentRefEnv specifies name and value of an env. -// -// Deprecated since v0.8. -type ComponentRefEnv struct { - // The name of the env, it must be a C identifier. - // - // +kubebuilder:validation:Required - // +kubebuilder:validation:Pattern=`^[A-Za-z_][A-Za-z0-9_]*$` - Name string `json:"name"` - - // The value of the env. - // - // +optional - Value string `json:"value,omitempty"` - - // The source from which the value of the env. - // - // +optional - ValueFrom *ComponentValueFrom `json:"valueFrom,omitempty"` -} - -// ComponentValueFrom is deprecated since v0.8. -type ComponentValueFrom struct { - // Specifies the source to select. It can be one of three types: `FieldRef`, `ServiceRef`, `HeadlessServiceRef`. - // - // +kubebuilder:validation:Enum={FieldRef,ServiceRef,HeadlessServiceRef} - // +kubebuilder:validation:Required - Type ComponentValueFromType `json:"type"` - - // The jsonpath of the source to select when the Type is `FieldRef`. - // Two objects are registered in the jsonpath: `componentDef` and `components`: - // - // - `componentDef` is the component definition object specified in `componentRef.componentDefName`. - // - `components` are the component list objects referring to the component definition object. - // - // +optional - FieldPath string `json:"fieldPath,omitempty"` - - // Defines the format of each headless service address. - // Three builtin variables can be used as placeholders: `$POD_ORDINAL`, `$POD_FQDN`, `$POD_NAME` - // - // - `$POD_ORDINAL` represents the ordinal of the pod. - // - `$POD_FQDN` represents the fully qualified domain name of the pod. - // - `$POD_NAME` represents the name of the pod. - // - // +kubebuilder:default=="$POD_FQDN" - // +optional - Format string `json:"format,omitempty"` - - // The string used to join the values of headless service addresses. - // - // +kubebuilder:default="," - // +optional - JoinWith string `json:"joinWith,omitempty"` -} diff --git a/apis/apps/v1alpha1/zz_generated.deepcopy.go b/apis/apps/v1alpha1/zz_generated.deepcopy.go index db91aabc8394..a88faf4d5eac 100644 --- a/apis/apps/v1alpha1/zz_generated.deepcopy.go +++ b/apis/apps/v1alpha1/zz_generated.deepcopy.go @@ -481,20 +481,6 @@ func (in *ClusterComponentDefinition) DeepCopyInto(out *ClusterComponentDefiniti *out = new(PostStartAction) (*in).DeepCopyInto(*out) } - if in.ComponentDefRef != nil { - in, out := &in.ComponentDefRef, &out.ComponentDefRef - *out = make([]ComponentDefRef, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.ServiceRefDeclarations != nil { - in, out := &in.ServiceRefDeclarations, &out.ServiceRefDeclarations - *out = make([]ServiceRefDeclaration, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterComponentDefinition. @@ -1389,28 +1375,6 @@ func (in *ComponentConfigSpec) DeepCopy() *ComponentConfigSpec { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ComponentDefRef) DeepCopyInto(out *ComponentDefRef) { - *out = *in - if in.ComponentRefEnvs != nil { - in, out := &in.ComponentRefEnvs, &out.ComponentRefEnvs - *out = make([]ComponentRefEnv, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentDefRef. -func (in *ComponentDefRef) DeepCopy() *ComponentDefRef { - if in == nil { - return nil - } - out := new(ComponentDefRef) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ComponentDefinition) DeepCopyInto(out *ComponentDefinition) { *out = *in @@ -1767,26 +1731,6 @@ func (in *ComponentOps) DeepCopy() *ComponentOps { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ComponentRefEnv) DeepCopyInto(out *ComponentRefEnv) { - *out = *in - if in.ValueFrom != nil { - in, out := &in.ValueFrom, &out.ValueFrom - *out = new(ComponentValueFrom) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentRefEnv. -func (in *ComponentRefEnv) DeepCopy() *ComponentRefEnv { - if in == nil { - return nil - } - out := new(ComponentRefEnv) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ComponentService) DeepCopyInto(out *ComponentService) { *out = *in @@ -2060,21 +2004,6 @@ func (in *ComponentTemplateSpec) DeepCopy() *ComponentTemplateSpec { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ComponentValueFrom) DeepCopyInto(out *ComponentValueFrom) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentValueFrom. -func (in *ComponentValueFrom) DeepCopy() *ComponentValueFrom { - if in == nil { - return nil - } - out := new(ComponentValueFrom) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ComponentVarSelector) DeepCopyInto(out *ComponentVarSelector) { *out = *in diff --git a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml index 97d6a3fce778..6e12486aa79c 100644 --- a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml @@ -89,109 +89,6 @@ spec: Deprecated: Use ComponentDefinition instead. This type is deprecated as of version 0.8. properties: - componentDefRef: - description: |- - Used to inject values from other components into the current component. Values will be saved and updated in a - configmap and mounted to the current component. - items: - description: |- - ComponentDefRef is used to select the component and its fields to be referenced. - - - Deprecated since v0.8. - properties: - componentDefName: - description: The name of the componentDef to be selected. - type: string - componentRefEnv: - description: The values that are to be injected as environment - variables into each component. - items: - description: |- - ComponentRefEnv specifies name and value of an env. - - - Deprecated since v0.8. - properties: - name: - description: The name of the env, it must be a C - identifier. - pattern: ^[A-Za-z_][A-Za-z0-9_]*$ - type: string - value: - description: The value of the env. - type: string - valueFrom: - description: The source from which the value of - the env. - properties: - fieldPath: - description: |- - The jsonpath of the source to select when the Type is `FieldRef`. - Two objects are registered in the jsonpath: `componentDef` and `components`: - - - - `componentDef` is the component definition object specified in `componentRef.componentDefName`. - - `components` are the component list objects referring to the component definition object. - type: string - format: - default: ="$POD_FQDN" - description: |- - Defines the format of each headless service address. - Three builtin variables can be used as placeholders: `$POD_ORDINAL`, `$POD_FQDN`, `$POD_NAME` - - - - `$POD_ORDINAL` represents the ordinal of the pod. - - `$POD_FQDN` represents the fully qualified domain name of the pod. - - `$POD_NAME` represents the name of the pod. - type: string - joinWith: - default: ',' - description: The string used to join the values - of headless service addresses. - type: string - type: - allOf: - - enum: - - FieldRef - - ServiceRef - - HeadlessServiceRef - - enum: - - FieldRef - - ServiceRef - - HeadlessServiceRef - description: 'Specifies the source to select. - It can be one of three types: `FieldRef`, - `ServiceRef`, `HeadlessServiceRef`.' - type: string - required: - - type - type: object - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - failurePolicy: - allOf: - - enum: - - Ignore - - Fail - - enum: - - Ignore - - Fail - description: Defines the policy to be followed in case - of a failure in finding the component. - type: string - required: - - componentDefName - type: object - type: array - x-kubernetes-list-map-keys: - - componentDefName - x-kubernetes-list-type: map configSpecs: description: Defines the template of configurations. items: @@ -8623,72 +8520,6 @@ spec: - protocol x-kubernetes-list-type: map type: object - serviceRefDeclarations: - description: Used to declare the service reference of the current - component. - items: - description: |- - ServiceRefDeclaration represents a reference to a service that can be either provided by a KubeBlocks Cluster - or an external service. - It acts as a placeholder for the actual service reference, which is determined later when a Cluster is created. - - - The purpose of ServiceRefDeclaration is to declare a service dependency without specifying the concrete details - of the service. - It allows for flexibility and abstraction in defining service references within a Component. - By using ServiceRefDeclaration, you can define service dependencies in a declarative manner, enabling loose coupling - and easier management of service references across different components and clusters. - - - Upon Cluster creation, the ServiceRefDeclaration is bound to an actual service through the ServiceRef field, - effectively resolving and connecting to the specified service. - properties: - name: - description: Specifies the name of the ServiceRefDeclaration. - type: string - optional: - description: |- - Specifies whether the service reference can be optional. - - - For an optional service-ref, the component can still be created even if the service-ref is not provided. - type: boolean - serviceRefDeclarationSpecs: - description: |- - Defines a list of constraints and requirements for services that can be bound to this ServiceRefDeclaration - upon Cluster creation. - Each ServiceRefDeclarationSpec defines a ServiceKind and ServiceVersion, - outlining the acceptable service types and versions that are compatible. - - - This flexibility allows a ServiceRefDeclaration to be fulfilled by any one of the provided specs. - For example, if it requires an OLTP database, specs for both MySQL and PostgreSQL are listed, - either MySQL or PostgreSQL services can be used when binding. - items: - properties: - serviceKind: - description: |- - Specifies the type or nature of the service. This should be a well-known application cluster type, such as - {mysql, redis, mongodb}. - The field is case-insensitive and supports abbreviations for some well-known databases. - For instance, both `zk` and `zookeeper` are considered as a ZooKeeper cluster, while `pg`, `postgres`, `postgresql` - are all recognized as a PostgreSQL cluster. - type: string - serviceVersion: - description: |- - Defines the service version of the service reference. This is a regular expression that matches a version number pattern. - For instance, `^8.0.8$`, `8.0.\d{1,2}$`, `^[v\-]*?(\d{1,2}\.){0,3}\d{1,2}$` are all valid patterns. - type: string - required: - - serviceKind - - serviceVersion - type: object - type: array - required: - - name - - serviceRefDeclarationSpecs - type: object - type: array statefulSpec: description: Defines spec for `Stateful` workloads. properties: diff --git a/controllers/apps/transformer_component_vars.go b/controllers/apps/transformer_component_vars.go index ea13a8fd64dd..d3f50d3a7649 100644 --- a/controllers/apps/transformer_component_vars.go +++ b/controllers/apps/transformer_component_vars.go @@ -110,11 +110,6 @@ func generatedComponent4LegacyCluster(transCtx *componentTransformContext) (bool func buildEnvVarsNData(synthesizedComp *component.SynthesizedComponent, vars []corev1.EnvVar, legacy bool) ([]corev1.EnvVar, map[string]string) { envData := make(map[string]string) - if synthesizedComp != nil && synthesizedComp.ComponentRefEnvs != nil { - for _, env := range synthesizedComp.ComponentRefEnvs { - envData[env.Name] = env.Value - } - } // for legacy cluster, don't move direct values into ConfigMap if legacy { diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml index 97d6a3fce778..6e12486aa79c 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml @@ -89,109 +89,6 @@ spec: Deprecated: Use ComponentDefinition instead. This type is deprecated as of version 0.8. properties: - componentDefRef: - description: |- - Used to inject values from other components into the current component. Values will be saved and updated in a - configmap and mounted to the current component. - items: - description: |- - ComponentDefRef is used to select the component and its fields to be referenced. - - - Deprecated since v0.8. - properties: - componentDefName: - description: The name of the componentDef to be selected. - type: string - componentRefEnv: - description: The values that are to be injected as environment - variables into each component. - items: - description: |- - ComponentRefEnv specifies name and value of an env. - - - Deprecated since v0.8. - properties: - name: - description: The name of the env, it must be a C - identifier. - pattern: ^[A-Za-z_][A-Za-z0-9_]*$ - type: string - value: - description: The value of the env. - type: string - valueFrom: - description: The source from which the value of - the env. - properties: - fieldPath: - description: |- - The jsonpath of the source to select when the Type is `FieldRef`. - Two objects are registered in the jsonpath: `componentDef` and `components`: - - - - `componentDef` is the component definition object specified in `componentRef.componentDefName`. - - `components` are the component list objects referring to the component definition object. - type: string - format: - default: ="$POD_FQDN" - description: |- - Defines the format of each headless service address. - Three builtin variables can be used as placeholders: `$POD_ORDINAL`, `$POD_FQDN`, `$POD_NAME` - - - - `$POD_ORDINAL` represents the ordinal of the pod. - - `$POD_FQDN` represents the fully qualified domain name of the pod. - - `$POD_NAME` represents the name of the pod. - type: string - joinWith: - default: ',' - description: The string used to join the values - of headless service addresses. - type: string - type: - allOf: - - enum: - - FieldRef - - ServiceRef - - HeadlessServiceRef - - enum: - - FieldRef - - ServiceRef - - HeadlessServiceRef - description: 'Specifies the source to select. - It can be one of three types: `FieldRef`, - `ServiceRef`, `HeadlessServiceRef`.' - type: string - required: - - type - type: object - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - failurePolicy: - allOf: - - enum: - - Ignore - - Fail - - enum: - - Ignore - - Fail - description: Defines the policy to be followed in case - of a failure in finding the component. - type: string - required: - - componentDefName - type: object - type: array - x-kubernetes-list-map-keys: - - componentDefName - x-kubernetes-list-type: map configSpecs: description: Defines the template of configurations. items: @@ -8623,72 +8520,6 @@ spec: - protocol x-kubernetes-list-type: map type: object - serviceRefDeclarations: - description: Used to declare the service reference of the current - component. - items: - description: |- - ServiceRefDeclaration represents a reference to a service that can be either provided by a KubeBlocks Cluster - or an external service. - It acts as a placeholder for the actual service reference, which is determined later when a Cluster is created. - - - The purpose of ServiceRefDeclaration is to declare a service dependency without specifying the concrete details - of the service. - It allows for flexibility and abstraction in defining service references within a Component. - By using ServiceRefDeclaration, you can define service dependencies in a declarative manner, enabling loose coupling - and easier management of service references across different components and clusters. - - - Upon Cluster creation, the ServiceRefDeclaration is bound to an actual service through the ServiceRef field, - effectively resolving and connecting to the specified service. - properties: - name: - description: Specifies the name of the ServiceRefDeclaration. - type: string - optional: - description: |- - Specifies whether the service reference can be optional. - - - For an optional service-ref, the component can still be created even if the service-ref is not provided. - type: boolean - serviceRefDeclarationSpecs: - description: |- - Defines a list of constraints and requirements for services that can be bound to this ServiceRefDeclaration - upon Cluster creation. - Each ServiceRefDeclarationSpec defines a ServiceKind and ServiceVersion, - outlining the acceptable service types and versions that are compatible. - - - This flexibility allows a ServiceRefDeclaration to be fulfilled by any one of the provided specs. - For example, if it requires an OLTP database, specs for both MySQL and PostgreSQL are listed, - either MySQL or PostgreSQL services can be used when binding. - items: - properties: - serviceKind: - description: |- - Specifies the type or nature of the service. This should be a well-known application cluster type, such as - {mysql, redis, mongodb}. - The field is case-insensitive and supports abbreviations for some well-known databases. - For instance, both `zk` and `zookeeper` are considered as a ZooKeeper cluster, while `pg`, `postgres`, `postgresql` - are all recognized as a PostgreSQL cluster. - type: string - serviceVersion: - description: |- - Defines the service version of the service reference. This is a regular expression that matches a version number pattern. - For instance, `^8.0.8$`, `8.0.\d{1,2}$`, `^[v\-]*?(\d{1,2}\.){0,3}\d{1,2}$` are all valid patterns. - type: string - required: - - serviceKind - - serviceVersion - type: object - type: array - required: - - name - - serviceRefDeclarationSpecs - type: object - type: array statefulSpec: description: Defines spec for `Stateful` workloads. properties: diff --git a/docs/developer_docs/api-reference/cluster.md b/docs/developer_docs/api-reference/cluster.md index 662c938c79a1..a882a91cb360 100644 --- a/docs/developer_docs/api-reference/cluster.md +++ b/docs/developer_docs/api-reference/cluster.md @@ -4279,35 +4279,6 @@ PostStartAction the component becomes ready.

    - - -componentDefRef
    - -
    -[]ComponentDefRef - - - - -(Optional) -

    Used to inject values from other components into the current component. Values will be saved and updated in a -configmap and mounted to the current component.

    - - - - -serviceRefDeclarations
    - - -[]ServiceRefDeclaration - - - - -(Optional) -

    Used to declare the service reference of the current component.

    - -

    ClusterComponentPhase @@ -6860,64 +6831,6 @@ or cluster topology. Examples:

    -

    ComponentDefRef -

    -

    -(Appears on:ClusterComponentDefinition) -

    -
    -

    ComponentDefRef is used to select the component and its fields to be referenced.

    -

    Deprecated since v0.8.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -componentDefName
    - -string - -
    -

    The name of the componentDef to be selected.

    -
    -failurePolicy
    - - -FailurePolicyType - - -
    -(Optional) -

    Defines the policy to be followed in case of a failure in finding the component.

    -
    -componentRefEnv
    - - -[]ComponentRefEnv - - -
    -(Optional) -

    The values that are to be injected as environment variables into each component.

    -

    ComponentDefinitionSpec

    @@ -8046,62 +7959,6 @@ string -

    ComponentRefEnv -

    -

    -(Appears on:ComponentDefRef) -

    -
    -

    ComponentRefEnv specifies name and value of an env.

    -

    Deprecated since v0.8.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -name
    - -string - -
    -

    The name of the env, it must be a C identifier.

    -
    -value
    - -string - -
    -(Optional) -

    The value of the env.

    -
    -valueFrom
    - - -ComponentValueFrom - - -
    -(Optional) -

    The source from which the value of the env.

    -

    ComponentResourceKey (string alias)

    @@ -8968,111 +8825,6 @@ Refers to documents of k8s.ConfigMapVolumeSource.defaultMode for more informatio -

    ComponentValueFrom -

    -

    -(Appears on:ComponentRefEnv) -

    -
    -

    ComponentValueFrom is deprecated since v0.8.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -type
    - - -ComponentValueFromType - - -
    -

    Specifies the source to select. It can be one of three types: FieldRef, ServiceRef, HeadlessServiceRef.

    -
    -fieldPath
    - -string - -
    -(Optional) -

    The jsonpath of the source to select when the Type is FieldRef. -Two objects are registered in the jsonpath: componentDef and components:

    -
      -
    • componentDef is the component definition object specified in componentRef.componentDefName.
    • -
    • components are the component list objects referring to the component definition object.
    • -
    -
    -format
    - -string - -
    -(Optional) -

    Defines the format of each headless service address. -Three builtin variables can be used as placeholders: $POD_ORDINAL, $POD_FQDN, $POD_NAME

    -
      -
    • $POD_ORDINAL represents the ordinal of the pod.
    • -
    • $POD_FQDN represents the fully qualified domain name of the pod.
    • -
    • $POD_NAME represents the name of the pod.
    • -
    -
    -joinWith
    - -string - -
    -(Optional) -

    The string used to join the values of headless service addresses.

    -
    -

    ComponentValueFromType -(string alias)

    -

    -(Appears on:ComponentValueFrom) -

    -
    -

    ComponentValueFromType specifies the type of component value from which the data is derived.

    -

    Deprecated since v0.8.

    -
    - - - - - - - - - - - - - - -
    ValueDescription

    "FieldRef"

    FromFieldRef refers to the value of a specific field in the object.

    -

    "HeadlessServiceRef"

    FromHeadlessServiceRef refers to a headless service within the same namespace as the object.

    -

    "ServiceRef"

    FromServiceRef refers to a service within the same namespace as the object.

    -

    ComponentVarSelector

    @@ -11572,7 +11324,7 @@ in each OpsService definition.

    FailurePolicyType (string alias)

    -(Appears on:ComponentDefRef, OpsAction) +(Appears on:OpsAction)

    FailurePolicyType specifies the type of failure policy.

    @@ -18339,7 +18091,7 @@ string

    ServiceRefDeclaration

    -(Appears on:ClusterComponentDefinition, ComponentDefinitionSpec) +(Appears on:ComponentDefinitionSpec)

    ServiceRefDeclaration represents a reference to a service that can be either provided by a KubeBlocks Cluster diff --git a/pkg/controller/component/definition_convertor.go b/pkg/controller/component/definition_convertor.go index 618ad016574c..107419fe4014 100644 --- a/pkg/controller/component/definition_convertor.go +++ b/pkg/controller/component/definition_convertor.go @@ -423,8 +423,7 @@ func (c *compDefRolesConvertor) convertConsensusRole(clusterCompDef *appsv1alpha type compDefServiceRefDeclarationsConvertor struct{} func (c *compDefServiceRefDeclarationsConvertor) convert(args ...any) (any, error) { - clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - return clusterCompDef.ServiceRefDeclarations, nil + return nil, nil } // compDefLifecycleActionsConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.LifecycleActions. diff --git a/pkg/controller/component/definition_convertor_test.go b/pkg/controller/component/definition_convertor_test.go index d07e0bc314cc..89d27edbd135 100644 --- a/pkg/controller/component/definition_convertor_test.go +++ b/pkg/controller/component/definition_convertor_test.go @@ -241,9 +241,6 @@ var _ = Describe("Component Definition Convertor", func() { }, }, }, - SwitchoverSpec: &appsv1alpha1.SwitchoverSpec{}, - ComponentDefRef: []appsv1alpha1.ComponentDefRef{}, - ServiceRefDeclarations: []appsv1alpha1.ServiceRefDeclaration{}, } }) @@ -768,7 +765,7 @@ var _ = Describe("Component Definition Convertor", func() { convertor := &compDefServiceRefDeclarationsConvertor{} res, err := convertor.convert(clusterCompDef) Expect(err).Should(Succeed()) - Expect(res).Should(BeEquivalentTo(clusterCompDef.ServiceRefDeclarations)) + Expect(res).Should(BeNil()) }) }) }) diff --git a/pkg/controller/component/fieldref_util.go b/pkg/controller/component/fieldref_util.go deleted file mode 100644 index aac03a3e75d4..000000000000 --- a/pkg/controller/component/fieldref_util.go +++ /dev/null @@ -1,177 +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 ( - "bytes" - "fmt" - "strconv" - "strings" - - corev1 "k8s.io/api/core/v1" - "k8s.io/client-go/util/jsonpath" - "k8s.io/klog/v2" - - appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" -) - -func buildComponentRef(clusterDef *appsv1alpha1.ClusterDefinition, - cluster *appsv1alpha1.Cluster, - clusterCompDef *appsv1alpha1.ClusterComponentDefinition, - component *SynthesizedComponent) error { - - compRefs := clusterCompDef.ComponentDefRef - if len(compRefs) == 0 { - return nil - } - - component.ComponentRefEnvs = make([]corev1.EnvVar, 0) - - for _, compRef := range compRefs { - referredComponentDef := clusterDef.GetComponentDefByName(compRef.ComponentDefName) - referredComponents := cluster.Spec.GetDefNameMappingComponents()[compRef.ComponentDefName] - - if referredComponentDef == nil || len(referredComponents) == 0 { - err := fmt.Errorf("failed to match %s in cluster %s", compRef.ComponentDefName, cluster.Name) - if compRef.FailurePolicy == appsv1alpha1.FailurePolicyFail { - return err - } else { - klog.V(1).Info(err.Error()) - continue - } - } - - envMap := make(map[string]string) - for _, refEnv := range compRef.ComponentRefEnvs { - env := corev1.EnvVar{Name: refEnv.Name} - var err error - if len(refEnv.Value) != 0 { - env.Value = refEnv.Value - } else if refEnv.ValueFrom != nil { - switch refEnv.ValueFrom.Type { - case appsv1alpha1.FromFieldRef: - if env.Value, err = resolveFieldRef(refEnv.ValueFrom, referredComponents, referredComponentDef); err != nil { - return err - } - case appsv1alpha1.FromServiceRef: - if env.Value, err = resolveServiceRef(cluster.Name, referredComponents, referredComponentDef); err != nil { - return err - } - case appsv1alpha1.FromHeadlessServiceRef: - if referredComponentDef.WorkloadType == appsv1alpha1.Stateless { - errMsg := fmt.Sprintf("headless service ref is not supported for stateless component, cluster: %s, referred component: %s", cluster.Name, referredComponentDef.Name) - klog.V(1).Infof(errMsg) - if compRef.FailurePolicy == appsv1alpha1.FailurePolicyFail { - return fmt.Errorf(errMsg) - } - } - env.Value = resolveHeadlessServiceFieldRef(refEnv.ValueFrom, cluster, referredComponents) - } - } - - component.ComponentRefEnvs = append(component.ComponentRefEnvs, env) - envMap[env.Name] = env.Value - } - - // for each env in componentRefEnvs, resolve reference - for _, env := range component.ComponentRefEnvs { - val := env.Value - for k, v := range envMap { - val = strings.ReplaceAll(val, fmt.Sprintf("$(%s)", k), v) - } - env.Value = val - } - } - return nil -} - -type referredObject struct { - ComponentDef *appsv1alpha1.ClusterComponentDefinition `json:"componentDef"` - Components []appsv1alpha1.ClusterComponentSpec `json:"components"` -} - -func resolveFieldRef(valueFrom *appsv1alpha1.ComponentValueFrom, components []appsv1alpha1.ClusterComponentSpec, componentDef *appsv1alpha1.ClusterComponentDefinition) (string, error) { - referred := referredObject{ - ComponentDef: componentDef, - Components: components, - } - - if value, err := retrieveValueByJSONPath(referred, valueFrom.FieldPath); err != nil { - return "", err - } else { - return string(value), nil - } -} - -func resolveServiceRef(clusterName string, components []appsv1alpha1.ClusterComponentSpec, componentDef *appsv1alpha1.ClusterComponentDefinition) (string, error) { - if componentDef.Service == nil { - return "", fmt.Errorf("componentDef %s does not have service", componentDef.Name) - } - if len(components) != 1 { - return "", fmt.Errorf("expect one component but got %d for componentDef %s", len(components), componentDef.Name) - } - return fmt.Sprintf("%s-%s", clusterName, components[0].Name), nil -} - -func resolveHeadlessServiceFieldRef(valueFrom *appsv1alpha1.ComponentValueFrom, - cluster *appsv1alpha1.Cluster, components []appsv1alpha1.ClusterComponentSpec) string { - - preDefineVars := []string{"POD_NAME", "POD_FQDN", "POD_ORDINAL"} - - format := valueFrom.Format - if len(format) == 0 { - format = "$(POD_FQDN)" - } - joinWith := valueFrom.JoinWith - if len(joinWith) == 0 { - joinWith = "," - } - - hosts := make([]string, 0) - for _, comp := range components { - for i := int32(0); i < comp.Replicas; i++ { - qualifiedName := fmt.Sprintf("%s-%s", cluster.Name, comp.Name) - podOrdinal := strconv.Itoa(int(i)) - podName := fmt.Sprintf("%s-%s", qualifiedName, podOrdinal) - podFQDN := fmt.Sprintf("%s.%s-headless.%s.svc", podName, qualifiedName, cluster.Namespace) - - valuesToReplace := []string{podName, podFQDN, podOrdinal} - - host := format - for idx, preDefineVar := range preDefineVars { - host = strings.ReplaceAll(host, "$("+preDefineVar+")", valuesToReplace[idx]) - } - hosts = append(hosts, host) - } - } - return strings.Join(hosts, joinWith) -} - -func retrieveValueByJSONPath(jsonObj interface{}, jpath string) ([]byte, error) { - path := jsonpath.New("jsonpath") - if err := path.Parse(fmt.Sprintf("{%s}", jpath)); err != nil { - return nil, fmt.Errorf("failed to parse jsonpath %s", jpath) - } - buff := bytes.NewBuffer([]byte{}) - if err := path.Execute(buff, jsonObj); err != nil { - return nil, fmt.Errorf("failed to execute jsonpath %s", jpath) - } - return buff.Bytes(), nil -} diff --git a/pkg/controller/component/fieldref_util_test.go b/pkg/controller/component/fieldref_util_test.go deleted file mode 100644 index 47e9d49cef09..000000000000 --- a/pkg/controller/component/fieldref_util_test.go +++ /dev/null @@ -1,194 +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 ( - "fmt" - "strings" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" - testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" -) - -var _ = Describe("ComponentRef Fields Tests", func() { - const clusterDefName = "test-clusterdef" - const clusterName = "test-cluster" - const clusterNamespace = "test-compref" - const mysqlCompDefName = "mysql-def" - const referredCompDefName = "maxscale-def" - - const mysqlCompName = "mysql" - const referredCompName = "maxscale" - - Context("test fieldRef", func() { - var clusterDefBuilder *testapps.MockClusterDefFactory - var clusterBuilder *testapps.MockClusterFactory - - BeforeEach(func() { - By("create cluster definition builder") - clusterDefBuilder = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). - AddComponentDef(testapps.StatefulMySQLComponent, referredCompDefName) - - // add one mysql component - clusterDefBuilder = clusterDefBuilder.AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName) - - By("create cluster builder") - clusterBuilder = testapps.NewClusterFactory(clusterNamespace, clusterName, clusterDefName) - }) - - It("test fieldref", func() { - clusterDef := clusterDefBuilder.GetObject() - - By("add one component to cluster") - clusterBuilder = clusterBuilder.AddComponent(mysqlCompName, mysqlCompDefName).AddComponent(referredCompName, referredCompDefName) - cluster := clusterBuilder.GetObject() - - componentDef := clusterDef.GetComponentDefByName(referredCompDefName) - Expect(componentDef).NotTo(BeNil()) - components := cluster.Spec.GetDefNameMappingComponents()[referredCompDefName] - Expect(len(components)).To(Equal(1)) - - By("lookup component name, should success") - valueFrom := &appsv1alpha1.ComponentValueFrom{ - Type: appsv1alpha1.FromFieldRef, - FieldPath: "$.components[0].name", - } - value, err := resolveFieldRef(valueFrom, components, componentDef) - Expect(err).To(BeNil()) - Expect(value).To(Equal(referredCompName)) - - By("lookup componentSpec name, should success") - valueFrom = &appsv1alpha1.ComponentValueFrom{ - Type: appsv1alpha1.FromFieldRef, - FieldPath: "$.componentDef.name", - } - value, err = resolveFieldRef(valueFrom, components, componentDef) - Expect(err).To(BeNil()) - Expect(value).To(Equal(referredCompDefName)) - - By("invalid json path, should fail") - valueFrom = &appsv1alpha1.ComponentValueFrom{ - Type: appsv1alpha1.FromFieldRef, - FieldPath: "$.invalidField.name", - } - _, err = resolveFieldRef(valueFrom, components, componentDef) - Expect(err).ShouldNot(BeNil()) - }) - - It("test invalid serviceRef with no service", func() { - clusterDef := clusterDefBuilder.GetObject() - - By("add one component to cluster") - clusterBuilder = clusterBuilder.AddComponent(mysqlCompName, mysqlCompDefName).AddComponent(referredCompName, referredCompDefName) - cluster := clusterBuilder.GetObject() - - componentDef := clusterDef.GetComponentDefByName(referredCompDefName) - Expect(componentDef).NotTo(BeNil()) - components := cluster.Spec.GetDefNameMappingComponents()[referredCompDefName] - Expect(len(components)).To(Equal(1)) - - By("lookup service name, should fail") - _, err := resolveServiceRef(cluster.Name, components, componentDef) - if componentDef.Service != nil { - Expect(err).To(BeNil()) - } else { - Expect(err).NotTo(BeNil()) - Expect(err.Error()).To(ContainSubstring("does not have service")) - } - }) - - It("test invalid serviceRef with multiple components", func() { - clusterDef := clusterDefBuilder.GetObject() - - By("add one component to cluster") - clusterBuilder = clusterBuilder. - AddComponent(mysqlCompName, mysqlCompDefName). - AddComponent(referredCompName, referredCompDefName). - // add component one more time - AddComponent("oneMoreComp", referredCompDefName) - cluster := clusterBuilder.GetObject() - - componentDef := clusterDef.GetComponentDefByName(referredCompDefName) - Expect(componentDef).NotTo(BeNil()) - components := cluster.Spec.GetDefNameMappingComponents()[referredCompDefName] - Expect(len(components)).To(Equal(2)) - - By("lookup service name, should fail") - _, err := resolveServiceRef(cluster.Name, components, componentDef) - Expect(err).NotTo(BeNil()) - Expect(err.Error()).To(ContainSubstring("expect one component but got")) - }) - - It("test serviceRef with correct setting", func() { - clusterDef := clusterDefBuilder.AddNamedServicePort("mysql", 3306).GetObject() - - By("add one component to cluster") - clusterBuilder = clusterBuilder. - AddComponent(mysqlCompName, mysqlCompDefName). - AddComponent(referredCompName, referredCompDefName) - cluster := clusterBuilder.GetObject() - - componentDef := clusterDef.GetComponentDefByName(referredCompDefName) - Expect(componentDef).NotTo(BeNil()) - components := cluster.Spec.GetDefNameMappingComponents()[referredCompDefName] - Expect(len(components)).To(Equal(1)) - - By("lookup service name, should fail") - value, err := resolveServiceRef(cluster.Name, components, componentDef) - Expect(err).To(BeNil()) - Expect(value).To(Equal(fmt.Sprintf("%s-%s", cluster.Name, referredCompName))) - }) - - It("test headlessServiceSvc", func() { - clusterDef := clusterDefBuilder.GetObject() - - By("add one component to cluster") - var replicas int32 = 3 - clusterBuilder = clusterBuilder. - AddComponent(mysqlCompName, mysqlCompDefName). - AddComponent(referredCompName, referredCompDefName).SetReplicas(replicas) - cluster := clusterBuilder.GetObject() - - componentDef := clusterDef.GetComponentDefByName(referredCompDefName) - Expect(componentDef).NotTo(BeNil()) - - components := cluster.Spec.GetDefNameMappingComponents()[referredCompDefName] - Expect(len(components)).To(Equal(1)) - - By("construct headless service name") - valueFrom := &appsv1alpha1.ComponentValueFrom{ - Type: appsv1alpha1.FromHeadlessServiceRef, - Format: "", - JoinWith: "", - } - - value := resolveHeadlessServiceFieldRef(valueFrom, cluster, components) - addrs := strings.Split(value, ",") - Expect(len(addrs)).To(Equal(int(replicas))) - for i, addr := range addrs { - Expect(addr).To(Equal(fmt.Sprintf("%s-%s-%d.%s-%s-headless.%s.svc", cluster.Name, referredCompName, i, cluster.Name, referredCompName, cluster.Namespace))) - } - }) - }) -}) diff --git a/pkg/controller/component/service_descriptor_utils_test.go b/pkg/controller/component/service_descriptor_utils_test.go index 991142b60a1e..5da22e782bb3 100644 --- a/pkg/controller/component/service_descriptor_utils_test.go +++ b/pkg/controller/component/service_descriptor_utils_test.go @@ -20,7 +20,6 @@ along with this program. If not, see . package component import ( - "context" "fmt" "strings" @@ -28,7 +27,6 @@ import ( . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -36,7 +34,6 @@ import ( "github.com/apecloud/kubeblocks/pkg/constant" "github.com/apecloud/kubeblocks/pkg/generics" testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" - testutil "github.com/apecloud/kubeblocks/pkg/testutil/k8s" ) var _ = Describe("build service references", func() { @@ -60,97 +57,20 @@ var _ = Describe("build service references", func() { } var ( - mockClient *testutil.K8sClientMockHelper - clusterDef *appsv1alpha1.ClusterDefinition - cluster *appsv1alpha1.Cluster - beReferencedCluster *appsv1alpha1.Cluster - ) - - var ( - namespace = "default" - clusterName = "cluster" - beReferencedClusterName = "cluster-be-referenced" - clusterDefName = "test-cd" - nginxCompName = "nginx" - nginxCompDefName = "nginx" - mysqlCompName = "mysql" - mysqlCompDefName = "mysql" - externalServiceDescriptorName = "mock-external-service-descriptor-name" - externalServiceDescriptorKind = "redis" - externalServiceDescriptorVersion = "7.0.1" - internalClusterServiceRefKind = "mysql" - internalClusterServiceRefVersion = "8.0.2" - secretName = constant.GenerateDefaultConnCredential(beReferencedClusterName) - redisServiceRefDeclarationName = "redis" - mysqlServiceRefDeclarationName = "mysql" + namespace = "default" + clusterName = "cluster" ) BeforeEach(func() { cleanEnv() - mockClient = testutil.NewK8sMockClient() }) AfterEach(func() { - mockClient.Finish() cleanEnv() }) - buildServiceReferences4Test := func(ctx context.Context, - cli client.Reader, - clusterDef *appsv1alpha1.ClusterDefinition, - cluster *appsv1alpha1.Cluster, - clusterCompSpec *appsv1alpha1.ClusterComponentSpec) (map[string]*appsv1alpha1.ServiceDescriptor, error) { - var ( - compDef *appsv1alpha1.ComponentDefinition - comp *appsv1alpha1.Component - err error - ) - if compDef, err = BuildComponentDefinition(clusterDef, clusterCompSpec); err != nil { - return nil, err - } - if comp, err = BuildComponent(cluster, clusterCompSpec, nil, nil); err != nil { - return nil, err - } - synthesizedComp := &SynthesizedComponent{ - Namespace: namespace, - ClusterName: cluster.Name, - } - if err = buildServiceReferencesWithoutResolve(ctx, cli, synthesizedComp, compDef, comp); err != nil { - return nil, err - } - return synthesizedComp.ServiceReferences, nil - } - - // for test GetContainerWithVolumeMount - Context("generate service descriptor test", func() { - BeforeEach(func() { - serviceRefDeclarations := []appsv1alpha1.ServiceRefDeclaration{ - { - Name: redisServiceRefDeclarationName, - ServiceRefDeclarationSpecs: []appsv1alpha1.ServiceRefDeclarationSpec{ - { - ServiceKind: externalServiceDescriptorKind, - ServiceVersion: externalServiceDescriptorVersion, - }, - }, - }, - { - Name: mysqlServiceRefDeclarationName, - ServiceRefDeclarationSpecs: []appsv1alpha1.ServiceRefDeclarationSpec{ - { - ServiceKind: internalClusterServiceRefKind, - ServiceVersion: internalClusterServiceRefVersion, - }, - }, - }, - } - clusterDef = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatelessNginxComponent, nginxCompDefName). - AddServiceRefDeclarations(serviceRefDeclarations). - Create(&testCtx).GetObject() - }) - - It("serviceRefDeclaration serviceVersion regex validation test", func() { + Context("service descriptor", func() { + It("service version regex validation test", func() { type versionCmp struct { serviceRefDeclRegex string serviceDescriptorVersion string @@ -214,137 +134,6 @@ var _ = Describe("build service references", func() { Expect(match).Should(Equal(tt.want)) } }) - - It("generate service descriptor test", func() { - By("Create cluster and beReferencedCluster object") - beReferencedCluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, beReferencedClusterName, clusterDef.Name). - AddComponent(mysqlCompName, mysqlCompDefName). - Create(&testCtx).GetObject() - - serviceRefs := []appsv1alpha1.ServiceRef{ - { - Name: redisServiceRefDeclarationName, - ServiceDescriptor: externalServiceDescriptorName, - }, - { - Name: mysqlServiceRefDeclarationName, - Cluster: beReferencedCluster.Name, - }, - } - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). - AddComponent(nginxCompName, nginxCompDefName). - SetServiceRefs(serviceRefs). - Create(&testCtx).GetObject() - - By("GenServiceReferences failed because external service descriptor not found") - serviceReferences, err := buildServiceReferences4Test(testCtx.Ctx, testCtx.Cli, clusterDef, cluster, &cluster.Spec.ComponentSpecs[0]) - Expect(err).ShouldNot(Succeed()) - Expect(apierrors.IsNotFound(err)).Should(BeTrue()) - Expect(serviceReferences).Should(BeNil()) - - By("create external service descriptor") - endpoint := appsv1alpha1.CredentialVar{ - Value: "mock-endpoint", - } - host := appsv1alpha1.CredentialVar{ - Value: "mock-host", - } - port := appsv1alpha1.CredentialVar{ - Value: "mock-port", - } - auth := appsv1alpha1.ConnectionCredentialAuth{ - Username: &appsv1alpha1.CredentialVar{ - Value: "mock-username", - }, - Password: &appsv1alpha1.CredentialVar{ - Value: "mock-password", - }, - } - externalServiceDescriptor := testapps.NewServiceDescriptorFactory(testCtx.DefaultNamespace, externalServiceDescriptorName). - SetEndpoint(endpoint). - SetHost(host). - SetPort(port). - SetAuth(auth). - Create(&testCtx).GetObject() - - By("GenServiceReferences failed because external service descriptor status is not available") - serviceReferences, err = buildServiceReferences4Test(testCtx.Ctx, testCtx.Cli, clusterDef, cluster, &cluster.Spec.ComponentSpecs[0]) - Expect(err).ShouldNot(Succeed()) - Expect(err.Error()).Should(ContainSubstring("status is not available")) - Expect(serviceReferences).Should(BeNil()) - - By("update external service descriptor status to available") - Expect(testapps.ChangeObjStatus(&testCtx, externalServiceDescriptor, func() { - externalServiceDescriptor.Status.Phase = appsv1alpha1.AvailablePhase - })).Should(Succeed()) - - By("GenServiceReferences failed because external service descriptor kind and version not match") - serviceReferences, err = buildServiceReferences4Test(testCtx.Ctx, testCtx.Cli, clusterDef, cluster, &cluster.Spec.ComponentSpecs[0]) - Expect(err).ShouldNot(Succeed()) - Expect(err.Error()).Should(ContainSubstring("kind or version is not match with")) - Expect(serviceReferences).Should(BeNil()) - - By("update external service descriptor kind and version") - Expect(testapps.ChangeObj(&testCtx, externalServiceDescriptor, func(externalServiceDescriptor *appsv1alpha1.ServiceDescriptor) { - externalServiceDescriptor.Spec.ServiceKind = externalServiceDescriptorKind - externalServiceDescriptor.Spec.ServiceVersion = externalServiceDescriptorVersion - })).Should(Succeed()) - - By("GenServiceReferences succeed because external service descriptor found and internal cluster reference found") - secret := &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: secretName, - Namespace: namespace, - }, - Data: map[string][]byte{ - constant.ServiceDescriptorEndpointKey: []byte("my-mysql-0.default.svc.cluster.local:3306"), - constant.ServiceDescriptorHostKey: []byte("my-mysql-0.default.svc.cluster.local"), - constant.ServiceDescriptorPortKey: []byte("3306"), - constant.ServiceDescriptorUsernameKey: []byte("cm9vdA=="), - constant.ServiceDescriptorPasswordKey: []byte("NHpycWZsMnI="), - }, - } - Expect(testCtx.CheckedCreateObj(ctx, secret)).Should(Succeed()) - Expect(k8sClient.Get(context.Background(), client.ObjectKey{Name: secret.Name, - Namespace: secret.Namespace}, secret)).Should(Succeed()) - serviceReferences, err = buildServiceReferences4Test(testCtx.Ctx, testCtx.Cli, clusterDef, cluster, &cluster.Spec.ComponentSpecs[0]) - Expect(err).Should(Succeed()) - Expect(serviceReferences).ShouldNot(BeNil()) - Expect(len(serviceReferences)).Should(Equal(2)) - Expect(serviceReferences[redisServiceRefDeclarationName]).ShouldNot(BeNil()) - Expect(serviceReferences[redisServiceRefDeclarationName].Spec.Endpoint).ShouldNot(BeNil()) - Expect(serviceReferences[redisServiceRefDeclarationName].Spec.Endpoint.Value).ShouldNot(BeEmpty()) - Expect(serviceReferences[redisServiceRefDeclarationName].Spec.Endpoint.ValueFrom).Should(BeNil()) - Expect(serviceReferences[redisServiceRefDeclarationName].Spec.Host).ShouldNot(BeNil()) - Expect(serviceReferences[redisServiceRefDeclarationName].Spec.Host.Value).ShouldNot(BeEmpty()) - Expect(serviceReferences[redisServiceRefDeclarationName].Spec.Host.ValueFrom).Should(BeNil()) - Expect(serviceReferences[redisServiceRefDeclarationName].Spec.Port).ShouldNot(BeNil()) - Expect(serviceReferences[redisServiceRefDeclarationName].Spec.Port.Value).ShouldNot(BeEmpty()) - Expect(serviceReferences[redisServiceRefDeclarationName].Spec.Port.ValueFrom).Should(BeNil()) - Expect(serviceReferences[redisServiceRefDeclarationName].Spec.Auth).ShouldNot(BeNil()) - Expect(serviceReferences[redisServiceRefDeclarationName].Spec.Auth.Username.Value).ShouldNot(BeEmpty()) - Expect(serviceReferences[redisServiceRefDeclarationName].Spec.Auth.Username.ValueFrom).Should(BeNil()) - Expect(serviceReferences[redisServiceRefDeclarationName].Spec.Auth.Password.Value).ShouldNot(BeEmpty()) - Expect(serviceReferences[redisServiceRefDeclarationName].Spec.Auth.Password.ValueFrom).Should(BeNil()) - - Expect(serviceReferences[mysqlServiceRefDeclarationName]).ShouldNot(BeNil()) - Expect(serviceReferences[mysqlServiceRefDeclarationName].Spec.Endpoint).ShouldNot(BeNil()) - Expect(serviceReferences[mysqlServiceRefDeclarationName].Spec.Endpoint.Value).Should(BeEmpty()) - Expect(serviceReferences[mysqlServiceRefDeclarationName].Spec.Endpoint.ValueFrom).ShouldNot(BeNil()) - Expect(serviceReferences[mysqlServiceRefDeclarationName].Spec.Endpoint.ValueFrom.SecretKeyRef).ShouldNot(BeNil()) - Expect(serviceReferences[mysqlServiceRefDeclarationName].Spec.Host).Should(BeNil()) // reference to a legacy cluster - Expect(serviceReferences[mysqlServiceRefDeclarationName].Spec.Port).ShouldNot(BeNil()) - Expect(serviceReferences[mysqlServiceRefDeclarationName].Spec.Port.Value).Should(BeEmpty()) - Expect(serviceReferences[mysqlServiceRefDeclarationName].Spec.Port.ValueFrom).ShouldNot(BeNil()) - Expect(serviceReferences[mysqlServiceRefDeclarationName].Spec.Port.ValueFrom.SecretKeyRef).ShouldNot(BeNil()) - Expect(serviceReferences[mysqlServiceRefDeclarationName].Spec.Auth).ShouldNot(BeNil()) - Expect(serviceReferences[mysqlServiceRefDeclarationName].Spec.Auth.Username.Value).Should(BeEmpty()) - Expect(serviceReferences[mysqlServiceRefDeclarationName].Spec.Auth.Username.ValueFrom).ShouldNot(BeNil()) - Expect(serviceReferences[mysqlServiceRefDeclarationName].Spec.Auth.Username.ValueFrom.SecretKeyRef).ShouldNot(BeNil()) - Expect(serviceReferences[mysqlServiceRefDeclarationName].Spec.Auth.Password.Value).Should(BeEmpty()) - Expect(serviceReferences[mysqlServiceRefDeclarationName].Spec.Auth.Password.ValueFrom).ShouldNot(BeNil()) - Expect(serviceReferences[mysqlServiceRefDeclarationName].Spec.Auth.Password.ValueFrom.SecretKeyRef).ShouldNot(BeNil()) - }) }) Context("service reference from new cluster objects", func() { diff --git a/pkg/controller/component/service_reference_test.go b/pkg/controller/component/service_reference_test.go deleted file mode 100644 index d444ff697b96..000000000000 --- a/pkg/controller/component/service_reference_test.go +++ /dev/null @@ -1,280 +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 ( - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/log" - - appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" - "github.com/apecloud/kubeblocks/pkg/constant" - intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" - "github.com/apecloud/kubeblocks/pkg/generics" - testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" - testutil "github.com/apecloud/kubeblocks/pkg/testutil/k8s" -) - -var _ = Describe("service reference", 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, - // in race conditions, it will find the existence of old objects, resulting failure to - // create the new objects. - By("clean resources") - - inNS := client.InNamespace(testCtx.DefaultNamespace) - ml := client.HasLabels{testCtx.TestObjLabelKey} - - // resources should be released in following order - // non-namespaced - testapps.ClearResources(&testCtx, generics.ConfigConstraintSignature, ml) - testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.ClusterDefinitionSignature, true, ml) - - // namespaced - testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.ConfigMapSignature, true, inNS, ml) - testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.ServiceDescriptorSignature, true, inNS, ml) - } - - var ( - mockClient *testutil.K8sClientMockHelper - clusterDef *appsv1alpha1.ClusterDefinition - cluster *appsv1alpha1.Cluster - beReferencedCluster *appsv1alpha1.Cluster - beReferencedServiceDescriptor *appsv1alpha1.ServiceDescriptor - ) - - var ( - namespace = "default" - clusterName = "mycluster" - beReferencedClusterName = "mycluster-be-referenced" - clusterDefName = "test-clusterdef" - nginxCompName = "nginx" - nginxCompDefName = "nginx" - mysqlCompName = "mysql" - mysqlCompDefName = "mysql" - externalServiceDescriptorName = "mock-external-service-descriptor-name" - externalServiceDescriptorKind = "redis" - externalServiceDescriptorVersion = "7.0.1" - internalClusterServiceRefKind = "mysql" - internalClusterServiceRefVersion = "8.0.2" - redisServiceRefDeclarationName = "redis" - mysqlServiceRefDeclarationName = "mysql" - - serviceRefEndpointValue = "my-mysql-0.default.svc.cluster.local:3306" - serviceRefHostValue = "my-mysql-0.default.svc.cluster.local" - serviceRefPortValue = "3306" - serviceRefUsernameValue = "mock-username" - serviceRefPasswordValue = "mock-password" - ) - - BeforeEach(func() { - cleanEnv() - mockClient = testutil.NewK8sMockClient() - serviceRefDeclarations := []appsv1alpha1.ServiceRefDeclaration{ - { - Name: redisServiceRefDeclarationName, - ServiceRefDeclarationSpecs: []appsv1alpha1.ServiceRefDeclarationSpec{ - { - ServiceKind: externalServiceDescriptorKind, - ServiceVersion: externalServiceDescriptorVersion, - }, - }, - }, - { - Name: mysqlServiceRefDeclarationName, - ServiceRefDeclarationSpecs: []appsv1alpha1.ServiceRefDeclarationSpec{ - { - ServiceKind: internalClusterServiceRefKind, - ServiceVersion: internalClusterServiceRefVersion, - }, - }, - }, - } - clusterDef = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatelessNginxComponent, nginxCompDefName). - AddServiceRefDeclarations(serviceRefDeclarations). - Create(&testCtx).GetObject() - - By("mock a service descriptor and the configmap referenced") - configMap := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: beReferencedClusterName + "-configmap-ref", - Namespace: namespace, - }, - Data: map[string]string{ - constant.ServiceDescriptorEndpointKey: serviceRefEndpointValue, - constant.ServiceDescriptorHostKey: serviceRefHostValue, - constant.ServiceDescriptorPortKey: serviceRefPortValue, - constant.ServiceDescriptorUsernameKey: serviceRefUsernameValue, - constant.ServiceDescriptorPasswordKey: serviceRefPasswordValue, - }, - } - Expect(testCtx.CheckedCreateObj(ctx, configMap)).Should(Succeed()) - beReferencedServiceDescriptor = testapps.NewServiceDescriptorFactory(testCtx.DefaultNamespace, externalServiceDescriptorName). - SetServiceKind(externalServiceDescriptorKind). - SetServiceVersion(externalServiceDescriptorVersion). - SetEndpoint(appsv1alpha1.CredentialVar{ - ValueFrom: &corev1.EnvVarSource{ - ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ - Key: constant.ServiceDescriptorEndpointKey, - LocalObjectReference: corev1.LocalObjectReference{ - Name: configMap.Name, - }, - }, - }, - }). - SetHost(appsv1alpha1.CredentialVar{ - ValueFrom: &corev1.EnvVarSource{ - ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ - Key: constant.ServiceDescriptorHostKey, - LocalObjectReference: corev1.LocalObjectReference{ - Name: configMap.Name, - }, - }, - }, - }). - SetPort(appsv1alpha1.CredentialVar{ - ValueFrom: &corev1.EnvVarSource{ - ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ - Key: constant.ServiceDescriptorPortKey, - LocalObjectReference: corev1.LocalObjectReference{ - Name: configMap.Name, - }, - }, - }, - }). - SetAuth(appsv1alpha1.ConnectionCredentialAuth{ - Username: &appsv1alpha1.CredentialVar{ - ValueFrom: &corev1.EnvVarSource{ - ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ - Key: constant.ServiceDescriptorUsernameKey, - LocalObjectReference: corev1.LocalObjectReference{ - Name: configMap.Name, - }, - }, - }, - }, - Password: &appsv1alpha1.CredentialVar{ - ValueFrom: &corev1.EnvVarSource{ - ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ - Key: constant.ServiceDescriptorPasswordKey, - LocalObjectReference: corev1.LocalObjectReference{ - Name: configMap.Name, - }, - }, - }, - }, - }). - Create(&testCtx). - GetObject() - Eventually(testapps.GetAndChangeObjStatus(&testCtx, client.ObjectKeyFromObject(beReferencedServiceDescriptor), - func(sd *appsv1alpha1.ServiceDescriptor) { - sd.Status.Phase = appsv1alpha1.AvailablePhase - })).Should(Succeed()) - - By("mock a cluster and the (conn credential) secret for referenced") - secret := &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: constant.GenerateDefaultConnCredential(beReferencedClusterName), - Namespace: namespace, - }, - Data: map[string][]byte{ - constant.ServiceDescriptorEndpointKey: []byte(serviceRefEndpointValue), - constant.ServiceDescriptorHostKey: []byte(serviceRefHostValue), - constant.ServiceDescriptorPortKey: []byte(serviceRefPortValue), - constant.ServiceDescriptorUsernameKey: []byte(serviceRefUsernameValue), - constant.ServiceDescriptorPasswordKey: []byte(serviceRefPasswordValue), - }, - } - Expect(testCtx.CheckedCreateObj(ctx, secret)).Should(Succeed()) - beReferencedCluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, beReferencedClusterName, clusterDef.Name). - AddComponent(mysqlCompName, mysqlCompDefName). - Create(&testCtx). - GetObject() - - serviceRefs := []appsv1alpha1.ServiceRef{ - { - Name: redisServiceRefDeclarationName, - ServiceDescriptor: beReferencedServiceDescriptor.Name, - }, - { - Name: mysqlServiceRefDeclarationName, - Cluster: beReferencedCluster.Name, - }, - } - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). - AddComponent(nginxCompName, nginxCompDefName). - SetServiceRefs(serviceRefs). - Create(&testCtx).GetObject() - }) - - AfterEach(func() { - mockClient.Finish() - cleanEnv() - }) - - Context("service reference test", func() { - It("service reference test", func() { - clusterKey := client.ObjectKeyFromObject(cluster) - req := ctrl.Request{ - NamespacedName: clusterKey, - } - reqCtx := intctrlutil.RequestCtx{ - Ctx: testCtx.Ctx, - Req: req, - Log: log.FromContext(ctx).WithValues("cluster", req.NamespacedName), - } - component, err := BuildSynthesizedComponentWrapper(reqCtx, testCtx.Cli, cluster, &cluster.Spec.ComponentSpecs[0]) - Expect(err).Should(Succeed()) - Expect(component).ShouldNot(BeNil()) - Expect(component.ServiceReferences).ShouldNot(BeNil()) - - err = resolveServiceReferences(ctx, k8sClient, component) - Expect(err).Should(Succeed()) - Expect(component.ServiceReferences).ShouldNot(BeNil()) - Expect(component.ServiceReferences[redisServiceRefDeclarationName].Spec.Endpoint.Value).Should(Equal(serviceRefEndpointValue)) - Expect(component.ServiceReferences[redisServiceRefDeclarationName].Spec.Endpoint.ValueFrom).Should(BeNil()) - Expect(component.ServiceReferences[redisServiceRefDeclarationName].Spec.Host.Value).Should(Equal(serviceRefHostValue)) - Expect(component.ServiceReferences[redisServiceRefDeclarationName].Spec.Host.ValueFrom).Should(BeNil()) - Expect(component.ServiceReferences[redisServiceRefDeclarationName].Spec.Port.Value).Should(Equal(serviceRefPortValue)) - Expect(component.ServiceReferences[redisServiceRefDeclarationName].Spec.Port.ValueFrom).Should(BeNil()) - Expect(component.ServiceReferences[redisServiceRefDeclarationName].Spec.Auth.Username.Value).Should(BeEmpty()) - Expect(component.ServiceReferences[redisServiceRefDeclarationName].Spec.Auth.Username.ValueFrom.ConfigMapKeyRef).ShouldNot(BeNil()) - Expect(component.ServiceReferences[redisServiceRefDeclarationName].Spec.Auth.Password.Value).Should(BeEmpty()) - Expect(component.ServiceReferences[redisServiceRefDeclarationName].Spec.Auth.Password.ValueFrom.ConfigMapKeyRef).ShouldNot(BeNil()) - - Expect(component.ServiceReferences[mysqlServiceRefDeclarationName].Spec.Endpoint.Value).Should(Equal(serviceRefEndpointValue)) - Expect(component.ServiceReferences[mysqlServiceRefDeclarationName].Spec.Endpoint.ValueFrom).Should(BeNil()) - Expect(component.ServiceReferences[mysqlServiceRefDeclarationName].Spec.Host).Should(BeNil()) // reference to a legacy cluster - Expect(component.ServiceReferences[mysqlServiceRefDeclarationName].Spec.Port.Value).Should(Equal(serviceRefPortValue)) - Expect(component.ServiceReferences[mysqlServiceRefDeclarationName].Spec.Port.ValueFrom).Should(BeNil()) - Expect(component.ServiceReferences[mysqlServiceRefDeclarationName].Spec.Auth.Username.Value).Should(BeEmpty()) - Expect(component.ServiceReferences[mysqlServiceRefDeclarationName].Spec.Auth.Username.ValueFrom.SecretKeyRef).ShouldNot(BeNil()) - Expect(component.ServiceReferences[mysqlServiceRefDeclarationName].Spec.Auth.Password.Value).Should(BeEmpty()) - Expect(component.ServiceReferences[mysqlServiceRefDeclarationName].Spec.Auth.Password.ValueFrom.SecretKeyRef).ShouldNot(BeNil()) - }) - }) -}) diff --git a/pkg/controller/component/synthesize_component.go b/pkg/controller/component/synthesize_component.go index ffdedc689c63..3387f6c91bc3 100644 --- a/pkg/controller/component/synthesize_component.go +++ b/pkg/controller/component/synthesize_component.go @@ -668,12 +668,6 @@ func buildBackwardCompatibleFields(reqCtx intctrlutil.RequestCtx, // build pod management policy buildPodManagementPolicy() - // build componentRefEnvs - if err := buildComponentRef(clusterDef, cluster, clusterCompDef, synthesizeComp); err != nil { - reqCtx.Log.Error(err, "failed to merge componentRef") - return err - } - return nil } diff --git a/pkg/controller/component/type.go b/pkg/controller/component/type.go index 9eb5cc488b04..cf611905e692 100644 --- a/pkg/controller/component/type.go +++ b/pkg/controller/component/type.go @@ -30,27 +30,25 @@ import ( ) type SynthesizedComponent struct { - Namespace string `json:"namespace,omitempty"` - ClusterName string `json:"clusterName,omitempty"` - ClusterUID string `json:"clusterUID,omitempty"` - ClusterGeneration string `json:"clusterGeneration,omitempty"` - Comp2CompDefs map[string]string `json:"comp2CompDefs,omitempty"` // {compName: compDefName} - Name string `json:"name,omitempty"` // the name of the component w/o clusterName prefix - FullCompName string `json:"fullCompName,omitempty"` // the full name of the component w/ clusterName prefix - CompDefName string `json:"compDefName,omitempty"` // the name of the componentDefinition - ServiceKind string - ServiceVersion string `json:"serviceVersion,omitempty"` - Replicas int32 `json:"replicas"` - Resources corev1.ResourceRequirements `json:"resources,omitempty"` - PodSpec *corev1.PodSpec `json:"podSpec,omitempty"` - VolumeClaimTemplates []corev1.PersistentVolumeClaimTemplate `json:"volumeClaimTemplates,omitempty"` - LogConfigs []v1alpha1.LogConfig `json:"logConfigs,omitempty"` - ConfigTemplates []v1alpha1.ComponentConfigSpec `json:"configTemplates,omitempty"` - ScriptTemplates []v1alpha1.ComponentTemplateSpec `json:"scriptTemplates,omitempty"` - TLSConfig *v1alpha1.TLSConfig `json:"tlsConfig"` - ServiceAccountName string `json:"serviceAccountName,omitempty"` - // TODO: remove this later - ComponentRefEnvs []corev1.EnvVar `json:"componentRefEnvs,omitempty"` + Namespace string `json:"namespace,omitempty"` + ClusterName string `json:"clusterName,omitempty"` + ClusterUID string `json:"clusterUID,omitempty"` + ClusterGeneration string `json:"clusterGeneration,omitempty"` + Comp2CompDefs map[string]string `json:"comp2CompDefs,omitempty"` // {compName: compDefName} + Name string `json:"name,omitempty"` // the name of the component w/o clusterName prefix + FullCompName string `json:"fullCompName,omitempty"` // the full name of the component w/ clusterName prefix + CompDefName string `json:"compDefName,omitempty"` // the name of the componentDefinition + ServiceKind string + ServiceVersion string `json:"serviceVersion,omitempty"` + Replicas int32 `json:"replicas"` + Resources corev1.ResourceRequirements `json:"resources,omitempty"` + PodSpec *corev1.PodSpec `json:"podSpec,omitempty"` + VolumeClaimTemplates []corev1.PersistentVolumeClaimTemplate `json:"volumeClaimTemplates,omitempty"` + LogConfigs []v1alpha1.LogConfig `json:"logConfigs,omitempty"` + ConfigTemplates []v1alpha1.ComponentConfigSpec `json:"configTemplates,omitempty"` + ScriptTemplates []v1alpha1.ComponentTemplateSpec `json:"scriptTemplates,omitempty"` + TLSConfig *v1alpha1.TLSConfig `json:"tlsConfig"` + ServiceAccountName string `json:"serviceAccountName,omitempty"` ServiceReferences map[string]*v1alpha1.ServiceDescriptor `json:"serviceReferences,omitempty"` UserDefinedLabels map[string]string UserDefinedAnnotations map[string]string diff --git a/pkg/testutil/apps/clusterdef_factory.go b/pkg/testutil/apps/clusterdef_factory.go index 97341627da9a..3db66d11c9ca 100644 --- a/pkg/testutil/apps/clusterdef_factory.go +++ b/pkg/testutil/apps/clusterdef_factory.go @@ -229,15 +229,6 @@ func (factory *MockClusterDefFactory) AddSwitchoverSpec(switchoverSpec *appsv1al return factory } -func (factory *MockClusterDefFactory) AddServiceRefDeclarations(serviceRefDeclarations []appsv1alpha1.ServiceRefDeclaration) *MockClusterDefFactory { - comp := factory.getLastCompDef() - if comp == nil { - return factory - } - comp.ServiceRefDeclarations = serviceRefDeclarations - return factory -} - func (factory *MockClusterDefFactory) AddInitContainerVolumeMounts(containerName string, volumeMounts []corev1.VolumeMount) *MockClusterDefFactory { comp := factory.getLastCompDef() if comp == nil { @@ -265,18 +256,6 @@ func (factory *MockClusterDefFactory) AddReplicationSpec(replicationSpec *appsv1 return factory } -func (factory *MockClusterDefFactory) AddComponentRef(ref *appsv1alpha1.ComponentDefRef) *MockClusterDefFactory { - comp := factory.getLastCompDef() - if comp == nil { - return factory - } - if len(comp.ComponentDefRef) == 0 { - comp.ComponentDefRef = make([]appsv1alpha1.ComponentDefRef, 0) - } - comp.ComponentDefRef = append(comp.ComponentDefRef, *ref) - return factory -} - func (factory *MockClusterDefFactory) AddNamedServicePort(name string, port int32) *MockClusterDefFactory { comp := factory.getLastCompDef() if comp == nil { From 40e12d94628ba2767fa343dcb1452717ccae295c Mon Sep 17 00:00:00 2001 From: zhangtao <111836083+sophon-zt@users.noreply.github.com> Date: Mon, 5 Aug 2024 14:27:34 +0800 Subject: [PATCH 33/45] fix: config-manager tools is not found (#7918) --- .../configuration/tool_image_builder.go | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/pkg/controller/configuration/tool_image_builder.go b/pkg/controller/configuration/tool_image_builder.go index 32701cd517bb..eaa96223c250 100644 --- a/pkg/controller/configuration/tool_image_builder.go +++ b/pkg/controller/configuration/tool_image_builder.go @@ -29,6 +29,7 @@ import ( "github.com/apecloud/kubeblocks/pkg/constant" "github.com/apecloud/kubeblocks/pkg/controller/factory" intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" + "github.com/apecloud/kubeblocks/pkg/generics" viper "github.com/apecloud/kubeblocks/pkg/viperx" ) @@ -101,32 +102,36 @@ func checkAndInstallToolsImageVolume(toolContainers []appsv1beta1.ToolConfig, bu return toolContainers, configManagerBinaryPath } +func containerExists(containers []appsv1beta1.ToolConfig, containerName string) bool { + return generics.CountFunc(containers, func(container appsv1beta1.ToolConfig) bool { + return container.Name == containerName + }) != 0 +} + func checkAndCreateRenderedInitContainer(toolContainers []appsv1beta1.ToolConfig, mountPoint string) []appsv1beta1.ToolConfig { - kbToolsImage := viper.GetString(constant.KBToolsImage) - for _, container := range toolContainers { - if container.Name == initSecRenderedToolContainerName { - return nil - } + if containerExists(toolContainers, initSecRenderedToolContainerName) { + return toolContainers } + + kbToolsImage := viper.GetString(constant.KBToolsImage) toolContainers = append(toolContainers, appsv1beta1.ToolConfig{ Name: initSecRenderedToolContainerName, Image: kbToolsImage, - Command: []string{"cp", constant.ConfigManagerToolPath, mountPoint}, + Command: []string{"cp", constant.TPLRenderToolPath, mountPoint}, }) return toolContainers } func checkAndCreateConfigManagerToolsContainer(toolContainers []appsv1beta1.ToolConfig, mountPoint string) []appsv1beta1.ToolConfig { - kbToolsImage := viper.GetString(constant.KBToolsImage) - for _, container := range toolContainers { - if container.Name == installConfigMangerToolContainerName { - return nil - } + if containerExists(toolContainers, installConfigMangerToolContainerName) { + return toolContainers } + + kbToolsImage := viper.GetString(constant.KBToolsImage) toolContainers = append(toolContainers, appsv1beta1.ToolConfig{ Name: installConfigMangerToolContainerName, Image: kbToolsImage, - Command: []string{"cp", constant.TPLRenderToolPath, mountPoint}, + Command: []string{"cp", constant.ConfigManagerToolPath, mountPoint}, }) return toolContainers } From 5f0cd218c5a45cd7d208ae0b41b2c7444361d49a Mon Sep 17 00:00:00 2001 From: zhangtao <111836083+sophon-zt@users.noreply.github.com> Date: Mon, 5 Aug 2024 14:29:06 +0800 Subject: [PATCH 34/45] fix: user config template patch strategy will discard some files (#7900) --- pkg/controller/configuration/template_merger.go | 8 ++++---- .../configuration/template_merger_test.go | 13 +++++++++++-- pkg/controller/configuration/utils.go | 8 ++++++++ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/pkg/controller/configuration/template_merger.go b/pkg/controller/configuration/template_merger.go index 6d21ebfd814d..b26b30a032c2 100644 --- a/pkg/controller/configuration/template_merger.go +++ b/pkg/controller/configuration/template_merger.go @@ -94,21 +94,21 @@ func (c *configPatcher) Merge(baseData map[string]string, updatedData map[string return baseData, nil } - r := make(map[string]string) + mergedData := copyMap(baseData) params := core.GenerateVisualizedParamsList(configPatch, formatter, nil) for key, patch := range splitParameters(params) { v, ok := baseData[key] if !ok { - r[key] = updatedData[key] + mergedData[key] = updatedData[key] continue } newConfig, err := core.ApplyConfigPatch([]byte(v), patch, formatter) if err != nil { return nil, err } - r[key] = newConfig + mergedData[key] = newConfig } - return r, err + return mergedData, err } func (c *configReplaceMerger) Merge(baseData map[string]string, updatedData map[string]string) (map[string]string, error) { diff --git a/pkg/controller/configuration/template_merger_test.go b/pkg/controller/configuration/template_merger_test.go index e4912793a45f..5077b4713972 100644 --- a/pkg/controller/configuration/template_merger_test.go +++ b/pkg/controller/configuration/template_merger_test.go @@ -56,6 +56,9 @@ xengine_block_cache_size=307 xengine_row_cache_size=102 max_connections=666 ` + + testString := "// this is a test string" + const ( baseCMName = "base-cm" updatedCMName = "updated-cm" @@ -63,6 +66,7 @@ max_connections=666 testConfigSpecName = "test-config" testClusterName = "test-cluster" testConfigName = "my.cnf" + testConfig2Name = "test.txt" ) var ( @@ -82,12 +86,14 @@ max_connections=666 &appsv1beta1.ConfigConstraint{}) baseCMObject = &corev1.ConfigMap{ Data: map[string]string{ - testConfigName: baseConfig, + testConfigName: baseConfig, + testConfig2Name: testString, }, } updatedCMObject = &corev1.ConfigMap{ Data: map[string]string{ - testConfigName: extendConfig, + testConfigName: extendConfig, + testConfig2Name: testString, }, } baseCMObject.SetName(baseCMName) @@ -101,6 +107,7 @@ max_connections=666 TemplateRef: baseCMObject.GetName(), Namespace: "default", }, + Keys: []string{"my.cnf"}, ConfigConstraintRef: configConstraintObj.GetName(), } @@ -141,6 +148,7 @@ max_connections=666 tmpCM := baseCMObject.DeepCopy() mergedData, err := mergerConfigTemplate(importedTemplate, templateBuilder, configSpec, tmpCM.Data, ctx, mockClient.Client()) Expect(err).To(Succeed()) + Expect(mergedData).Should(HaveLen(2)) configReaders, err := cfgcore.LoadRawConfigObject(mergedData, configConstraintObj.Spec.FileFormatConfig, configSpec.Keys) Expect(err).Should(Succeed()) @@ -169,6 +177,7 @@ max_connections=666 tmpCM := baseCMObject.DeepCopy() mergedData, err := mergerConfigTemplate(importedTemplate, templateBuilder, configSpec, tmpCM.Data, ctx, mockClient.Client()) Expect(err).Should(Succeed()) + Expect(mergedData).Should(HaveLen(2)) Expect(reflect.DeepEqual(mergedData, updatedCMObject.Data)).Should(BeTrue()) configReaders, err := cfgcore.LoadRawConfigObject(mergedData, configConstraintObj.Spec.FileFormatConfig, configSpec.Keys) diff --git a/pkg/controller/configuration/utils.go b/pkg/controller/configuration/utils.go index 0b8a7a3b78bd..291637c047da 100644 --- a/pkg/controller/configuration/utils.go +++ b/pkg/controller/configuration/utils.go @@ -30,3 +30,11 @@ func inDataContext() *multicluster.ClientOption { func inDataContextUnspecified() *multicluster.ClientOption { return multicluster.InDataContextUnspecified() } + +func copyMap(data map[string]string) map[string]string { + r := make(map[string]string, len(data)) + for k, v := range data { + r[k] = v + } + return r +} From f67c9f1ebd06ecac4428007264c75755da94578f Mon Sep 17 00:00:00 2001 From: Leon Date: Mon, 5 Aug 2024 17:18:51 +0800 Subject: [PATCH 35/45] chore: remove config & script templates and log configs from cd (#7771) --- apis/apps/v1alpha1/cluster_types.go | 17 -- apis/apps/v1alpha1/cluster_types_test.go | 47 --- apis/apps/v1alpha1/clusterdefinition_types.go | 53 ---- .../v1alpha1/clusterdefinition_types_test.go | 39 --- apis/apps/v1alpha1/zz_generated.deepcopy.go | 19 -- ...apps.kubeblocks.io_clusterdefinitions.yaml | 272 ------------------ controllers/apps/cluster_controller_test.go | 160 +++++------ .../apps/clusterdefinition_controller.go | 6 - .../apps/clusterdefinition_controller_test.go | 73 +---- controllers/apps/component_controller_test.go | 14 +- controllers/apps/configuration/config_util.go | 45 +-- .../apps/configuration/config_util_test.go | 51 ++-- .../configconstraint_controller.go | 2 +- .../configconstraint_controller_test.go | 21 +- .../configuration_controller_test.go | 5 +- .../apps/configuration/configuration_test.go | 68 ++--- .../apps/configuration/policy_util_test.go | 1 - .../apps/operations/reconfigure_test.go | 86 +++--- controllers/apps/operations/suite_test.go | 40 ++- ...apps.kubeblocks.io_clusterdefinitions.yaml | 272 ------------------ docs/developer_docs/api-reference/cluster.md | 48 +--- pkg/configuration/core/configtemplate_util.go | 76 ----- .../core/configtemplate_util_test.go | 171 ----------- .../component/definition_convertor.go | 9 +- .../component/definition_convertor_test.go | 53 +--- .../configuration/configuration_test.go | 64 +++-- .../configuration/envfrom_utils_test.go | 51 ++-- pkg/controller/configuration/operator_test.go | 12 +- pkg/controller/configuration/pipeline_test.go | 12 +- .../configuration/resource_wrapper_test.go | 1 - .../configuration/template_wrapper_test.go | 25 +- .../configuration/tool_image_builder_test.go | 6 +- pkg/controller/instanceset/object_builder.go | 7 +- pkg/controller/plan/restore_test.go | 1 - pkg/kb_agent/cronjobs/checkrole.go | 3 +- pkg/kb_agent/cronjobs/job_test.go | 3 +- pkg/kb_agent/cronjobs/manager_test.go | 5 +- pkg/kb_agent/handlers/exec_handler_test.go | 3 +- pkg/kb_agent/handlers/grpc_handler_test.go | 3 +- pkg/kb_agent/httpserver/apis_test.go | 5 +- pkg/kb_agent/httpserver/server_test.go | 3 +- pkg/lorry/engines/dbmanager_mock.go | 5 +- .../apps/cluster_instance_set_test_util.go | 3 +- pkg/testutil/apps/clusterdef_factory.go | 49 ---- 44 files changed, 365 insertions(+), 1544 deletions(-) delete mode 100644 pkg/configuration/core/configtemplate_util.go delete mode 100644 pkg/configuration/core/configtemplate_util_test.go diff --git a/apis/apps/v1alpha1/cluster_types.go b/apis/apps/v1alpha1/cluster_types.go index c1c49e02baee..6de87bef8045 100644 --- a/apis/apps/v1alpha1/cluster_types.go +++ b/apis/apps/v1alpha1/cluster_types.go @@ -20,7 +20,6 @@ import ( "fmt" "strings" - "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -1584,22 +1583,6 @@ func (r ClusterSpec) GetComponentDefRefName(componentName string) string { return "" } -// ValidateEnabledLogs validates enabledLogs config in cluster.yaml, and returns metav1.Condition when detecting invalid values. -func (r ClusterSpec) ValidateEnabledLogs(cd *ClusterDefinition) error { - message := make([]string, 0) - for _, comp := range r.ComponentSpecs { - invalidLogNames := cd.ValidateEnabledLogConfigs(comp.ComponentDefRef, comp.EnabledLogs) - if len(invalidLogNames) == 0 { - continue - } - message = append(message, fmt.Sprintf("EnabledLogs: %s are not defined in Component: %s of the clusterDefinition", invalidLogNames, comp.Name)) - } - if len(message) > 0 { - return errors.New(strings.Join(message, ";")) - } - return nil -} - // GetMessage gets message map deep copy object. func (r ClusterComponentStatus) GetMessage() ComponentMessageMap { messageMap := map[string]string{} diff --git a/apis/apps/v1alpha1/cluster_types_test.go b/apis/apps/v1alpha1/cluster_types_test.go index ee6b15946cf4..f10136af6722 100644 --- a/apis/apps/v1alpha1/cluster_types_test.go +++ b/apis/apps/v1alpha1/cluster_types_test.go @@ -26,7 +26,6 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/yaml" "github.com/apecloud/kubeblocks/pkg/constant" viper "github.com/apecloud/kubeblocks/pkg/viperx" @@ -199,52 +198,6 @@ var _ = Describe("", func() { }) }) -func TestValidateEnabledLogs(t *testing.T) { - cluster := &Cluster{} - clusterDef := &ClusterDefinition{} - clusterByte := ` -apiVersion: apps.kubeblocks.io/v1alpha1 -kind: Cluster -metadata: - name: wesql -spec: - clusterDefinitionRef: cluster-definition-consensus - componentSpecs: - - name: wesql-test - componentDefRef: replicasets - enabledLogs: [error, slow] -` - clusterDefByte := ` -apiVersion: apps.kubeblocks.io/v1alpha1 -kind: ClusterDefinition -metadata: - name: cluster-definition-consensus -spec: - componentDefs: - - name: replicasets - workloadType: Consensus - logConfigs: - - name: error - filePathPattern: /log/mysql/mysqld.err - - name: slow - filePathPattern: /log/mysql/*slow.log - podSpec: - containers: - - name: mysql - imagePullPolicy: IfNotPresent` - _ = yaml.Unmarshal([]byte(clusterByte), cluster) - _ = yaml.Unmarshal([]byte(clusterDefByte), clusterDef) - // normal case - if err := cluster.Spec.ValidateEnabledLogs(clusterDef); err != nil { - t.Error("Expected empty conditionList") - } - // corner case - cluster.Spec.ComponentSpecs[0].EnabledLogs = []string{"error-test", "slow"} - if err := cluster.Spec.ValidateEnabledLogs(clusterDef); err == nil { - t.Error("Expected one element conditionList") - } -} - func TestGetMessage(t *testing.T) { podKey := "Pod/test-01" compStatus := ClusterComponentStatus{ diff --git a/apis/apps/v1alpha1/clusterdefinition_types.go b/apis/apps/v1alpha1/clusterdefinition_types.go index 5f1d19ef4627..8857e3c31e78 100644 --- a/apis/apps/v1alpha1/clusterdefinition_types.go +++ b/apis/apps/v1alpha1/clusterdefinition_types.go @@ -17,8 +17,6 @@ limitations under the License. package v1alpha1 import ( - "strings" - appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -492,38 +490,11 @@ type ClusterComponentDefinition struct { // +kubebuilder:validation:Required WorkloadType WorkloadType `json:"workloadType"` - // Defines the template of configurations. - // - // +patchMergeKey=name - // +patchStrategy=merge,retainKeys - // +listType=map - // +listMapKey=name - // +optional - ConfigSpecs []ComponentConfigSpec `json:"configSpecs,omitempty"` - - // Defines the template of scripts. - // - // +patchMergeKey=name - // +patchStrategy=merge,retainKeys - // +listType=map - // +listMapKey=name - // +optional - ScriptSpecs []ComponentTemplateSpec `json:"scriptSpecs,omitempty"` - // Settings for health checks. // // +optional Probes *ClusterDefinitionProbes `json:"probes,omitempty"` - // Specify the logging files which can be observed and configured by cluster users. - // - // +patchMergeKey=name - // +patchStrategy=merge,retainKeys - // +listType=map - // +listMapKey=name - // +optional - LogConfigs []LogConfig `json:"logConfigs,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"name"` - // Defines the pod spec template of component. // // +kubebuilder:pruning:PreserveUnknownFields @@ -1168,30 +1139,6 @@ func init() { SchemeBuilder.Register(&ClusterDefinition{}, &ClusterDefinitionList{}) } -// ValidateEnabledLogConfigs validates enabledLogs against component compDefName, and returns the invalid logNames undefined in ClusterDefinition. -func (r *ClusterDefinition) ValidateEnabledLogConfigs(compDefName string, enabledLogs []string) []string { - invalidLogNames := make([]string, 0, len(enabledLogs)) - logTypes := make(map[string]struct{}) - for _, comp := range r.Spec.ComponentDefs { - if !strings.EqualFold(compDefName, comp.Name) { - continue - } - for _, logConfig := range comp.LogConfigs { - logTypes[logConfig.Name] = struct{}{} - } - } - // imply that all values in enabledLogs config are invalid. - if len(logTypes) == 0 { - return enabledLogs - } - for _, name := range enabledLogs { - if _, ok := logTypes[name]; !ok { - invalidLogNames = append(invalidLogNames, name) - } - } - return invalidLogNames -} - // GetComponentDefByName gets component definition from ClusterDefinition with compDefName func (r *ClusterDefinition) GetComponentDefByName(compDefName string) *ClusterComponentDefinition { for _, component := range r.Spec.ComponentDefs { diff --git a/apis/apps/v1alpha1/clusterdefinition_types_test.go b/apis/apps/v1alpha1/clusterdefinition_types_test.go index a4c76f5470f1..02d779097636 100644 --- a/apis/apps/v1alpha1/clusterdefinition_types_test.go +++ b/apis/apps/v1alpha1/clusterdefinition_types_test.go @@ -23,47 +23,8 @@ import ( . "github.com/onsi/gomega" appsv1 "k8s.io/api/apps/v1" - "k8s.io/apimachinery/pkg/util/yaml" ) -func TestValidateEnabledLogConfigs(t *testing.T) { - clusterDef := &ClusterDefinition{} - clusterDefByte := ` -apiVersion: apps.kubeblocks.io/v1alpha1 -kind: ClusterDefinition -metadata: - name: cluster-definition-consensus -spec: - componentDefs: - - name: replicasets - workloadType: Consensus - logConfigs: - - name: error - filePathPattern: /log/mysql/mysqld.err - - name: slow - filePathPattern: /log/mysql/*slow.log - podSpec: - containers: - - name: mysql - imagePullPolicy: IfNotPresent` - _ = yaml.Unmarshal([]byte(clusterDefByte), clusterDef) - // normal case - invalidLogNames := clusterDef.ValidateEnabledLogConfigs("replicasets", []string{"error", "slow"}) - if len(invalidLogNames) != 0 { - t.Error("Expected empty [] invalidLogNames") - } - // corner case - invalidLogNames1 := clusterDef.ValidateEnabledLogConfigs("replicasets", []string{"error", "slow-test", "audit-test"}) - if len(invalidLogNames1) != 2 { - t.Error("Expected invalidLogNames are [slow-test, audit-test]") - } - // corner case - invalidLogNames2 := clusterDef.ValidateEnabledLogConfigs("non-exist-type", []string{"error", "slow", "audit"}) - if len(invalidLogNames2) != 3 { - t.Error("Expected invalidLogNames are [error, slow, audit]") - } -} - func TestGetComponentDefByName(t *testing.T) { componentDefName := "mysqlType" clusterDef := &ClusterDefinition{ diff --git a/apis/apps/v1alpha1/zz_generated.deepcopy.go b/apis/apps/v1alpha1/zz_generated.deepcopy.go index a88faf4d5eac..6060653b9ff3 100644 --- a/apis/apps/v1alpha1/zz_generated.deepcopy.go +++ b/apis/apps/v1alpha1/zz_generated.deepcopy.go @@ -402,30 +402,11 @@ func (in *ClusterComponentConfigSource) DeepCopy() *ClusterComponentConfigSource // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClusterComponentDefinition) DeepCopyInto(out *ClusterComponentDefinition) { *out = *in - if in.ConfigSpecs != nil { - in, out := &in.ConfigSpecs, &out.ConfigSpecs - *out = make([]ComponentConfigSpec, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.ScriptSpecs != nil { - in, out := &in.ScriptSpecs, &out.ScriptSpecs - *out = make([]ComponentTemplateSpec, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } if in.Probes != nil { in, out := &in.Probes, &out.Probes *out = new(ClusterDefinitionProbes) (*in).DeepCopyInto(*out) } - if in.LogConfigs != nil { - in, out := &in.LogConfigs, &out.LogConfigs - *out = make([]LogConfig, len(*in)) - copy(*out, *in) - } if in.PodSpec != nil { in, out := &in.PodSpec, &out.PodSpec *out = new(v1.PodSpec) diff --git a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml index 6e12486aa79c..a361e5925efe 100644 --- a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml @@ -89,187 +89,6 @@ spec: Deprecated: Use ComponentDefinition instead. This type is deprecated as of version 0.8. properties: - configSpecs: - description: Defines the template of configurations. - items: - properties: - asEnvFrom: - description: |- - Specifies the containers to inject the ConfigMap parameters as environment variables. - - - This is useful when application images accept parameters through environment variables and - generate the final configuration file in the startup script based on these variables. - - - This field allows users to specify a list of container names, and KubeBlocks will inject the environment - variables converted from the ConfigMap into these designated containers. This provides a flexible way to - pass the configuration items from the ConfigMap to the container without modifying the image. - - - Deprecated: `asEnvFrom` has been deprecated since 0.9.0 and will be removed in 0.10.0. - Use `injectEnvTo` instead. - items: - type: string - type: array - x-kubernetes-list-type: set - constraintRef: - description: Specifies the name of the referenced configuration - constraints object. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - defaultMode: - description: |- - The operator attempts to set default file permissions for scripts (0555) and configurations (0444). - However, certain database engines may require different file permissions. - You can specify the desired file permissions here. - - - Must be specified as an octal value between 0000 and 0777 (inclusive), - or as a decimal value between 0 and 511 (inclusive). - YAML supports both octal and decimal values for file permissions. - - - Please note that this setting only affects the permissions of the files themselves. - Directories within the specified path are not impacted by this setting. - It's important to be aware that this setting might conflict with other options - that influence the file mode, such as fsGroup. - In such cases, the resulting file mode may have additional bits set. - Refers to documents of k8s.ConfigMapVolumeSource.defaultMode for more information. - format: int32 - type: integer - injectEnvTo: - description: |- - Specifies the containers to inject the ConfigMap parameters as environment variables. - - - This is useful when application images accept parameters through environment variables and - generate the final configuration file in the startup script based on these variables. - - - This field allows users to specify a list of container names, and KubeBlocks will inject the environment - variables converted from the ConfigMap into these designated containers. This provides a flexible way to - pass the configuration items from the ConfigMap to the container without modifying the image. - items: - type: string - type: array - x-kubernetes-list-type: set - keys: - description: |- - Specifies the configuration files within the ConfigMap that support dynamic updates. - - - A configuration template (provided in the form of a ConfigMap) may contain templates for multiple - configuration files. - Each configuration file corresponds to a key in the ConfigMap. - Some of these configuration files may support dynamic modification and reloading without requiring - a pod restart. - - - If empty or omitted, all configuration files in the ConfigMap are assumed to support dynamic updates, - and ConfigConstraint applies to all keys. - items: - type: string - type: array - x-kubernetes-list-type: set - legacyRenderedConfigSpec: - description: |- - Specifies the secondary rendered config spec for pod-specific customization. - - - The template is rendered inside the pod (by the "config-manager" sidecar container) and merged with the main - template's render result to generate the final configuration file. - - - This field is intended to handle scenarios where different pods within the same Component have - varying configurations. It allows for pod-specific customization of the configuration. - - - Note: This field will be deprecated in future versions, and the functionality will be moved to - `cluster.spec.componentSpecs[*].instances[*]`. - properties: - namespace: - default: default - description: |- - Specifies the namespace of the referenced configuration template ConfigMap object. - An empty namespace is equivalent to the "default" namespace. - pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ - type: string - policy: - default: none - description: Defines the strategy for merging externally - imported templates into component templates. - enum: - - patch - - replace - - none - type: string - templateRef: - description: Specifies the name of the referenced - configuration template ConfigMap object. - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - required: - - templateRef - type: object - name: - description: Specifies the name of the configuration template. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - namespace: - default: default - description: |- - Specifies the namespace of the referenced configuration template ConfigMap object. - An empty namespace is equivalent to the "default" namespace. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ - type: string - reRenderResourceTypes: - description: |- - Specifies whether the configuration needs to be re-rendered after v-scale or h-scale operations to reflect changes. - - - In some scenarios, the configuration may need to be updated to reflect the changes in resource allocation - or cluster topology. Examples: - - - - Redis: adjust maxmemory after v-scale operation. - - MySQL: increase max connections after v-scale operation. - - Zookeeper: update zoo.cfg with new node addresses after h-scale operation. - items: - description: RerenderResourceType defines the resource - requirements for a component. - enum: - - vscale - - hscale - - tls - type: string - type: array - x-kubernetes-list-type: set - templateRef: - description: Specifies the name of the referenced configuration - template ConfigMap object. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - volumeName: - description: |- - Refers to the volume name of PodTemplate. The configuration file produced through the configuration - template will be mounted to the corresponding volume. Must be a DNS_LABEL name. - The volume name must be defined in podSpec.containers[*].volumeMounts. - maxLength: 63 - pattern: ^[a-z]([a-z0-9\-]*[a-z0-9])?$ - type: string - required: - - name - - volumeName - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map consensusSpec: description: Defines spec for `Consensus` workloads. It's required if the workload type is `Consensus`. @@ -459,38 +278,6 @@ spec: This only works if Type is not None. If not specified, the first volumeMount will be selected. type: string type: object - logConfigs: - description: Specify the logging files which can be observed - and configured by cluster users. - items: - properties: - filePathPattern: - description: |- - Specifies the paths or patterns identifying where the log files are stored. - This field allows the system to locate and manage log files effectively. - - - Examples: - - - - /home/postgres/pgdata/pgroot/data/log/postgresql-* - - /data/mysql/log/mysqld-error.log - maxLength: 4096 - type: string - name: - description: |- - Specifies a descriptive label for the log type, such as 'slow' for a MySQL slow log file. - It provides a clear identification of the log's purpose and content. - maxLength: 128 - type: string - required: - - filePathPattern - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map name: description: |- This name could be used as default name of `cluster.spec.componentSpecs.name`, and needs to conform with same @@ -8390,65 +8177,6 @@ spec: type: object type: array type: object - scriptSpecs: - description: Defines the template of scripts. - items: - properties: - defaultMode: - description: |- - The operator attempts to set default file permissions for scripts (0555) and configurations (0444). - However, certain database engines may require different file permissions. - You can specify the desired file permissions here. - - - Must be specified as an octal value between 0000 and 0777 (inclusive), - or as a decimal value between 0 and 511 (inclusive). - YAML supports both octal and decimal values for file permissions. - - - Please note that this setting only affects the permissions of the files themselves. - Directories within the specified path are not impacted by this setting. - It's important to be aware that this setting might conflict with other options - that influence the file mode, such as fsGroup. - In such cases, the resulting file mode may have additional bits set. - Refers to documents of k8s.ConfigMapVolumeSource.defaultMode for more information. - format: int32 - type: integer - name: - description: Specifies the name of the configuration template. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - namespace: - default: default - description: |- - Specifies the namespace of the referenced configuration template ConfigMap object. - An empty namespace is equivalent to the "default" namespace. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ - type: string - templateRef: - description: Specifies the name of the referenced configuration - template ConfigMap object. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - volumeName: - description: |- - Refers to the volume name of PodTemplate. The configuration file produced through the configuration - template will be mounted to the corresponding volume. Must be a DNS_LABEL name. - The volume name must be defined in podSpec.containers[*].volumeMounts. - maxLength: 63 - pattern: ^[a-z]([a-z0-9\-]*[a-z0-9])?$ - type: string - required: - - name - - volumeName - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map service: description: Defines the service spec. properties: diff --git a/controllers/apps/cluster_controller_test.go b/controllers/apps/cluster_controller_test.go index e27356d2c56f..5654438c91d5 100644 --- a/controllers/apps/cluster_controller_test.go +++ b/controllers/apps/cluster_controller_test.go @@ -48,16 +48,15 @@ import ( var _ = Describe("Cluster Controller", func() { const ( - clusterDefName = "test-clusterdef" - compDefName = "test-compdef" - compVersionName = "test-compversion" - clusterName = "test-cluster" // this become cluster prefix name if used with testapps.NewClusterFactory().WithRandomName() - consensusCompName = "consensus" - consensusCompDefName = "consensus" - multiConsensusCompName = "consensus1" - defaultServiceVersion = "8.0.31-r0" - latestServiceVersion = "8.0.31-r1" - defaultShardCount = 2 + clusterDefName = "test-clusterdef" + compDefName = "test-compdef" + compVersionName = "test-compversion" + clusterName = "test-cluster" + defaultCompName = "default" + defaultClusterCompDefName = "default" // TODO: remove this + defaultServiceVersion = "8.0.31-r0" + latestServiceVersion = "8.0.31-r1" + defaultShardCount = 2 ) var ( @@ -72,26 +71,24 @@ var _ = Describe("Cluster Controller", func() { Default: true, Components: []appsv1alpha1.ClusterTopologyComponent{ { - Name: consensusCompName, + Name: defaultCompName, CompDef: compDefName, // prefix }, }, } ) - resetViperCfg := func() { + resetTestContext := func() { + clusterDefObj = nil + compDefObj = nil + compVersionObj = nil + clusterObj = nil if allSettings != nil { Expect(viper.MergeConfigMap(allSettings)).ShouldNot(HaveOccurred()) allSettings = nil } } - resetTestContext := func() { - clusterDefObj = nil - clusterObj = nil - resetViperCfg() - } - // Cleanups cleanEnv := func() { // must wait till resources deleted and no longer existed before the testcases start, @@ -135,14 +132,7 @@ var _ = Describe("Cluster Controller", func() { return str } - createAllWorkloadTypesClusterDef := func(noCreateAssociateCV ...bool) { - By("Create a clusterDefinition obj") - clusterDefObj = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.ConsensusMySQLComponent, consensusCompDefName). - AddClusterTopology(defaultTopology). - Create(&testCtx). - GetObject() - + createAllDefinitionObjects := func() { By("Create a componentDefinition obj") compDefObj = testapps.NewComponentDefinitionFactory(compDefName). WithRandomName(). @@ -150,9 +140,6 @@ var _ = Describe("Cluster Controller", func() { Create(&testCtx). GetObject() - By("Create a bpt obj") - createBackupPolicyTpl(clusterDefObj, compDefObj.Name) - By("Create a componentVersion obj") compVersionObj = testapps.NewComponentVersionFactory(compVersionName). SetSpec(appsv1alpha1.ComponentVersionSpec{ @@ -184,12 +171,17 @@ var _ = Describe("Cluster Controller", func() { Create(&testCtx). GetObject() + By("Create a clusterDefinition obj") + clusterDefObj = testapps.NewClusterDefFactory(clusterDefName). + AddComponentDef(testapps.ConsensusMySQLComponent, defaultClusterCompDefName). + AddClusterTopology(defaultTopology). + Create(&testCtx). + GetObject() + + By("Create a bpt obj") + createBackupPolicyTpl(clusterDefObj, compDefObj.Name) + By("Wait objects available") - Eventually(testapps.CheckObj(&testCtx, client.ObjectKeyFromObject(clusterDefObj), - func(g Gomega, clusterDef *appsv1alpha1.ClusterDefinition) { - g.Expect(clusterDef.Status.ObservedGeneration).Should(Equal(clusterDef.Generation)) - g.Expect(clusterDef.Status.Phase).Should(Equal(appsv1alpha1.AvailablePhase)) - })).Should(Succeed()) Eventually(testapps.CheckObj(&testCtx, client.ObjectKeyFromObject(compDefObj), func(g Gomega, compDef *appsv1alpha1.ComponentDefinition) { g.Expect(compDef.Status.ObservedGeneration).Should(Equal(compDef.Generation)) @@ -200,6 +192,11 @@ var _ = Describe("Cluster Controller", func() { g.Expect(compVersion.Status.ObservedGeneration).Should(Equal(compVersion.Generation)) g.Expect(compVersion.Status.Phase).Should(Equal(appsv1alpha1.AvailablePhase)) })).Should(Succeed()) + Eventually(testapps.CheckObj(&testCtx, client.ObjectKeyFromObject(clusterDefObj), + func(g Gomega, clusterDef *appsv1alpha1.ClusterDefinition) { + g.Expect(clusterDef.Status.ObservedGeneration).Should(Equal(clusterDef.Generation)) + g.Expect(clusterDef.Status.Phase).Should(Equal(appsv1alpha1.AvailablePhase)) + })).Should(Succeed()) } waitForCreatingResourceCompletely := func(clusterKey client.ObjectKey, compNames ...string) { @@ -394,14 +391,14 @@ var _ = Describe("Cluster Controller", func() { testCluster := func(compName, compDefName string) { clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). - AddComponent(consensusCompName, consensusCompDefName).SetReplicas(3). + AddComponent(defaultCompName, defaultClusterCompDefName).SetReplicas(3). WithRandomName(). Create(&testCtx). GetObject() clusterKey = client.ObjectKeyFromObject(clusterObj) By("waiting for the cluster controller to create resources completely") - waitForCreatingResourceCompletely(clusterKey, consensusCompName) + waitForCreatingResourceCompletely(clusterKey, defaultCompName) } testClusterComponent := func(compName, compDefName string, createObj func(string, string, func(*testapps.MockClusterFactory))) { @@ -466,17 +463,19 @@ var _ = Describe("Cluster Controller", func() { } testClusterComponentScaleIn := func(compName, compDefName string) { + otherCompName := fmt.Sprintf("%s-a", compName) + By("creating and checking a cluster with multi component") clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). AddComponent(compName, compDefName).SetReplicas(3). - AddComponent(multiConsensusCompName, compDefName).SetReplicas(3). + AddComponent(otherCompName, compDefName).SetReplicas(3). WithRandomName(). Create(&testCtx). GetObject() clusterKey = client.ObjectKeyFromObject(clusterObj) By("waiting for the cluster controller to create resources completely") - waitForCreatingResourceCompletely(clusterKey, compName, multiConsensusCompName) + waitForCreatingResourceCompletely(clusterKey, compName, otherCompName) By("scale in the target component") Expect(testapps.GetAndChangeObj(&testCtx, clusterKey, func(cluster *appsv1alpha1.Cluster) { @@ -495,7 +494,7 @@ var _ = Describe("Cluster Controller", func() { } multiCompKey := types.NamespacedName{ Namespace: clusterObj.Namespace, - Name: constant.GenerateClusterComponentName(clusterObj.Name, multiConsensusCompName), + Name: constant.GenerateClusterComponentName(clusterObj.Name, otherCompName), } Eventually(testapps.CheckObjExists(&testCtx, compKey, &appsv1alpha1.Component{}, false)).Should(Succeed()) Eventually(testapps.CheckObjExists(&testCtx, multiCompKey, &appsv1alpha1.Component{}, true)).Should(Succeed()) @@ -577,10 +576,7 @@ var _ = Describe("Cluster Controller", func() { g.Expect(svc.Spec.Selector).Should(HaveKeyWithValue(constant.AppInstanceLabelKey, clusterObj.Name)) g.Expect(svc.Spec.Selector).Should(HaveKeyWithValue(constant.KBAppComponentLabelKey, compName)) g.Expect(svc.Spec.Selector).Should(HaveKey(constant.RoleLabelKey)) - if compDefName == consensusCompDefName { - // default role selector for Consensus workload - g.Expect(svc.Spec.Selector).Should(HaveKeyWithValue(constant.RoleLabelKey, constant.Leader)) - } + g.Expect(svc.Spec.Selector).Should(HaveKeyWithValue(constant.RoleLabelKey, constant.Leader)) })).Should(Succeed()) } @@ -593,8 +589,6 @@ var _ = Describe("Cluster Controller", func() { clusterTolerationValue = "testClusterTolerationValue" ) - Expect(compDefName).Should(BeElementOf(consensusCompDefName)) - By("Creating a cluster with Affinity and Toleration") affinity := appsv1alpha1.Affinity{ PodAntiAffinity: appsv1alpha1.Required, @@ -646,8 +640,6 @@ var _ = Describe("Cluster Controller", func() { compTolerationValue = "testCompTolerationValue" ) - Expect(compDefName).Should(BeElementOf(consensusCompDefName)) - By("Creating a cluster with Affinity and Toleration") affinity := appsv1alpha1.Affinity{ PodAntiAffinity: appsv1alpha1.Required, @@ -1072,7 +1064,7 @@ var _ = Describe("Cluster Controller", func() { Context("cluster provisioning", func() { BeforeEach(func() { - createAllWorkloadTypesClusterDef() + createAllDefinitionObjects() }) AfterEach(func() { @@ -1080,48 +1072,48 @@ var _ = Describe("Cluster Controller", func() { }) It("create cluster", func() { - testCluster(consensusCompName, consensusCompDefName) + testCluster(defaultCompName, defaultClusterCompDefName) }) It("create cluster with legacy component", func() { - testClusterComponent(consensusCompName, consensusCompDefName, createLegacyClusterObj) + testClusterComponent(defaultCompName, defaultClusterCompDefName, createLegacyClusterObj) }) It("create cluster", func() { - testClusterComponent(consensusCompName, compDefObj.Name, createClusterObj) + testClusterComponent(defaultCompName, compDefObj.Name, createClusterObj) }) It("create sharding cluster with legacy component", func() { - testShardingClusterComponent(consensusCompName, consensusCompDefName, createLegacyClusterObjWithSharding, defaultShardCount) + testShardingClusterComponent(defaultCompName, defaultClusterCompDefName, createLegacyClusterObjWithSharding, defaultShardCount) }) It("create sharding cluster", func() { - testShardingClusterComponent(consensusCompName, compDefObj.Name, createClusterObjWithSharding, defaultShardCount) + testShardingClusterComponent(defaultCompName, compDefObj.Name, createClusterObjWithSharding, defaultShardCount) }) It("create cluster with default topology", func() { - testClusterComponentWithTopology("", consensusCompName, nil, compDefObj.Name, latestServiceVersion) + testClusterComponentWithTopology("", defaultCompName, nil, compDefObj.Name, latestServiceVersion) }) It("create cluster with specified topology", func() { - testClusterComponentWithTopology(defaultTopology.Name, consensusCompName, nil, compDefObj.Name, latestServiceVersion) + testClusterComponentWithTopology(defaultTopology.Name, defaultCompName, nil, compDefObj.Name, latestServiceVersion) }) It("create cluster with specified service version", func() { setServiceVersion := func(f *testapps.MockClusterFactory) { f.SetServiceVersion(defaultServiceVersion) } - testClusterComponentWithTopology(defaultTopology.Name, consensusCompName, setServiceVersion, compDefObj.Name, defaultServiceVersion) + testClusterComponentWithTopology(defaultTopology.Name, defaultCompName, setServiceVersion, compDefObj.Name, defaultServiceVersion) }) It("create multiple templates cluster", func() { - testClusterComponent(consensusCompName, compDefObj.Name, createClusterObjWithMultipleTemplates) + testClusterComponent(defaultCompName, compDefObj.Name, createClusterObjWithMultipleTemplates) }) }) Context("cluster component scale-in", func() { BeforeEach(func() { - createAllWorkloadTypesClusterDef() + createAllDefinitionObjects() }) AfterEach(func() { @@ -1129,30 +1121,30 @@ var _ = Describe("Cluster Controller", func() { }) It("with cluster component scale-in", func() { - testClusterComponentScaleIn(consensusCompName, consensusCompDefName) + testClusterComponentScaleIn(defaultCompName, defaultClusterCompDefName) }) It("with cluster sharding scale-in", func() { - testClusterShardingComponentScaleIn(consensusCompName, compDefObj.Name, createClusterObjWithSharding, defaultShardCount) + testClusterShardingComponentScaleIn(defaultCompName, compDefObj.Name, createClusterObjWithSharding, defaultShardCount) }) }) Context("cluster termination policy", func() { var ( createObjV1 = func(policyType appsv1alpha1.TerminationPolicyType) { - createLegacyClusterObj(consensusCompName, consensusCompDefName, func(f *testapps.MockClusterFactory) { + createLegacyClusterObj(defaultCompName, defaultClusterCompDefName, func(f *testapps.MockClusterFactory) { f.SetTerminationPolicy(policyType) }) } createObjV2 = func(policyType appsv1alpha1.TerminationPolicyType) { - createClusterObj(consensusCompName, compDefObj.Name, func(f *testapps.MockClusterFactory) { + createClusterObj(defaultCompName, compDefObj.Name, func(f *testapps.MockClusterFactory) { f.SetTerminationPolicy(policyType) }) } ) BeforeEach(func() { - createAllWorkloadTypesClusterDef() + createAllDefinitionObjects() }) AfterEach(func() { @@ -1161,7 +1153,7 @@ var _ = Describe("Cluster Controller", func() { for _, createObj := range []func(appsv1alpha1.TerminationPolicyType){createObjV1, createObjV2} { It("deleted after all the sub-resources", func() { - testClusterFinalizer(consensusCompName, createObj) + testClusterFinalizer(defaultCompName, createObj) }) It("delete cluster with terminationPolicy=DoNotTerminate", func() { @@ -1192,7 +1184,7 @@ var _ = Describe("Cluster Controller", func() { Context("cluster status", func() { BeforeEach(func() { - createAllWorkloadTypesClusterDef() + createAllDefinitionObjects() }) AfterEach(func() { @@ -1201,8 +1193,8 @@ var _ = Describe("Cluster Controller", func() { It("test cluster conditions when cluster definition non-exist", func() { By("create a cluster with cluster definition non-exist") - mockCompDefName := fmt.Sprintf("%s-%s", consensusCompDefName, testCtx.GetRandomStr()) - createClusterObjNoWait(clusterDefObj.Name, componentProcessorWrapper(true, consensusCompName, mockCompDefName)) + mockCompDefName := fmt.Sprintf("%s-%s", defaultClusterCompDefName, testCtx.GetRandomStr()) + createClusterObjNoWait(clusterDefObj.Name, componentProcessorWrapper(true, defaultCompName, mockCompDefName)) By("check conditions") Eventually(testapps.CheckObj(&testCtx, clusterKey, func(g Gomega, cluster *appsv1alpha1.Cluster) { @@ -1216,21 +1208,19 @@ var _ = Describe("Cluster Controller", func() { Context("cluster with backup", func() { const ( - compName = consensusCompName - compDefName = consensusCompDefName backupRepoName = "test-backup-repo" backupMethodName = "test-backup-method" ) BeforeEach(func() { cleanEnv() - createAllWorkloadTypesClusterDef() + createAllDefinitionObjects() }) createClusterWithBackup := func(backup *appsv1alpha1.ClusterBackup) { By("Creating a cluster") clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). - AddComponent(compName, compDefName).WithRandomName().SetBackup(backup). + AddComponent(defaultCompName, defaultClusterCompDefName).WithRandomName().SetBackup(backup). Create(&testCtx).GetObject() clusterKey = client.ObjectKeyFromObject(clusterObj) @@ -1341,14 +1331,14 @@ var _ = Describe("Cluster Controller", func() { } By("checking backup policy") - backupPolicyName := generateBackupPolicyName(clusterKey.Name, consensusCompName, "") + backupPolicyName := generateBackupPolicyName(clusterKey.Name, defaultCompName, "") backupPolicyKey := client.ObjectKey{Name: backupPolicyName, Namespace: clusterKey.Namespace} backupPolicy := &dpv1alpha1.BackupPolicy{} Eventually(testapps.CheckObjExists(&testCtx, backupPolicyKey, backupPolicy, true)).Should(Succeed()) Eventually(testapps.CheckObj(&testCtx, backupPolicyKey, checkPolicy)).Should(Succeed()) By("checking backup schedule") - backupScheduleName := generateBackupScheduleName(clusterKey.Name, consensusCompName, "") + backupScheduleName := generateBackupScheduleName(clusterKey.Name, defaultCompName, "") backupScheduleKey := client.ObjectKey{Name: backupScheduleName, Namespace: clusterKey.Namespace} if backup == nil { Eventually(testapps.CheckObjExists(&testCtx, backupScheduleKey, @@ -1362,7 +1352,7 @@ var _ = Describe("Cluster Controller", func() { Context("cluster service", func() { BeforeEach(func() { - createAllWorkloadTypesClusterDef() + createAllDefinitionObjects() }) AfterEach(func() { @@ -1370,21 +1360,21 @@ var _ = Describe("Cluster Controller", func() { }) It("with cluster service set", func() { - testClusterService(consensusCompName, consensusCompDefName, createLegacyClusterObj) + testClusterService(defaultCompName, defaultClusterCompDefName, createLegacyClusterObj) }) It("should create and delete cluster service correctly", func() { - testClusterServiceCreateAndDelete(consensusCompName, consensusCompDefName, createLegacyClusterObj) + testClusterServiceCreateAndDelete(defaultCompName, defaultClusterCompDefName, createLegacyClusterObj) }) It("should create and delete shard topology cluster service correctly", func() { - testShardingClusterServiceCreateAndDelete(consensusCompName, consensusCompDefName, createLegacyClusterObjWithSharding) + testShardingClusterServiceCreateAndDelete(defaultCompName, defaultClusterCompDefName, createLegacyClusterObjWithSharding) }) }) Context("cluster affinity and toleration", func() { BeforeEach(func() { - createAllWorkloadTypesClusterDef() + createAllDefinitionObjects() }) AfterEach(func() { @@ -1392,17 +1382,17 @@ var _ = Describe("Cluster Controller", func() { }) It("with cluster affinity and toleration set", func() { - testClusterAffinityNToleration(consensusCompName, consensusCompDefName, createLegacyClusterObj) + testClusterAffinityNToleration(defaultCompName, defaultClusterCompDefName, createLegacyClusterObj) }) It("with both cluster and component affinity and toleration set", func() { - testClusterComponentAffinityNToleration(consensusCompName, consensusCompDefName, createLegacyClusterObj) + testClusterComponentAffinityNToleration(defaultCompName, defaultClusterCompDefName, createLegacyClusterObj) }) }) Context("cluster upgrade", func() { BeforeEach(func() { - createAllWorkloadTypesClusterDef() + createAllDefinitionObjects() }) AfterEach(func() { @@ -1413,7 +1403,7 @@ var _ = Describe("Cluster Controller", func() { setServiceVersion := func(f *testapps.MockClusterFactory) { f.SetServiceVersion(defaultServiceVersion) } - testClusterComponentWithTopology(defaultTopology.Name, consensusCompName, setServiceVersion, compDefObj.Name, defaultServiceVersion) + testClusterComponentWithTopology(defaultTopology.Name, defaultCompName, setServiceVersion, compDefObj.Name, defaultServiceVersion) By("update cluster to upgrade service version") Expect(testapps.GetAndChangeObj(&testCtx, clusterKey, func(cluster *appsv1alpha1.Cluster) { @@ -1423,7 +1413,7 @@ var _ = Describe("Cluster Controller", func() { By("check cluster and component objects been upgraded") compKey := types.NamespacedName{ Namespace: clusterObj.Namespace, - Name: constant.GenerateClusterComponentName(clusterObj.Name, consensusCompName), + Name: constant.GenerateClusterComponentName(clusterObj.Name, defaultCompName), } Eventually(testapps.CheckObj(&testCtx, clusterKey, func(g Gomega, cluster *appsv1alpha1.Cluster) { g.Expect(cluster.Spec.ComponentSpecs[0].ComponentDef).Should(Equal(compDefObj.Name)) @@ -1439,7 +1429,7 @@ var _ = Describe("Cluster Controller", func() { setServiceVersion := func(f *testapps.MockClusterFactory) { f.SetServiceVersion(defaultServiceVersion) } - testClusterComponentWithTopology(defaultTopology.Name, consensusCompName, setServiceVersion, compDefObj.Name, defaultServiceVersion) + testClusterComponentWithTopology(defaultTopology.Name, defaultCompName, setServiceVersion, compDefObj.Name, defaultServiceVersion) By("publish a new component definition obj") newCompDefObj := testapps.NewComponentDefinitionFactory(compDefObj.Name+"-r100"). @@ -1455,7 +1445,7 @@ var _ = Describe("Cluster Controller", func() { By("check cluster and component objects stay in original version before upgrading") compKey := types.NamespacedName{ Namespace: clusterObj.Namespace, - Name: constant.GenerateClusterComponentName(clusterObj.Name, consensusCompName), + Name: constant.GenerateClusterComponentName(clusterObj.Name, defaultCompName), } Consistently(testapps.CheckObj(&testCtx, clusterKey, func(g Gomega, cluster *appsv1alpha1.Cluster) { g.Expect(cluster.Spec.ComponentSpecs[0].ComponentDef).Should(Equal(compDefObj.Name)) diff --git a/controllers/apps/clusterdefinition_controller.go b/controllers/apps/clusterdefinition_controller.go index 40a3f924501b..4df626f5a6eb 100644 --- a/controllers/apps/clusterdefinition_controller.go +++ b/controllers/apps/clusterdefinition_controller.go @@ -23,7 +23,6 @@ import ( "context" "fmt" "strings" - "time" "golang.org/x/exp/slices" corev1 "k8s.io/api/core/v1" @@ -164,11 +163,6 @@ func (r *ClusterDefinitionReconciler) reconcile(rctx intctrlutil.RequestCtx, clu res, err1 := intctrlutil.CheckedRequeueWithError(err, rctx.Log, "") return &res, err1 } - - if err := appsconfig.ReconcileConfigSpecsForReferencedCR(r.Client, rctx, clusterDef); err != nil { - res, err1 := intctrlutil.RequeueAfter(time.Second, rctx.Log, err.Error()) - return &res, err1 - } return nil, nil } diff --git a/controllers/apps/clusterdefinition_controller_test.go b/controllers/apps/clusterdefinition_controller_test.go index 454f95aa46c7..fb9de205fbfa 100644 --- a/controllers/apps/clusterdefinition_controller_test.go +++ b/controllers/apps/clusterdefinition_controller_test.go @@ -25,28 +25,17 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" - appsv1beta1 "github.com/apecloud/kubeblocks/apis/apps/v1beta1" - cfgcore "github.com/apecloud/kubeblocks/pkg/configuration/core" - "github.com/apecloud/kubeblocks/pkg/constant" intctrlutil "github.com/apecloud/kubeblocks/pkg/generics" testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" ) var _ = Describe("ClusterDefinition Controller", func() { const ( - clusterDefName = "test-clusterdef" - compDefinitionName = "test-component-definition" - statefulCompDefName = "replicasets" - - configVolumeName = "mysql-config" - - cmName = "mysql-tree-node-template-8.0" + clusterDefName = "test-clusterdef" + compDefinitionName = "test-component-definition" ) var ( @@ -75,70 +64,12 @@ var _ = Describe("ClusterDefinition Controller", func() { BeforeEach(func() { cleanEnv() - }) AfterEach(func() { cleanEnv() }) - assureCfgTplConfigMapObj := func() *corev1.ConfigMap { - By("Create a configmap and config template obj") - cm := testapps.CreateCustomizedObj(&testCtx, "config/config-template.yaml", &corev1.ConfigMap{}, - testCtx.UseDefaultNamespace()) - - cfgTpl := testapps.CreateCustomizedObj(&testCtx, "config/config-constraint.yaml", - &appsv1beta1.ConfigConstraint{}) - Expect(testapps.ChangeObjStatus(&testCtx, cfgTpl, func() { - cfgTpl.Status.Phase = appsv1beta1.CCAvailablePhase - })).Should(Succeed()) - return cm - } - - Context("with ConfigSpec", func() { - BeforeEach(func() { - By("Create a clusterDefinition obj") - clusterDefObj = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatefulMySQLComponent, statefulCompDefName). - AddConfigTemplate(cmName, cmName, cmName, testCtx.DefaultNamespace, configVolumeName). - Create(&testCtx).GetObject() - }) - - It("should stop proceeding the status of clusterDefinition if configmap is invalid or doesn't exist", func() { - By("check the reconciler set the status phase as unavailable if configmap doesn't exist.") - Eventually(testapps.CheckObj(&testCtx, client.ObjectKeyFromObject(clusterDefObj), - func(g Gomega, cd *appsv1alpha1.ClusterDefinition) { - g.Expect(cd.Status.ObservedGeneration).Should(Equal(cd.Generation)) - g.Expect(cd.Status.Phase).Should(Equal(appsv1alpha1.UnavailablePhase)) - })).Should(Succeed()) - - assureCfgTplConfigMapObj() - - By("check the reconciler update Status.ObservedGeneration after configmap is created.") - Eventually(testapps.CheckObj(&testCtx, client.ObjectKeyFromObject(clusterDefObj), - func(g Gomega, cd *appsv1alpha1.ClusterDefinition) { - g.Expect(cd.Status.ObservedGeneration).Should(Equal(cd.Generation)) - g.Expect(cd.Status.Phase).Should(Equal(appsv1alpha1.AvailablePhase)) - - // check labels and finalizers - g.Expect(cd.Finalizers).ShouldNot(BeEmpty()) - configCMLabel := cfgcore.GenerateTPLUniqLabelKeyWithConfig(cmName) - configConstraintLabel := cfgcore.GenerateConstraintsUniqLabelKeyWithConfig(cmName) - g.Expect(cd.Labels[configCMLabel]).Should(BeEquivalentTo(cmName)) - g.Expect(cd.Labels[configConstraintLabel]).Should(BeEquivalentTo(cmName)) - })).Should(Succeed()) - - By("check the reconciler update configmap.Finalizer after configmap is created.") - cmKey := types.NamespacedName{ - Namespace: testCtx.DefaultNamespace, - Name: cmName, - } - Eventually(testapps.CheckObj(&testCtx, cmKey, func(g Gomega, cmObj *corev1.ConfigMap) { - g.Expect(controllerutil.ContainsFinalizer(cmObj, constant.ConfigFinalizerName)).To(BeTrue()) - })).Should(Succeed()) - }) - }) - Context("cluster topology", func() { var ( singleCompTopology = appsv1alpha1.ClusterTopology{ diff --git a/controllers/apps/component_controller_test.go b/controllers/apps/component_controller_test.go index b322172620f5..d8cadc0bb261 100644 --- a/controllers/apps/component_controller_test.go +++ b/controllers/apps/component_controller_test.go @@ -157,19 +157,17 @@ var _ = Describe("Component Controller", func() { allSettings map[string]interface{} ) - resetViperCfg := func() { + resetTestContext := func() { + clusterDefObj = nil + compDefObj = nil + compVerObj = nil + clusterObj = nil if allSettings != nil { Expect(viper.MergeConfigMap(allSettings)).ShouldNot(HaveOccurred()) allSettings = nil } } - resetTestContext := func() { - clusterDefObj = nil - clusterObj = nil - resetViperCfg() - } - // Cleanups cleanEnv := func() { // must wait till resources deleted and no longer existed before the testcases start, @@ -2334,7 +2332,7 @@ var _ = Describe("Component Controller", func() { } }) - When("creating cluster with workloadType=consensus component", func() { + Context("creating cluster with workloadType=consensus component", func() { BeforeEach(func() { createAllWorkloadTypesClusterDef() createBackupPolicyTpl(clusterDefObj, compDefName) diff --git a/controllers/apps/configuration/config_util.go b/controllers/apps/configuration/config_util.go index 5361f0f91152..43c072ae41f6 100644 --- a/controllers/apps/configuration/config_util.go +++ b/controllers/apps/configuration/config_util.go @@ -234,18 +234,16 @@ func deleteConfigMapFinalizer(cli client.Client, ctx intctrlutil.RequestCtx, con } type ConfigTemplateHandler func([]appsv1alpha1.ComponentConfigSpec) (bool, error) -type ComponentValidateHandler func(component *appsv1alpha1.ClusterComponentDefinition) error +type componentValidateHandler func(*appsv1alpha1.ComponentDefinition) error -func handleConfigTemplate(object client.Object, handler ConfigTemplateHandler, handler2 ...ComponentValidateHandler) (bool, error) { +func handleConfigTemplate(object client.Object, handler ConfigTemplateHandler, handler2 ...componentValidateHandler) (bool, error) { var ( err error configTemplates []appsv1alpha1.ComponentConfigSpec ) switch cr := object.(type) { - case *appsv1alpha1.ClusterDefinition: - configTemplates, err = getConfigTemplateFromCD(cr, handler2...) case *appsv1alpha1.ComponentDefinition: - configTemplates = getConfigTemplateFromComponentDef(cr) + configTemplates, err = getConfigTemplateFromComponentDef(cr, handler2...) default: return false, core.MakeError("not support CR type: %v", cr) } @@ -260,31 +258,8 @@ func handleConfigTemplate(object client.Object, handler ConfigTemplateHandler, h } } -func getConfigTemplateFromCD(clusterDef *appsv1alpha1.ClusterDefinition, validators ...ComponentValidateHandler) ([]appsv1alpha1.ComponentConfigSpec, error) { - configTemplates := make([]appsv1alpha1.ComponentConfigSpec, 0) - for _, component := range clusterDef.Spec.ComponentDefs { - // For compatibility with the previous lifecycle management of configurationSpec.TemplateRef, it is necessary to convert ScriptSpecs to ConfigSpecs, - // ensuring that the script-related configmap is not allowed to be deleted. - for _, scriptSpec := range component.ScriptSpecs { - configTemplates = append(configTemplates, appsv1alpha1.ComponentConfigSpec{ - ComponentTemplateSpec: scriptSpec, - }) - } - if len(component.ConfigSpecs) == 0 { - continue - } - configTemplates = append(configTemplates, component.ConfigSpecs...) - // Check reload configure config template - for _, validator := range validators { - if err := validator(&component); err != nil { - return nil, err - } - } - } - return configTemplates, nil -} - -func getConfigTemplateFromComponentDef(componentDef *appsv1alpha1.ComponentDefinition) []appsv1alpha1.ComponentConfigSpec { +func getConfigTemplateFromComponentDef(componentDef *appsv1alpha1.ComponentDefinition, + validators ...componentValidateHandler) ([]appsv1alpha1.ComponentConfigSpec, error) { configTemplates := make([]appsv1alpha1.ComponentConfigSpec, 0) // For compatibility with the previous lifecycle management of configurationSpec.TemplateRef, // it is necessary to convert ScriptSpecs to ConfigSpecs, @@ -294,7 +269,15 @@ func getConfigTemplateFromComponentDef(componentDef *appsv1alpha1.ComponentDefin ComponentTemplateSpec: scriptSpec, }) } - return append(configTemplates, componentDef.Spec.Configs...) + if len(componentDef.Spec.Configs) > 0 { + // Check reload configure config template + for _, validator := range validators { + if err := validator(componentDef); err != nil { + return nil, err + } + } + } + return append(configTemplates, componentDef.Spec.Configs...), nil } func checkConfigTemplate(client client.Client, ctx intctrlutil.RequestCtx, obj client.Object) (bool, error) { diff --git a/controllers/apps/configuration/config_util_test.go b/controllers/apps/configuration/config_util_test.go index fb6da10d08c7..0cd46b262ce4 100644 --- a/controllers/apps/configuration/config_util_test.go +++ b/controllers/apps/configuration/config_util_test.go @@ -37,11 +37,6 @@ import ( ) var _ = Describe("ConfigWrapper util test", func() { - const clusterDefName = "test-clusterdef" - const statefulCompDefName = "replicasets" - const configSpecName = "mysql-config-tpl" - const configVolumeName = "mysql-config" - var ( // ctrl *gomock.Controller // mockClient *mock_client.MockClient @@ -56,7 +51,7 @@ var _ = Describe("ConfigWrapper util test", func() { var ( configMapObj *corev1.ConfigMap configConstraintObj *appsv1beta1.ConfigConstraint - clusterDefObj *appsv1alpha1.ClusterDefinition + compDefObj *appsv1alpha1.ComponentDefinition ) cleanEnv := func() { @@ -72,7 +67,7 @@ var _ = Describe("ConfigWrapper util test", func() { // namespaced testapps.ClearResources(&testCtx, generics.ConfigMapSignature, inNS, ml) // non-namespaced - testapps.ClearResources(&testCtx, generics.ClusterDefinitionSignature, ml) + testapps.ClearResources(&testCtx, generics.ComponentDefinitionSignature, ml) testapps.ClearResources(&testCtx, generics.ConfigConstraintSignature, ml) } @@ -91,11 +86,13 @@ var _ = Describe("ConfigWrapper util test", func() { "resources/mysql-config-constraint.yaml", &appsv1beta1.ConfigConstraint{}) - By("Create a clusterDefinition obj") - clusterDefObj = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatefulMySQLComponent, statefulCompDefName). + By("Create a componentDefinition obj") + compDefObj = testapps.NewComponentDefinitionFactory(compDefName). + WithRandomName(). + SetDefaultSpec(). AddConfigTemplate(configSpecName, configMapObj.Name, configConstraintObj.Name, testCtx.DefaultNamespace, configVolumeName). - Create(&testCtx).GetObject() + Create(&testCtx). + GetObject() }) AfterEach(func() { @@ -105,7 +102,7 @@ var _ = Describe("ConfigWrapper util test", func() { k8sMockClient.Finish() }) - Context("clusterdefinition CR test", func() { + Context("ComponentDefinition CR test", func() { It("Should success without error", func() { availableTPL := configConstraintObj.DeepCopy() availableTPL.Status.Phase = appsv1beta1.CCAvailablePhase @@ -134,45 +131,45 @@ var _ = Describe("ConfigWrapper util test", func() { }, ), testutil.WithAnyTimes())) - _, err := checkConfigTemplate(k8sMockClient.Client(), reqCtx, clusterDefObj) + _, err := checkConfigTemplate(k8sMockClient.Client(), reqCtx, compDefObj) Expect(err).ShouldNot(Succeed()) Expect(err.Error()).Should(ContainSubstring("failed to get cc object")) - _, err = checkConfigTemplate(k8sMockClient.Client(), reqCtx, clusterDefObj) + _, err = checkConfigTemplate(k8sMockClient.Client(), reqCtx, compDefObj) Expect(err).ShouldNot(Succeed()) Expect(err.Error()).Should(ContainSubstring("failed to get cc object")) - _, err = checkConfigTemplate(k8sMockClient.Client(), reqCtx, clusterDefObj) + _, err = checkConfigTemplate(k8sMockClient.Client(), reqCtx, compDefObj) Expect(err).ShouldNot(Succeed()) Expect(err.Error()).Should(ContainSubstring("status not ready")) - ok, err := checkConfigTemplate(k8sMockClient.Client(), reqCtx, clusterDefObj) + ok, err := checkConfigTemplate(k8sMockClient.Client(), reqCtx, compDefObj) Expect(err).Should(Succeed()) Expect(ok).Should(BeTrue()) - ok, err = updateLabelsByConfigSpec(k8sMockClient.Client(), reqCtx, clusterDefObj) + ok, err = updateLabelsByConfigSpec(k8sMockClient.Client(), reqCtx, compDefObj) Expect(err).Should(Succeed()) Expect(ok).Should(BeTrue()) - _, err = updateLabelsByConfigSpec(k8sMockClient.Client(), reqCtx, clusterDefObj) + _, err = updateLabelsByConfigSpec(k8sMockClient.Client(), reqCtx, compDefObj) Expect(err).Should(Succeed()) - err = DeleteConfigMapFinalizer(k8sMockClient.Client(), reqCtx, clusterDefObj) + err = DeleteConfigMapFinalizer(k8sMockClient.Client(), reqCtx, compDefObj) Expect(err).Should(Succeed()) }) }) - Context("clusterdefinition CR test without config Constraints", func() { + Context("ComponentDefinition CR test without config Constraints", func() { It("Should success without error", func() { // remove ConfigConstraintRef - _, err := handleConfigTemplate(clusterDefObj, func(templates []appsv1alpha1.ComponentConfigSpec) (bool, error) { + _, err := handleConfigTemplate(compDefObj, func(templates []appsv1alpha1.ComponentConfigSpec) (bool, error) { return true, nil - }, func(component *appsv1alpha1.ClusterComponentDefinition) error { - if len(component.ConfigSpecs) == 0 { + }, func(compDef *appsv1alpha1.ComponentDefinition) error { + if len(compDef.Spec.Configs) == 0 { return nil } - for i := range component.ConfigSpecs { - tpl := &component.ConfigSpecs[i] + for i := range compDef.Spec.Configs { + tpl := &compDef.Spec.Configs[i] tpl.ConfigConstraintRef = "" } return nil @@ -193,11 +190,11 @@ var _ = Describe("ConfigWrapper util test", func() { }}}, ), testutil.WithAnyTimes())) - _, err = checkConfigTemplate(k8sMockClient.Client(), reqCtx, clusterDefObj) + _, err = checkConfigTemplate(k8sMockClient.Client(), reqCtx, compDefObj) Expect(err).ShouldNot(Succeed()) Expect(err.Error()).Should(ContainSubstring("failed to get cc object")) - ok, err := checkConfigTemplate(k8sMockClient.Client(), reqCtx, clusterDefObj) + ok, err := checkConfigTemplate(k8sMockClient.Client(), reqCtx, compDefObj) Expect(err).Should(Succeed()) Expect(ok).Should(BeTrue()) }) diff --git a/controllers/apps/configuration/configconstraint_controller.go b/controllers/apps/configuration/configconstraint_controller.go index cd6f0a45d1e6..8d9fc988226a 100644 --- a/controllers/apps/configuration/configconstraint_controller.go +++ b/controllers/apps/configuration/configconstraint_controller.go @@ -85,7 +85,7 @@ func (r *ConfigConstraintReconciler) Reconcile(ctx context.Context, req ctrl.Req } if res, err := intctrlutil.ValidateReferenceCR(reqCtx, r.Client, configConstraint, cfgcore.GenerateConstraintsUniqLabelKeyWithConfig(configConstraint.GetName()), - recordEvent, &appsv1alpha1.ClusterDefinitionList{}); res != nil || err != nil { + recordEvent, &appsv1alpha1.ClusterDefinitionList{}, &appsv1alpha1.ComponentDefinitionList{}); res != nil || err != nil { return res, err } return nil, nil diff --git a/controllers/apps/configuration/configconstraint_controller_test.go b/controllers/apps/configuration/configconstraint_controller_test.go index 0d6881f5a3a0..e824c1758fc3 100644 --- a/controllers/apps/configuration/configconstraint_controller_test.go +++ b/controllers/apps/configuration/configconstraint_controller_test.go @@ -38,11 +38,6 @@ import ( ) var _ = Describe("ConfigConstraint Controller", func() { - const clusterDefName = "test-clusterdef" - const statefulCompDefName = "replicasets" - const configSpecName = "mysql-config-tpl" - const configVolumeName = "mysql-config" - 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, @@ -69,23 +64,23 @@ var _ = Describe("ConfigConstraint Controller", func() { Context("Create config constraint with cue validate", func() { It("Should ready", func() { By("creating a configmap and a config constraint") - configmap := testapps.CreateCustomizedObj(&testCtx, "resources/mysql-config-template.yaml", &corev1.ConfigMap{}, testCtx.UseDefaultNamespace()) - constraint := testapps.CreateCustomizedObj(&testCtx, "resources/mysql-config-constraint.yaml", &appsv1beta1.ConfigConstraint{}) constraintKey := client.ObjectKeyFromObject(constraint) - By("Create a clusterDefinition obj") - clusterDefObj := testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatefulMySQLComponent, statefulCompDefName). + By("Create a componentDefinition obj") + compDefObj := testapps.NewComponentDefinitionFactory(compDefName). + WithRandomName(). + SetDefaultSpec(). AddConfigTemplate(configSpecName, configmap.Name, constraint.Name, testCtx.DefaultNamespace, configVolumeName). AddLabels(cfgcore.GenerateTPLUniqLabelKeyWithConfig(configSpecName), configmap.Name, cfgcore.GenerateConstraintsUniqLabelKeyWithConfig(constraint.Name), constraint.Name). - Create(&testCtx).GetObject() + Create(&testCtx). + GetObject() By("check ConfigConstraint(template) status and finalizer") Eventually(testapps.CheckObj(&testCtx, constraintKey, @@ -107,8 +102,8 @@ var _ = Describe("ConfigConstraint Controller", func() { g.Expect(tpl.Status.Phase).To(BeEquivalentTo(appsv1beta1.CCDeletingPhase)) })).Should(Succeed()) - By("By delete referencing clusterdefinition") - Expect(k8sClient.Delete(testCtx.Ctx, clusterDefObj)).Should(Succeed()) + By("By delete referencing componentdefinition") + Expect(k8sClient.Delete(testCtx.Ctx, compDefObj)).Should(Succeed()) By("check ConfigConstraint should be deleted") Eventually(testapps.CheckObjExists(&testCtx, constraintKey, &appsv1beta1.ConfigConstraint{}, false), time.Second*60, time.Second*1).Should(Succeed()) diff --git a/controllers/apps/configuration/configuration_controller_test.go b/controllers/apps/configuration/configuration_controller_test.go index 74b7a7b2c55d..49bfe4c4c6ef 100644 --- a/controllers/apps/configuration/configuration_controller_test.go +++ b/controllers/apps/configuration/configuration_controller_test.go @@ -45,7 +45,7 @@ var _ = Describe("Configuration Controller", func() { _, _, clusterObj, componentObj, synthesizedComp := mockReconcileResource() cfgKey := client.ObjectKey{ - Name: core.GenerateComponentConfigurationName(clusterName, statefulCompName), + Name: core.GenerateComponentConfigurationName(clusterName, defaultCompName), Namespace: testCtx.DefaultNamespace, } checkCfgStatus := func(phase appsv1alpha1.ConfigurationPhase) func() bool { @@ -64,7 +64,7 @@ var _ = Describe("Configuration Controller", func() { Context: ctx, Namespace: testCtx.DefaultNamespace, ClusterName: clusterName, - ComponentName: statefulCompName, + ComponentName: defaultCompName, }, synthesizedComp, clusterObj, componentObj)).Should(Succeed()) Eventually(checkCfgStatus(appsv1alpha1.CFinishedPhase)).Should(BeTrue()) @@ -114,5 +114,4 @@ var _ = Describe("Configuration Controller", func() { }, time.Second*60, time.Second*1).Should(Succeed()) }) }) - }) diff --git a/controllers/apps/configuration/configuration_test.go b/controllers/apps/configuration/configuration_test.go index ee2ce05709a6..73fef0ff6553 100644 --- a/controllers/apps/configuration/configuration_test.go +++ b/controllers/apps/configuration/configuration_test.go @@ -42,14 +42,15 @@ import ( testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" ) -const clusterDefName = "test-clusterdef" -const clusterName = "test-cluster" -const statefulCompDefName = "replicasets" -const statefulCompName = "mysql" -const statefulSetName = "mysql-statefulset" -const configSpecName = "mysql-config-tpl" -const configVolumeName = "mysql-config" -const cmName = "mysql-tree-node-template-8.0" +const ( + compDefName = "test-compdef" + clusterName = "test-cluster" + defaultCompName = "mysql" + defaultITSName = "mysql-statefulset" + configSpecName = "mysql-config-tpl" + configVolumeName = "mysql-config" + cmName = "mysql-tree-node-template-8.0" +) func mockConfigResource() (*corev1.ConfigMap, *appsv1beta1.ConfigConstraint) { By("Create a config template obj") @@ -59,7 +60,7 @@ func mockConfigResource() (*corev1.ConfigMap, *appsv1beta1.ConfigConstraint) { testapps.WithLabels( constant.AppNameLabelKey, clusterName, constant.AppInstanceLabelKey, clusterName, - constant.KBAppComponentLabelKey, statefulCompName, + constant.KBAppComponentLabelKey, defaultCompName, constant.CMConfigurationTemplateNameLabelKey, configSpecName, constant.CMConfigurationConstraintsNameLabelKey, cmName, constant.CMConfigurationSpecProviderLabelKey, configSpecName, @@ -82,9 +83,9 @@ func mockConfigResource() (*corev1.ConfigMap, *appsv1beta1.ConfigConstraint) { By("Create a configuration obj") // test-cluster-mysql-mysql-config-tpl - configuration := builder.NewConfigurationBuilder(testCtx.DefaultNamespace, core.GenerateComponentConfigurationName(clusterName, statefulCompName)). + configuration := builder.NewConfigurationBuilder(testCtx.DefaultNamespace, core.GenerateComponentConfigurationName(clusterName, defaultCompName)). ClusterRef(clusterName). - Component(statefulCompName). + Component(defaultCompName). AddConfigurationItem(appsv1alpha1.ComponentConfigSpec{ ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ Name: configSpecName, @@ -103,29 +104,28 @@ func mockConfigResource() (*corev1.ConfigMap, *appsv1beta1.ConfigConstraint) { func mockReconcileResource() (*corev1.ConfigMap, *appsv1beta1.ConfigConstraint, *appsv1alpha1.Cluster, *appsv1alpha1.Component, *component.SynthesizedComponent) { configmap, constraint := mockConfigResource() - By("Create a clusterDefinition obj") - clusterDefObj := testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatefulMySQLComponent, statefulCompDefName). + By("Create a component definition obj and mock to available") + compDefObj := testapps.NewComponentDefinitionFactory(compDefName). + WithRandomName(). + SetDefaultSpec(). AddConfigTemplate(configSpecName, configmap.Name, constraint.Name, testCtx.DefaultNamespace, configVolumeName). AddLabels(core.GenerateTPLUniqLabelKeyWithConfig(configSpecName), configmap.Name, core.GenerateConstraintsUniqLabelKeyWithConfig(constraint.Name), constraint.Name). - Create(&testCtx).GetObject() - - By("Creating a cluster") - clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). - AddComponent(statefulCompName, statefulCompDefName).Create(&testCtx).GetObject() - - By("Create a component definition obj and mock to available") - componentDefObj := testapps.NewComponentDefinitionFactory(statefulCompDefName). - SetRuntime(nil). - Create(&testCtx).GetObject() - Expect(testapps.GetAndChangeObjStatus(&testCtx, client.ObjectKeyFromObject(componentDefObj), func(obj *appsv1alpha1.ComponentDefinition) { + Create(&testCtx). + GetObject() + Expect(testapps.GetAndChangeObjStatus(&testCtx, client.ObjectKeyFromObject(compDefObj), func(obj *appsv1alpha1.ComponentDefinition) { obj.Status.Phase = appsv1alpha1.AvailablePhase })()).Should(Succeed()) + By("Creating a cluster") + clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). + AddComponentV2(defaultCompName, compDefObj.GetName()). + Create(&testCtx). + GetObject() + By("Create a component obj") - fullCompName := constant.GenerateClusterComponentName(clusterName, statefulCompName) - componentObj := testapps.NewComponentFactory(testCtx.DefaultNamespace, fullCompName, componentDefObj.Name). + fullCompName := constant.GenerateClusterComponentName(clusterName, defaultCompName) + compObj := testapps.NewComponentFactory(testCtx.DefaultNamespace, fullCompName, compDefObj.Name). AddLabels(constant.AppInstanceLabelKey, clusterName). AddLabels(constant.KBAppClusterUIDLabelKey, string(clusterObj.UID)). SetUID(types.UID(fmt.Sprintf("%s-%s", clusterObj.Name, "test-uid"))). @@ -137,22 +137,23 @@ func mockReconcileResource() (*corev1.ConfigMap, *appsv1beta1.ConfigConstraint, Name: configVolumeName, MountPath: "/mnt/config", }).GetObject() - _ = testapps.NewInstanceSetFactory(testCtx.DefaultNamespace, statefulSetName, clusterObj.Name, statefulCompName). + _ = testapps.NewInstanceSetFactory(testCtx.DefaultNamespace, defaultITSName, clusterObj.Name, defaultCompName). AddConfigmapVolume(configVolumeName, configmap.Name). AddContainer(container). AddAppNameLabel(clusterName). AddAppInstanceLabel(clusterName). - AddAppComponentLabel(statefulCompName). + AddAppComponentLabel(defaultCompName). AddAnnotations(core.GenerateTPLUniqLabelKeyWithConfig(configSpecName), configmap.Name). Create(&testCtx).GetObject() - synthesizedComp, err := component.BuildSynthesizedComponentWrapper(intctrlutil.RequestCtx{ + reqCtx := intctrlutil.RequestCtx{ Ctx: testCtx.Ctx, Log: log.FromContext(testCtx.Ctx), - }, testCtx.Cli, clusterObj, clusterObj.Spec.GetComponentByName(statefulCompName)) + } + synthesizedComp, err := component.BuildSynthesizedComponent(reqCtx, testCtx.Cli, clusterObj, compDefObj, compObj) Expect(err).ShouldNot(HaveOccurred()) - return configmap, constraint, clusterObj, componentObj, synthesizedComp + return configmap, constraint, clusterObj, compObj, synthesizedComp } func initConfiguration(resourceCtx *configctrl.ResourceCtx, @@ -183,14 +184,13 @@ func cleanEnv() { By("clean resources") // delete cluster(and all dependent sub-resources), cluster definition - testapps.ClearClusterResources(&testCtx) + testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest mocked objects inNS := client.InNamespace(testCtx.DefaultNamespace) ml := client.HasLabels{testCtx.TestObjLabelKey} // non-namespaced testapps.ClearResources(&testCtx, generics.ConfigConstraintSignature, ml) - testapps.ClearResources(&testCtx, generics.ComponentDefinitionSignature, ml) // namespaced testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.ComponentSignature, true, inNS, ml) testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.ConfigMapSignature, true, inNS, ml) diff --git a/controllers/apps/configuration/policy_util_test.go b/controllers/apps/configuration/policy_util_test.go index 15129f39ddf7..3c6b663e8b09 100644 --- a/controllers/apps/configuration/policy_util_test.go +++ b/controllers/apps/configuration/policy_util_test.go @@ -155,7 +155,6 @@ func withConfigPatch(patch map[string]string) ParamsOps { func withCDComponent(compType appsv1alpha1.WorkloadType, tpls []appsv1alpha1.ComponentConfigSpec) ParamsOps { return func(params *reconfigureParams) { params.Component = &appsv1alpha1.ClusterComponentDefinition{ - ConfigSpecs: tpls, WorkloadType: compType, Name: string(compType), } diff --git a/controllers/apps/operations/reconfigure_test.go b/controllers/apps/operations/reconfigure_test.go index 8b80237c18e2..1a9b2392c4cd 100644 --- a/controllers/apps/operations/reconfigure_test.go +++ b/controllers/apps/operations/reconfigure_test.go @@ -24,8 +24,8 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/spf13/cast" + "github.com/spf13/cast" corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" @@ -43,11 +43,10 @@ import ( ) var _ = Describe("Reconfigure OpsRequest", func() { - var ( - randomStr = testCtx.GetRandomStr() - clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterName = "cluster-for-ops-" + randomStr + randomStr = testCtx.GetRandomStr() + compDefName = "test-compdef-" + randomStr + clusterName = "test-cluster-" + randomStr ) cleanEnv := func() { @@ -58,7 +57,7 @@ var _ = Describe("Reconfigure OpsRequest", func() { By("clean resources") // delete cluster(and all dependent sub-resources), cluster definition - testapps.ClearClusterResources(&testCtx) + testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest resources inNS := client.InNamespace(testCtx.DefaultNamespace) @@ -91,8 +90,8 @@ var _ = Describe("Reconfigure OpsRequest", func() { return cfgCM, cfgTpl } - assureConfigInstanceObj := func(clusterName, componentName, ns string, cdComponent *appsv1alpha1.ClusterComponentDefinition) (*appsv1alpha1.Configuration, *corev1.ConfigMap) { - if len(cdComponent.ConfigSpecs) == 0 { + assureConfigInstanceObj := func(clusterName, componentName, ns string, compDef *appsv1alpha1.ComponentDefinition) (*appsv1alpha1.Configuration, *corev1.ConfigMap) { + if len(compDef.Spec.Configs) == 0 { return nil, nil } @@ -100,7 +99,7 @@ var _ = Describe("Reconfigure OpsRequest", func() { configuration := builder.NewConfigurationBuilder(testCtx.DefaultNamespace, core.GenerateComponentConfigurationName(clusterName, componentName)). ClusterRef(clusterName). Component(componentName) - for _, configSpec := range cdComponent.ConfigSpecs { + for _, configSpec := range compDef.Spec.Configs { configuration.AddConfigurationItem(configSpec) } Expect(testCtx.CheckedCreateObj(ctx, configuration.GetObject())).Should(Succeed()) @@ -118,7 +117,7 @@ var _ = Describe("Reconfigure OpsRequest", func() { By("create configmap for configSpecs") var cmObj *corev1.ConfigMap - for _, configSpec := range cdComponent.ConfigSpecs { + for _, configSpec := range compDef.Spec.Configs { cmInsName := core.GetComponentCfgName(clusterName, componentName, configSpec.Name) By("create configmap: " + cmInsName) cfgCM := testapps.NewCustomizedObj("operations_config/config-template.yaml", @@ -143,13 +142,8 @@ var _ = Describe("Reconfigure OpsRequest", func() { assureMockReconfigureData := func(policyName string) (*OpsResource, *appsv1alpha1.Configuration, *corev1.ConfigMap) { By("init operations resources ") - opsRes, clusterDef, clusterObject := initOperationsResources(clusterDefinitionName, clusterName) + opsRes, compDef, clusterObject := initOperationsResources2(compDefName, clusterName) - var ( - cfgObj *corev1.ConfigMap - config *appsv1alpha1.Configuration - stsComponent *appsv1alpha1.ClusterComponentDefinition - ) By("Test Reconfigure") { // mock cluster is Running to support reconfiguring ops @@ -159,32 +153,24 @@ var _ = Describe("Reconfigure OpsRequest", func() { Expect(k8sClient.Status().Patch(ctx, clusterObject, patch)).Should(Succeed()) } - { - By("mock config tpl") - cmObj, tplObj := assureCfgTplObj("mysql-tpl-test", "mysql-cm-test", testCtx.DefaultNamespace) - By("update clusterdefinition tpl") - patch := client.MergeFrom(clusterDef.DeepCopy()) - for i := range clusterDef.Spec.ComponentDefs { - component := &clusterDef.Spec.ComponentDefs[i] - if component.Name != consensusComp { - continue - } - stsComponent = component - component.ConfigSpecs = []appsv1alpha1.ComponentConfigSpec{{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "mysql-test", - TemplateRef: cmObj.Name, - VolumeName: "mysql-config", - Namespace: testCtx.DefaultNamespace, - }, - ConfigConstraintRef: tplObj.Name, - }} - } - - Expect(k8sClient.Patch(ctx, clusterDef, patch)).Should(Succeed()) - By("mock config cm object") - config, cfgObj = assureConfigInstanceObj(clusterName, consensusComp, testCtx.DefaultNamespace, stsComponent) - } + By("mock config tpl") + cmObj, tplObj := assureCfgTplObj("mysql-tpl-test", "mysql-cm-test", testCtx.DefaultNamespace) + + By("update clusterdefinition tpl") + patch := client.MergeFrom(compDef.DeepCopy()) + compDef.Spec.Configs = []appsv1alpha1.ComponentConfigSpec{{ + ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ + Name: "mysql-test", + TemplateRef: cmObj.Name, + VolumeName: "mysql-config", + Namespace: testCtx.DefaultNamespace, + }, + ConfigConstraintRef: tplObj.Name, + }} + Expect(k8sClient.Patch(ctx, compDef, patch)).Should(Succeed()) + + By("mock config cm object") + config, cfgObj := assureConfigInstanceObj(clusterName, defaultCompName, testCtx.DefaultNamespace, compDef) return opsRes, config, cfgObj } @@ -218,7 +204,7 @@ var _ = Describe("Reconfigure OpsRequest", func() { }, }}, }}, - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, } By("Init Reconfiguring opsrequest") @@ -260,7 +246,7 @@ var _ = Describe("Reconfigure OpsRequest", func() { By("mock configmap controller to updated") Eventually(testapps.GetAndChangeObj(&testCtx, client.ObjectKey{ - Name: core.GetComponentCfgName(clusterName, consensusComp, "mysql-test"), + Name: core.GetComponentCfgName(clusterName, defaultCompName, "mysql-test"), Namespace: testCtx.DefaultNamespace}, func(cm *corev1.ConfigMap) { b, err := json.Marshal(item) @@ -283,7 +269,6 @@ var _ = Describe("Reconfigure OpsRequest", func() { Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(opsRes.OpsRequest), opsRes.OpsRequest)).Should(Succeed()) _, _ = opsManager.Reconcile(reqCtx, k8sClient, opsRes) Expect(opsRes.OpsRequest.Status.Phase).Should(Equal(appsv1alpha1.OpsSucceedPhase)) - }) It("Test Reconfigure OpsRequest with autoReload", func() { @@ -309,7 +294,7 @@ var _ = Describe("Reconfigure OpsRequest", func() { }}, }}, }}, - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, } By("Init Reconfiguring opsrequest") @@ -336,9 +321,9 @@ var _ = Describe("Reconfigure OpsRequest", func() { mockClusterCompPhase := func(clusterObj *appsv1alpha1.Cluster, phase appsv1alpha1.ClusterComponentPhase) { clusterObject := clusterObj.DeepCopy() patch := client.MergeFrom(clusterObject.DeepCopy()) - compStatus := clusterObject.Status.Components[consensusComp] + compStatus := clusterObject.Status.Components[defaultCompName] compStatus.Phase = phase - clusterObject.Status.Components[consensusComp] = compStatus + clusterObject.Status.Components[defaultCompName] = compStatus Expect(k8sClient.Status().Patch(ctx, clusterObject, patch)).Should(Succeed()) } mockClusterCompPhase(opsRes.Cluster, appsv1alpha1.UpdatingClusterCompPhase) @@ -346,7 +331,7 @@ var _ = Describe("Reconfigure OpsRequest", func() { By("check cluster.status.components[*].phase == Reconfiguring") Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(opsRes.OpsRequest), opsRes.OpsRequest)).Should(Succeed()) - Expect(opsRes.Cluster.Status.Components[consensusComp].Phase).Should(Equal(appsv1alpha1.UpdatingClusterCompPhase)) // appsv1alpha1.ReconfiguringPhase + Expect(opsRes.Cluster.Status.Components[defaultCompName].Phase).Should(Equal(appsv1alpha1.UpdatingClusterCompPhase)) // appsv1alpha1.ReconfiguringPhase // TODO: add status condition expect _, _ = opsManager.Reconcile(reqCtx, k8sClient, opsRes) // mock cluster.status.component.phase to Running @@ -354,8 +339,7 @@ var _ = Describe("Reconfigure OpsRequest", func() { By("check cluster.status.components[*].phase == Running") Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(opsRes.Cluster), opsRes.Cluster)).Should(Succeed()) - Expect(opsRes.Cluster.Status.Components[consensusComp].Phase).Should(Equal(appsv1alpha1.RunningClusterCompPhase)) + Expect(opsRes.Cluster.Status.Components[defaultCompName].Phase).Should(Equal(appsv1alpha1.RunningClusterCompPhase)) }) - }) }) diff --git a/controllers/apps/operations/suite_test.go b/controllers/apps/operations/suite_test.go index 37e2e881c638..5b6d51f81cec 100644 --- a/controllers/apps/operations/suite_test.go +++ b/controllers/apps/operations/suite_test.go @@ -65,9 +65,10 @@ var testCtx testutil.TestContext var eventRecorder record.EventRecorder const ( - statelessComp = "stateless" - statefulComp = "stateful" - consensusComp = "consensus" + statelessComp = "stateless" + statefulComp = "stateful" + consensusComp = "consensus" + defaultCompName = "default" ) func init() { @@ -156,6 +157,7 @@ func initOperationsResources(clusterDefinitionName, clusterName string) (*OpsRes Cluster: clusterObject, Recorder: k8sManager.GetEventRecorderFor("opsrequest-controller"), } + By("mock cluster is Running and the status operations") Expect(testapps.ChangeObjStatus(&testCtx, clusterObject, func() { clusterObject.Status.Phase = appsv1alpha1.RunningClusterPhase @@ -175,6 +177,38 @@ func initOperationsResources(clusterDefinitionName, clusterName string) (*OpsRes return opsRes, clusterDef, clusterObject } +func initOperationsResources2(compDefName, clusterName string) (*OpsResource, *appsv1alpha1.ComponentDefinition, *appsv1alpha1.Cluster) { + compDef := testapps.NewComponentDefinitionFactory(compDefName). + SetDefaultSpec(). + Create(&testCtx). + GetObject() + + pvcSpec := testapps.NewPVCSpec("1Gi") + clusterObject := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). + AddComponentV2(defaultCompName, compDef.GetName()). + SetReplicas(1). + AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). + Create(&testCtx). + GetObject() + + opsRes := &OpsResource{ + Cluster: clusterObject, + Recorder: k8sManager.GetEventRecorderFor("opsrequest-controller"), + } + + By("mock cluster is Running and the status operations") + Expect(testapps.ChangeObjStatus(&testCtx, clusterObject, func() { + clusterObject.Status.Phase = appsv1alpha1.RunningClusterPhase + clusterObject.Status.Components = map[string]appsv1alpha1.ClusterComponentStatus{ + defaultCompName: { + Phase: appsv1alpha1.RunningClusterCompPhase, + }, + } + })).Should(Succeed()) + opsRes.Cluster = clusterObject + return opsRes, compDef, clusterObject +} + func initInstanceSetPods(ctx context.Context, cli client.Client, opsRes *OpsResource) []*corev1.Pod { // mock the pods of consensusSet component testapps.MockInstanceSetPods(&testCtx, nil, opsRes.Cluster, consensusComp) diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml index 6e12486aa79c..a361e5925efe 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml @@ -89,187 +89,6 @@ spec: Deprecated: Use ComponentDefinition instead. This type is deprecated as of version 0.8. properties: - configSpecs: - description: Defines the template of configurations. - items: - properties: - asEnvFrom: - description: |- - Specifies the containers to inject the ConfigMap parameters as environment variables. - - - This is useful when application images accept parameters through environment variables and - generate the final configuration file in the startup script based on these variables. - - - This field allows users to specify a list of container names, and KubeBlocks will inject the environment - variables converted from the ConfigMap into these designated containers. This provides a flexible way to - pass the configuration items from the ConfigMap to the container without modifying the image. - - - Deprecated: `asEnvFrom` has been deprecated since 0.9.0 and will be removed in 0.10.0. - Use `injectEnvTo` instead. - items: - type: string - type: array - x-kubernetes-list-type: set - constraintRef: - description: Specifies the name of the referenced configuration - constraints object. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - defaultMode: - description: |- - The operator attempts to set default file permissions for scripts (0555) and configurations (0444). - However, certain database engines may require different file permissions. - You can specify the desired file permissions here. - - - Must be specified as an octal value between 0000 and 0777 (inclusive), - or as a decimal value between 0 and 511 (inclusive). - YAML supports both octal and decimal values for file permissions. - - - Please note that this setting only affects the permissions of the files themselves. - Directories within the specified path are not impacted by this setting. - It's important to be aware that this setting might conflict with other options - that influence the file mode, such as fsGroup. - In such cases, the resulting file mode may have additional bits set. - Refers to documents of k8s.ConfigMapVolumeSource.defaultMode for more information. - format: int32 - type: integer - injectEnvTo: - description: |- - Specifies the containers to inject the ConfigMap parameters as environment variables. - - - This is useful when application images accept parameters through environment variables and - generate the final configuration file in the startup script based on these variables. - - - This field allows users to specify a list of container names, and KubeBlocks will inject the environment - variables converted from the ConfigMap into these designated containers. This provides a flexible way to - pass the configuration items from the ConfigMap to the container without modifying the image. - items: - type: string - type: array - x-kubernetes-list-type: set - keys: - description: |- - Specifies the configuration files within the ConfigMap that support dynamic updates. - - - A configuration template (provided in the form of a ConfigMap) may contain templates for multiple - configuration files. - Each configuration file corresponds to a key in the ConfigMap. - Some of these configuration files may support dynamic modification and reloading without requiring - a pod restart. - - - If empty or omitted, all configuration files in the ConfigMap are assumed to support dynamic updates, - and ConfigConstraint applies to all keys. - items: - type: string - type: array - x-kubernetes-list-type: set - legacyRenderedConfigSpec: - description: |- - Specifies the secondary rendered config spec for pod-specific customization. - - - The template is rendered inside the pod (by the "config-manager" sidecar container) and merged with the main - template's render result to generate the final configuration file. - - - This field is intended to handle scenarios where different pods within the same Component have - varying configurations. It allows for pod-specific customization of the configuration. - - - Note: This field will be deprecated in future versions, and the functionality will be moved to - `cluster.spec.componentSpecs[*].instances[*]`. - properties: - namespace: - default: default - description: |- - Specifies the namespace of the referenced configuration template ConfigMap object. - An empty namespace is equivalent to the "default" namespace. - pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ - type: string - policy: - default: none - description: Defines the strategy for merging externally - imported templates into component templates. - enum: - - patch - - replace - - none - type: string - templateRef: - description: Specifies the name of the referenced - configuration template ConfigMap object. - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - required: - - templateRef - type: object - name: - description: Specifies the name of the configuration template. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - namespace: - default: default - description: |- - Specifies the namespace of the referenced configuration template ConfigMap object. - An empty namespace is equivalent to the "default" namespace. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ - type: string - reRenderResourceTypes: - description: |- - Specifies whether the configuration needs to be re-rendered after v-scale or h-scale operations to reflect changes. - - - In some scenarios, the configuration may need to be updated to reflect the changes in resource allocation - or cluster topology. Examples: - - - - Redis: adjust maxmemory after v-scale operation. - - MySQL: increase max connections after v-scale operation. - - Zookeeper: update zoo.cfg with new node addresses after h-scale operation. - items: - description: RerenderResourceType defines the resource - requirements for a component. - enum: - - vscale - - hscale - - tls - type: string - type: array - x-kubernetes-list-type: set - templateRef: - description: Specifies the name of the referenced configuration - template ConfigMap object. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - volumeName: - description: |- - Refers to the volume name of PodTemplate. The configuration file produced through the configuration - template will be mounted to the corresponding volume. Must be a DNS_LABEL name. - The volume name must be defined in podSpec.containers[*].volumeMounts. - maxLength: 63 - pattern: ^[a-z]([a-z0-9\-]*[a-z0-9])?$ - type: string - required: - - name - - volumeName - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map consensusSpec: description: Defines spec for `Consensus` workloads. It's required if the workload type is `Consensus`. @@ -459,38 +278,6 @@ spec: This only works if Type is not None. If not specified, the first volumeMount will be selected. type: string type: object - logConfigs: - description: Specify the logging files which can be observed - and configured by cluster users. - items: - properties: - filePathPattern: - description: |- - Specifies the paths or patterns identifying where the log files are stored. - This field allows the system to locate and manage log files effectively. - - - Examples: - - - - /home/postgres/pgdata/pgroot/data/log/postgresql-* - - /data/mysql/log/mysqld-error.log - maxLength: 4096 - type: string - name: - description: |- - Specifies a descriptive label for the log type, such as 'slow' for a MySQL slow log file. - It provides a clear identification of the log's purpose and content. - maxLength: 128 - type: string - required: - - filePathPattern - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map name: description: |- This name could be used as default name of `cluster.spec.componentSpecs.name`, and needs to conform with same @@ -8390,65 +8177,6 @@ spec: type: object type: array type: object - scriptSpecs: - description: Defines the template of scripts. - items: - properties: - defaultMode: - description: |- - The operator attempts to set default file permissions for scripts (0555) and configurations (0444). - However, certain database engines may require different file permissions. - You can specify the desired file permissions here. - - - Must be specified as an octal value between 0000 and 0777 (inclusive), - or as a decimal value between 0 and 511 (inclusive). - YAML supports both octal and decimal values for file permissions. - - - Please note that this setting only affects the permissions of the files themselves. - Directories within the specified path are not impacted by this setting. - It's important to be aware that this setting might conflict with other options - that influence the file mode, such as fsGroup. - In such cases, the resulting file mode may have additional bits set. - Refers to documents of k8s.ConfigMapVolumeSource.defaultMode for more information. - format: int32 - type: integer - name: - description: Specifies the name of the configuration template. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - namespace: - default: default - description: |- - Specifies the namespace of the referenced configuration template ConfigMap object. - An empty namespace is equivalent to the "default" namespace. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ - type: string - templateRef: - description: Specifies the name of the referenced configuration - template ConfigMap object. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - volumeName: - description: |- - Refers to the volume name of PodTemplate. The configuration file produced through the configuration - template will be mounted to the corresponding volume. Must be a DNS_LABEL name. - The volume name must be defined in podSpec.containers[*].volumeMounts. - maxLength: 63 - pattern: ^[a-z]([a-z0-9\-]*[a-z0-9])?$ - type: string - required: - - name - - volumeName - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map service: description: Defines the service spec. properties: diff --git a/docs/developer_docs/api-reference/cluster.md b/docs/developer_docs/api-reference/cluster.md index a882a91cb360..ad42c2ff06fd 100644 --- a/docs/developer_docs/api-reference/cluster.md +++ b/docs/developer_docs/api-reference/cluster.md @@ -4066,34 +4066,6 @@ WorkloadType -configSpecs
    - - -[]ComponentConfigSpec - - - - -(Optional) -

    Defines the template of configurations.

    - - - - -scriptSpecs
    - - -[]ComponentTemplateSpec - - - - -(Optional) -

    Defines the template of scripts.

    - - - - probes
    @@ -4108,20 +4080,6 @@ ClusterDefinitionProbes -logConfigs
    - -
    -[]LogConfig - - - - -(Optional) -

    Specify the logging files which can be observed and configured by cluster users.

    - - - - podSpec
    @@ -6694,7 +6652,7 @@ MatchExpressions

    ComponentConfigSpec

    -(Appears on:ClusterComponentDefinition, ComponentDefinitionSpec, ConfigurationItemDetail) +(Appears on:ComponentDefinitionSpec, ConfigurationItemDetail)

    @@ -8739,7 +8697,7 @@ ProvisionSecretRef

    ComponentTemplateSpec

    -(Appears on:ClusterComponentDefinition, ComponentConfigSpec, ComponentDefinitionSpec) +(Appears on:ComponentConfigSpec, ComponentDefinitionSpec)

    @@ -12464,7 +12422,7 @@ Then the controller will interact with these actions via GRPCAction calls.

    LogConfig

    -(Appears on:ClusterComponentDefinition, ComponentDefinitionSpec) +(Appears on:ComponentDefinitionSpec)

    diff --git a/pkg/configuration/core/configtemplate_util.go b/pkg/configuration/core/configtemplate_util.go deleted file mode 100644 index 080eaa3bcecf..000000000000 --- a/pkg/configuration/core/configtemplate_util.go +++ /dev/null @@ -1,76 +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 core - -import ( - appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" -) - -type ComponentsType interface { - appsv1alpha1.ClusterComponentDefinition | appsv1alpha1.ClusterComponentSpec -} - -type filterFn[T ComponentsType] func(o T) bool - -func filter[T ComponentsType](components []T, f filterFn[T]) *T { - for _, c := range components { - if f(c) { - return &c - } - } - return nil -} - -// GetConfigTemplatesFromComponent returns ConfigTemplate list used by the component -func GetConfigTemplatesFromComponent( - cComponents []appsv1alpha1.ClusterComponentSpec, - dComponents []appsv1alpha1.ClusterComponentDefinition, - componentName string) ([]appsv1alpha1.ComponentConfigSpec, error) { - findCompTypeByName := func(comName string) *appsv1alpha1.ClusterComponentSpec { - return filter(cComponents, func(o appsv1alpha1.ClusterComponentSpec) bool { - return o.Name == comName - }) - } - - cCom := findCompTypeByName(componentName) - if cCom == nil { - return nil, MakeError("failed to find component[%s]", componentName) - } - dCom := filter(dComponents, func(o appsv1alpha1.ClusterComponentDefinition) bool { - return o.Name == cCom.ComponentDefRef - }) - - if dCom != nil { - return dCom.ConfigSpecs, nil - } - return nil, nil -} - -func IsSupportConfigFileReconfigure(configTemplateSpec appsv1alpha1.ComponentConfigSpec, configFileKey string) bool { - if len(configTemplateSpec.Keys) == 0 { - return true - } - for _, keySelector := range configTemplateSpec.Keys { - if keySelector == configFileKey { - return true - } - } - return false -} diff --git a/pkg/configuration/core/configtemplate_util_test.go b/pkg/configuration/core/configtemplate_util_test.go deleted file mode 100644 index 18f514229917..000000000000 --- a/pkg/configuration/core/configtemplate_util_test.go +++ /dev/null @@ -1,171 +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 core - -import ( - "testing" - - "github.com/stretchr/testify/require" - - appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" -) - -func TestGetConfigTemplatesFromComponent(t *testing.T) { - var ( - comName = "replicats_name" - comType = "replicats" - cComponents = []appsv1alpha1.ClusterComponentSpec{ - { - Name: comName, - ComponentDefRef: comType, - }, - } - tpl = appsv1alpha1.ComponentConfigSpec{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "tpl1", - TemplateRef: "cm1", - VolumeName: "volum1", - }, - } - ) - - type args struct { - cComponents []appsv1alpha1.ClusterComponentSpec - dComponents []appsv1alpha1.ClusterComponentDefinition - comName string - } - tests := []struct { - name string - args args - want []appsv1alpha1.ComponentConfigSpec - wantErr bool - }{ - { - name: "normal_test", - args: args{ - comName: comName, - cComponents: cComponents, - dComponents: []appsv1alpha1.ClusterComponentDefinition{{ - Name: comType, - ConfigSpecs: []appsv1alpha1.ComponentConfigSpec{tpl}, - }}, - }, - want: []appsv1alpha1.ComponentConfigSpec{ - tpl, - }, - wantErr: false, - }, - { - name: "failed_test", - args: args{ - comName: "not exist component", - cComponents: cComponents, - dComponents: []appsv1alpha1.ClusterComponentDefinition{{ - Name: comType, - ConfigSpecs: []appsv1alpha1.ComponentConfigSpec{tpl}, - }}, - }, - want: nil, - wantErr: true, - }, { - name: "not_exist_and_not_failed", - args: args{ - comName: comName, - cComponents: cComponents, - dComponents: []appsv1alpha1.ClusterComponentDefinition{{ - Name: comType, - ConfigSpecs: []appsv1alpha1.ComponentConfigSpec{tpl}, - }}, - }, - want: []appsv1alpha1.ComponentConfigSpec{ - tpl, - }, - wantErr: false, - }, - } - - for _, tt := range tests { - got, err := GetConfigTemplatesFromComponent( - tt.args.cComponents, - tt.args.dComponents, - tt.args.comName) - require.Equal(t, err != nil, tt.wantErr) - require.EqualValues(t, got, tt.want) - } -} - -func TestIsSupportConfigFileReconfigure(t *testing.T) { - mockTemplateSpec := func() appsv1alpha1.ComponentTemplateSpec { - return appsv1alpha1.ComponentTemplateSpec{ - Name: "tpl", - TemplateRef: "config", - VolumeName: "volume", - } - } - - type args struct { - configTemplateSpec appsv1alpha1.ComponentConfigSpec - configFileKey string - } - tests := []struct { - name string - args args - want bool - }{{ - name: "not_key_test", - args: args{ - configTemplateSpec: appsv1alpha1.ComponentConfigSpec{ - ConfigConstraintRef: "cc", - ComponentTemplateSpec: mockTemplateSpec(), - }, - configFileKey: "test_config", - }, - want: true, - }, { - name: "not_exit_key_test", - args: args{ - configTemplateSpec: appsv1alpha1.ComponentConfigSpec{ - ConfigConstraintRef: "cc", - ComponentTemplateSpec: mockTemplateSpec(), - Keys: []string{"config1", "config2"}, - }, - configFileKey: "test_config", - }, - want: false, - }, { - name: "exit_key_test", - args: args{ - configTemplateSpec: appsv1alpha1.ComponentConfigSpec{ - ConfigConstraintRef: "cc", - ComponentTemplateSpec: mockTemplateSpec(), - Keys: []string{"test_config", "config2"}, - }, - configFileKey: "test_config", - }, - want: true, - }} - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := IsSupportConfigFileReconfigure(tt.args.configTemplateSpec, tt.args.configFileKey); got != tt.want { - t.Errorf("IsSupportConfigFileReconfigure() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/pkg/controller/component/definition_convertor.go b/pkg/controller/component/definition_convertor.go index 107419fe4014..2ae9fa30ae66 100644 --- a/pkg/controller/component/definition_convertor.go +++ b/pkg/controller/component/definition_convertor.go @@ -241,24 +241,21 @@ func (c *compDefServicesConvertor) roleSelector(clusterCompDef *appsv1alpha1.Clu type compDefConfigsConvertor struct{} func (c *compDefConfigsConvertor) convert(args ...any) (any, error) { - clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - return clusterCompDef.ConfigSpecs, nil + return nil, nil } // compDefLogConfigsConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.LogConfigs. type compDefLogConfigsConvertor struct{} func (c *compDefLogConfigsConvertor) convert(args ...any) (any, error) { - clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - return clusterCompDef.LogConfigs, nil + return nil, nil } // compDefScriptsConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.Scripts. type compDefScriptsConvertor struct{} func (c *compDefScriptsConvertor) convert(args ...any) (any, error) { - clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - return clusterCompDef.ScriptSpecs, nil + return nil, nil } // compDefPolicyRulesConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.PolicyRules. diff --git a/pkg/controller/component/definition_convertor_test.go b/pkg/controller/component/definition_convertor_test.go index 89d27edbd135..0977279a2b8a 100644 --- a/pkg/controller/component/definition_convertor_test.go +++ b/pkg/controller/component/definition_convertor_test.go @@ -43,8 +43,6 @@ var _ = Describe("Component Definition Convertor", func() { dataVolumeName = "data" logVolumeName = "log" - defaultVolumeMode = int32(0555) - runAsUser = int64(0) runAsNonRoot = false ) @@ -66,25 +64,6 @@ var _ = Describe("Component Definition Convertor", func() { clusterCompDef = &appsv1alpha1.ClusterComponentDefinition{ Name: "mysql", WorkloadType: appsv1alpha1.Consensus, - ConfigSpecs: []appsv1alpha1.ComponentConfigSpec{ - { - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "mysql-config", - TemplateRef: "mysql-config-template", - VolumeName: "mysql-config", - DefaultMode: &defaultVolumeMode, - }, - ConfigConstraintRef: "mysql-config-constraints", - }, - }, - ScriptSpecs: []appsv1alpha1.ComponentTemplateSpec{ - { - Name: "mysql-scripts", - TemplateRef: "mysql-scripts", - VolumeName: "scripts", - DefaultMode: &defaultVolumeMode, - }, - }, Probes: &appsv1alpha1.ClusterDefinitionProbes{ RoleProbe: &appsv1alpha1.ClusterDefinitionProbe{ FailureThreshold: 3, @@ -92,20 +71,6 @@ var _ = Describe("Component Definition Convertor", func() { TimeoutSeconds: 5, }, }, - LogConfigs: []appsv1alpha1.LogConfig{ - { - Name: "error", - FilePathPattern: "/data/mysql/log/mysqld-error.log", - }, - { - Name: "slow", - FilePathPattern: "/data/mysql/log/mysqld-slowquery.log", - }, - { - Name: "general", - FilePathPattern: "/data/mysql/log/mysqld.log", - }, - }, PodSpec: &corev1.PodSpec{ Volumes: []corev1.Volume{}, Containers: []corev1.Container{ @@ -452,25 +417,21 @@ var _ = Describe("Component Definition Convertor", func() { convertor := &compDefConfigsConvertor{} res, err := convertor.convert(clusterCompDef) Expect(err).Should(Succeed()) - Expect(res).Should(BeEquivalentTo(clusterCompDef.ConfigSpecs)) + Expect(res).Should(BeNil()) }) - It("log configs", func() { - convertor := &compDefLogConfigsConvertor{} + It("scripts", func() { + convertor := &compDefScriptsConvertor{} res, err := convertor.convert(clusterCompDef) Expect(err).Should(Succeed()) - - logConfigs := res.([]appsv1alpha1.LogConfig) - Expect(logConfigs).Should(BeEquivalentTo(clusterCompDef.LogConfigs)) + Expect(res).Should(BeNil()) }) - It("scripts", func() { - convertor := &compDefScriptsConvertor{} + It("log configs", func() { + convertor := &compDefLogConfigsConvertor{} res, err := convertor.convert(clusterCompDef) Expect(err).Should(Succeed()) - - scripts := res.([]appsv1alpha1.ComponentTemplateSpec) - Expect(scripts).Should(BeEquivalentTo(clusterCompDef.ScriptSpecs)) + Expect(res).Should(BeNil()) }) It("policy rules", func() { diff --git a/pkg/controller/configuration/configuration_test.go b/pkg/controller/configuration/configuration_test.go index eb1033ca338f..4f033edd3d6a 100644 --- a/pkg/controller/configuration/configuration_test.go +++ b/pkg/controller/configuration/configuration_test.go @@ -20,6 +20,8 @@ along with this program. If not, see . package configuration import ( + "fmt" + . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" @@ -32,54 +34,60 @@ import ( testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" ) -const clusterDefName = "test-clusterdef" -const clusterName = "test-cluster" -const mysqlCompDefName = "replicasets" -const scriptConfigName = "test-script-config" -const configSpecName = "test-config-spec" -const mysqlCompName = "mysql" -const mysqlConfigName = "mysql-component-config" -const mysqlConfigConstraintName = "mysql8.0-config-constraints" -const mysqlScriptsConfigName = "apecloud-mysql-scripts" -const testConfigContent = "test-config-content" +const ( + compDefName = "test-compdef" + clusterName = "test-cluster" + configTemplateName = "test-config-template" + scriptTemplateName = "test-script-template" + mysqlCompName = "mysql" + mysqlConfigName = "mysql-component-config" + mysqlConfigConstraintName = "mysql8.0-config-constraints" + mysqlScriptsTemplateName = "apecloud-mysql-scripts" + testConfigContent = "test-config-content" +) -func allFieldsClusterDefObj(needCreate bool) *appsv1alpha1.ClusterDefinition { - clusterDefObj := testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). - AddScriptTemplate(scriptConfigName, mysqlScriptsConfigName, testCtx.DefaultNamespace, testapps.ScriptsVolumeName, nil). - AddConfigTemplate(configSpecName, mysqlConfigName, mysqlConfigConstraintName, testCtx.DefaultNamespace, testapps.ConfVolumeName). +func allFieldsCompDefObj(create bool) *appsv1alpha1.ComponentDefinition { + compDef := testapps.NewComponentDefinitionFactory(compDefName). + SetDefaultSpec(). + AddConfigTemplate(configTemplateName, mysqlConfigName, mysqlConfigConstraintName, testCtx.DefaultNamespace, testapps.ConfVolumeName). + AddScriptTemplate(scriptTemplateName, mysqlScriptsTemplateName, testCtx.DefaultNamespace, testapps.ScriptsVolumeName, nil). GetObject() - if needCreate { - Expect(testCtx.CreateObj(testCtx.Ctx, clusterDefObj)).Should(Succeed()) + if create { + Expect(testCtx.CreateObj(testCtx.Ctx, compDef)).Should(Succeed()) } - return clusterDefObj + return compDef } -func newAllFieldsClusterObj(clusterDefObj *appsv1alpha1.ClusterDefinition, needCreate bool) (*appsv1alpha1.Cluster, *appsv1alpha1.ClusterDefinition, types.NamespacedName) { - // setup Cluster obj requires default ClusterDefinition object - if clusterDefObj == nil { - clusterDefObj = allFieldsClusterDefObj(needCreate) +func newAllFieldsClusterObj(compDef *appsv1alpha1.ComponentDefinition, create bool) (*appsv1alpha1.Cluster, *appsv1alpha1.ComponentDefinition, types.NamespacedName) { + // setup Cluster obj requires default ComponentDefinition object + if compDef == nil { + compDef = allFieldsCompDefObj(create) } pvcSpec := testapps.NewPVCSpec("1Gi") - clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). - AddComponent(mysqlCompName, mysqlCompDefName).SetReplicas(1). + clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). + AddComponentV2(mysqlCompName, compDef.Name). + SetReplicas(1). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). AddComponentService(testapps.ServiceVPCName, corev1.ServiceTypeLoadBalancer). AddComponentService(testapps.ServiceInternetName, corev1.ServiceTypeLoadBalancer). GetObject() key := client.ObjectKeyFromObject(clusterObj) - if needCreate { + if create { Expect(testCtx.CreateObj(testCtx.Ctx, clusterObj)).Should(Succeed()) } - return clusterObj, clusterDefObj, key + return clusterObj, compDef, key } -func newAllFieldsSynthesizedComponent(clusterDef *appsv1alpha1.ClusterDefinition, cluster *appsv1alpha1.Cluster) *component.SynthesizedComponent { +func newAllFieldsSynthesizedComponent(compDef *appsv1alpha1.ComponentDefinition, cluster *appsv1alpha1.Cluster) *component.SynthesizedComponent { reqCtx := intctrlutil.RequestCtx{ Ctx: testCtx.Ctx, Log: logger, } - synthesizeComp, err := component.BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, cluster, &cluster.Spec.ComponentSpecs[0]) + 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) 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 ef2a4b17ea88..5c340a35968e 100644 --- a/pkg/controller/configuration/envfrom_utils_test.go +++ b/pkg/controller/configuration/envfrom_utils_test.go @@ -36,17 +36,15 @@ import ( ) var _ = Describe("ConfigEnvFrom test", func() { - const ( - clusterDefName = "test-clusterdef" - clusterName = "test-cluster" - - mysqlCompDefName = "replicasets" - mysqlCompName = "mysql" + compDefName = "test-compdef" + clusterName = "test-cluster" + mysqlCompName = "mysql" ) + var ( - clusterDef *appsv1alpha1.ClusterDefinition - cluster *appsv1alpha1.Cluster + compDef *appsv1alpha1.ComponentDefinition + cluster *appsv1alpha1.Cluster k8sMockClient *testutil.K8sClientMockHelper origCMObject *corev1.ConfigMap @@ -62,13 +60,14 @@ var _ = Describe("ConfigEnvFrom test", func() { configConstraint = testapps.NewCustomizedObj("config/envfrom-constraint.yaml", &appsv1beta1.ConfigConstraint{}) - clusterDef = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). + compDef = testapps.NewComponentDefinitionFactory(compDefName). + SetDefaultSpec(). AddConfigTemplate(cm.Name, cm.Name, configConstraint.Name, testCtx.DefaultNamespace, "mysql-config", testapps.DefaultMySQLContainerName). GetObject() + pvcSpec := testapps.NewPVCSpec("1Gi") - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). - AddComponent(mysqlCompName, mysqlCompDefName). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). + AddComponentV2(mysqlCompName, compDef.Name). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). GetObject() @@ -86,7 +85,10 @@ var _ = Describe("ConfigEnvFrom test", func() { Ctx: ctx, Log: logger, } - synthesizeComp, err := component.BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, cluster, &cluster.Spec.ComponentSpecs[0]) + 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) Expect(err).Should(Succeed()) podSpec := &corev1.PodSpec{ @@ -96,19 +98,22 @@ var _ = Describe("ConfigEnvFrom test", func() { }, }, } - k8sMockClient.MockGetMethod(testutil.WithGetReturned(testutil.WithConstructSimpleGetResult([]client.Object{ - origCMObject, - configConstraint, - }), testutil.WithAnyTimes())) - k8sMockClient.MockCreateMethod(testutil.WithCreateReturned(testutil.WithCreatedFailedResult(), testutil.WithTimes(1)), - testutil.WithCreateReturned(testutil.WithCreatedSucceedResult(), testutil.WithAnyTimes())) + k8sMockClient.MockGetMethod( + testutil.WithGetReturned(testutil.WithConstructSimpleGetResult([]client.Object{ + origCMObject, + configConstraint, + }), testutil.WithAnyTimes())) + k8sMockClient.MockCreateMethod( + testutil.WithCreateReturned(testutil.WithCreatedFailedResult(), testutil.WithTimes(1)), + testutil.WithCreateReturned(testutil.WithCreatedSucceedResult(), testutil.WithAnyTimes()), + ) Expect(injectTemplateEnvFrom(cluster, synthesizeComp, podSpec, k8sMockClient.Client(), reqCtx.Ctx, nil)).ShouldNot(Succeed()) Expect(injectTemplateEnvFrom(cluster, synthesizeComp, podSpec, k8sMockClient.Client(), reqCtx.Ctx, nil)).Should(Succeed()) }) It("should SyncEnvConfigmap success", func() { - configSpec := clusterDef.Spec.ComponentDefs[0].ConfigSpecs[0] + configSpec := compDef.Spec.Configs[0] configSpec.Keys = []string{"env-config"} cmObj := origCMObject.DeepCopy() @@ -125,7 +130,7 @@ var _ = Describe("ConfigEnvFrom test", func() { }) It("SyncEnvConfigmap abnormal test", func() { - configSpec := clusterDef.Spec.ComponentDefs[0].ConfigSpecs[0] + configSpec := compDef.Spec.Configs[0] configSpec.InjectEnvTo = nil Expect(SyncEnvConfigmap(configSpec, origCMObject, &configConstraint.Spec, k8sMockClient.Client(), ctx)).Should(Succeed()) @@ -138,11 +143,9 @@ var _ = Describe("ConfigEnvFrom test", func() { }), testutil.WithAnyTimes())) k8sMockClient.MockPatchMethod(testutil.WithSucceed(testutil.WithAnyTimes())) - configSpec = clusterDef.Spec.ComponentDefs[0].ConfigSpecs[0] + configSpec = compDef.Spec.Configs[0] configSpec.Keys = []string{"env-config", "not-exist"} Expect(SyncEnvConfigmap(configSpec, origCMObject, &configConstraint.Spec, k8sMockClient.Client(), ctx)).Should(Succeed()) }) - }) - }) diff --git a/pkg/controller/configuration/operator_test.go b/pkg/controller/configuration/operator_test.go index 82747e53d8ed..147c74790e75 100644 --- a/pkg/controller/configuration/operator_test.go +++ b/pkg/controller/configuration/operator_test.go @@ -40,7 +40,7 @@ import ( var _ = Describe("ConfigurationOperatorTest", func() { var clusterObj *appsv1alpha1.Cluster - var clusterDefObj *appsv1alpha1.ClusterDefinition + var compDefObj *appsv1alpha1.ComponentDefinition var componentObj *appsv1alpha1.Component var synthesizedComponent *component.SynthesizedComponent var configMapObj *corev1.ConfigMap @@ -68,12 +68,12 @@ var _ = Describe("ConfigurationOperatorTest", func() { BeforeEach(func() { // Add any setup steps that needs to be executed before each test k8sMockClient = testutil.NewK8sMockClient() - clusterObj, clusterDefObj, _ = newAllFieldsClusterObj(nil, false) - synthesizedComponent = newAllFieldsSynthesizedComponent(clusterDefObj, clusterObj) + clusterObj, compDefObj, _ = newAllFieldsClusterObj(nil, false) + synthesizedComponent = newAllFieldsSynthesizedComponent(compDefObj, clusterObj) componentObj = newAllFieldsComponent(clusterObj) configMapObj = testapps.NewConfigMap("default", mysqlConfigName, testapps.SetConfigMapData("test", "test")) - scriptsObj = testapps.NewConfigMap("default", mysqlScriptsConfigName, + scriptsObj = testapps.NewConfigMap("default", mysqlScriptsTemplateName, testapps.SetConfigMapData("script.sh", "echo \"hello\"")) configurationObj = builder.NewConfigurationBuilder(testCtx.DefaultNamespace, cfgcore.GenerateComponentConfigurationName(clusterName, mysqlCompName)). @@ -111,7 +111,7 @@ var _ = Describe("ConfigurationOperatorTest", func() { It("NormalTest", func() { k8sMockClient.MockGetMethod(testutil.WithGetReturned(testutil.WithConstructSimpleGetResult( []client.Object{ - clusterDefObj, + compDefObj, clusterObj, clusterObj, scriptsObj, @@ -147,7 +147,7 @@ var _ = Describe("ConfigurationOperatorTest", func() { k8sMockClient.MockCreateMethod(testutil.WithCreateReturned(testutil.WithCreatedSucceedResult(), testutil.WithTimes(1))) k8sMockClient.MockGetMethod(testutil.WithGetReturned(testutil.WithConstructSimpleGetResult( []client.Object{ - clusterDefObj, + compDefObj, clusterObj, clusterObj, }, diff --git a/pkg/controller/configuration/pipeline_test.go b/pkg/controller/configuration/pipeline_test.go index 341468f51e07..40a99f2f783a 100644 --- a/pkg/controller/configuration/pipeline_test.go +++ b/pkg/controller/configuration/pipeline_test.go @@ -46,7 +46,7 @@ var _ = Describe("ConfigurationPipelineTest", func() { var clusterObj *appsv1alpha1.Cluster var componentObj *appsv1alpha1.Component - var clusterDefObj *appsv1alpha1.ClusterDefinition + var compDefObj *appsv1alpha1.ComponentDefinition var synthesizedComponent *component.SynthesizedComponent var configMapObj *corev1.ConfigMap var configConstraint *appsv1beta1.ConfigConstraint @@ -56,7 +56,7 @@ var _ = Describe("ConfigurationPipelineTest", func() { mockAPIResource := func(lazyFetcher testutil.Getter) { k8sMockClient.MockGetMethod(testutil.WithGetReturned(testutil.WithConstructSimpleGetResult( []client.Object{ - clusterDefObj, + compDefObj, clusterObj, clusterObj, configMapObj, @@ -91,9 +91,9 @@ var _ = Describe("ConfigurationPipelineTest", func() { BeforeEach(func() { // Add any setup steps that needs to be executed before each test k8sMockClient = testutil.NewK8sMockClient() - clusterObj, clusterDefObj, _ = newAllFieldsClusterObj(nil, false) + clusterObj, compDefObj, _ = newAllFieldsClusterObj(nil, false) componentObj = newAllFieldsComponent(clusterObj) - synthesizedComponent = newAllFieldsSynthesizedComponent(clusterDefObj, clusterObj) + synthesizedComponent = newAllFieldsSynthesizedComponent(compDefObj, clusterObj) configMapObj = testapps.NewConfigMap("default", mysqlConfigName, testapps.SetConfigMapData(testConfigFile, ` bgwriter_delay = '200ms' @@ -195,7 +195,7 @@ max_connections = '1000' By("update configuration resource") err = reconcileTask.InitConfigSpec(). Configuration(). - ConfigMap(configSpecName). + ConfigMap(configTemplateName). ConfigConstraints(reconcileTask.ConfigSpec().ConfigConstraintRef). PrepareForTemplate(). RerenderTemplate(). @@ -210,7 +210,7 @@ max_connections = '1000' reconcileTask.item.Version = "v2" err = reconcileTask.InitConfigSpec(). Configuration(). - ConfigMap(configSpecName). + ConfigMap(configTemplateName). ConfigConstraints(reconcileTask.ConfigSpec().ConfigConstraintRef). PrepareForTemplate(). RerenderTemplate(). diff --git a/pkg/controller/configuration/resource_wrapper_test.go b/pkg/controller/configuration/resource_wrapper_test.go index 2a88bf3d620e..9d806abe420c 100644 --- a/pkg/controller/configuration/resource_wrapper_test.go +++ b/pkg/controller/configuration/resource_wrapper_test.go @@ -56,7 +56,6 @@ var _ = Describe("resource Fetcher", func() { k8sMockClient = testutil.NewK8sMockClient() clusterDef = testapps.NewClusterDefFactory(clusterDefName). AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). - AddConfigTemplate(mysqlConfigName, mysqlConfigName, mysqlConfigName, "default", mysqlVolumeName). GetObject() pvcSpec := testapps.NewPVCSpec("1Gi") cluster = testapps.NewClusterFactory("default", clusterName, clusterDef.Name). diff --git a/pkg/controller/configuration/template_wrapper_test.go b/pkg/controller/configuration/template_wrapper_test.go index 0bf686a143c6..52642f4bce7d 100644 --- a/pkg/controller/configuration/template_wrapper_test.go +++ b/pkg/controller/configuration/template_wrapper_test.go @@ -39,7 +39,7 @@ var _ = Describe("TemplateWrapperTest", func() { var mockK8sCli *testutil.K8sClientMockHelper var clusterObj *appsv1alpha1.Cluster var componentObj *appsv1alpha1.Component - var clusterDefObj *appsv1alpha1.ClusterDefinition + var compDefObj *appsv1alpha1.ComponentDefinition var clusterComponent *component.SynthesizedComponent mockTemplateWrapper := func() renderWrapper { @@ -52,8 +52,8 @@ var _ = Describe("TemplateWrapperTest", func() { // Add any setup steps that needs to be executed before each test mockK8sCli = testutil.NewK8sMockClient() - clusterObj, clusterDefObj, _ = newAllFieldsClusterObj(nil, false) - clusterComponent = newAllFieldsSynthesizedComponent(clusterDefObj, clusterObj) + clusterObj, compDefObj, _ = newAllFieldsClusterObj(nil, false) + clusterComponent = newAllFieldsSynthesizedComponent(compDefObj, clusterObj) componentObj = newAllFieldsComponent(clusterObj) }) @@ -66,11 +66,11 @@ var _ = Describe("TemplateWrapperTest", func() { mockK8sCli.MockGetMethod(testutil.WithGetReturned(testutil.WithConstructSimpleGetResult([]client.Object{ &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: configSpecName, + Name: configTemplateName, Namespace: testCtx.DefaultNamespace, }, Data: map[string]string{ - configSpecName: testConfigContent, + configTemplateName: testConfigContent, }, }, }), testutil.WithAnyTimes())) @@ -87,7 +87,7 @@ var _ = Describe("TemplateWrapperTest", func() { Namespace: testCtx.DefaultNamespace, }, Data: map[string]string{ - configSpecName: testConfigContent, + configTemplateName: testConfigContent, }, }, }), testutil.WithAnyTimes())) @@ -109,12 +109,12 @@ var _ = Describe("TemplateWrapperTest", func() { }, }, Data: map[string]string{ - configSpecName: testConfigContent, + configTemplateName: testConfigContent, }, }, &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: configSpecName, + Name: configTemplateName, Namespace: testCtx.DefaultNamespace, Labels: make(map[string]string), Annotations: make(map[string]string), @@ -125,7 +125,7 @@ var _ = Describe("TemplateWrapperTest", func() { }, &appsv1beta1.ConfigConstraint{ ObjectMeta: metav1.ObjectMeta{ - Name: configSpecName, + Name: configTemplateName, }, Spec: appsv1beta1.ConfigConstraintSpec{ FileFormatConfig: &appsv1beta1.FileFormatConfig{ @@ -141,7 +141,6 @@ var _ = Describe("TemplateWrapperTest", func() { tplWrapper := mockTemplateWrapper() Expect(tplWrapper.renderConfigTemplate(clusterObj, clusterComponent, nil, nil)).Should(Succeed()) }) - }) Context("TestScriptsSpec", func() { @@ -150,11 +149,11 @@ var _ = Describe("TemplateWrapperTest", func() { mockK8sCli.MockGetMethod(testutil.WithGetReturned(testutil.WithConstructSimpleGetResult([]client.Object{ &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: mysqlScriptsConfigName, + Name: mysqlScriptsTemplateName, Namespace: testCtx.DefaultNamespace, }, Data: map[string]string{ - configSpecName: testConfigContent, + configTemplateName: testConfigContent, }, }, }), testutil.WithAnyTimes())) @@ -170,7 +169,7 @@ var _ = Describe("TemplateWrapperTest", func() { Namespace: testCtx.DefaultNamespace, }, Data: map[string]string{ - configSpecName: testConfigContent, + configTemplateName: testConfigContent, }, } tplWrapper := mockTemplateWrapper() diff --git a/pkg/controller/configuration/tool_image_builder_test.go b/pkg/controller/configuration/tool_image_builder_test.go index 1f9f54478db6..7dce61457802 100644 --- a/pkg/controller/configuration/tool_image_builder_test.go +++ b/pkg/controller/configuration/tool_image_builder_test.go @@ -39,13 +39,13 @@ var _ = Describe("ToolsImageBuilderTest", func() { var noneCommand = []string{"/bin/true"} var clusterObj *appsv1alpha1.Cluster - var ClusterDefObj *appsv1alpha1.ClusterDefinition + var compDefObj *appsv1alpha1.ComponentDefinition var clusterComponent *component.SynthesizedComponent BeforeEach(func() { // Add any setup steps that needs to be executed before each test - clusterObj, ClusterDefObj, _ = newAllFieldsClusterObj(nil, false) - clusterComponent = newAllFieldsSynthesizedComponent(ClusterDefObj, clusterObj) + clusterObj, compDefObj, _ = newAllFieldsClusterObj(nil, false) + clusterComponent = newAllFieldsSynthesizedComponent(compDefObj, clusterObj) viper.SetDefault(constant.KBToolsImage, kbToolsImage) }) diff --git a/pkg/controller/instanceset/object_builder.go b/pkg/controller/instanceset/object_builder.go index 8aa9d08ef4f0..6ba798462a6f 100644 --- a/pkg/controller/instanceset/object_builder.go +++ b/pkg/controller/instanceset/object_builder.go @@ -25,14 +25,15 @@ import ( "strconv" "strings" + "golang.org/x/exp/slices" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/intstr" + workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" "github.com/apecloud/kubeblocks/pkg/constant" "github.com/apecloud/kubeblocks/pkg/controller/builder" "github.com/apecloud/kubeblocks/pkg/controllerutil" viper "github.com/apecloud/kubeblocks/pkg/viperx" - "golang.org/x/exp/slices" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/util/intstr" ) func buildSvc(its workloads.InstanceSet, labels, selectors map[string]string) *corev1.Service { diff --git a/pkg/controller/plan/restore_test.go b/pkg/controller/plan/restore_test.go index c18f4e671300..ed9fe400992e 100644 --- a/pkg/controller/plan/restore_test.go +++ b/pkg/controller/plan/restore_test.go @@ -167,7 +167,6 @@ var _ = Describe("Restore", func() { clusterCompDefObj := clusterDef.Spec.ComponentDefs[0] synthesizedComponent = &component.SynthesizedComponent{ PodSpec: clusterCompDefObj.PodSpec, - LogConfigs: clusterCompDefObj.LogConfigs, HorizontalScalePolicy: clusterCompDefObj.HorizontalScalePolicy, VolumeClaimTemplates: cluster.Spec.ComponentSpecs[0].ToVolumeClaimTemplates(), Name: mysqlCompName, diff --git a/pkg/kb_agent/cronjobs/checkrole.go b/pkg/kb_agent/cronjobs/checkrole.go index d20da53a9ed5..1b600c95a556 100644 --- a/pkg/kb_agent/cronjobs/checkrole.go +++ b/pkg/kb_agent/cronjobs/checkrole.go @@ -23,9 +23,10 @@ import ( "context" "time" + "github.com/spf13/pflag" + "github.com/apecloud/kubeblocks/pkg/kb_agent/handlers" "github.com/apecloud/kubeblocks/pkg/kb_agent/util" - "github.com/spf13/pflag" ) type CheckRoleJob struct { diff --git a/pkg/kb_agent/cronjobs/job_test.go b/pkg/kb_agent/cronjobs/job_test.go index fb0df7b5fe5d..7d612bb18148 100644 --- a/pkg/kb_agent/cronjobs/job_test.go +++ b/pkg/kb_agent/cronjobs/job_test.go @@ -24,9 +24,10 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/apecloud/kubeblocks/pkg/constant" "github.com/apecloud/kubeblocks/pkg/kb_agent/util" - "github.com/stretchr/testify/assert" ) func TestNewJob(t *testing.T) { diff --git a/pkg/kb_agent/cronjobs/manager_test.go b/pkg/kb_agent/cronjobs/manager_test.go index 613af0f46f0b..f765c00af523 100644 --- a/pkg/kb_agent/cronjobs/manager_test.go +++ b/pkg/kb_agent/cronjobs/manager_test.go @@ -23,11 +23,12 @@ import ( "encoding/json" "testing" + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" + "github.com/apecloud/kubeblocks/pkg/constant" "github.com/apecloud/kubeblocks/pkg/kb_agent/handlers" "github.com/apecloud/kubeblocks/pkg/kb_agent/util" - "github.com/spf13/viper" - "github.com/stretchr/testify/assert" ) func TestNewManager(t *testing.T) { diff --git a/pkg/kb_agent/handlers/exec_handler_test.go b/pkg/kb_agent/handlers/exec_handler_test.go index b22492381f39..ecdadb334cf3 100644 --- a/pkg/kb_agent/handlers/exec_handler_test.go +++ b/pkg/kb_agent/handlers/exec_handler_test.go @@ -25,8 +25,9 @@ import ( "github.com/pkg/errors" - "github.com/apecloud/kubeblocks/pkg/kb_agent/util" "github.com/stretchr/testify/assert" + + "github.com/apecloud/kubeblocks/pkg/kb_agent/util" ) func TestNewExecHandler(t *testing.T) { diff --git a/pkg/kb_agent/handlers/grpc_handler_test.go b/pkg/kb_agent/handlers/grpc_handler_test.go index fee324cdf27b..f98b2f17796b 100644 --- a/pkg/kb_agent/handlers/grpc_handler_test.go +++ b/pkg/kb_agent/handlers/grpc_handler_test.go @@ -23,9 +23,10 @@ import ( "context" "testing" - "github.com/apecloud/kubeblocks/pkg/kb_agent/util" "github.com/pkg/errors" "github.com/stretchr/testify/assert" + + "github.com/apecloud/kubeblocks/pkg/kb_agent/util" ) func TestNewGRPCHandler(t *testing.T) { diff --git a/pkg/kb_agent/httpserver/apis_test.go b/pkg/kb_agent/httpserver/apis_test.go index 04ccb6f7cf93..e5de1f36fefc 100644 --- a/pkg/kb_agent/httpserver/apis_test.go +++ b/pkg/kb_agent/httpserver/apis_test.go @@ -26,12 +26,13 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/assert" + "github.com/valyala/fasthttp" + "github.com/apecloud/kubeblocks/pkg/constant" "github.com/apecloud/kubeblocks/pkg/kb_agent/handlers" "github.com/apecloud/kubeblocks/pkg/kb_agent/util" viper "github.com/apecloud/kubeblocks/pkg/viperx" - "github.com/stretchr/testify/assert" - "github.com/valyala/fasthttp" ) func TestEndpoints(t *testing.T) { diff --git a/pkg/kb_agent/httpserver/server_test.go b/pkg/kb_agent/httpserver/server_test.go index da21b8f766ac..698a6d7ec4db 100644 --- a/pkg/kb_agent/httpserver/server_test.go +++ b/pkg/kb_agent/httpserver/server_test.go @@ -23,10 +23,11 @@ import ( "os" "testing" - "github.com/apecloud/kubeblocks/pkg/kb_agent/util" "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/valyala/fasthttp" + + "github.com/apecloud/kubeblocks/pkg/kb_agent/util" ) func TestNewServer(t *testing.T) { diff --git a/pkg/lorry/engines/dbmanager_mock.go b/pkg/lorry/engines/dbmanager_mock.go index a2ea88b8b129..15bd8bd84732 100644 --- a/pkg/lorry/engines/dbmanager_mock.go +++ b/pkg/lorry/engines/dbmanager_mock.go @@ -29,10 +29,11 @@ import ( context "context" reflect "reflect" - dcs "github.com/apecloud/kubeblocks/pkg/lorry/dcs" - models "github.com/apecloud/kubeblocks/pkg/lorry/engines/models" logr "github.com/go-logr/logr" gomock "github.com/golang/mock/gomock" + + dcs "github.com/apecloud/kubeblocks/pkg/lorry/dcs" + models "github.com/apecloud/kubeblocks/pkg/lorry/engines/models" ) // MockDBManager is a mock of DBManager interface. diff --git a/pkg/testutil/apps/cluster_instance_set_test_util.go b/pkg/testutil/apps/cluster_instance_set_test_util.go index 6922c83559e6..036ec641fe39 100644 --- a/pkg/testutil/apps/cluster_instance_set_test_util.go +++ b/pkg/testutil/apps/cluster_instance_set_test_util.go @@ -75,9 +75,8 @@ func CreateConsensusMysqlCluster( // CreateConsensusMysqlClusterDef creates a mysql clusterDefinition with a component of ConsensusSet type. func CreateConsensusMysqlClusterDef(testCtx *testutil.TestContext, clusterDefName, componentDefName string) *appsv1alpha1.ClusterDefinition { - filePathPattern := "/data/mysql/log/mysqld.err" return NewClusterDefFactory(clusterDefName).AddComponentDef(ConsensusMySQLComponent, componentDefName). - AddLogConfig(errorLogName, filePathPattern).Create(testCtx).GetObject() + Create(testCtx).GetObject() } // MockInstanceSetComponent mocks the ITS component, just using in envTest diff --git a/pkg/testutil/apps/clusterdef_factory.go b/pkg/testutil/apps/clusterdef_factory.go index 3db66d11c9ca..3286c35bcbc0 100644 --- a/pkg/testutil/apps/clusterdef_factory.go +++ b/pkg/testutil/apps/clusterdef_factory.go @@ -105,55 +105,6 @@ func (factory *MockClusterDefFactory) AddServicePort(port int32) *MockClusterDef return factory } -func (factory *MockClusterDefFactory) AddScriptTemplate(name, - configTemplateRef, namespace, volumeName string, mode *int32) *MockClusterDefFactory { - comp := factory.getLastCompDef() - if comp == nil { - return nil - } - comp.ScriptSpecs = append(comp.ScriptSpecs, - appsv1alpha1.ComponentTemplateSpec{ - Name: name, - TemplateRef: configTemplateRef, - Namespace: namespace, - VolumeName: volumeName, - DefaultMode: mode, - }) - return factory -} - -func (factory *MockClusterDefFactory) AddConfigTemplate(name, - configTemplateRef, configConstraintRef, namespace, volumeName string, injectEnvTo ...string) *MockClusterDefFactory { - comp := factory.getLastCompDef() - if comp == nil { - return nil - } - comp.ConfigSpecs = append(comp.ConfigSpecs, - appsv1alpha1.ComponentConfigSpec{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: name, - TemplateRef: configTemplateRef, - Namespace: namespace, - VolumeName: volumeName, - }, - ConfigConstraintRef: configConstraintRef, - InjectEnvTo: injectEnvTo, - }) - return factory -} - -func (factory *MockClusterDefFactory) AddLogConfig(name, filePathPattern string) *MockClusterDefFactory { - comp := factory.getLastCompDef() - if comp == nil { - return nil - } - comp.LogConfigs = append(comp.LogConfigs, appsv1alpha1.LogConfig{ - FilePathPattern: filePathPattern, - Name: name, - }) - return factory -} - func (factory *MockClusterDefFactory) AddContainerEnv(containerName string, envVar corev1.EnvVar) *MockClusterDefFactory { comp := factory.getLastCompDef() if comp == nil { From 0565e79702bf9182e6457beb0e7e3a6c34f55579 Mon Sep 17 00:00:00 2001 From: Leon Date: Mon, 5 Aug 2024 19:13:29 +0800 Subject: [PATCH 36/45] chore: remove services, accounts and post-start from cd (#7776) --- apis/apps/v1alpha1/clusterdefinition_types.go | 205 ------- .../v1alpha1/clusterdefinition_types_test.go | 11 - apis/apps/v1alpha1/type.go | 40 -- apis/apps/v1alpha1/zz_generated.deepcopy.go | 163 ------ ...apps.kubeblocks.io_clusterdefinitions.yaml | 515 ----------------- controllers/apps/cluster_controller_test.go | 8 +- controllers/apps/component_controller_test.go | 2 +- .../componentdefinition_controller_test.go | 23 +- controllers/apps/operations/expose.go | 34 +- controllers/apps/operations/expose_test.go | 20 +- .../apps/transformer_cluster_credential.go | 22 - .../apps/transformer_cluster_service.go | 3 +- ...apps.kubeblocks.io_clusterdefinitions.yaml | 515 ----------------- docs/developer_docs/api-reference/cluster.md | 534 +----------------- pkg/controller/component/component_test.go | 168 ++---- .../component/definition_convertor.go | 89 +-- .../component/definition_convertor_test.go | 162 +----- pkg/controller/factory/builder_test.go | 50 -- pkg/testutil/apps/clusterdef_factory.go | 70 +-- pkg/testutil/apps/constant.go | 65 +-- 20 files changed, 100 insertions(+), 2599 deletions(-) diff --git a/apis/apps/v1alpha1/clusterdefinition_types.go b/apis/apps/v1alpha1/clusterdefinition_types.go index 8857e3c31e78..5551c60ddc0a 100644 --- a/apis/apps/v1alpha1/clusterdefinition_types.go +++ b/apis/apps/v1alpha1/clusterdefinition_types.go @@ -171,32 +171,6 @@ type ClusterTopologyOrders struct { Update []string `json:"update,omitempty"` } -// SystemAccountSpec specifies information to create system accounts. -// -// Deprecated since v0.8, be replaced by `componentDefinition.spec.systemAccounts` and -// `componentDefinition.spec.lifecycleActions.accountProvision`. -type SystemAccountSpec struct { - // Configures how to obtain the client SDK and execute statements. - // - // +kubebuilder:validation:Required - CmdExecutorConfig *CmdExecutorConfig `json:"cmdExecutorConfig"` - - // Defines the pattern used to generate passwords for system accounts. - // - // +kubebuilder:validation:Required - PasswordConfig PasswordConfig `json:"passwordConfig"` - - // Defines the configuration settings for system accounts. - // - // +kubebuilder:validation:Required - // +kubebuilder:validation:MinItems=1 - // +patchMergeKey=name - // +patchStrategy=merge,retainKeys - // +listType=map - // +listMapKey=name - Accounts []SystemAccountConfig `json:"accounts" patchStrategy:"merge,retainKeys" patchMergeKey:"name"` -} - // CmdExecutorConfig specifies how to perform creation and deletion statements. // // Deprecated since v0.8. @@ -244,46 +218,6 @@ type PasswordConfig struct { Seed string `json:"seed,omitempty"` } -// SystemAccountConfig specifies how to create and delete system accounts. -// -// Deprecated since v0.9. -type SystemAccountConfig struct { - // The unique identifier of a system account. - // - // +kubebuilder:validation:Required - Name AccountName `json:"name"` - - // Outlines the strategy for creating the account. - // - // +kubebuilder:validation:Required - ProvisionPolicy ProvisionPolicy `json:"provisionPolicy"` -} - -// ProvisionPolicy defines the policy details for creating accounts. -// -// Deprecated since v0.9. -type ProvisionPolicy struct { - // Specifies the method to provision an account. - // - // +kubebuilder:validation:Required - Type ProvisionPolicyType `json:"type"` - - // Defines the scope within which the account is provisioned. - // - // +kubebuilder:default=AnyPods - Scope ProvisionScope `json:"scope"` - - // The statement to provision an account. - // - // +optional - Statements *ProvisionStatements `json:"statements,omitempty"` - - // The external secret to refer. - // - // +optional - SecretRef *ProvisionSecretRef `json:"secretRef,omitempty"` -} - // ProvisionSecretRef represents the reference to a secret. type ProvisionSecretRef struct { // The unique identifier of the secret. @@ -297,30 +231,6 @@ type ProvisionSecretRef struct { Namespace string `json:"namespace"` } -// ProvisionStatements defines the statements used to create accounts. -// -// Deprecated since v0.9. -type ProvisionStatements struct { - // Specifies the statement required to create a new account with the necessary privileges. - // - // +kubebuilder:validation:Required - CreationStatement string `json:"creation"` - - // Defines the statement required to update the password of an existing account. - // - // +optional - UpdateStatement string `json:"update,omitempty"` - - // Defines the statement required to delete an existing account. - // Typically used in conjunction with the creation statement to delete an account before recreating it. - // For example, one might use a `drop user if exists` statement followed by a `create user` statement to ensure a fresh account. - // - // Deprecated: This field is deprecated and the update statement should be used instead. - // - // +optional - DeletionStatement string `json:"deletion,omitempty"` -} - // ClusterDefinitionStatus defines the observed state of ClusterDefinition type ClusterDefinitionStatus struct { // Represents the most recent generation observed for this ClusterDefinition. @@ -501,11 +411,6 @@ type ClusterComponentDefinition struct { // +optional PodSpec *corev1.PodSpec `json:"podSpec,omitempty"` - // Defines the service spec. - // - // +optional - Service *ServiceSpec `json:"service,omitempty"` - // Defines spec for `Stateless` workloads. // // +kubebuilder:deprecatedversion:warning="This field is deprecated from KB 0.7.0, use RSMSpec instead." @@ -542,23 +447,12 @@ type ClusterComponentDefinition struct { // +optional HorizontalScalePolicy *HorizontalScalePolicy `json:"horizontalScalePolicy,omitempty"` - // Defines system accounts needed to manage the component, and the statement to create them. - // - // +optional - SystemAccounts *SystemAccountSpec `json:"systemAccounts,omitempty"` - // Defines command to do switchover. // In particular, when workloadType=Replication, the command defined in switchoverSpec will only be executed under // the condition of cluster.componentSpecs[x].SwitchPolicy.type=Noop. // // +optional SwitchoverSpec *SwitchoverSpec `json:"switchoverSpec,omitempty"` - - // Defines the command to be executed when the component is ready, and the command will only be executed once after - // the component becomes ready. - // - // +optional - PostStartSpec *PostStartAction `json:"postStartSpec,omitempty"` } func (r *ClusterComponentDefinition) GetStatefulSetWorkload() StatefulSetWorkload { @@ -601,91 +495,6 @@ func (r *ClusterComponentDefinition) GetCommonStatefulSpec() (*StatefulSetSpec, return nil, nil } -// ServiceSpec is deprecated since v0.8. -type ServiceSpec struct { - // The list of ports that are exposed by this service. - // More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies - // - // +patchMergeKey=port - // +patchStrategy=merge - // +listType=map - // +listMapKey=port - // +listMapKey=protocol - // +optional - Ports []ServicePort `json:"ports,omitempty" patchStrategy:"merge" patchMergeKey:"port" protobuf:"bytes,1,rep,name=ports"` - - // NOTES: name also need to be key -} - -func (r *ServiceSpec) ToSVCPorts() []corev1.ServicePort { - ports := make([]corev1.ServicePort, 0, len(r.Ports)) - for _, p := range r.Ports { - ports = append(ports, p.toSVCPort()) - } - return ports -} - -func (r ServiceSpec) ToSVCSpec() corev1.ServiceSpec { - return corev1.ServiceSpec{ - Ports: r.ToSVCPorts(), - } -} - -// ServicePort is deprecated since v0.8. -type ServicePort struct { - // The name of this port within the service. This must be a DNS_LABEL. - // All ports within a ServiceSpec must have unique names. When considering - // the endpoints for a Service, this must match the 'name' field in the - // EndpointPort. - // +kubebuilder:validation:Required - Name string `json:"name,omitempty" protobuf:"bytes,1,opt,name=name"` - - // The IP protocol for this port. Supports "TCP", "UDP", and "SCTP". - // Default is TCP. - // +kubebuilder:validation:Enum={TCP,UDP,SCTP} - // +default="TCP" - // +optional - Protocol corev1.Protocol `json:"protocol,omitempty" protobuf:"bytes,2,opt,name=protocol,casttype=Protocol"` - - // The application protocol for this port. - // This field follows standard Kubernetes label syntax. - // Un-prefixed names are reserved for IANA standard service names (as per - // RFC-6335 and https://www.iana.org/assignments/service-names). - // Non-standard protocols should use prefixed names such as - // mycompany.com/my-custom-protocol. - // +optional - AppProtocol *string `json:"appProtocol,omitempty" protobuf:"bytes,6,opt,name=appProtocol"` - - // The port that will be exposed by this service. - Port int32 `json:"port" protobuf:"varint,3,opt,name=port"` - - // Number or name of the port to access on the pods targeted by the service. - // - // Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - // - // - If this is a string, it will be looked up as a named port in the target Pod's container ports. - // - If this is not specified, the value of the `port` field is used (an identity map). - // - // This field is ignored for services with clusterIP=None, and should be - // omitted or set equal to the `port` field. - // - // More info: https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service - // - // +kubebuilder:validation:XIntOrString - // +optional - TargetPort intstr.IntOrString `json:"targetPort,omitempty" protobuf:"bytes,4,opt,name=targetPort"` -} - -func (r *ServicePort) toSVCPort() corev1.ServicePort { - return corev1.ServicePort{ - Name: r.Name, - Protocol: r.Protocol, - AppProtocol: r.AppProtocol, - Port: r.Port, - TargetPort: r.TargetPort, - } -} - // HorizontalScalePolicy is deprecated since v0.8. type HorizontalScalePolicy struct { // Determines the data synchronization method when a component scales out. @@ -1013,20 +822,6 @@ func (r *ReplicationSetSpec) FinalStsUpdateStrategy() (appsv1.PodManagementPolic return appsv1.ParallelPodManagement, s } -// PostStartAction is deprecated since v0.8. -type PostStartAction struct { - // Specifies the post-start command to be executed. - // - // +kubebuilder:validation:Required - CmdExecutorConfig CmdExecutorConfig `json:"cmdExecutorConfig"` - - // Used to select the script that need to be referenced. - // When defined, the scripts defined in scriptSpecs can be referenced within the CmdExecutorConfig. - // - // +optional - ScriptSpecSelectors []ScriptSpecSelector `json:"scriptSpecSelectors,omitempty"` -} - // SwitchoverSpec is deprecated since v0.8. type SwitchoverSpec struct { // Represents the action of switching over to a specified candidate primary or leader instance. diff --git a/apis/apps/v1alpha1/clusterdefinition_types_test.go b/apis/apps/v1alpha1/clusterdefinition_types_test.go index 02d779097636..4ce8340b91e3 100644 --- a/apis/apps/v1alpha1/clusterdefinition_types_test.go +++ b/apis/apps/v1alpha1/clusterdefinition_types_test.go @@ -87,17 +87,6 @@ var _ = Describe("", func() { Expect(spec).Should(BeEquivalentTo(&r.ReplicationSpec.StatefulSetSpec)) }) - It("test ToSVCSpec", func() { - r := ServiceSpec{ - Ports: []ServicePort{ - { - Name: "test-name", - }, - }, - } - Expect(r.ToSVCSpec().Ports[0].Name).Should(Equal(r.Ports[0].Name)) - }) - It("test GetUpdateStrategy", func() { r := &StatefulSetSpec{} r.UpdateStrategy = BestEffortParallelStrategy diff --git a/apis/apps/v1alpha1/type.go b/apis/apps/v1alpha1/type.go index 2a96db615974..6ae88ad04f28 100644 --- a/apis/apps/v1alpha1/type.go +++ b/apis/apps/v1alpha1/type.go @@ -612,46 +612,6 @@ type OpsRecorder struct { QueueBySelf bool `json:"queueBySelf,omitempty"` } -// ProvisionPolicyType defines the policy for creating accounts. -// -// +enum -// +kubebuilder:validation:Enum={CreateByStmt,ReferToExisting} -type ProvisionPolicyType string - -const ( - // CreateByStmt will create account w.r.t. deletion and creation statement given by provider. - CreateByStmt ProvisionPolicyType = "CreateByStmt" - - // ReferToExisting will not create account, but create a secret by copying data from referred secret file. - ReferToExisting ProvisionPolicyType = "ReferToExisting" -) - -// ProvisionScope defines the scope of provision within a component. -// -// +enum -type ProvisionScope string - -const ( - // AllPods indicates that accounts will be created for all pods within the component. - AllPods ProvisionScope = "AllPods" - - // AnyPods indicates that accounts will be created only on a single pod within the component. - AnyPods ProvisionScope = "AnyPods" -) - -// AccountName defines system account names. -// +enum -// +kubebuilder:validation:Enum={kbadmin,kbdataprotection,kbprobe,kbmonitoring,kbreplicator} -type AccountName string - -const ( - AdminAccount AccountName = "kbadmin" - DataprotectionAccount AccountName = "kbdataprotection" - ProbeAccount AccountName = "kbprobe" - MonitorAccount AccountName = "kbmonitoring" - ReplicatorAccount AccountName = "kbreplicator" -) - // LetterCase defines the available cases to be used in password generation. // // +enum diff --git a/apis/apps/v1alpha1/zz_generated.deepcopy.go b/apis/apps/v1alpha1/zz_generated.deepcopy.go index 6060653b9ff3..28ef93f46349 100644 --- a/apis/apps/v1alpha1/zz_generated.deepcopy.go +++ b/apis/apps/v1alpha1/zz_generated.deepcopy.go @@ -412,11 +412,6 @@ func (in *ClusterComponentDefinition) DeepCopyInto(out *ClusterComponentDefiniti *out = new(v1.PodSpec) (*in).DeepCopyInto(*out) } - if in.Service != nil { - in, out := &in.Service, &out.Service - *out = new(ServiceSpec) - (*in).DeepCopyInto(*out) - } if in.StatelessSpec != nil { in, out := &in.StatelessSpec, &out.StatelessSpec *out = new(StatelessSetSpec) @@ -447,21 +442,11 @@ func (in *ClusterComponentDefinition) DeepCopyInto(out *ClusterComponentDefiniti *out = new(HorizontalScalePolicy) **out = **in } - if in.SystemAccounts != nil { - in, out := &in.SystemAccounts, &out.SystemAccounts - *out = new(SystemAccountSpec) - (*in).DeepCopyInto(*out) - } if in.SwitchoverSpec != nil { in, out := &in.SwitchoverSpec, &out.SwitchoverSpec *out = new(SwitchoverSpec) (*in).DeepCopyInto(*out) } - if in.PostStartSpec != nil { - in, out := &in.PostStartSpec, &out.PostStartSpec - *out = new(PostStartAction) - (*in).DeepCopyInto(*out) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterComponentDefinition. @@ -4312,27 +4297,6 @@ func (in *PointInTimeRefSpec) DeepCopy() *PointInTimeRefSpec { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PostStartAction) DeepCopyInto(out *PostStartAction) { - *out = *in - in.CmdExecutorConfig.DeepCopyInto(&out.CmdExecutorConfig) - if in.ScriptSpecSelectors != nil { - in, out := &in.ScriptSpecSelectors, &out.ScriptSpecSelectors - *out = make([]ScriptSpecSelector, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PostStartAction. -func (in *PostStartAction) DeepCopy() *PostStartAction { - if in == nil { - return nil - } - out := new(PostStartAction) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PreCheckResult) DeepCopyInto(out *PreCheckResult) { *out = *in @@ -4463,31 +4427,6 @@ func (in *ProtectedVolume) DeepCopy() *ProtectedVolume { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ProvisionPolicy) DeepCopyInto(out *ProvisionPolicy) { - *out = *in - if in.Statements != nil { - in, out := &in.Statements, &out.Statements - *out = new(ProvisionStatements) - **out = **in - } - if in.SecretRef != nil { - in, out := &in.SecretRef, &out.SecretRef - *out = new(ProvisionSecretRef) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProvisionPolicy. -func (in *ProvisionPolicy) DeepCopy() *ProvisionPolicy { - if in == nil { - return nil - } - out := new(ProvisionPolicy) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProvisionSecretRef) DeepCopyInto(out *ProvisionSecretRef) { *out = *in @@ -4503,21 +4442,6 @@ func (in *ProvisionSecretRef) DeepCopy() *ProvisionSecretRef { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ProvisionStatements) DeepCopyInto(out *ProvisionStatements) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProvisionStatements. -func (in *ProvisionStatements) DeepCopy() *ProvisionStatements { - if in == nil { - return nil - } - out := new(ProvisionStatements) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RSMSpec) DeepCopyInto(out *RSMSpec) { *out = *in @@ -5188,27 +5112,6 @@ func (in *ServiceDescriptorStatus) DeepCopy() *ServiceDescriptorStatus { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ServicePort) DeepCopyInto(out *ServicePort) { - *out = *in - if in.AppProtocol != nil { - in, out := &in.AppProtocol, &out.AppProtocol - *out = new(string) - **out = **in - } - out.TargetPort = in.TargetPort -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServicePort. -func (in *ServicePort) DeepCopy() *ServicePort { - if in == nil { - return nil - } - out := new(ServicePort) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceRef) DeepCopyInto(out *ServiceRef) { *out = *in @@ -5372,28 +5275,6 @@ func (in *ServiceRefVars) DeepCopy() *ServiceRefVars { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ServiceSpec) DeepCopyInto(out *ServiceSpec) { - *out = *in - if in.Ports != nil { - in, out := &in.Ports, &out.Ports - *out = make([]ServicePort, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceSpec. -func (in *ServiceSpec) DeepCopy() *ServiceSpec { - if in == nil { - return nil - } - out := new(ServiceSpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceVarSelector) DeepCopyInto(out *ServiceVarSelector) { *out = *in @@ -5687,50 +5568,6 @@ func (in *SystemAccount) DeepCopy() *SystemAccount { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SystemAccountConfig) DeepCopyInto(out *SystemAccountConfig) { - *out = *in - in.ProvisionPolicy.DeepCopyInto(&out.ProvisionPolicy) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SystemAccountConfig. -func (in *SystemAccountConfig) DeepCopy() *SystemAccountConfig { - if in == nil { - return nil - } - out := new(SystemAccountConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SystemAccountSpec) DeepCopyInto(out *SystemAccountSpec) { - *out = *in - if in.CmdExecutorConfig != nil { - in, out := &in.CmdExecutorConfig, &out.CmdExecutorConfig - *out = new(CmdExecutorConfig) - (*in).DeepCopyInto(*out) - } - out.PasswordConfig = in.PasswordConfig - if in.Accounts != nil { - in, out := &in.Accounts, &out.Accounts - *out = make([]SystemAccountConfig, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SystemAccountSpec. -func (in *SystemAccountSpec) DeepCopy() *SystemAccountSpec { - if in == nil { - return nil - } - out := new(SystemAccountSpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TLSConfig) DeepCopyInto(out *TLSConfig) { *out = *in diff --git a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml index a361e5925efe..f1d83dc56fd3 100644 --- a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml @@ -7518,172 +7518,6 @@ spec: - containers type: object x-kubernetes-preserve-unknown-fields: true - postStartSpec: - description: |- - Defines the command to be executed when the component is ready, and the command will only be executed once after - the component becomes ready. - properties: - cmdExecutorConfig: - description: Specifies the post-start command to be executed. - properties: - args: - description: Additional parameters used in the execution - of the command. - items: - type: string - type: array - command: - description: The command to be executed. - items: - type: string - minItems: 1 - type: array - env: - description: A list of environment variables that will - be injected into the command execution context. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, defaults - to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults to - "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-preserve-unknown-fields: true - image: - description: Specifies the image used to execute the - command. - type: string - required: - - command - - image - type: object - scriptSpecSelectors: - description: |- - Used to select the script that need to be referenced. - When defined, the scripts defined in scriptSpecs can be referenced within the CmdExecutorConfig. - items: - properties: - name: - description: Represents the name of the ScriptSpec - referent. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - required: - - name - type: object - type: array - required: - - cmdExecutorConfig - type: object probes: description: Settings for health checks. properties: @@ -8177,77 +8011,6 @@ spec: type: object type: array type: object - service: - description: Defines the service spec. - properties: - ports: - description: |- - The list of ports that are exposed by this service. - More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies - items: - description: ServicePort is deprecated since v0.8. - properties: - appProtocol: - description: |- - The application protocol for this port. - This field follows standard Kubernetes label syntax. - Un-prefixed names are reserved for IANA standard service names (as per - RFC-6335 and https://www.iana.org/assignments/service-names). - Non-standard protocols should use prefixed names such as - mycompany.com/my-custom-protocol. - type: string - name: - description: |- - The name of this port within the service. This must be a DNS_LABEL. - All ports within a ServiceSpec must have unique names. When considering - the endpoints for a Service, this must match the 'name' field in the - EndpointPort. - type: string - port: - description: The port that will be exposed by this - service. - format: int32 - type: integer - protocol: - default: TCP - description: |- - The IP protocol for this port. Supports "TCP", "UDP", and "SCTP". - Default is TCP. - enum: - - TCP - - UDP - - SCTP - type: string - targetPort: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the pods targeted by the service. - - - Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - - - - If this is a string, it will be looked up as a named port in the target Pod's container ports. - - If this is not specified, the value of the `port` field is used (an identity map). - - - This field is ignored for services with clusterIP=None, and should be - omitted or set equal to the `port` field. - - - More info: https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service - x-kubernetes-int-or-string: true - required: - - port - type: object - type: array - x-kubernetes-list-map-keys: - - port - - protocol - x-kubernetes-list-type: map - type: object statefulSpec: description: Defines spec for `Stateful` workloads. properties: @@ -8710,284 +8473,6 @@ spec: - cmdExecutorConfig type: object type: object - systemAccounts: - description: Defines system accounts needed to manage the component, - and the statement to create them. - properties: - accounts: - description: Defines the configuration settings for system - accounts. - items: - description: |- - SystemAccountConfig specifies how to create and delete system accounts. - - - Deprecated since v0.9. - properties: - name: - description: The unique identifier of a system account. - enum: - - kbadmin - - kbdataprotection - - kbprobe - - kbmonitoring - - kbreplicator - type: string - provisionPolicy: - description: Outlines the strategy for creating the - account. - properties: - scope: - default: AnyPods - description: Defines the scope within which the - account is provisioned. - type: string - secretRef: - description: The external secret to refer. - properties: - name: - description: The unique identifier of the - secret. - type: string - namespace: - description: The namespace where the secret - is located. - type: string - required: - - name - - namespace - type: object - statements: - description: The statement to provision an account. - properties: - creation: - description: Specifies the statement required - to create a new account with the necessary - privileges. - type: string - deletion: - description: |- - Defines the statement required to delete an existing account. - Typically used in conjunction with the creation statement to delete an account before recreating it. - For example, one might use a `drop user if exists` statement followed by a `create user` statement to ensure a fresh account. - - - Deprecated: This field is deprecated and the update statement should be used instead. - type: string - update: - description: Defines the statement required - to update the password of an existing account. - type: string - required: - - creation - type: object - type: - description: Specifies the method to provision - an account. - enum: - - CreateByStmt - - ReferToExisting - type: string - required: - - scope - - type - type: object - required: - - name - - provisionPolicy - type: object - minItems: 1 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - cmdExecutorConfig: - description: Configures how to obtain the client SDK and - execute statements. - properties: - args: - description: Additional parameters used in the execution - of the command. - items: - type: string - type: array - command: - description: The command to be executed. - items: - type: string - minItems: 1 - type: array - env: - description: A list of environment variables that will - be injected into the command execution context. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, defaults - to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults to - "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-preserve-unknown-fields: true - image: - description: Specifies the image used to execute the - command. - type: string - required: - - command - - image - type: object - passwordConfig: - description: Defines the pattern used to generate passwords - for system accounts. - properties: - length: - default: 16 - description: The length of the password. - format: int32 - maximum: 32 - minimum: 8 - type: integer - letterCase: - default: MixedCases - description: The case of the letters in the password. - enum: - - LowerCases - - UpperCases - - MixedCases - type: string - numDigits: - default: 4 - description: The number of digits in the password. - format: int32 - maximum: 8 - minimum: 0 - type: integer - numSymbols: - default: 0 - description: The number of symbols in the password. - format: int32 - maximum: 8 - minimum: 0 - type: integer - seed: - description: |- - Seed to generate the account's password. - Cannot be updated. - type: string - type: object - required: - - accounts - - cmdExecutorConfig - - passwordConfig - type: object workloadType: description: |- Defines the type of the workload. diff --git a/controllers/apps/cluster_controller_test.go b/controllers/apps/cluster_controller_test.go index 5654438c91d5..2d916c97491c 100644 --- a/controllers/apps/cluster_controller_test.go +++ b/controllers/apps/cluster_controller_test.go @@ -566,7 +566,7 @@ var _ = Describe("Cluster Controller", func() { g.Expect(svc.Spec.ExternalTrafficPolicy).Should(BeEquivalentTo(corev1.ServiceExternalTrafficPolicyTypeLocal)) })).Should(Succeed()) - By("check component service created") + By("check default component service created") compSvcKey := types.NamespacedName{ Namespace: clusterKey.Namespace, Name: constant.GenerateComponentServiceName(clusterObj.Name, compName, ""), @@ -1360,15 +1360,15 @@ var _ = Describe("Cluster Controller", func() { }) It("with cluster service set", func() { - testClusterService(defaultCompName, defaultClusterCompDefName, createLegacyClusterObj) + testClusterService(defaultCompName, compDefObj.Name, createClusterObj) }) It("should create and delete cluster service correctly", func() { - testClusterServiceCreateAndDelete(defaultCompName, defaultClusterCompDefName, createLegacyClusterObj) + testClusterServiceCreateAndDelete(defaultCompName, compDefObj.Name, createClusterObj) }) It("should create and delete shard topology cluster service correctly", func() { - testShardingClusterServiceCreateAndDelete(defaultCompName, defaultClusterCompDefName, createLegacyClusterObjWithSharding) + testShardingClusterServiceCreateAndDelete(defaultCompName, compDefObj.Name, createClusterObjWithSharding) }) }) diff --git a/controllers/apps/component_controller_test.go b/controllers/apps/component_controller_test.go index d8cadc0bb261..d84e9e00b1e1 100644 --- a/controllers/apps/component_controller_test.go +++ b/controllers/apps/component_controller_test.go @@ -1256,7 +1256,7 @@ var _ = Describe("Component Controller", func() { targetEnvVars := []corev1.EnvVar{ { Name: "SERVICE_HOST", - Value: constant.GenerateComponentServiceName(clusterObj.Name, compName, compDefObj.Spec.Services[0].Name), + Value: constant.GenerateComponentServiceName(clusterObj.Name, compName, compDefObj.Spec.Services[0].ServiceName), }, { Name: "SERVICE_PORT", diff --git a/controllers/apps/componentdefinition_controller_test.go b/controllers/apps/componentdefinition_controller_test.go index 374e88b3d3cf..ce4df5a80e4e 100644 --- a/controllers/apps/componentdefinition_controller_test.go +++ b/controllers/apps/componentdefinition_controller_test.go @@ -39,6 +39,9 @@ import ( var _ = Describe("ComponentDefinition Controller", func() { const ( componentDefName = "test-componentdef" + adminAccount = "kbadmin" + probeAccount = "kbprobe" + monitorAccount = "kbmonitoring" ) var ( @@ -250,7 +253,7 @@ var _ = Describe("ComponentDefinition Controller", func() { By("create a ComponentDefinition obj") componentDefObj := testapps.NewComponentDefinitionFactory(componentDefName). SetRuntime(nil). - AddSystemAccount(string(appsv1alpha1.AdminAccount), false, "create user"). + AddSystemAccount(adminAccount, false, "create user"). Create(&testCtx).GetObject() checkObjectStatus(componentDefObj, appsv1alpha1.UnavailablePhase) @@ -260,7 +263,7 @@ var _ = Describe("ComponentDefinition Controller", func() { By("create a ComponentDefinition obj") componentDefObj := testapps.NewComponentDefinitionFactory(componentDefName). SetRuntime(nil). - AddSystemAccount(string(appsv1alpha1.AdminAccount), true, "create user"). + AddSystemAccount(adminAccount, true, "create user"). SetLifecycleAction("AccountProvision", defaultActionHandler). Create(&testCtx).GetObject() @@ -271,8 +274,8 @@ var _ = Describe("ComponentDefinition Controller", func() { By("create a ComponentDefinition obj") componentDefObj := testapps.NewComponentDefinitionFactory(componentDefName). SetRuntime(nil). - AddSystemAccount(string(appsv1alpha1.AdminAccount), true, "create user"). - AddSystemAccount(string(appsv1alpha1.AdminAccount), false, "create user"). + AddSystemAccount(adminAccount, true, "create user"). + AddSystemAccount(adminAccount, false, "create user"). SetLifecycleAction("AccountProvision", defaultActionHandler). Create(&testCtx).GetObject() @@ -283,9 +286,9 @@ var _ = Describe("ComponentDefinition Controller", func() { By("create a ComponentDefinition obj") componentDefObj := testapps.NewComponentDefinitionFactory(componentDefName). SetRuntime(nil). - AddSystemAccount(string(appsv1alpha1.AdminAccount), true, "create user"). - AddSystemAccount(string(appsv1alpha1.ProbeAccount), true, "create user"). - AddSystemAccount(string(appsv1alpha1.MonitorAccount), false, "create user"). + AddSystemAccount(adminAccount, true, "create user"). + AddSystemAccount(probeAccount, true, "create user"). + AddSystemAccount(monitorAccount, false, "create user"). SetLifecycleAction("AccountProvision", defaultActionHandler). Create(&testCtx).GetObject() @@ -296,9 +299,9 @@ var _ = Describe("ComponentDefinition Controller", func() { By("create a ComponentDefinition obj") componentDefObj := testapps.NewComponentDefinitionFactory(componentDefName). SetRuntime(nil). - AddSystemAccount(string(appsv1alpha1.AdminAccount), true, "create user"). - AddSystemAccount(string(appsv1alpha1.ProbeAccount), false, "create user"). - AddSystemAccount(string(appsv1alpha1.MonitorAccount), false, "create user"). + AddSystemAccount(adminAccount, true, "create user"). + AddSystemAccount(probeAccount, false, "create user"). + AddSystemAccount(monitorAccount, false, "create user"). SetLifecycleAction("AccountProvision", defaultActionHandler). Create(&testCtx).GetObject() diff --git a/controllers/apps/operations/expose.go b/controllers/apps/operations/expose.go index c19608b2f84e..fa001cd2dcf0 100644 --- a/controllers/apps/operations/expose.go +++ b/controllers/apps/operations/expose.go @@ -65,7 +65,6 @@ func (e ExposeOpsHandler) Action(reqCtx intctrlutil.RequestCtx, cli client.Clien for _, expose := range exposeMap { clusterCompSpecName := "" compDef := "" - clusterCompDefRefName := "" if len(expose.ComponentName) > 0 { clusterCompSpec, ok := compMap[expose.ComponentName] if !ok { @@ -73,12 +72,11 @@ func (e ExposeOpsHandler) Action(reqCtx intctrlutil.RequestCtx, cli client.Clien } clusterCompSpecName = clusterCompSpec.Name compDef = clusterCompSpec.ComponentDef - clusterCompDefRefName = clusterCompSpec.ComponentDefRef } switch expose.Switch { case appsv1alpha1.EnableExposeSwitch: - if err := e.buildClusterServices(reqCtx, cli, opsRes.Cluster, clusterCompSpecName, compDef, clusterCompDefRefName, expose.Services); err != nil { + if err := e.buildClusterServices(reqCtx, cli, opsRes.Cluster, clusterCompSpecName, compDef, expose.Services); err != nil { return err } case appsv1alpha1.DisableExposeSwitch: @@ -269,7 +267,6 @@ func (e ExposeOpsHandler) buildClusterServices(reqCtx intctrlutil.RequestCtx, cluster *appsv1alpha1.Cluster, clusterCompSpecName string, compDefName string, - clusterCompDefRefName string, exposeServices []appsv1alpha1.OpsService) error { if cluster == nil || len(exposeServices) == 0 { return nil @@ -334,17 +331,6 @@ func (e ExposeOpsHandler) buildClusterServices(reqCtx intctrlutil.RequestCtx, } return convertDefaultCompDefServicePorts(compDef.Spec.Services) } - if cluster.Spec.ClusterDefRef != "" && clusterCompDefRefName != "" { - clusterDef, err := getClusterDefByName(reqCtx.Ctx, cli, cluster.Spec.ClusterDefRef) - if err != nil { - return nil, err - } - clusterCompDef := clusterDef.GetComponentDefByName(clusterCompDefRefName) - if clusterCompDef == nil || clusterCompDef.Service == nil { - return nil, fmt.Errorf("referenced cluster component definition or services is not defined: %s", clusterCompDefRefName) - } - return clusterCompDef.Service.ToSVCPorts(), nil - } return nil, fmt.Errorf("component definition is not defined, cluster: %s, component: %s", cluster.Name, clusterCompSpecName) } @@ -356,24 +342,6 @@ func (e ExposeOpsHandler) buildClusterServices(reqCtx intctrlutil.RequestCtx, } return len(compDef.Spec.Roles) > 0, nil } - if cluster.Spec.ClusterDefRef != "" && clusterCompDefRefName != "" { - clusterDef, err := getClusterDefByName(reqCtx.Ctx, cli, cluster.Spec.ClusterDefRef) - if err != nil { - return false, err - } - clusterCompDef := clusterDef.GetComponentDefByName(clusterCompDefRefName) - if clusterCompDef == nil { - return false, fmt.Errorf("referenced cluster component definition is not defined: %s", clusterCompDefRefName) - } - switch clusterCompDef.WorkloadType { - case appsv1alpha1.Replication, appsv1alpha1.Consensus: - return true, nil - case appsv1alpha1.Stateful: - if clusterCompDef.RSMSpec != nil { - return len(clusterCompDef.RSMSpec.Roles) > 0, nil - } - } - } return false, nil } diff --git a/controllers/apps/operations/expose_test.go b/controllers/apps/operations/expose_test.go index 1bec9b64082b..6ec799e30248 100644 --- a/controllers/apps/operations/expose_test.go +++ b/controllers/apps/operations/expose_test.go @@ -22,9 +22,9 @@ package operations import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/intstr" - "sigs.k8s.io/controller-runtime/pkg/client" appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" @@ -36,13 +36,9 @@ import ( var _ = Describe("", func() { var ( - randomStr = testCtx.GetRandomStr() - clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterName = "cluster-for-ops-" + randomStr - ) - - const ( - consensusCompName = "consensus" + randomStr = testCtx.GetRandomStr() + compDefName = "test-compdef-" + randomStr + clusterName = "test-cluster-" + randomStr ) cleanEnv := func() { @@ -53,7 +49,7 @@ var _ = Describe("", func() { By("clean resources") // delete cluster(and all dependent sub-resources), cluster definition - testapps.ClearClusterResources(&testCtx) + testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest resources inNS := client.InNamespace(testCtx.DefaultNamespace) @@ -69,14 +65,14 @@ var _ = Describe("", func() { Context("Test OpsRequest", func() { It("Test expose OpsRequest", func() { reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx} - opsRes, _, clusterObject := initOperationsResources(clusterDefinitionName, clusterName) + opsRes, _, clusterObject := initOperationsResources2(compDefName, clusterName) By("create Expose opsRequest") ops := testapps.NewOpsRequestObj("expose-expose-"+randomStr, testCtx.DefaultNamespace, clusterObject.Name, appsv1alpha1.ExposeType) ops.Spec.ExposeList = []appsv1alpha1.Expose{ { - ComponentName: consensusCompName, + ComponentName: clusterObject.Spec.ComponentSpecs[0].Name, Switch: appsv1alpha1.EnableExposeSwitch, Services: []appsv1alpha1.OpsService{ { @@ -107,7 +103,7 @@ var _ = Describe("", func() { It("Test expose OpsRequest with empty ComponentName", func() { reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx} - opsRes, _, clusterObject := initOperationsResources(clusterDefinitionName, clusterName) + opsRes, _, clusterObject := initOperationsResources2(compDefName, clusterName) By("create Expose opsRequest") ops := testapps.NewOpsRequestObj("expose-expose-"+randomStr, testCtx.DefaultNamespace, diff --git a/controllers/apps/transformer_cluster_credential.go b/controllers/apps/transformer_cluster_credential.go index 34fc6c6a69ce..c8c7041707ba 100644 --- a/controllers/apps/transformer_cluster_credential.go +++ b/controllers/apps/transformer_cluster_credential.go @@ -24,7 +24,6 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" "sigs.k8s.io/controller-runtime/pkg/client" - appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" "github.com/apecloud/kubeblocks/pkg/common" "github.com/apecloud/kubeblocks/pkg/controller/component" "github.com/apecloud/kubeblocks/pkg/controller/factory" @@ -84,26 +83,5 @@ func (t *clusterConnCredentialTransformer) buildClusterConnCredential(transCtx * } func (t *clusterConnCredentialTransformer) buildSynthesizedComponent(transCtx *clusterTransformContext) *component.SynthesizedComponent { - for _, compDef := range transCtx.ClusterDef.Spec.ComponentDefs { - if compDef.Service == nil { - continue - } - for _, compSpec := range transCtx.ComponentSpecs { - if compDef.Name != compSpec.ComponentDefRef { - continue - } - return &component.SynthesizedComponent{ - Name: compSpec.Name, - Annotations: transCtx.Cluster.Annotations, - ComponentServices: []appsv1alpha1.ComponentService{ - { - Service: appsv1alpha1.Service{ - Spec: compDef.Service.ToSVCSpec(), - }, - }, - }, - } - } - } return nil } diff --git a/controllers/apps/transformer_cluster_service.go b/controllers/apps/transformer_cluster_service.go index 26b11878b93f..54b62dcc84fd 100644 --- a/controllers/apps/transformer_cluster_service.go +++ b/controllers/apps/transformer_cluster_service.go @@ -131,7 +131,6 @@ func (t *clusterServiceTransformer) convertLegacyClusterCompSpecServices(transCt if clusterCompDef == nil { continue } - defaultLegacyServicePorts := clusterCompDef.Service.ToSVCPorts() for _, item := range compSpec.Services { legacyService := &appsv1alpha1.ClusterService{ @@ -140,7 +139,7 @@ func (t *clusterServiceTransformer) convertLegacyClusterCompSpecServices(transCt ServiceName: constant.GenerateClusterServiceName(cluster.Name, item.Name), Annotations: item.Annotations, Spec: corev1.ServiceSpec{ - Ports: defaultLegacyServicePorts, + Ports: []corev1.ServicePort{}, Type: item.ServiceType, }, }, diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml index a361e5925efe..f1d83dc56fd3 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml @@ -7518,172 +7518,6 @@ spec: - containers type: object x-kubernetes-preserve-unknown-fields: true - postStartSpec: - description: |- - Defines the command to be executed when the component is ready, and the command will only be executed once after - the component becomes ready. - properties: - cmdExecutorConfig: - description: Specifies the post-start command to be executed. - properties: - args: - description: Additional parameters used in the execution - of the command. - items: - type: string - type: array - command: - description: The command to be executed. - items: - type: string - minItems: 1 - type: array - env: - description: A list of environment variables that will - be injected into the command execution context. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, defaults - to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults to - "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-preserve-unknown-fields: true - image: - description: Specifies the image used to execute the - command. - type: string - required: - - command - - image - type: object - scriptSpecSelectors: - description: |- - Used to select the script that need to be referenced. - When defined, the scripts defined in scriptSpecs can be referenced within the CmdExecutorConfig. - items: - properties: - name: - description: Represents the name of the ScriptSpec - referent. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - required: - - name - type: object - type: array - required: - - cmdExecutorConfig - type: object probes: description: Settings for health checks. properties: @@ -8177,77 +8011,6 @@ spec: type: object type: array type: object - service: - description: Defines the service spec. - properties: - ports: - description: |- - The list of ports that are exposed by this service. - More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies - items: - description: ServicePort is deprecated since v0.8. - properties: - appProtocol: - description: |- - The application protocol for this port. - This field follows standard Kubernetes label syntax. - Un-prefixed names are reserved for IANA standard service names (as per - RFC-6335 and https://www.iana.org/assignments/service-names). - Non-standard protocols should use prefixed names such as - mycompany.com/my-custom-protocol. - type: string - name: - description: |- - The name of this port within the service. This must be a DNS_LABEL. - All ports within a ServiceSpec must have unique names. When considering - the endpoints for a Service, this must match the 'name' field in the - EndpointPort. - type: string - port: - description: The port that will be exposed by this - service. - format: int32 - type: integer - protocol: - default: TCP - description: |- - The IP protocol for this port. Supports "TCP", "UDP", and "SCTP". - Default is TCP. - enum: - - TCP - - UDP - - SCTP - type: string - targetPort: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the pods targeted by the service. - - - Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - - - - If this is a string, it will be looked up as a named port in the target Pod's container ports. - - If this is not specified, the value of the `port` field is used (an identity map). - - - This field is ignored for services with clusterIP=None, and should be - omitted or set equal to the `port` field. - - - More info: https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service - x-kubernetes-int-or-string: true - required: - - port - type: object - type: array - x-kubernetes-list-map-keys: - - port - - protocol - x-kubernetes-list-type: map - type: object statefulSpec: description: Defines spec for `Stateful` workloads. properties: @@ -8710,284 +8473,6 @@ spec: - cmdExecutorConfig type: object type: object - systemAccounts: - description: Defines system accounts needed to manage the component, - and the statement to create them. - properties: - accounts: - description: Defines the configuration settings for system - accounts. - items: - description: |- - SystemAccountConfig specifies how to create and delete system accounts. - - - Deprecated since v0.9. - properties: - name: - description: The unique identifier of a system account. - enum: - - kbadmin - - kbdataprotection - - kbprobe - - kbmonitoring - - kbreplicator - type: string - provisionPolicy: - description: Outlines the strategy for creating the - account. - properties: - scope: - default: AnyPods - description: Defines the scope within which the - account is provisioned. - type: string - secretRef: - description: The external secret to refer. - properties: - name: - description: The unique identifier of the - secret. - type: string - namespace: - description: The namespace where the secret - is located. - type: string - required: - - name - - namespace - type: object - statements: - description: The statement to provision an account. - properties: - creation: - description: Specifies the statement required - to create a new account with the necessary - privileges. - type: string - deletion: - description: |- - Defines the statement required to delete an existing account. - Typically used in conjunction with the creation statement to delete an account before recreating it. - For example, one might use a `drop user if exists` statement followed by a `create user` statement to ensure a fresh account. - - - Deprecated: This field is deprecated and the update statement should be used instead. - type: string - update: - description: Defines the statement required - to update the password of an existing account. - type: string - required: - - creation - type: object - type: - description: Specifies the method to provision - an account. - enum: - - CreateByStmt - - ReferToExisting - type: string - required: - - scope - - type - type: object - required: - - name - - provisionPolicy - type: object - minItems: 1 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - cmdExecutorConfig: - description: Configures how to obtain the client SDK and - execute statements. - properties: - args: - description: Additional parameters used in the execution - of the command. - items: - type: string - type: array - command: - description: The command to be executed. - items: - type: string - minItems: 1 - type: array - env: - description: A list of environment variables that will - be injected into the command execution context. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, defaults - to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults to - "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-preserve-unknown-fields: true - image: - description: Specifies the image used to execute the - command. - type: string - required: - - command - - image - type: object - passwordConfig: - description: Defines the pattern used to generate passwords - for system accounts. - properties: - length: - default: 16 - description: The length of the password. - format: int32 - maximum: 32 - minimum: 8 - type: integer - letterCase: - default: MixedCases - description: The case of the letters in the password. - enum: - - LowerCases - - UpperCases - - MixedCases - type: string - numDigits: - default: 4 - description: The number of digits in the password. - format: int32 - maximum: 8 - minimum: 0 - type: integer - numSymbols: - default: 0 - description: The number of symbols in the password. - format: int32 - maximum: 8 - minimum: 0 - type: integer - seed: - description: |- - Seed to generate the account's password. - Cannot be updated. - type: string - type: object - required: - - accounts - - cmdExecutorConfig - - passwordConfig - type: object workloadType: description: |- Defines the type of the workload. diff --git a/docs/developer_docs/api-reference/cluster.md b/docs/developer_docs/api-reference/cluster.md index ad42c2ff06fd..e7a6fe2ece88 100644 --- a/docs/developer_docs/api-reference/cluster.md +++ b/docs/developer_docs/api-reference/cluster.md @@ -2869,33 +2869,6 @@ The modes can be None, Readonly, or ReadWrite -

    AccountName -(string alias)

    -

    -(Appears on:SystemAccountConfig) -

    -
    -

    AccountName defines system account names.

    -
    - - - - - - - - - - - - - - - - - - -
    ValueDescription

    "kbadmin"

    "kbdataprotection"

    "kbmonitoring"

    "kbprobe"

    "kbreplicator"

    Action

    @@ -4094,20 +4067,6 @@ Kubernetes core/v1.PodSpec -service
    - - -ServiceSpec - - - - -(Optional) -

    Defines the service spec.

    - - - - statelessSpec
    @@ -4194,20 +4153,6 @@ HorizontalScalePolicy -systemAccounts
    - -
    -SystemAccountSpec - - - - -(Optional) -

    Defines system accounts needed to manage the component, and the statement to create them.

    - - - - switchoverSpec
    @@ -4222,21 +4167,6 @@ In particular, when workloadType=Replication, the command defined in switchoverS the condition of cluster.componentSpecs[x].SwitchPolicy.type=Noop.

    - - -postStartSpec
    - -
    -PostStartAction - - - - -(Optional) -

    Defines the command to be executed when the component is ready, and the command will only be executed once after -the component becomes ready.

    - -

    ClusterComponentPhase @@ -6450,7 +6380,7 @@ separated by commas.

    CmdExecutorConfig

    -(Appears on:PostStartAction, SwitchoverAction, SystemAccountSpec) +(Appears on:SwitchoverAction)

    CmdExecutorConfig specifies how to perform creation and deletion statements.

    @@ -14427,7 +14357,7 @@ The supported property types include:

    PasswordConfig

    -(Appears on:ComponentSystemAccount, SystemAccount, SystemAccountSpec) +(Appears on:ComponentSystemAccount, SystemAccount)

    PasswordConfig helps provide to customize complexity of password generation pattern.

    @@ -14860,52 +14790,6 @@ RefNamespaceName -

    PostStartAction -

    -

    -(Appears on:ClusterComponentDefinition) -

    -
    -

    PostStartAction is deprecated since v0.8.

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -cmdExecutorConfig
    - - -CmdExecutorConfig - - -
    -

    Specifies the post-start command to be executed.

    -
    -scriptSpecSelectors
    - - -[]ScriptSpecSelector - - -
    -(Optional) -

    Used to select the script that need to be referenced. -When defined, the scripts defined in scriptSpecs can be referenced within the CmdExecutorConfig.

    -

    PreCheckResult

    @@ -15373,129 +15257,10 @@ If the value is invalid, it will be ignored and the component level threshold wi -

    ProvisionPolicy -

    -

    -(Appears on:SystemAccountConfig) -

    -
    -

    ProvisionPolicy defines the policy details for creating accounts.

    -

    Deprecated since v0.9.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -type
    - - -ProvisionPolicyType - - -
    -

    Specifies the method to provision an account.

    -
    -scope
    - - -ProvisionScope - - -
    -

    Defines the scope within which the account is provisioned.

    -
    -statements
    - - -ProvisionStatements - - -
    -(Optional) -

    The statement to provision an account.

    -
    -secretRef
    - - -ProvisionSecretRef - - -
    -(Optional) -

    The external secret to refer.

    -
    -

    ProvisionPolicyType -(string alias)

    -

    -(Appears on:ProvisionPolicy) -

    -
    -

    ProvisionPolicyType defines the policy for creating accounts.

    -
    - - - - - - - - - - - - -
    ValueDescription

    "CreateByStmt"

    CreateByStmt will create account w.r.t. deletion and creation statement given by provider.

    -

    "ReferToExisting"

    ReferToExisting will not create account, but create a secret by copying data from referred secret file.

    -
    -

    ProvisionScope -(string alias)

    -

    -(Appears on:ProvisionPolicy) -

    -
    -

    ProvisionScope defines the scope of provision within a component.

    -
    - - - - - - - - - - - - -
    ValueDescription

    "AllPods"

    AllPods indicates that accounts will be created for all pods within the component.

    -

    "AnyPods"

    AnyPods indicates that accounts will be created only on a single pod within the component.

    -

    ProvisionSecretRef

    -(Appears on:ComponentSystemAccount, ProvisionPolicy, SystemAccount) +(Appears on:ComponentSystemAccount, SystemAccount)

    ProvisionSecretRef represents the reference to a secret.

    @@ -15532,63 +15297,6 @@ string -

    ProvisionStatements -

    -

    -(Appears on:ProvisionPolicy) -

    -
    -

    ProvisionStatements defines the statements used to create accounts.

    -

    Deprecated since v0.9.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -creation
    - -string - -
    -

    Specifies the statement required to create a new account with the necessary privileges.

    -
    -update
    - -string - -
    -(Optional) -

    Defines the statement required to update the password of an existing account.

    -
    -deletion
    - -string - -
    -(Optional) -

    Defines the statement required to delete an existing account. -Typically used in conjunction with the creation statement to delete an account before recreating it. -For example, one might use a drop user if exists statement followed by a create user statement to ensure a fresh account.

    -

    Deprecated: This field is deprecated and the update statement should be used instead.

    -

    RSMSpec

    @@ -17018,7 +16726,7 @@ In these cases, the script must be executed on all replica Pods matching the sel

    ScriptSpecSelector

    -(Appears on:ComponentSwitchover, PostStartAction, SwitchoverAction) +(Appears on:ComponentSwitchover, SwitchoverAction)

    @@ -17747,103 +17455,6 @@ int64 -

    ServicePort -

    -

    -(Appears on:ServiceSpec) -

    -
    -

    ServicePort is deprecated since v0.8.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -name
    - -string - -
    -

    The name of this port within the service. This must be a DNS_LABEL. -All ports within a ServiceSpec must have unique names. When considering -the endpoints for a Service, this must match the ‘name’ field in the -EndpointPort.

    -
    -protocol
    - - -Kubernetes core/v1.Protocol - - -
    -(Optional) -

    The IP protocol for this port. Supports “TCP”, “UDP”, and “SCTP”. -Default is TCP.

    -
    -appProtocol
    - -string - -
    -(Optional) -

    The application protocol for this port. -This field follows standard Kubernetes label syntax. -Un-prefixed names are reserved for IANA standard service names (as per -RFC-6335 and https://www.iana.org/assignments/service-names). -Non-standard protocols should use prefixed names such as -mycompany.com/my-custom-protocol.

    -
    -port
    - -int32 - -
    -

    The port that will be exposed by this service.

    -
    -targetPort
    - - -Kubernetes api utils intstr.IntOrString - - -
    -(Optional) -

    Number or name of the port to access on the pods targeted by the service.

    -

    Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME.

    -
      -
    • If this is a string, it will be looked up as a named port in the target Pod’s container ports.
    • -
    • If this is not specified, the value of the port field is used (an identity map).
    • -
    -

    This field is ignored for services with clusterIP=None, and should be -omitted or set equal to the port field.

    -

    More info: https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service

    -

    ServiceRef

    @@ -18340,39 +17951,6 @@ CredentialVars -

    ServiceSpec -

    -

    -(Appears on:ClusterComponentDefinition) -

    -
    -

    ServiceSpec is deprecated since v0.8.

    -
    - - - - - - - - - - - - - -
    FieldDescription
    -ports
    - - -[]ServicePort - - -
    -(Optional) -

    The list of ports that are exposed by this service. -More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies

    -

    ServiceVarSelector

    @@ -19211,110 +18789,6 @@ ProvisionSecretRef -

    SystemAccountConfig -

    -

    -(Appears on:SystemAccountSpec) -

    -
    -

    SystemAccountConfig specifies how to create and delete system accounts.

    -

    Deprecated since v0.9.

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -name
    - - -AccountName - - -
    -

    The unique identifier of a system account.

    -
    -provisionPolicy
    - - -ProvisionPolicy - - -
    -

    Outlines the strategy for creating the account.

    -
    -

    SystemAccountSpec -

    -

    -(Appears on:ClusterComponentDefinition) -

    -
    -

    SystemAccountSpec specifies information to create system accounts.

    -

    Deprecated since v0.8, be replaced by componentDefinition.spec.systemAccounts and -componentDefinition.spec.lifecycleActions.accountProvision.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -cmdExecutorConfig
    - - -CmdExecutorConfig - - -
    -

    Configures how to obtain the client SDK and execute statements.

    -
    -passwordConfig
    - - -PasswordConfig - - -
    -

    Defines the pattern used to generate passwords for system accounts.

    -
    -accounts
    - - -[]SystemAccountConfig - - -
    -

    Defines the configuration settings for system accounts.

    -

    TLSConfig

    diff --git a/pkg/controller/component/component_test.go b/pkg/controller/component/component_test.go index 2a019739a6da..3f1aea1c5d5d 100644 --- a/pkg/controller/component/component_test.go +++ b/pkg/controller/component/component_test.go @@ -34,106 +34,40 @@ import ( "github.com/apecloud/kubeblocks/pkg/constant" intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" - viper "github.com/apecloud/kubeblocks/pkg/viperx" ) var _ = Describe("Component", func() { Context("has the BuildComponent function", func() { const ( - clusterDefName = "test-clusterdef" + compDefName = "test-compdef" clusterName = "test-cluster" - mysqlCompDefName = "replicasets" mysqlCompName = "mysql" - proxyCompDefName = "proxy" - proxyCompName = "proxy" mysqlSecretUserEnvName = "MYSQL_ROOT_USER" mysqlSecretPasswdEnvName = "MYSQL_ROOT_PASSWORD" ) var ( - clusterDef *appsv1alpha1.ClusterDefinition - cluster *appsv1alpha1.Cluster + compDef *appsv1alpha1.ComponentDefinition + cluster *appsv1alpha1.Cluster ) BeforeEach(func() { - clusterDef = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). - AddComponentDef(testapps.StatelessNginxComponent, proxyCompDefName). + compDef = testapps.NewComponentDefinitionFactory(compDefName). + SetDefaultSpec(). GetObject() - pvcSpec := testapps.NewPVCSpec("1Gi") - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). - AddComponent(mysqlCompName, mysqlCompDefName). - AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). - AddComponent(proxyCompName, proxyCompDefName). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). + AddComponentV2(mysqlCompName, compDef.GetName()). + AddVolumeClaimTemplate(testapps.DataVolumeName, testapps.NewPVCSpec("1Gi")). GetObject() - }) - - It("should auto fill first component if it's empty", func() { - reqCtx := intctrlutil.RequestCtx{ - Ctx: ctx, - Log: logger, - } - - By("fill simplified fields") - r := int32(3) - cluster.Spec.Replicas = &r - cluster.Spec.Resources.CPU = resource.MustParse("1000m") - cluster.Spec.Resources.Memory = resource.MustParse("2Gi") - cluster.Spec.Storage.Size = resource.MustParse("20Gi") - - By("clear cluster's component spec") - cluster.Spec.ComponentSpecs = nil - - By("build first component from simplified fields") - synthesizeComp, err := BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, cluster, nil) - Expect(err).Should(Succeed()) - Expect(synthesizeComp).ShouldNot(BeNil()) - Expect(synthesizeComp.Replicas).Should(Equal(*cluster.Spec.Replicas)) - Expect(synthesizeComp.VolumeClaimTemplates[0].Spec.Resources.Requests["storage"]).Should(Equal(cluster.Spec.Storage.Size)) - }) - It("build affinity correctly", func() { - reqCtx := intctrlutil.RequestCtx{ - Ctx: ctx, - Log: logger, - } - By("fill affinity") - cluster.Spec.AvailabilityPolicy = appsv1alpha1.AvailabilityPolicyZone - cluster.Spec.Tenancy = appsv1alpha1.DedicatedNode - By("clear cluster's component spec") - cluster.Spec.ComponentSpecs = nil - By("call build") - synthesizeComp, err := BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, cluster, nil) - Expect(err).Should(Succeed()) - Expect(synthesizeComp).ShouldNot(BeNil()) - Expect(synthesizeComp.PodSpec.Affinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution[0].PodAffinityTerm.TopologyKey).Should(Equal("topology.kubernetes.io/zone")) - Expect(synthesizeComp.PodSpec.Affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution[0].TopologyKey).Should(Equal("kubernetes.io/hostname")) }) - It("build network correctly", func() { - reqCtx := intctrlutil.RequestCtx{ - Ctx: ctx, - Log: logger, - } - By("setup cloud provider") - viper.Set(constant.CfgKeyServerInfo, "v1.26.5-gke.1200") - By("fill network") - cluster.Spec.Network = &appsv1alpha1.ClusterNetwork{ - HostNetworkAccessible: true, - PubliclyAccessible: false, - } - By("clear cluster's component spec") - cluster.Spec.ComponentSpecs = nil - By("call build") - synthesizeComp, err := BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, cluster, nil) + compObj := func() *appsv1alpha1.Component { + comp, err := BuildComponent(cluster, &cluster.Spec.ComponentSpecs[0], nil, nil) Expect(err).Should(Succeed()) - Expect(synthesizeComp).ShouldNot(BeNil()) - Expect(synthesizeComp.ComponentServices).Should(HaveLen(2)) - Expect(synthesizeComp.ComponentServices[1].Name).Should(Equal("vpc")) - Expect(synthesizeComp.ComponentServices[1].Annotations["networking.gke.io/load-balancer-type"]).Should(Equal("Internal")) - Expect(synthesizeComp.ComponentServices[1].Spec.Type).Should(BeEquivalentTo("LoadBalancer")) - }) + return comp + } It("Test replace secretRef env placeholder token", func() { By("mock connect credential and do replace placeholder token") @@ -171,19 +105,6 @@ var _ = Describe("Component", func() { } }) - It("should not fill component if none of simplified api is present", func() { - reqCtx := intctrlutil.RequestCtx{ - Ctx: ctx, - Log: logger, - } - By("clear cluster's component spec") - cluster.Spec.ComponentSpecs = nil - By("call build") - synthesizeComp, err := BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, cluster, nil) - Expect(err).Should(Succeed()) - Expect(synthesizeComp).Should(BeNil()) - }) - PIt("build serviceReference correctly", func() { reqCtx := intctrlutil.RequestCtx{ Ctx: ctx, @@ -210,7 +131,7 @@ var _ = Describe("Component", func() { testapps.NginxImage: serviceDescriptor, } By("call build") - synthesizeComp, err := BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, cluster, &cluster.Spec.ComponentSpecs[0]) + synthesizeComp, err := BuildSynthesizedComponent(reqCtx, testCtx.Cli, cluster, compDef, compObj()) Expect(err).Should(Succeed()) Expect(synthesizeComp).ShouldNot(BeNil()) Expect(synthesizeComp.ServiceReferences).ShouldNot(BeNil()) @@ -228,45 +149,42 @@ var _ = Describe("Component", func() { _2048m = resource.MustParse("2Gi") reqCtx = intctrlutil.RequestCtx{Ctx: ctx, Log: logger} ) - for i := range clusterDef.Spec.ComponentDefs { - compDef := &clusterDef.Spec.ComponentDefs[i] - compDef.PodSpec.Volumes = append(compDef.PodSpec.Volumes, []corev1.Volume{ - { - Name: "shmd-ok", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{ - Medium: corev1.StorageMediumMemory, - }, + compDef.Spec.Runtime.Volumes = append(compDef.Spec.Runtime.Volumes, []corev1.Volume{ + { + Name: "shmd-ok", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{ + Medium: corev1.StorageMediumMemory, }, }, - { - Name: "shmd-medium", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{ - Medium: corev1.StorageMediumDefault, - }, + }, + { + Name: "shmd-medium", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{ + Medium: corev1.StorageMediumDefault, }, }, - { - Name: "shmd-size-small", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{ - Medium: corev1.StorageMediumMemory, - SizeLimit: &_128m, - }, + }, + { + Name: "shmd-size-small", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{ + Medium: corev1.StorageMediumMemory, + SizeLimit: &_128m, }, }, - { - Name: "shmd-size-large", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{ - Medium: corev1.StorageMediumMemory, - SizeLimit: &_2048m, - }, + }, + { + Name: "shmd-size-large", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{ + Medium: corev1.StorageMediumMemory, + SizeLimit: &_2048m, }, }, - }...) - } + }, + }...) By("with memory resource set") if cluster.Spec.ComponentSpecs[0].Resources.Requests == nil { @@ -277,7 +195,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 := BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, cluster, &cluster.Spec.ComponentSpecs[0]) + comp, err := BuildSynthesizedComponent(reqCtx, testCtx.Cli, cluster, compDef.DeepCopy(), compObj()) Expect(err).Should(Succeed()) Expect(comp).ShouldNot(BeNil()) for _, vol := range comp.PodSpec.Volumes { @@ -298,7 +216,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 = BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, clusterDef, cluster, &cluster.Spec.ComponentSpecs[0]) + comp, err = BuildSynthesizedComponent(reqCtx, testCtx.Cli, cluster, compDef.DeepCopy(), compObj()) Expect(err).Should(Succeed()) Expect(comp).ShouldNot(BeNil()) for _, vol := range comp.PodSpec.Volumes { diff --git a/pkg/controller/component/definition_convertor.go b/pkg/controller/component/definition_convertor.go index 2ae9fa30ae66..54d6756821f5 100644 --- a/pkg/controller/component/definition_convertor.go +++ b/pkg/controller/component/definition_convertor.go @@ -22,13 +22,10 @@ package component import ( "fmt" - corev1 "k8s.io/api/core/v1" - appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" "github.com/apecloud/kubeblocks/pkg/apiutil" "github.com/apecloud/kubeblocks/pkg/constant" - "github.com/apecloud/kubeblocks/pkg/controller/builder" ) // TODO(component): type check @@ -191,50 +188,7 @@ func convertHostNetwork(clusterCompDef *appsv1alpha1.ClusterComponentDefinition) type compDefServicesConvertor struct{} func (c *compDefServicesConvertor) convert(args ...any) (any, error) { - clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - if clusterCompDef.Service == nil { - return nil, nil - } - - svc := builder.NewServiceBuilder("", ""). - SetType(corev1.ServiceTypeClusterIP). - AddPorts(clusterCompDef.Service.ToSVCSpec().Ports...). - GetObject() - services := []appsv1alpha1.ComponentService{ - { - Service: appsv1alpha1.Service{ - Name: "default", - ServiceName: "", - Spec: svc.Spec, - RoleSelector: c.roleSelector(clusterCompDef), - }, - }, - } - return services, nil -} - -func (c *compDefServicesConvertor) roleSelector(clusterCompDef *appsv1alpha1.ClusterComponentDefinition) string { - // if rsmSpec is not nil, pick the one with AccessMode == ReadWrite as the primary. - if clusterCompDef.RSMSpec != nil && clusterCompDef.RSMSpec.Roles != nil { - for _, role := range clusterCompDef.RSMSpec.Roles { - if role.AccessMode == workloads.ReadWriteMode { - return role.Name - } - } - } - - // convert the leader name w.r.t workload type. - switch clusterCompDef.WorkloadType { - case appsv1alpha1.Consensus: - if clusterCompDef.ConsensusSpec == nil { - return constant.Leader - } - return clusterCompDef.ConsensusSpec.Leader.Name - case appsv1alpha1.Replication: - return constant.Primary - default: - return "" - } + return nil, nil } // compDefConfigsConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.Configs. @@ -282,23 +236,7 @@ func (c *compDefReplicasLimitConvertor) convert(args ...any) (any, error) { type compDefSystemAccountsConvertor struct{} func (c *compDefSystemAccountsConvertor) convert(args ...any) (any, error) { - clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - if clusterCompDef.SystemAccounts == nil { - return nil, nil - } - - accounts := make([]appsv1alpha1.SystemAccount, 0) - for _, account := range clusterCompDef.SystemAccounts.Accounts { - accounts = append(accounts, appsv1alpha1.SystemAccount{ - Name: string(account.Name), - PasswordGenerationPolicy: clusterCompDef.SystemAccounts.PasswordConfig, - SecretRef: account.ProvisionPolicy.SecretRef, - }) - if account.ProvisionPolicy.Statements != nil { - accounts[len(accounts)-1].Statement = account.ProvisionPolicy.Statements.CreationStatement - } - } - return accounts, nil + return nil, nil } // compDefUpdateStrategyConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.UpdateStrategy. @@ -440,10 +378,6 @@ func (c *compDefLifecycleActionsConvertor) convert(args ...any) (any, error) { lifecycleActions.Switchover = c.convertSwitchover(clusterCompDef.SwitchoverSpec) } - if clusterCompDef.PostStartSpec != nil { - lifecycleActions.PostProvision = c.convertPostProvision(clusterCompDef.PostStartSpec) - } - lifecycleActions.PreTerminate = nil lifecycleActions.MemberJoin = nil lifecycleActions.MemberLeave = nil @@ -501,25 +435,6 @@ func (c *compDefLifecycleActionsConvertor) convertRoleProbe(clusterCompDef *apps return roleProbe } -func (c *compDefLifecycleActionsConvertor) convertPostProvision(postStart *appsv1alpha1.PostStartAction) *appsv1alpha1.LifecycleActionHandler { - if postStart == nil { - return nil - } - - defaultPreCondition := appsv1alpha1.ComponentReadyPreConditionType - return &appsv1alpha1.LifecycleActionHandler{ - CustomHandler: &appsv1alpha1.Action{ - Exec: &appsv1alpha1.ExecAction{ - Image: postStart.CmdExecutorConfig.Image, - Command: postStart.CmdExecutorConfig.Command, - Args: postStart.CmdExecutorConfig.Args, - Env: postStart.CmdExecutorConfig.Env, - }, - PreCondition: &defaultPreCondition, - }, - } -} - func (c *compDefLifecycleActionsConvertor) convertSwitchover(switchover *appsv1alpha1.SwitchoverSpec) *appsv1alpha1.ComponentSwitchover { spec := *switchover if spec.WithCandidate == nil && spec.WithoutCandidate == nil { diff --git a/pkg/controller/component/definition_convertor_test.go b/pkg/controller/component/definition_convertor_test.go index 0977279a2b8a..1da59d5df5cc 100644 --- a/pkg/controller/component/definition_convertor_test.go +++ b/pkg/controller/component/definition_convertor_test.go @@ -24,7 +24,6 @@ import ( . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/util/intstr" appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" @@ -117,26 +116,6 @@ var _ = Describe("Component Definition Convertor", func() { }, }, }, - Service: &appsv1alpha1.ServiceSpec{ - Ports: []appsv1alpha1.ServicePort{ - { - Name: "mysql", - Port: 3306, - TargetPort: intstr.IntOrString{ - Type: intstr.String, - StrVal: "mysql", - }, - }, - { - Name: "paxos", - Port: 13306, - TargetPort: intstr.IntOrString{ - Type: intstr.String, - StrVal: "paxos", - }, - }, - }, - }, StatelessSpec: nil, StatefulSpec: nil, ConsensusSpec: &appsv1alpha1.ConsensusSetSpec{ @@ -157,55 +136,6 @@ var _ = Describe("Component Definition Convertor", func() { }, ReplicationSpec: nil, HorizontalScalePolicy: &appsv1alpha1.HorizontalScalePolicy{}, - SystemAccounts: &appsv1alpha1.SystemAccountSpec{ - CmdExecutorConfig: &appsv1alpha1.CmdExecutorConfig{ - CommandExecutorEnvItem: appsv1alpha1.CommandExecutorEnvItem{ - Image: "image", - Env: []corev1.EnvVar{ - { - Name: "user", - Value: "user", - }, - { - Name: "password", - Value: "password", - }, - }, - }, - CommandExecutorItem: appsv1alpha1.CommandExecutorItem{ - Command: []string{"mysql"}, - Args: []string{"create user"}, - }, - }, - PasswordConfig: appsv1alpha1.PasswordConfig{ - Length: 16, - NumDigits: 8, - NumSymbols: 8, - LetterCase: appsv1alpha1.MixedCases, - }, - Accounts: []appsv1alpha1.SystemAccountConfig{ - { - Name: appsv1alpha1.AdminAccount, - ProvisionPolicy: appsv1alpha1.ProvisionPolicy{ - Type: appsv1alpha1.CreateByStmt, - Scope: appsv1alpha1.AnyPods, - Statements: &appsv1alpha1.ProvisionStatements{ - CreationStatement: "creation-statement", - }, - }, - }, - { - Name: appsv1alpha1.ReplicatorAccount, - ProvisionPolicy: appsv1alpha1.ProvisionPolicy{ - Type: appsv1alpha1.ReferToExisting, - SecretRef: &appsv1alpha1.ProvisionSecretRef{ - Name: "refer-to-existing", - Namespace: "default", - }, - }, - }, - }, - }, } }) @@ -367,49 +297,11 @@ var _ = Describe("Component Definition Convertor", func() { }) Context("services", func() { - It("w/o service defined", func() { - clusterCompDef.Service = nil - - convertor := &compDefServicesConvertor{} - res, err := convertor.convert(clusterCompDef, clusterName) - Expect(err).Should(Succeed()) - Expect(res).Should(BeNil()) - }) - It("ok", func() { convertor := &compDefServicesConvertor{} res, err := convertor.convert(clusterCompDef, clusterName) Expect(err).Should(Succeed()) - - services, ok := res.([]appsv1alpha1.ComponentService) - Expect(ok).Should(BeTrue()) - Expect(services).Should(HaveLen(1)) - - // service - Expect(services[0].ServiceName).Should(BeEmpty()) - Expect(services[0].Spec.Ports).Should(HaveLen(len(clusterCompDef.Service.Ports))) - for i := range services[0].Spec.Ports { - Expect(services[0].Spec.Ports[i].Name).Should(Equal(clusterCompDef.Service.Ports[i].Name)) - Expect(services[0].Spec.Ports[i].Port).Should(Equal(clusterCompDef.Service.Ports[i].Port)) - Expect(services[0].Spec.Ports[i].TargetPort).Should(Equal(clusterCompDef.Service.Ports[i].TargetPort)) - } - Expect(services[0].Spec.Type).Should(Equal(corev1.ServiceTypeClusterIP)) - Expect(services[0].Spec.ClusterIP).Should(BeEmpty()) - Expect(services[0].RoleSelector).Should(BeEquivalentTo(constant.Leader)) - - // consensus role selector - clusterCompDef.WorkloadType = appsv1alpha1.Consensus - clusterCompDef.ConsensusSpec = &appsv1alpha1.ConsensusSetSpec{ - Leader: appsv1alpha1.ConsensusMember{ - Name: constant.Primary, - AccessMode: appsv1alpha1.ReadWrite, - }, - } - res2, _ := convertor.convert(clusterCompDef, clusterName) - services2, ok2 := res2.([]appsv1alpha1.ComponentService) - Expect(ok2).Should(BeTrue()) - Expect(services2).Should(HaveLen(1)) - Expect(services2[0].RoleSelector).Should(BeEquivalentTo(constant.Primary)) + Expect(res).Should(BeNil()) }) }) @@ -449,34 +341,12 @@ var _ = Describe("Component Definition Convertor", func() { }) Context("system accounts", func() { - It("w/o accounts", func() { - clusterCompDef.SystemAccounts = nil - + It("ok", func() { convertor := &compDefSystemAccountsConvertor{} res, err := convertor.convert(clusterCompDef) Expect(err).Should(Succeed()) Expect(res).Should(BeNil()) }) - - It("w/ accounts", func() { - convertor := &compDefSystemAccountsConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - - expectedAccounts := []appsv1alpha1.SystemAccount{ - { - Name: string(clusterCompDef.SystemAccounts.Accounts[0].Name), - PasswordGenerationPolicy: clusterCompDef.SystemAccounts.PasswordConfig, - Statement: clusterCompDef.SystemAccounts.Accounts[0].ProvisionPolicy.Statements.CreationStatement, - }, - { - Name: string(clusterCompDef.SystemAccounts.Accounts[1].Name), - PasswordGenerationPolicy: clusterCompDef.SystemAccounts.PasswordConfig, - SecretRef: clusterCompDef.SystemAccounts.Accounts[1].ProvisionPolicy.SecretRef, - }, - } - Expect(res).Should(BeEquivalentTo(expectedAccounts)) - }) }) Context("update strategy", func() { @@ -641,34 +511,6 @@ var _ = Describe("Component Definition Convertor", func() { Expect(actions.Switchover.WithoutCandidate).ShouldNot(BeNil()) }) - It("post provision", func() { - clusterCompDef.Probes.RoleProbe = nil - clusterCompDef.SwitchoverSpec = nil - convertor := &compDefLifecycleActionsConvertor{} - clusterCompDef.PostStartSpec = &appsv1alpha1.PostStartAction{ - CmdExecutorConfig: appsv1alpha1.CmdExecutorConfig{ - CommandExecutorEnvItem: *commandExecutorEnvItem, - CommandExecutorItem: *commandExecutorItem, - }, - ScriptSpecSelectors: []appsv1alpha1.ScriptSpecSelector{ - { - Name: "post-start", - }, - }, - } - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - - actions := res.(*appsv1alpha1.ComponentLifecycleActions) - Expect(actions.PostProvision).ShouldNot(BeNil()) - Expect(actions.PostProvision.CustomHandler).ShouldNot(BeNil()) - Expect(actions.PostProvision.CustomHandler.Exec.Image).Should(BeEquivalentTo(commandExecutorEnvItem.Image)) - Expect(actions.PostProvision.CustomHandler.Exec.Env).Should(BeEquivalentTo(commandExecutorEnvItem.Env)) - Expect(actions.PostProvision.CustomHandler.Exec.Command).Should(BeEquivalentTo(commandExecutorItem.Command)) - Expect(actions.PostProvision.CustomHandler.Exec.Args).Should(BeEquivalentTo(commandExecutorItem.Args)) - Expect(*actions.PostProvision.CustomHandler.PreCondition).Should(BeEquivalentTo(appsv1alpha1.ComponentReadyPreConditionType)) - }) - It("role probe", func() { convertor := &compDefLifecycleActionsConvertor{} res, err := convertor.convert(clusterCompDef) diff --git a/pkg/controller/factory/builder_test.go b/pkg/controller/factory/builder_test.go index 902a7e80eaa7..25cb431e59e1 100644 --- a/pkg/controller/factory/builder_test.go +++ b/pkg/controller/factory/builder_test.go @@ -153,56 +153,6 @@ var _ = Describe("builder", func() { Expect(pvc.Spec.StorageClassName).Should(Equal(synthesizedComponent.VolumeClaimTemplates[0].Spec.StorageClassName)) }) - It("builds Conn. Credential correctly", func() { - var ( - clusterDefObj = testapps.NewClusterDefFactoryWithConnCredential("conn-cred", mysqlCompDefName).GetObject() - clusterDef, cluster, synthesizedComponent = newClusterObjs(clusterDefObj) - ) - credential := BuildConnCredential(clusterDef, cluster, synthesizedComponent) - Expect(credential).ShouldNot(BeNil()) - // "username": "root", - // "SVC_FQDN": "$(SVC_FQDN)", - // "RANDOM_PASSWD": "$(RANDOM_PASSWD)", - // "tcpEndpoint": "tcp:$(SVC_FQDN):$(SVC_PORT_mysql)", - // "paxosEndpoint": "paxos:$(SVC_FQDN):$(SVC_PORT_paxos)", - // "UUID": "$(UUID)", - // "UUID_B64": "$(UUID_B64)", - // "UUID_STR_B64": "$(UUID_STR_B64)", - // "UUID_HEX": "$(UUID_HEX)", - Expect(credential.StringData).ShouldNot(BeEmpty()) - Expect(credential.StringData["username"]).Should(Equal("root")) - - for _, v := range []string{ - "SVC_FQDN", - "RANDOM_PASSWD", - "UUID", - "UUID_B64", - "UUID_STR_B64", - "UUID_HEX", - "HEADLESS_SVC_FQDN", - } { - Expect(credential.StringData[v]).ShouldNot(BeEquivalentTo(fmt.Sprintf("$(%s)", v))) - } - Expect(credential.StringData["RANDOM_PASSWD"]).Should(HaveLen(8)) - svcFQDN := fmt.Sprintf("%s-%s", cluster.Name, synthesizedComponent.Name) - headlessSvcFQDN := fmt.Sprintf("%s-%s-headless", cluster.Name, synthesizedComponent.Name) - var mysqlPort corev1.ServicePort - var paxosPort corev1.ServicePort - for _, s := range synthesizedComponent.ComponentServices[0].Spec.Ports { - switch s.Name { - case "mysql": - mysqlPort = s - case "paxos": - paxosPort = s - } - } - Expect(credential.StringData["SVC_FQDN"]).Should(Equal(svcFQDN)) - Expect(credential.StringData["HEADLESS_SVC_FQDN"]).Should(Equal(headlessSvcFQDN)) - Expect(credential.StringData["tcpEndpoint"]).Should(Equal(fmt.Sprintf("tcp:%s:%d", svcFQDN, mysqlPort.Port))) - Expect(credential.StringData["paxosEndpoint"]).Should(Equal(fmt.Sprintf("paxos:%s:%d", svcFQDN, paxosPort.Port))) - - }) - It("builds Conn. Credential during restoring from backup", func() { originalPassword := "test-passw0rd" encryptionKey := "encryptionKey" diff --git a/pkg/testutil/apps/clusterdef_factory.go b/pkg/testutil/apps/clusterdef_factory.go index 3286c35bcbc0..da4e17e71eac 100644 --- a/pkg/testutil/apps/clusterdef_factory.go +++ b/pkg/testutil/apps/clusterdef_factory.go @@ -62,14 +62,14 @@ func NewClusterDefFactory(name string) *MockClusterDefFactory { ComponentDefs: []appsv1alpha1.ClusterComponentDefinition{}, }, }, f) - f.SetConnectionCredential(getDefaultConnectionCredential(), nil) + f.SetConnectionCredential(getDefaultConnectionCredential()) return f } func NewClusterDefFactoryWithConnCredential(name, compDefName string) *MockClusterDefFactory { f := NewClusterDefFactory(name) f.AddComponentDef(StatefulMySQLComponent, compDefName) - f.SetConnectionCredential(getDefaultConnectionCredential(), &defaultSvcSpec) + f.SetConnectionCredential(getDefaultConnectionCredential()) return f } @@ -91,20 +91,6 @@ func (factory *MockClusterDefFactory) AddComponentDef(tplType ComponentDefTplTyp return factory } -func (factory *MockClusterDefFactory) AddServicePort(port int32) *MockClusterDefFactory { - comp := factory.getLastCompDef() - if comp == nil { - return nil - } - comp.Service = &appsv1alpha1.ServiceSpec{ - Ports: []appsv1alpha1.ServicePort{{ - Protocol: corev1.ProtocolTCP, - Port: port, - }}, - } - return factory -} - func (factory *MockClusterDefFactory) AddContainerEnv(containerName string, envVar corev1.EnvVar) *MockClusterDefFactory { comp := factory.getLastCompDef() if comp == nil { @@ -130,20 +116,11 @@ func (factory *MockClusterDefFactory) AddHorizontalScalePolicy(policy appsv1alph return factory } -func (factory *MockClusterDefFactory) SetConnectionCredential( - connectionCredential map[string]string, svc *appsv1alpha1.ServiceSpec) *MockClusterDefFactory { +func (factory *MockClusterDefFactory) SetConnectionCredential(connectionCredential map[string]string) *MockClusterDefFactory { factory.Get().Spec.ConnectionCredential = connectionCredential - factory.SetServiceSpec(svc) return factory } -func (factory *MockClusterDefFactory) get1stCompDef() *appsv1alpha1.ClusterComponentDefinition { - if len(factory.Get().Spec.ComponentDefs) == 0 { - return nil - } - return &factory.Get().Spec.ComponentDefs[0] -} - func (factory *MockClusterDefFactory) getLastCompDef() *appsv1alpha1.ClusterComponentDefinition { l := len(factory.Get().Spec.ComponentDefs) if l == 0 { @@ -153,24 +130,6 @@ func (factory *MockClusterDefFactory) getLastCompDef() *appsv1alpha1.ClusterComp return &comps[l-1] } -func (factory *MockClusterDefFactory) SetServiceSpec(svc *appsv1alpha1.ServiceSpec) *MockClusterDefFactory { - comp := factory.get1stCompDef() - if comp == nil { - return factory - } - comp.Service = svc - return factory -} - -func (factory *MockClusterDefFactory) AddSystemAccountSpec(sysAccounts *appsv1alpha1.SystemAccountSpec) *MockClusterDefFactory { - comp := factory.getLastCompDef() - if comp == nil { - return factory - } - comp.SystemAccounts = sysAccounts - return factory -} - func (factory *MockClusterDefFactory) AddSwitchoverSpec(switchoverSpec *appsv1alpha1.SwitchoverSpec) *MockClusterDefFactory { comp := factory.getLastCompDef() if comp == nil { @@ -207,29 +166,6 @@ func (factory *MockClusterDefFactory) AddReplicationSpec(replicationSpec *appsv1 return factory } -func (factory *MockClusterDefFactory) AddNamedServicePort(name string, port int32) *MockClusterDefFactory { - comp := factory.getLastCompDef() - if comp == nil { - return nil - } - if comp.Service != nil { - comp.Service.Ports = append(comp.Service.Ports, appsv1alpha1.ServicePort{ - Name: name, - Protocol: corev1.ProtocolTCP, - Port: port, - }) - return factory - } - comp.Service = &appsv1alpha1.ServiceSpec{ - Ports: []appsv1alpha1.ServicePort{{ - Name: name, - Protocol: corev1.ProtocolTCP, - Port: port, - }}, - } - return factory -} - func (factory *MockClusterDefFactory) AddClusterTopology(topology appsv1alpha1.ClusterTopology) *MockClusterDefFactory { factory.Get().Spec.Topologies = append(factory.Get().Spec.Topologies, topology) return factory diff --git a/pkg/testutil/apps/constant.go b/pkg/testutil/apps/constant.go index 6d134e8660f0..e9f0c1f9cfe3 100644 --- a/pkg/testutil/apps/constant.go +++ b/pkg/testutil/apps/constant.go @@ -92,35 +92,6 @@ var ( Resources: zeroResRequirements, }}, }, - Service: &appsv1alpha1.ServiceSpec{ - Ports: []appsv1alpha1.ServicePort{{ - Protocol: corev1.ProtocolTCP, - Port: 80, - }}, - }, - } - - // defaultSvc value are corresponding to defaultMySQLContainer.Ports name mapping and - // corresponding to defaultConnectionCredential variable placeholder - defaultSvcSpec = appsv1alpha1.ServiceSpec{ - Ports: []appsv1alpha1.ServicePort{ - { - Name: "mysql", - TargetPort: intstr.IntOrString{ - Type: intstr.String, - StrVal: "mysql", - }, - Port: 3306, - }, - { - Name: "paxos", - TargetPort: intstr.IntOrString{ - Type: intstr.String, - StrVal: "paxos", - }, - Port: 13306, - }, - }, } defaultMySQLContainer = corev1.Container{ @@ -167,7 +138,6 @@ var ( TimeoutSeconds: 5, }, }, - Service: &defaultMySQLService, PodSpec: &corev1.PodSpec{ Containers: []corev1.Container{ defaultMySQLContainer, @@ -189,14 +159,6 @@ var ( }, } - defaultMySQLService = appsv1alpha1.ServiceSpec{ - Ports: []appsv1alpha1.ServicePort{{ - Name: "mysql", - Protocol: corev1.ProtocolTCP, - Port: 3306, - }}, - } - consensusMySQLComponent = appsv1alpha1.ClusterComponentDefinition{ WorkloadType: appsv1alpha1.Consensus, ConsensusSpec: &defaultConsensusSpec, @@ -207,7 +169,6 @@ var ( TimeoutSeconds: 5, }, }, - Service: &defaultMySQLService, PodSpec: &corev1.PodSpec{ Containers: []corev1.Container{ defaultMySQLContainer, @@ -236,6 +197,24 @@ var ( }, }, Services: []appsv1alpha1.ComponentService{ + { + Service: appsv1alpha1.Service{ + Name: "default", + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + { + Protocol: corev1.ProtocolTCP, + Port: 3306, + TargetPort: intstr.IntOrString{ + Type: intstr.String, + StrVal: "mysql", + }, + }, + }, + }, + RoleSelector: "leader", + }, + }, { Service: appsv1alpha1.Service{ Name: "rw", @@ -363,13 +342,6 @@ var ( }, } - defaultRedisService = appsv1alpha1.ServiceSpec{ - Ports: []appsv1alpha1.ServicePort{{ - Protocol: corev1.ProtocolTCP, - Port: 6379, - }}, - } - defaultReplicationRedisVolumeMounts = []corev1.VolumeMount{ { Name: DataVolumeName, @@ -430,7 +402,6 @@ var ( TimeoutSeconds: 5, }, }, - Service: &defaultRedisService, PodSpec: &corev1.PodSpec{ Volumes: []corev1.Volume{ { From af21346fec290903e733a5f0da43adb25b97054f Mon Sep 17 00:00:00 2001 From: Leon Date: Tue, 6 Aug 2024 00:54:43 +0800 Subject: [PATCH 37/45] chore: remove the conn-credential (#7765) --- apis/apps/v1alpha1/clusterdefinition_types.go | 26 ----- apis/apps/v1alpha1/zz_generated.deepcopy.go | 7 -- ...apps.kubeblocks.io_clusterdefinitions.yaml | 29 ----- controllers/apps/cluster_controller.go | 2 - controllers/apps/operations/datascript.go | 7 +- .../apps/operations/datascript_test.go | 2 +- .../apps/operations/switchover_util.go | 17 --- .../apps/transformer_cluster_backup_policy.go | 29 +---- .../apps/transformer_cluster_credential.go | 87 --------------- ...apps.kubeblocks.io_clusterdefinitions.yaml | 29 ----- docs/developer_docs/api-reference/cluster.md | 62 ----------- go.mod | 2 +- .../config_manager/handler_util.go | 2 +- pkg/constant/const.go | 1 - pkg/constant/pattern.go | 6 - pkg/controller/component/component_test.go | 45 +------- pkg/controller/component/its_convertor.go | 60 +++++----- pkg/controller/component/lorry_utils.go | 2 - .../component/service_descriptor_utils.go | 3 +- .../component/synthesize_component.go | 32 ------ pkg/controller/configuration/builtin_env.go | 3 - pkg/controller/configuration/config_utils.go | 6 +- .../configuration/tool_image_builder_test.go | 1 - pkg/controller/factory/builder.go | 104 ------------------ pkg/controller/factory/builder_test.go | 20 ---- pkg/testutil/apps/clusterdef_factory.go | 29 ----- 26 files changed, 43 insertions(+), 570 deletions(-) delete mode 100644 controllers/apps/transformer_cluster_credential.go diff --git a/apis/apps/v1alpha1/clusterdefinition_types.go b/apis/apps/v1alpha1/clusterdefinition_types.go index 5551c60ddc0a..a0d557d2925e 100644 --- a/apis/apps/v1alpha1/clusterdefinition_types.go +++ b/apis/apps/v1alpha1/clusterdefinition_types.go @@ -43,32 +43,6 @@ type ClusterDefinitionSpec struct { // +optional ComponentDefs []ClusterComponentDefinition `json:"componentDefs" patchStrategy:"merge,retainKeys" patchMergeKey:"name"` - // Connection credential template used for creating a connection credential secret for cluster objects. - // - // Built-in objects are: - // - // - `$(RANDOM_PASSWD)` random 8 characters. - // - `$(STRONG_RANDOM_PASSWD)` random 16 characters, with mixed cases, digits and symbols. - // - `$(UUID)` generate a random UUID v4 string. - // - `$(UUID_B64)` generate a random UUID v4 BASE64 encoded string. - // - `$(UUID_STR_B64)` generate a random UUID v4 string then BASE64 encoded. - // - `$(UUID_HEX)` generate a random UUID v4 HEX representation. - // - `$(HEADLESS_SVC_FQDN)` headless service FQDN placeholder, value pattern is `$(CLUSTER_NAME)-$(1ST_COMP_NAME)-headless.$(NAMESPACE).svc`, - // where 1ST_COMP_NAME is the 1st component that provide `ClusterDefinition.spec.componentDefs[].service` attribute; - // - `$(SVC_FQDN)` service FQDN placeholder, value pattern is `$(CLUSTER_NAME)-$(1ST_COMP_NAME).$(NAMESPACE).svc`, - // where 1ST_COMP_NAME is the 1st component that provide `ClusterDefinition.spec.componentDefs[].service` attribute; - // - `$(SVC_PORT_{PORT-NAME})` is ServicePort's port value with specified port name, i.e, a servicePort JSON struct: - // `{"name": "mysql", "targetPort": "mysqlContainerPort", "port": 3306}`, and `$(SVC_PORT_mysql)` in the - // connection credential value is 3306. - // - // Deprecated since v0.9. - // This field is maintained for backward compatibility and its use is discouraged. - // Existing usage should be updated to the current preferred approach to avoid compatibility issues in future releases. - // - // +kubebuilder:deprecatedversion:warning="This field has been deprecated since 0.9.0" - // +optional - ConnectionCredential map[string]string `json:"connectionCredential,omitempty"` - // Topologies defines all possible topologies within the cluster. // // +kubebuilder:validation:MinItems=1 diff --git a/apis/apps/v1alpha1/zz_generated.deepcopy.go b/apis/apps/v1alpha1/zz_generated.deepcopy.go index 28ef93f46349..5083370bbb77 100644 --- a/apis/apps/v1alpha1/zz_generated.deepcopy.go +++ b/apis/apps/v1alpha1/zz_generated.deepcopy.go @@ -842,13 +842,6 @@ func (in *ClusterDefinitionSpec) DeepCopyInto(out *ClusterDefinitionSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.ConnectionCredential != nil { - in, out := &in.ConnectionCredential, &out.ConnectionCredential - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } if in.Topologies != nil { in, out := &in.Topologies, &out.Topologies *out = make([]ClusterTopology, len(*in)) diff --git a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml index f1d83dc56fd3..e433b1d10397 100644 --- a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml @@ -8502,35 +8502,6 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map - connectionCredential: - additionalProperties: - type: string - description: |- - Connection credential template used for creating a connection credential secret for cluster objects. - - - Built-in objects are: - - - - `$(RANDOM_PASSWD)` random 8 characters. - - `$(STRONG_RANDOM_PASSWD)` random 16 characters, with mixed cases, digits and symbols. - - `$(UUID)` generate a random UUID v4 string. - - `$(UUID_B64)` generate a random UUID v4 BASE64 encoded string. - - `$(UUID_STR_B64)` generate a random UUID v4 string then BASE64 encoded. - - `$(UUID_HEX)` generate a random UUID v4 HEX representation. - - `$(HEADLESS_SVC_FQDN)` headless service FQDN placeholder, value pattern is `$(CLUSTER_NAME)-$(1ST_COMP_NAME)-headless.$(NAMESPACE).svc`, - where 1ST_COMP_NAME is the 1st component that provide `ClusterDefinition.spec.componentDefs[].service` attribute; - - `$(SVC_FQDN)` service FQDN placeholder, value pattern is `$(CLUSTER_NAME)-$(1ST_COMP_NAME).$(NAMESPACE).svc`, - where 1ST_COMP_NAME is the 1st component that provide `ClusterDefinition.spec.componentDefs[].service` attribute; - - `$(SVC_PORT_{PORT-NAME})` is ServicePort's port value with specified port name, i.e, a servicePort JSON struct: - `{"name": "mysql", "targetPort": "mysqlContainerPort", "port": 3306}`, and `$(SVC_PORT_mysql)` in the - connection credential value is 3306. - - - Deprecated since v0.9. - This field is maintained for backward compatibility and its use is discouraged. - Existing usage should be updated to the current preferred approach to avoid compatibility issues in future releases. - type: object topologies: description: Topologies defines all possible topologies within the cluster. diff --git a/controllers/apps/cluster_controller.go b/controllers/apps/cluster_controller.go index 388b4489e303..aff101604523 100644 --- a/controllers/apps/cluster_controller.go +++ b/controllers/apps/cluster_controller.go @@ -149,8 +149,6 @@ func (r *ClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct &clusterComponentTransformer{}, // update cluster components' status &clusterComponentStatusTransformer{}, - // create default cluster connection credential secret object - &clusterConnCredentialTransformer{}, // build backuppolicy and backupschedule from backupPolicyTemplate &clusterBackupPolicyTransformer{}, // add our finalizer to all objects diff --git a/controllers/apps/operations/datascript.go b/controllers/apps/operations/datascript.go index 2193b0619025..87ef2955a81d 100644 --- a/controllers/apps/operations/datascript.go +++ b/controllers/apps/operations/datascript.go @@ -245,12 +245,9 @@ func buildDataScriptJobs(reqCtx intctrlutil.RequestCtx, cli client.Client, clust // parse username and password secretFrom := ops.Spec.ScriptSpec.Secret if secretFrom == nil { - secretFrom = &appsv1alpha1.ScriptSecret{ - Name: constant.GenerateDefaultConnCredential(cluster.Name), - PasswordKey: "password", - UsernameKey: "username", - } + return nil, intctrlutil.NewFatalError("missing secret for user & password") } + // verify secrets exist if err := cli.Get(reqCtx.Ctx, types.NamespacedName{Namespace: reqCtx.Req.Namespace, Name: secretFrom.Name}, &corev1.Secret{}); err != nil { return nil, intctrlutil.NewFatalError(err.Error()) diff --git a/controllers/apps/operations/datascript_test.go b/controllers/apps/operations/datascript_test.go index d9b9452ac8f0..8b93043b0adb 100644 --- a/controllers/apps/operations/datascript_test.go +++ b/controllers/apps/operations/datascript_test.go @@ -252,7 +252,7 @@ var _ = Describe("DataScriptOps", func() { By("mock a job one more time, fail with missing secret") _, err = buildDataScriptJobs(reqCtx, k8sClient, clusterObj, comp, ops, "mysql") Expect(err).Should(HaveOccurred()) - Expect(err.Error()).Should(ContainSubstring("conn-credential")) + Expect(err.Error()).Should(ContainSubstring("missing secret")) By("patch a secret name to ops, fail with missing secret") secretName := fmt.Sprintf("%s-%s", clusterObj.Name, comp.Name) diff --git a/controllers/apps/operations/switchover_util.go b/controllers/apps/operations/switchover_util.go index 32eaf0694dba..ec0b75e33f71 100644 --- a/controllers/apps/operations/switchover_util.go +++ b/controllers/apps/operations/switchover_util.go @@ -360,8 +360,6 @@ func buildSwitchoverEnvs(ctx context.Context, return nil, errors.New("switchover spec withCandidate and withoutCandidate can't be nil at the same time") } - // replace secret env and merge envs defined in SwitchoverSpec - replaceSwitchoverConnCredentialEnv(synthesizeComp.LifecycleActions.Switchover, cluster.Name, synthesizeComp.Name) var switchoverEnvs []corev1.EnvVar switch switchover.InstanceName { case KBSwitchoverCandidateInstanceForAnyPod: @@ -387,21 +385,6 @@ func buildSwitchoverEnvs(ctx context.Context, return switchoverEnvs, nil } -// replaceSwitchoverConnCredentialEnv replaces the connection credential environment variables for the switchover job. -func replaceSwitchoverConnCredentialEnv(switchoverSpec *appsv1alpha1.ComponentSwitchover, clusterName, componentName string) { - if switchoverSpec == nil { - return - } - connCredentialMap := component.GetEnvReplacementMapForConnCredential(clusterName) - replaceEnvVars := func(action *appsv1alpha1.Action) { - if action != nil { - action.Exec.Env = component.ReplaceSecretEnvVars(connCredentialMap, action.Exec.Env) - } - } - replaceEnvVars(switchoverSpec.WithCandidate) - replaceEnvVars(switchoverSpec.WithoutCandidate) -} - // buildSwitchoverWorkloadEnvs builds the replication or consensus workload environment variables for the switchover job. func buildSwitchoverWorkloadEnvs(ctx context.Context, cli client.Client, diff --git a/controllers/apps/transformer_cluster_backup_policy.go b/controllers/apps/transformer_cluster_backup_policy.go index b708ba1c75ca..fff26d0d6127 100644 --- a/controllers/apps/transformer_cluster_backup_policy.go +++ b/controllers/apps/transformer_cluster_backup_policy.go @@ -510,31 +510,12 @@ func (r *clusterBackupPolicyTransformer) buildBackupTarget( target.Name = comp.fullComponentName } // build the target connection credential - cc := dpv1alpha1.ConnectionCredential{} - switch { - case len(comp.compSpec.ComponentDef) > 0 && len(targetTpl.Account) > 0: - cc.SecretName = constant.GenerateAccountSecretName(clusterName, comp.fullComponentName, targetTpl.Account) - cc.PasswordKey = constant.AccountPasswdForSecret - cc.UsernameKey = constant.AccountNameForSecret - case len(comp.compSpec.ComponentDef) == 0 && len(comp.compSpec.ComponentDefRef) > 0: - // TODO: remove HACK code in version 0.9, only no componentDef can using connect credential - cc.SecretName = constant.GenerateDefaultConnCredential(clusterName) - ccKey := targetTpl.ConnectionCredentialKey - if ccKey.PasswordKey != nil { - cc.PasswordKey = *ccKey.PasswordKey - } - if ccKey.UsernameKey != nil { - cc.UsernameKey = *ccKey.UsernameKey - } - if ccKey.PortKey != nil { - cc.PortKey = *ccKey.PortKey + if targetTpl.Account != "" { + target.ConnectionCredential = &dpv1alpha1.ConnectionCredential{ + SecretName: constant.GenerateAccountSecretName(clusterName, comp.fullComponentName, targetTpl.Account), + PasswordKey: constant.AccountPasswdForSecret, + UsernameKey: constant.AccountNameForSecret, } - if ccKey.HostKey != nil { - cc.HostKey = *ccKey.HostKey - } - } - if cc.SecretName != "" { - target.ConnectionCredential = &cc } return target } diff --git a/controllers/apps/transformer_cluster_credential.go b/controllers/apps/transformer_cluster_credential.go deleted file mode 100644 index c8c7041707ba..000000000000 --- a/controllers/apps/transformer_cluster_credential.go +++ /dev/null @@ -1,87 +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 apps - -import ( - corev1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/apecloud/kubeblocks/pkg/common" - "github.com/apecloud/kubeblocks/pkg/controller/component" - "github.com/apecloud/kubeblocks/pkg/controller/factory" - "github.com/apecloud/kubeblocks/pkg/controller/graph" - "github.com/apecloud/kubeblocks/pkg/controller/model" -) - -// clusterCredentialTransformer creates the default cluster connection credential secret -type clusterConnCredentialTransformer struct{} - -var _ graph.Transformer = &clusterConnCredentialTransformer{} - -func (t *clusterConnCredentialTransformer) Transform(ctx graph.TransformContext, dag *graph.DAG) error { - transCtx, _ := ctx.(*clusterTransformContext) - if model.IsObjectDeleting(transCtx.OrigCluster) { - return nil - } - if common.IsCompactMode(transCtx.OrigCluster.Annotations) { - transCtx.V(1).Info("Cluster is in compact mode, no need to create accounts related secrets", "cluster", client.ObjectKeyFromObject(transCtx.OrigCluster)) - return nil - } - - if !t.isLegacyCluster(transCtx) { - return nil - } - return t.buildClusterConnCredential(transCtx, dag) -} - -func (t *clusterConnCredentialTransformer) isLegacyCluster(transCtx *clusterTransformContext) bool { - for _, compSpec := range transCtx.ComponentSpecs { - compDef, ok := transCtx.ComponentDefs[compSpec.ComponentDef] - if ok && (len(compDef.UID) > 0 || !compDef.CreationTimestamp.IsZero()) { - return false - } - } - return true -} - -func (t *clusterConnCredentialTransformer) buildClusterConnCredential(transCtx *clusterTransformContext, dag *graph.DAG) error { - graphCli, _ := transCtx.Client.(model.GraphClient) - synthesizedComponent := t.buildSynthesizedComponent(transCtx) - if synthesizedComponent == nil { - return nil - } - secret := factory.BuildConnCredential(transCtx.ClusterDef, transCtx.Cluster, synthesizedComponent) - if secret == nil { - return nil - } - err := transCtx.Client.Get(transCtx.Context, client.ObjectKeyFromObject(secret), &corev1.Secret{}) - if err != nil && !apierrors.IsNotFound(err) { - return err - } - if apierrors.IsNotFound(err) { - graphCli.Create(dag, secret, inUniversalContext4G()) - } - return nil -} - -func (t *clusterConnCredentialTransformer) buildSynthesizedComponent(transCtx *clusterTransformContext) *component.SynthesizedComponent { - return nil -} diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml index f1d83dc56fd3..e433b1d10397 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml @@ -8502,35 +8502,6 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map - connectionCredential: - additionalProperties: - type: string - description: |- - Connection credential template used for creating a connection credential secret for cluster objects. - - - Built-in objects are: - - - - `$(RANDOM_PASSWD)` random 8 characters. - - `$(STRONG_RANDOM_PASSWD)` random 16 characters, with mixed cases, digits and symbols. - - `$(UUID)` generate a random UUID v4 string. - - `$(UUID_B64)` generate a random UUID v4 BASE64 encoded string. - - `$(UUID_STR_B64)` generate a random UUID v4 string then BASE64 encoded. - - `$(UUID_HEX)` generate a random UUID v4 HEX representation. - - `$(HEADLESS_SVC_FQDN)` headless service FQDN placeholder, value pattern is `$(CLUSTER_NAME)-$(1ST_COMP_NAME)-headless.$(NAMESPACE).svc`, - where 1ST_COMP_NAME is the 1st component that provide `ClusterDefinition.spec.componentDefs[].service` attribute; - - `$(SVC_FQDN)` service FQDN placeholder, value pattern is `$(CLUSTER_NAME)-$(1ST_COMP_NAME).$(NAMESPACE).svc`, - where 1ST_COMP_NAME is the 1st component that provide `ClusterDefinition.spec.componentDefs[].service` attribute; - - `$(SVC_PORT_{PORT-NAME})` is ServicePort's port value with specified port name, i.e, a servicePort JSON struct: - `{"name": "mysql", "targetPort": "mysqlContainerPort", "port": 3306}`, and `$(SVC_PORT_mysql)` in the - connection credential value is 3306. - - - Deprecated since v0.9. - This field is maintained for backward compatibility and its use is discouraged. - Existing usage should be updated to the current preferred approach to avoid compatibility issues in future releases. - type: object topologies: description: Topologies defines all possible topologies within the cluster. diff --git a/docs/developer_docs/api-reference/cluster.md b/docs/developer_docs/api-reference/cluster.md index e7a6fe2ece88..c228091ece49 100644 --- a/docs/developer_docs/api-reference/cluster.md +++ b/docs/developer_docs/api-reference/cluster.md @@ -531,37 +531,6 @@ Existing usage should be updated to the current preferred approach to avoid comp -connectionCredential
    - -map[string]string - - - -(Optional) -

    Connection credential template used for creating a connection credential secret for cluster objects.

    -

    Built-in objects are:

    -
      -
    • $(RANDOM_PASSWD) random 8 characters.
    • -
    • $(STRONG_RANDOM_PASSWD) random 16 characters, with mixed cases, digits and symbols.
    • -
    • $(UUID) generate a random UUID v4 string.
    • -
    • $(UUID_B64) generate a random UUID v4 BASE64 encoded string.
    • -
    • $(UUID_STR_B64) generate a random UUID v4 string then BASE64 encoded.
    • -
    • $(UUID_HEX) generate a random UUID v4 HEX representation.
    • -
    • $(HEADLESS_SVC_FQDN) headless service FQDN placeholder, value pattern is $(CLUSTER_NAME)-$(1ST_COMP_NAME)-headless.$(NAMESPACE).svc, -where 1ST_COMP_NAME is the 1st component that provide ClusterDefinition.spec.componentDefs[].service attribute;
    • -
    • $(SVC_FQDN) service FQDN placeholder, value pattern is $(CLUSTER_NAME)-$(1ST_COMP_NAME).$(NAMESPACE).svc, -where 1ST_COMP_NAME is the 1st component that provide ClusterDefinition.spec.componentDefs[].service attribute;
    • -
    • $(SVC_PORT_{PORT-NAME}) is ServicePort’s port value with specified port name, i.e, a servicePort JSON struct: -{"name": "mysql", "targetPort": "mysqlContainerPort", "port": 3306}, and $(SVC_PORT_mysql) in the -connection credential value is 3306.
    • -
    -

    Deprecated since v0.9. -This field is maintained for backward compatibility and its use is discouraged. -Existing usage should be updated to the current preferred approach to avoid compatibility issues in future releases.

    - - - - topologies
    @@ -5292,37 +5261,6 @@ Existing usage should be updated to the current preferred approach to avoid comp -connectionCredential
    - -map[string]string - - - -(Optional) -

    Connection credential template used for creating a connection credential secret for cluster objects.

    -

    Built-in objects are:

    -
      -
    • $(RANDOM_PASSWD) random 8 characters.
    • -
    • $(STRONG_RANDOM_PASSWD) random 16 characters, with mixed cases, digits and symbols.
    • -
    • $(UUID) generate a random UUID v4 string.
    • -
    • $(UUID_B64) generate a random UUID v4 BASE64 encoded string.
    • -
    • $(UUID_STR_B64) generate a random UUID v4 string then BASE64 encoded.
    • -
    • $(UUID_HEX) generate a random UUID v4 HEX representation.
    • -
    • $(HEADLESS_SVC_FQDN) headless service FQDN placeholder, value pattern is $(CLUSTER_NAME)-$(1ST_COMP_NAME)-headless.$(NAMESPACE).svc, -where 1ST_COMP_NAME is the 1st component that provide ClusterDefinition.spec.componentDefs[].service attribute;
    • -
    • $(SVC_FQDN) service FQDN placeholder, value pattern is $(CLUSTER_NAME)-$(1ST_COMP_NAME).$(NAMESPACE).svc, -where 1ST_COMP_NAME is the 1st component that provide ClusterDefinition.spec.componentDefs[].service attribute;
    • -
    • $(SVC_PORT_{PORT-NAME}) is ServicePort’s port value with specified port name, i.e, a servicePort JSON struct: -{"name": "mysql", "targetPort": "mysqlContainerPort", "port": 3306}, and $(SVC_PORT_mysql) in the -connection credential value is 3306.
    • -
    -

    Deprecated since v0.9. -This field is maintained for backward compatibility and its use is discouraged. -Existing usage should be updated to the current preferred approach to avoid compatibility issues in future releases.

    - - - - topologies
    diff --git a/go.mod b/go.mod index 6e6d19933ad2..268c914154e1 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,6 @@ require ( github.com/go-sql-driver/mysql v1.7.1 github.com/golang/mock v1.6.0 github.com/google/go-cmp v0.6.0 - github.com/google/uuid v1.6.0 github.com/hashicorp/go-hclog v1.5.0 github.com/hashicorp/vault/sdk v0.9.2 github.com/imdario/mergo v0.3.14 @@ -163,6 +162,7 @@ require ( github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20230323073829-e72429f035bd // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/gosuri/uitable v0.0.4 // indirect diff --git a/pkg/configuration/config_manager/handler_util.go b/pkg/configuration/config_manager/handler_util.go index c9ffbe5e02f8..ac7d6e882e4b 100644 --- a/pkg/configuration/config_manager/handler_util.go +++ b/pkg/configuration/config_manager/handler_util.go @@ -44,7 +44,7 @@ type CfgManagerBuildParams struct { Volumes []corev1.VolumeMount `json:"volumes"` ComponentName string `json:"componentName"` - SecreteName string `json:"secreteName"` + SecreteName string `json:"secreteName"` // TODO(v1.0): conn-credential // add volume to pod ScriptVolume []corev1.Volume diff --git a/pkg/constant/const.go b/pkg/constant/const.go index 37758effadde..7173f9dfd28c 100644 --- a/pkg/constant/const.go +++ b/pkg/constant/const.go @@ -29,7 +29,6 @@ const ( // TODO: deprecated, will be removed later. const ( - KBConnCredentialPlaceHolder = "$(CONN_CREDENTIAL_SECRET_NAME)" KBComponentEnvCMPlaceHolder = "$(COMP_ENV_CM_NAME)" KBToolsImagePlaceHolder = "$(KUBEBLOCKS_TOOLS_IMAGE)" ) diff --git a/pkg/constant/pattern.go b/pkg/constant/pattern.go index fe3f6cce033c..ba466a90c367 100644 --- a/pkg/constant/pattern.go +++ b/pkg/constant/pattern.go @@ -69,12 +69,6 @@ func GenerateDefaultComponentHeadlessServiceName(clusterName, compName string) s return GenerateComponentHeadlessServiceName(clusterName, compName, "") } -// GenerateDefaultConnCredential generates the default connection credential name for cluster. -// TODO: deprecated, will be removed later. -func GenerateDefaultConnCredential(clusterName string) string { - return fmt.Sprintf("%s-conn-credential", clusterName) -} - // GenerateClusterComponentEnvPattern generates cluster and component pattern func GenerateClusterComponentEnvPattern(clusterName, compName string) string { return fmt.Sprintf("%s-%s-env", clusterName, compName) diff --git a/pkg/controller/component/component_test.go b/pkg/controller/component/component_test.go index 3f1aea1c5d5d..781b54cf32d1 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" appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" - "github.com/apecloud/kubeblocks/pkg/constant" intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" ) @@ -40,11 +39,9 @@ var _ = Describe("Component", func() { Context("has the BuildComponent function", func() { const ( - compDefName = "test-compdef" - clusterName = "test-cluster" - mysqlCompName = "mysql" - mysqlSecretUserEnvName = "MYSQL_ROOT_USER" - mysqlSecretPasswdEnvName = "MYSQL_ROOT_PASSWORD" + compDefName = "test-compdef" + clusterName = "test-cluster" + mysqlCompName = "mysql" ) var ( @@ -69,42 +66,6 @@ var _ = Describe("Component", func() { return comp } - It("Test replace secretRef env placeholder token", func() { - By("mock connect credential and do replace placeholder token") - credentialMap := GetEnvReplacementMapForConnCredential(cluster.Name) - mockEnvs := []corev1.EnvVar{ - { - Name: mysqlSecretUserEnvName, - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: "username", - LocalObjectReference: corev1.LocalObjectReference{ - Name: constant.KBConnCredentialPlaceHolder, - }, - }, - }, - }, - { - Name: mysqlSecretPasswdEnvName, - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: "password", - LocalObjectReference: corev1.LocalObjectReference{ - Name: constant.KBConnCredentialPlaceHolder, - }, - }, - }, - }, - } - mockEnvs = ReplaceSecretEnvVars(credentialMap, mockEnvs) - Expect(len(mockEnvs)).Should(Equal(2)) - for _, env := range mockEnvs { - Expect(env.ValueFrom).ShouldNot(BeNil()) - Expect(env.ValueFrom.SecretKeyRef).ShouldNot(BeNil()) - Expect(env.ValueFrom.SecretKeyRef.Name).Should(Equal(constant.GenerateDefaultConnCredential(cluster.Name))) - } - }) - PIt("build serviceReference correctly", func() { reqCtx := intctrlutil.RequestCtx{ Ctx: ctx, diff --git a/pkg/controller/component/its_convertor.go b/pkg/controller/component/its_convertor.go index fe18b2ff8485..969e80f1d534 100644 --- a/pkg/controller/component/its_convertor.go +++ b/pkg/controller/component/its_convertor.go @@ -320,47 +320,39 @@ func (c *itsCredentialConvertor) convert(args ...any) (any, error) { return nil, err } - // use first init account as the default credential - var sysInitAccount *appsv1alpha1.SystemAccount - for index, sysAccount := range synthesizeComp.SystemAccounts { - if sysAccount.InitAccount { - sysInitAccount = &synthesizeComp.SystemAccounts[index] - break - } - } - if sysInitAccount == nil && len(synthesizeComp.CompDefName) != 0 { - return nil, nil - } - - var secretName string - if sysInitAccount != nil { - secretName = constant.GenerateAccountSecretName(synthesizeComp.ClusterName, synthesizeComp.Name, sysInitAccount.Name) - } else { - secretName = constant.GenerateDefaultConnCredential(synthesizeComp.ClusterName) - } - credential := &workloads.Credential{ - Username: workloads.CredentialVar{ - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: secretName, + credential := func(sysAccount appsv1alpha1.SystemAccount) *workloads.Credential { + secretName := constant.GenerateAccountSecretName(synthesizeComp.ClusterName, synthesizeComp.Name, sysAccount.Name) + return &workloads.Credential{ + Username: workloads.CredentialVar{ + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: secretName, + }, + Key: constant.AccountNameForSecret, }, - Key: constant.AccountNameForSecret, }, }, - }, - Password: workloads.CredentialVar{ - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: secretName, + Password: workloads.CredentialVar{ + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: secretName, + }, + Key: constant.AccountPasswdForSecret, }, - Key: constant.AccountPasswdForSecret, }, }, - }, + } + } + + // use first init account as the default credential + for index, sysAccount := range synthesizeComp.SystemAccounts { + if sysAccount.InitAccount { + return credential(synthesizeComp.SystemAccounts[index]), nil + } } - return credential, nil + return nil, nil } func (c *itsMembershipReconfigurationConvertor) convert(args ...any) (any, error) { diff --git a/pkg/controller/component/lorry_utils.go b/pkg/controller/component/lorry_utils.go index 74c9c776bce0..f0e05b8328d5 100644 --- a/pkg/controller/component/lorry_utils.go +++ b/pkg/controller/component/lorry_utils.go @@ -335,8 +335,6 @@ func buildEnv4DBAccount(synthesizeComp *SynthesizedComponent, clusterCompSpec *a if sysInitAccount != nil { secretName = constant.GenerateAccountSecretName(synthesizeComp.ClusterName, synthesizeComp.Name, sysInitAccount.Name) } - } else { - secretName = constant.GenerateDefaultConnCredential(synthesizeComp.ClusterName) } envs := []corev1.EnvVar{} if secretName == "" { diff --git a/pkg/controller/component/service_descriptor_utils.go b/pkg/controller/component/service_descriptor_utils.go index 80b7e14d50eb..ff6db397a739 100644 --- a/pkg/controller/component/service_descriptor_utils.go +++ b/pkg/controller/component/service_descriptor_utils.go @@ -228,7 +228,8 @@ func referencedVars4Legacy(ctx context.Context, cli client.Reader, namespace str } return namespace }(), - Name: constant.GenerateDefaultConnCredential(serviceRef.Cluster), + // 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 diff --git a/pkg/controller/component/synthesize_component.go b/pkg/controller/component/synthesize_component.go index 3387f6c91bc3..239c13587bb2 100644 --- a/pkg/controller/component/synthesize_component.go +++ b/pkg/controller/component/synthesize_component.go @@ -246,9 +246,6 @@ func buildSynthesizedComponent(reqCtx intctrlutil.RequestCtx, return nil, err } - // replace podSpec containers env default credential placeholder - replaceContainerPlaceholderTokens(synthesizeComp, GetEnvReplacementMapForConnCredential(synthesizeComp.ClusterName)) - return synthesizeComp, nil } @@ -682,23 +679,6 @@ func buildCompatibleHorizontalScalePolicy(compDef *appsv1alpha1.ComponentDefinit } } -// GetEnvReplacementMapForConnCredential gets the replacement map for connect credential -// TODO: deprecated, will be removed later. -func GetEnvReplacementMapForConnCredential(clusterName string) map[string]string { - return map[string]string{ - constant.KBConnCredentialPlaceHolder: constant.GenerateDefaultConnCredential(clusterName), - } -} - -func replaceContainerPlaceholderTokens(component *SynthesizedComponent, namedValuesMap map[string]string) { - // replace env[].valueFrom.secretKeyRef.name variables - for _, cc := range [][]corev1.Container{component.PodSpec.InitContainers, component.PodSpec.Containers} { - for _, c := range cc { - c.Env = ReplaceSecretEnvVars(namedValuesMap, c.Env) - } - } -} - // GetReplacementMapForBuiltInEnv gets the replacement map for KubeBlocks built-in environment variables. func GetReplacementMapForBuiltInEnv(clusterName, clusterUID, componentName string) map[string]string { cc := constant.GenerateClusterComponentName(clusterName, componentName) @@ -729,18 +709,6 @@ func ReplaceNamedVars(namedValuesMap map[string]string, targetVar string, limits return targetVar } -// ReplaceSecretEnvVars replaces the env secret value with namedValues and returns new envs -func ReplaceSecretEnvVars(namedValuesMap map[string]string, envs []corev1.EnvVar) []corev1.EnvVar { - newEnvs := make([]corev1.EnvVar, 0, len(envs)) - for _, e := range envs { - if e.ValueFrom != nil && e.ValueFrom.SecretKeyRef != nil { - e.ValueFrom.SecretKeyRef.Name = ReplaceNamedVars(namedValuesMap, e.ValueFrom.SecretKeyRef.Name, 1, false) - } - newEnvs = append(newEnvs, e) - } - return newEnvs -} - func GetConfigSpecByName(synthesizedComp *SynthesizedComponent, configSpec string) *appsv1alpha1.ComponentConfigSpec { for i := range synthesizedComp.ConfigTemplates { template := &synthesizedComp.ConfigTemplates[i] diff --git a/pkg/controller/configuration/builtin_env.go b/pkg/controller/configuration/builtin_env.go index c57cbba7f3ea..4cb8bfb85376 100644 --- a/pkg/controller/configuration/builtin_env.go +++ b/pkg/controller/configuration/builtin_env.go @@ -24,7 +24,6 @@ import ( "strings" "github.com/StudioSol/set" - "golang.org/x/exp/maps" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/kubectl/pkg/util/resource" @@ -232,8 +231,6 @@ func (w *envWrapper) doEnvReplace(replacedVars *set.LinkedHashSetString, oldValu builtInEnvMap = component.GetReplacementMapForBuiltInEnv(clusterName, clusterUID, componentName) ) - maps.Copy(builtInEnvMap, component.GetEnvReplacementMapForConnCredential(clusterName)) - kbInnerEnvReplaceFn := func(envName string, strToReplace string) string { return strings.ReplaceAll(strToReplace, envName, builtInEnvMap[envName]) } diff --git a/pkg/controller/configuration/config_utils.go b/pkg/controller/configuration/config_utils.go index 90ab426dcfdc..d58f8a4426fe 100644 --- a/pkg/controller/configuration/config_utils.go +++ b/pkg/controller/configuration/config_utils.go @@ -205,10 +205,8 @@ func getUsingVolumesByConfigSpecs(podSpec *corev1.PodSpec, configSpecs []appsv1a func buildConfigManagerParams(cli client.Client, ctx context.Context, cluster *appsv1alpha1.Cluster, comp *component.SynthesizedComponent, configSpecBuildParams []cfgcm.ConfigSpecMeta, volumeDirs []corev1.VolumeMount, podSpec *corev1.PodSpec) (*cfgcm.CfgManagerBuildParams, error) { cfgManagerParams := &cfgcm.CfgManagerBuildParams{ - ManagerName: constant.ConfigSidecarName, - ComponentName: comp.Name, - // TODO: (good-first-issue) the default cluster connection credential is deprecated - SecreteName: constant.GenerateDefaultConnCredential(cluster.Name), + ManagerName: constant.ConfigSidecarName, + ComponentName: comp.Name, Image: viper.GetString(constant.KBToolsImage), Volumes: volumeDirs, Cluster: cluster, diff --git a/pkg/controller/configuration/tool_image_builder_test.go b/pkg/controller/configuration/tool_image_builder_test.go index 7dce61457802..53b6075b2c27 100644 --- a/pkg/controller/configuration/tool_image_builder_test.go +++ b/pkg/controller/configuration/tool_image_builder_test.go @@ -61,7 +61,6 @@ var _ = Describe("ToolsImageBuilderTest", func() { cfgManagerParams := &cfgcm.CfgManagerBuildParams{ ManagerName: constant.ConfigSidecarName, ComponentName: clusterComponent.Name, - SecreteName: constant.GenerateDefaultConnCredential(clusterObj.Name), Image: viper.GetString(constant.KBToolsImage), Volumes: make([]corev1.VolumeMount, 0), Cluster: clusterObj, diff --git a/pkg/controller/factory/builder.go b/pkg/controller/factory/builder.go index 1c91381f35ea..0f482735fe4e 100644 --- a/pkg/controller/factory/builder.go +++ b/pkg/controller/factory/builder.go @@ -20,20 +20,14 @@ along with this program. If not, see . package factory import ( - "encoding/base64" - "encoding/hex" "encoding/json" - "fmt" "path/filepath" "strconv" - "strings" - "github.com/google/uuid" snapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumesnapshot/v1" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/rand" "k8s.io/klog/v2" appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" @@ -199,104 +193,6 @@ func BuildPersistentVolumeClaimLabels(component *component.SynthesizedComponent, } } -func randomString(length int) string { - return rand.String(length) -} - -func strongRandomString(length int) string { - str, _ := common.GeneratePassword(length, 3, 3, false, "") - return str -} - -func BuildConnCredential(clusterDefinition *appsv1alpha1.ClusterDefinition, cluster *appsv1alpha1.Cluster, - synthesizedComp *component.SynthesizedComponent) *corev1.Secret { - wellKnownLabels := constant.GetKBWellKnownLabels(clusterDefinition.Name, cluster.Name, "") - delete(wellKnownLabels, constant.KBAppComponentLabelKey) - credentialBuilder := builder.NewSecretBuilder(cluster.Namespace, constant.GenerateDefaultConnCredential(cluster.Name)). - AddLabelsInMap(wellKnownLabels). - SetStringData(clusterDefinition.Spec.ConnectionCredential) - connCredential := credentialBuilder.GetObject() - - if len(connCredential.StringData) == 0 { - return connCredential - } - - replaceVarObjects := func(k, v *string, i int, origValue string, varObjectsMap map[string]string) { - toReplace := origValue - for j, r := range varObjectsMap { - replaced := strings.ReplaceAll(toReplace, j, r) - if replaced == toReplace { - continue - } - toReplace = replaced - // replace key - if i == 0 { - delete(connCredential.StringData, origValue) - *k = replaced - } else { - *v = replaced - } - } - } - - // REVIEW: perhaps handles value replacement at `func mergeComponents` - replaceData := func(varObjectsMap map[string]string) { - copyStringData := connCredential.DeepCopy().StringData - for k, v := range copyStringData { - for i, vv := range []string{k, v} { - if !strings.Contains(vv, "$(") { - continue - } - replaceVarObjects(&k, &v, i, vv, varObjectsMap) - } - connCredential.StringData[k] = v - } - } - - // TODO: do JIT value generation for lower CPU resources - // 1st pass replace variables - uuidVal := uuid.New() - uuidBytes := uuidVal[:] - uuidStr := uuidVal.String() - uuidB64 := base64.RawStdEncoding.EncodeToString(uuidBytes) - uuidStrB64 := base64.RawStdEncoding.EncodeToString([]byte(strings.ReplaceAll(uuidStr, "-", ""))) - uuidHex := hex.EncodeToString(uuidBytes) - randomPassword := randomString(8) - strongRandomPasswd := strongRandomString(16) - restorePassword := GetRestorePassword(synthesizedComp) - // check if a connection password is specified during recovery. - // if exists, replace the random password - if restorePassword != "" { - randomPassword = restorePassword - strongRandomPasswd = restorePassword - } - m := map[string]string{ - "$(RANDOM_PASSWD)": randomPassword, - "$(STRONG_RANDOM_PASSWD)": strongRandomPasswd, - "$(UUID)": uuidStr, - "$(UUID_B64)": uuidB64, - "$(UUID_STR_B64)": uuidStrB64, - "$(UUID_HEX)": uuidHex, - "$(SVC_FQDN)": constant.GenerateDefaultComponentServiceName(cluster.Name, synthesizedComp.Name), - constant.EnvPlaceHolder(constant.KBEnvClusterCompName): constant.GenerateClusterComponentName(cluster.Name, synthesizedComp.Name), - "$(HEADLESS_SVC_FQDN)": constant.GenerateDefaultComponentHeadlessServiceName(cluster.Name, synthesizedComp.Name), - } - if len(synthesizedComp.ComponentServices) > 0 { - for _, p := range synthesizedComp.ComponentServices[0].Spec.Ports { - m[fmt.Sprintf("$(SVC_PORT_%s)", p.Name)] = strconv.Itoa(int(p.Port)) - } - } - replaceData(m) - - // 2nd pass replace $(CONN_CREDENTIAL) variables - m = map[string]string{} - for k, v := range connCredential.StringData { - m[fmt.Sprintf("$(CONN_CREDENTIAL).%s", k)] = v - } - replaceData(m) - return connCredential -} - // GetRestorePassword gets restore password if exists during recovery. func GetRestorePassword(synthesizedComp *component.SynthesizedComponent) string { valueString := synthesizedComp.Annotations[constant.RestoreFromBackupAnnotationKey] diff --git a/pkg/controller/factory/builder_test.go b/pkg/controller/factory/builder_test.go index 25cb431e59e1..059a2c34918c 100644 --- a/pkg/controller/factory/builder_test.go +++ b/pkg/controller/factory/builder_test.go @@ -153,23 +153,6 @@ var _ = Describe("builder", func() { Expect(pvc.Spec.StorageClassName).Should(Equal(synthesizedComponent.VolumeClaimTemplates[0].Spec.StorageClassName)) }) - It("builds Conn. Credential during restoring from backup", func() { - originalPassword := "test-passw0rd" - encryptionKey := "encryptionKey" - viper.Set(constant.CfgKeyDPEncryptionKey, encryptionKey) - var ( - clusterDefObj = testapps.NewClusterDefFactoryWithConnCredential("conn-cred", mysqlCompDefName).GetObject() - clusterDef, cluster, synthesizedComponent = newClusterObjs(clusterDefObj) - ) - e := intctrlutil.NewEncryptor(encryptionKey) - ciphertext, _ := e.Encrypt([]byte(originalPassword)) - cluster.Annotations[constant.RestoreFromBackupAnnotationKey] = fmt.Sprintf(`{"%s":{"%s":"%s"}}`, - synthesizedComponent.Name, constant.ConnectionPassword, ciphertext) - credential := BuildConnCredential(clusterDef, cluster, synthesizedComponent) - Expect(credential).ShouldNot(BeNil()) - Expect(credential.StringData["RANDOM_PASSWD"]).Should(Equal(originalPassword)) - }) - It("builds InstanceSet correctly", func() { clusterDef, cluster, synthesizedComponent := newClusterObjs(nil) @@ -278,7 +261,6 @@ var _ = Describe("builder", func() { _, cluster, synthesizedComponent := newClusterObjs(nil) sidecarRenderedParam := &cfgcm.CfgManagerBuildParams{ ManagerName: "cfgmgr", - SecreteName: "test-secret", ComponentName: synthesizedComponent.Name, Image: constant.KBToolsImage, Args: []string{}, @@ -296,7 +278,6 @@ var _ = Describe("builder", func() { _, cluster, _ := newClusterObjs(nil) sidecarRenderedParam := &cfgcm.CfgManagerBuildParams{ ManagerName: "cfgmgr", - SecreteName: "test-secret", Image: constant.KBToolsImage, ShareProcessNamespace: true, Args: []string{}, @@ -325,7 +306,6 @@ var _ = Describe("builder", func() { _, cluster, _ := newClusterObjs(nil) cfgManagerParams := &cfgcm.CfgManagerBuildParams{ ManagerName: constant.ConfigSidecarName, - SecreteName: constant.GenerateDefaultConnCredential(cluster.Name), Image: viper.GetString(constant.KBToolsImage), Cluster: cluster, ConfigLazyRenderedVolumes: make(map[string]corev1.VolumeMount), diff --git a/pkg/testutil/apps/clusterdef_factory.go b/pkg/testutil/apps/clusterdef_factory.go index da4e17e71eac..112854422da5 100644 --- a/pkg/testutil/apps/clusterdef_factory.go +++ b/pkg/testutil/apps/clusterdef_factory.go @@ -38,22 +38,6 @@ type MockClusterDefFactory struct { BaseFactory[appsv1alpha1.ClusterDefinition, *appsv1alpha1.ClusterDefinition, MockClusterDefFactory] } -func getDefaultConnectionCredential() map[string]string { - return map[string]string{ - "username": "root", - "SVC_FQDN": "$(SVC_FQDN)", - "HEADLESS_SVC_FQDN": "$(HEADLESS_SVC_FQDN)", - "RANDOM_PASSWD": "$(RANDOM_PASSWD)", - "STRONG_RANDOM_PASSWD": "$(STRONG_RANDOM_PASSWD)", - "tcpEndpoint": "tcp:$(SVC_FQDN):$(SVC_PORT_mysql)", - "paxosEndpoint": "paxos:$(SVC_FQDN):$(SVC_PORT_paxos)", - "UUID": "$(UUID)", - "UUID_B64": "$(UUID_B64)", - "UUID_STR_B64": "$(UUID_STR_B64)", - "UUID_HEX": "$(UUID_HEX)", - } -} - func NewClusterDefFactory(name string) *MockClusterDefFactory { f := &MockClusterDefFactory{} f.Init("", name, @@ -62,14 +46,6 @@ func NewClusterDefFactory(name string) *MockClusterDefFactory { ComponentDefs: []appsv1alpha1.ClusterComponentDefinition{}, }, }, f) - f.SetConnectionCredential(getDefaultConnectionCredential()) - return f -} - -func NewClusterDefFactoryWithConnCredential(name, compDefName string) *MockClusterDefFactory { - f := NewClusterDefFactory(name) - f.AddComponentDef(StatefulMySQLComponent, compDefName) - f.SetConnectionCredential(getDefaultConnectionCredential()) return f } @@ -116,11 +92,6 @@ func (factory *MockClusterDefFactory) AddHorizontalScalePolicy(policy appsv1alph return factory } -func (factory *MockClusterDefFactory) SetConnectionCredential(connectionCredential map[string]string) *MockClusterDefFactory { - factory.Get().Spec.ConnectionCredential = connectionCredential - return factory -} - func (factory *MockClusterDefFactory) getLastCompDef() *appsv1alpha1.ClusterComponentDefinition { l := len(factory.Get().Spec.ComponentDefs) if l == 0 { From ab818e53db9b836c9bd69c1fac939b9ec0d89c31 Mon Sep 17 00:00:00 2001 From: wanglong <46259301+gnolong@users.noreply.github.com> Date: Tue, 6 Aug 2024 11:16:15 +0800 Subject: [PATCH 38/45] feat: support filtering backup target pods by the alternative label selector (#7831) --- .../v1alpha1/backuppolicytemplate_types.go | 6 + .../v1alpha1/backuppolicy_types.go | 6 + .../v1alpha1/zz_generated.deepcopy.go | 5 + ...s.kubeblocks.io_backuppolicytemplates.yaml | 104 ++++++++++ ...otection.kubeblocks.io_backuppolicies.yaml | 185 ++++++++++++++++++ .../dataprotection.kubeblocks.io_backups.yaml | 184 +++++++++++++++++ ...dataprotection.kubeblocks.io_restores.yaml | 47 +++++ .../apps/transformer_cluster_backup_policy.go | 28 ++- .../dataprotection/backup_controller_test.go | 73 +++++++ controllers/dataprotection/utils.go | 89 +++++---- ...s.kubeblocks.io_backuppolicytemplates.yaml | 104 ++++++++++ ...otection.kubeblocks.io_backuppolicies.yaml | 185 ++++++++++++++++++ .../dataprotection.kubeblocks.io_backups.yaml | 184 +++++++++++++++++ ...dataprotection.kubeblocks.io_restores.yaml | 47 +++++ docs/developer_docs/api-reference/backup.md | 15 ++ docs/developer_docs/api-reference/cluster.md | 13 ++ pkg/dataprotection/restore/manager.go | 2 +- pkg/dataprotection/utils/utils.go | 16 +- 18 files changed, 1240 insertions(+), 53 deletions(-) diff --git a/apis/apps/v1alpha1/backuppolicytemplate_types.go b/apis/apps/v1alpha1/backuppolicytemplate_types.go index acd19f3f1051..200e9fb5428a 100644 --- a/apis/apps/v1alpha1/backuppolicytemplate_types.go +++ b/apis/apps/v1alpha1/backuppolicytemplate_types.go @@ -210,6 +210,12 @@ type TargetInstance struct { // the `strategy` field below. Role string `json:"role"` + // Specifies the fallback role to select one replica for backup, this only takes effect when the + // `strategy` field below is set to `Any`. + // + // +optional + FallbackRole string `json:"fallbackRole,omitempty"` + // If `backupPolicy.componentDefs` is set, this field is required to specify the system account name. // This account must match one listed in `componentDefinition.spec.systemAccounts[*].name`. // The corresponding secret created by this account is used to connect to the database. diff --git a/apis/dataprotection/v1alpha1/backuppolicy_types.go b/apis/dataprotection/v1alpha1/backuppolicy_types.go index 92527c5c17e0..31fe87f49e77 100644 --- a/apis/dataprotection/v1alpha1/backuppolicy_types.go +++ b/apis/dataprotection/v1alpha1/backuppolicy_types.go @@ -111,6 +111,12 @@ type PodSelector struct { // labelsSelector is the label selector to filter the target pods. *metav1.LabelSelector `json:",inline"` + // fallbackLabelSelector is used to filter available pods when the labelSelector fails. + // This only takes effect when the `strategy` field below is set to `Any`. + // + // +optional + FallbackLabelSelector *metav1.LabelSelector `json:"fallbackLabelSelector,omitempty"` + // Specifies the strategy to select the target pod when multiple pods are selected. // Valid values are: // diff --git a/apis/dataprotection/v1alpha1/zz_generated.deepcopy.go b/apis/dataprotection/v1alpha1/zz_generated.deepcopy.go index 0279a22601bf..0fb63af2b215 100644 --- a/apis/dataprotection/v1alpha1/zz_generated.deepcopy.go +++ b/apis/dataprotection/v1alpha1/zz_generated.deepcopy.go @@ -1162,6 +1162,11 @@ func (in *PodSelector) DeepCopyInto(out *PodSelector) { *out = new(metav1.LabelSelector) (*in).DeepCopyInto(*out) } + if in.FallbackLabelSelector != nil { + in, out := &in.FallbackLabelSelector, &out.FallbackLabelSelector + *out = new(metav1.LabelSelector) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodSelector. diff --git a/config/crd/bases/apps.kubeblocks.io_backuppolicytemplates.yaml b/config/crd/bases/apps.kubeblocks.io_backuppolicytemplates.yaml index 4f0ae6e1b580..d9fee4b254ad 100644 --- a/config/crd/bases/apps.kubeblocks.io_backuppolicytemplates.yaml +++ b/config/crd/bases/apps.kubeblocks.io_backuppolicytemplates.yaml @@ -416,6 +416,11 @@ spec: If not specified, the default key "username" is used. type: string type: object + fallbackRole: + description: |- + Specifies the fallback role to select one replica for backup, this only takes effect when the + `strategy` field below is set to `Any`. + type: string name: description: |- Specifies a mandatory and unique identifier for each target when using the "targets" field. @@ -425,6 +430,53 @@ spec: description: Used to find the target pod. The volumes of the target pod will be backed up. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list of + label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are @@ -687,6 +739,53 @@ spec: description: Used to find the target pod. The volumes of the target pod will be backed up. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are @@ -916,6 +1015,11 @@ spec: If not specified, the default key "username" is used. type: string type: object + fallbackRole: + description: |- + Specifies the fallback role to select one replica for backup, this only takes effect when the + `strategy` field below is set to `Any`. + type: string role: description: |- Specifies the role to select one or more replicas for backup. diff --git a/config/crd/bases/dataprotection.kubeblocks.io_backuppolicies.yaml b/config/crd/bases/dataprotection.kubeblocks.io_backuppolicies.yaml index ee2934a16f3e..d7fa06edd4c5 100644 --- a/config/crd/bases/dataprotection.kubeblocks.io_backuppolicies.yaml +++ b/config/crd/bases/dataprotection.kubeblocks.io_backuppolicies.yaml @@ -307,6 +307,52 @@ spec: description: Used to find the target pod. The volumes of the target pod will be backed up. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. @@ -538,6 +584,53 @@ spec: description: Used to find the target pod. The volumes of the target pod will be backed up. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. @@ -774,6 +867,52 @@ spec: description: Used to find the target pod. The volumes of the target pod will be backed up. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. @@ -948,6 +1087,52 @@ spec: description: Used to find the target pod. The volumes of the target pod will be backed up. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. diff --git a/config/crd/bases/dataprotection.kubeblocks.io_backups.yaml b/config/crd/bases/dataprotection.kubeblocks.io_backups.yaml index 2e140a05cc83..76b17beecad8 100644 --- a/config/crd/bases/dataprotection.kubeblocks.io_backups.yaml +++ b/config/crd/bases/dataprotection.kubeblocks.io_backups.yaml @@ -501,6 +501,52 @@ spec: description: Used to find the target pod. The volumes of the target pod will be backed up. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. @@ -731,6 +777,52 @@ spec: description: Used to find the target pod. The volumes of the target pod will be backed up. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. @@ -1013,6 +1105,52 @@ spec: description: Used to find the target pod. The volumes of the target pod will be backed up. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. @@ -1189,6 +1327,52 @@ spec: description: Used to find the target pod. The volumes of the target pod will be backed up. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. diff --git a/config/crd/bases/dataprotection.kubeblocks.io_restores.yaml b/config/crd/bases/dataprotection.kubeblocks.io_restores.yaml index defd85fe5bd8..bcd3ca3b0af6 100644 --- a/config/crd/bases/dataprotection.kubeblocks.io_restores.yaml +++ b/config/crd/bases/dataprotection.kubeblocks.io_restores.yaml @@ -2042,6 +2042,53 @@ spec: Selects one of the pods, identified by labels, to build the job spec. This includes mounting required volumes and injecting built-in environment variables of the selected pod. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. diff --git a/controllers/apps/transformer_cluster_backup_policy.go b/controllers/apps/transformer_cluster_backup_policy.go index fff26d0d6127..49ad32b562ae 100644 --- a/controllers/apps/transformer_cluster_backup_policy.go +++ b/controllers/apps/transformer_cluster_backup_policy.go @@ -362,7 +362,7 @@ func (r *clusterBackupPolicyTransformer) syncBackupPolicy(comp componentItem, ba r.syncBackupPolicyTargetSpec(backupPolicy, comp) } -func (r *clusterBackupPolicyTransformer) syncRoleLabelSelector(comp componentItem, target *dpv1alpha1.BackupTarget, role string) { +func (r *clusterBackupPolicyTransformer) syncRoleLabelSelector(comp componentItem, target *dpv1alpha1.BackupTarget, role, alternateRole string) { if len(role) == 0 || target == nil { return } @@ -372,8 +372,17 @@ func (r *clusterBackupPolicyTransformer) syncRoleLabelSelector(comp componentIte } if r.getCompReplicas(comp) == 1 { delete(podSelector.LabelSelector.MatchLabels, constant.RoleLabelKey) - } else if podSelector.LabelSelector.MatchLabels[constant.RoleLabelKey] == "" { + if podSelector.FallbackLabelSelector != nil && podSelector.FallbackLabelSelector.MatchLabels != nil { + delete(podSelector.FallbackLabelSelector.MatchLabels, constant.RoleLabelKey) + } + } else { podSelector.LabelSelector.MatchLabels[constant.RoleLabelKey] = role + if len(alternateRole) > 0 { + if podSelector.FallbackLabelSelector == nil || podSelector.FallbackLabelSelector.MatchLabels == nil { + podSelector.FallbackLabelSelector = &metav1.LabelSelector{MatchLabels: map[string]string{}} + } + podSelector.FallbackLabelSelector.MatchLabels[constant.RoleLabelKey] = alternateRole + } } } @@ -489,7 +498,7 @@ func (r *clusterBackupPolicyTransformer) buildBackupTarget( ) *dpv1alpha1.BackupTarget { if oldTarget != nil { // if the target already exists, only sync the role by component replicas automatically. - r.syncRoleLabelSelector(comp, oldTarget, targetTpl.Role) + r.syncRoleLabelSelector(comp, oldTarget, targetTpl.Role, targetTpl.FallbackRole) return oldTarget } clusterName := r.OrigCluster.Name @@ -500,12 +509,17 @@ func (r *clusterBackupPolicyTransformer) buildBackupTarget( PodSelector: &dpv1alpha1.PodSelector{ Strategy: targetTpl.Strategy, LabelSelector: &metav1.LabelSelector{ - MatchLabels: r.buildTargetPodLabels(targetTpl, comp), + MatchLabels: r.buildTargetPodLabels(targetTpl.Role, comp), }, }, // dataprotection will use its dedicated service account if this field is empty. ServiceAccountName: "", } + if len(targetTpl.Role) != 0 && len(targetTpl.FallbackRole) != 0 { + target.PodSelector.FallbackLabelSelector = &metav1.LabelSelector{ + MatchLabels: r.buildTargetPodLabels(targetTpl.FallbackRole, comp), + } + } if comp.isSharding { target.Name = comp.fullComponentName } @@ -724,16 +738,16 @@ func (r *clusterBackupPolicyTransformer) compDefNameFromPolicy(policy *dpv1alpha // buildTargetPodLabels builds the target labels for the backup policy that will be // used to select the target pod. -func (r *clusterBackupPolicyTransformer) buildTargetPodLabels(targetTpl appsv1alpha1.TargetInstance, comp componentItem) map[string]string { +func (r *clusterBackupPolicyTransformer) buildTargetPodLabels(role string, comp componentItem) map[string]string { labels := map[string]string{ constant.AppInstanceLabelKey: r.OrigCluster.Name, constant.AppManagedByLabelKey: constant.AppName, constant.KBAppComponentLabelKey: comp.fullComponentName, } // append label to filter specific role of the component. - if len(targetTpl.Role) > 0 && r.getCompReplicas(comp) > 1 { + if len(role) > 0 && r.getCompReplicas(comp) > 1 { // the role only works when the component has multiple replicas. - labels[constant.RoleLabelKey] = targetTpl.Role + labels[constant.RoleLabelKey] = role } if comp.isSharding { labels[constant.KBAppShardingNameLabelKey] = comp.componentName diff --git a/controllers/dataprotection/backup_controller_test.go b/controllers/dataprotection/backup_controller_test.go index 3ff97117a171..9084cc590d59 100644 --- a/controllers/dataprotection/backup_controller_test.go +++ b/controllers/dataprotection/backup_controller_test.go @@ -20,6 +20,7 @@ along with this program. If not, see . package dataprotection import ( + "context" "fmt" "slices" "time" @@ -362,6 +363,78 @@ var _ = Describe("Backup Controller test", func() { })).Should(Succeed()) }) + It("create an backup using fallbackLabelSelector", func() { + podFactory := func(name string) *testapps.MockPodFactory { + return testapps.NewPodFactory(testCtx.DefaultNamespace, name). + AddAppInstanceLabel(testdp.ClusterName). + AddAppComponentLabel(testdp.ComponentName). + AddContainer(corev1.Container{Name: testdp.ContainerName, Image: testapps.ApeCloudMySQLImage}) + } + podName := "fallback" + testdp.ClusterName + "-" + testdp.ComponentName + By("mock a primary pod that is available ") + pod0 := podFactory(podName + "-0"). + AddRoleLabel("primary"). + Create(&testCtx).GetObject() + Expect(testapps.ChangeObjStatus(&testCtx, pod0, func() { + pod0.Status.Phase = corev1.PodRunning + testk8s.MockPodAvailable(pod0, metav1.Now()) + })).Should(Succeed()) + By("mock a secondary pod that is unavailable") + pod1 := podFactory(podName + "-1"). + AddRoleLabel("secondary"). + Create(&testCtx).GetObject() + Expect(testapps.ChangeObjStatus(&testCtx, pod1, func() { + pod1.Status.Phase = corev1.PodFailed + testk8s.MockPodIsFailed(context.Background(), testCtx, pod1) + })).Should(Succeed()) + + By("Set backupPolicy's target with fallbackLabelSelector") + Expect(testapps.ChangeObj(&testCtx, backupPolicy, func(bp *dpv1alpha1.BackupPolicy) { + podSelector := &dpv1alpha1.PodSelector{ + LabelSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + constant.AppInstanceLabelKey: testdp.ClusterName, + constant.KBAppComponentLabelKey: testdp.ComponentName, + constant.RoleLabelKey: "secondary", + }, + }, + FallbackLabelSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + constant.AppInstanceLabelKey: testdp.ClusterName, + constant.KBAppComponentLabelKey: testdp.ComponentName, + constant.RoleLabelKey: "primary", + }, + }, + Strategy: dpv1alpha1.PodSelectionStrategyAny, + } + backupPolicy.Spec.Target = &dpv1alpha1.BackupTarget{ + Name: testdp.ComponentName + "-0", PodSelector: podSelector, + } + })).Should(Succeed()) + + By("check targets pod") + target := backupPolicy.Spec.Target + reqCtx := intctrlutil.RequestCtx{Ctx: ctx} + targetPods, err := GetTargetPods(reqCtx, k8sClient, nil, backupPolicy, target, dpv1alpha1.BackupTypeFull) + Expect(err).ShouldNot(HaveOccurred()) + Expect(targetPods).Should(HaveLen(1)) + Expect(targetPods[0].Name).Should(Equal(pod0.Name)) + + By("create a backup") + backup := testdp.NewFakeBackup(&testCtx, nil) + getJobKey := func(targetName string) client.ObjectKey { + return client.ObjectKey{ + Name: dpbackup.GenerateBackupJobName(backup, fmt.Sprintf("%s-%s-0", dpbackup.BackupDataJobNamePrefix, targetName)), + Namespace: backup.Namespace, + } + } + By("mock backup jobs to completed and backup should be completed") + testdp.PatchK8sJobStatus(&testCtx, getJobKey(target.Name), batchv1.JobComplete) + Eventually(testapps.CheckObj(&testCtx, client.ObjectKeyFromObject(backup), func(g Gomega, fetched *dpv1alpha1.Backup) { + g.Expect(fetched.Status.Phase).To(Equal(dpv1alpha1.BackupPhaseCompleted)) + })).Should(Succeed()) + }) + Context("creates a backup with encryption", func() { const ( encryptionKeySecretName = "backup-encryption" diff --git a/controllers/dataprotection/utils.go b/controllers/dataprotection/utils.go index 061c271f4027..f31462452a25 100644 --- a/controllers/dataprotection/utils.go +++ b/controllers/dataprotection/utils.go @@ -24,7 +24,6 @@ import ( "encoding/json" "fmt" "reflect" - "sort" "strings" "sync" @@ -149,59 +148,63 @@ func GetTargetPods(reqCtx intctrlutil.RequestCtx, if !existPodSelector(selector) { return nil, nil } - labelSelector, err := metav1.LabelSelectorAsSelector(selector.LabelSelector) - if err != nil { - return nil, err - } - pods := &corev1.PodList{} - if err = cli.List(reqCtx.Ctx, pods, - client.InNamespace(reqCtx.Req.Namespace), - client.MatchingLabelsSelector{Selector: labelSelector}); err != nil { - return nil, err - } - if len(pods.Items) == 0 { - return nil, fmt.Errorf("failed to find target pods by backup policy %s/%s", - backupPolicy.Namespace, backupPolicy.Name) - } - sort.Sort(intctrlutil.ByPodName(pods.Items)) - var targetPods []*corev1.Pod - if len(selectedPodNames) == 0 || backupType == dpv1alpha1.BackupTypeContinuous { - switch selector.Strategy { + filterTargetPods := func(strategy dpv1alpha1.PodSelectionStrategy, + labelSelector *metav1.LabelSelector) ([]*corev1.Pod, error) { + var targetPods []*corev1.Pod + pods, err := dputils.GetPodListByLabelSelector(reqCtx, cli, labelSelector) + if err != nil { + return nil, err + } + switch strategy { case dpv1alpha1.PodSelectionStrategyAny: - // always selecting the first pod - pod := dputils.GetFirstIndexRunningPod(pods) + var pod *corev1.Pod + if len(selectedPodNames) == 0 || backupType == dpv1alpha1.BackupTypeContinuous { + pod = dputils.GetFirstIndexRunningPod(pods) + } else { + // if already selected target pods and backupType is not Continuous, we should re-use them. + pod = dputils.GetPodByName(pods, selectedPodNames[0]) + } if pod != nil { targetPods = append(targetPods, pod) } case dpv1alpha1.PodSelectionStrategyAll: + if len(selectedPodNames) == 0 || backupType == dpv1alpha1.BackupTypeContinuous { + for i := range pods.Items { + targetPods = append(targetPods, &pods.Items[i]) + } + return targetPods, nil + } + // if already selected target pods and backupType is not Continuous, we should re-use them. + if len(pods.Items) == 0 { + return nil, fmt.Errorf("failed to find target pods by backup policy %s/%s", + backupPolicy.Namespace, backupPolicy.Name) + } + podMap := map[string]*corev1.Pod{} for i := range pods.Items { - targetPods = append(targetPods, &pods.Items[i]) + podMap[pods.Items[i].Name] = &pods.Items[i] + } + for _, podName := range selectedPodNames { + pod, ok := podMap[podName] + if !ok { + return nil, intctrlutil.NewFatalError(fmt.Sprintf(`can not found the target pod "%s"`, podName)) + } + targetPods = append(targetPods, pod) } } return targetPods, nil } - // if already selected target pods and backupType is not Continuous, we should re-use them. - switch selector.Strategy { - case dpv1alpha1.PodSelectionStrategyAny: - for _, pod := range pods.Items { - if pod.Name == selectedPodNames[0] { - targetPods = append(targetPods, &pod) - break - } - } - case dpv1alpha1.PodSelectionStrategyAll: - podMap := map[string]corev1.Pod{} - for i := range pods.Items { - podMap[pods.Items[i].Name] = pods.Items[i] - } - for _, podName := range selectedPodNames { - pod, ok := podMap[podName] - if !ok { - return nil, intctrlutil.NewFatalError(fmt.Sprintf(`can not found the target pod "%s"`, podName)) - } - targetPods = append(targetPods, &pod) - } + + targetPods, err := filterTargetPods(selector.Strategy, selector.LabelSelector) + if err != nil { + return nil, err + } + if selector.Strategy == dpv1alpha1.PodSelectionStrategyAll || targetPods != nil || + selector.FallbackLabelSelector == nil { + return targetPods, nil + } + if targetPods, err = filterTargetPods(selector.Strategy, selector.FallbackLabelSelector); err != nil { + return nil, err } return targetPods, nil } diff --git a/deploy/helm/crds/apps.kubeblocks.io_backuppolicytemplates.yaml b/deploy/helm/crds/apps.kubeblocks.io_backuppolicytemplates.yaml index 4f0ae6e1b580..d9fee4b254ad 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_backuppolicytemplates.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_backuppolicytemplates.yaml @@ -416,6 +416,11 @@ spec: If not specified, the default key "username" is used. type: string type: object + fallbackRole: + description: |- + Specifies the fallback role to select one replica for backup, this only takes effect when the + `strategy` field below is set to `Any`. + type: string name: description: |- Specifies a mandatory and unique identifier for each target when using the "targets" field. @@ -425,6 +430,53 @@ spec: description: Used to find the target pod. The volumes of the target pod will be backed up. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list of + label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are @@ -687,6 +739,53 @@ spec: description: Used to find the target pod. The volumes of the target pod will be backed up. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are @@ -916,6 +1015,11 @@ spec: If not specified, the default key "username" is used. type: string type: object + fallbackRole: + description: |- + Specifies the fallback role to select one replica for backup, this only takes effect when the + `strategy` field below is set to `Any`. + type: string role: description: |- Specifies the role to select one or more replicas for backup. diff --git a/deploy/helm/crds/dataprotection.kubeblocks.io_backuppolicies.yaml b/deploy/helm/crds/dataprotection.kubeblocks.io_backuppolicies.yaml index ee2934a16f3e..d7fa06edd4c5 100644 --- a/deploy/helm/crds/dataprotection.kubeblocks.io_backuppolicies.yaml +++ b/deploy/helm/crds/dataprotection.kubeblocks.io_backuppolicies.yaml @@ -307,6 +307,52 @@ spec: description: Used to find the target pod. The volumes of the target pod will be backed up. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. @@ -538,6 +584,53 @@ spec: description: Used to find the target pod. The volumes of the target pod will be backed up. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. @@ -774,6 +867,52 @@ spec: description: Used to find the target pod. The volumes of the target pod will be backed up. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. @@ -948,6 +1087,52 @@ spec: description: Used to find the target pod. The volumes of the target pod will be backed up. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. diff --git a/deploy/helm/crds/dataprotection.kubeblocks.io_backups.yaml b/deploy/helm/crds/dataprotection.kubeblocks.io_backups.yaml index 2e140a05cc83..76b17beecad8 100644 --- a/deploy/helm/crds/dataprotection.kubeblocks.io_backups.yaml +++ b/deploy/helm/crds/dataprotection.kubeblocks.io_backups.yaml @@ -501,6 +501,52 @@ spec: description: Used to find the target pod. The volumes of the target pod will be backed up. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. @@ -731,6 +777,52 @@ spec: description: Used to find the target pod. The volumes of the target pod will be backed up. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. @@ -1013,6 +1105,52 @@ spec: description: Used to find the target pod. The volumes of the target pod will be backed up. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. @@ -1189,6 +1327,52 @@ spec: description: Used to find the target pod. The volumes of the target pod will be backed up. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. diff --git a/deploy/helm/crds/dataprotection.kubeblocks.io_restores.yaml b/deploy/helm/crds/dataprotection.kubeblocks.io_restores.yaml index defd85fe5bd8..bcd3ca3b0af6 100644 --- a/deploy/helm/crds/dataprotection.kubeblocks.io_restores.yaml +++ b/deploy/helm/crds/dataprotection.kubeblocks.io_restores.yaml @@ -2042,6 +2042,53 @@ spec: Selects one of the pods, identified by labels, to build the job spec. This includes mounting required volumes and injecting built-in environment variables of the selected pod. properties: + fallbackLabelSelector: + description: |- + fallbackLabelSelector is used to filter available pods when the labelSelector fails. + This only takes effect when the `strategy` field below is set to `Any`. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. diff --git a/docs/developer_docs/api-reference/backup.md b/docs/developer_docs/api-reference/backup.md index 3997e475cf8e..6ddc639bcb55 100644 --- a/docs/developer_docs/api-reference/backup.md +++ b/docs/developer_docs/api-reference/backup.md @@ -3900,6 +3900,21 @@ Kubernetes meta/v1.LabelSelector +fallbackLabelSelector
    + +
    +Kubernetes meta/v1.LabelSelector + + + + +(Optional) +

    fallbackLabelSelector is used to filter available pods when the labelSelector fails. +This only takes effect when the strategy field below is set to Any.

    + + + + strategy
    diff --git a/docs/developer_docs/api-reference/cluster.md b/docs/developer_docs/api-reference/cluster.md index c228091ece49..8f12caf9e90f 100644 --- a/docs/developer_docs/api-reference/cluster.md +++ b/docs/developer_docs/api-reference/cluster.md @@ -18879,6 +18879,19 @@ the strategy field below.
  • +fallbackRole
    + +string + + + +(Optional) +

    Specifies the fallback role to select one replica for backup, this only takes effect when the +strategy field below is set to Any.

    + + + + account
    string diff --git a/pkg/dataprotection/restore/manager.go b/pkg/dataprotection/restore/manager.go index 931c4722f1fa..c1c9aa58879c 100644 --- a/pkg/dataprotection/restore/manager.go +++ b/pkg/dataprotection/restore/manager.go @@ -537,7 +537,7 @@ func (r *RestoreManager) BuildPostReadyActionJobs(reqCtx intctrlutil.RequestCtx, } actionSpec := backupSet.ActionSet.Spec.Restore.PostReady[step] getTargetPodList := func(labelSelector metav1.LabelSelector, msgKey string) (*corev1.PodList, error) { - targetPodList, err := utils.GetPodListByLabelSelector(reqCtx, cli, labelSelector) + targetPodList, err := utils.GetPodListByLabelSelector(reqCtx, cli, &labelSelector) if err != nil { return nil, err } diff --git a/pkg/dataprotection/utils/utils.go b/pkg/dataprotection/utils/utils.go index 667827eb378f..2bbabdc3ba26 100644 --- a/pkg/dataprotection/utils/utils.go +++ b/pkg/dataprotection/utils/utils.go @@ -144,8 +144,8 @@ func GetBackupMethodByName(name string, backupPolicy *dpv1alpha1.BackupPolicy) * func GetPodListByLabelSelector(reqCtx intctrlutil.RequestCtx, cli client.Client, - labelSelector metav1.LabelSelector) (*corev1.PodList, error) { - selector, err := metav1.LabelSelectorAsSelector(&labelSelector) + labelSelector *metav1.LabelSelector) (*corev1.PodList, error) { + selector, err := metav1.LabelSelectorAsSelector(labelSelector) if err != nil { return nil, err } @@ -289,6 +289,18 @@ func GetFirstIndexRunningPod(podList *corev1.PodList) *corev1.Pod { return nil } +func GetPodByName(podList *corev1.PodList, name string) *corev1.Pod { + if podList == nil { + return nil + } + for i, v := range podList.Items { + if v.Name == name { + return &podList.Items[i] + } + } + return nil +} + // GetKubeVersion get the version of Kubernetes and return the gitVersion func GetKubeVersion() (string, error) { verInfo := viper.Get(constant.CfgKeyServerInfo) From 7e76254c5eec9be15f38560acf3c00542b7eac9e Mon Sep 17 00:00:00 2001 From: wangyelei Date: Tue, 6 Aug 2024 11:23:19 +0800 Subject: [PATCH 39/45] chore: fix cluster is always running when existing running opsRequest (#7929) --- controllers/apps/opsrequest_controller.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/apps/opsrequest_controller.go b/controllers/apps/opsrequest_controller.go index 7a548d023470..1f95a8d6adc8 100644 --- a/controllers/apps/opsrequest_controller.go +++ b/controllers/apps/opsrequest_controller.go @@ -78,8 +78,8 @@ func (r *OpsRequestReconciler) Reconcile(ctx context.Context, req ctrl.Request) opsCtrlHandler := &opsControllerHandler{} return opsCtrlHandler.Handle(reqCtx, &operations.OpsResource{Recorder: r.Recorder}, r.fetchOpsRequest, - r.handleDeletion, r.fetchCluster, + r.handleDeletion, r.addClusterLabelAndSetOwnerReference, r.handleCancelSignal, r.handleOpsRequestByPhase, @@ -122,7 +122,7 @@ func (r *OpsRequestReconciler) fetchOpsRequest(reqCtx intctrlutil.RequestCtx, op // handleDeletion handles the delete event of the OpsRequest. func (r *OpsRequestReconciler) handleDeletion(reqCtx intctrlutil.RequestCtx, opsRes *operations.OpsResource) (*ctrl.Result, error) { - if opsRes.OpsRequest.Status.Phase == appsv1alpha1.OpsRunningPhase { + if opsRes.OpsRequest.Status.Phase == appsv1alpha1.OpsRunningPhase && !opsRes.Cluster.IsDeleting() { return nil, nil } return intctrlutil.HandleCRDeletion(reqCtx, r, opsRes.OpsRequest, constant.OpsRequestFinalizerName, func() (*ctrl.Result, error) { From 5d1c6c54485d5edad6d3475dfdd7226870354084 Mon Sep 17 00:00:00 2001 From: wangyelei Date: Wed, 7 Aug 2024 11:24:22 +0800 Subject: [PATCH 40/45] feat: add a switch whether to verify the cluster status for opsrequest (#7931) --- apis/apps/v1alpha1/opsrequest_types.go | 5 +++ .../bases/apps.kubeblocks.io_opsrequests.yaml | 5 +++ controllers/apps/operations/custom.go | 17 +++++++--- controllers/apps/operations/ops_manager.go | 2 +- controllers/apps/operations/ops_util.go | 9 +++++- controllers/apps/operations/ops_util_test.go | 32 +++++++++++++++++++ controllers/apps/operations/queue_util.go | 9 +++++- .../crds/apps.kubeblocks.io_opsrequests.yaml | 5 +++ docs/developer_docs/api-reference/cluster.md | 24 ++++++++++++++ 9 files changed, 101 insertions(+), 7 deletions(-) diff --git a/apis/apps/v1alpha1/opsrequest_types.go b/apis/apps/v1alpha1/opsrequest_types.go index a1e196e5e618..98d2716c8ad6 100644 --- a/apis/apps/v1alpha1/opsrequest_types.go +++ b/apis/apps/v1alpha1/opsrequest_types.go @@ -64,6 +64,11 @@ type OpsRequestSpec struct { // +optional Force bool `json:"force,omitempty"` + // Indicates whether opsRequest should continue to queue when 'force' is set to true. + // +kubebuilder:default=false + // +optional + EnqueueOnForce bool `json:"enqueueOnForce,omitempty"` + // Specifies the type of this operation. Supported types include "Start", "Stop", "Restart", "Switchover", // "VerticalScaling", "HorizontalScaling", "VolumeExpansion", "Reconfiguring", "Upgrade", "Backup", "Restore", // "Expose", "DataScript", "RebuildInstance", "Custom". diff --git a/config/crd/bases/apps.kubeblocks.io_opsrequests.yaml b/config/crd/bases/apps.kubeblocks.io_opsrequests.yaml index c0f19bda32ba..282a58c7a9ee 100644 --- a/config/crd/bases/apps.kubeblocks.io_opsrequests.yaml +++ b/config/crd/bases/apps.kubeblocks.io_opsrequests.yaml @@ -280,6 +280,11 @@ spec: - components - opsDefinitionName type: object + enqueueOnForce: + default: false + description: Indicates whether opsRequest should continue to queue + when 'force' is set to true. + type: boolean expose: description: Lists Expose objects, each specifying a Component and its services to be exposed. diff --git a/controllers/apps/operations/custom.go b/controllers/apps/operations/custom.go index 714e7e5928b7..eb5810e115e7 100644 --- a/controllers/apps/operations/custom.go +++ b/controllers/apps/operations/custom.go @@ -82,7 +82,10 @@ func (c CustomOpsHandler) ReconcileAction(reqCtx intctrlutil.RequestCtx, cli cli // TODO: support Parallelism for _, v := range customSpec.CustomOpsComponents { // 1. init component action progress and preCheck if the conditions for executing ops are met. - passed := c.initCompActionStatusAndPreCheck(reqCtx, cli, opsRes, v) + requeueAfter, passed := c.initCompActionStatusAndPreCheck(reqCtx, cli, opsRes, v) + if requeueAfter != 0 { + return opsRequestPhase, requeueAfter, nil + } if !passed { compCompleteCount += 1 compFailedCount += 1 @@ -180,6 +183,9 @@ func (c CustomOpsHandler) checkExpression(reqCtx intctrlutil.RequestCtx, return err } if buf.String() == "false" { + if needWaitPreConditionDeadline(opsRes.OpsRequest) { + return intctrlutil.NewRequeueError(time.Second, rule.Message) + } return fmt.Errorf(rule.Message) } } @@ -190,7 +196,7 @@ func (c CustomOpsHandler) checkExpression(reqCtx intctrlutil.RequestCtx, func (c CustomOpsHandler) initCompActionStatusAndPreCheck(reqCtx intctrlutil.RequestCtx, cli client.Client, opsRes *OpsResource, - compCustomItem appsv1alpha1.CustomOpsComponent) bool { + compCustomItem appsv1alpha1.CustomOpsComponent) (time.Duration, bool) { if opsRes.OpsRequest.Status.Components == nil { opsRes.OpsRequest.Status.Components = map[string]appsv1alpha1.OpsRequestComponentStatus{} } @@ -204,7 +210,10 @@ func (c CustomOpsHandler) initCompActionStatusAndPreCheck(reqCtx intctrlutil.Req compStatus.PreCheckResult = &appsv1alpha1.PreCheckResult{Pass: false, Message: err.Error()} opsRes.OpsRequest.Status.Components[compCustomItem.ComponentName] = compStatus opsRes.Recorder.Event(opsRes.OpsRequest, corev1.EventTypeWarning, "PreCheckFailed", err.Error()) - return false + if intctrlutil.IsRequeueError(err) { + return err.(intctrlutil.RequeueError).RequeueAfter(), false + } + return 0, false } compStatus.PreCheckResult = &appsv1alpha1.PreCheckResult{Pass: true} } @@ -218,7 +227,7 @@ func (c CustomOpsHandler) initCompActionStatusAndPreCheck(reqCtx intctrlutil.Req } opsRes.OpsRequest.Status.Components[compCustomItem.ComponentName] = compStatus } - return true + return 0, true } func covertParametersToMap(parameters []appsv1alpha1.Parameter) map[string]string { diff --git a/controllers/apps/operations/ops_manager.go b/controllers/apps/operations/ops_manager.go index 9011054a9241..64919da3e764 100644 --- a/controllers/apps/operations/ops_manager.go +++ b/controllers/apps/operations/ops_manager.go @@ -76,7 +76,7 @@ func (opsMgr *OpsManager) Do(reqCtx intctrlutil.RequestCtx, cli client.Client, o return &ctrl.Result{}, patchValidateErrorCondition(reqCtx.Ctx, cli, opsRes, err.Error()) } // validate OpsRequest.spec - // if the operation will create a new cluster, don't validate the cluster + // if the operation will create a new cluster, don't validate the cluster phase if err = opsRequest.Validate(reqCtx.Ctx, cli, opsRes.Cluster, !opsBehaviour.IsClusterCreation); err != nil { return &ctrl.Result{}, patchValidateErrorCondition(reqCtx.Ctx, cli, opsRes, err.Error()) } diff --git a/controllers/apps/operations/ops_util.go b/controllers/apps/operations/ops_util.go index 79ca214f8b23..598032da878e 100644 --- a/controllers/apps/operations/ops_util.go +++ b/controllers/apps/operations/ops_util.go @@ -213,7 +213,7 @@ func validateOpsWaitingPhase(cluster *appsv1alpha1.Cluster, ops *appsv1alpha1.Op } // check if entry-condition is met // if the cluster is not in the expected phase, we should wait for it for up to TTLSecondsBeforeAbort seconds. - if ops.Spec.PreConditionDeadlineSeconds == nil || (time.Now().After(ops.GetCreationTimestamp().Add(time.Duration(*ops.Spec.PreConditionDeadlineSeconds) * time.Second))) { + if !needWaitPreConditionDeadline(ops) { return nil } @@ -224,6 +224,13 @@ func validateOpsWaitingPhase(cluster *appsv1alpha1.Cluster, ops *appsv1alpha1.Op } } +func needWaitPreConditionDeadline(ops *appsv1alpha1.OpsRequest) bool { + if ops.Spec.PreConditionDeadlineSeconds == nil { + return false + } + return time.Now().Before(ops.GetCreationTimestamp().Add(time.Duration(*ops.Spec.PreConditionDeadlineSeconds) * time.Second)) +} + func abortEarlierOpsRequestWithSameKind(reqCtx intctrlutil.RequestCtx, cli client.Client, opsRes *OpsResource, diff --git a/controllers/apps/operations/ops_util_test.go b/controllers/apps/operations/ops_util_test.go index d1bba1cc2dca..3df54d798312 100644 --- a/controllers/apps/operations/ops_util_test.go +++ b/controllers/apps/operations/ops_util_test.go @@ -300,5 +300,37 @@ var _ = Describe("OpsUtil functions", func() { Expect(err).ShouldNot(HaveOccurred()) Eventually(testapps.GetOpsRequestPhase(&testCtx, client.ObjectKeyFromObject(ops2))).Should(Equal(appsv1alpha1.OpsCancelledPhase)) }) + + It("Test EnqueueOnForce=true", func() { + By("init operations resources ") + opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) + testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) + + By("mock cluster phase to Updating") + Expect(testapps.ChangeObjStatus(&testCtx, opsRes.Cluster, func() { + opsRes.Cluster.Status.Phase = appsv1alpha1.UpdatingClusterPhase + })).Should(Succeed()) + + By("expect the ops phase is failed") + opsRes.OpsRequest = createHorizontalScaling(clusterName, appsv1alpha1.HorizontalScaling{ + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + Replicas: pointer.Int32(1), + }) + reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx} + _, _ = GetOpsManager().Do(reqCtx, k8sClient, opsRes) + Eventually(testapps.GetOpsRequestPhase(&testCtx, client.ObjectKeyFromObject(opsRes.OpsRequest))).Should(Equal(appsv1alpha1.OpsFailedPhase)) + + By("Test EnqueueOnForce=true") + opsRes.OpsRequest = createHorizontalScaling(clusterName, appsv1alpha1.HorizontalScaling{ + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + Replicas: pointer.Int32(1), + }) + opsRes.OpsRequest.Spec.Force = true + opsRes.OpsRequest.Spec.EnqueueOnForce = true + opsRes.OpsRequest.Status.Phase = appsv1alpha1.OpsPendingPhase + By("expect the ops phase is Creating") + _, _ = GetOpsManager().Do(reqCtx, k8sClient, opsRes) + Eventually(testapps.GetOpsRequestPhase(&testCtx, client.ObjectKeyFromObject(opsRes.OpsRequest))).Should(Equal(appsv1alpha1.OpsCreatingPhase)) + }) }) }) diff --git a/controllers/apps/operations/queue_util.go b/controllers/apps/operations/queue_util.go index 1605c0f94bf1..0f7ce95a4db5 100644 --- a/controllers/apps/operations/queue_util.go +++ b/controllers/apps/operations/queue_util.go @@ -105,6 +105,13 @@ func enqueueOpsRequestToClusterAnnotation(ctx context.Context, cli client.Client return nil, err } + inQueue := func() bool { + if opsRes.OpsRequest.Force() && !opsRes.OpsRequest.Spec.EnqueueOnForce { + return false + } + return existOtherRunningOps(opsRequestSlice, opsRes.OpsRequest.Spec.Type, opsBehaviour) + } + index, opsRecorder := GetOpsRecorderFromSlice(opsRequestSlice, opsRes.OpsRequest.Name) switch index { case -1: @@ -121,7 +128,7 @@ func enqueueOpsRequestToClusterAnnotation(ctx context.Context, cli client.Client Type: opsRes.OpsRequest.Spec.Type, QueueBySelf: opsBehaviour.QueueBySelf, // check if the opsRequest should be in the queue. - InQueue: existOtherRunningOps(opsRequestSlice, opsRes.OpsRequest.Spec.Type, opsBehaviour) && !opsRes.OpsRequest.Force(), + InQueue: inQueue(), } opsRequestSlice = append(opsRequestSlice, opsRecorder) default: diff --git a/deploy/helm/crds/apps.kubeblocks.io_opsrequests.yaml b/deploy/helm/crds/apps.kubeblocks.io_opsrequests.yaml index c0f19bda32ba..282a58c7a9ee 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_opsrequests.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_opsrequests.yaml @@ -280,6 +280,11 @@ spec: - components - opsDefinitionName type: object + enqueueOnForce: + default: false + description: Indicates whether opsRequest should continue to queue + when 'force' is set to true. + type: boolean expose: description: Lists Expose objects, each specifying a Component and its services to be exposed. diff --git a/docs/developer_docs/api-reference/cluster.md b/docs/developer_docs/api-reference/cluster.md index 8f12caf9e90f..dd11a84eab44 100644 --- a/docs/developer_docs/api-reference/cluster.md +++ b/docs/developer_docs/api-reference/cluster.md @@ -2544,6 +2544,18 @@ simultaneously.

    +enqueueOnForce
    + +bool + + + +(Optional) +

    Indicates whether opsRequest should continue to queue and run when ‘force’ is set to true.

    + + + + type
    @@ -13336,6 +13348,18 @@ simultaneously.

    +enqueueOnForce
    + +bool + + + +(Optional) +

    Indicates whether opsRequest should continue to queue and run when ‘force’ is set to true.

    + + + + type
    From 2379471ca9078debfd1c28d039391208335593b3 Mon Sep 17 00:00:00 2001 From: Leon Date: Wed, 7 Aug 2024 15:54:38 +0800 Subject: [PATCH 41/45] chore: remove all deprecated fields in CD (#7774) --- apis/apps/v1alpha1/cluster_types.go | 2 +- apis/apps/v1alpha1/clusterdefinition_types.go | 577 +- .../v1alpha1/clusterdefinition_types_test.go | 138 - .../v1alpha1/componentdefinition_types.go | 9 + apis/apps/v1alpha1/opsdefinition_types.go | 13 + apis/apps/v1alpha1/opsrequest_types.go | 5 - apis/apps/v1alpha1/opsrequest_validation.go | 61 +- apis/apps/v1alpha1/type.go | 50 - apis/apps/v1alpha1/zz_generated.deepcopy.go | 407 - ...apps.kubeblocks.io_clusterdefinitions.yaml | 8431 ----------------- .../bases/apps.kubeblocks.io_clusters.yaml | 4 +- .../bases/apps.kubeblocks.io_opsrequests.yaml | 10 - controllers/apps/cluster_controller_test.go | 203 +- .../apps/clusterdefinition_controller.go | 2 +- controllers/apps/component_controller_test.go | 746 +- .../apps/component_hscale_volume_populator.go | 43 +- controllers/apps/component_utils_test.go | 26 - .../combine_upgrade_policy_test.go | 14 +- .../apps/configuration/configuration_test.go | 2 +- .../parallel_upgrade_policy_test.go | 53 +- .../apps/configuration/policy_util_test.go | 48 - .../apps/configuration/reconfigure_policy.go | 4 - .../configuration/rolling_upgrade_policy.go | 5 +- .../rolling_upgrade_policy_test.go | 248 - .../apps/configuration/simple_policy_test.go | 22 +- .../configuration/sync_upgrade_policy_test.go | 17 +- controllers/apps/operations/backup_test.go | 11 +- controllers/apps/operations/custom_test.go | 38 +- controllers/apps/operations/datascript.go | 38 +- .../apps/operations/datascript_test.go | 38 +- controllers/apps/operations/expose_test.go | 4 +- .../operations/horizontal_scaling_test.go | 94 +- .../apps/operations/ops_progress_util.go | 13 +- .../apps/operations/ops_progress_util_test.go | 97 +- controllers/apps/operations/ops_util_test.go | 54 +- .../apps/operations/rebuild_instance_test.go | 66 +- .../apps/operations/reconfigure_test.go | 2 +- controllers/apps/operations/restart_test.go | 16 +- controllers/apps/operations/restore_test.go | 22 +- controllers/apps/operations/start_test.go | 16 +- controllers/apps/operations/stop_test.go | 16 +- controllers/apps/operations/suite_test.go | 49 +- .../apps/operations/switchover_test.go | 64 +- .../apps/operations/switchover_util.go | 37 - .../apps/operations/switchover_util_test.go | 242 - controllers/apps/operations/upgrade_test.go | 38 +- .../apps/operations/util/common_util_test.go | 13 +- .../apps/operations/vertical_scaling_test.go | 31 +- .../apps/operations/volume_expansion_test.go | 12 +- .../apps/opsrequest_controller_test.go | 76 +- .../transformer_cluster_api_normalization.go | 23 +- .../apps/transformer_cluster_deletion_test.go | 6 +- .../transformer_cluster_load_resources.go | 10 +- .../apps/transformer_cluster_service.go | 98 +- .../apps/transformer_component_rbac_test.go | 2 +- .../apps/transformer_component_tls_test.go | 4 +- .../apps/transformer_component_workload.go | 4 + .../extensions/addon_controller_test.go | 4 +- controllers/k8score/event_controller_test.go | 25 +- ...apps.kubeblocks.io_clusterdefinitions.yaml | 8431 ----------------- .../crds/apps.kubeblocks.io_clusters.yaml | 4 +- .../crds/apps.kubeblocks.io_opsrequests.yaml | 10 - docs/developer_docs/api-reference/cluster.md | 1225 +-- pkg/constant/labels.go | 9 - pkg/constant/pattern.go | 5 - .../apiconversion/simplified_cluster_api.go | 193 - pkg/controller/apiconversion/type.go | 31 - .../component/action_post_provision_test.go | 38 +- .../component/action_pre_terminate_test.go | 35 +- pkg/controller/component/action_utils_test.go | 35 +- pkg/controller/component/component.go | 32 +- pkg/controller/component/component_test.go | 2 +- .../component/definition_convertor.go | 497 - .../component/definition_convertor_test.go | 574 -- .../component/synthesize_component.go | 109 +- pkg/controller/component/type.go | 7 +- .../configuration/config_template_test.go | 7 +- .../configuration/configuration_test.go | 2 +- .../configuration/envfrom_utils_test.go | 2 +- .../configuration/resource_wrapper_test.go | 22 +- pkg/controller/factory/builder.go | 17 +- pkg/controller/factory/builder_test.go | 107 +- pkg/controller/job/job_utils_test.go | 19 +- pkg/controller/plan/prepare_test.go | 36 +- pkg/controller/plan/restore_test.go | 58 +- pkg/controller/scheduling/scheduling_utils.go | 18 +- pkg/controllerutil/cluster_utils_test.go | 16 +- pkg/controllerutil/sharding_utils_test.go | 16 +- pkg/testutil/apps/cluster_factory.go | 23 - .../apps/cluster_instance_set_test_util.go | 52 +- pkg/testutil/apps/cluster_util.go | 24 - pkg/testutil/apps/clusterdef_factory.go | 134 +- .../apps/componentdefinition_factory.go | 16 + pkg/testutil/apps/constant.go | 165 +- pkg/testutil/dataprotection/backup_utils.go | 5 +- 95 files changed, 1125 insertions(+), 23254 deletions(-) delete mode 100644 apis/apps/v1alpha1/clusterdefinition_types_test.go delete mode 100644 controllers/apps/configuration/rolling_upgrade_policy_test.go delete mode 100644 controllers/apps/operations/switchover_util_test.go delete mode 100644 pkg/controller/apiconversion/simplified_cluster_api.go delete mode 100644 pkg/controller/apiconversion/type.go delete mode 100644 pkg/controller/component/definition_convertor.go delete mode 100644 pkg/controller/component/definition_convertor_test.go diff --git a/apis/apps/v1alpha1/cluster_types.go b/apis/apps/v1alpha1/cluster_types.go index 6de87bef8045..026fe1cf25b4 100644 --- a/apis/apps/v1alpha1/cluster_types.go +++ b/apis/apps/v1alpha1/cluster_types.go @@ -742,7 +742,7 @@ type ClusterComponentSpec struct { // +optional Configs []ClusterComponentConfig `json:"configs,omitempty"` - // Defines the strategy for switchover and failover when workloadType is Replication. + // Defines the strategy for switchover and failover. // // Deprecated since v0.9. // This field is maintained for backward compatibility and its use is discouraged. diff --git a/apis/apps/v1alpha1/clusterdefinition_types.go b/apis/apps/v1alpha1/clusterdefinition_types.go index a0d557d2925e..5b9fae0b09f0 100644 --- a/apis/apps/v1alpha1/clusterdefinition_types.go +++ b/apis/apps/v1alpha1/clusterdefinition_types.go @@ -17,32 +17,11 @@ limitations under the License. package v1alpha1 import ( - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" - - workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" ) // ClusterDefinitionSpec defines the desired state of ClusterDefinition. type ClusterDefinitionSpec struct { - // Provides the definitions for the cluster components. - // - // Deprecated since v0.9. - // Components should now be individually defined using ComponentDefinition and - // collectively referenced via `topology.components`. - // This field is maintained for backward compatibility and its use is discouraged. - // Existing usage should be updated to the current preferred approach to avoid compatibility issues in future releases. - // - // +kubebuilder:deprecatedversion:warning="This field has been deprecated since 0.9.0" - // +patchMergeKey=name - // +patchStrategy=merge,retainKeys - // +listType=map - // +listMapKey=name - // +optional - ComponentDefs []ClusterComponentDefinition `json:"componentDefs" patchStrategy:"merge,retainKeys" patchMergeKey:"name"` - // Topologies defines all possible topologies within the cluster. // // +kubebuilder:validation:MinItems=1 @@ -145,14 +124,6 @@ type ClusterTopologyOrders struct { Update []string `json:"update,omitempty"` } -// CmdExecutorConfig specifies how to perform creation and deletion statements. -// -// Deprecated since v0.8. -type CmdExecutorConfig struct { - CommandExecutorEnvItem `json:",inline"` - CommandExecutorItem `json:",inline"` -} - // PasswordConfig helps provide to customize complexity of password generation pattern. type PasswordConfig struct { // The length of the password. @@ -232,10 +203,6 @@ type ClusterDefinitionStatus struct { ServiceRefs string `json:"serviceRefs,omitempty"` } -func (r ClusterDefinitionStatus) GetTerminalPhases() []Phase { - return []Phase{AvailablePhase} -} - type LogConfig struct { // Specifies a descriptive label for the log type, such as 'slow' for a MySQL slow log file. // It provides a clear identification of the log's purpose and content. @@ -257,6 +224,8 @@ type LogConfig struct { FilePathPattern string `json:"filePathPattern"` } +// TODO(v1.0): remove this after lorry + // VolumeProtectionSpec is deprecated since v0.9, replaced with ComponentVolume.HighWatermark. type VolumeProtectionSpec struct { // The high watermark threshold for volume space usage. @@ -348,525 +317,6 @@ type ServiceRefDeclarationSpec struct { ServiceVersion string `json:"serviceVersion"` } -// ClusterComponentDefinition defines a Component within a ClusterDefinition but is deprecated and -// has been replaced by ComponentDefinition. -// -// Deprecated: Use ComponentDefinition instead. This type is deprecated as of version 0.8. -// -// +kubebuilder:validation:XValidation:rule="has(self.workloadType) && self.workloadType == 'Consensus' ? (has(self.consensusSpec) || has(self.rsmSpec)) : !has(self.consensusSpec)",message="componentDefs.consensusSpec(deprecated) or componentDefs.rsmSpec(recommended) is required when componentDefs.workloadType is Consensus, and forbidden otherwise" -type ClusterComponentDefinition struct { - // This name could be used as default name of `cluster.spec.componentSpecs.name`, and needs to conform with same - // validation rules as `cluster.spec.componentSpecs.name`, currently complying with IANA Service Naming rule. - // This name will apply to cluster objects as the value of label "apps.kubeblocks.io/component-name". - // - // +kubebuilder:validation:Required - // +kubebuilder:validation:MaxLength=22 - // +kubebuilder:validation:Pattern:=`^[a-z]([a-z0-9\-]*[a-z0-9])?$` - Name string `json:"name"` - - // Defines the type of the workload. - // - // - `Stateless` describes stateless applications. - // - `Stateful` describes common stateful applications. - // - `Consensus` describes applications based on consensus protocols, such as raft and paxos. - // - `Replication` describes applications based on the primary-secondary data replication protocol. - // - // +kubebuilder:validation:Required - WorkloadType WorkloadType `json:"workloadType"` - - // Settings for health checks. - // - // +optional - Probes *ClusterDefinitionProbes `json:"probes,omitempty"` - - // Defines the pod spec template of component. - // - // +kubebuilder:pruning:PreserveUnknownFields - // +optional - PodSpec *corev1.PodSpec `json:"podSpec,omitempty"` - - // Defines spec for `Stateless` workloads. - // - // +kubebuilder:deprecatedversion:warning="This field is deprecated from KB 0.7.0, use RSMSpec instead." - // +optional - StatelessSpec *StatelessSetSpec `json:"statelessSpec,omitempty"` - - // Defines spec for `Stateful` workloads. - // - // +kubebuilder:deprecatedversion:warning="This field is deprecated from KB 0.7.0, use RSMSpec instead." - // +optional - StatefulSpec *StatefulSetSpec `json:"statefulSpec,omitempty"` - - // Defines spec for `Consensus` workloads. It's required if the workload type is `Consensus`. - // - // +kubebuilder:deprecatedversion:warning="This field is deprecated from KB 0.7.0, use RSMSpec instead." - // +optional - ConsensusSpec *ConsensusSetSpec `json:"consensusSpec,omitempty"` - - // Defines spec for `Replication` workloads. - // - // +kubebuilder:deprecatedversion:warning="This field is deprecated from KB 0.7.0, use RSMSpec instead." - // +optional - ReplicationSpec *ReplicationSetSpec `json:"replicationSpec,omitempty"` - - // Defines workload spec of this component. - // From KB 0.7.0, RSM(InstanceSetSpec) will be the underlying CR which powers all kinds of workload in KB. - // RSM is an enhanced stateful workload extension dedicated for heavy-state workloads like databases. - // - // +optional - RSMSpec *RSMSpec `json:"rsmSpec,omitempty"` - - // Defines the behavior of horizontal scale. - // - // +optional - HorizontalScalePolicy *HorizontalScalePolicy `json:"horizontalScalePolicy,omitempty"` - - // Defines command to do switchover. - // In particular, when workloadType=Replication, the command defined in switchoverSpec will only be executed under - // the condition of cluster.componentSpecs[x].SwitchPolicy.type=Noop. - // - // +optional - SwitchoverSpec *SwitchoverSpec `json:"switchoverSpec,omitempty"` -} - -func (r *ClusterComponentDefinition) GetStatefulSetWorkload() StatefulSetWorkload { - switch r.WorkloadType { - case Stateless: - return nil - case Stateful: - return r.StatefulSpec - case Consensus: - return r.ConsensusSpec - case Replication: - return r.ReplicationSpec - } - panic("unreachable") -} - -func (r *ClusterComponentDefinition) IsStatelessWorkload() bool { - return r.WorkloadType == Stateless -} - -func (r *ClusterComponentDefinition) GetCommonStatefulSpec() (*StatefulSetSpec, error) { - if r.IsStatelessWorkload() { - return nil, ErrWorkloadTypeIsStateless - } - switch r.WorkloadType { - case Stateful: - return r.StatefulSpec, nil - case Consensus: - if r.ConsensusSpec != nil { - return &r.ConsensusSpec.StatefulSetSpec, nil - } - case Replication: - if r.ReplicationSpec != nil { - return &r.ReplicationSpec.StatefulSetSpec, nil - } - default: - panic("unreachable") - // return nil, ErrWorkloadTypeIsUnknown - } - return nil, nil -} - -// HorizontalScalePolicy is deprecated since v0.8. -type HorizontalScalePolicy struct { - // Determines the data synchronization method when a component scales out. - // The policy can be one of the following: {None, CloneVolume}. The default policy is `None`. - // - // - `None`: This is the default policy. It creates an empty volume without data cloning. - // - `CloneVolume`: This policy clones data to newly scaled pods. It first tries to use a volume snapshot. - // If volume snapshot is not enabled, it will attempt to use a backup tool. If neither method works, it will report an error. - // - `Snapshot`: This policy is deprecated and is an alias for CloneVolume. - // - // +kubebuilder:default=None - // +optional - Type HScaleDataClonePolicyType `json:"type,omitempty"` - - // Refers to the backup policy template. - // - // +optional - BackupPolicyTemplateName string `json:"backupPolicyTemplateName,omitempty"` - - // Specifies the volumeMount of the container to backup. - // This only works if Type is not None. If not specified, the first volumeMount will be selected. - // - // +optional - VolumeMountsName string `json:"volumeMountsName,omitempty"` -} - -// ClusterDefinitionProbeCMDs is deprecated since v0.8. -type ClusterDefinitionProbeCMDs struct { - // Defines write checks that are executed on the probe sidecar. - // - // +optional - Writes []string `json:"writes,omitempty"` - - // Defines read checks that are executed on the probe sidecar. - // - // +optional - Queries []string `json:"queries,omitempty"` -} - -// ClusterDefinitionProbe is deprecated since v0.8. -type ClusterDefinitionProbe struct { - // How often (in seconds) to perform the probe. - // - // +kubebuilder:default=1 - // +kubebuilder:validation:Minimum=1 - PeriodSeconds int32 `json:"periodSeconds,omitempty"` - - // Number of seconds after which the probe times out. Defaults to 1 second. - // - // +kubebuilder:default=1 - // +kubebuilder:validation:Minimum=1 - TimeoutSeconds int32 `json:"timeoutSeconds,omitempty"` - - // Minimum consecutive failures for the probe to be considered failed after having succeeded. - // - // +kubebuilder:default=3 - // +kubebuilder:validation:Minimum=2 - FailureThreshold int32 `json:"failureThreshold,omitempty"` - - // Commands used to execute for probe. - // - // +optional - Commands *ClusterDefinitionProbeCMDs `json:"commands,omitempty"` -} - -// ClusterDefinitionProbes is deprecated since v0.8. -type ClusterDefinitionProbes struct { - // Specifies the probe used for checking the running status of the component. - // - // +optional - RunningProbe *ClusterDefinitionProbe `json:"runningProbe,omitempty"` - - // Specifies the probe used for checking the status of the component. - // - // +optional - StatusProbe *ClusterDefinitionProbe `json:"statusProbe,omitempty"` - - // Specifies the probe used for checking the role of the component. - // - // +kubebuilder:deprecatedversion:warning="This field is deprecated from KB 0.7.0, use RSMSpec instead." - // +optional - RoleProbe *ClusterDefinitionProbe `json:"roleProbe,omitempty"` - - // Defines the timeout (in seconds) for the role probe after all pods of the component are ready. - // The system will check if the application is available in the pod. - // If pods exceed the InitializationTimeoutSeconds time without a role label, this component will enter the - // Failed/Abnormal phase. - // - // Note that this configuration will only take effect if the component supports RoleProbe - // and will not affect the life cycle of the pod. default values are 60 seconds. - // - // +kubebuilder:validation:Minimum=30 - // +optional - RoleProbeTimeoutAfterPodsReady int32 `json:"roleProbeTimeoutAfterPodsReady,omitempty"` -} - -// StatelessSetSpec is deprecated since v0.7. -type StatelessSetSpec struct { - // Specifies the deployment strategy that will be used to replace existing pods with new ones. - // - // +patchStrategy=retainKeys - // +optional - UpdateStrategy appsv1.DeploymentStrategy `json:"updateStrategy,omitempty"` -} - -// StatefulSetSpec is deprecated since v0.7. -type StatefulSetSpec struct { - // Specifies the strategy for updating Pods. - // For workloadType=`Consensus`, the update strategy can be one of the following: - // - // - `Serial`: Updates Members sequentially to minimize component downtime. - // - `BestEffortParallel`: Updates Members in parallel to minimize component write downtime. Majority remains online - // at all times. - // - `Parallel`: Forces parallel updates. - // - // +kubebuilder:default=Serial - // +optional - UpdateStrategy UpdateStrategy `json:"updateStrategy,omitempty"` - - // Controls the creation of pods during initial scale up, replacement of pods on nodes, and scaling down. - // - // - `OrderedReady`: Creates pods in increasing order (pod-0, then pod-1, etc). The controller waits until each pod - // is ready before continuing. Pods are removed in reverse order when scaling down. - // - `Parallel`: Creates pods in parallel to match the desired scale without waiting. All pods are deleted at once - // when scaling down. - // - // +optional - LLPodManagementPolicy appsv1.PodManagementPolicyType `json:"llPodManagementPolicy,omitempty"` - - // Specifies the low-level StatefulSetUpdateStrategy to be used when updating Pods in the StatefulSet upon a - // revision to the Template. - // `UpdateStrategy` will be ignored if this is provided. - // - // +optional - LLUpdateStrategy *appsv1.StatefulSetUpdateStrategy `json:"llUpdateStrategy,omitempty"` -} - -var _ StatefulSetWorkload = &StatefulSetSpec{} - -func (r *StatefulSetSpec) GetUpdateStrategy() UpdateStrategy { - if r == nil { - return SerialStrategy - } - return r.UpdateStrategy -} - -func (r *StatefulSetSpec) FinalStsUpdateStrategy() (appsv1.PodManagementPolicyType, appsv1.StatefulSetUpdateStrategy) { - if r == nil { - r = &StatefulSetSpec{ - UpdateStrategy: SerialStrategy, - } - } - return r.finalStsUpdateStrategy() -} - -func (r *StatefulSetSpec) finalStsUpdateStrategy() (appsv1.PodManagementPolicyType, appsv1.StatefulSetUpdateStrategy) { - if r.LLUpdateStrategy != nil { - return r.LLPodManagementPolicy, *r.LLUpdateStrategy - } - - zeroPartition := int32(0) - switch r.UpdateStrategy { - case BestEffortParallelStrategy: - m := intstr.FromString("49%") - return appsv1.ParallelPodManagement, appsv1.StatefulSetUpdateStrategy{ - Type: appsv1.RollingUpdateStatefulSetStrategyType, - RollingUpdate: &appsv1.RollingUpdateStatefulSetStrategy{ - // explicitly set the partition as 0 to avoid update workload unexpectedly. - Partition: &zeroPartition, - // alpha feature since v1.24 - // ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#maximum-unavailable-pods - MaxUnavailable: &m, - }, - } - case ParallelStrategy: - return appsv1.ParallelPodManagement, appsv1.StatefulSetUpdateStrategy{ - Type: appsv1.RollingUpdateStatefulSetStrategyType, - } - case SerialStrategy: - fallthrough - default: - m := intstr.FromInt(1) - return appsv1.OrderedReadyPodManagement, appsv1.StatefulSetUpdateStrategy{ - Type: appsv1.RollingUpdateStatefulSetStrategyType, - RollingUpdate: &appsv1.RollingUpdateStatefulSetStrategy{ - // explicitly set the partition as 0 to avoid update workload unexpectedly. - Partition: &zeroPartition, - // alpha feature since v1.24 - // ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#maximum-unavailable-pods - MaxUnavailable: &m, - }, - } - } -} - -// ConsensusSetSpec is deprecated since v0.7. -type ConsensusSetSpec struct { - StatefulSetSpec `json:",inline"` - - // Represents a single leader in the consensus set. - // - // +kubebuilder:validation:Required - Leader ConsensusMember `json:"leader"` - - // Members of the consensus set that have voting rights but are not the leader. - // - // +optional - Followers []ConsensusMember `json:"followers,omitempty"` - - // Represents a member of the consensus set that does not have voting rights. - // - // +optional - Learner *ConsensusMember `json:"learner,omitempty"` -} - -var _ StatefulSetWorkload = &ConsensusSetSpec{} - -func (r *ConsensusSetSpec) GetUpdateStrategy() UpdateStrategy { - if r == nil { - return SerialStrategy - } - return r.UpdateStrategy -} - -func (r *ConsensusSetSpec) FinalStsUpdateStrategy() (appsv1.PodManagementPolicyType, appsv1.StatefulSetUpdateStrategy) { - if r == nil { - r = NewConsensusSetSpec() - } - if r.LLUpdateStrategy != nil { - return r.LLPodManagementPolicy, *r.LLUpdateStrategy - } - _, s := r.StatefulSetSpec.finalStsUpdateStrategy() - // switch r.UpdateStrategy { - // case SerialStrategy, BestEffortParallelStrategy: - s.Type = appsv1.OnDeleteStatefulSetStrategyType - s.RollingUpdate = nil - // } - return appsv1.ParallelPodManagement, s -} - -func NewConsensusSetSpec() *ConsensusSetSpec { - return &ConsensusSetSpec{ - Leader: DefaultLeader, - StatefulSetSpec: StatefulSetSpec{ - UpdateStrategy: SerialStrategy, - }, - } -} - -// ConsensusMember is deprecated since v0.7. -type ConsensusMember struct { - // Specifies the name of the consensus member. - // - // +kubebuilder:validation:Required - // +kubebuilder:default=leader - Name string `json:"name"` - - // Specifies the services that this member is capable of providing. - // - // +kubebuilder:validation:Required - // +kubebuilder:default=ReadWrite - AccessMode AccessMode `json:"accessMode"` - - // Indicates the number of Pods that perform this role. - // The default is 1 for `Leader`, 0 for `Learner`, others for `Followers`. - // - // +kubebuilder:default=0 - // +kubebuilder:validation:Minimum=0 - // +optional - Replicas *int32 `json:"replicas,omitempty"` -} - -// RSMSpec is deprecated since v0.8. -type RSMSpec struct { - // Specifies a list of roles defined within the system. - // - // +optional - Roles []workloads.ReplicaRole `json:"roles,omitempty"` - - // Defines the method used to probe a role. - // - // +optional - RoleProbe *workloads.RoleProbe `json:"roleProbe,omitempty"` - - // Indicates the actions required for dynamic membership reconfiguration. - // - // +optional - MembershipReconfiguration *workloads.MembershipReconfiguration `json:"membershipReconfiguration,omitempty"` - - // Describes the strategy for updating Members (Pods). - // - // - `Serial`: Updates Members sequentially to ensure minimum component downtime. - // - `BestEffortParallel`: Updates Members in parallel to ensure minimum component write downtime. - // - `Parallel`: Forces parallel updates. - // - // +kubebuilder:validation:Enum={Serial,BestEffortParallel,Parallel} - // +optional - MemberUpdateStrategy *workloads.MemberUpdateStrategy `json:"memberUpdateStrategy,omitempty"` -} - -// ReplicationSetSpec is deprecated since v0.7. -type ReplicationSetSpec struct { - StatefulSetSpec `json:",inline"` -} - -var _ StatefulSetWorkload = &ReplicationSetSpec{} - -func (r *ReplicationSetSpec) GetUpdateStrategy() UpdateStrategy { - if r == nil { - return SerialStrategy - } - return r.UpdateStrategy -} - -func (r *ReplicationSetSpec) FinalStsUpdateStrategy() (appsv1.PodManagementPolicyType, appsv1.StatefulSetUpdateStrategy) { - if r == nil { - r = &ReplicationSetSpec{} - } - if r.LLUpdateStrategy != nil { - return r.LLPodManagementPolicy, *r.LLUpdateStrategy - } - _, s := r.StatefulSetSpec.finalStsUpdateStrategy() - s.Type = appsv1.OnDeleteStatefulSetStrategyType - s.RollingUpdate = nil - return appsv1.ParallelPodManagement, s -} - -// SwitchoverSpec is deprecated since v0.8. -type SwitchoverSpec struct { - // Represents the action of switching over to a specified candidate primary or leader instance. - // - // +optional - WithCandidate *SwitchoverAction `json:"withCandidate,omitempty"` - - // Represents the action of switching over without specifying a candidate primary or leader instance. - // - // +optional - WithoutCandidate *SwitchoverAction `json:"withoutCandidate,omitempty"` -} - -// SwitchoverAction is deprecated since v0.8. -type SwitchoverAction struct { - // Specifies the switchover command. - // - // +kubebuilder:validation:Required - CmdExecutorConfig *CmdExecutorConfig `json:"cmdExecutorConfig"` - - // Used to select the script that need to be referenced. - // When defined, the scripts defined in scriptSpecs can be referenced within the SwitchoverAction.CmdExecutorConfig. - // - // +kubebuilder:deprecatedversion:warning="This field is deprecated from KB 0.9.0" - // +optional - ScriptSpecSelectors []ScriptSpecSelector `json:"scriptSpecSelectors,omitempty"` -} - -type ScriptSpecSelector struct { - // Represents the name of the ScriptSpec referent. - // - // +kubebuilder:validation:Required - // +kubebuilder:validation:MaxLength=63 - // +kubebuilder:validation:Pattern:=`^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$` - Name string `json:"name"` -} - -// CommandExecutorEnvItem is deprecated since v0.8. -type CommandExecutorEnvItem struct { - // Specifies the image used to execute the command. - // - // +kubebuilder:validation:Required - Image string `json:"image"` - - // A list of environment variables that will be injected into the command execution context. - // - // +kubebuilder:pruning:PreserveUnknownFields - // +patchMergeKey=name - // +patchStrategy=merge,retainKeys - // +optional - Env []corev1.EnvVar `json:"env,omitempty" patchStrategy:"merge" patchMergeKey:"name"` -} - -// CommandExecutorItem is deprecated since v0.8. -type CommandExecutorItem struct { - // The command to be executed. - // - // +kubebuilder:validation:Required - // +kubebuilder:validation:MinItems=1 - Command []string `json:"command"` - - // Additional parameters used in the execution of the command. - // - // +optional - Args []string `json:"args,omitempty"` -} - -// TODO(API): -// 1. how to display the aggregated topologies and its service references line by line? -// 2. the services and versions supported - // +genclient // +genclient:nonNamespaced // +k8s:openapi-gen=true @@ -907,26 +357,3 @@ type ClusterDefinitionList struct { func init() { SchemeBuilder.Register(&ClusterDefinition{}, &ClusterDefinitionList{}) } - -// GetComponentDefByName gets component definition from ClusterDefinition with compDefName -func (r *ClusterDefinition) GetComponentDefByName(compDefName string) *ClusterComponentDefinition { - for _, component := range r.Spec.ComponentDefs { - if component.Name == compDefName { - return &component - } - } - return nil -} - -// FailurePolicyType specifies the type of failure policy. -// -// +enum -// +kubebuilder:validation:Enum={Ignore,Fail} -type FailurePolicyType string - -const ( - // FailurePolicyIgnore means that an error will be ignored but logged. - FailurePolicyIgnore FailurePolicyType = "Ignore" - // FailurePolicyFail means that an error will be reported. - FailurePolicyFail FailurePolicyType = "Fail" -) diff --git a/apis/apps/v1alpha1/clusterdefinition_types_test.go b/apis/apps/v1alpha1/clusterdefinition_types_test.go deleted file mode 100644 index 4ce8340b91e3..000000000000 --- a/apis/apps/v1alpha1/clusterdefinition_types_test.go +++ /dev/null @@ -1,138 +0,0 @@ -/* -Copyright (C) 2022-2024 ApeCloud Co., Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha1 - -import ( - "testing" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - appsv1 "k8s.io/api/apps/v1" -) - -func TestGetComponentDefByName(t *testing.T) { - componentDefName := "mysqlType" - clusterDef := &ClusterDefinition{ - Spec: ClusterDefinitionSpec{ - ComponentDefs: []ClusterComponentDefinition{ - { - Name: componentDefName, - }, - }, - }, - } - if clusterDef.GetComponentDefByName(componentDefName) == nil { - t.Error("function GetComponentDefByName should not return nil") - } - componentDefName = "test" - if clusterDef.GetComponentDefByName(componentDefName) != nil { - t.Error("function GetComponentDefByName should return nil") - } -} - -var _ = Describe("", func() { - - It("test GetTerminalPhases", func() { - r := ClusterDefinitionStatus{} - Expect(r.GetTerminalPhases()).Should(ContainElement(AvailablePhase)) - }) - - It("test GetStatefulSetWorkload", func() { - r := &ClusterComponentDefinition{} - r.WorkloadType = Stateless - Expect(r.GetStatefulSetWorkload()).Should(BeNil()) - r.WorkloadType = Stateful - Expect(r.GetStatefulSetWorkload()).Should(BeEquivalentTo(r.StatefulSpec)) - r.WorkloadType = Consensus - Expect(r.GetStatefulSetWorkload()).Should(BeEquivalentTo(r.ConsensusSpec)) - r.WorkloadType = Replication - Expect(r.GetStatefulSetWorkload()).Should(BeEquivalentTo(r.ReplicationSpec)) - }) - - It("test GetCommonStatefulSpec", func() { - r := &ClusterComponentDefinition{} - r.WorkloadType = Stateful - r.StatefulSpec = &StatefulSetSpec{} - spec, err := r.GetCommonStatefulSpec() - Expect(err).Should(BeNil()) - Expect(spec).Should(BeEquivalentTo(r.StatefulSpec)) - r.WorkloadType = Consensus - r.ConsensusSpec = &ConsensusSetSpec{ - StatefulSetSpec: StatefulSetSpec{}, - } - spec, err = r.GetCommonStatefulSpec() - Expect(err).Should(BeNil()) - Expect(spec).Should(BeEquivalentTo(&r.ConsensusSpec.StatefulSetSpec)) - r.WorkloadType = Replication - r.ReplicationSpec = &ReplicationSetSpec{ - StatefulSetSpec: StatefulSetSpec{}, - } - spec, err = r.GetCommonStatefulSpec() - Expect(err).Should(BeNil()) - Expect(spec).Should(BeEquivalentTo(&r.ReplicationSpec.StatefulSetSpec)) - }) - - It("test GetUpdateStrategy", func() { - r := &StatefulSetSpec{} - r.UpdateStrategy = BestEffortParallelStrategy - Expect(r.GetUpdateStrategy()).Should(Equal(r.UpdateStrategy)) - }) - - It("test finalStsUpdateStrategy", func() { - r := &StatefulSetSpec{} - r.UpdateStrategy = ParallelStrategy - policyType, strategy := r.finalStsUpdateStrategy() - Expect(policyType).Should(BeEquivalentTo(appsv1.ParallelPodManagement)) - Expect(strategy.Type).Should(BeEquivalentTo(appsv1.RollingUpdateStatefulSetStrategyType)) - r.UpdateStrategy = SerialStrategy - policyType, strategy = r.finalStsUpdateStrategy() - Expect(policyType).Should(BeEquivalentTo(appsv1.OrderedReadyPodManagement)) - Expect(strategy.Type).Should(BeEquivalentTo(appsv1.RollingUpdateStatefulSetStrategyType)) - Expect(strategy.RollingUpdate.MaxUnavailable.IntValue()).Should(BeEquivalentTo(1)) - }) - - It("test consensus GetUpdateStrategy", func() { - r := &ConsensusSetSpec{} - r.UpdateStrategy = BestEffortParallelStrategy - Expect(r.GetUpdateStrategy()).Should(Equal(r.UpdateStrategy)) - }) - - It("test consensus FinalStsUpdateStrategy", func() { - r := ConsensusSetSpec{} - policyType, strategy := r.FinalStsUpdateStrategy() - Expect(policyType).Should(BeEquivalentTo(appsv1.ParallelPodManagement)) - Expect(strategy.Type).Should(BeEquivalentTo(appsv1.OnDeleteStatefulSetStrategyType)) - }) - - It("test NewConsensusSetSpec", func() { - Expect(NewConsensusSetSpec()).ShouldNot(BeNil()) - }) - - It("test replication GetUpdateStrategy", func() { - r := &ReplicationSetSpec{} - r.UpdateStrategy = BestEffortParallelStrategy - Expect(r.GetUpdateStrategy()).Should(Equal(r.UpdateStrategy)) - }) - - It("test replication FinalStsUpdateStrategy", func() { - r := ReplicationSetSpec{} - policyType, strategy := r.FinalStsUpdateStrategy() - Expect(policyType).Should(BeEquivalentTo(appsv1.ParallelPodManagement)) - Expect(strategy.Type).Should(BeEquivalentTo(appsv1.OnDeleteStatefulSetStrategyType)) - }) -}) diff --git a/apis/apps/v1alpha1/componentdefinition_types.go b/apis/apps/v1alpha1/componentdefinition_types.go index d0e2150903f8..afc250fa4954 100644 --- a/apis/apps/v1alpha1/componentdefinition_types.go +++ b/apis/apps/v1alpha1/componentdefinition_types.go @@ -1359,3 +1359,12 @@ type ComponentSwitchover struct { // +optional ScriptSpecSelectors []ScriptSpecSelector `json:"scriptSpecSelectors,omitempty"` } + +type ScriptSpecSelector struct { + // Represents the name of the ScriptSpec referent. + // + // +kubebuilder:validation:Required + // +kubebuilder:validation:MaxLength=63 + // +kubebuilder:validation:Pattern:=`^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$` + Name string `json:"name"` +} diff --git a/apis/apps/v1alpha1/opsdefinition_types.go b/apis/apps/v1alpha1/opsdefinition_types.go index 1f0ee74bda36..4b25594f640d 100644 --- a/apis/apps/v1alpha1/opsdefinition_types.go +++ b/apis/apps/v1alpha1/opsdefinition_types.go @@ -298,6 +298,19 @@ type OpsAction struct { ResourceModifier *OpsResourceModifierAction `json:"resourceModifier,omitempty"` } +// FailurePolicyType specifies the type of failure policy. +// +// +enum +// +kubebuilder:validation:Enum={Ignore,Fail} +type FailurePolicyType string + +const ( + // FailurePolicyIgnore means that an error will be ignored but logged. + FailurePolicyIgnore FailurePolicyType = "Ignore" + // FailurePolicyFail means that an error will be reported. + FailurePolicyFail FailurePolicyType = "Fail" +) + type OpsWorkloadAction struct { // Defines the workload type of the action. Valid values include "Job" and "Pod". // diff --git a/apis/apps/v1alpha1/opsrequest_types.go b/apis/apps/v1alpha1/opsrequest_types.go index 98d2716c8ad6..bb9b8ab701d0 100644 --- a/apis/apps/v1alpha1/opsrequest_types.go +++ b/apis/apps/v1alpha1/opsrequest_types.go @@ -1248,11 +1248,6 @@ type OpsRequestComponentStatus struct { // +optional ProgressDetails []ProgressStatusDetail `json:"progressDetails,omitempty"` - // Records the workload type of Component in ClusterDefinition. - // Deprecated and should be removed in the future version. - // +optional - WorkloadType WorkloadType `json:"workloadType,omitempty"` - // Provides an explanation for the Component being in its current state. // +kubebuilder:validation:MaxLength=1024 // +optional diff --git a/apis/apps/v1alpha1/opsrequest_validation.go b/apis/apps/v1alpha1/opsrequest_validation.go index d1d6d9e6de92..28cce5f40036 100644 --- a/apis/apps/v1alpha1/opsrequest_validation.go +++ b/apis/apps/v1alpha1/opsrequest_validation.go @@ -824,50 +824,6 @@ func validateSwitchoverResourceList(ctx context.Context, cli client.Client, clus return notEmptyError("switchover.instanceName") } - // TODO(xingran): this will be removed in the future. - validateBaseOnClusterCompDef := func(clusterCmpDef string) error { - // check clusterComponentDefinition whether support switchover - clusterCompDefObj, err := getClusterComponentDefByName(ctx, cli, *cluster, clusterCmpDef) - if err != nil { - return err - } - if clusterCompDefObj == nil { - return fmt.Errorf("this cluster component %s is invalid", switchover.ComponentName) - } - if clusterCompDefObj.SwitchoverSpec == nil { - return fmt.Errorf("this cluster component %s does not support switchover", switchover.ComponentName) - } - switch switchover.InstanceName { - case KBSwitchoverCandidateInstanceForAnyPod: - if clusterCompDefObj.SwitchoverSpec.WithoutCandidate == nil { - return fmt.Errorf("this cluster component %s does not support promote without specifying an instance. Please specify a specific instance for the promotion", switchover.ComponentName) - } - default: - if clusterCompDefObj.SwitchoverSpec.WithCandidate == nil { - return fmt.Errorf("this cluster component %s does not support specifying an instance for promote. If you want to perform a promote operation, please do not specify an instance", switchover.ComponentName) - } - } - // check switchover.InstanceName whether exist and role label is correct - if switchover.InstanceName == KBSwitchoverCandidateInstanceForAnyPod { - return nil - } - pod := &corev1.Pod{} - if err := cli.Get(ctx, types.NamespacedName{Namespace: cluster.Namespace, Name: switchover.InstanceName}, pod); err != nil { - return fmt.Errorf("get instanceName %s failed, err: %s, and check the validity of the instanceName using \"kbcli cluster list-instances\"", switchover.InstanceName, err.Error()) - } - v, ok := pod.Labels[constant.RoleLabelKey] - if !ok || v == "" { - return fmt.Errorf("instanceName %s cannot be promoted because it had a invalid role label", switchover.InstanceName) - } - if v == constant.Primary || v == constant.Leader { - return fmt.Errorf("instanceName %s cannot be promoted because it is already the primary or leader instance", switchover.InstanceName) - } - if !strings.HasPrefix(pod.Name, fmt.Sprintf("%s-%s", cluster.Name, switchover.ComponentName)) { - return fmt.Errorf("instanceName %s does not belong to the current component, please check the validity of the instance using \"kbcli cluster list-instances\"", switchover.InstanceName) - } - return nil - } - validateBaseOnCompDef := func(compDef string) error { getTargetRole := func(roles []ReplicaRole) (string, error) { targetRole = "" @@ -939,7 +895,7 @@ func validateSwitchoverResourceList(ctx context.Context, cli client.Client, clus if compSpec.ComponentDef != "" { return validateBaseOnCompDef(compSpec.ComponentDef) } else { - return validateBaseOnClusterCompDef(cluster.Spec.GetComponentDefRefName(switchover.ComponentName)) + return fmt.Errorf("not-supported") } } return nil @@ -953,18 +909,3 @@ func getComponentDefByName(ctx context.Context, cli client.Client, compDefName s } return compDef, nil } - -// getClusterComponentDefByName gets component from ClusterDefinition with compDefName -func getClusterComponentDefByName(ctx context.Context, cli client.Client, cluster Cluster, - compDefName string) (*ClusterComponentDefinition, error) { - clusterDef := &ClusterDefinition{} - if err := cli.Get(ctx, client.ObjectKey{Name: cluster.Spec.ClusterDefRef}, clusterDef); err != nil { - return nil, err - } - for _, component := range clusterDef.Spec.ComponentDefs { - if component.Name == compDefName { - return &component, nil - } - } - return nil, ErrNotMatchingCompDef -} diff --git a/apis/apps/v1alpha1/type.go b/apis/apps/v1alpha1/type.go index 6ae88ad04f28..140d4358f985 100644 --- a/apis/apps/v1alpha1/type.go +++ b/apis/apps/v1alpha1/type.go @@ -447,37 +447,6 @@ const ( BestEffortParallelStrategy UpdateStrategy = "BestEffortParallel" ) -var DefaultLeader = ConsensusMember{ - Name: "leader", - AccessMode: ReadWrite, -} - -// WorkloadType defines the type of workload for the components of the ClusterDefinition. -// It can be one of the following: `Stateless`, `Stateful`, `Consensus`, or `Replication`. -// -// Deprecated since v0.8. -// -// +enum -// +kubebuilder:validation:Enum={Stateless,Stateful,Consensus,Replication} -type WorkloadType string - -const ( - // Stateless represents a workload type where components do not maintain state, and instances are interchangeable. - Stateless WorkloadType = "Stateless" - - // Stateful represents a workload type where components maintain state, and each instance has a unique identity. - Stateful WorkloadType = "Stateful" - - // Consensus represents a workload type involving distributed consensus algorithms for coordinated decision-making. - Consensus WorkloadType = "Consensus" - - // Replication represents a workload type that involves replication, typically used for achieving high availability - // and fault tolerance. - Replication WorkloadType = "Replication" -) - -var WorkloadTypes = []string{"Stateless", "Stateful", "Consensus", "Replication"} - // TerminationPolicyType defines termination policy types. // // +enum @@ -498,25 +467,6 @@ const ( WipeOut TerminationPolicyType = "WipeOut" ) -// HScaleDataClonePolicyType defines the data clone policy to be used during horizontal scaling. -// This policy determines how data is handled when new nodes are added to the cluster. -// The policy can be set to `None`, `CloneVolume`, or `Snapshot`. -// -// +enum -// +kubebuilder:validation:Enum={None,CloneVolume,Snapshot} -type HScaleDataClonePolicyType string - -const ( - // HScaleDataClonePolicyNone indicates that no data cloning will occur during horizontal scaling. - HScaleDataClonePolicyNone HScaleDataClonePolicyType = "None" - - // HScaleDataClonePolicyCloneVolume indicates that data will be cloned from existing volumes during horizontal scaling. - HScaleDataClonePolicyCloneVolume HScaleDataClonePolicyType = "CloneVolume" - - // HScaleDataClonePolicyFromSnapshot indicates that data will be cloned from a snapshot during horizontal scaling. - HScaleDataClonePolicyFromSnapshot HScaleDataClonePolicyType = "Snapshot" -) - // PodAntiAffinity defines the pod anti-affinity strategy. // // This strategy determines how pods are scheduled in relation to other pods, with the aim of either spreading pods diff --git a/apis/apps/v1alpha1/zz_generated.deepcopy.go b/apis/apps/v1alpha1/zz_generated.deepcopy.go index 5083370bbb77..89d4cb36cf79 100644 --- a/apis/apps/v1alpha1/zz_generated.deepcopy.go +++ b/apis/apps/v1alpha1/zz_generated.deepcopy.go @@ -399,66 +399,6 @@ func (in *ClusterComponentConfigSource) DeepCopy() *ClusterComponentConfigSource return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterComponentDefinition) DeepCopyInto(out *ClusterComponentDefinition) { - *out = *in - if in.Probes != nil { - in, out := &in.Probes, &out.Probes - *out = new(ClusterDefinitionProbes) - (*in).DeepCopyInto(*out) - } - if in.PodSpec != nil { - in, out := &in.PodSpec, &out.PodSpec - *out = new(v1.PodSpec) - (*in).DeepCopyInto(*out) - } - if in.StatelessSpec != nil { - in, out := &in.StatelessSpec, &out.StatelessSpec - *out = new(StatelessSetSpec) - (*in).DeepCopyInto(*out) - } - if in.StatefulSpec != nil { - in, out := &in.StatefulSpec, &out.StatefulSpec - *out = new(StatefulSetSpec) - (*in).DeepCopyInto(*out) - } - if in.ConsensusSpec != nil { - in, out := &in.ConsensusSpec, &out.ConsensusSpec - *out = new(ConsensusSetSpec) - (*in).DeepCopyInto(*out) - } - if in.ReplicationSpec != nil { - in, out := &in.ReplicationSpec, &out.ReplicationSpec - *out = new(ReplicationSetSpec) - (*in).DeepCopyInto(*out) - } - if in.RSMSpec != nil { - in, out := &in.RSMSpec, &out.RSMSpec - *out = new(RSMSpec) - (*in).DeepCopyInto(*out) - } - if in.HorizontalScalePolicy != nil { - in, out := &in.HorizontalScalePolicy, &out.HorizontalScalePolicy - *out = new(HorizontalScalePolicy) - **out = **in - } - if in.SwitchoverSpec != nil { - in, out := &in.SwitchoverSpec, &out.SwitchoverSpec - *out = new(SwitchoverSpec) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterComponentDefinition. -func (in *ClusterComponentDefinition) DeepCopy() *ClusterComponentDefinition { - if in == nil { - return nil - } - out := new(ClusterComponentDefinition) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClusterComponentService) DeepCopyInto(out *ClusterComponentService) { *out = *in @@ -757,91 +697,9 @@ func (in *ClusterDefinitionList) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterDefinitionProbe) DeepCopyInto(out *ClusterDefinitionProbe) { - *out = *in - if in.Commands != nil { - in, out := &in.Commands, &out.Commands - *out = new(ClusterDefinitionProbeCMDs) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterDefinitionProbe. -func (in *ClusterDefinitionProbe) DeepCopy() *ClusterDefinitionProbe { - if in == nil { - return nil - } - out := new(ClusterDefinitionProbe) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterDefinitionProbeCMDs) DeepCopyInto(out *ClusterDefinitionProbeCMDs) { - *out = *in - if in.Writes != nil { - in, out := &in.Writes, &out.Writes - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.Queries != nil { - in, out := &in.Queries, &out.Queries - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterDefinitionProbeCMDs. -func (in *ClusterDefinitionProbeCMDs) DeepCopy() *ClusterDefinitionProbeCMDs { - if in == nil { - return nil - } - out := new(ClusterDefinitionProbeCMDs) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterDefinitionProbes) DeepCopyInto(out *ClusterDefinitionProbes) { - *out = *in - if in.RunningProbe != nil { - in, out := &in.RunningProbe, &out.RunningProbe - *out = new(ClusterDefinitionProbe) - (*in).DeepCopyInto(*out) - } - if in.StatusProbe != nil { - in, out := &in.StatusProbe, &out.StatusProbe - *out = new(ClusterDefinitionProbe) - (*in).DeepCopyInto(*out) - } - if in.RoleProbe != nil { - in, out := &in.RoleProbe, &out.RoleProbe - *out = new(ClusterDefinitionProbe) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterDefinitionProbes. -func (in *ClusterDefinitionProbes) DeepCopy() *ClusterDefinitionProbes { - if in == nil { - return nil - } - out := new(ClusterDefinitionProbes) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClusterDefinitionSpec) DeepCopyInto(out *ClusterDefinitionSpec) { *out = *in - if in.ComponentDefs != nil { - in, out := &in.ComponentDefs, &out.ComponentDefs - *out = make([]ClusterComponentDefinition, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } if in.Topologies != nil { in, out := &in.Topologies, &out.Topologies *out = make([]ClusterTopology, len(*in)) @@ -1186,70 +1044,6 @@ func (in *ClusterTopologyOrders) DeepCopy() *ClusterTopologyOrders { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CmdExecutorConfig) DeepCopyInto(out *CmdExecutorConfig) { - *out = *in - in.CommandExecutorEnvItem.DeepCopyInto(&out.CommandExecutorEnvItem) - in.CommandExecutorItem.DeepCopyInto(&out.CommandExecutorItem) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CmdExecutorConfig. -func (in *CmdExecutorConfig) DeepCopy() *CmdExecutorConfig { - if in == nil { - return nil - } - out := new(CmdExecutorConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CommandExecutorEnvItem) DeepCopyInto(out *CommandExecutorEnvItem) { - *out = *in - if in.Env != nil { - in, out := &in.Env, &out.Env - *out = make([]v1.EnvVar, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommandExecutorEnvItem. -func (in *CommandExecutorEnvItem) DeepCopy() *CommandExecutorEnvItem { - if in == nil { - return nil - } - out := new(CommandExecutorEnvItem) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CommandExecutorItem) DeepCopyInto(out *CommandExecutorItem) { - *out = *in - if in.Command != nil { - in, out := &in.Command, &out.Command - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.Args != nil { - in, out := &in.Args, &out.Args - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommandExecutorItem. -func (in *CommandExecutorItem) DeepCopy() *CommandExecutorItem { - if in == nil { - return nil - } - out := new(CommandExecutorItem) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CompletionProbe) DeepCopyInto(out *CompletionProbe) { *out = *in @@ -2677,55 +2471,6 @@ func (in *ConnectionCredentialKey) DeepCopy() *ConnectionCredentialKey { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConsensusMember) DeepCopyInto(out *ConsensusMember) { - *out = *in - if in.Replicas != nil { - in, out := &in.Replicas, &out.Replicas - *out = new(int32) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConsensusMember. -func (in *ConsensusMember) DeepCopy() *ConsensusMember { - if in == nil { - return nil - } - out := new(ConsensusMember) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConsensusSetSpec) DeepCopyInto(out *ConsensusSetSpec) { - *out = *in - in.StatefulSetSpec.DeepCopyInto(&out.StatefulSetSpec) - in.Leader.DeepCopyInto(&out.Leader) - if in.Followers != nil { - in, out := &in.Followers, &out.Followers - *out = make([]ConsensusMember, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Learner != nil { - in, out := &in.Learner, &out.Learner - *out = new(ConsensusMember) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConsensusSetSpec. -func (in *ConsensusSetSpec) DeepCopy() *ConsensusSetSpec { - if in == nil { - return nil - } - out := new(ConsensusSetSpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ContainerVars) DeepCopyInto(out *ContainerVars) { *out = *in @@ -3001,21 +2746,6 @@ func (in *Expose) DeepCopy() *Expose { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HorizontalScalePolicy) DeepCopyInto(out *HorizontalScalePolicy) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HorizontalScalePolicy. -func (in *HorizontalScalePolicy) DeepCopy() *HorizontalScalePolicy { - if in == nil { - return nil - } - out := new(HorizontalScalePolicy) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HorizontalScaling) DeepCopyInto(out *HorizontalScaling) { *out = *in @@ -4435,41 +4165,6 @@ func (in *ProvisionSecretRef) DeepCopy() *ProvisionSecretRef { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RSMSpec) DeepCopyInto(out *RSMSpec) { - *out = *in - if in.Roles != nil { - in, out := &in.Roles, &out.Roles - *out = make([]workloadsv1alpha1.ReplicaRole, len(*in)) - copy(*out, *in) - } - if in.RoleProbe != nil { - in, out := &in.RoleProbe, &out.RoleProbe - *out = new(workloadsv1alpha1.RoleProbe) - (*in).DeepCopyInto(*out) - } - if in.MembershipReconfiguration != nil { - in, out := &in.MembershipReconfiguration, &out.MembershipReconfiguration - *out = new(workloadsv1alpha1.MembershipReconfiguration) - (*in).DeepCopyInto(*out) - } - if in.MemberUpdateStrategy != nil { - in, out := &in.MemberUpdateStrategy, &out.MemberUpdateStrategy - *out = new(workloadsv1alpha1.MemberUpdateStrategy) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RSMSpec. -func (in *RSMSpec) DeepCopy() *RSMSpec { - if in == nil { - return nil - } - out := new(RSMSpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RebuildInstance) DeepCopyInto(out *RebuildInstance) { *out = *in @@ -4670,22 +4365,6 @@ func (in *ReplicasLimit) DeepCopy() *ReplicasLimit { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ReplicationSetSpec) DeepCopyInto(out *ReplicationSetSpec) { - *out = *in - in.StatefulSetSpec.DeepCopyInto(&out.StatefulSetSpec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplicationSetSpec. -func (in *ReplicationSetSpec) DeepCopy() *ReplicationSetSpec { - if in == nil { - return nil - } - out := new(ReplicationSetSpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResourceMeta) DeepCopyInto(out *ResourceMeta) { *out = *in @@ -5438,42 +5117,6 @@ func (in *SpecificOpsRequest) DeepCopy() *SpecificOpsRequest { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *StatefulSetSpec) DeepCopyInto(out *StatefulSetSpec) { - *out = *in - if in.LLUpdateStrategy != nil { - in, out := &in.LLUpdateStrategy, &out.LLUpdateStrategy - *out = new(appsv1.StatefulSetUpdateStrategy) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StatefulSetSpec. -func (in *StatefulSetSpec) DeepCopy() *StatefulSetSpec { - if in == nil { - return nil - } - out := new(StatefulSetSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *StatelessSetSpec) DeepCopyInto(out *StatelessSetSpec) { - *out = *in - in.UpdateStrategy.DeepCopyInto(&out.UpdateStrategy) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StatelessSetSpec. -func (in *StatelessSetSpec) DeepCopy() *StatelessSetSpec { - if in == nil { - return nil - } - out := new(StatelessSetSpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Switchover) DeepCopyInto(out *Switchover) { *out = *in @@ -5490,56 +5133,6 @@ func (in *Switchover) DeepCopy() *Switchover { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SwitchoverAction) DeepCopyInto(out *SwitchoverAction) { - *out = *in - if in.CmdExecutorConfig != nil { - in, out := &in.CmdExecutorConfig, &out.CmdExecutorConfig - *out = new(CmdExecutorConfig) - (*in).DeepCopyInto(*out) - } - if in.ScriptSpecSelectors != nil { - in, out := &in.ScriptSpecSelectors, &out.ScriptSpecSelectors - *out = make([]ScriptSpecSelector, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SwitchoverAction. -func (in *SwitchoverAction) DeepCopy() *SwitchoverAction { - if in == nil { - return nil - } - out := new(SwitchoverAction) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SwitchoverSpec) DeepCopyInto(out *SwitchoverSpec) { - *out = *in - if in.WithCandidate != nil { - in, out := &in.WithCandidate, &out.WithCandidate - *out = new(SwitchoverAction) - (*in).DeepCopyInto(*out) - } - if in.WithoutCandidate != nil { - in, out := &in.WithoutCandidate, &out.WithoutCandidate - *out = new(SwitchoverAction) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SwitchoverSpec. -func (in *SwitchoverSpec) DeepCopy() *SwitchoverSpec { - if in == nil { - return nil - } - out := new(SwitchoverSpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SystemAccount) DeepCopyInto(out *SystemAccount) { *out = *in diff --git a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml index e433b1d10397..a626e4fb3762 100644 --- a/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/config/crd/bases/apps.kubeblocks.io_clusterdefinitions.yaml @@ -71,8437 +71,6 @@ spec: spec: description: ClusterDefinitionSpec defines the desired state of ClusterDefinition. properties: - componentDefs: - description: |- - Provides the definitions for the cluster components. - - - Deprecated since v0.9. - Components should now be individually defined using ComponentDefinition and - collectively referenced via `topology.components`. - This field is maintained for backward compatibility and its use is discouraged. - Existing usage should be updated to the current preferred approach to avoid compatibility issues in future releases. - items: - description: |- - ClusterComponentDefinition defines a Component within a ClusterDefinition but is deprecated and - has been replaced by ComponentDefinition. - - - Deprecated: Use ComponentDefinition instead. This type is deprecated as of version 0.8. - properties: - consensusSpec: - description: Defines spec for `Consensus` workloads. It's required - if the workload type is `Consensus`. - properties: - followers: - description: Members of the consensus set that have voting - rights but are not the leader. - items: - description: ConsensusMember is deprecated since v0.7. - properties: - accessMode: - default: ReadWrite - description: Specifies the services that this member - is capable of providing. - enum: - - None - - Readonly - - ReadWrite - type: string - name: - default: leader - description: Specifies the name of the consensus member. - type: string - replicas: - default: 0 - description: |- - Indicates the number of Pods that perform this role. - The default is 1 for `Leader`, 0 for `Learner`, others for `Followers`. - format: int32 - minimum: 0 - type: integer - required: - - accessMode - - name - type: object - type: array - leader: - description: Represents a single leader in the consensus - set. - properties: - accessMode: - default: ReadWrite - description: Specifies the services that this member - is capable of providing. - enum: - - None - - Readonly - - ReadWrite - type: string - name: - default: leader - description: Specifies the name of the consensus member. - type: string - replicas: - default: 0 - description: |- - Indicates the number of Pods that perform this role. - The default is 1 for `Leader`, 0 for `Learner`, others for `Followers`. - format: int32 - minimum: 0 - type: integer - required: - - accessMode - - name - type: object - learner: - description: Represents a member of the consensus set that - does not have voting rights. - properties: - accessMode: - default: ReadWrite - description: Specifies the services that this member - is capable of providing. - enum: - - None - - Readonly - - ReadWrite - type: string - name: - default: leader - description: Specifies the name of the consensus member. - type: string - replicas: - default: 0 - description: |- - Indicates the number of Pods that perform this role. - The default is 1 for `Leader`, 0 for `Learner`, others for `Followers`. - format: int32 - minimum: 0 - type: integer - required: - - accessMode - - name - type: object - llPodManagementPolicy: - description: |- - Controls the creation of pods during initial scale up, replacement of pods on nodes, and scaling down. - - - - `OrderedReady`: Creates pods in increasing order (pod-0, then pod-1, etc). The controller waits until each pod - is ready before continuing. Pods are removed in reverse order when scaling down. - - `Parallel`: Creates pods in parallel to match the desired scale without waiting. All pods are deleted at once - when scaling down. - type: string - llUpdateStrategy: - description: |- - Specifies the low-level StatefulSetUpdateStrategy to be used when updating Pods in the StatefulSet upon a - revision to the Template. - `UpdateStrategy` will be ignored if this is provided. - properties: - rollingUpdate: - description: RollingUpdate is used to communicate parameters - when Type is RollingUpdateStatefulSetStrategyType. - properties: - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of pods that can be unavailable during the update. - Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - Absolute number is calculated from percentage by rounding up. This can not be 0. - Defaults to 1. This field is alpha-level and is only honored by servers that enable the - MaxUnavailableStatefulSet feature. The field applies to all pods in the range 0 to - Replicas-1. That means if there is any unavailable pod in the range 0 to Replicas-1, it - will be counted towards MaxUnavailable. - x-kubernetes-int-or-string: true - partition: - description: |- - Partition indicates the ordinal at which the StatefulSet should be partitioned - for updates. During a rolling update, all pods from ordinal Replicas-1 to - Partition are updated. All pods from ordinal Partition-1 to 0 remain untouched. - This is helpful in being able to do a canary based deployment. The default value is 0. - format: int32 - type: integer - type: object - type: - description: |- - Type indicates the type of the StatefulSetUpdateStrategy. - Default is RollingUpdate. - type: string - type: object - updateStrategy: - default: Serial - description: |- - Specifies the strategy for updating Pods. - For workloadType=`Consensus`, the update strategy can be one of the following: - - - - `Serial`: Updates Members sequentially to minimize component downtime. - - `BestEffortParallel`: Updates Members in parallel to minimize component write downtime. Majority remains online - at all times. - - `Parallel`: Forces parallel updates. - enum: - - Serial - - BestEffortParallel - - Parallel - type: string - required: - - leader - type: object - horizontalScalePolicy: - description: Defines the behavior of horizontal scale. - properties: - backupPolicyTemplateName: - description: Refers to the backup policy template. - type: string - type: - default: None - description: |- - Determines the data synchronization method when a component scales out. - The policy can be one of the following: {None, CloneVolume}. The default policy is `None`. - - - - `None`: This is the default policy. It creates an empty volume without data cloning. - - `CloneVolume`: This policy clones data to newly scaled pods. It first tries to use a volume snapshot. - If volume snapshot is not enabled, it will attempt to use a backup tool. If neither method works, it will report an error. - - `Snapshot`: This policy is deprecated and is an alias for CloneVolume. - enum: - - None - - CloneVolume - - Snapshot - type: string - volumeMountsName: - description: |- - Specifies the volumeMount of the container to backup. - This only works if Type is not None. If not specified, the first volumeMount will be selected. - type: string - type: object - name: - description: |- - This name could be used as default name of `cluster.spec.componentSpecs.name`, and needs to conform with same - validation rules as `cluster.spec.componentSpecs.name`, currently complying with IANA Service Naming rule. - This name will apply to cluster objects as the value of label "apps.kubeblocks.io/component-name". - maxLength: 22 - pattern: ^[a-z]([a-z0-9\-]*[a-z0-9])?$ - type: string - podSpec: - description: Defines the pod spec template of component. - properties: - activeDeadlineSeconds: - description: |- - Optional duration in seconds the pod may be active on the node relative to - StartTime before the system will actively try to mark it failed and kill associated containers. - Value must be a positive integer. - format: int64 - type: integer - affinity: - description: If specified, the pod's scheduling constraints - properties: - nodeAffinity: - description: Describes node affinity scheduling rules - for the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node matches the corresponding matchExpressions; the - node(s) with the highest sum are the most preferred. - items: - description: |- - An empty preferred scheduling term matches all objects with implicit weight 0 - (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). - properties: - preference: - description: A node selector term, associated - with the corresponding weight. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - x-kubernetes-map-type: atomic - weight: - description: Weight associated with matching - the corresponding nodeSelectorTerm, in the - range 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. - properties: - nodeSelectorTerms: - description: Required. A list of node selector - terms. The terms are ORed. - items: - description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - x-kubernetes-map-type: atomic - type: array - required: - - nodeSelectorTerms - type: object - x-kubernetes-map-type: atomic - type: object - podAffinity: - description: Describes pod affinity scheduling rules - (e.g. co-locate this pod in the same node, zone, etc. - as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched - WeightedPodAffinityTerm fields are added per-node - to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. - properties: - labelSelector: - description: A label query over a set - of resources, in this case pods. - properties: - matchExpressions: - description: matchExpressions is a - list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a - list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling - rules (e.g. avoid putting this pod in the same node, - zone, etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the anti-affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched - WeightedPodAffinityTerm fields are added per-node - to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. - properties: - labelSelector: - description: A label query over a set - of resources, in this case pods. - properties: - matchExpressions: - description: matchExpressions is a - list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a - list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the anti-affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the anti-affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - type: object - type: object - automountServiceAccountToken: - description: AutomountServiceAccountToken indicates whether - a service account token should be automatically mounted. - type: boolean - containers: - description: |- - List of containers belonging to the pod. - Containers cannot currently be added or removed. - There must be at least one container in a Pod. - Cannot be updated. - items: - description: A single application container that you want - to run within a pod. - properties: - args: - description: |- - Arguments to the entrypoint. - The container image's CMD is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - command: - description: |- - Entrypoint array. Not executed within a shell. - The container image's ENTRYPOINT is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - env: - description: |- - List of environment variables to set in the container. - Cannot be updated. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, - defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults - to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - description: |- - List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple - sources, the value associated with the last source will take precedence. - Values defined by an Env with a duplicate key will take precedence. - Cannot be updated. - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - lifecycle: - description: |- - Actions that the management system should take in response to container lifecycle events. - Cannot be updated. - properties: - postStart: - description: |- - PostStart is called immediately after a container is created. If the handler fails, - the container is terminated and restarted according to its restart policy. - Other management of the container blocks until the hook completes. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: |- - PreStop is called immediately before a container is terminated due to an - API request or management event such as liveness/startup probe failure, - preemption, resource contention, etc. The handler is not called if the - container crashes or exits. The Pod's termination grace period countdown begins before the - PreStop hook is executed. Regardless of the outcome of the handler, the - container will eventually terminate within the Pod's termination grace - period (unless delayed by finalizers). Other management of the container blocks until the hook completes - or until the termination grace period is reached. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: |- - Periodic probe of container liveness. - Container will be restarted if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - name: - description: |- - Name of the container specified as a DNS_LABEL. - Each container in a pod must have a unique name (DNS_LABEL). - Cannot be updated. - type: string - ports: - description: |- - List of ports to expose from the container. Not specifying a port here - DOES NOT prevent that port from being exposed. Any port which is - listening on the default "0.0.0.0" address inside a container will be - accessible from the network. - Modifying this array with strategic merge patch may corrupt the data. - For more information See https://github.com/kubernetes/kubernetes/issues/108255. - Cannot be updated. - items: - description: ContainerPort represents a network - port in a single container. - properties: - containerPort: - description: |- - Number of port to expose on the pod's IP address. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external - port to. - type: string - hostPort: - description: |- - Number of port to expose on the host. - If specified, this must be a valid port number, 0 < x < 65536. - If HostNetwork is specified, this must match ContainerPort. - Most containers do not need this. - format: int32 - type: integer - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - protocol: - default: TCP - description: |- - Protocol for port. Must be UDP, TCP, or SCTP. - Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: |- - Periodic probe of container service readiness. - Container will be removed from service endpoints if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - resizePolicy: - description: Resources resize policy for the container. - items: - description: ContainerResizePolicy represents resource - resize policy for the container. - properties: - resourceName: - description: |- - Name of the resource to which this resource resize policy applies. - Supported values: cpu, memory. - type: string - restartPolicy: - description: |- - Restart policy to apply when specified resource is resized. - If not specified, it defaults to NotRequired. - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Compute Resources required by this container. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - restartPolicy: - description: |- - RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, - the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: - this init container will be continually restarted on - exit until all regular containers have terminated. Once all regular - containers have completed, all init containers with restartPolicy "Always" - will be shut down. This lifecycle differs from normal init containers and - is often referred to as a "sidecar" container. Although this init - container still starts in the init container sequence, it does not wait - for the container to complete before proceeding to the next init - container. Instead, the next init container starts immediately after this - init container is started, or after any startupProbe has successfully - completed. - type: string - securityContext: - description: |- - SecurityContext defines the security options the container should be run with. - If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - properties: - allowPrivilegeEscalation: - description: |- - AllowPrivilegeEscalation controls whether a process can gain more - privileges than its parent process. This bool directly controls if - the no_new_privs flag will be set on the container process. - AllowPrivilegeEscalation is true always when the container is: - 1) run as Privileged - 2) has CAP_SYS_ADMIN - Note that this field cannot be set when spec.os.name is windows. - type: boolean - capabilities: - description: |- - The capabilities to add/drop when running containers. - Defaults to the default set of capabilities granted by the container runtime. - Note that this field cannot be set when spec.os.name is windows. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - drop: - description: Removed capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - type: object - privileged: - description: |- - Run container in privileged mode. - Processes in privileged containers are essentially equivalent to root on the host. - Defaults to false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - procMount: - description: |- - procMount denotes the type of proc mount to use for the containers. - The default is DefaultProcMount which uses the container runtime defaults for - readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. - Note that this field cannot be set when spec.os.name is windows. - type: string - readOnlyRootFilesystem: - description: |- - Whether this container has a read-only root filesystem. - Default is false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to the container. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label - that applies to the container. - type: string - role: - description: Role is a SELinux role label - that applies to the container. - type: string - type: - description: Type is a SELinux type label - that applies to the container. - type: string - user: - description: User is a SELinux user label - that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by this container. If seccomp options are - provided at both the pod & container level, the container options - override the pod options. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options from the PodSecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the - name of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: |- - StartupProbe indicates that the Pod has successfully initialized. - If specified, no other probes are executed until this completes successfully. - If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. - This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, - when it might take a long time to load data or warm a cache, than during steady-state operation. - This cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - stdin: - description: |- - Whether this container should allocate a buffer for stdin in the container runtime. If this - is not set, reads from stdin in the container will always result in EOF. - Default is false. - type: boolean - stdinOnce: - description: |- - Whether the container runtime should close the stdin channel after it has been opened by - a single attach. When stdin is true the stdin stream will remain open across multiple attach - sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - first client attaches to stdin, and then remains open and accepts data until the client disconnects, - at which time stdin is closed and remains closed until the container is restarted. If this - flag is false, a container processes that reads from stdin will never receive an EOF. - Default is false - type: boolean - terminationMessagePath: - description: |- - Optional: Path at which the file to which the container's termination message - will be written is mounted into the container's filesystem. - Message written is intended to be brief final status, such as an assertion failure message. - Will be truncated by the node if greater than 4096 bytes. The total message length across - all containers will be limited to 12kb. - Defaults to /dev/termination-log. - Cannot be updated. - type: string - terminationMessagePolicy: - description: |- - Indicate how the termination message should be populated. File will use the contents of - terminationMessagePath to populate the container status message on both success and failure. - FallbackToLogsOnError will use the last chunk of container log output if the termination - message file is empty and the container exited with an error. - The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - Defaults to File. - Cannot be updated. - type: string - tty: - description: |- - Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices - to be used by the container. - items: - description: volumeDevice describes a mapping of - a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside of - the container that the device will be mapped - to. - type: string - name: - description: name must match the name of a persistentVolumeClaim - in the pod - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - description: |- - Pod volumes to mount into the container's filesystem. - Cannot be updated. - items: - description: VolumeMount describes a mounting of - a Volume within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - workingDir: - description: |- - Container's working directory. - If not specified, the container runtime's default will be used, which - might be configured in the container image. - Cannot be updated. - type: string - required: - - name - type: object - type: array - dnsConfig: - description: |- - Specifies the DNS parameters of a pod. - Parameters specified here will be merged to the generated DNS - configuration based on DNSPolicy. - properties: - nameservers: - description: |- - A list of DNS name server IP addresses. - This will be appended to the base nameservers generated from DNSPolicy. - Duplicated nameservers will be removed. - items: - type: string - type: array - options: - description: |- - A list of DNS resolver options. - This will be merged with the base options generated from DNSPolicy. - Duplicated entries will be removed. Resolution options given in Options - will override those that appear in the base DNSPolicy. - items: - description: PodDNSConfigOption defines DNS resolver - options of a pod. - properties: - name: - description: Required. - type: string - value: - type: string - type: object - type: array - searches: - description: |- - A list of DNS search domains for host-name lookup. - This will be appended to the base search paths generated from DNSPolicy. - Duplicated search paths will be removed. - items: - type: string - type: array - type: object - dnsPolicy: - description: |- - Set DNS policy for the pod. - Defaults to "ClusterFirst". - Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. - DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. - To have DNS options set along with hostNetwork, you have to specify DNS policy - explicitly to 'ClusterFirstWithHostNet'. - type: string - enableServiceLinks: - description: |- - EnableServiceLinks indicates whether information about services should be injected into pod's - environment variables, matching the syntax of Docker links. - Optional: Defaults to true. - type: boolean - ephemeralContainers: - description: |- - List of ephemeral containers run in this pod. Ephemeral containers may be run in an existing - pod to perform user-initiated actions such as debugging. This list cannot be specified when - creating a pod, and it cannot be modified by updating the pod spec. In order to add an - ephemeral container to an existing pod, use the pod's ephemeralcontainers subresource. - items: - description: |- - An EphemeralContainer is a temporary container that you may add to an existing Pod for - user-initiated activities such as debugging. Ephemeral containers have no resource or - scheduling guarantees, and they will not be restarted when they exit or when a Pod is - removed or restarted. The kubelet may evict a Pod if an ephemeral container causes the - Pod to exceed its resource allocation. - - - To add an ephemeral container, use the ephemeralcontainers subresource of an existing - Pod. Ephemeral containers may not be removed or restarted. - properties: - args: - description: |- - Arguments to the entrypoint. - The image's CMD is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - command: - description: |- - Entrypoint array. Not executed within a shell. - The image's ENTRYPOINT is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - env: - description: |- - List of environment variables to set in the container. - Cannot be updated. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, - defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults - to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - description: |- - List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple - sources, the value associated with the last source will take precedence. - Values defined by an Env with a duplicate key will take precedence. - Cannot be updated. - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - lifecycle: - description: Lifecycle is not allowed for ephemeral - containers. - properties: - postStart: - description: |- - PostStart is called immediately after a container is created. If the handler fails, - the container is terminated and restarted according to its restart policy. - Other management of the container blocks until the hook completes. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: |- - PreStop is called immediately before a container is terminated due to an - API request or management event such as liveness/startup probe failure, - preemption, resource contention, etc. The handler is not called if the - container crashes or exits. The Pod's termination grace period countdown begins before the - PreStop hook is executed. Regardless of the outcome of the handler, the - container will eventually terminate within the Pod's termination grace - period (unless delayed by finalizers). Other management of the container blocks until the hook completes - or until the termination grace period is reached. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: Probes are not allowed for ephemeral - containers. - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - name: - description: |- - Name of the ephemeral container specified as a DNS_LABEL. - This name must be unique among all containers, init containers and ephemeral containers. - type: string - ports: - description: Ports are not allowed for ephemeral containers. - items: - description: ContainerPort represents a network - port in a single container. - properties: - containerPort: - description: |- - Number of port to expose on the pod's IP address. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external - port to. - type: string - hostPort: - description: |- - Number of port to expose on the host. - If specified, this must be a valid port number, 0 < x < 65536. - If HostNetwork is specified, this must match ContainerPort. - Most containers do not need this. - format: int32 - type: integer - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - protocol: - default: TCP - description: |- - Protocol for port. Must be UDP, TCP, or SCTP. - Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: Probes are not allowed for ephemeral - containers. - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - resizePolicy: - description: Resources resize policy for the container. - items: - description: ContainerResizePolicy represents resource - resize policy for the container. - properties: - resourceName: - description: |- - Name of the resource to which this resource resize policy applies. - Supported values: cpu, memory. - type: string - restartPolicy: - description: |- - Restart policy to apply when specified resource is resized. - If not specified, it defaults to NotRequired. - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources are not allowed for ephemeral containers. Ephemeral containers use spare resources - already allocated to the pod. - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - restartPolicy: - description: |- - Restart policy for the container to manage the restart behavior of each - container within a pod. - This may only be set for init containers. You cannot set this field on - ephemeral containers. - type: string - securityContext: - description: |- - Optional: SecurityContext defines the security options the ephemeral container should be run with. - If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - properties: - allowPrivilegeEscalation: - description: |- - AllowPrivilegeEscalation controls whether a process can gain more - privileges than its parent process. This bool directly controls if - the no_new_privs flag will be set on the container process. - AllowPrivilegeEscalation is true always when the container is: - 1) run as Privileged - 2) has CAP_SYS_ADMIN - Note that this field cannot be set when spec.os.name is windows. - type: boolean - capabilities: - description: |- - The capabilities to add/drop when running containers. - Defaults to the default set of capabilities granted by the container runtime. - Note that this field cannot be set when spec.os.name is windows. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - drop: - description: Removed capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - type: object - privileged: - description: |- - Run container in privileged mode. - Processes in privileged containers are essentially equivalent to root on the host. - Defaults to false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - procMount: - description: |- - procMount denotes the type of proc mount to use for the containers. - The default is DefaultProcMount which uses the container runtime defaults for - readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. - Note that this field cannot be set when spec.os.name is windows. - type: string - readOnlyRootFilesystem: - description: |- - Whether this container has a read-only root filesystem. - Default is false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to the container. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label - that applies to the container. - type: string - role: - description: Role is a SELinux role label - that applies to the container. - type: string - type: - description: Type is a SELinux type label - that applies to the container. - type: string - user: - description: User is a SELinux user label - that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by this container. If seccomp options are - provided at both the pod & container level, the container options - override the pod options. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options from the PodSecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the - name of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: Probes are not allowed for ephemeral - containers. - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - stdin: - description: |- - Whether this container should allocate a buffer for stdin in the container runtime. If this - is not set, reads from stdin in the container will always result in EOF. - Default is false. - type: boolean - stdinOnce: - description: |- - Whether the container runtime should close the stdin channel after it has been opened by - a single attach. When stdin is true the stdin stream will remain open across multiple attach - sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - first client attaches to stdin, and then remains open and accepts data until the client disconnects, - at which time stdin is closed and remains closed until the container is restarted. If this - flag is false, a container processes that reads from stdin will never receive an EOF. - Default is false - type: boolean - targetContainerName: - description: |- - If set, the name of the container from PodSpec that this ephemeral container targets. - The ephemeral container will be run in the namespaces (IPC, PID, etc) of this container. - If not set then the ephemeral container uses the namespaces configured in the Pod spec. - - - The container runtime must implement support for this feature. If the runtime does not - support namespace targeting then the result of setting this field is undefined. - type: string - terminationMessagePath: - description: |- - Optional: Path at which the file to which the container's termination message - will be written is mounted into the container's filesystem. - Message written is intended to be brief final status, such as an assertion failure message. - Will be truncated by the node if greater than 4096 bytes. The total message length across - all containers will be limited to 12kb. - Defaults to /dev/termination-log. - Cannot be updated. - type: string - terminationMessagePolicy: - description: |- - Indicate how the termination message should be populated. File will use the contents of - terminationMessagePath to populate the container status message on both success and failure. - FallbackToLogsOnError will use the last chunk of container log output if the termination - message file is empty and the container exited with an error. - The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - Defaults to File. - Cannot be updated. - type: string - tty: - description: |- - Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices - to be used by the container. - items: - description: volumeDevice describes a mapping of - a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside of - the container that the device will be mapped - to. - type: string - name: - description: name must match the name of a persistentVolumeClaim - in the pod - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - description: |- - Pod volumes to mount into the container's filesystem. Subpath mounts are not allowed for ephemeral containers. - Cannot be updated. - items: - description: VolumeMount describes a mounting of - a Volume within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - workingDir: - description: |- - Container's working directory. - If not specified, the container runtime's default will be used, which - might be configured in the container image. - Cannot be updated. - type: string - required: - - name - type: object - type: array - hostAliases: - description: |- - HostAliases is an optional list of hosts and IPs that will be injected into the pod's hosts - file if specified. This is only valid for non-hostNetwork pods. - items: - description: |- - HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the - pod's hosts file. - properties: - hostnames: - description: Hostnames for the above IP address. - items: - type: string - type: array - ip: - description: IP address of the host file entry. - type: string - type: object - type: array - hostIPC: - description: |- - Use the host's ipc namespace. - Optional: Default to false. - type: boolean - hostNetwork: - description: |- - Host networking requested for this pod. Use the host's network namespace. - If this option is set, the ports that will be used must be specified. - Default to false. - type: boolean - hostPID: - description: |- - Use the host's pid namespace. - Optional: Default to false. - type: boolean - hostUsers: - description: |- - Use the host's user namespace. - Optional: Default to true. - If set to true or not present, the pod will be run in the host user namespace, useful - for when the pod needs a feature only available to the host user namespace, such as - loading a kernel module with CAP_SYS_MODULE. - When set to false, a new userns is created for the pod. Setting false is useful for - mitigating container breakout vulnerabilities even allowing users to run their - containers as root without actually having root privileges on the host. - This field is alpha-level and is only honored by servers that enable the UserNamespacesSupport feature. - type: boolean - hostname: - description: |- - Specifies the hostname of the Pod - If not specified, the pod's hostname will be set to a system-defined value. - type: string - imagePullSecrets: - description: |- - ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. - If specified, these secrets will be passed to individual puller implementations for them to use. - More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod - items: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - type: array - initContainers: - description: |- - List of initialization containers belonging to the pod. - Init containers are executed in order prior to containers being started. If any - init container fails, the pod is considered to have failed and is handled according - to its restartPolicy. The name for an init container or normal container must be - unique among all containers. - Init containers may not have Lifecycle actions, Readiness probes, Liveness probes, or Startup probes. - The resourceRequirements of an init container are taken into account during scheduling - by finding the highest request/limit for each resource type, and then using the max of - of that value or the sum of the normal containers. Limits are applied to init containers - in a similar fashion. - Init containers cannot currently be added or removed. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ - items: - description: A single application container that you want - to run within a pod. - properties: - args: - description: |- - Arguments to the entrypoint. - The container image's CMD is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - command: - description: |- - Entrypoint array. Not executed within a shell. - The container image's ENTRYPOINT is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - env: - description: |- - List of environment variables to set in the container. - Cannot be updated. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, - defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults - to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - description: |- - List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple - sources, the value associated with the last source will take precedence. - Values defined by an Env with a duplicate key will take precedence. - Cannot be updated. - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - lifecycle: - description: |- - Actions that the management system should take in response to container lifecycle events. - Cannot be updated. - properties: - postStart: - description: |- - PostStart is called immediately after a container is created. If the handler fails, - the container is terminated and restarted according to its restart policy. - Other management of the container blocks until the hook completes. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: |- - PreStop is called immediately before a container is terminated due to an - API request or management event such as liveness/startup probe failure, - preemption, resource contention, etc. The handler is not called if the - container crashes or exits. The Pod's termination grace period countdown begins before the - PreStop hook is executed. Regardless of the outcome of the handler, the - container will eventually terminate within the Pod's termination grace - period (unless delayed by finalizers). Other management of the container blocks until the hook completes - or until the termination grace period is reached. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: |- - Periodic probe of container liveness. - Container will be restarted if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - name: - description: |- - Name of the container specified as a DNS_LABEL. - Each container in a pod must have a unique name (DNS_LABEL). - Cannot be updated. - type: string - ports: - description: |- - List of ports to expose from the container. Not specifying a port here - DOES NOT prevent that port from being exposed. Any port which is - listening on the default "0.0.0.0" address inside a container will be - accessible from the network. - Modifying this array with strategic merge patch may corrupt the data. - For more information See https://github.com/kubernetes/kubernetes/issues/108255. - Cannot be updated. - items: - description: ContainerPort represents a network - port in a single container. - properties: - containerPort: - description: |- - Number of port to expose on the pod's IP address. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external - port to. - type: string - hostPort: - description: |- - Number of port to expose on the host. - If specified, this must be a valid port number, 0 < x < 65536. - If HostNetwork is specified, this must match ContainerPort. - Most containers do not need this. - format: int32 - type: integer - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - protocol: - default: TCP - description: |- - Protocol for port. Must be UDP, TCP, or SCTP. - Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: |- - Periodic probe of container service readiness. - Container will be removed from service endpoints if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - resizePolicy: - description: Resources resize policy for the container. - items: - description: ContainerResizePolicy represents resource - resize policy for the container. - properties: - resourceName: - description: |- - Name of the resource to which this resource resize policy applies. - Supported values: cpu, memory. - type: string - restartPolicy: - description: |- - Restart policy to apply when specified resource is resized. - If not specified, it defaults to NotRequired. - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Compute Resources required by this container. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - restartPolicy: - description: |- - RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, - the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: - this init container will be continually restarted on - exit until all regular containers have terminated. Once all regular - containers have completed, all init containers with restartPolicy "Always" - will be shut down. This lifecycle differs from normal init containers and - is often referred to as a "sidecar" container. Although this init - container still starts in the init container sequence, it does not wait - for the container to complete before proceeding to the next init - container. Instead, the next init container starts immediately after this - init container is started, or after any startupProbe has successfully - completed. - type: string - securityContext: - description: |- - SecurityContext defines the security options the container should be run with. - If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - properties: - allowPrivilegeEscalation: - description: |- - AllowPrivilegeEscalation controls whether a process can gain more - privileges than its parent process. This bool directly controls if - the no_new_privs flag will be set on the container process. - AllowPrivilegeEscalation is true always when the container is: - 1) run as Privileged - 2) has CAP_SYS_ADMIN - Note that this field cannot be set when spec.os.name is windows. - type: boolean - capabilities: - description: |- - The capabilities to add/drop when running containers. - Defaults to the default set of capabilities granted by the container runtime. - Note that this field cannot be set when spec.os.name is windows. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - drop: - description: Removed capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - type: object - privileged: - description: |- - Run container in privileged mode. - Processes in privileged containers are essentially equivalent to root on the host. - Defaults to false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - procMount: - description: |- - procMount denotes the type of proc mount to use for the containers. - The default is DefaultProcMount which uses the container runtime defaults for - readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. - Note that this field cannot be set when spec.os.name is windows. - type: string - readOnlyRootFilesystem: - description: |- - Whether this container has a read-only root filesystem. - Default is false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to the container. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label - that applies to the container. - type: string - role: - description: Role is a SELinux role label - that applies to the container. - type: string - type: - description: Type is a SELinux type label - that applies to the container. - type: string - user: - description: User is a SELinux user label - that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by this container. If seccomp options are - provided at both the pod & container level, the container options - override the pod options. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options from the PodSecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the - name of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: |- - StartupProbe indicates that the Pod has successfully initialized. - If specified, no other probes are executed until this completes successfully. - If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. - This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, - when it might take a long time to load data or warm a cache, than during steady-state operation. - This cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - stdin: - description: |- - Whether this container should allocate a buffer for stdin in the container runtime. If this - is not set, reads from stdin in the container will always result in EOF. - Default is false. - type: boolean - stdinOnce: - description: |- - Whether the container runtime should close the stdin channel after it has been opened by - a single attach. When stdin is true the stdin stream will remain open across multiple attach - sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - first client attaches to stdin, and then remains open and accepts data until the client disconnects, - at which time stdin is closed and remains closed until the container is restarted. If this - flag is false, a container processes that reads from stdin will never receive an EOF. - Default is false - type: boolean - terminationMessagePath: - description: |- - Optional: Path at which the file to which the container's termination message - will be written is mounted into the container's filesystem. - Message written is intended to be brief final status, such as an assertion failure message. - Will be truncated by the node if greater than 4096 bytes. The total message length across - all containers will be limited to 12kb. - Defaults to /dev/termination-log. - Cannot be updated. - type: string - terminationMessagePolicy: - description: |- - Indicate how the termination message should be populated. File will use the contents of - terminationMessagePath to populate the container status message on both success and failure. - FallbackToLogsOnError will use the last chunk of container log output if the termination - message file is empty and the container exited with an error. - The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - Defaults to File. - Cannot be updated. - type: string - tty: - description: |- - Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices - to be used by the container. - items: - description: volumeDevice describes a mapping of - a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside of - the container that the device will be mapped - to. - type: string - name: - description: name must match the name of a persistentVolumeClaim - in the pod - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - description: |- - Pod volumes to mount into the container's filesystem. - Cannot be updated. - items: - description: VolumeMount describes a mounting of - a Volume within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - workingDir: - description: |- - Container's working directory. - If not specified, the container runtime's default will be used, which - might be configured in the container image. - Cannot be updated. - type: string - required: - - name - type: object - type: array - nodeName: - description: |- - NodeName is a request to schedule this pod onto a specific node. If it is non-empty, - the scheduler simply schedules this pod onto that node, assuming that it fits resource - requirements. - type: string - nodeSelector: - additionalProperties: - type: string - description: |- - NodeSelector is a selector which must be true for the pod to fit on a node. - Selector which must match a node's labels for the pod to be scheduled on that node. - More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - type: object - x-kubernetes-map-type: atomic - os: - description: |- - Specifies the OS of the containers in the pod. - Some pod and container fields are restricted if this is set. - - - If the OS field is set to linux, the following fields must be unset: - -securityContext.windowsOptions - - - If the OS field is set to windows, following fields must be unset: - - spec.hostPID - - spec.hostIPC - - spec.hostUsers - - spec.securityContext.seLinuxOptions - - spec.securityContext.seccompProfile - - spec.securityContext.fsGroup - - spec.securityContext.fsGroupChangePolicy - - spec.securityContext.sysctls - - spec.shareProcessNamespace - - spec.securityContext.runAsUser - - spec.securityContext.runAsGroup - - spec.securityContext.supplementalGroups - - spec.containers[*].securityContext.seLinuxOptions - - spec.containers[*].securityContext.seccompProfile - - spec.containers[*].securityContext.capabilities - - spec.containers[*].securityContext.readOnlyRootFilesystem - - spec.containers[*].securityContext.privileged - - spec.containers[*].securityContext.allowPrivilegeEscalation - - spec.containers[*].securityContext.procMount - - spec.containers[*].securityContext.runAsUser - - spec.containers[*].securityContext.runAsGroup - properties: - name: - description: |- - Name is the name of the operating system. The currently supported values are linux and windows. - Additional value may be defined in future and can be one of: - https://github.com/opencontainers/runtime-spec/blob/master/config.md#platform-specific-configuration - Clients should expect to handle additional values and treat unrecognized values in this field as os: null - type: string - required: - - name - type: object - overhead: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Overhead represents the resource overhead associated with running a pod for a given RuntimeClass. - This field will be autopopulated at admission time by the RuntimeClass admission controller. If - the RuntimeClass admission controller is enabled, overhead must not be set in Pod create requests. - The RuntimeClass admission controller will reject Pod create requests which have the overhead already - set. If RuntimeClass is configured and selected in the PodSpec, Overhead will be set to the value - defined in the corresponding RuntimeClass, otherwise it will remain unset and treated as zero. - More info: https://git.k8s.io/enhancements/keps/sig-node/688-pod-overhead/README.md - type: object - preemptionPolicy: - description: |- - PreemptionPolicy is the Policy for preempting pods with lower priority. - One of Never, PreemptLowerPriority. - Defaults to PreemptLowerPriority if unset. - type: string - priority: - description: |- - The priority value. Various system components use this field to find the - priority of the pod. When Priority Admission Controller is enabled, it - prevents users from setting this field. The admission controller populates - this field from PriorityClassName. - The higher the value, the higher the priority. - format: int32 - type: integer - priorityClassName: - description: |- - If specified, indicates the pod's priority. "system-node-critical" and - "system-cluster-critical" are two special keywords which indicate the - highest priorities with the former being the highest priority. Any other - name must be defined by creating a PriorityClass object with that name. - If not specified, the pod priority will be default or zero if there is no - default. - type: string - readinessGates: - description: |- - If specified, all readiness gates will be evaluated for pod readiness. - A pod is ready when all its containers are ready AND - all conditions specified in the readiness gates have status equal to "True" - More info: https://git.k8s.io/enhancements/keps/sig-network/580-pod-readiness-gates - items: - description: PodReadinessGate contains the reference to - a pod condition - properties: - conditionType: - description: ConditionType refers to a condition in - the pod's condition list with matching type. - type: string - required: - - conditionType - type: object - type: array - resourceClaims: - description: |- - ResourceClaims defines which ResourceClaims must be allocated - and reserved before the Pod is allowed to start. The resources - will be made available to those containers which consume them - by name. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. - items: - description: |- - PodResourceClaim references exactly one ResourceClaim through a ClaimSource. - It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. - Containers that need access to the ResourceClaim reference it with this name. - properties: - name: - description: |- - Name uniquely identifies this resource claim inside the pod. - This must be a DNS_LABEL. - type: string - source: - description: Source describes where to find the ResourceClaim. - properties: - resourceClaimName: - description: |- - ResourceClaimName is the name of a ResourceClaim object in the same - namespace as this pod. - type: string - resourceClaimTemplateName: - description: |- - ResourceClaimTemplateName is the name of a ResourceClaimTemplate - object in the same namespace as this pod. - - - The template will be used to create a new ResourceClaim, which will - be bound to this pod. When this pod is deleted, the ResourceClaim - will also be deleted. The pod name and resource name, along with a - generated component, will be used to form a unique name for the - ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses. - - - This field is immutable and no changes will be made to the - corresponding ResourceClaim by the control plane after creating the - ResourceClaim. - type: string - type: object - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - restartPolicy: - description: |- - Restart policy for all containers within the pod. - One of Always, OnFailure, Never. In some contexts, only a subset of those values may be permitted. - Default to Always. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy - type: string - runtimeClassName: - description: |- - RuntimeClassName refers to a RuntimeClass object in the node.k8s.io group, which should be used - to run this pod. If no RuntimeClass resource matches the named class, the pod will not be run. - If unset or empty, the "legacy" RuntimeClass will be used, which is an implicit class with an - empty definition that uses the default runtime handler. - More info: https://git.k8s.io/enhancements/keps/sig-node/585-runtime-class - type: string - schedulerName: - description: |- - If specified, the pod will be dispatched by specified scheduler. - If not specified, the pod will be dispatched by default scheduler. - type: string - schedulingGates: - description: |- - SchedulingGates is an opaque list of values that if specified will block scheduling the pod. - If schedulingGates is not empty, the pod will stay in the SchedulingGated state and the - scheduler will not attempt to schedule the pod. - - - SchedulingGates can only be set at pod creation time, and be removed only afterwards. - - - This is a beta feature enabled by the PodSchedulingReadiness feature gate. - items: - description: PodSchedulingGate is associated to a Pod - to guard its scheduling. - properties: - name: - description: |- - Name of the scheduling gate. - Each scheduling gate must have a unique name field. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - securityContext: - description: |- - SecurityContext holds pod-level security attributes and common container settings. - Optional: Defaults to empty. See type description for default values of each field. - properties: - fsGroup: - description: |- - A special supplemental group that applies to all containers in a pod. - Some volume types allow the Kubelet to change the ownership of that volume - to be owned by the pod: - - - 1. The owning GID will be the FSGroup - 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) - 3. The permission bits are OR'd with rw-rw---- - - - If unset, the Kubelet will not modify the ownership and permissions of any volume. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - fsGroupChangePolicy: - description: |- - fsGroupChangePolicy defines behavior of changing ownership and permission of the volume - before being exposed inside Pod. This field will only apply to - volume types which support fsGroup based ownership(and permissions). - It will have no effect on ephemeral volume types such as: secret, configmaps - and emptydir. - Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. - Note that this field cannot be set when spec.os.name is windows. - type: string - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to all containers. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in SecurityContext. If set in - both SecurityContext and PodSecurityContext, the value specified in SecurityContext - takes precedence for that container. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label that applies - to the container. - type: string - role: - description: Role is a SELinux role label that applies - to the container. - type: string - type: - description: Type is a SELinux type label that applies - to the container. - type: string - user: - description: User is a SELinux user label that applies - to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by the containers in this pod. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - supplementalGroups: - description: |- - A list of groups applied to the first process run in each container, in addition - to the container's primary GID, the fsGroup (if specified), and group memberships - defined in the container image for the uid of the container process. If unspecified, - no additional groups are added to any container. Note that group memberships - defined in the container image for the uid of the container process are still effective, - even if they are not included in this list. - Note that this field cannot be set when spec.os.name is windows. - items: - format: int64 - type: integer - type: array - sysctls: - description: |- - Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported - sysctls (by the container runtime) might fail to launch. - Note that this field cannot be set when spec.os.name is windows. - items: - description: Sysctl defines a kernel parameter to - be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options within a container's SecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name - of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - serviceAccount: - description: |- - DeprecatedServiceAccount is a depreciated alias for ServiceAccountName. - Deprecated: Use serviceAccountName instead. - type: string - serviceAccountName: - description: |- - ServiceAccountName is the name of the ServiceAccount to use to run this pod. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ - type: string - setHostnameAsFQDN: - description: |- - If true the pod's hostname will be configured as the pod's FQDN, rather than the leaf name (the default). - In Linux containers, this means setting the FQDN in the hostname field of the kernel (the nodename field of struct utsname). - In Windows containers, this means setting the registry value of hostname for the registry key HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters to FQDN. - If a pod does not have FQDN, this has no effect. - Default to false. - type: boolean - shareProcessNamespace: - description: |- - Share a single process namespace between all of the containers in a pod. - When this is set containers will be able to view and signal processes from other containers - in the same pod, and the first process in each container will not be assigned PID 1. - HostPID and ShareProcessNamespace cannot both be set. - Optional: Default to false. - type: boolean - subdomain: - description: |- - If specified, the fully qualified Pod hostname will be "...svc.". - If not specified, the pod will not have a domainname at all. - type: string - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - If this value is nil, the default grace period will be used instead. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - Defaults to 30 seconds. - format: int64 - type: integer - tolerations: - description: If specified, the pod's tolerations. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - topologySpreadConstraints: - description: |- - TopologySpreadConstraints describes how a group of pods ought to spread across topology - domains. Scheduler will schedule pods in a way which abides by the constraints. - All topologySpreadConstraints are ANDed. - items: - description: TopologySpreadConstraint specifies how to - spread matching pods among the given topology. - properties: - labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - MatchLabelKeys cannot be set when LabelSelector isn't set. - Keys that don't exist in the incoming pod labels will - be ignored. A null or empty list means only match against labelSelector. - - - This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. - The global minimum is the minimum number of matching pods in an eligible domain - or zero if the number of eligible domains is less than MinDomains. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 2/2/1: - In this case, the global minimum is 1. - | zone1 | zone2 | zone3 | - | P P | P P | P | - - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 2/2/2; - scheduling it onto zone1(zone2) would make the ActualSkew(3-1) on zone1(zone2) - violate MaxSkew(1). - - if MaxSkew is 2, incoming pod can be scheduled onto any zone. - When `whenUnsatisfiable=ScheduleAnyway`, it is used to give higher precedence - to topologies that satisfy it. - It's a required field. Default value is 1 and 0 is not allowed. - format: int32 - type: integer - minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. - And when the number of eligible domains with matching topology keys equals or greater than minDomains, - this value has no effect on scheduling. - As a result, when the number of eligible domains is less than minDomains, - scheduler won't schedule more than maxSkew Pods to those domains. - If value is nil, the constraint behaves as if MinDomains is equal to 1. - Valid values are integers greater than 0. - When value is not nil, WhenUnsatisfiable must be DoNotSchedule. - - - For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same - labelSelector spread as 2/2/2: - | zone1 | zone2 | zone3 | - | P P | P P | P P | - The number of domains is less than 5(MinDomains), so "global minimum" is treated as 0. - In this situation, new pod with the same labelSelector cannot be scheduled, - because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, - it will violate MaxSkew. - - - This is a beta field and requires the MinDomainsInPodTopologySpread feature gate to be enabled (enabled by default). - format: int32 - type: integer - nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. - - - If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. - type: string - nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. - - - If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. - type: string - topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. - Also, we define an eligible domain as a domain whose nodes meet the requirements of - nodeAffinityPolicy and nodeTaintsPolicy. - e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. - And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. - It's a required field. - type: string - whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. - A constraint is considered "Unsatisfiable" for an incoming pod - if and only if every possible node assignment for that pod would violate - "MaxSkew" on some topology. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 3/1/1: - | zone1 | zone2 | zone3 | - | P P P | P | P | - If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled - to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies - MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler - won't make it *more* imbalanced. - It's a required field. - type: string - required: - - maxSkew - - topologyKey - - whenUnsatisfiable - type: object - type: array - x-kubernetes-list-map-keys: - - topologyKey - - whenUnsatisfiable - x-kubernetes-list-type: map - volumes: - description: |- - List of volumes that can be mounted by containers belonging to the pod. - More info: https://kubernetes.io/docs/concepts/storage/volumes - items: - description: Volume represents a named volume in a pod - that may be accessed by any container in the pod. - properties: - awsElasticBlockStore: - description: |- - awsElasticBlockStore represents an AWS Disk resource that is attached to a - kubelet's host machine and then exposed to the pod. - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - properties: - fsType: - description: |- - fsType is the filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - TODO: how do we prevent errors in the filesystem from compromising the machine - type: string - partition: - description: |- - partition is the partition in the volume that you want to mount. - If omitted, the default is to mount by volume name. - Examples: For volume /dev/sda1, you specify the partition as "1". - Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty). - format: int32 - type: integer - readOnly: - description: |- - readOnly value true will force the readOnly setting in VolumeMounts. - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - type: boolean - volumeID: - description: |- - volumeID is unique ID of the persistent disk resource in AWS (Amazon EBS volume). - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - type: string - required: - - volumeID - type: object - azureDisk: - description: azureDisk represents an Azure Data Disk - mount on the host and bind mount to the pod. - properties: - cachingMode: - description: 'cachingMode is the Host Caching - mode: None, Read Only, Read Write.' - type: string - diskName: - description: diskName is the Name of the data - disk in the blob storage - type: string - diskURI: - description: diskURI is the URI of data disk in - the blob storage - type: string - fsType: - description: |- - fsType is Filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - kind: - description: 'kind expected values are Shared: - multiple blob disks per storage account Dedicated: - single blob disk per storage account Managed: - azure managed data disk (only in managed availability - set). defaults to shared' - type: string - readOnly: - description: |- - readOnly Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - required: - - diskName - - diskURI - type: object - azureFile: - description: azureFile represents an Azure File Service - mount on the host and bind mount to the pod. - properties: - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretName: - description: secretName is the name of secret - that contains Azure Storage Account Name and - Key - type: string - shareName: - description: shareName is the azure share Name - type: string - required: - - secretName - - shareName - type: object - cephfs: - description: cephFS represents a Ceph FS mount on - the host that shares a pod's lifetime - properties: - monitors: - description: |- - monitors is Required: Monitors is a collection of Ceph monitors - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - items: - type: string - type: array - path: - description: 'path is Optional: Used as the mounted - root, rather than the full Ceph tree, default - is /' - type: string - readOnly: - description: |- - readOnly is Optional: Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - type: boolean - secretFile: - description: |- - secretFile is Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - type: string - secretRef: - description: |- - secretRef is Optional: SecretRef is reference to the authentication secret for User, default is empty. - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - user: - description: |- - user is optional: User is the rados user name, default is admin - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - type: string - required: - - monitors - type: object - cinder: - description: |- - cinder represents a cinder volume attached and mounted on kubelets host machine. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - type: boolean - secretRef: - description: |- - secretRef is optional: points to a secret object containing parameters used to connect - to OpenStack. - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - volumeID: - description: |- - volumeID used to identify the volume in cinder. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - type: string - required: - - volumeID - type: object - configMap: - description: configMap represents a configMap that - should populate this volume - properties: - defaultMode: - description: |- - defaultMode is optional: mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - Defaults to 0644. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the ConfigMap, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: optional specify whether the ConfigMap - or its keys must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - csi: - description: csi (Container Storage Interface) represents - ephemeral storage that is handled by certain external - CSI drivers (Beta feature). - properties: - driver: - description: |- - driver is the name of the CSI driver that handles this volume. - Consult with your admin for the correct name as registered in the cluster. - type: string - fsType: - description: |- - fsType to mount. Ex. "ext4", "xfs", "ntfs". - If not provided, the empty value is passed to the associated CSI driver - which will determine the default filesystem to apply. - type: string - nodePublishSecretRef: - description: |- - nodePublishSecretRef is a reference to the secret object containing - sensitive information to pass to the CSI driver to complete the CSI - NodePublishVolume and NodeUnpublishVolume calls. - This field is optional, and may be empty if no secret is required. If the - secret object contains more than one secret, all secret references are passed. - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - readOnly: - description: |- - readOnly specifies a read-only configuration for the volume. - Defaults to false (read/write). - type: boolean - volumeAttributes: - additionalProperties: - type: string - description: |- - volumeAttributes stores driver-specific properties that are passed to the CSI - driver. Consult your driver's documentation for supported values. - type: object - required: - - driver - type: object - downwardAPI: - description: downwardAPI represents downward API about - the pod that should populate this volume - properties: - defaultMode: - description: |- - Optional: mode bits to use on created files by default. Must be a - Optional: mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - Defaults to 0644. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - items: - description: Items is a list of downward API volume - file - items: - description: DownwardAPIVolumeFile represents - information to create the file containing - the pod field - properties: - fieldRef: - description: 'Required: Selects a field - of the pod: only annotations, labels, - name and namespace are supported.' - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, - defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - mode: - description: |- - Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: 'Required: Path is the relative - path name of the file to be created. Must - not be absolute or contain the ''..'' - path. Must be utf-8 encoded. The first - item of the relative path must not start - with ''..''' - type: string - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults - to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - required: - - path - type: object - type: array - type: object - emptyDir: - description: |- - emptyDir represents a temporary directory that shares a pod's lifetime. - More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir - properties: - medium: - description: |- - medium represents what type of storage medium should back this directory. - The default is "" which means to use the node's default medium. - Must be an empty string (default) or Memory. - More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir - type: string - sizeLimit: - anyOf: - - type: integer - - type: string - description: |- - sizeLimit is the total amount of local storage required for this EmptyDir volume. - The size limit is also applicable for memory medium. - The maximum usage on memory medium EmptyDir would be the minimum value between - the SizeLimit specified here and the sum of memory limits of all containers in a pod. - The default is nil which means that the limit is undefined. - More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - ephemeral: - description: |- - ephemeral represents a volume that is handled by a cluster storage driver. - The volume's lifecycle is tied to the pod that defines it - it will be created before the pod starts, - and deleted when the pod is removed. - - - Use this if: - a) the volume is only needed while the pod runs, - b) features of normal volumes like restoring from snapshot or capacity - tracking are needed, - c) the storage driver is specified through a storage class, and - d) the storage driver supports dynamic volume provisioning through - a PersistentVolumeClaim (see EphemeralVolumeSource for more - information on the connection between this volume type - and PersistentVolumeClaim). - - - Use PersistentVolumeClaim or one of the vendor-specific - APIs for volumes that persist for longer than the lifecycle - of an individual pod. - - - Use CSI for light-weight local ephemeral volumes if the CSI driver is meant to - be used that way - see the documentation of the driver for - more information. - - - A pod can use both types of ephemeral volumes and - persistent volumes at the same time. - properties: - volumeClaimTemplate: - description: |- - Will be used to create a stand-alone PVC to provision the volume. - The pod in which this EphemeralVolumeSource is embedded will be the - owner of the PVC, i.e. the PVC will be deleted together with the - pod. The name of the PVC will be `-` where - `` is the name from the `PodSpec.Volumes` array - entry. Pod validation will reject the pod if the concatenated name - is not valid for a PVC (for example, too long). - - - An existing PVC with that name that is not owned by the pod - will *not* be used for the pod to avoid using an unrelated - volume by mistake. Starting the pod is then blocked until - the unrelated PVC is removed. If such a pre-created PVC is - meant to be used by the pod, the PVC has to updated with an - owner reference to the pod once the pod exists. Normally - this should not be necessary, but it may be useful when - manually reconstructing a broken cluster. - - - This field is read-only and no changes will be made by Kubernetes - to the PVC after it has been created. - - - Required, must not be nil. - properties: - metadata: - description: |- - May contain labels and annotations that will be copied into the PVC - when creating it. No other fields are allowed and will be rejected during - validation. - properties: - annotations: - additionalProperties: - type: string - type: object - finalizers: - items: - type: string - type: array - labels: - additionalProperties: - type: string - type: object - name: - type: string - namespace: - type: string - type: object - spec: - description: |- - The specification for the PersistentVolumeClaim. The entire content is - copied unchanged into the PVC that gets created from this - template. The same fields as in a PersistentVolumeClaim - are also valid here. - properties: - accessModes: - description: |- - accessModes contains the desired access modes the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 - items: - type: string - type: array - dataSource: - description: |- - dataSource field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) - * An existing PVC (PersistentVolumeClaim) - If the provisioner or an external controller can support the specified data source, - it will create a new volume based on the contents of the specified data source. - When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, - and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. - If the namespace is specified, then dataSourceRef will not be copied to dataSource. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource - being referenced - type: string - name: - description: Name is the name of resource - being referenced - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - description: |- - dataSourceRef specifies the object from which to populate the volume with data, if a non-empty - volume is desired. This may be any object from a non-empty API group (non - core object) or a PersistentVolumeClaim object. - When this field is specified, volume binding will only succeed if the type of - the specified object matches some installed volume populator or dynamic - provisioner. - This field will replace the functionality of the dataSource field and as such - if both fields are non-empty, they must have the same value. For backwards - compatibility, when namespace isn't specified in dataSourceRef, - both fields (dataSource and dataSourceRef) will be set to the same - value automatically if one of them is empty and the other is non-empty. - When namespace is specified in dataSourceRef, - dataSource isn't set to the same value and must be empty. - There are three important differences between dataSource and dataSourceRef: - * While dataSource only allows two specific types of objects, dataSourceRef - allows any non-core object, as well as PersistentVolumeClaim objects. - * While dataSource ignores disallowed values (dropping them), dataSourceRef - preserves all values, and generates an error if a disallowed value is - specified. - * While dataSource only allows local objects, dataSourceRef allows objects - in any namespaces. - (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. - (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource - being referenced - type: string - name: - description: Name is the name of resource - being referenced - type: string - namespace: - description: |- - Namespace is the namespace of resource being referenced - Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. - (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. - type: string - required: - - kind - - name - type: object - resources: - description: |- - resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements - that are lower than previous value but must still be higher than capacity recorded in the - status field of the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - selector: - description: selector is a label query - over volumes to consider for binding. - properties: - matchExpressions: - description: matchExpressions is a - list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - description: |- - storageClassName is the name of the StorageClass required by the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 - type: string - volumeMode: - description: |- - volumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. - type: string - volumeName: - description: volumeName is the binding - reference to the PersistentVolume backing - this claim. - type: string - type: object - required: - - spec - type: object - type: object - fc: - description: fc represents a Fibre Channel resource - that is attached to a kubelet's host machine and - then exposed to the pod. - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - TODO: how do we prevent errors in the filesystem from compromising the machine - type: string - lun: - description: 'lun is Optional: FC target lun number' - format: int32 - type: integer - readOnly: - description: |- - readOnly is Optional: Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - targetWWNs: - description: 'targetWWNs is Optional: FC target - worldwide names (WWNs)' - items: - type: string - type: array - wwids: - description: |- - wwids Optional: FC volume world wide identifiers (wwids) - Either wwids or combination of targetWWNs and lun must be set, but not both simultaneously. - items: - type: string - type: array - type: object - flexVolume: - description: |- - flexVolume represents a generic volume resource that is - provisioned/attached using an exec based plugin. - properties: - driver: - description: driver is the name of the driver - to use for this volume. - type: string - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". The default filesystem depends on FlexVolume script. - type: string - options: - additionalProperties: - type: string - description: 'options is Optional: this field - holds extra command options if any.' - type: object - readOnly: - description: |- - readOnly is Optional: defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef is Optional: secretRef is reference to the secret object containing - sensitive information to pass to the plugin scripts. This may be - empty if no secret object is specified. If the secret object - contains more than one secret, all secrets are passed to the plugin - scripts. - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - required: - - driver - type: object - flocker: - description: flocker represents a Flocker volume attached - to a kubelet's host machine. This depends on the - Flocker control service being running - properties: - datasetName: - description: |- - datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker - should be considered as deprecated - type: string - datasetUUID: - description: datasetUUID is the UUID of the dataset. - This is unique identifier of a Flocker dataset - type: string - type: object - gcePersistentDisk: - description: |- - gcePersistentDisk represents a GCE Disk resource that is attached to a - kubelet's host machine and then exposed to the pod. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - properties: - fsType: - description: |- - fsType is filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - TODO: how do we prevent errors in the filesystem from compromising the machine - type: string - partition: - description: |- - partition is the partition in the volume that you want to mount. - If omitted, the default is to mount by volume name. - Examples: For volume /dev/sda1, you specify the partition as "1". - Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty). - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - format: int32 - type: integer - pdName: - description: |- - pdName is unique name of the PD resource in GCE. Used to identify the disk in GCE. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - type: string - readOnly: - description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - type: boolean - required: - - pdName - type: object - gitRepo: - description: |- - gitRepo represents a git repository at a particular revision. - DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an - EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir - into the Pod's container. - properties: - directory: - description: |- - directory is the target directory name. - Must not contain or start with '..'. If '.' is supplied, the volume directory will be the - git repository. Otherwise, if specified, the volume will contain the git repository in - the subdirectory with the given name. - type: string - repository: - description: repository is the URL - type: string - revision: - description: revision is the commit hash for the - specified revision. - type: string - required: - - repository - type: object - glusterfs: - description: |- - glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. - More info: https://examples.k8s.io/volumes/glusterfs/README.md - properties: - endpoints: - description: |- - endpoints is the endpoint name that details Glusterfs topology. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod - type: string - path: - description: |- - path is the Glusterfs volume path. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod - type: string - readOnly: - description: |- - readOnly here will force the Glusterfs volume to be mounted with read-only permissions. - Defaults to false. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod - type: boolean - required: - - endpoints - - path - type: object - hostPath: - description: |- - hostPath represents a pre-existing file or directory on the host - machine that is directly exposed to the container. This is generally - used for system agents or other privileged things that are allowed - to see the host machine. Most containers will NOT need this. - More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - --- - TODO(jonesdl) We need to restrict who can use host directory mounts and who can/can not - mount host directories as read/write. - properties: - path: - description: |- - path of the directory on the host. - If the path is a symlink, it will follow the link to the real path. - More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - type: string - type: - description: |- - type for HostPath Volume - Defaults to "" - More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - type: string - required: - - path - type: object - iscsi: - description: |- - iscsi represents an ISCSI Disk resource that is attached to a - kubelet's host machine and then exposed to the pod. - More info: https://examples.k8s.io/volumes/iscsi/README.md - properties: - chapAuthDiscovery: - description: chapAuthDiscovery defines whether - support iSCSI Discovery CHAP authentication - type: boolean - chapAuthSession: - description: chapAuthSession defines whether support - iSCSI Session CHAP authentication - type: boolean - fsType: - description: |- - fsType is the filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi - TODO: how do we prevent errors in the filesystem from compromising the machine - type: string - initiatorName: - description: |- - initiatorName is the custom iSCSI Initiator Name. - If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface - : will be created for the connection. - type: string - iqn: - description: iqn is the target iSCSI Qualified - Name. - type: string - iscsiInterface: - description: |- - iscsiInterface is the interface Name that uses an iSCSI transport. - Defaults to 'default' (tcp). - type: string - lun: - description: lun represents iSCSI Target Lun number. - format: int32 - type: integer - portals: - description: |- - portals is the iSCSI Target Portal List. The portal is either an IP or ip_addr:port if the port - is other than default (typically TCP ports 860 and 3260). - items: - type: string - type: array - readOnly: - description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. - type: boolean - secretRef: - description: secretRef is the CHAP Secret for - iSCSI target and initiator authentication - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - targetPortal: - description: |- - targetPortal is iSCSI Target Portal. The Portal is either an IP or ip_addr:port if the port - is other than default (typically TCP ports 860 and 3260). - type: string - required: - - iqn - - lun - - targetPortal - type: object - name: - description: |- - name of the volume. - Must be a DNS_LABEL and unique within the pod. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - nfs: - description: |- - nfs represents an NFS mount on the host that shares a pod's lifetime - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - properties: - path: - description: |- - path that is exported by the NFS server. - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - type: string - readOnly: - description: |- - readOnly here will force the NFS export to be mounted with read-only permissions. - Defaults to false. - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - type: boolean - server: - description: |- - server is the hostname or IP address of the NFS server. - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - type: string - required: - - path - - server - type: object - persistentVolumeClaim: - description: |- - persistentVolumeClaimVolumeSource represents a reference to a - PersistentVolumeClaim in the same namespace. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - properties: - claimName: - description: |- - claimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - type: string - readOnly: - description: |- - readOnly Will force the ReadOnly setting in VolumeMounts. - Default false. - type: boolean - required: - - claimName - type: object - photonPersistentDisk: - description: photonPersistentDisk represents a PhotonController - persistent disk attached and mounted on kubelets - host machine - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - pdID: - description: pdID is the ID that identifies Photon - Controller persistent disk - type: string - required: - - pdID - type: object - portworxVolume: - description: portworxVolume represents a portworx - volume attached and mounted on kubelets host machine - properties: - fsType: - description: |- - fSType represents the filesystem type to mount - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified. - type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - volumeID: - description: volumeID uniquely identifies a Portworx - volume - type: string - required: - - volumeID - type: object - projected: - description: projected items for all in one resources - secrets, configmaps, and downward API - properties: - defaultMode: - description: |- - defaultMode are the mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - sources: - description: sources is the list of volume projections - items: - description: Projection that may be projected - along with other supported volume types - properties: - configMap: - description: configMap information about - the configMap data to project - properties: - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the ConfigMap, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to - a path within a volume. - properties: - key: - description: key is the key to - project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: optional specify whether - the ConfigMap or its keys must be - defined - type: boolean - type: object - x-kubernetes-map-type: atomic - downwardAPI: - description: downwardAPI information about - the downwardAPI data to project - properties: - items: - description: Items is a list of DownwardAPIVolume - file - items: - description: DownwardAPIVolumeFile - represents information to create - the file containing the pod field - properties: - fieldRef: - description: 'Required: Selects - a field of the pod: only annotations, - labels, name and namespace are - supported.' - properties: - apiVersion: - description: Version of the - schema the FieldPath is - written in terms of, defaults - to "v1". - type: string - fieldPath: - description: Path of the field - to select in the specified - API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - mode: - description: |- - Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: 'Required: Path is the - relative path name of the file - to be created. Must not be absolute - or contain the ''..'' path. - Must be utf-8 encoded. The first - item of the relative path must - not start with ''..''' - type: string - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported. - properties: - containerName: - description: 'Container name: - required for volumes, optional - for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the - output format of the exposed - resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource - to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - required: - - path - type: object - type: array - type: object - secret: - description: secret information about the - secret data to project - properties: - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to - a path within a volume. - properties: - key: - description: key is the key to - project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: optional field specify - whether the Secret or its key must - be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - serviceAccountToken: - description: serviceAccountToken is information - about the serviceAccountToken data to - project - properties: - audience: - description: |- - audience is the intended audience of the token. A recipient of a token - must identify itself with an identifier specified in the audience of the - token, and otherwise should reject the token. The audience defaults to the - identifier of the apiserver. - type: string - expirationSeconds: - description: |- - expirationSeconds is the requested duration of validity of the service - account token. As the token approaches expiration, the kubelet volume - plugin will proactively rotate the service account token. The kubelet will - start trying to rotate the token if the token is older than 80 percent of - its time to live or if the token is older than 24 hours.Defaults to 1 hour - and must be at least 10 minutes. - format: int64 - type: integer - path: - description: |- - path is the path relative to the mount point of the file to project the - token into. - type: string - required: - - path - type: object - type: object - type: array - type: object - quobyte: - description: quobyte represents a Quobyte mount on - the host that shares a pod's lifetime - properties: - group: - description: |- - group to map volume access to - Default is no group - type: string - readOnly: - description: |- - readOnly here will force the Quobyte volume to be mounted with read-only permissions. - Defaults to false. - type: boolean - registry: - description: |- - registry represents a single or multiple Quobyte Registry services - specified as a string as host:port pair (multiple entries are separated with commas) - which acts as the central registry for volumes - type: string - tenant: - description: |- - tenant owning the given Quobyte volume in the Backend - Used with dynamically provisioned Quobyte volumes, value is set by the plugin - type: string - user: - description: |- - user to map volume access to - Defaults to serivceaccount user - type: string - volume: - description: volume is a string that references - an already created Quobyte volume by name. - type: string - required: - - registry - - volume - type: object - rbd: - description: |- - rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. - More info: https://examples.k8s.io/volumes/rbd/README.md - properties: - fsType: - description: |- - fsType is the filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd - TODO: how do we prevent errors in the filesystem from compromising the machine - type: string - image: - description: |- - image is the rados image name. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - keyring: - description: |- - keyring is the path to key ring for RBDUser. - Default is /etc/ceph/keyring. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - monitors: - description: |- - monitors is a collection of Ceph monitors. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - items: - type: string - type: array - pool: - description: |- - pool is the rados pool name. - Default is rbd. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - readOnly: - description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: boolean - secretRef: - description: |- - secretRef is name of the authentication secret for RBDUser. If provided - overrides keyring. - Default is nil. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - user: - description: |- - user is the rados user name. - Default is admin. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - required: - - image - - monitors - type: object - scaleIO: - description: scaleIO represents a ScaleIO persistent - volume attached and mounted on Kubernetes nodes. - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". - Default is "xfs". - type: string - gateway: - description: gateway is the host address of the - ScaleIO API Gateway. - type: string - protectionDomain: - description: protectionDomain is the name of the - ScaleIO Protection Domain for the configured - storage. - type: string - readOnly: - description: |- - readOnly Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef references to the secret for ScaleIO user and other - sensitive information. If this is not provided, Login operation will fail. - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - sslEnabled: - description: sslEnabled Flag enable/disable SSL - communication with Gateway, default false - type: boolean - storageMode: - description: |- - storageMode indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. - Default is ThinProvisioned. - type: string - storagePool: - description: storagePool is the ScaleIO Storage - Pool associated with the protection domain. - type: string - system: - description: system is the name of the storage - system as configured in ScaleIO. - type: string - volumeName: - description: |- - volumeName is the name of a volume already created in the ScaleIO system - that is associated with this volume source. - type: string - required: - - gateway - - secretRef - - system - type: object - secret: - description: |- - secret represents a secret that should populate this volume. - More info: https://kubernetes.io/docs/concepts/storage/volumes#secret - properties: - defaultMode: - description: |- - defaultMode is Optional: mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values - for mode bits. Defaults to 0644. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - items: - description: |- - items If unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - optional: - description: optional field specify whether the - Secret or its keys must be defined - type: boolean - secretName: - description: |- - secretName is the name of the secret in the pod's namespace to use. - More info: https://kubernetes.io/docs/concepts/storage/volumes#secret - type: string - type: object - storageos: - description: storageOS represents a StorageOS volume - attached and mounted on Kubernetes nodes. - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef specifies the secret to use for obtaining the StorageOS API - credentials. If not specified, default values will be attempted. - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - volumeName: - description: |- - volumeName is the human-readable name of the StorageOS volume. Volume - names are only unique within a namespace. - type: string - volumeNamespace: - description: |- - volumeNamespace specifies the scope of the volume within StorageOS. If no - namespace is specified then the Pod's namespace will be used. This allows the - Kubernetes name scoping to be mirrored within StorageOS for tighter integration. - Set VolumeName to any name to override the default behaviour. - Set to "default" if you are not using namespaces within StorageOS. - Namespaces that do not pre-exist within StorageOS will be created. - type: string - type: object - vsphereVolume: - description: vsphereVolume represents a vSphere volume - attached and mounted on kubelets host machine - properties: - fsType: - description: |- - fsType is filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - storagePolicyID: - description: storagePolicyID is the storage Policy - Based Management (SPBM) profile ID associated - with the StoragePolicyName. - type: string - storagePolicyName: - description: storagePolicyName is the storage - Policy Based Management (SPBM) profile name. - type: string - volumePath: - description: volumePath is the path that identifies - vSphere volume vmdk - type: string - required: - - volumePath - type: object - required: - - name - type: object - type: array - required: - - containers - type: object - x-kubernetes-preserve-unknown-fields: true - probes: - description: Settings for health checks. - properties: - roleProbe: - description: Specifies the probe used for checking the role - of the component. - properties: - commands: - description: Commands used to execute for probe. - properties: - queries: - description: Defines read checks that are executed - on the probe sidecar. - items: - type: string - type: array - writes: - description: Defines write checks that are executed - on the probe sidecar. - items: - type: string - type: array - type: object - failureThreshold: - default: 3 - description: Minimum consecutive failures for the probe - to be considered failed after having succeeded. - format: int32 - minimum: 2 - type: integer - periodSeconds: - default: 1 - description: How often (in seconds) to perform the probe. - format: int32 - minimum: 1 - type: integer - timeoutSeconds: - default: 1 - description: Number of seconds after which the probe - times out. Defaults to 1 second. - format: int32 - minimum: 1 - type: integer - type: object - roleProbeTimeoutAfterPodsReady: - description: |- - Defines the timeout (in seconds) for the role probe after all pods of the component are ready. - The system will check if the application is available in the pod. - If pods exceed the InitializationTimeoutSeconds time without a role label, this component will enter the - Failed/Abnormal phase. - - - Note that this configuration will only take effect if the component supports RoleProbe - and will not affect the life cycle of the pod. default values are 60 seconds. - format: int32 - minimum: 30 - type: integer - runningProbe: - description: Specifies the probe used for checking the running - status of the component. - properties: - commands: - description: Commands used to execute for probe. - properties: - queries: - description: Defines read checks that are executed - on the probe sidecar. - items: - type: string - type: array - writes: - description: Defines write checks that are executed - on the probe sidecar. - items: - type: string - type: array - type: object - failureThreshold: - default: 3 - description: Minimum consecutive failures for the probe - to be considered failed after having succeeded. - format: int32 - minimum: 2 - type: integer - periodSeconds: - default: 1 - description: How often (in seconds) to perform the probe. - format: int32 - minimum: 1 - type: integer - timeoutSeconds: - default: 1 - description: Number of seconds after which the probe - times out. Defaults to 1 second. - format: int32 - minimum: 1 - type: integer - type: object - statusProbe: - description: Specifies the probe used for checking the status - of the component. - properties: - commands: - description: Commands used to execute for probe. - properties: - queries: - description: Defines read checks that are executed - on the probe sidecar. - items: - type: string - type: array - writes: - description: Defines write checks that are executed - on the probe sidecar. - items: - type: string - type: array - type: object - failureThreshold: - default: 3 - description: Minimum consecutive failures for the probe - to be considered failed after having succeeded. - format: int32 - minimum: 2 - type: integer - periodSeconds: - default: 1 - description: How often (in seconds) to perform the probe. - format: int32 - minimum: 1 - type: integer - timeoutSeconds: - default: 1 - description: Number of seconds after which the probe - times out. Defaults to 1 second. - format: int32 - minimum: 1 - type: integer - type: object - type: object - replicationSpec: - description: Defines spec for `Replication` workloads. - properties: - llPodManagementPolicy: - description: |- - Controls the creation of pods during initial scale up, replacement of pods on nodes, and scaling down. - - - - `OrderedReady`: Creates pods in increasing order (pod-0, then pod-1, etc). The controller waits until each pod - is ready before continuing. Pods are removed in reverse order when scaling down. - - `Parallel`: Creates pods in parallel to match the desired scale without waiting. All pods are deleted at once - when scaling down. - type: string - llUpdateStrategy: - description: |- - Specifies the low-level StatefulSetUpdateStrategy to be used when updating Pods in the StatefulSet upon a - revision to the Template. - `UpdateStrategy` will be ignored if this is provided. - properties: - rollingUpdate: - description: RollingUpdate is used to communicate parameters - when Type is RollingUpdateStatefulSetStrategyType. - properties: - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of pods that can be unavailable during the update. - Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - Absolute number is calculated from percentage by rounding up. This can not be 0. - Defaults to 1. This field is alpha-level and is only honored by servers that enable the - MaxUnavailableStatefulSet feature. The field applies to all pods in the range 0 to - Replicas-1. That means if there is any unavailable pod in the range 0 to Replicas-1, it - will be counted towards MaxUnavailable. - x-kubernetes-int-or-string: true - partition: - description: |- - Partition indicates the ordinal at which the StatefulSet should be partitioned - for updates. During a rolling update, all pods from ordinal Replicas-1 to - Partition are updated. All pods from ordinal Partition-1 to 0 remain untouched. - This is helpful in being able to do a canary based deployment. The default value is 0. - format: int32 - type: integer - type: object - type: - description: |- - Type indicates the type of the StatefulSetUpdateStrategy. - Default is RollingUpdate. - type: string - type: object - updateStrategy: - default: Serial - description: |- - Specifies the strategy for updating Pods. - For workloadType=`Consensus`, the update strategy can be one of the following: - - - - `Serial`: Updates Members sequentially to minimize component downtime. - - `BestEffortParallel`: Updates Members in parallel to minimize component write downtime. Majority remains online - at all times. - - `Parallel`: Forces parallel updates. - enum: - - Serial - - BestEffortParallel - - Parallel - type: string - type: object - rsmSpec: - description: |- - Defines workload spec of this component. - From KB 0.7.0, RSM(InstanceSetSpec) will be the underlying CR which powers all kinds of workload in KB. - RSM is an enhanced stateful workload extension dedicated for heavy-state workloads like databases. - properties: - memberUpdateStrategy: - description: |- - Describes the strategy for updating Members (Pods). - - - - `Serial`: Updates Members sequentially to ensure minimum component downtime. - - `BestEffortParallel`: Updates Members in parallel to ensure minimum component write downtime. - - `Parallel`: Forces parallel updates. - enum: - - Serial - - BestEffortParallel - - Parallel - type: string - membershipReconfiguration: - description: Indicates the actions required for dynamic - membership reconfiguration. - properties: - logSyncAction: - description: |- - Defines the action to trigger the new member to start log syncing. - If the Image is not configured, the Image from the previous non-nil action will be used. - properties: - args: - description: Additional parameters used to perform - specific statements. This field is optional. - items: - type: string - type: array - command: - description: A set of instructions that will be - executed within the Container to retrieve or process - role information. This field is required. - items: - type: string - type: array - image: - description: Refers to the utility image that contains - the command which can be utilized to retrieve - or process role information. - type: string - required: - - command - type: object - memberJoinAction: - description: |- - Defines the action to add a member. - If the Image is not configured, the Image from the previous non-nil action will be used. - properties: - args: - description: Additional parameters used to perform - specific statements. This field is optional. - items: - type: string - type: array - command: - description: A set of instructions that will be - executed within the Container to retrieve or process - role information. This field is required. - items: - type: string - type: array - image: - description: Refers to the utility image that contains - the command which can be utilized to retrieve - or process role information. - type: string - required: - - command - type: object - memberLeaveAction: - description: |- - Defines the action to remove a member. - If the Image is not configured, the Image from the previous non-nil action will be used. - properties: - args: - description: Additional parameters used to perform - specific statements. This field is optional. - items: - type: string - type: array - command: - description: A set of instructions that will be - executed within the Container to retrieve or process - role information. This field is required. - items: - type: string - type: array - image: - description: Refers to the utility image that contains - the command which can be utilized to retrieve - or process role information. - type: string - required: - - command - type: object - promoteAction: - description: |- - Defines the action to inform the cluster that the new member can join voting now. - If the Image is not configured, the Image from the previous non-nil action will be used. - properties: - args: - description: Additional parameters used to perform - specific statements. This field is optional. - items: - type: string - type: array - command: - description: A set of instructions that will be - executed within the Container to retrieve or process - role information. This field is required. - items: - type: string - type: array - image: - description: Refers to the utility image that contains - the command which can be utilized to retrieve - or process role information. - type: string - required: - - command - type: object - switchoverAction: - description: |- - Specifies the environment variables that can be used in all following Actions: - - KB_ITS_USERNAME: Represents the username part of the credential - - KB_ITS_PASSWORD: Represents the password part of the credential - - KB_ITS_LEADER_HOST: Represents the leader host - - KB_ITS_TARGET_HOST: Represents the target host - - KB_ITS_SERVICE_PORT: Represents the service port - - - Defines the action to perform a switchover. - If the Image is not configured, the latest [BusyBox](https://busybox.net/) image will be used. - properties: - args: - description: Additional parameters used to perform - specific statements. This field is optional. - items: - type: string - type: array - command: - description: A set of instructions that will be - executed within the Container to retrieve or process - role information. This field is required. - items: - type: string - type: array - image: - description: Refers to the utility image that contains - the command which can be utilized to retrieve - or process role information. - type: string - required: - - command - type: object - type: object - roleProbe: - description: Defines the method used to probe a role. - properties: - builtinHandlerName: - description: |- - Specifies the builtin handler name to use to probe the role of the main container. - Available handlers include: mysql, postgres, mongodb, redis, etcd, kafka. - Use CustomHandler to define a custom role probe function if none of the built-in handlers meet the requirement. - type: string - customHandler: - description: |- - Defines a custom method for role probing. - If the BuiltinHandler meets the requirement, use it instead. - Actions defined here are executed in series. - Upon completion of all actions, the final output should be a single string representing the role name defined in spec.Roles. - The latest [BusyBox](https://busybox.net/) image will be used if Image is not configured. - Environment variables can be used in Command: - - v_KB_ITS_LAST_STDOUT: stdout from the last action, watch for 'v_' prefix - - KB_ITS_USERNAME: username part of the credential - - KB_ITS_PASSWORD: password part of the credential - items: - properties: - args: - description: Additional parameters used to perform - specific statements. This field is optional. - items: - type: string - type: array - command: - description: A set of instructions that will be - executed within the Container to retrieve or - process role information. This field is required. - items: - type: string - type: array - image: - description: Refers to the utility image that - contains the command which can be utilized to - retrieve or process role information. - type: string - required: - - command - type: object - type: array - failureThreshold: - default: 3 - description: Specifies the minimum number of consecutive - failures for the probe to be considered failed after - having succeeded. - format: int32 - minimum: 1 - type: integer - initialDelaySeconds: - default: 0 - description: Specifies the number of seconds to wait - after the container has started before initiating - role probing. - format: int32 - minimum: 0 - type: integer - periodSeconds: - default: 2 - description: Specifies the frequency (in seconds) of - probe execution. - format: int32 - minimum: 1 - type: integer - roleUpdateMechanism: - default: ReadinessProbeEventUpdate - description: Specifies the method for updating the pod - role label. - enum: - - ReadinessProbeEventUpdate - - DirectAPIServerEventUpdate - type: string - successThreshold: - default: 1 - description: Specifies the minimum number of consecutive - successes for the probe to be considered successful - after having failed. - format: int32 - minimum: 1 - type: integer - timeoutSeconds: - default: 1 - description: Specifies the number of seconds after which - the probe times out. - format: int32 - minimum: 1 - type: integer - type: object - roles: - description: Specifies a list of roles defined within the - system. - items: - properties: - accessMode: - default: ReadWrite - description: Specifies the service capabilities of - this member. - enum: - - None - - Readonly - - ReadWrite - type: string - canVote: - default: true - description: Indicates if this member has voting rights. - type: boolean - isLeader: - default: false - description: Determines if this member is the leader. - type: boolean - name: - default: leader - description: Defines the role name of the replica. - type: string - required: - - accessMode - - name - type: object - type: array - type: object - statefulSpec: - description: Defines spec for `Stateful` workloads. - properties: - llPodManagementPolicy: - description: |- - Controls the creation of pods during initial scale up, replacement of pods on nodes, and scaling down. - - - - `OrderedReady`: Creates pods in increasing order (pod-0, then pod-1, etc). The controller waits until each pod - is ready before continuing. Pods are removed in reverse order when scaling down. - - `Parallel`: Creates pods in parallel to match the desired scale without waiting. All pods are deleted at once - when scaling down. - type: string - llUpdateStrategy: - description: |- - Specifies the low-level StatefulSetUpdateStrategy to be used when updating Pods in the StatefulSet upon a - revision to the Template. - `UpdateStrategy` will be ignored if this is provided. - properties: - rollingUpdate: - description: RollingUpdate is used to communicate parameters - when Type is RollingUpdateStatefulSetStrategyType. - properties: - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of pods that can be unavailable during the update. - Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - Absolute number is calculated from percentage by rounding up. This can not be 0. - Defaults to 1. This field is alpha-level and is only honored by servers that enable the - MaxUnavailableStatefulSet feature. The field applies to all pods in the range 0 to - Replicas-1. That means if there is any unavailable pod in the range 0 to Replicas-1, it - will be counted towards MaxUnavailable. - x-kubernetes-int-or-string: true - partition: - description: |- - Partition indicates the ordinal at which the StatefulSet should be partitioned - for updates. During a rolling update, all pods from ordinal Replicas-1 to - Partition are updated. All pods from ordinal Partition-1 to 0 remain untouched. - This is helpful in being able to do a canary based deployment. The default value is 0. - format: int32 - type: integer - type: object - type: - description: |- - Type indicates the type of the StatefulSetUpdateStrategy. - Default is RollingUpdate. - type: string - type: object - updateStrategy: - default: Serial - description: |- - Specifies the strategy for updating Pods. - For workloadType=`Consensus`, the update strategy can be one of the following: - - - - `Serial`: Updates Members sequentially to minimize component downtime. - - `BestEffortParallel`: Updates Members in parallel to minimize component write downtime. Majority remains online - at all times. - - `Parallel`: Forces parallel updates. - enum: - - Serial - - BestEffortParallel - - Parallel - type: string - type: object - statelessSpec: - description: Defines spec for `Stateless` workloads. - properties: - updateStrategy: - description: Specifies the deployment strategy that will - be used to replace existing pods with new ones. - properties: - rollingUpdate: - description: |- - Rolling update config params. Present only if DeploymentStrategyType = - RollingUpdate. - --- - TODO: Update this to follow our convention for oneOf, whatever we decide it - to be. - properties: - maxSurge: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of pods that can be scheduled above the desired number of - pods. - Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - This can not be 0 if MaxUnavailable is 0. - Absolute number is calculated from percentage by rounding up. - Defaults to 25%. - Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when - the rolling update starts, such that the total number of old and new pods do not exceed - 130% of desired pods. Once old pods have been killed, - new ReplicaSet can be scaled up further, ensuring that total number of pods running - at any time during the update is at most 130% of desired pods. - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of pods that can be unavailable during the update. - Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - Absolute number is calculated from percentage by rounding down. - This can not be 0 if MaxSurge is 0. - Defaults to 25%. - Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods - immediately when the rolling update starts. Once new pods are ready, old ReplicaSet - can be scaled down further, followed by scaling up the new ReplicaSet, ensuring - that the total number of pods available at all times during the update is at - least 70% of desired pods. - x-kubernetes-int-or-string: true - type: object - type: - description: Type of deployment. Can be "Recreate" or - "RollingUpdate". Default is RollingUpdate. - type: string - type: object - type: object - switchoverSpec: - description: |- - Defines command to do switchover. - In particular, when workloadType=Replication, the command defined in switchoverSpec will only be executed under - the condition of cluster.componentSpecs[x].SwitchPolicy.type=Noop. - properties: - withCandidate: - description: Represents the action of switching over to - a specified candidate primary or leader instance. - properties: - cmdExecutorConfig: - description: Specifies the switchover command. - properties: - args: - description: Additional parameters used in the execution - of the command. - items: - type: string - type: array - command: - description: The command to be executed. - items: - type: string - minItems: 1 - type: array - env: - description: A list of environment variables that - will be injected into the command execution context. - items: - description: EnvVar represents an environment - variable present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema - the FieldPath is written in terms - of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to - select in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output - format of the exposed resources, - defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret - in the pod's namespace - properties: - key: - description: The key of the secret - to select from. Must be a valid - secret key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-preserve-unknown-fields: true - image: - description: Specifies the image used to execute - the command. - type: string - required: - - command - - image - type: object - scriptSpecSelectors: - description: |- - Used to select the script that need to be referenced. - When defined, the scripts defined in scriptSpecs can be referenced within the SwitchoverAction.CmdExecutorConfig. - items: - properties: - name: - description: Represents the name of the ScriptSpec - referent. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - required: - - name - type: object - type: array - required: - - cmdExecutorConfig - type: object - withoutCandidate: - description: Represents the action of switching over without - specifying a candidate primary or leader instance. - properties: - cmdExecutorConfig: - description: Specifies the switchover command. - properties: - args: - description: Additional parameters used in the execution - of the command. - items: - type: string - type: array - command: - description: The command to be executed. - items: - type: string - minItems: 1 - type: array - env: - description: A list of environment variables that - will be injected into the command execution context. - items: - description: EnvVar represents an environment - variable present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema - the FieldPath is written in terms - of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to - select in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output - format of the exposed resources, - defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret - in the pod's namespace - properties: - key: - description: The key of the secret - to select from. Must be a valid - secret key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-preserve-unknown-fields: true - image: - description: Specifies the image used to execute - the command. - type: string - required: - - command - - image - type: object - scriptSpecSelectors: - description: |- - Used to select the script that need to be referenced. - When defined, the scripts defined in scriptSpecs can be referenced within the SwitchoverAction.CmdExecutorConfig. - items: - properties: - name: - description: Represents the name of the ScriptSpec - referent. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - required: - - name - type: object - type: array - required: - - cmdExecutorConfig - type: object - type: object - workloadType: - description: |- - Defines the type of the workload. - - - - `Stateless` describes stateless applications. - - `Stateful` describes common stateful applications. - - `Consensus` describes applications based on consensus protocols, such as raft and paxos. - - `Replication` describes applications based on the primary-secondary data replication protocol. - enum: - - Stateless - - Stateful - - Consensus - - Replication - type: string - required: - - name - - workloadType - type: object - x-kubernetes-validations: - - message: componentDefs.consensusSpec(deprecated) or componentDefs.rsmSpec(recommended) - is required when componentDefs.workloadType is Consensus, and - forbidden otherwise - rule: 'has(self.workloadType) && self.workloadType == ''Consensus'' - ? (has(self.consensusSpec) || has(self.rsmSpec)) : !has(self.consensusSpec)' - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map topologies: description: Topologies defines all possible topologies within the cluster. diff --git a/config/crd/bases/apps.kubeblocks.io_clusters.yaml b/config/crd/bases/apps.kubeblocks.io_clusters.yaml index 0abe99e9e9af..a1bb7628553b 100644 --- a/config/crd/bases/apps.kubeblocks.io_clusters.yaml +++ b/config/crd/bases/apps.kubeblocks.io_clusters.yaml @@ -5230,7 +5230,7 @@ spec: type: boolean switchPolicy: description: |- - Defines the strategy for switchover and failover when workloadType is Replication. + Defines the strategy for switchover and failover. Deprecated since v0.9. @@ -13930,7 +13930,7 @@ spec: type: boolean switchPolicy: description: |- - Defines the strategy for switchover and failover when workloadType is Replication. + Defines the strategy for switchover and failover. Deprecated since v0.9. diff --git a/config/crd/bases/apps.kubeblocks.io_opsrequests.yaml b/config/crd/bases/apps.kubeblocks.io_opsrequests.yaml index 282a58c7a9ee..7c703b54575e 100644 --- a/config/crd/bases/apps.kubeblocks.io_opsrequests.yaml +++ b/config/crd/bases/apps.kubeblocks.io_opsrequests.yaml @@ -5022,16 +5022,6 @@ spec: in its current state. maxLength: 1024 type: string - workloadType: - description: |- - Records the workload type of Component in ClusterDefinition. - Deprecated and should be removed in the future version. - enum: - - Stateless - - Stateful - - Consensus - - Replication - type: string type: object description: Records the status information of Components changed due to the OpsRequest. diff --git a/controllers/apps/cluster_controller_test.go b/controllers/apps/cluster_controller_test.go index 2d916c97491c..1077b7cdb3b4 100644 --- a/controllers/apps/cluster_controller_test.go +++ b/controllers/apps/cluster_controller_test.go @@ -48,15 +48,14 @@ import ( var _ = Describe("Cluster Controller", func() { const ( - clusterDefName = "test-clusterdef" - compDefName = "test-compdef" - compVersionName = "test-compversion" - clusterName = "test-cluster" - defaultCompName = "default" - defaultClusterCompDefName = "default" // TODO: remove this - defaultServiceVersion = "8.0.31-r0" - latestServiceVersion = "8.0.31-r1" - defaultShardCount = 2 + clusterDefName = "test-clusterdef" + compDefName = "test-compdef" + compVersionName = "test-compver" + clusterName = "test-cluster" + defaultCompName = "mysql" + defaultServiceVersion = "8.0.31-r0" + latestServiceVersion = "8.0.31-r1" + defaultShardCount = 2 ) var ( @@ -173,13 +172,12 @@ var _ = Describe("Cluster Controller", func() { By("Create a clusterDefinition obj") clusterDefObj = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.ConsensusMySQLComponent, defaultClusterCompDefName). AddClusterTopology(defaultTopology). Create(&testCtx). GetObject() By("Create a bpt obj") - createBackupPolicyTpl(clusterDefObj, compDefObj.Name) + createBackupPolicyTpl(compDefObj.Name) By("Wait objects available") Eventually(testapps.CheckObj(&testCtx, client.ObjectKeyFromObject(compDefObj), @@ -226,13 +224,9 @@ var _ = Describe("Cluster Controller", func() { clusterKey = client.ObjectKeyFromObject(clusterObj) } - componentProcessorWrapper := func(legacy bool, compName, compDefName string, processor ...func(*testapps.MockClusterFactory)) func(f *testapps.MockClusterFactory) { + componentProcessorWrapper := func(compName, compDefName string, processor ...func(*testapps.MockClusterFactory)) func(f *testapps.MockClusterFactory) { return func(f *testapps.MockClusterFactory) { - if legacy { - f.AddComponent(compName, compDefName).SetReplicas(1) - } else { - f.AddComponentV2(compName, compDefName).SetReplicas(1) - } + f.AddComponent(compName, compDefName).SetReplicas(1) for _, p := range processor { if p != nil { p(f) @@ -241,13 +235,9 @@ var _ = Describe("Cluster Controller", func() { } } - shardingComponentProcessorWrapper := func(legacy bool, compName, compDefName string, processor ...func(*testapps.MockClusterFactory)) func(f *testapps.MockClusterFactory) { + shardingComponentProcessorWrapper := func(compName, compDefName string, processor ...func(*testapps.MockClusterFactory)) func(f *testapps.MockClusterFactory) { return func(f *testapps.MockClusterFactory) { - if legacy { - f.AddShardingSpec(compName, compDefName).SetShards(defaultShardCount) - } else { - f.AddShardingSpecV2(compName, compDefName).SetShards(defaultShardCount) - } + f.AddShardingSpec(compName, compDefName).SetShards(defaultShardCount) for _, p := range processor { if p != nil { p(f) @@ -269,7 +259,7 @@ var _ = Describe("Cluster Controller", func() { createClusterObj := func(compName, compDefName string, processor func(*testapps.MockClusterFactory)) { By("Creating a cluster with new component definition") - createClusterObjNoWait("", componentProcessorWrapper(false, compName, compDefName, processor)) + createClusterObjNoWait("", componentProcessorWrapper(compName, compDefName, processor)) By("Waiting for the cluster enter Creating phase") Eventually(testapps.GetClusterObservedGeneration(&testCtx, clusterKey)).Should(BeEquivalentTo(1)) @@ -286,7 +276,7 @@ var _ = Describe("Cluster Controller", func() { createClusterObjWithTopology := func(topology, compName string, processor func(*testapps.MockClusterFactory)) { By("Creating a cluster with new component definition") setTopology := func(f *testapps.MockClusterFactory) { f.SetTopology(topology) } - createClusterObjNoWait(clusterDefObj.Name, componentProcessorWrapper(false, compName, "", setTopology, processor)) + createClusterObjNoWait(clusterDefObj.Name, componentProcessorWrapper(compName, "", setTopology, processor)) By("Waiting for the cluster enter Creating phase") Eventually(testapps.GetClusterObservedGeneration(&testCtx, clusterKey)).Should(BeEquivalentTo(1)) @@ -300,25 +290,9 @@ var _ = Describe("Cluster Controller", func() { Eventually(testapps.CheckObjExists(&testCtx, compKey, &appsv1alpha1.Component{}, true)).Should(Succeed()) } - createLegacyClusterObj := func(compName, compDefName string, processor func(*testapps.MockClusterFactory)) { - By("Creating a cluster") - createClusterObjNoWait(clusterDefObj.Name, componentProcessorWrapper(true, compName, compDefName, processor)) - - By("Waiting for the cluster enter Creating phase") - Eventually(testapps.GetClusterObservedGeneration(&testCtx, clusterKey)).Should(BeEquivalentTo(1)) - Eventually(testapps.GetClusterPhase(&testCtx, clusterKey)).Should(Equal(appsv1alpha1.CreatingClusterPhase)) - - By("Wait component created") - compKey := types.NamespacedName{ - Namespace: clusterObj.Namespace, - Name: constant.GenerateClusterComponentName(clusterObj.Name, compName), - } - Eventually(testapps.CheckObjExists(&testCtx, compKey, &appsv1alpha1.Component{}, true)).Should(Succeed()) - } - createClusterObjWithSharding := func(compTplName, compDefName string, processor func(*testapps.MockClusterFactory)) { By("Creating a cluster with new component definition") - createClusterObjNoWait("", shardingComponentProcessorWrapper(false, compTplName, compDefName, processor)) + createClusterObjNoWait("", shardingComponentProcessorWrapper(compTplName, compDefName, processor)) By("Waiting for the cluster enter Creating phase") Eventually(testapps.GetClusterObservedGeneration(&testCtx, clusterKey)).Should(BeEquivalentTo(1)) @@ -346,23 +320,6 @@ var _ = Describe("Cluster Controller", func() { &dpv1alpha1.BackupSchedule{}, true)).Should(Succeed()) } - createLegacyClusterObjWithSharding := func(compTplName, compDefName string, processor func(*testapps.MockClusterFactory)) { - By("Creating a cluster") - createClusterObjNoWait(clusterDefObj.Name, shardingComponentProcessorWrapper(true, compTplName, compDefName, processor)) - - By("Waiting for the cluster enter Creating phase") - Eventually(testapps.GetClusterObservedGeneration(&testCtx, clusterKey)).Should(BeEquivalentTo(1)) - Eventually(testapps.GetClusterPhase(&testCtx, clusterKey)).Should(Equal(appsv1alpha1.CreatingClusterPhase)) - - By("Wait component created") - ml := client.MatchingLabels{ - constant.AppInstanceLabelKey: clusterKey.Name, - constant.KBAppShardingNameLabelKey: compTplName, - } - Eventually(testapps.List(&testCtx, generics.ComponentSignature, - ml, client.InNamespace(clusterKey.Namespace))).Should(HaveLen(defaultShardCount)) - } - createClusterObjWithMultipleTemplates := func(compName, compDefName string, processor func(*testapps.MockClusterFactory)) { By("Creating a cluster with new component definition") createClusterObjNoWait("", multipleTemplateComponentProcessorWrapper(compName, compDefName, processor)) @@ -389,18 +346,6 @@ var _ = Describe("Cluster Controller", func() { })).Should(Succeed()) } - testCluster := func(compName, compDefName string) { - clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). - AddComponent(defaultCompName, defaultClusterCompDefName).SetReplicas(3). - WithRandomName(). - Create(&testCtx). - GetObject() - clusterKey = client.ObjectKeyFromObject(clusterObj) - - By("waiting for the cluster controller to create resources completely") - waitForCreatingResourceCompletely(clusterKey, defaultCompName) - } - testClusterComponent := func(compName, compDefName string, createObj func(string, string, func(*testapps.MockClusterFactory))) { createObj(compName, compDefName, nil) @@ -466,10 +411,10 @@ var _ = Describe("Cluster Controller", func() { otherCompName := fmt.Sprintf("%s-a", compName) By("creating and checking a cluster with multi component") - clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). + clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). + WithRandomName(). AddComponent(compName, compDefName).SetReplicas(3). AddComponent(otherCompName, compDefName).SetReplicas(3). - WithRandomName(). Create(&testCtx). GetObject() clusterKey = client.ObjectKeyFromObject(clusterObj) @@ -1071,22 +1016,10 @@ var _ = Describe("Cluster Controller", func() { cleanEnv() }) - It("create cluster", func() { - testCluster(defaultCompName, defaultClusterCompDefName) - }) - - It("create cluster with legacy component", func() { - testClusterComponent(defaultCompName, defaultClusterCompDefName, createLegacyClusterObj) - }) - It("create cluster", func() { testClusterComponent(defaultCompName, compDefObj.Name, createClusterObj) }) - It("create sharding cluster with legacy component", func() { - testShardingClusterComponent(defaultCompName, defaultClusterCompDefName, createLegacyClusterObjWithSharding, defaultShardCount) - }) - It("create sharding cluster", func() { testShardingClusterComponent(defaultCompName, compDefObj.Name, createClusterObjWithSharding, defaultShardCount) }) @@ -1121,7 +1054,7 @@ var _ = Describe("Cluster Controller", func() { }) It("with cluster component scale-in", func() { - testClusterComponentScaleIn(defaultCompName, defaultClusterCompDefName) + testClusterComponentScaleIn(defaultCompName, compDefObj.Name) }) It("with cluster sharding scale-in", func() { @@ -1131,12 +1064,7 @@ var _ = Describe("Cluster Controller", func() { Context("cluster termination policy", func() { var ( - createObjV1 = func(policyType appsv1alpha1.TerminationPolicyType) { - createLegacyClusterObj(defaultCompName, defaultClusterCompDefName, func(f *testapps.MockClusterFactory) { - f.SetTerminationPolicy(policyType) - }) - } - createObjV2 = func(policyType appsv1alpha1.TerminationPolicyType) { + createObj = func(policyType appsv1alpha1.TerminationPolicyType) { createClusterObj(defaultCompName, compDefObj.Name, func(f *testapps.MockClusterFactory) { f.SetTerminationPolicy(policyType) }) @@ -1151,35 +1079,33 @@ var _ = Describe("Cluster Controller", func() { cleanEnv() }) - for _, createObj := range []func(appsv1alpha1.TerminationPolicyType){createObjV1, createObjV2} { - It("deleted after all the sub-resources", func() { - testClusterFinalizer(defaultCompName, createObj) - }) + It("deleted after all the sub-resources", func() { + testClusterFinalizer(defaultCompName, createObj) + }) - It("delete cluster with terminationPolicy=DoNotTerminate", func() { - testDeleteClusterWithDoNotTerminate(createObj) - }) + It("delete cluster with terminationPolicy=DoNotTerminate", func() { + testDeleteClusterWithDoNotTerminate(createObj) + }) - It("delete cluster with terminationPolicy=Halt", func() { - testDeleteClusterWithHalt(createObj) - }) + It("delete cluster with terminationPolicy=Halt", func() { + testDeleteClusterWithHalt(createObj) + }) - It("cluster Halt and Recovery", func() { - testClusterHaltNRecovery(createObj) - }) + It("cluster Halt and Recovery", func() { + testClusterHaltNRecovery(createObj) + }) - It("delete cluster with terminationPolicy=Delete", func() { - testDeleteClusterWithDelete(createObj) - }) + It("delete cluster with terminationPolicy=Delete", func() { + testDeleteClusterWithDelete(createObj) + }) - It("delete cluster with terminationPolicy=WipeOut and backupRetainPolicy=Delete", func() { - testDeleteClusterWithWipeOut(createObj, constant.BackupDelete) - }) + It("delete cluster with terminationPolicy=WipeOut and backupRetainPolicy=Delete", func() { + testDeleteClusterWithWipeOut(createObj, constant.BackupDelete) + }) - It("delete cluster with terminationPolicy=WipeOut and backupRetainPolicy=Retain", func() { - testDeleteClusterWithWipeOut(createObj, constant.BackupRetain) - }) - } + It("delete cluster with terminationPolicy=WipeOut and backupRetainPolicy=Retain", func() { + testDeleteClusterWithWipeOut(createObj, constant.BackupRetain) + }) }) Context("cluster status", func() { @@ -1193,8 +1119,8 @@ var _ = Describe("Cluster Controller", func() { It("test cluster conditions when cluster definition non-exist", func() { By("create a cluster with cluster definition non-exist") - mockCompDefName := fmt.Sprintf("%s-%s", defaultClusterCompDefName, testCtx.GetRandomStr()) - createClusterObjNoWait(clusterDefObj.Name, componentProcessorWrapper(true, defaultCompName, mockCompDefName)) + mockCompDefName := fmt.Sprintf("%s-%s", compDefName, testCtx.GetRandomStr()) + createClusterObjNoWait(clusterDefObj.Name, componentProcessorWrapper(defaultCompName, mockCompDefName)) By("check conditions") Eventually(testapps.CheckObj(&testCtx, clusterKey, func(g Gomega, cluster *appsv1alpha1.Cluster) { @@ -1219,8 +1145,10 @@ var _ = Describe("Cluster Controller", func() { createClusterWithBackup := func(backup *appsv1alpha1.ClusterBackup) { By("Creating a cluster") - clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). - AddComponent(defaultCompName, defaultClusterCompDefName).WithRandomName().SetBackup(backup). + clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). + WithRandomName(). + AddComponent(defaultCompName, compDefName). + SetBackup(backup). Create(&testCtx).GetObject() clusterKey = client.ObjectKeyFromObject(clusterObj) @@ -1382,11 +1310,11 @@ var _ = Describe("Cluster Controller", func() { }) It("with cluster affinity and toleration set", func() { - testClusterAffinityNToleration(defaultCompName, defaultClusterCompDefName, createLegacyClusterObj) + testClusterAffinityNToleration(defaultCompName, compDefName, createClusterObj) }) It("with both cluster and component affinity and toleration set", func() { - testClusterComponentAffinityNToleration(defaultCompName, defaultClusterCompDefName, createLegacyClusterObj) + testClusterComponentAffinityNToleration(defaultCompName, compDefName, createClusterObj) }) }) @@ -1474,31 +1402,22 @@ var _ = Describe("Cluster Controller", func() { }) }) -func createBackupPolicyTpl(clusterDefObj *appsv1alpha1.ClusterDefinition, compDef string) { +func createBackupPolicyTpl(compDef string) { By("create actionSet") - fakeActionSet(clusterDefObj.Name) + fakeActionSet("") By("Creating a BackupPolicyTemplate") bpt := testapps.NewBackupPolicyTemplateFactory(backupPolicyTPLName). - AddLabels(constant.ClusterDefLabelKey, clusterDefObj.Name). - AddLabels(compDef, compDef). - SetClusterDefRef(clusterDefObj.Name) + AddLabels(compDef, compDef) + ttl := "7d" - for _, v := range clusterDefObj.Spec.ComponentDefs { - bpt = bpt.AddBackupPolicy(v.Name). - AddBackupMethod(backupMethodName, false, actionSetName). - SetComponentDef(compDef). - SetBackupMethodVolumeMounts("data", "/data"). - AddBackupMethod(vsBackupMethodName, true, ""). - SetBackupMethodVolumes([]string{"data"}). - AddSchedule(backupMethodName, "0 0 * * *", ttl, true). - AddSchedule(vsBackupMethodName, "0 0 * * *", ttl, true) - switch v.WorkloadType { - case appsv1alpha1.Consensus: - bpt.SetTargetRole("leader") - case appsv1alpha1.Replication: - bpt.SetTargetRole("primary") - } - } + bpt = bpt.AddBackupPolicy(compDef). + AddBackupMethod(backupMethodName, false, actionSetName). + SetComponentDef(compDef). + SetBackupMethodVolumeMounts("data", "/data"). + AddBackupMethod(vsBackupMethodName, true, ""). + SetBackupMethodVolumes([]string{"data"}). + AddSchedule(backupMethodName, "0 0 * * *", ttl, true). + AddSchedule(vsBackupMethodName, "0 0 * * *", ttl, true) bpt.Create(&testCtx) } diff --git a/controllers/apps/clusterdefinition_controller.go b/controllers/apps/clusterdefinition_controller.go index 4df626f5a6eb..7c604ec77da7 100644 --- a/controllers/apps/clusterdefinition_controller.go +++ b/controllers/apps/clusterdefinition_controller.go @@ -73,7 +73,7 @@ func (r *ClusterDefinitionReconciler) Reconcile(ctx context.Context, req ctrl.Re } if clusterDef.Status.ObservedGeneration == clusterDef.Generation && - slices.Contains(clusterDef.Status.GetTerminalPhases(), clusterDef.Status.Phase) { + slices.Contains([]appsv1alpha1.Phase{appsv1alpha1.AvailablePhase}, clusterDef.Status.Phase) { return intctrlutil.Reconciled() } diff --git a/controllers/apps/component_controller_test.go b/controllers/apps/component_controller_test.go index d84e9e00b1e1..645a23dc6f70 100644 --- a/controllers/apps/component_controller_test.go +++ b/controllers/apps/component_controller_test.go @@ -34,7 +34,6 @@ import ( snapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumesnapshot/v1" "github.com/sethvargo/go-password/password" "golang.org/x/exp/maps" - "golang.org/x/exp/slices" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" @@ -66,13 +65,13 @@ import ( ) const ( - backupPolicyTPLName = "test-backup-policy-template-mysql" - backupMethodName = "test-backup-method" - vsBackupMethodName = "test-vs-backup-method" - actionSetName = "test-action-set" + backupMethodName = "test-backup-method" + vsBackupMethodName = "test-vs-backup-method" + actionSetName = "test-action-set" ) var ( + backupPolicyTPLName = "test-backup-policy-template-mysql" podAnnotationKey4Test = fmt.Sprintf("%s-test", constant.ComponentReplicasAnnotationKey) ) @@ -129,36 +128,25 @@ var mockLorryClient4HScale = func(clusterKey types.NamespacedName, compName stri var _ = Describe("Component Controller", func() { const ( - clusterDefName = "test-clusterdef" - compDefName = "test-compdef" - compVerName = "test-compver" - clusterName = "test-cluster" // this become cluster prefix name if used with testapps.NewClusterFactory().WithRandomName() - leader = "leader" - follower = "follower" - // REVIEW: - // - setup componentName and componentDefName as map entry pair - statefulCompName = "stateful" - statefulCompDefName = "stateful" - consensusCompName = "consensus" - consensusCompDefName = "consensus" - replicationCompName = "replication" - replicationCompDefName = "replication" - defaultCompName = "default" + compDefName = "test-compdef" + compVerName = "test-compver" + clusterName = "test-cluster" // this become cluster prefix name if used with testapps.NewClusterFactory().WithRandomName() + leader = "leader" + follower = "follower" + defaultCompName = "default" ) var ( - clusterDefObj *appsv1alpha1.ClusterDefinition - compDefObj *appsv1alpha1.ComponentDefinition - compVerObj *appsv1alpha1.ComponentVersion - clusterObj *appsv1alpha1.Cluster - clusterKey types.NamespacedName - compObj *appsv1alpha1.Component - compKey types.NamespacedName - allSettings map[string]interface{} + compDefObj *appsv1alpha1.ComponentDefinition + compVerObj *appsv1alpha1.ComponentVersion + clusterObj *appsv1alpha1.Cluster + clusterKey types.NamespacedName + compObj *appsv1alpha1.Component + compKey types.NamespacedName + allSettings map[string]interface{} ) resetTestContext := func() { - clusterDefObj = nil compDefObj = nil compVerObj = nil clusterObj = nil @@ -211,14 +199,7 @@ var _ = Describe("Component Controller", func() { } // test function helpers - createAllWorkloadTypesClusterDef := func() { - By("Create a clusterDefinition obj") - clusterDefObj = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatefulMySQLComponent, statefulCompDefName). - AddComponentDef(testapps.ConsensusMySQLComponent, consensusCompDefName). - AddComponentDef(testapps.ReplicationRedisComponent, replicationCompDefName). - Create(&testCtx).GetObject() - + createAllDefinitionObjects := func() { By("Create a componentDefinition obj") compDefObj = testapps.NewComponentDefinitionFactory(compDefName). WithRandomName(). @@ -252,15 +233,12 @@ var _ = Describe("Component Controller", func() { } } - createClusterObjVx := func(clusterDefName, compName, compDefName string, v2 bool, + createClusterObjX := func(clusterDefName, compName, compDefName string, processor func(*testapps.MockClusterFactory), phase *appsv1alpha1.ClusterPhase) { factory := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefName). - WithRandomName() - if !v2 { - factory.AddComponent(compName, compDefName).SetReplicas(1) - } else { - factory.AddComponentV2(compName, compDefName).SetReplicas(1) - } + WithRandomName(). + AddComponent(compName, compDefName). + SetReplicas(1) if processor != nil { processor(factory) } @@ -289,18 +267,13 @@ var _ = Describe("Component Controller", func() { } createClusterObj := func(compName, compDefName string, processor func(*testapps.MockClusterFactory)) { - By("Creating a cluster") - createClusterObjVx(clusterDefObj.Name, compName, compDefName, false, processor, nil) - } - - createClusterObjV2 := func(compName, compDefName string, processor func(*testapps.MockClusterFactory)) { By("Creating a cluster with new component definition") - createClusterObjVx("", compName, compDefName, true, processor, nil) + createClusterObjX("", compName, compDefName, processor, nil) } - createClusterObjV2WithPhase := func(compName, compDefName string, processor func(*testapps.MockClusterFactory), phase appsv1alpha1.ClusterPhase) { + createClusterObjWithPhase := func(compName, compDefName string, processor func(*testapps.MockClusterFactory), phase appsv1alpha1.ClusterPhase) { By("Creating a cluster with new component definition") - createClusterObjVx("", compName, compDefName, true, processor, &phase) + createClusterObjX("", compName, compDefName, processor, &phase) } mockCompRunning := func(compName string) { @@ -356,7 +329,6 @@ var _ = Describe("Component Controller", func() { } testChangeReplicas := func(compName, compDefName string) { - Expect(compDefName).Should(BeElementOf(statefulCompDefName, replicationCompDefName, consensusCompDefName)) createClusterObj(compName, compDefName, nil) replicasSeq := []int32{5, 3, 1, 2, 4} expectedOG := int64(1) @@ -384,7 +356,7 @@ var _ = Describe("Component Controller", func() { target = int32(0) ) - createClusterObjV2(compName, compDefObj.Name, func(f *testapps.MockClusterFactory) { + createClusterObj(compName, compDefName, func(f *testapps.MockClusterFactory) { f.SetReplicas(init) }) @@ -423,7 +395,7 @@ var _ = Describe("Component Controller", func() { } })).Should(Succeed()) - createClusterObjV2(compName, compDefObj.Name, func(f *testapps.MockClusterFactory) { + createClusterObj(compName, compDefName, func(f *testapps.MockClusterFactory) { f.SetReplicas(init) }) @@ -488,8 +460,8 @@ var _ = Describe("Component Controller", func() { } mockPodsForTest := func(cluster *appsv1alpha1.Cluster, number int) []corev1.Pod { - clusterDefName := cluster.Spec.ClusterDefRef componentName := cluster.Spec.ComponentSpecs[0].Name + compDefName := cluster.Spec.ComponentSpecs[0].ComponentDef clusterName := cluster.Name itsName := cluster.Name + "-" + componentName pods := make([]corev1.Pod, 0) @@ -501,7 +473,7 @@ var _ = Describe("Component Controller", func() { Namespace: testCtx.DefaultNamespace, Labels: map[string]string{ constant.AppManagedByLabelKey: constant.AppName, - constant.AppNameLabelKey: clusterDefName, + constant.AppNameLabelKey: compDefName, constant.AppInstanceLabelKey: clusterName, constant.KBAppComponentLabelKey: componentName, appsv1.ControllerRevisionHashLabelKey: "mock-version", @@ -523,8 +495,7 @@ var _ = Describe("Component Controller", func() { return pods } - horizontalScaleComp := func(updatedReplicas int, comp *appsv1alpha1.ClusterComponentSpec, - storageClassName string, policy *appsv1alpha1.HorizontalScalePolicy) { + horizontalScaleComp := func(updatedReplicas int, comp *appsv1alpha1.ClusterComponentSpec, storageClassName string, bpt *string) { By("Mocking component PVCs to bound") mockComponentPVCsAndBound(comp, int(comp.Replicas), true, storageClassName) @@ -534,11 +505,7 @@ var _ = Describe("Component Controller", func() { By("Creating mock pods in InstanceSet") pods := mockPodsForTest(clusterObj, int(comp.Replicas)) - for i, pod := range pods { - if comp.ComponentDefRef == replicationCompDefName && i == 0 { - By("mocking primary for replication to pass check") - pods[0].ObjectMeta.Labels[constant.RoleLabelKey] = "primary" - } + for _, pod := range pods { Expect(testCtx.CheckedCreateObj(testCtx.Ctx, &pod)).Should(Succeed()) Eventually(testapps.GetAndChangeObj(&testCtx, client.ObjectKeyFromObject(&pod), func(p *corev1.Pod) { // mock the status to pass the isReady(pod) check in consensus_set @@ -570,7 +537,7 @@ var _ = Describe("Component Controller", func() { constant.KBAppComponentLabelKey: comp.Name, constant.KBManagedByKey: "cluster", } - if policy != nil { + if bpt != nil { By(fmt.Sprintf("Checking backup of component %s created", comp.Name)) Eventually(testapps.List(&testCtx, generics.BackupSignature, ml, client.InNamespace(clusterKey.Namespace))).Should(HaveLen(1)) @@ -614,11 +581,11 @@ var _ = Describe("Component Controller", func() { By("Mock PVCs and set status to bound") mockComponentPVCsAndBound(comp, updatedReplicas, true, storageClassName) - if policy != nil { + if bpt != nil { checkRestoreAndSetCompleted(clusterKey, comp.Name, updatedReplicas-int(comp.Replicas)) } - if policy != nil { + if bpt != nil { By("Checking Backup and Restore cleanup") Eventually(testapps.List(&testCtx, generics.BackupSignature, ml, client.InNamespace(clusterKey.Namespace))).Should(HaveLen(0)) Eventually(testapps.List(&testCtx, generics.RestoreSignature, ml, client.InNamespace(clusterKey.Namespace))).Should(HaveLen(0)) @@ -708,77 +675,58 @@ var _ = Describe("Component Controller", func() { } } - setHorizontalScalePolicy := func(policyType appsv1alpha1.HScaleDataClonePolicyType, componentDefsWithHScalePolicy ...string) { - By(fmt.Sprintf("Set HorizontalScalePolicy, policyType is %s", policyType)) - Expect(testapps.GetAndChangeObj(&testCtx, client.ObjectKeyFromObject(clusterDefObj), - func(clusterDef *appsv1alpha1.ClusterDefinition) { - // assign 1st component - if len(componentDefsWithHScalePolicy) == 0 && len(clusterDef.Spec.ComponentDefs) > 0 { - componentDefsWithHScalePolicy = []string{ - clusterDef.Spec.ComponentDefs[0].Name, - } - } - for i, compDef := range clusterDef.Spec.ComponentDefs { - if !slices.Contains(componentDefsWithHScalePolicy, compDef.Name) { - continue - } - - if len(policyType) == 0 { - clusterDef.Spec.ComponentDefs[i].HorizontalScalePolicy = nil - continue - } - - By("Checking backup policy created from backup policy template") - policyName := generateBackupPolicyName(clusterKey.Name, compDef.Name, "") - clusterDef.Spec.ComponentDefs[i].HorizontalScalePolicy = &appsv1alpha1.HorizontalScalePolicy{ - Type: policyType, - BackupPolicyTemplateName: backupPolicyTPLName, + setHorizontalScalePolicy := func(bpt *string, compDefNames ...string) { + bptName := "nil" + if bpt != nil { + bptName = *bpt + } + By(fmt.Sprintf("set HorizontalScalePolicy as %s", bptName)) + for _, compDefName := range compDefNames { + Expect(testapps.GetAndChangeObj(&testCtx, types.NamespacedName{Name: compDefName}, + func(compDef *appsv1alpha1.ComponentDefinition) { + if compDef.Annotations == nil { + compDef.Annotations = map[string]string{} } - - Eventually(testapps.CheckObjExists(&testCtx, client.ObjectKey{Name: policyName, Namespace: clusterKey.Namespace}, - &dpv1alpha1.BackupPolicy{}, true)).Should(Succeed()) - - if policyType == appsv1alpha1.HScaleDataClonePolicyCloneVolume { - By("creating actionSet if backup policy is backup") - fakeActionSet(clusterDef.Name) + if bpt == nil || len(*bpt) == 0 { + delete(compDef.Annotations, constant.HorizontalScaleBackupPolicyTemplateKey) + } else { + compDef.Annotations[constant.HorizontalScaleBackupPolicyTemplateKey] = *bpt } - } - })()).ShouldNot(HaveOccurred()) + })()).ShouldNot(HaveOccurred()) + } } - // @argument componentDefsWithHScalePolicy assign ClusterDefinition.spec.componentDefs[].horizontalScalePolicy for - // the matching names. If not provided, will set 1st ClusterDefinition.spec.componentDefs[0].horizontalScalePolicy. - horizontalScale := func(updatedReplicas int, storageClassName string, - policyType appsv1alpha1.HScaleDataClonePolicyType, componentDefsWithHScalePolicy ...string) { + horizontalScale := func(updatedReplicas int, storageClassName string, policyType *string, compDefNames ...string) { defer lorry.UnsetMockClient() cluster := &appsv1alpha1.Cluster{} Expect(k8sClient.Get(testCtx.Ctx, clusterKey, cluster)).Should(Succeed()) initialGeneration := int(cluster.Status.ObservedGeneration) - setHorizontalScalePolicy(policyType, componentDefsWithHScalePolicy...) + setHorizontalScalePolicy(policyType, compDefNames...) By("Mocking all components' PVCs to bound") for _, comp := range cluster.Spec.ComponentSpecs { mockComponentPVCsAndBound(&comp, int(comp.Replicas), true, storageClassName) } - hscalePolicy := func(comp appsv1alpha1.ClusterComponentSpec) *appsv1alpha1.HorizontalScalePolicy { - for _, componentDef := range clusterDefObj.Spec.ComponentDefs { - if componentDef.Name == comp.ComponentDefRef { - return componentDef.HorizontalScalePolicy + bpt := func(comp appsv1alpha1.ClusterComponentSpec) *string { + compDef := &appsv1alpha1.ComponentDefinition{} + Expect(k8sClient.Get(testCtx.Ctx, types.NamespacedName{Name: comp.ComponentDef}, compDef)).Should(Succeed()) + if len(compDef.Annotations) > 0 { + template, ok := compDef.Annotations[constant.HorizontalScaleBackupPolicyTemplateKey] + if ok { + return &template } } return nil } - By("Get the latest cluster def") - Expect(k8sClient.Get(testCtx.Ctx, client.ObjectKeyFromObject(clusterDefObj), clusterDefObj)).Should(Succeed()) for i, comp := range cluster.Spec.ComponentSpecs { mockLorryClient4HScale(clusterKey, comp.Name, updatedReplicas) - By(fmt.Sprintf("H-scale component %s with policy %s", comp.Name, hscalePolicy(comp))) - horizontalScaleComp(updatedReplicas, &cluster.Spec.ComponentSpecs[i], storageClassName, hscalePolicy(comp)) + By(fmt.Sprintf("H-scale component %s with policy %v", comp.Name, bpt(comp))) + horizontalScaleComp(updatedReplicas, &cluster.Spec.ComponentSpecs[i], storageClassName, bpt(comp)) } By("Checking cluster status and the number of replicas changed") @@ -786,11 +734,10 @@ var _ = Describe("Component Controller", func() { Should(BeEquivalentTo(initialGeneration + len(cluster.Spec.ComponentSpecs))) } - testHorizontalScale := func(compName, compDefName string, initialReplicas, updatedReplicas int32, - dataClonePolicy appsv1alpha1.HScaleDataClonePolicyType) { + testHorizontalScale := func(compName, compDefName string, initialReplicas, updatedReplicas int32, bpt *string) { By("Creating a single component cluster with VolumeClaimTemplate") pvcSpec := testapps.NewPVCSpec("1Gi") - createClusterObjV2(compName, compDefName, func(f *testapps.MockClusterFactory) { + createClusterObj(compName, compDefName, func(f *testapps.MockClusterFactory) { f.SetReplicas(initialReplicas). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). AddVolumeClaimTemplate(testapps.LogVolumeName, pvcSpec) @@ -799,10 +746,10 @@ var _ = Describe("Component Controller", func() { // REVIEW: this test flow, wait for running phase? testk8s.MockEnableVolumeSnapshot(&testCtx, testk8s.DefaultStorageClassName) - horizontalScale(int(updatedReplicas), testk8s.DefaultStorageClassName, dataClonePolicy, compDefName) + horizontalScale(int(updatedReplicas), testk8s.DefaultStorageClassName, bpt, compDefName) } - testVolumeExpansion := func(compName, compDefName string, storageClass *storagev1.StorageClass) { + testVolumeExpansion := func(compDef *appsv1alpha1.ComponentDefinition, compName string, storageClass *storagev1.StorageClass) { var ( replicas = 3 volumeSize = "1Gi" @@ -819,8 +766,9 @@ var _ = Describe("Component Controller", func() { pvcSpec.StorageClassName = &storageClass.Name By("Create cluster and waiting for the cluster initialized") - createClusterObj(compName, compDefName, func(f *testapps.MockClusterFactory) { + createClusterObj(compName, compDef.GetName(), func(f *testapps.MockClusterFactory) { f.SetReplicas(int32(replicas)). + SetServiceVersion(compDef.Spec.ServiceVersion). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). AddVolumeClaimTemplate(testapps.LogVolumeName, pvcSpec) }) @@ -1048,7 +996,7 @@ var _ = Describe("Component Controller", func() { } testCompFinalizerNLabel := func(compName, compDefName string) { - createClusterObjV2(compName, compDefObj.Name, nil) + createClusterObj(compName, compDefName, nil) By("check component finalizers and labels") Eventually(testapps.CheckObj(&testCtx, compKey, func(g Gomega, comp *appsv1alpha1.Component) { @@ -1061,7 +1009,7 @@ var _ = Describe("Component Controller", func() { } testCompService := func(compName, compDefName string) { - createClusterObjV2(compName, compDefObj.Name, nil) + createClusterObj(compName, compDefName, nil) targetPort := corev1.ServicePort{ Protocol: corev1.ProtocolTCP, @@ -1101,7 +1049,7 @@ var _ = Describe("Component Controller", func() { } testCompSystemAccount := func(compName, compDefName string) { - createClusterObjV2(compName, compDefObj.Name, nil) + createClusterObj(compName, compDefName, nil) By("check root account") rootSecretKey := types.NamespacedName{ @@ -1164,7 +1112,7 @@ var _ = Describe("Component Controller", func() { } } - createClusterObjV2(compName, compDefObj.Name, func(f *testapps.MockClusterFactory) { + createClusterObj(compName, compDefName, func(f *testapps.MockClusterFactory) { f.AddSystemAccount("root", passwordConfig, nil). AddSystemAccount("admin", nil, secretRef()). AddSystemAccount("not-exist", nil, nil) @@ -1250,7 +1198,7 @@ var _ = Describe("Component Controller", func() { }, } })).Should(Succeed()) - createClusterObjV2(compName, compDefObj.Name, nil) + createClusterObj(compName, compDefName, nil) By("check workload template env") targetEnvVars := []corev1.EnvVar{ @@ -1419,7 +1367,7 @@ var _ = Describe("Component Controller", func() { MaxReplicas: 16, } By("create component w/o replicas limit set") - createClusterObjV2(compName, compDefObj.Name, func(f *testapps.MockClusterFactory) { + createClusterObj(compName, compDefName, func(f *testapps.MockClusterFactory) { f.SetReplicas(replicasLimit.MaxReplicas * 2) }) itsKey := types.NamespacedName{ @@ -1438,7 +1386,7 @@ var _ = Describe("Component Controller", func() { By("create component w/ replicas limit set - out-of-limit") for _, replicas := range []int32{replicasLimit.MinReplicas / 2, replicasLimit.MaxReplicas * 2} { - createClusterObjV2WithPhase(compName, compDefObj.Name, func(f *testapps.MockClusterFactory) { + createClusterObjWithPhase(compName, compDefName, func(f *testapps.MockClusterFactory) { f.SetReplicas(replicas) }, "") Eventually(testapps.CheckObj(&testCtx, compKey, func(g Gomega, comp *appsv1alpha1.Component) { @@ -1457,7 +1405,7 @@ var _ = Describe("Component Controller", func() { By("create component w/ replicas limit set - ok") for _, replicas := range []int32{replicasLimit.MinReplicas, (replicasLimit.MinReplicas + replicasLimit.MaxReplicas) / 2, replicasLimit.MaxReplicas} { - createClusterObjV2(compName, compDefObj.Name, func(f *testapps.MockClusterFactory) { + createClusterObj(compName, compDefName, func(f *testapps.MockClusterFactory) { f.SetReplicas(replicas) }) itsKey := types.NamespacedName{ @@ -1471,7 +1419,7 @@ var _ = Describe("Component Controller", func() { } testCompRole := func(compName, compDefName string) { - createClusterObjV2(compName, compDefObj.Name, nil) + createClusterObj(compName, compDefName, nil) By("check default component roles") targetRoles := []workloads.ReplicaRole{ @@ -1504,7 +1452,7 @@ var _ = Describe("Component Controller", func() { } testCompTLSConfig := func(compName, compDefName string) { - createClusterObjV2(compName, compDefObj.Name, func(f *testapps.MockClusterFactory) { + createClusterObj(compName, compDefName, func(f *testapps.MockClusterFactory) { issuer := &appsv1alpha1.Issuer{ Name: appsv1alpha1.IssuerKubeBlocks, } @@ -1583,7 +1531,7 @@ var _ = Describe("Component Controller", func() { Operator: corev1.TolerationOpEqual, Effect: corev1.TaintEffectNoSchedule, } - createClusterObjV2(compName, compDefObj.Name, func(f *testapps.MockClusterFactory) { + createClusterObj(compName, compDefName, func(f *testapps.MockClusterFactory) { f.SetComponentAffinity(&affinity).AddComponentToleration(toleration) }) @@ -1642,7 +1590,7 @@ var _ = Describe("Component Controller", func() { if len(saName) == 0 { saName = "test-sa-" + randomStr() } - createClusterObjV2(compName, compDefObj.Name, func(f *testapps.MockClusterFactory) { + createClusterObj(compName, compDefName, func(f *testapps.MockClusterFactory) { f.SetServiceAccountName(saName) }) @@ -1703,39 +1651,16 @@ var _ = Describe("Component Controller", func() { checkRBACResourcesExistence(saName, true) } - testReplicationWorkloadRunning := func(compName, compDefName string) { - By("Mock a cluster obj with replication componentDefRef.") - pvcSpec := testapps.NewPVCSpec("1Gi") - clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). - WithRandomName(). - AddComponent(compName, compDefName). - SetReplicas(testapps.DefaultReplicationReplicas). - AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). - Create(&testCtx).GetObject() - clusterKey = client.ObjectKeyFromObject(clusterObj) - - By("Waiting for the cluster controller to create resources completely") - waitForCreatingResourceCompletely(clusterKey, compDefName) - - By("Checking instanceSet number") - itsList := testk8s.ListAndCheckInstanceSetItemsCount(&testCtx, clusterKey, 1) - its := &itsList.Items[0] - mockPods := testapps.MockInstanceSetPods(&testCtx, its, clusterObj, compDefName) - Expect(testapps.ChangeObjStatus(&testCtx, its, func() { - testk8s.MockInstanceSetReady(its, mockPods...) - })).ShouldNot(HaveOccurred()) - Eventually(testapps.GetClusterPhase(&testCtx, clusterKey)).Should(Equal(appsv1alpha1.RunningClusterPhase)) - } - testThreeReplicas := func(compName, compDefName string) { const replicas = 3 By("Mock a cluster obj") pvcSpec := testapps.NewPVCSpec("1Gi") - clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). + clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). WithRandomName(). AddComponent(compName, compDefName). - SetReplicas(replicas).AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). + SetReplicas(replicas). + AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). Create(&testCtx).GetObject() clusterKey = client.ObjectKeyFromObject(clusterObj) @@ -1748,6 +1673,7 @@ var _ = Describe("Component Controller", func() { g.Expect(itsList.Items).ShouldNot(BeEmpty()) its = &itsList.Items[0] }).Should(Succeed()) + By("Creating mock pods in InstanceSet, and set controller reference") pods := mockPodsForTest(clusterObj, replicas) for i, pod := range pods { @@ -1794,6 +1720,7 @@ var _ = Describe("Component Controller", func() { Expect(testapps.GetAndChangeObj(&testCtx, client.ObjectKeyFromObject(its), func(its *workloads.InstanceSet) { its.Annotations["time"] = time.Now().Format(time.RFC3339) })()).Should(Succeed()) + By("Checking pods' annotations") Eventually(func(g Gomega) { pods, err := intctrlutil.GetPodListByInstanceSet(ctx, k8sClient, its) @@ -1805,6 +1732,7 @@ var _ = Describe("Component Controller", func() { } }).Should(Succeed()) itsPatch := client.MergeFrom(its.DeepCopy()) + By("Updating ITS status") its.Status.UpdateRevision = "mock-version" pods, err := intctrlutil.GetPodListByInstanceSet(ctx, k8sClient, its) @@ -1832,7 +1760,7 @@ var _ = Describe("Component Controller", func() { Should(Equal(appsv1alpha1.RunningClusterCompPhase)) } - testRestoreClusterFromBackup := func(compName, compDefName string) { + testRestoreClusterFromBackup := func(compName string, compDef *appsv1alpha1.ComponentDefinition) { By("mock backuptool object") backupPolicyName := "test-backup-policy" backupName := "test-backup" @@ -1855,9 +1783,10 @@ var _ = Describe("Component Controller", func() { restoreFromBackup := fmt.Sprintf(`{"%s":{"name":"%s"}}`, compName, backupName) pvcSpec := testapps.NewPVCSpec("1Gi") replicas := 3 - clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). + clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). WithRandomName(). - AddComponent(compName, compDefName). + AddComponent(compName, compDef.GetName()). + SetServiceVersion(compDef.Spec.ServiceVersion). SetReplicas(int32(replicas)). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). AddAnnotations(constant.RestoreFromBackupAnnotationKey, restoreFromBackup). @@ -1906,87 +1835,6 @@ var _ = Describe("Component Controller", func() { })).Should(Succeed()) } - testBackupError := func(compName, compDefName string) { - initialReplicas := int32(1) - updatedReplicas := int32(3) - testk8s.MockEnableVolumeSnapshot(&testCtx, testk8s.DefaultStorageClassName) - - By("Set HorizontalScalePolicy") - Expect(testapps.GetAndChangeObj(&testCtx, client.ObjectKeyFromObject(clusterDefObj), - func(clusterDef *appsv1alpha1.ClusterDefinition) { - for i, def := range clusterDef.Spec.ComponentDefs { - if def.Name != compDefName { - continue - } - clusterDef.Spec.ComponentDefs[i].HorizontalScalePolicy = - &appsv1alpha1.HorizontalScalePolicy{Type: appsv1alpha1.HScaleDataClonePolicyCloneVolume, - BackupPolicyTemplateName: backupPolicyTPLName} - } - })()).ShouldNot(HaveOccurred()) - - By("Creating a cluster with VolumeClaimTemplate") - pvcSpec := testapps.NewPVCSpec("1Gi") - createClusterObj(compName, compDefName, func(f *testapps.MockClusterFactory) { - f.SetReplicas(initialReplicas).AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec) - }) - - By("Create and Mock PVCs status to bound") - for _, comp := range clusterObj.Spec.ComponentSpecs { - mockComponentPVCsAndBound(&comp, int(comp.Replicas), true, testk8s.DefaultStorageClassName) - } - - By(fmt.Sprintf("Changing replicas to %d", updatedReplicas)) - changeCompReplicas(clusterKey, updatedReplicas, &clusterObj.Spec.ComponentSpecs[0]) - Eventually(testapps.GetClusterObservedGeneration(&testCtx, clusterKey)).Should(BeEquivalentTo(2)) - - By("Waiting for the backup object been created") - ml := client.MatchingLabels{ - constant.AppInstanceLabelKey: clusterKey.Name, - constant.KBAppComponentLabelKey: compName, - } - Eventually(testapps.List(&testCtx, generics.BackupSignature, - ml, client.InNamespace(clusterKey.Namespace))).Should(HaveLen(1)) - - By("Mocking backup status to failed") - backupList := dpv1alpha1.BackupList{} - Expect(k8sClient.List(testCtx.Ctx, &backupList, ml)).Should(Succeed()) - backupKey := types.NamespacedName{ - Namespace: backupList.Items[0].Namespace, - Name: backupList.Items[0].Name, - } - Expect(testapps.GetAndChangeObjStatus(&testCtx, backupKey, func(backup *dpv1alpha1.Backup) { - backup.Status.Phase = dpv1alpha1.BackupPhaseFailed - })()).Should(Succeed()) - - By("Checking cluster status failed with backup error") - Eventually(testapps.CheckObj(&testCtx, clusterKey, func(g Gomega, cluster *appsv1alpha1.Cluster) { - g.Expect(testk8s.IsMockVolumeSnapshotEnabled(&testCtx, testk8s.DefaultStorageClassName)).Should(BeTrue()) - g.Expect(cluster.Status.Conditions).ShouldNot(BeEmpty()) - var err error - for _, cond := range cluster.Status.Conditions { - if strings.Contains(cond.Message, "backup for horizontalScaling failed") { - err = fmt.Errorf("has backup error") - break - } - } - g.Expect(err).Should(HaveOccurred()) - })).Should(Succeed()) - - By("Expect for backup error event") - Eventually(func(g Gomega) { - eventList := corev1.EventList{} - Expect(k8sClient.List(ctx, &eventList, client.InNamespace(testCtx.DefaultNamespace))).Should(Succeed()) - hasBackupErrorEvent := false - for _, v := range eventList.Items { - if v.Reason == string(intctrlutil.ErrorTypeBackupFailed) { - hasBackupErrorEvent = true - break - } - } - g.Expect(hasBackupErrorEvent).Should(BeTrue()) - }).Should(Succeed()) - } - testUpdateKubeBlocksToolsImage := func(compName, compDefName string) { createClusterObj(compName, compDefName, nil) @@ -2072,7 +1920,7 @@ var _ = Describe("Component Controller", func() { customAnnotationKeyBeFiltered: customAnnotationValueBeFiltered, constant.FeatureReconciliationInCompactModeAnnotationKey: "true", } - createClusterObjV2(compName, compDefObj.Name, func(f *testapps.MockClusterFactory) { + createClusterObj(compName, compDefName, func(f *testapps.MockClusterFactory) { f.AddLabelsInMap(customLabels) f.AddAnnotationsInMap(customAnnotations) }) @@ -2089,8 +1937,8 @@ var _ = Describe("Component Controller", func() { Context("provisioning", func() { BeforeEach(func() { - createAllWorkloadTypesClusterDef() - createBackupPolicyTpl(clusterDefObj, compDefName) + createAllDefinitionObjects() + createBackupPolicyTpl(compDefObj.GetName()) }) AfterEach(func() { @@ -2106,11 +1954,9 @@ var _ = Describe("Component Controller", func() { }) It("with component zero replicas", func() { + zeroReplicas := func(f *testapps.MockClusterFactory) { f.SetReplicas(0) } phase := appsv1alpha1.ClusterPhase("") - createClusterObjVx("", defaultCompName, compDefName, true, - func(f *testapps.MockClusterFactory) { - f.SetReplicas(0) - }, &phase) + createClusterObjX("", defaultCompName, compDefName, zeroReplicas, &phase) By("checking the component status can't be reconciled well") Eventually(testapps.CheckObj(&testCtx, compKey, func(g Gomega, comp *appsv1alpha1.Component) { @@ -2142,6 +1988,10 @@ var _ = Describe("Component Controller", func() { testCompRole(defaultCompName, compDefName) }) + It("with component roles - should success with one leader pod and two follower pods", func() { + testThreeReplicas(defaultCompName, compDefObj.Name) + }) + It("with component TlS", func() { testCompTLSConfig(defaultCompName, compDefName) }) @@ -2165,12 +2015,16 @@ var _ = Describe("Component Controller", func() { It("create component with custom RBAC which is already exist created by User", func() { tesCreateCompWithRBACCreateByUser(defaultCompName, compDefName) }) + + It("update kubeblocks-tools image", func() { + testUpdateKubeBlocksToolsImage(defaultCompName, compDefName) + }) }) Context("h-scaling", func() { BeforeEach(func() { - createAllWorkloadTypesClusterDef() - createBackupPolicyTpl(clusterDefObj, compDefName) + createAllDefinitionObjects() + createBackupPolicyTpl(compDefObj.GetName()) }) AfterEach(func() { @@ -2178,269 +2032,141 @@ var _ = Describe("Component Controller", func() { }) It("should create/delete pods to match the desired replica number", func() { - testChangeReplicas(replicationCompName, replicationCompDefName) + testChangeReplicas(defaultCompName, compDefObj.Name) }) It("scale-in to 0", func() { - testChangeReplicasToZero(replicationCompName, replicationCompDefName) + testChangeReplicasToZero(defaultCompName, compDefObj.Name) }) It("scale-in to 0 w/ min replicas limit as 0", func() { - testChangeReplicasToZeroWithReplicasLimit(replicationCompName, replicationCompDefName) + testChangeReplicasToZeroWithReplicasLimit(defaultCompName, compDefObj.Name) }) - }) - Context("h-scaling with different backup methods", func() { - BeforeEach(func() { - cleanEnv() - createAllWorkloadTypesClusterDef() - createBackupPolicyTpl(clusterDefObj, compDefName) + It("scale-out from 1 to 3 with backup(snapshot) policy normally", func() { + testHorizontalScale(defaultCompName, compDefObj.Name, 1, 3, &backupPolicyTPLName) }) - createNWaitClusterObj := func(components map[string]string, - addedComponentProcessor func(compName string, factory *testapps.MockClusterFactory), - withFixedName ...bool) { - Expect(components).ShouldNot(BeEmpty()) - - By("Creating a cluster") - clusterBuilder := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name) - - compNames := make([]string, 0, len(components)) - for compName, compDefName := range components { - clusterBuilder = clusterBuilder.AddComponent(compName, compDefName) - if addedComponentProcessor != nil { - addedComponentProcessor(compName, clusterBuilder) - } - compNames = append(compNames, compName) - } - if len(withFixedName) == 0 || !withFixedName[0] { - clusterBuilder.WithRandomName() - } - clusterObj = clusterBuilder.Create(&testCtx).GetObject() - clusterKey = client.ObjectKeyFromObject(clusterObj) - - By("Waiting for the cluster controller to create resources completely") - waitForCreatingResourceCompletely(clusterKey, compNames...) - } - - testMultiCompHScale := func(policyType appsv1alpha1.HScaleDataClonePolicyType) { - compNameNDef := map[string]string{ - statefulCompName: statefulCompDefName, - consensusCompName: consensusCompDefName, - replicationCompName: replicationCompDefName, - } - initialReplicas := int32(1) - updatedReplicas := int32(2) - - By("Creating a multi components cluster with VolumeClaimTemplate") - pvcSpec := testapps.NewPVCSpec("1Gi") - - createNWaitClusterObj(compNameNDef, func(compName string, factory *testapps.MockClusterFactory) { - factory.AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec).SetReplicas(initialReplicas) - }, false) - - By("Waiting for the cluster controller to create resources completely") - waitForCreatingResourceCompletely(clusterKey, statefulCompName, consensusCompName, replicationCompName) - - // statefulCompDefName not in componentDefsWithHScalePolicy, for nil backup policy test - // REVIEW: - // 1. this test flow, wait for running phase? - horizontalScale(int(updatedReplicas), testk8s.DefaultStorageClassName, policyType, consensusCompDefName, replicationCompDefName) - } - - It("h-scale with volume snapshot", func() { - testk8s.MockEnableVolumeSnapshot(&testCtx, testk8s.DefaultStorageClassName) - testMultiCompHScale(appsv1alpha1.HScaleDataClonePolicyCloneVolume) + It("scale-out without data clone policy", func() { + testHorizontalScale(defaultCompName, compDefObj.Name, 1, 3, nil) }) - It("h-scale with backup tool", func() { - testk8s.MockDisableVolumeSnapshot(&testCtx, testk8s.DefaultStorageClassName) - testMultiCompHScale(appsv1alpha1.HScaleDataClonePolicyCloneVolume) + It("scale-in from 3 to 1", func() { + testHorizontalScale(defaultCompName, compDefObj.Name, 3, 1, &backupPolicyTPLName) }) - }) - Context("h-scaling and volume expansion", func() { - var ( - mockStorageClass *storagev1.StorageClass - ) - - compNameNDef := map[string]string{ - replicationCompName: replicationCompDefName, - } - - BeforeEach(func() { - createAllWorkloadTypesClusterDef() - createBackupPolicyTpl(clusterDefObj, compDefName) - mockStorageClass = testk8s.CreateMockStorageClass(&testCtx, testk8s.DefaultStorageClassName) + It("scale-in to 0 and PVCs should not been deleted", func() { + testHorizontalScale(defaultCompName, compDefObj.Name, 3, 0, &backupPolicyTPLName) }) - for key := range compNameNDef { - compName := key - compDefName := compNameNDef[key] + Context("with different backup methods", func() { + createNWaitClusterObj := func(components map[string]string, + processor func(compName string, factory *testapps.MockClusterFactory), + withFixedName ...bool) { + Expect(components).ShouldNot(BeEmpty()) - Context(fmt.Sprintf("[comp: %s] update kubeblocks-tools image ", compName), func() { - It(fmt.Sprintf("[comp: %s] update kubeblocks-tools image", compName), func() { - testUpdateKubeBlocksToolsImage(compName, compDefName) - }) - }) + By("Creating a cluster") + clusterBuilder := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, "") - Context(fmt.Sprintf("[comp: %s] volume expansion", compName), func() { - It("should update PVC request storage size accordingly", func() { - testVolumeExpansion(compName, compDefName, mockStorageClass) - }) + compNames := make([]string, 0, len(components)) + for compName, compDefName := range components { + clusterBuilder = clusterBuilder.AddComponent(compName, compDefName) + if processor != nil { + processor(compName, clusterBuilder) + } + compNames = append(compNames, compName) + } + if len(withFixedName) == 0 || !withFixedName[0] { + clusterBuilder.WithRandomName() + } + clusterObj = clusterBuilder.Create(&testCtx).GetObject() + clusterKey = client.ObjectKeyFromObject(clusterObj) - It("should be able to recover if volume expansion fails", func() { - testVolumeExpansionFailedAndRecover(compName, compDefName) - }) - }) + By("Waiting for the cluster controller to create resources completely") + waitForCreatingResourceCompletely(clusterKey, compNames...) + } - Context(fmt.Sprintf("[comp: %s] horizontal scale", compName), func() { - It("scale-out from 1 to 3 with backup(snapshot) policy normally", func() { - testHorizontalScale(compName, compDefObj.Name, 1, 3, appsv1alpha1.HScaleDataClonePolicyCloneVolume) - }) + testMultiCompHScale := func(bpt *string) { + compNameNDef := map[string]string{ + fmt.Sprintf("%s-0", defaultCompName): compDefObj.Name, + fmt.Sprintf("%s-1", defaultCompName): compDefObj.Name, + fmt.Sprintf("%s-2", defaultCompName): compDefObj.Name, + } + initialReplicas := int32(1) + updatedReplicas := int32(2) - // TODO(component): events & conditions - PIt("backup error at scale-out", func() { - testBackupError(compName, compDefObj.Name) - }) + By("Creating a multi components cluster with VolumeClaimTemplate") + pvcSpec := testapps.NewPVCSpec("1Gi") - It("scale-out without data clone policy", func() { - testHorizontalScale(compName, compDefObj.Name, 1, 3, "") - }) + createNWaitClusterObj(compNameNDef, func(compName string, factory *testapps.MockClusterFactory) { + factory.AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec).SetReplicas(initialReplicas) + }, false) - It("scale-in from 3 to 1", func() { - testHorizontalScale(compName, compDefObj.Name, 3, 1, appsv1alpha1.HScaleDataClonePolicyCloneVolume) - }) + horizontalScale(int(updatedReplicas), testk8s.DefaultStorageClassName, bpt, compDefObj.Name) + } - It("scale-in to 0 and PVCs should not been deleted", func() { - testHorizontalScale(compName, compDefObj.Name, 3, 0, appsv1alpha1.HScaleDataClonePolicyCloneVolume) - }) + It("h-scale with volume snapshot", func() { + testk8s.MockEnableVolumeSnapshot(&testCtx, testk8s.DefaultStorageClassName) + testMultiCompHScale(&backupPolicyTPLName) }) - Context(fmt.Sprintf("[comp: %s] scale-out after volume expansion", compName), func() { - It("scale-out with data clone policy", func() { - testVolumeExpansion(compName, compDefName, mockStorageClass) - testk8s.MockEnableVolumeSnapshot(&testCtx, mockStorageClass.Name) - horizontalScale(5, mockStorageClass.Name, appsv1alpha1.HScaleDataClonePolicyCloneVolume, compDefName) - }) - - It("scale-out without data clone policy", func() { - testVolumeExpansion(compName, compDefName, mockStorageClass) - horizontalScale(5, mockStorageClass.Name, "", compDefName) - }) + It("h-scale with backup tool", func() { + testk8s.MockDisableVolumeSnapshot(&testCtx, testk8s.DefaultStorageClassName) + testMultiCompHScale(&backupPolicyTPLName) }) - } + }) }) - Context("creating cluster with workloadType=consensus component", func() { + Context("volume expansion", func() { + var ( + mockStorageClass *storagev1.StorageClass + ) + BeforeEach(func() { - createAllWorkloadTypesClusterDef() - createBackupPolicyTpl(clusterDefObj, compDefName) + createAllDefinitionObjects() + createBackupPolicyTpl(compDefObj.GetName()) + mockStorageClass = testk8s.CreateMockStorageClass(&testCtx, testk8s.DefaultStorageClassName) }) - AfterEach(func() { - cleanEnv() + It("should update PVC request storage size accordingly", func() { + testVolumeExpansion(compDefObj, defaultCompName, mockStorageClass) }) - // REVIEW/TODO: following test always failed at cluster.phase.observerGeneration=1 with cluster.phase.phase=creating - It("Should success with primary pod and secondary pod", func() { - testReplicationWorkloadRunning(replicationCompName, replicationCompDefName) + It("should be able to recover if volume expansion fails", func() { + testVolumeExpansionFailedAndRecover(defaultCompName, compDefName) }) - It("Should success with one leader pod and two follower pods", func() { - testThreeReplicas(consensusCompName, consensusCompDefName) + It("scale-out with data clone policy", func() { + testVolumeExpansion(compDefObj, defaultCompName, mockStorageClass) + testk8s.MockEnableVolumeSnapshot(&testCtx, mockStorageClass.Name) + horizontalScale(5, mockStorageClass.Name, &backupPolicyTPLName, compDefObj.Name) }) - It("test restore cluster from backup", func() { - testRestoreClusterFromBackup(consensusCompName, consensusCompDefName) + It("scale-out without data clone policy", func() { + testVolumeExpansion(compDefObj, defaultCompName, mockStorageClass) + horizontalScale(5, mockStorageClass.Name, nil, compDefObj.Name) }) }) - Context("reconcile with definition and version", func() { + Context("restore", func() { BeforeEach(func() { - cleanEnv() - createAllWorkloadTypesClusterDef() + createAllDefinitionObjects() + createBackupPolicyTpl(compDefObj.GetName()) }) - testImageUnchangedAfterNewReleasePublished := func(release appsv1alpha1.ComponentVersionRelease) { - prevRelease := compVerObj.Spec.Releases[0] - - By("check new release") - Expect(prevRelease.Images).Should(HaveLen(len(release.Images))) - Expect(maps.Keys(prevRelease.Images)).Should(BeEquivalentTo(maps.Keys(release.Images))) - Expect(maps.Values(prevRelease.Images)).ShouldNot(BeEquivalentTo(maps.Values(release.Images))) - - // createCompObj(defaultCompName, compDefObj.Name, compVerObj.Spec.Releases[0].ServiceVersion, nil) - createClusterObjV2(defaultCompName, compDefObj.Name, func(f *testapps.MockClusterFactory) { - f.SetServiceVersion(prevRelease.ServiceVersion) - }) - - By("check the labels and image in its") - itsKey := compKey - Eventually(testapps.CheckObj(&testCtx, itsKey, func(g Gomega, its *workloads.InstanceSet) { - // check comp-def and service-version labels - g.Expect(its.Annotations).ShouldNot(BeEmpty()) - g.Expect(its.Annotations).Should(HaveKeyWithValue(constant.AppComponentLabelKey, compObj.Spec.CompDef)) - g.Expect(its.Annotations).Should(HaveKeyWithValue(constant.KBAppServiceVersionKey, compObj.Spec.ServiceVersion)) - // check the image - c := its.Spec.Template.Spec.Containers[0] - g.Expect(c.Image).To(BeEquivalentTo(prevRelease.Images[c.Name])) - })).Should(Succeed()) - - By("publish a new release") - compVerKey := client.ObjectKeyFromObject(compVerObj) - Expect(testapps.GetAndChangeObj(&testCtx, compVerKey, func(compVer *appsv1alpha1.ComponentVersion) { - compVer.Spec.Releases = append(compVer.Spec.Releases, release) - compVer.Spec.CompatibilityRules[0].Releases = append(compVer.Spec.CompatibilityRules[0].Releases, release.Name) - })()).Should(Succeed()) - - By("trigger component reconcile") - now := time.Now().Format(time.RFC3339) - Expect(testapps.GetAndChangeObj(&testCtx, compKey, func(comp *appsv1alpha1.Component) { - comp.Annotations["now"] = now - })()).Should(Succeed()) - - By("wait its updated and check the labels and image in its not changed") - Eventually(testapps.CheckObj(&testCtx, itsKey, func(g Gomega, its *workloads.InstanceSet) { - // check the its is updated - g.Expect(its.Annotations).ShouldNot(BeEmpty()) - g.Expect(its.Annotations).Should(HaveKeyWithValue("now", now)) - // check comp-def and service-version labels unchanged - g.Expect(its.Annotations).Should(HaveKeyWithValue(constant.AppComponentLabelKey, compObj.Spec.CompDef)) - g.Expect(its.Annotations).Should(HaveKeyWithValue(constant.KBAppServiceVersionKey, compObj.Spec.ServiceVersion)) - // check the image unchanged - c := its.Spec.Template.Spec.Containers[0] - g.Expect(c.Image).To(BeEquivalentTo(prevRelease.Images[c.Name])) - })).Should(Succeed()) - } - - It("publish new release with different service version", func() { - release := appsv1alpha1.ComponentVersionRelease{ - Name: "8.0.30-r2", - ServiceVersion: "8.0.31", // different service version - Images: map[string]string{ - testapps.DefaultMySQLContainerName: "mysql:8.0.31", // new image - }, - } - testImageUnchangedAfterNewReleasePublished(release) + AfterEach(func() { + cleanEnv() }) - It("publish new release with same service version", func() { - release := appsv1alpha1.ComponentVersionRelease{ - Name: "8.0.30-r2", - ServiceVersion: "8.0.30", // same service version - Images: map[string]string{ - testapps.DefaultMySQLContainerName: "mysql:8.0.31", // new image - }, - } - testImageUnchangedAfterNewReleasePublished(release) + It("test restore cluster from backup", func() { + testRestoreClusterFromBackup(defaultCompName, compDefObj) }) }) Context("start & stop", func() { BeforeEach(func() { cleanEnv() - createAllWorkloadTypesClusterDef() + createAllDefinitionObjects() }) startComp := func() { @@ -2493,7 +2219,7 @@ var _ = Describe("Component Controller", func() { } It("stop a component", func() { - createClusterObjV2(defaultCompName, compDefObj.Name, nil) + createClusterObj(defaultCompName, compDefName, nil) checkCompCreating() By("stop it") @@ -2506,7 +2232,7 @@ var _ = Describe("Component Controller", func() { }) It("start a component", func() { - createClusterObjV2(defaultCompName, compDefObj.Name, nil) + createClusterObj(defaultCompName, compDefName, nil) checkCompCreating() By("start it") @@ -2527,7 +2253,7 @@ var _ = Describe("Component Controller", func() { }) It("h-scale a stopped component", func() { - createClusterObjV2WithPhase(defaultCompName, compDefObj.Name, func(f *testapps.MockClusterFactory) { + createClusterObjWithPhase(defaultCompName, compDefName, func(f *testapps.MockClusterFactory) { f.SetStop(func() *bool { b := true; return &b }()) }, appsv1alpha1.StoppedClusterPhase) checkCompStopped() @@ -2563,6 +2289,87 @@ var _ = Describe("Component Controller", func() { // TODO: stop a component in h-scaling }) + + Context("reconcile with definition and version", func() { + BeforeEach(func() { + cleanEnv() + createAllDefinitionObjects() + }) + + testImageUnchangedAfterNewReleasePublished := func(release appsv1alpha1.ComponentVersionRelease) { + prevRelease := compVerObj.Spec.Releases[0] + + By("check new release") + Expect(prevRelease.Images).Should(HaveLen(len(release.Images))) + Expect(maps.Keys(prevRelease.Images)).Should(BeEquivalentTo(maps.Keys(release.Images))) + Expect(maps.Values(prevRelease.Images)).ShouldNot(BeEquivalentTo(maps.Values(release.Images))) + + // createCompObj(defaultCompName, compDefName, compVerObj.Spec.Releases[0].ServiceVersion, nil) + createClusterObj(defaultCompName, compDefName, func(f *testapps.MockClusterFactory) { + f.SetServiceVersion(prevRelease.ServiceVersion) + }) + + By("check the labels and image in its") + itsKey := compKey + Eventually(testapps.CheckObj(&testCtx, itsKey, func(g Gomega, its *workloads.InstanceSet) { + // check comp-def and service-version labels + g.Expect(its.Annotations).ShouldNot(BeEmpty()) + g.Expect(its.Annotations).Should(HaveKeyWithValue(constant.AppComponentLabelKey, compObj.Spec.CompDef)) + g.Expect(its.Annotations).Should(HaveKeyWithValue(constant.KBAppServiceVersionKey, compObj.Spec.ServiceVersion)) + // check the image + c := its.Spec.Template.Spec.Containers[0] + g.Expect(c.Image).To(BeEquivalentTo(prevRelease.Images[c.Name])) + })).Should(Succeed()) + + By("publish a new release") + compVerKey := client.ObjectKeyFromObject(compVerObj) + Expect(testapps.GetAndChangeObj(&testCtx, compVerKey, func(compVer *appsv1alpha1.ComponentVersion) { + compVer.Spec.Releases = append(compVer.Spec.Releases, release) + compVer.Spec.CompatibilityRules[0].Releases = append(compVer.Spec.CompatibilityRules[0].Releases, release.Name) + })()).Should(Succeed()) + + By("trigger component reconcile") + now := time.Now().Format(time.RFC3339) + Expect(testapps.GetAndChangeObj(&testCtx, compKey, func(comp *appsv1alpha1.Component) { + comp.Annotations["now"] = now + })()).Should(Succeed()) + + By("wait its updated and check the labels and image in its not changed") + Eventually(testapps.CheckObj(&testCtx, itsKey, func(g Gomega, its *workloads.InstanceSet) { + // check the its is updated + g.Expect(its.Annotations).ShouldNot(BeEmpty()) + g.Expect(its.Annotations).Should(HaveKeyWithValue("now", now)) + // check comp-def and service-version labels unchanged + g.Expect(its.Annotations).Should(HaveKeyWithValue(constant.AppComponentLabelKey, compObj.Spec.CompDef)) + g.Expect(its.Annotations).Should(HaveKeyWithValue(constant.KBAppServiceVersionKey, compObj.Spec.ServiceVersion)) + // check the image unchanged + c := its.Spec.Template.Spec.Containers[0] + g.Expect(c.Image).To(BeEquivalentTo(prevRelease.Images[c.Name])) + })).Should(Succeed()) + } + + It("publish new release with different service version", func() { + release := appsv1alpha1.ComponentVersionRelease{ + Name: "8.0.30-r2", + ServiceVersion: "8.0.31", // different service version + Images: map[string]string{ + testapps.DefaultMySQLContainerName: "mysql:8.0.31", // new image + }, + } + testImageUnchangedAfterNewReleasePublished(release) + }) + + It("publish new release with same service version", func() { + release := appsv1alpha1.ComponentVersionRelease{ + Name: "8.0.30-r2", + ServiceVersion: "8.0.30", // same service version + Images: map[string]string{ + testapps.DefaultMySQLContainerName: "mysql:8.0.31", // new image + }, + } + testImageUnchangedAfterNewReleasePublished(release) + }) + }) }) func mockRestoreCompleted(ml client.MatchingLabels) { @@ -2593,10 +2400,8 @@ func checkRestoreAndSetCompleted(clusterKey types.NamespacedName, compName strin func fakeActionSet(clusterDefName string) *dpv1alpha1.ActionSet { actionSet := &dpv1alpha1.ActionSet{ ObjectMeta: metav1.ObjectMeta{ - Name: actionSetName, - Labels: map[string]string{ - constant.ClusterDefLabelKey: clusterDefName, - }, + Name: actionSetName, + Labels: map[string]string{}, }, Spec: dpv1alpha1.ActionSetSpec{ Env: []corev1.EnvVar{ @@ -2630,6 +2435,9 @@ func fakeActionSet(clusterDefName string) *dpv1alpha1.ActionSet { }, }, } + if len(clusterDefName) > 0 { + actionSet.Labels[constant.ClusterDefLabelKey] = clusterDefName + } testapps.CheckedCreateK8sResource(&testCtx, actionSet) return actionSet } diff --git a/controllers/apps/component_hscale_volume_populator.go b/controllers/apps/component_hscale_volume_populator.go index dcb07ab40026..072d546da638 100644 --- a/controllers/apps/component_hscale_volume_populator.go +++ b/controllers/apps/component_hscale_volume_populator.go @@ -82,7 +82,7 @@ func newDataClone(reqCtx intctrlutil.RequestCtx, if err != nil { return nil, err } - if component.HorizontalScalePolicy == nil { + if component.HorizontalScaleBackupPolicyTemplate == nil { return &dummyDataClone{ baseDataClone{ reqCtx: reqCtx, @@ -97,23 +97,19 @@ func newDataClone(reqCtx intctrlutil.RequestCtx, }, }, nil } - if component.HorizontalScalePolicy.Type == appsv1alpha1.HScaleDataClonePolicyCloneVolume { - return &backupDataClone{ - baseDataClone{ - reqCtx: reqCtx, - cli: cli, - cluster: cluster, - component: component, - itsObj: itsObj, - itsProto: itsProto, - backupKey: backupKey, - desiredPodNames: desiredPodNames, - currentPodNameSet: sets.New(currentPodNames...), - }, - }, nil - } - // TODO: how about policy None and Snapshot? - return nil, nil + return &backupDataClone{ + baseDataClone{ + reqCtx: reqCtx, + cli: cli, + cluster: cluster, + component: component, + itsObj: itsObj, + itsProto: itsProto, + backupKey: backupKey, + desiredPodNames: desiredPodNames, + currentPodNameSet: sets.New(currentPodNames...), + }, + }, nil } type baseDataClone struct { @@ -372,15 +368,8 @@ func (d *backupDataClone) GetTmpResources() ([]client.Object, error) { } func (d *backupDataClone) backup() ([]client.Object, error) { - componentDef := func() string { - name := d.component.CompDefName - if name == "" { - name = d.component.ClusterCompDefName - } - return name - }() - backupPolicyTplName := d.component.HorizontalScalePolicy.BackupPolicyTemplateName - backupPolicy, err := getBackupPolicyFromTemplate(d.reqCtx, d.cli, d.cluster, componentDef, backupPolicyTplName) + backupPolicyTplName := *d.component.HorizontalScaleBackupPolicyTemplate + backupPolicy, err := getBackupPolicyFromTemplate(d.reqCtx, d.cli, d.cluster, d.component.CompDefName, backupPolicyTplName) if err != nil { return nil, err } diff --git a/controllers/apps/component_utils_test.go b/controllers/apps/component_utils_test.go index 76d1c031b798..df699b0fed17 100644 --- a/controllers/apps/component_utils_test.go +++ b/controllers/apps/component_utils_test.go @@ -31,24 +31,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" - "github.com/apecloud/kubeblocks/pkg/controller/component" "github.com/apecloud/kubeblocks/pkg/controllerutil" "github.com/apecloud/kubeblocks/pkg/generics" testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" ) var _ = Describe("Component Utils", func() { - var ( - randomStr = testCtx.GetRandomStr() - clusterDefName = "mysql-clusterdef-" + randomStr - clusterName = "mysql-" + randomStr - ) - - const ( - consensusCompName = "consensus" - statelessCompName = "stateless" - ) - cleanAll := func() { // must wait until resources deleted and no longer exist before the testcases start, // otherwise if later it needs to create some new resource objects with the same name, @@ -70,20 +58,6 @@ var _ = Describe("Component Utils", func() { AfterEach(cleanAll) - Context("Component test", func() { - It("Component test", func() { - By(" init cluster, instanceSet, pods") - _, cluster := testapps.InitClusterWithHybridComps(&testCtx, clusterDefName, - clusterName, statelessCompName, "stateful", consensusCompName) - its := testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusCompName) - _ = testapps.MockInstanceSetPods(&testCtx, its, cluster, consensusCompName) - - By("test GetMinReadySeconds function") - minReadySeconds, _ := component.GetMinReadySeconds(ctx, k8sClient, *cluster, consensusCompName) - Expect(minReadySeconds).To(Equal(int32(0))) - }) - }) - Context("test mergeServiceAnnotations", func() { It("test sync pod spec default values set by k8s", func() { var ( diff --git a/controllers/apps/configuration/combine_upgrade_policy_test.go b/controllers/apps/configuration/combine_upgrade_policy_test.go index d72a8a7dccd3..88877c32fdd4 100644 --- a/controllers/apps/configuration/combine_upgrade_policy_test.go +++ b/controllers/apps/configuration/combine_upgrade_policy_test.go @@ -57,12 +57,7 @@ var _ = Describe("Reconfigure CombineSyncPolicy", func() { withConfigSpec("for_test", map[string]string{ "key": "value", }), - withClusterComponent(2), - withCDComponent(appsv1alpha1.Consensus, []appsv1alpha1.ComponentConfigSpec{{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "for_test", - VolumeName: "test_volume", - }}})) + withClusterComponent(2)) Expect(testPolicyExecs.GetPolicyName()).Should(BeEquivalentTo(appsv1alpha1.DynamicReloadAndRestartPolicy)) status, err := testPolicyExecs.Upgrade(mockParam) @@ -81,12 +76,7 @@ var _ = Describe("Reconfigure CombineSyncPolicy", func() { withConfigSpec("for_test", map[string]string{ "key": "value", }), - withClusterComponent(2), - withCDComponent(appsv1alpha1.Consensus, []appsv1alpha1.ComponentConfigSpec{{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "for_test", - VolumeName: "test_volume", - }}})) + withClusterComponent(2)) Expect(testPolicyExecs.GetPolicyName()).Should(BeEquivalentTo(appsv1alpha1.DynamicReloadAndRestartPolicy)) status, err := testPolicyExecs.Upgrade(mockParam) diff --git a/controllers/apps/configuration/configuration_test.go b/controllers/apps/configuration/configuration_test.go index 73fef0ff6553..64342353d9ad 100644 --- a/controllers/apps/configuration/configuration_test.go +++ b/controllers/apps/configuration/configuration_test.go @@ -119,7 +119,7 @@ func mockReconcileResource() (*corev1.ConfigMap, *appsv1beta1.ConfigConstraint, By("Creating a cluster") clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). - AddComponentV2(defaultCompName, compDefObj.GetName()). + AddComponent(defaultCompName, compDefObj.GetName()). Create(&testCtx). GetObject() diff --git a/controllers/apps/configuration/parallel_upgrade_policy_test.go b/controllers/apps/configuration/parallel_upgrade_policy_test.go index 8e1cca3b066f..0e82aae8f783 100644 --- a/controllers/apps/configuration/parallel_upgrade_policy_test.go +++ b/controllers/apps/configuration/parallel_upgrade_policy_test.go @@ -25,7 +25,6 @@ import ( "github.com/golang/mock/gomock" - appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" cfgcore "github.com/apecloud/kubeblocks/pkg/configuration/core" cfgproto "github.com/apecloud/kubeblocks/pkg/configuration/proto" mock_proto "github.com/apecloud/kubeblocks/pkg/configuration/proto/mocks" @@ -69,13 +68,7 @@ var _ = Describe("Reconfigure ParallelPolicy", func() { withClusterComponent(3), withConfigSpec("for_test", map[string]string{ "a": "b", - }), - withCDComponent(appsv1alpha1.Consensus, []appsv1alpha1.ComponentConfigSpec{{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "for_test", - VolumeName: "test_volume", - }, - }})) + })) k8sMockClient.MockListMethod(testutil.WithListReturned( testutil.WithConstructListReturnedResult(fromPodObjectList( @@ -98,13 +91,7 @@ var _ = Describe("Reconfigure ParallelPolicy", func() { withClusterComponent(3), withConfigSpec("for_test", map[string]string{ "a": "b", - }), - withCDComponent(appsv1alpha1.Consensus, []appsv1alpha1.ComponentConfigSpec{{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "for_test", - VolumeName: "test_volume", - }, - }})) + })) // first failed getPodsError := cfgcore.MakeError("for grpc failed.") @@ -138,12 +125,7 @@ var _ = Describe("Reconfigure ParallelPolicy", func() { withClusterComponent(3), withConfigSpec("for_test", map[string]string{ "a": "b", - }), - withCDComponent(appsv1alpha1.Consensus, []appsv1alpha1.ComponentConfigSpec{{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "for_test", - VolumeName: "test_volume", - }}})) + })) k8sMockClient.MockListMethod(testutil.WithListReturned( testutil.WithConstructListReturnedResult( @@ -180,12 +162,7 @@ var _ = Describe("Reconfigure ParallelPolicy", func() { withClusterComponent(3), withConfigSpec("for_test", map[string]string{ "a": "b", - }), - withCDComponent(appsv1alpha1.Consensus, []appsv1alpha1.ComponentConfigSpec{{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "for_test", - VolumeName: "test_volume", - }}})) + })) setPods := newMockPodsWithInstanceSet(&mockParam.InstanceSetUnits[0], 5) k8sMockClient.MockListMethod(testutil.WithListReturned( @@ -198,26 +175,4 @@ var _ = Describe("Reconfigure ParallelPolicy", func() { Expect(status.Status).Should(BeEquivalentTo(ESFailedAndRetry)) }) }) - - // TODO(component) - PContext("parallel reconfigure policy test for not supported component", func() { - It("Should failed", func() { - // not support type - mockParam := newMockReconfigureParams("parallelPolicy", k8sMockClient.Client(), - withMockInstanceSet(2, nil), - withConfigSpec("for_test", map[string]string{ - "key": "value", - }), - withClusterComponent(2), - withCDComponent(appsv1alpha1.Stateless, []appsv1alpha1.ComponentConfigSpec{{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "for_test", - VolumeName: "test_volume", - }}})) - status, err := parallelPolicy.Upgrade(mockParam) - Expect(err).ShouldNot(Succeed()) - Expect(err.Error()).Should(ContainSubstring("not supported component workload type")) - Expect(status.Status).Should(BeEquivalentTo(ESNotSupport)) - }) - }) }) diff --git a/controllers/apps/configuration/policy_util_test.go b/controllers/apps/configuration/policy_util_test.go index 3c6b663e8b09..4fbd815dd635 100644 --- a/controllers/apps/configuration/policy_util_test.go +++ b/controllers/apps/configuration/policy_util_test.go @@ -21,7 +21,6 @@ package configuration import ( "fmt" - "time" "github.com/sethvargo/go-password/password" corev1 "k8s.io/api/core/v1" @@ -152,33 +151,6 @@ func withConfigPatch(patch map[string]string) ParamsOps { } } -func withCDComponent(compType appsv1alpha1.WorkloadType, tpls []appsv1alpha1.ComponentConfigSpec) ParamsOps { - return func(params *reconfigureParams) { - params.Component = &appsv1alpha1.ClusterComponentDefinition{ - WorkloadType: compType, - Name: string(compType), - } - if compType == appsv1alpha1.Consensus || compType == appsv1alpha1.Replication { - params.Component.RSMSpec = &appsv1alpha1.RSMSpec{ - Roles: []workloads.ReplicaRole{ - { - Name: "leader", - IsLeader: true, - AccessMode: workloads.ReadWriteMode, - CanVote: true, - }, - { - Name: "follower", - IsLeader: false, - AccessMode: workloads.ReadonlyMode, - CanVote: true, - }, - }, - } - } - } -} - func newMockReconfigureParams(testName string, cli client.Client, paramOps ...ParamsOps) reconfigureParams { params := reconfigureParams{ Restart: true, @@ -251,26 +223,6 @@ func withReadyPod(rMin, rMax int) PodOptions { } } -func withAvailablePod(rMin, rMax int) PodOptions { - return func(pod *corev1.Pod, index int) { - if index < rMin || index >= rMax { - return - } - - if pod.Status.Conditions == nil { - pod.Status.Conditions = make([]corev1.PodCondition, 0) - } - - h, _ := time.ParseDuration("-1h") - pod.Status.Conditions = append(pod.Status.Conditions, corev1.PodCondition{ - Type: corev1.PodReady, - Status: corev1.ConditionTrue, - LastTransitionTime: metav1.NewTime(time.Now().Add(h)), - }) - pod.Status.Phase = corev1.PodRunning - } -} - func fromPodObjectList(pods []corev1.Pod) []runtime.Object { objs := make([]runtime.Object, len(pods)) for i := 0; i < len(pods); i++ { diff --git a/controllers/apps/configuration/reconfigure_policy.go b/controllers/apps/configuration/reconfigure_policy.go index 0f806f6d7a3a..849db0c55fc3 100644 --- a/controllers/apps/configuration/reconfigure_policy.go +++ b/controllers/apps/configuration/reconfigure_policy.go @@ -107,10 +107,6 @@ type reconfigureParams struct { // Associated component for component and component definition. SynthesizedComponent *component.SynthesizedComponent - // Associated component for clusterdefinition. - // TODO(xingran): remove this field when test case is refactored. - Component *appsv1alpha1.ClusterComponentDefinition - // List of InstanceSet using this config template. InstanceSetUnits []workloads.InstanceSet } diff --git a/controllers/apps/configuration/rolling_upgrade_policy.go b/controllers/apps/configuration/rolling_upgrade_policy.go index aaf59c06d400..3c0d053562d6 100644 --- a/controllers/apps/configuration/rolling_upgrade_policy.go +++ b/controllers/apps/configuration/rolling_upgrade_policy.go @@ -63,10 +63,7 @@ func canPerformUpgrade(pods []corev1.Pod, params reconfigureParams) bool { // TODO(xingran&zhangtao): review this logic return len(pods) == target - /* if params.WorkloadType() == appsv1alpha1.Consensus { - params.Ctx.Log.Info(fmt.Sprintf("wait for consensus component is ready, %d pods are ready, and the expected replicas is %d.", len(pods), target)) - return false - } + /* if len(pods) < target { params.Ctx.Log.Info(fmt.Sprintf("component pods are not all ready, %d pods are ready, which is less than the expected replicas(%d).", len(pods), target)) return false diff --git a/controllers/apps/configuration/rolling_upgrade_policy_test.go b/controllers/apps/configuration/rolling_upgrade_policy_test.go deleted file mode 100644 index a1959b6a288b..000000000000 --- a/controllers/apps/configuration/rolling_upgrade_policy_test.go +++ /dev/null @@ -1,248 +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 configuration - -import ( - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - "github.com/golang/mock/gomock" - apps "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime" - metautil "k8s.io/apimachinery/pkg/util/intstr" - "sigs.k8s.io/controller-runtime/pkg/client" - - appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" - cfgproto "github.com/apecloud/kubeblocks/pkg/configuration/proto" - mock_proto "github.com/apecloud/kubeblocks/pkg/configuration/proto/mocks" - "github.com/apecloud/kubeblocks/pkg/constant" - testutil "github.com/apecloud/kubeblocks/pkg/testutil/k8s" -) - -var _ = Describe("Reconfigure RollingPolicy", func() { - - var ( - k8sMockClient *testutil.K8sClientMockHelper - mockParam reconfigureParams - reconfigureClient *mock_proto.MockReconfigureClient - - defaultReplica = 3 - rollingPolicy = upgradePolicyMap[appsv1alpha1.RollingPolicy] - ) - - updateLabelPatch := func(pods []corev1.Pod, patch *corev1.Pod) { - patchKey := client.ObjectKeyFromObject(patch) - for i := range pods { - orgPod := &pods[i] - if client.ObjectKeyFromObject(orgPod) == patchKey { - orgPod.Labels = patch.Labels - break - } - } - } - - createReconfigureParam := func(compType appsv1alpha1.WorkloadType, replicas int) reconfigureParams { - return newMockReconfigureParams("rollingPolicy", k8sMockClient.Client(), - withMockInstanceSet(replicas, nil), - withConfigSpec("for_test", map[string]string{ - "key": "value", - }), - withGRPCClient(func(addr string) (cfgproto.ReconfigureClient, error) { - return reconfigureClient, nil - }), - withClusterComponent(replicas), - withCDComponent(compType, []appsv1alpha1.ComponentConfigSpec{{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "for_test", - VolumeName: "test_volume", - }}})) - } - - BeforeEach(func() { - k8sMockClient = testutil.NewK8sMockClient() - reconfigureClient = mock_proto.NewMockReconfigureClient(k8sMockClient.Controller()) - mockParam = createReconfigureParam(appsv1alpha1.Consensus, defaultReplica) - }) - - AfterEach(func() { - // Add any teardown steps that needs to be executed after each test - k8sMockClient.Finish() - }) - - // TODO(component) - PContext("consensus rolling reconfigure policy test", func() { - It("Should success without error", func() { - Expect(rollingPolicy.GetPolicyName()).Should(BeEquivalentTo("rolling")) - - mockLeaderLabel := func(pod *corev1.Pod, i int) { - if pod.Labels == nil { - pod.Labels = make(map[string]string, 1) - } - if i == 1 { - pod.Labels[constant.RoleLabelKey] = "leader" - } else { - pod.Labels[constant.RoleLabelKey] = "follower" - } - } - - acc := 0 - mockPods := [][]corev1.Pod{ - newMockPodsWithInstanceSet(&mockParam.InstanceSetUnits[0], 2), - newMockPodsWithInstanceSet(&mockParam.InstanceSetUnits[0], 5, - mockLeaderLabel), - newMockPodsWithInstanceSet(&mockParam.InstanceSetUnits[0], 3, - withReadyPod(0, 0), - withAvailablePod(0, 3), - mockLeaderLabel), - } - - k8sMockClient.MockListMethod(testutil.WithListReturned( - testutil.WithConstructListSequenceResult([][]runtime.Object{ - fromPodObjectList(mockPods[0]), - fromPodObjectList(mockPods[1]), - fromPodObjectList(mockPods[2]), - }, func(sequence int, r []runtime.Object) { acc = sequence }), testutil.WithAnyTimes())) - - k8sMockClient.MockPatchMethod(testutil.WithPatchReturned(func(obj client.Object, patch client.Patch) error { - pod, _ := obj.(*corev1.Pod) - // mock patch - updateLabelPatch(mockPods[acc], pod) - return nil - }, testutil.WithAnyTimes())) - - reconfigureClient.EXPECT().StopContainer(gomock.Any(), gomock.Any()). - Return(&cfgproto.StopContainerResponse{}, nil). - AnyTimes() - - // mock wait the number of pods to target replicas - status, err := rollingPolicy.Upgrade(mockParam) - Expect(err).Should(Succeed()) - Expect(status.Status).Should(BeEquivalentTo(ESRetry)) - - // mock wait the number of pods to ready status - status, err = rollingPolicy.Upgrade(mockParam) - Expect(err).Should(Succeed()) - Expect(status.Status).Should(BeEquivalentTo(ESRetry)) - - // upgrade pod-0 - status, err = rollingPolicy.Upgrade(mockParam) - Expect(err).Should(Succeed()) - Expect(status.Status).Should(BeEquivalentTo(ESRetry)) - Expect(mockPods[acc][0].Labels[mockParam.getConfigKey()]).Should(BeEquivalentTo(mockParam.getTargetVersionHash())) - Expect(mockPods[acc][1].Labels[mockParam.getConfigKey()]).ShouldNot(BeEquivalentTo(mockParam.getTargetVersionHash())) - Expect(mockPods[acc][2].Labels[mockParam.getConfigKey()]).ShouldNot(BeEquivalentTo(mockParam.getTargetVersionHash())) - - // upgrade pod-2 - status, err = rollingPolicy.Upgrade(mockParam) - Expect(err).Should(Succeed()) - Expect(status.Status).Should(BeEquivalentTo(ESRetry)) - Expect(mockPods[acc][2].Labels[mockParam.getConfigKey()]).Should(BeEquivalentTo(mockParam.getTargetVersionHash())) - Expect(mockPods[acc][1].Labels[mockParam.getConfigKey()]).ShouldNot(BeEquivalentTo(mockParam.getTargetVersionHash())) - - // upgrade pod-1 - status, err = rollingPolicy.Upgrade(mockParam) - Expect(err).Should(Succeed()) - Expect(status.Status).Should(BeEquivalentTo(ESRetry)) - Expect(mockPods[acc][1].Labels[mockParam.getConfigKey()]).Should(BeEquivalentTo(mockParam.getTargetVersionHash())) - - // finish check, not upgrade - status, err = rollingPolicy.Upgrade(mockParam) - Expect(err).Should(Succeed()) - Expect(status.Status).Should(BeEquivalentTo(ESNone)) - }) - }) - - Context("statefulSet rolling reconfigure policy test", func() { - It("Should success without error", func() { - - // for mock its - var pods []corev1.Pod - { - mockParam.Component.WorkloadType = appsv1alpha1.Stateful - mockParam.Component.StatefulSpec = &appsv1alpha1.StatefulSetSpec{ - LLUpdateStrategy: &apps.StatefulSetUpdateStrategy{ - RollingUpdate: &apps.RollingUpdateStatefulSetStrategy{ - MaxUnavailable: func() *metautil.IntOrString { v := metautil.FromString("100%"); return &v }(), - }, - }, - } - pods = newMockPodsWithInstanceSet(&mockParam.InstanceSetUnits[0], defaultReplica) - } - - k8sMockClient.MockListMethod(testutil.WithListReturned( - testutil.WithConstructListReturnedResult(fromPodObjectList(pods)), - testutil.WithMinTimes(3))) - - k8sMockClient.MockPatchMethod(testutil.WithPatchReturned(func(obj client.Object, patch client.Patch) error { - pod, _ := obj.(*corev1.Pod) - updateLabelPatch(pods, pod) - return nil - }, testutil.WithTimes(defaultReplica))) - - reconfigureClient.EXPECT().StopContainer(gomock.Any(), gomock.Any()). - Return(&cfgproto.StopContainerResponse{}, nil). - Times(defaultReplica) - - // mock wait the number of pods to target replicas - status, err := rollingPolicy.Upgrade(mockParam) - Expect(err).Should(Succeed()) - Expect(status.Status).Should(BeEquivalentTo(ESRetry)) - - // finish check, not finished - status, err = rollingPolicy.Upgrade(mockParam) - Expect(err).Should(Succeed()) - Expect(status.Status).Should(BeEquivalentTo(ESRetry)) - - // mock async update state - go func() { - f := withAvailablePod(0, len(pods)) - for i := range pods { - f(&pods[i], i) - } - }() - - // finish check, not finished - Eventually(func() bool { - status, err = rollingPolicy.Upgrade(mockParam) - Expect(err).Should(Succeed()) - Expect(status.Status).Should(BeElementOf(ESNone, ESRetry)) - return status.Status == ESNone - }).Should(BeTrue()) - - status, err = rollingPolicy.Upgrade(mockParam) - Expect(status.Status).Should(BeEquivalentTo(ESNone)) - }) - }) - - // TODO(component) - // PContext("rolling reconfigure policy test for not supported component", func() { - // It("Should failed", func() { - // // not supported type - // _ = mockParam - // k8sMockClient.MockListMethod(testutil.WithSucceed(testutil.WithTimes(0))) - // - // status, err := rollingPolicy.Upgrade(createReconfigureParam(appsv1alpha1.Stateless, defaultReplica)) - // Expect(err).ShouldNot(Succeed()) - // Expect(err.Error()).Should(ContainSubstring("not supported component workload type")) - // Expect(status.Status).Should(BeEquivalentTo(ESNotSupport)) - // }) - // }) -}) diff --git a/controllers/apps/configuration/simple_policy_test.go b/controllers/apps/configuration/simple_policy_test.go index c04087398e9e..2ccf1daf065c 100644 --- a/controllers/apps/configuration/simple_policy_test.go +++ b/controllers/apps/configuration/simple_policy_test.go @@ -63,12 +63,7 @@ var _ = Describe("Reconfigure simplePolicy", func() { withConfigSpec("for_test", map[string]string{ "key": "value", }), - withClusterComponent(2), - withCDComponent(appsv1alpha1.Consensus, []appsv1alpha1.ComponentConfigSpec{{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "for_test", - VolumeName: "test_volume", - }}})) + withClusterComponent(2)) // mock client update caller updateErr := core.MakeError("update failed!") @@ -126,13 +121,7 @@ var _ = Describe("Reconfigure simplePolicy", func() { withConfigSpec("for_test", map[string]string{ "key": "value", }), - withClusterComponent(2), - withCDComponent(appsv1alpha1.Replication, []appsv1alpha1.ComponentConfigSpec{{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "for_test", - VolumeName: "test_volume", - }}}), - ) + withClusterComponent(2)) k8sMockClient.MockPatchMethod(testutil.WithSucceed(testutil.WithAnyTimes())) k8sMockClient.MockListMethod(testutil.WithListReturned( @@ -165,12 +154,7 @@ var _ = Describe("Reconfigure simplePolicy", func() { withConfigSpec("for_test", map[string]string{ "key": "value", }), - withClusterComponent(2), - withCDComponent(appsv1alpha1.Stateless, []appsv1alpha1.ComponentConfigSpec{{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "for_test", - VolumeName: "test_volume", - }}})) + withClusterComponent(2)) updateErr := core.MakeError("update failed!") k8sMockClient.MockPatchMethod( diff --git a/controllers/apps/configuration/sync_upgrade_policy_test.go b/controllers/apps/configuration/sync_upgrade_policy_test.go index f2517f01c96a..77368a683e92 100644 --- a/controllers/apps/configuration/sync_upgrade_policy_test.go +++ b/controllers/apps/configuration/sync_upgrade_policy_test.go @@ -28,7 +28,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" appsv1beta1 "github.com/apecloud/kubeblocks/apis/apps/v1beta1" cfgproto "github.com/apecloud/kubeblocks/pkg/configuration/proto" mock_proto "github.com/apecloud/kubeblocks/pkg/configuration/proto/mocks" @@ -69,13 +68,7 @@ var _ = Describe("Reconfigure OperatorSyncPolicy", func() { withConfigPatch(map[string]string{ "a": "c b e f", }), - withClusterComponent(3), - withCDComponent(appsv1alpha1.Consensus, []appsv1alpha1.ComponentConfigSpec{{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "for_test", - VolumeName: "test_volume", - }, - }})) + withClusterComponent(3)) By("mock client get pod caller") k8sMockClient.MockListMethod(testutil.WithListReturned( @@ -126,13 +119,7 @@ var _ = Describe("Reconfigure OperatorSyncPolicy", func() { withConfigPatch(map[string]string{ "a": "c b e f", }), - withClusterComponent(3), - withCDComponent(appsv1alpha1.Consensus, []appsv1alpha1.ComponentConfigSpec{{ - ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{ - Name: "for_test", - VolumeName: "test_volume", - }, - }})) + withClusterComponent(3)) // add selector mockParam.ConfigConstraint.ReloadAction = &appsv1beta1.ReloadAction{ diff --git a/controllers/apps/operations/backup_test.go b/controllers/apps/operations/backup_test.go index 02326b6378da..614d7eefa412 100644 --- a/controllers/apps/operations/backup_test.go +++ b/controllers/apps/operations/backup_test.go @@ -34,9 +34,9 @@ import ( var _ = Describe("Backup OpsRequest", func() { var ( - randomStr = testCtx.GetRandomStr() - clusterDefinitionName = "cluster-definition-for-ops-" + randomStr //nolint:goconst - clusterName = "cluster-for-ops-" + randomStr //nolint:goconst + randomStr = testCtx.GetRandomStr() + compDefName = "test-compdef-" + randomStr + clusterName = "test-cluster-" + randomStr //nolint:goconst ) cleanEnv := func() { @@ -47,7 +47,7 @@ var _ = Describe("Backup OpsRequest", func() { By("clean resources") // delete cluster(and all dependent sub-resources), cluster definition - testapps.ClearClusterResources(&testCtx) + testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest resources inNS := client.InNamespace(testCtx.DefaultNamespace) @@ -65,9 +65,10 @@ var _ = Describe("Backup OpsRequest", func() { opsRes *OpsResource reqCtx intctrlutil.RequestCtx ) + BeforeEach(func() { By("init operations resources ") - opsRes, _, _ = initOperationsResources(clusterDefinitionName, clusterName) + opsRes, _, _ = initOperationsResources(compDefName, clusterName) reqCtx = intctrlutil.RequestCtx{Ctx: testCtx.Ctx} }) diff --git a/controllers/apps/operations/custom_test.go b/controllers/apps/operations/custom_test.go index 05f11782c3b1..f43266c40d35 100644 --- a/controllers/apps/operations/custom_test.go +++ b/controllers/apps/operations/custom_test.go @@ -36,15 +36,14 @@ import ( var _ = Describe("CustomOps", func() { var ( - randomStr = testCtx.GetRandomStr() - clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterName = "cluster-for-ops-" + randomStr - compDefName = "apecloud-mysql" - opsResource *OpsResource - compObj *appsv1alpha1.Component - opsDef *appsv1alpha1.OpsDefinition - reqCtx intctrlutil.RequestCtx - cluster *appsv1alpha1.Cluster + randomStr = testCtx.GetRandomStr() + compDefName = "test-compdef-" + randomStr + clusterName = "test-cluster-" + randomStr + opsResource *OpsResource + compObj *appsv1alpha1.Component + opsDef *appsv1alpha1.OpsDefinition + reqCtx intctrlutil.RequestCtx + cluster *appsv1alpha1.Cluster ) cleanEnv := func() { @@ -55,7 +54,7 @@ var _ = Describe("CustomOps", func() { By("clean resources") // delete cluster(and all dependent sub-resources), cluster definition - testapps.ClearClusterResources(&testCtx) + testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest resources inNS := client.InNamespace(testCtx.DefaultNamespace) @@ -67,7 +66,6 @@ var _ = Describe("CustomOps", func() { // non-namespaced testapps.ClearResources(&testCtx, generics.OpsDefinitionSignature, ml) - testapps.ClearResources(&testCtx, generics.ComponentDefinitionSignature, ml) } BeforeEach(cleanEnv) @@ -103,10 +101,10 @@ var _ = Describe("CustomOps", func() { Create(&testCtx). GetObject() - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefinitionName). - WithRandomName().AddComponentV2(consensusComp, componentDefObj.Name).SetReplicas(1).Create(&testCtx).GetObject() + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). + WithRandomName().AddComponent(defaultCompName, componentDefObj.Name).SetReplicas(1).Create(&testCtx).GetObject() - fullCompName := constant.GenerateClusterComponentName(cluster.Name, consensusComp) + fullCompName := constant.GenerateClusterComponentName(cluster.Name, defaultCompName) compObj = testapps.NewComponentFactory(testCtx.DefaultNamespace, fullCompName, compDefName). AddLabels(constant.AppInstanceLabelKey, cluster.Name). AddLabels(constant.KBAppClusterUIDLabelKey, string(cluster.UID)). @@ -145,7 +143,7 @@ var _ = Describe("CustomOps", func() { {Name: "test", Value: "test"}, } By("validate json schema, 'sql' parameter is required") - ops := createCustomOps(consensusComp, params) + ops := createCustomOps(defaultCompName, params) opsResource.OpsRequest = ops _, _ = GetOpsManager().Reconcile(reqCtx, k8sClient, opsResource) Expect(ops.Status.Conditions).ShouldNot(BeEmpty()) @@ -159,7 +157,7 @@ var _ = Describe("CustomOps", func() { params := []appsv1alpha1.Parameter{ {Name: "sql", Value: "select 1"}, } - ops := createCustomOps(consensusComp, params) + ops := createCustomOps(defaultCompName, params) By("validate pass for json schema") _, err := GetOpsManager().Do(reqCtx, k8sClient, opsResource) @@ -170,8 +168,8 @@ var _ = Describe("CustomOps", func() { opsResource.OpsRequest = ops _, err = GetOpsManager().Reconcile(reqCtx, k8sClient, opsResource) Expect(err).ShouldNot(HaveOccurred()) - Expect(ops.Status.Components[consensusComp].PreCheckResult.Pass).Should(BeFalse()) - Expect(ops.Status.Components[consensusComp].PreCheckResult.Message).Should(ContainSubstring("Component is not in Running status")) + Expect(ops.Status.Components[defaultCompName].PreCheckResult.Pass).Should(BeFalse()) + Expect(ops.Status.Components[defaultCompName].PreCheckResult.Message).Should(ContainSubstring("Component is not in Running status")) Expect(ops.Status.Phase).Should(Equal(appsv1alpha1.OpsFailedPhase)) }) @@ -180,7 +178,7 @@ var _ = Describe("CustomOps", func() { params := []appsv1alpha1.Parameter{ {Name: "sql", Value: "select 1"}, } - ops := createCustomOps(consensusComp, params) + ops := createCustomOps(defaultCompName, params) By("mock component is Running") Expect(testapps.ChangeObjStatus(&testCtx, compObj, func() { @@ -201,7 +199,7 @@ var _ = Describe("CustomOps", func() { By("reconcile once and make the action succeed") _, err = GetOpsManager().Reconcile(reqCtx, k8sClient, opsResource) Expect(err).ShouldNot(HaveOccurred()) - Expect(opsResource.OpsRequest.Status.Components[consensusComp].ProgressDetails[0].Status).Should(Equal(appsv1alpha1.SucceedProgressStatus)) + Expect(opsResource.OpsRequest.Status.Components[defaultCompName].ProgressDetails[0].Status).Should(Equal(appsv1alpha1.SucceedProgressStatus)) By("reconcile again and make the opsRequest succeed") _, err = GetOpsManager().Reconcile(reqCtx, k8sClient, opsResource) diff --git a/controllers/apps/operations/datascript.go b/controllers/apps/operations/datascript.go index 87ef2955a81d..cf84ba308471 100644 --- a/controllers/apps/operations/datascript.go +++ b/controllers/apps/operations/datascript.go @@ -81,24 +81,26 @@ func (o DataScriptOpsHandler) Action(reqCtx intctrlutil.RequestCtx, cli client.C } return err } - // get componentDef - componentDef := clusterDef.GetComponentDefByName(component.ComponentDefRef) - if componentDef == nil { - return intctrlutil.NewFatalError(fmt.Sprintf("componentDef %s not found in clusterDef %s", component.ComponentDefRef, clusterDef.Name)) - } - - // create jobs - var jobs []*batchv1.Job - // TODO(v1.0): character-type - if jobs, err = buildDataScriptJobs(reqCtx, cli, opsResource.Cluster, component, opsRequest, ""); err != nil { - return err - } - for _, job := range jobs { - if err = cli.Create(reqCtx.Ctx, job); err != nil { - return err - } - } - return nil + // TODO(v1.0): how to? + //// get componentDef + // componentDef := clusterDef.GetComponentDefByName(component.ComponentDefRef) + // if componentDef == nil { + // return intctrlutil.NewFatalError(fmt.Sprintf("componentDef %s not found in clusterDef %s", component.ComponentDefRef, clusterDef.Name)) + // } + return intctrlutil.NewFatalError(fmt.Sprintf("componentDef %s not found in clusterDef %s", component.ComponentDefRef, clusterDef.Name)) + + //// create jobs + // var jobs []*batchv1.Job + //// TODO(v1.0): character-type + // if jobs, err = buildDataScriptJobs(reqCtx, cli, opsResource.Cluster, component, opsRequest, ""); err != nil { + // return err + // } + // for _, job := range jobs { + // if err = cli.Create(reqCtx.Ctx, job); err != nil { + // return err + // } + // } + // return nil } // ReconcileAction implements OpsHandler.ReconcileAction diff --git a/controllers/apps/operations/datascript_test.go b/controllers/apps/operations/datascript_test.go index 8b93043b0adb..900943c291b1 100644 --- a/controllers/apps/operations/datascript_test.go +++ b/controllers/apps/operations/datascript_test.go @@ -42,9 +42,9 @@ import ( var _ = Describe("DataScriptOps", func() { var ( - randomStr = testCtx.GetRandomStr() - clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterName = "cluster-for-ops-" + randomStr + randomStr = testCtx.GetRandomStr() + compDefName = "test-compdef-" + randomStr + clusterName = "test-cluster-" + randomStr clusterObj *appsv1alpha1.Cluster opsResource *OpsResource @@ -63,7 +63,7 @@ var _ = Describe("DataScriptOps", func() { By("clean resources") // delete cluster(and all dependent sub-resources), cluster definition - testapps.ClearClusterResources(&testCtx) + testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest resources inNS := client.InNamespace(testCtx.DefaultNamespace) @@ -123,13 +123,7 @@ var _ = Describe("DataScriptOps", func() { Expect(testapps.ChangeObjStatus(&testCtx, clusterObj, func() { clusterObj.Status.Phase = phase clusterObj.Status.Components = map[string]appsv1alpha1.ClusterComponentStatus{ - consensusComp: { - Phase: compPhase, - }, - statelessComp: { - Phase: compPhase, - }, - statefulComp: { + defaultCompName: { Phase: compPhase, }, } @@ -139,8 +133,7 @@ var _ = Describe("DataScriptOps", func() { Context("with Cluster which has MySQL ConsensusSet", func() { BeforeEach(func() { By("mock cluster") - _, clusterObj = testapps.InitClusterWithHybridComps(&testCtx, clusterDefinitionName, - clusterName, statelessComp, statefulComp, consensusComp) + _, _, clusterObj = initOperationsResources(compDefName, clusterName) By("init opsResource") opsResource = &OpsResource{ @@ -170,7 +163,7 @@ var _ = Describe("DataScriptOps", func() { By("create a datascript ops with ttlSecondsBeforeAbort=0") // create a datascript ops with ttlSecondsBeforeAbort=0 - ops := createClusterDatascriptOps(consensusComp, 0) + ops := createClusterDatascriptOps(defaultCompName, 0) opsKey := client.ObjectKeyFromObject(ops) patchOpsPhase(opsKey, appsv1alpha1.OpsCreatingPhase) Expect(k8sClient.Get(testCtx.Ctx, opsKey, ops)).Should(Succeed()) @@ -189,7 +182,7 @@ var _ = Describe("DataScriptOps", func() { By("create a datascript ops with ttlSecondsBeforeAbort=100") // create a datascript ops with ttlSecondsBeforeAbort=0 - ops := createClusterDatascriptOps(consensusComp, 100) + ops := createClusterDatascriptOps(defaultCompName, 100) opsKey := client.ObjectKeyFromObject(ops) patchOpsPhase(opsKey, appsv1alpha1.OpsPendingPhase) Expect(k8sClient.Get(testCtx.Ctx, opsKey, ops)).Should(Succeed()) @@ -203,12 +196,13 @@ var _ = Describe("DataScriptOps", func() { Expect(ops.Status.Phase).Should(Equal(prevOpsStatus)) }) - It("create a datascript ops on running cluster", func() { + // TODO(v1.0): depends on clusterDefinition exist? + PIt("create a datascript ops on running cluster", func() { By("patch cluster to running") patchClusterStatus(appsv1alpha1.RunningClusterPhase) By("create a datascript ops with ttlSecondsBeforeAbort=0") - ops := createClusterDatascriptOps(consensusComp, 0) + ops := createClusterDatascriptOps(defaultCompName, 0) opsResource.OpsRequest = ops opsKey := client.ObjectKeyFromObject(ops) patchOpsPhase(opsKey, appsv1alpha1.OpsCreatingPhase) @@ -227,7 +221,7 @@ var _ = Describe("DataScriptOps", func() { patchClusterStatus(appsv1alpha1.RunningClusterPhase) By("create a datascript ops with ttlSecondsBeforeAbort=0") - ops := createClusterDatascriptOps(consensusComp, 0) + ops := createClusterDatascriptOps(defaultCompName, 0) opsResource.OpsRequest = ops opsKey := client.ObjectKeyFromObject(ops) patchOpsPhase(opsKey, appsv1alpha1.OpsRunningPhase) @@ -236,7 +230,7 @@ var _ = Describe("DataScriptOps", func() { reqCtx.Req = reconcile.Request{NamespacedName: opsKey} By("mock a job, missing service, should fail") - comp := clusterObj.Spec.GetComponentByName(consensusComp) + comp := clusterObj.Spec.GetComponentByName(defaultCompName) _, err := buildDataScriptJobs(reqCtx, k8sClient, clusterObj, comp, ops, "mysql") Expect(err).Should(HaveOccurred()) @@ -318,7 +312,7 @@ var _ = Describe("DataScriptOps", func() { patchClusterStatus(appsv1alpha1.RunningClusterPhase) By("create a datascript ops with ttlSecondsBeforeAbort=0") - ops := createClusterDatascriptOps(consensusComp, 0) + ops := createClusterDatascriptOps(defaultCompName, 0) opsResource.OpsRequest = ops opsKey := client.ObjectKeyFromObject(ops) patchOpsPhase(opsKey, appsv1alpha1.OpsRunningPhase) @@ -326,7 +320,7 @@ var _ = Describe("DataScriptOps", func() { opsResource.OpsRequest = ops reqCtx.Req = reconcile.Request{NamespacedName: opsKey} - comp := clusterObj.Spec.GetComponentByName(consensusComp) + comp := clusterObj.Spec.GetComponentByName(defaultCompName) By("mock a service, should pass") serviceName := fmt.Sprintf("%s-%s", clusterObj.Name, comp.Name) service := &corev1.Service{ @@ -399,7 +393,7 @@ var _ = Describe("DataScriptOps", func() { ops := testapps.NewOpsRequestObj(opsName, testCtx.DefaultNamespace, clusterObj.Name, appsv1alpha1.DataScriptType) ops.Spec.ScriptSpec = &appsv1alpha1.ScriptSpec{ - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, Script: []string{"CREATE TABLE test (id INT);"}, ScriptFrom: &appsv1alpha1.ScriptFrom{ ConfigMapRef: []corev1.ConfigMapKeySelector{ diff --git a/controllers/apps/operations/expose_test.go b/controllers/apps/operations/expose_test.go index 6ec799e30248..5478342e07d8 100644 --- a/controllers/apps/operations/expose_test.go +++ b/controllers/apps/operations/expose_test.go @@ -65,7 +65,7 @@ var _ = Describe("", func() { Context("Test OpsRequest", func() { It("Test expose OpsRequest", func() { reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx} - opsRes, _, clusterObject := initOperationsResources2(compDefName, clusterName) + opsRes, _, clusterObject := initOperationsResources(compDefName, clusterName) By("create Expose opsRequest") ops := testapps.NewOpsRequestObj("expose-expose-"+randomStr, testCtx.DefaultNamespace, @@ -103,7 +103,7 @@ var _ = Describe("", func() { It("Test expose OpsRequest with empty ComponentName", func() { reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx} - opsRes, _, clusterObject := initOperationsResources2(compDefName, clusterName) + opsRes, _, clusterObject := initOperationsResources(compDefName, clusterName) By("create Expose opsRequest") ops := testapps.NewOpsRequestObj("expose-expose-"+randomStr, testCtx.DefaultNamespace, diff --git a/controllers/apps/operations/horizontal_scaling_test.go b/controllers/apps/operations/horizontal_scaling_test.go index 1cfe932e67d3..1bafe43d1fe2 100644 --- a/controllers/apps/operations/horizontal_scaling_test.go +++ b/controllers/apps/operations/horizontal_scaling_test.go @@ -44,10 +44,10 @@ import ( var _ = Describe("HorizontalScaling OpsRequest", func() { var ( - randomStr = testCtx.GetRandomStr() - clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterName = "cluster-for-ops-" + randomStr - insTplName = "foo" + randomStr = testCtx.GetRandomStr() + compDefName = "test-compdef-" + randomStr + clusterName = "test-cluster-" + randomStr + insTplName = "foo" ) cleanEnv := func() { @@ -58,7 +58,7 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { By("clean resources") // delete cluster(and all dependent sub-resources), cluster definition - testapps.ClearClusterResources(&testCtx) + testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest resources inNS := client.InNamespace(testCtx.DefaultNamespace) @@ -86,21 +86,21 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { changeClusterSpec func(cluster *appsv1alpha1.Cluster), horizontalScaling appsv1alpha1.HorizontalScaling) (*OpsResource, []*corev1.Pod) { By("init operations resources with CLusterDefinition/Hybrid components Cluster/consensus Pods") - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) - its := testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) + opsRes, _, _ := initOperationsResources(compDefName, clusterName) + its := testapps.MockInstanceSetComponent(&testCtx, clusterName, defaultCompName) if changeClusterSpec != nil { Expect(testapps.ChangeObj(&testCtx, opsRes.Cluster, func(cluster *appsv1alpha1.Cluster) { changeClusterSpec(cluster) })).Should(Succeed()) } - pods := testapps.MockInstanceSetPods(&testCtx, its, opsRes.Cluster, consensusComp) + pods := testapps.MockInstanceSetPods(&testCtx, its, opsRes.Cluster, defaultCompName) By("create opsRequest for horizontal scaling of consensus component") initClusterAnnotationAndPhaseForOps(opsRes) - horizontalScaling.ComponentName = consensusComp + horizontalScaling.ComponentName = defaultCompName opsRes.OpsRequest = createHorizontalScaling(clusterName, horizontalScaling) // set ops phase to Pending opsRes.OpsRequest.Status.Phase = appsv1alpha1.OpsPendingPhase - mockComponentIsOperating(opsRes.Cluster, appsv1alpha1.UpdatingClusterCompPhase, consensusComp) + mockComponentIsOperating(opsRes.Cluster, appsv1alpha1.UpdatingClusterCompPhase, defaultCompName) By("expect for opsRequest phase is Creating after doing action") _, err := GetOpsManager().Do(reqCtx, k8sClient, opsRes) @@ -114,7 +114,7 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { if horizontalScaling.Replicas == nil { return } - lastCompConfiguration := opsRes.OpsRequest.Status.LastConfiguration.Components[consensusComp] + lastCompConfiguration := opsRes.OpsRequest.Status.LastConfiguration.Components[defaultCompName] var expectedCompReplicas int32 switch { case horizontalScaling.ScaleIn != nil: @@ -124,7 +124,7 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { default: expectedCompReplicas = *horizontalScaling.Replicas } - g.Expect(tmpCluster.Spec.GetComponentByName(consensusComp).Replicas).Should(BeEquivalentTo(expectedCompReplicas)) + g.Expect(tmpCluster.Spec.GetComponentByName(defaultCompName).Replicas).Should(BeEquivalentTo(expectedCompReplicas)) })).Should(Succeed()) By("Test OpsManager.Reconcile function when horizontal scaling OpsRequest is Running") @@ -147,7 +147,7 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { _, err := GetOpsManager().Reconcile(reqCtx, k8sClient, opsRes) Expect(err).ShouldNot(HaveOccurred()) Expect(opsRes.OpsRequest.Status.Phase).Should(Equal(appsv1alpha1.OpsCancelledPhase)) - opsProgressDetails := opsRes.OpsRequest.Status.Components[consensusComp].ProgressDetails + opsProgressDetails := opsRes.OpsRequest.Status.Components[defaultCompName].ProgressDetails Expect(opsRes.OpsRequest.Status.Progress).Should(Equal("2/2")) Expect(len(opsProgressDetails)).Should(Equal(2)) } @@ -166,8 +166,8 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { prefix = "-" + templateName } for i := range ordinals { - podName := fmt.Sprintf("%s-%s%s-%d", clusterName, consensusComp, prefix, ordinals[i]) - pod := testapps.MockInstanceSetPod(&testCtx, nil, clusterName, consensusComp, podName, "follower", "Readonly") + podName := fmt.Sprintf("%s-%s%s-%d", clusterName, defaultCompName, prefix, ordinals[i]) + pod := testapps.MockInstanceSetPod(&testCtx, nil, clusterName, defaultCompName, podName, "follower", "Readonly") pods = append(pods, pod) } return pods @@ -180,7 +180,7 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx} opsRes, podList := commonHScaleConsensusCompTest(reqCtx, changeClusterSpec, horizontalScaling) mockHScale(podList) - testapps.MockInstanceSetStatus(testCtx, opsRes.Cluster, consensusComp) + testapps.MockInstanceSetStatus(testCtx, opsRes.Cluster, defaultCompName) checkOpsRequestPhaseIsSucceed(reqCtx, opsRes) } @@ -198,7 +198,7 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { By("create the pod") pod = createPods("", 3)[0] } - testapps.MockInstanceSetStatus(testCtx, opsRes.Cluster, consensusComp) + testapps.MockInstanceSetStatus(testCtx, opsRes.Cluster, defaultCompName) By("cancel HScale opsRequest after one pod has been deleted") cancelOpsRequest(reqCtx, opsRes, time.Now().Add(-1*time.Second)) if isScaleDown { @@ -208,11 +208,11 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { By("delete the pod for rollback") deletePods(pod) } - testapps.MockInstanceSetStatus(testCtx, opsRes.Cluster, consensusComp) + testapps.MockInstanceSetStatus(testCtx, opsRes.Cluster, defaultCompName) By("expect for opsRequest phase is Succeed after pods has been scaled and component phase is Running") mockConsensusCompToRunning(opsRes) checkCancelledSucceed(reqCtx, opsRes) - Expect(findStatusProgressDetail(opsRes.OpsRequest.Status.Components[consensusComp].ProgressDetails, + Expect(findStatusProgressDetail(opsRes.OpsRequest.Status.Components[defaultCompName].ProgressDetails, getProgressObjectKey(constant.PodKind, pod.Name)).Status).Should(Equal(appsv1alpha1.SucceedProgressStatus)) } @@ -278,7 +278,7 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { setClusterCompSpec := func(cluster *appsv1alpha1.Cluster, instances []appsv1alpha1.InstanceTemplate, offlineInstances []string) { for i, v := range cluster.Spec.ComponentSpecs { - if v.Name == consensusComp { + if v.Name == defaultCompName { cluster.Spec.ComponentSpecs[i].OfflineInstances = offlineInstances cluster.Spec.ComponentSpecs[i].Instances = instances break @@ -293,7 +293,7 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx} opsRes, podList := commonHScaleConsensusCompTest(reqCtx, changeClusterSpec, horizontalScaling) By("verify cluster spec is correct") - targetSpec := opsRes.Cluster.Spec.GetComponentByName(consensusComp) + targetSpec := opsRes.Cluster.Spec.GetComponentByName(defaultCompName) Expect(targetSpec.OfflineInstances).Should(HaveLen(len(expectOfflineInstances))) expectedOfflineInsSet := sets.New(expectOfflineInstances...) for _, v := range targetSpec.OfflineInstances { @@ -303,13 +303,13 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { By("mock specified pods deleted") mockHScale(podList) - testapps.MockInstanceSetStatus(testCtx, opsRes.Cluster, consensusComp) + testapps.MockInstanceSetStatus(testCtx, opsRes.Cluster, defaultCompName) checkOpsRequestPhaseIsSucceed(reqCtx, opsRes) return opsRes } It("test offline the specified pod of the component", func() { - toDeletePodName := fmt.Sprintf("%s-%s-1", clusterName, consensusComp) + toDeletePodName := fmt.Sprintf("%s-%s-1", clusterName, defaultCompName) offlineInstances := []string{toDeletePodName} opsRes := testHScaleWithSpecifiedPod(func(cluster *appsv1alpha1.Cluster) { setClusterCompSpec(cluster, []appsv1alpha1.InstanceTemplate{ @@ -328,7 +328,7 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { }) It("test offline the specified pod and scale out another replicas", func() { - toDeletePodName := fmt.Sprintf("%s-%s-1", clusterName, consensusComp) + toDeletePodName := fmt.Sprintf("%s-%s-1", clusterName, defaultCompName) offlineInstances := []string{toDeletePodName} opsRes := testHScaleWithSpecifiedPod(func(cluster *appsv1alpha1.Cluster) { setClusterCompSpec(cluster, []appsv1alpha1.InstanceTemplate{ @@ -352,7 +352,7 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { }) It("test offline the specified pod and auto-sync replicaChanges", func() { - offlineInstanceName := fmt.Sprintf("%s-%s-%s-0", clusterName, consensusComp, insTplName) + offlineInstanceName := fmt.Sprintf("%s-%s-%s-0", clusterName, defaultCompName, insTplName) offlineInstances := []string{offlineInstanceName} opsRes := testHScaleWithSpecifiedPod(func(cluster *appsv1alpha1.Cluster) { setClusterCompSpec(cluster, []appsv1alpha1.InstanceTemplate{ @@ -368,13 +368,13 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { }) Expect(opsRes.OpsRequest.Status.Progress).Should(Equal("1/1")) By("expect replicas to 2 and template " + insTplName + " replicas to 0") - compSpec := opsRes.Cluster.Spec.GetComponentByName(consensusComp) + compSpec := opsRes.Cluster.Spec.GetComponentByName(defaultCompName) Expect(compSpec.Replicas).Should(BeEquivalentTo(2)) Expect(*compSpec.Instances[0].Replicas).Should(BeEquivalentTo(0)) }) It("test online the specified pod of the instance template and auto-sync replicaChanges", func() { - offlineInstanceName := fmt.Sprintf("%s-%s-%s-0", clusterName, consensusComp, insTplName) + offlineInstanceName := fmt.Sprintf("%s-%s-%s-0", clusterName, defaultCompName, insTplName) offlineInstances := []string{offlineInstanceName} opsRes := testHScaleWithSpecifiedPod(func(cluster *appsv1alpha1.Cluster) { setClusterCompSpec(cluster, []appsv1alpha1.InstanceTemplate{ @@ -386,18 +386,18 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { }, }, []string{}, func(podList []*corev1.Pod) { By("create the specified pod " + offlineInstanceName) - testapps.MockInstanceSetPod(&testCtx, nil, clusterName, consensusComp, offlineInstanceName, "follower", "Readonly") + testapps.MockInstanceSetPod(&testCtx, nil, clusterName, defaultCompName, offlineInstanceName, "follower", "Readonly") }) Expect(opsRes.OpsRequest.Status.Progress).Should(Equal("1/1")) By("expect replicas to 4") - compSpec := opsRes.Cluster.Spec.GetComponentByName(consensusComp) + compSpec := opsRes.Cluster.Spec.GetComponentByName(defaultCompName) Expect(compSpec.Replicas).Should(BeEquivalentTo(4)) Expect(*compSpec.Instances[0].Replicas).Should(BeEquivalentTo(2)) }) It("test offline and online the specified pod and auto-sync replicaChanges", func() { - onlinePodName := fmt.Sprintf("%s-%s-1", clusterName, consensusComp) - offlinePodName := fmt.Sprintf("%s-%s-%s-0", clusterName, consensusComp, insTplName) + onlinePodName := fmt.Sprintf("%s-%s-1", clusterName, defaultCompName) + offlinePodName := fmt.Sprintf("%s-%s-%s-0", clusterName, defaultCompName, insTplName) opsRes := testHScaleWithSpecifiedPod(func(cluster *appsv1alpha1.Cluster) { setClusterCompSpec(cluster, []appsv1alpha1.InstanceTemplate{ {Name: insTplName, Replicas: pointer.Int32(1)}, @@ -418,7 +418,7 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { }) Expect(opsRes.OpsRequest.Status.Progress).Should(Equal("2/2")) By("expect replicas to 3") - Expect(opsRes.Cluster.Spec.GetComponentByName(consensusComp).Replicas).Should(BeEquivalentTo(3)) + Expect(opsRes.Cluster.Spec.GetComponentByName(defaultCompName).Replicas).Should(BeEquivalentTo(3)) }) It("h-scale new instance templates and scale in all old replicas", func() { @@ -444,7 +444,7 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { var targetSpec *appsv1alpha1.ClusterComponentSpec for i := range opsRes.Cluster.Spec.ComponentSpecs { spec := &opsRes.Cluster.Spec.ComponentSpecs[i] - if spec.Name == consensusComp { + if spec.Name == defaultCompName { targetSpec = spec } } @@ -458,16 +458,16 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { createPods("bar", 0, 1, 2) By("delete three pods") deletePods(pods...) - testapps.MockInstanceSetStatus(testCtx, opsRes.Cluster, consensusComp) + testapps.MockInstanceSetStatus(testCtx, opsRes.Cluster, defaultCompName) checkOpsRequestPhaseIsSucceed(reqCtx, opsRes) }) createOpsAndToCreatingPhase := func(reqCtx intctrlutil.RequestCtx, opsRes *OpsResource, horizontalScaling appsv1alpha1.HorizontalScaling) *appsv1alpha1.OpsRequest { - horizontalScaling.ComponentName = consensusComp + horizontalScaling.ComponentName = defaultCompName opsRes.OpsRequest = createHorizontalScaling(clusterName, horizontalScaling) opsRes.OpsRequest.Spec.Force = true // set ops phase to Pending opsRes.OpsRequest.Status.Phase = appsv1alpha1.OpsPendingPhase - mockComponentIsOperating(opsRes.Cluster, appsv1alpha1.UpdatingClusterCompPhase, consensusComp) + mockComponentIsOperating(opsRes.Cluster, appsv1alpha1.UpdatingClusterCompPhase, defaultCompName) By("expect for opsRequest phase is Creating after doing action") _, err := GetOpsManager().Do(reqCtx, k8sClient, opsRes) @@ -482,12 +482,12 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { It("test offline the specified pod but it is not online", func() { By("init operations resources with CLusterDefinition/Hybrid components Cluster/consensus Pods") - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) - testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) + opsRes, _, _ := initOperationsResources(compDefName, clusterName) + testapps.MockInstanceSetComponent(&testCtx, clusterName, defaultCompName) reqCtx := intctrlutil.RequestCtx{Ctx: ctx} By("offline the specified pod but it is not online") - offlineInsName := fmt.Sprintf("%s-%s-4", clusterName, consensusComp) + offlineInsName := fmt.Sprintf("%s-%s-4", clusterName, defaultCompName) _ = createOpsAndToCreatingPhase(reqCtx, opsRes, appsv1alpha1.HorizontalScaling{ ScaleIn: &appsv1alpha1.ScaleIn{ ReplicaChanger: appsv1alpha1.ReplicaChanger{ReplicaChanges: pointer.Int32(1)}, @@ -502,23 +502,23 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { It("test run multi horizontalScaling opsRequest with force flag", func() { By("init operations resources with CLusterDefinition/Hybrid components Cluster/consensus Pods") - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) - testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) + opsRes, _, _ := initOperationsResources(compDefName, clusterName) + testapps.MockInstanceSetComponent(&testCtx, clusterName, defaultCompName) reqCtx := intctrlutil.RequestCtx{Ctx: ctx} By("create first opsRequest to add 1 replicas with `scaleOut` field and expect replicas to 4") ops1 := createOpsAndToCreatingPhase(reqCtx, opsRes, appsv1alpha1.HorizontalScaling{ ScaleOut: &appsv1alpha1.ScaleOut{ReplicaChanger: appsv1alpha1.ReplicaChanger{ReplicaChanges: pointer.Int32(1)}}, }) - Expect(opsRes.Cluster.Spec.GetComponentByName(consensusComp).Replicas).Should(BeEquivalentTo(4)) + Expect(opsRes.Cluster.Spec.GetComponentByName(defaultCompName).Replicas).Should(BeEquivalentTo(4)) By("create secondary opsRequest to add 1 replicas with `replicasToAdd` field and expect replicas to 5") ops2 := createOpsAndToCreatingPhase(reqCtx, opsRes, appsv1alpha1.HorizontalScaling{ ScaleOut: &appsv1alpha1.ScaleOut{ReplicaChanger: appsv1alpha1.ReplicaChanger{ReplicaChanges: pointer.Int32(1)}}, }) - Expect(opsRes.Cluster.Spec.GetComponentByName(consensusComp).Replicas).Should(BeEquivalentTo(5)) + Expect(opsRes.Cluster.Spec.GetComponentByName(defaultCompName).Replicas).Should(BeEquivalentTo(5)) By("create third opsRequest to offline a pod which is created by another running opsRequest and expect it to fail") - offlineInsName := fmt.Sprintf("%s-%s-3", clusterName, consensusComp) + offlineInsName := fmt.Sprintf("%s-%s-3", clusterName, defaultCompName) _ = createOpsAndToCreatingPhase(reqCtx, opsRes, appsv1alpha1.HorizontalScaling{ ScaleIn: &appsv1alpha1.ScaleIn{ ReplicaChanger: appsv1alpha1.ReplicaChanger{ReplicaChanges: pointer.Int32(1)}, @@ -551,7 +551,7 @@ var _ = Describe("HorizontalScaling OpsRequest", func() { ScaleOut: &appsv1alpha1.ScaleOut{ReplicaChanger: appsv1alpha1.ReplicaChanger{ReplicaChanges: pointer.Int32(1)}}, }) Eventually(testapps.GetOpsRequestPhase(&testCtx, client.ObjectKeyFromObject(ops3))).Should(Equal(appsv1alpha1.OpsAbortedPhase)) - Expect(opsRes.Cluster.Spec.GetComponentByName(consensusComp).Replicas).Should(BeEquivalentTo(4)) + Expect(opsRes.Cluster.Spec.GetComponentByName(defaultCompName).Replicas).Should(BeEquivalentTo(4)) }) }) }) @@ -581,7 +581,7 @@ func cancelOpsRequest(reqCtx intctrlutil.RequestCtx, opsRes *OpsResource, cancel func mockConsensusCompToRunning(opsRes *OpsResource) { // mock consensus component is Running - compStatus := opsRes.Cluster.Status.Components[consensusComp] + compStatus := opsRes.Cluster.Status.Components[defaultCompName] compStatus.Phase = appsv1alpha1.RunningClusterCompPhase - opsRes.Cluster.Status.Components[consensusComp] = compStatus + opsRes.Cluster.Status.Components[defaultCompName] = compStatus } diff --git a/controllers/apps/operations/ops_progress_util.go b/controllers/apps/operations/ops_progress_util.go index 375b3e894e0e..0cdf3773a9db 100644 --- a/controllers/apps/operations/ops_progress_util.go +++ b/controllers/apps/operations/ops_progress_util.go @@ -271,15 +271,10 @@ func handleCancelProgressForPodsRollingUpdate( } func needToCheckRole(pgRes *progressResource) bool { - var needCheckRole bool - if pgRes.componentDef != nil { - needCheckRole = len(pgRes.componentDef.Spec.Roles) > 0 - } else if pgRes.clusterDef != nil { - // TODO: get the componentDefinition by clusterDefinition after v0.9 - compDef := pgRes.clusterDef.GetComponentDefByName(pgRes.clusterComponent.ComponentDefRef) - needCheckRole = compDef != nil && (compDef.WorkloadType == appsv1alpha1.Replication || compDef.WorkloadType == appsv1alpha1.Consensus) - } - return needCheckRole + if pgRes.componentDef == nil { + panic("componentDef is nil") + } + return len(pgRes.componentDef.Spec.Roles) > 0 } func podIsAvailable(pgRes *progressResource, pod *corev1.Pod, minReadySeconds int32) bool { diff --git a/controllers/apps/operations/ops_progress_util_test.go b/controllers/apps/operations/ops_progress_util_test.go index fb71b78062d7..eba194e993a8 100644 --- a/controllers/apps/operations/ops_progress_util_test.go +++ b/controllers/apps/operations/ops_progress_util_test.go @@ -20,10 +20,13 @@ along with this program. If not, see . package operations import ( + "fmt" + "strings" "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" "k8s.io/utils/pointer" "sigs.k8s.io/controller-runtime/pkg/client" @@ -40,9 +43,9 @@ import ( var _ = Describe("Ops ProgressDetails", func() { var ( - randomStr = testCtx.GetRandomStr() - clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterName = "cluster-for-ops-" + randomStr + randomStr = testCtx.GetRandomStr() + compDefName = "test-compdef-" + randomStr + clusterName = "test-cluster-" + randomStr ) cleanEnv := func() { @@ -53,7 +56,7 @@ var _ = Describe("Ops ProgressDetails", func() { By("clean resources") // delete cluster(and all dependent sub-resources), cluster definition - testapps.ClearClusterResources(&testCtx) + testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest resources inNS := client.InNamespace(testCtx.DefaultNamespace) @@ -74,32 +77,32 @@ var _ = Describe("Ops ProgressDetails", func() { opsRes.Cluster.Status.Phase = appsv1alpha1.RunningClusterPhase } - testProgressDetailsWithStatefulPodUpdating := func(reqCtx intctrlutil.RequestCtx, opsRes *OpsResource, consensusPodList []*corev1.Pod) { + testProgressDetailsWithStatefulPodUpdating := func(reqCtx intctrlutil.RequestCtx, opsRes *OpsResource, pods []*corev1.Pod) { By("mock pod of InstanceSet updating by deleting the pod") - pod := consensusPodList[0] + pod := pods[0] testk8s.MockPodIsTerminating(ctx, testCtx, pod) _, _ = GetOpsManager().Reconcile(reqCtx, k8sClient, opsRes) - Expect(getProgressDetailStatus(opsRes, consensusComp, pod)).Should(Equal(appsv1alpha1.ProcessingProgressStatus)) + Expect(getProgressDetailStatus(opsRes, defaultCompName, pod)).Should(Equal(appsv1alpha1.ProcessingProgressStatus)) By("mock one pod of InstanceSet to update successfully") testk8s.RemovePodFinalizer(ctx, testCtx, pod) - testapps.MockInstanceSetPod(&testCtx, nil, clusterName, consensusComp, + testapps.MockInstanceSetPod(&testCtx, nil, clusterName, defaultCompName, pod.Name, "leader", "ReadWrite") _, _ = GetOpsManager().Reconcile(reqCtx, k8sClient, opsRes) - Expect(getProgressDetailStatus(opsRes, consensusComp, pod)).Should(Equal(appsv1alpha1.SucceedProgressStatus)) - Expect(opsRes.OpsRequest.Status.Progress).Should(Equal("1/4")) + Expect(getProgressDetailStatus(opsRes, defaultCompName, pod)).Should(Equal(appsv1alpha1.SucceedProgressStatus)) + Expect(opsRes.OpsRequest.Status.Progress).Should(Equal("1/3")) } Context("Test Ops ProgressDetails", func() { It("Test Ops ProgressDetails for rolling update", func() { By("init operations resources ") reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx} - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) + opsRes, _, _ := initOperationsResources(compDefName, clusterName) - By("create restart ops and pods of consensus component") + By("create restart ops and pods of component") opsRes.OpsRequest = createRestartOpsObj(clusterName, "restart-"+randomStr) - mockComponentIsOperating(opsRes.Cluster, appsv1alpha1.UpdatingClusterCompPhase, consensusComp, statelessComp) + mockComponentIsOperating(opsRes.Cluster, appsv1alpha1.UpdatingClusterCompPhase, defaultCompName) podList := initInstanceSetPods(ctx, k8sClient, opsRes) By("mock restart OpsRequest is Running") @@ -111,19 +114,19 @@ var _ = Describe("Ops ProgressDetails", func() { testProgressDetailsWithStatefulPodUpdating(reqCtx, opsRes, podList) }) - It("Test Ops ProgressDetails with horizontally scaling replicas", func() { + It("Test Ops ProgressDetails with scale-in replicas", func() { By("init operations resources ") reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx} - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) - its := testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) - podList := testapps.MockInstanceSetPods(&testCtx, its, opsRes.Cluster, consensusComp) + opsRes, _, _ := initOperationsResources(compDefName, clusterName) + its := testapps.MockInstanceSetComponent(&testCtx, clusterName, defaultCompName) + podList := testapps.MockInstanceSetPods(&testCtx, its, opsRes.Cluster, defaultCompName) By("create horizontalScaling operation to test the progressDetails when scaling in the replicas") opsRes.OpsRequest = createHorizontalScaling(clusterName, appsv1alpha1.HorizontalScaling{ - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, Replicas: pointer.Int32(1), }) - mockComponentIsOperating(opsRes.Cluster, appsv1alpha1.UpdatingClusterCompPhase, consensusComp) // appsv1alpha1.HorizontalScalingPhase + mockComponentIsOperating(opsRes.Cluster, appsv1alpha1.UpdatingClusterCompPhase, defaultCompName) // appsv1alpha1.HorizontalScalingPhase initClusterForOps(opsRes) By("mock HorizontalScaling OpsRequest phase is running") @@ -138,57 +141,65 @@ var _ = Describe("Ops ProgressDetails", func() { for i := 1; i < 3; i++ { pod := podList[i] testk8s.MockPodIsTerminating(ctx, testCtx, pod) - testapps.MockInstanceSetStatus(testCtx, opsRes.Cluster, consensusComp) + testapps.MockInstanceSetStatus(testCtx, opsRes.Cluster, defaultCompName) _, _ = GetOpsManager().Reconcile(reqCtx, k8sClient, opsRes) - Expect(getProgressDetailStatus(opsRes, consensusComp, pod)).Should(Equal(appsv1alpha1.ProcessingProgressStatus)) + Expect(getProgressDetailStatus(opsRes, defaultCompName, pod)).Should(Equal(appsv1alpha1.ProcessingProgressStatus)) } By("mock the target pod is deleted and progressDetail status should be succeed") targetPod := podList[1] testk8s.RemovePodFinalizer(ctx, testCtx, targetPod) - testapps.MockInstanceSetStatus(testCtx, opsRes.Cluster, consensusComp) + testapps.MockInstanceSetStatus(testCtx, opsRes.Cluster, defaultCompName) _, _ = GetOpsManager().Reconcile(reqCtx, k8sClient, opsRes) - Expect(getProgressDetailStatus(opsRes, consensusComp, targetPod)).Should(Equal(appsv1alpha1.SucceedProgressStatus)) + Expect(getProgressDetailStatus(opsRes, defaultCompName, targetPod)).Should(Equal(appsv1alpha1.SucceedProgressStatus)) Expect(opsRes.OpsRequest.Status.Progress).Should(Equal("1/2")) By("delete the pod[2]") pod := podList[2] testk8s.RemovePodFinalizer(ctx, testCtx, pod) // expect the progress is 2/2 - testapps.MockInstanceSetStatus(testCtx, opsRes.Cluster, consensusComp) + testapps.MockInstanceSetStatus(testCtx, opsRes.Cluster, defaultCompName) _, _ = GetOpsManager().Reconcile(reqCtx, k8sClient, opsRes) - Expect(getProgressDetailStatus(opsRes, consensusComp, targetPod)).Should(Equal(appsv1alpha1.SucceedProgressStatus)) + Expect(getProgressDetailStatus(opsRes, defaultCompName, targetPod)).Should(Equal(appsv1alpha1.SucceedProgressStatus)) Expect(opsRes.OpsRequest.Status.Progress).Should(Equal("2/2")) + }) + + It("Test Ops ProgressDetails with scale-out replicas", func() { + By("init operations resources ") + reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx} + opsRes, _, _ := initOperationsResources(compDefName, clusterName) + its := testapps.MockInstanceSetComponent(&testCtx, clusterName, defaultCompName) + podList := testapps.MockInstanceSetPods(&testCtx, its, opsRes.Cluster, defaultCompName) - By("create horizontalScaling operation to test the progressDetails when scaling out the replicas ") - initClusterForOps(opsRes) - expectClusterComponentReplicas := int32(2) - Expect(testapps.ChangeObj(&testCtx, opsRes.Cluster, func(lcluster *appsv1alpha1.Cluster) { - lcluster.Spec.ComponentSpecs[1].Replicas = expectClusterComponentReplicas - })).ShouldNot(HaveOccurred()) // ops will use the startTimestamp to make decision, start time should not equal the pod createTime during testing. time.Sleep(time.Second) + + By("create horizontalScaling operation to test the progressDetails when scaling out the replicas ") opsRes.OpsRequest = createHorizontalScaling(clusterName, appsv1alpha1.HorizontalScaling{ - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, - Replicas: pointer.Int32(3), + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, + Replicas: pointer.Int32(4), }) - mockComponentIsOperating(opsRes.Cluster, appsv1alpha1.UpdatingClusterCompPhase, consensusComp, statelessComp) - // update ops phase to Running first - _, err = GetOpsManager().Do(reqCtx, k8sClient, opsRes) + mockComponentIsOperating(opsRes.Cluster, appsv1alpha1.UpdatingClusterCompPhase, defaultCompName) // appsv1alpha1.HorizontalScalingPhase + initClusterForOps(opsRes) + + By("mock HorizontalScaling OpsRequest phase is running") + _, err := GetOpsManager().Do(reqCtx, k8sClient, opsRes) Expect(err).ShouldNot(HaveOccurred()) Eventually(testapps.GetOpsRequestPhase(&testCtx, client.ObjectKeyFromObject(opsRes.OpsRequest))).Should(Equal(appsv1alpha1.OpsCreatingPhase)) - // do h-scale cluster + // do h-scale action _, err = GetOpsManager().Do(reqCtx, k8sClient, opsRes) Expect(err).ShouldNot(HaveOccurred()) By("test the progressDetails when scaling out replicas") - targetPod = podList[2] - testapps.MockInstanceSetPod(&testCtx, nil, clusterName, consensusComp, - targetPod.Name, "follower", "Readonly") - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: targetPod.Name, Namespace: testCtx.DefaultNamespace}, targetPod)).Should(Succeed()) - testapps.MockInstanceSetStatus(testCtx, opsRes.Cluster, consensusComp) + tokens := strings.Split(podList[2].Name, "-") + targetPodName := fmt.Sprintf("%s-3", strings.Join(tokens[0:len(tokens)-1], "-")) + testapps.MockInstanceSetPod(&testCtx, nil, clusterName, defaultCompName, + targetPodName, "follower", "Readonly") + targetPod := &corev1.Pod{} + Expect(k8sClient.Get(ctx, client.ObjectKey{Name: targetPodName, Namespace: testCtx.DefaultNamespace}, targetPod)).Should(Succeed()) + testapps.MockInstanceSetStatus(testCtx, opsRes.Cluster, defaultCompName) _, _ = GetOpsManager().Reconcile(reqCtx, k8sClient, opsRes) - Expect(getProgressDetailStatus(opsRes, consensusComp, targetPod)).Should(Equal(appsv1alpha1.SucceedProgressStatus)) + Expect(getProgressDetailStatus(opsRes, defaultCompName, targetPod)).Should(Equal(appsv1alpha1.SucceedProgressStatus)) Expect(opsRes.OpsRequest.Status.Progress).Should(Equal("1/1")) }) }) diff --git a/controllers/apps/operations/ops_util_test.go b/controllers/apps/operations/ops_util_test.go index 3df54d798312..156b7add5cec 100644 --- a/controllers/apps/operations/ops_util_test.go +++ b/controllers/apps/operations/ops_util_test.go @@ -42,9 +42,9 @@ import ( var _ = Describe("OpsUtil functions", func() { var ( - randomStr = testCtx.GetRandomStr() - clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterName = "cluster-for-ops-" + randomStr + randomStr = testCtx.GetRandomStr() + compDefName = "test-compdef-" + randomStr + clusterName = "test-cluster-" + randomStr ) cleanEnv := func() { @@ -55,7 +55,7 @@ var _ = Describe("OpsUtil functions", func() { By("clean resources") // delete cluster(and all dependent sub-resources), cluster definition - testapps.ClearClusterResources(&testCtx) + testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest resources inNS := client.InNamespace(testCtx.DefaultNamespace) @@ -74,12 +74,12 @@ var _ = Describe("OpsUtil functions", func() { Context("Test ops_util functions", func() { It("Test ops_util functions", func() { By("init operations resources ") - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) - testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) + opsRes, _, _ := initOperationsResources(compDefName, clusterName) + testapps.MockInstanceSetComponent(&testCtx, clusterName, defaultCompName) By("Test the functions in ops_util.go") opsRes.OpsRequest = createHorizontalScaling(clusterName, appsv1alpha1.HorizontalScaling{ - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, Replicas: pointer.Int32(1), }) Expect(patchValidateErrorCondition(ctx, k8sClient, opsRes, "validate error")).Should(Succeed()) @@ -90,22 +90,22 @@ var _ = Describe("OpsUtil functions", func() { It("Test opsRequest failed cases", func() { By("init operations resources ") - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) - testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) - pods := testapps.MockInstanceSetPods(&testCtx, nil, opsRes.Cluster, consensusComp) + opsRes, _, _ := initOperationsResources(compDefName, clusterName) + testapps.MockInstanceSetComponent(&testCtx, clusterName, defaultCompName) + pods := testapps.MockInstanceSetPods(&testCtx, nil, opsRes.Cluster, defaultCompName) time.Sleep(time.Second) By("Test the functions in ops_util.go") ops := testapps.NewOpsRequestObj("restart-ops-"+randomStr, testCtx.DefaultNamespace, clusterName, appsv1alpha1.RestartType) - ops.Spec.RestartList = []appsv1alpha1.ComponentOps{{ComponentName: consensusComp}} + ops.Spec.RestartList = []appsv1alpha1.ComponentOps{{ComponentName: defaultCompName}} opsRes.OpsRequest = testapps.CreateOpsRequest(ctx, testCtx, ops) opsRes.OpsRequest.Status.Phase = appsv1alpha1.OpsRunningPhase opsRes.OpsRequest.Status.StartTimestamp = metav1.Now() By("mock component failed") - clusterComp := opsRes.Cluster.Status.Components[consensusComp] + clusterComp := opsRes.Cluster.Status.Components[defaultCompName] clusterComp.Phase = appsv1alpha1.FailedClusterCompPhase - opsRes.Cluster.Status.SetComponentStatus(consensusComp, clusterComp) + opsRes.Cluster.Status.SetComponentStatus(defaultCompName, clusterComp) By("expect for opsRequest is running") handleRestartProgress := func(reqCtx intctrlutil.RequestCtx, @@ -131,7 +131,7 @@ var _ = Describe("OpsUtil functions", func() { testk8s.MockPodIsTerminating(ctx, testCtx, pods[2]) testk8s.RemovePodFinalizer(ctx, testCtx, pods[2]) // recreate it - pod := testapps.MockInstanceSetPod(&testCtx, nil, clusterName, consensusComp, pods[2].Name, "follower", "Readonly") + pod := testapps.MockInstanceSetPod(&testCtx, nil, clusterName, defaultCompName, pods[2].Name, "follower", "Readonly") // mock pod is failed testk8s.MockPodIsFailed(ctx, testCtx, pod) opsPhase, _, err = compOpsHelper.reconcileActionWithComponentOps(reqCtx, k8sClient, opsRes, "test", handleRestartProgress) @@ -141,12 +141,12 @@ var _ = Describe("OpsUtil functions", func() { It("Test opsRequest with disable ha", func() { By("init operations resources ") - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) + opsRes, _, _ := initOperationsResources(compDefName, clusterName) By("Test the functions in ops_util.go") ops := testapps.NewOpsRequestObj("restart-ops-"+randomStr, testCtx.DefaultNamespace, clusterName, appsv1alpha1.RestartType) - ops.Spec.RestartList = []appsv1alpha1.ComponentOps{{ComponentName: consensusComp}} + ops.Spec.RestartList = []appsv1alpha1.ComponentOps{{ComponentName: defaultCompName}} opsRes.OpsRequest = testapps.CreateOpsRequest(ctx, testCtx, ops) Expect(testapps.ChangeObjStatus(&testCtx, opsRes.OpsRequest, func() { opsRes.OpsRequest.Status.Phase = appsv1alpha1.OpsCreatingPhase @@ -169,7 +169,7 @@ var _ = Describe("OpsUtil functions", func() { } By("mock instance set") - its := testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) + its := testapps.MockInstanceSetComponent(&testCtx, clusterName, defaultCompName) By("expect to disable ha") reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx} @@ -181,7 +181,7 @@ var _ = Describe("OpsUtil functions", func() { By("mock restart ops to succeed and expect to enable ha") opsRes.OpsRequest.Status.Phase = appsv1alpha1.OpsRunningPhase - _ = testapps.MockInstanceSetPods(&testCtx, its, opsRes.Cluster, consensusComp) + _ = testapps.MockInstanceSetPods(&testCtx, its, opsRes.Cluster, defaultCompName) _, err = GetOpsManager().Reconcile(reqCtx, k8sClient, opsRes) Expect(err).ShouldNot(HaveOccurred()) Eventually(testapps.GetOpsRequestPhase(&testCtx, client.ObjectKeyFromObject(opsRes.OpsRequest))).Should(Equal(appsv1alpha1.OpsSucceedPhase)) @@ -193,11 +193,11 @@ var _ = Describe("OpsUtil functions", func() { It("Test opsRequest Queue functions", func() { By("init operations resources ") reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx} - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) + opsRes, _, _ := initOperationsResources(compDefName, clusterName) runHscaleOps := func(expectPhase appsv1alpha1.OpsPhase) *appsv1alpha1.OpsRequest { ops := createHorizontalScaling(clusterName, appsv1alpha1.HorizontalScaling{ - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, Replicas: pointer.Int32(1), }) opsRes.OpsRequest = ops @@ -248,11 +248,11 @@ var _ = Describe("OpsUtil functions", func() { It("Test opsRequest dependency", func() { By("init operations resources ") reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx} - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) + opsRes, _, _ := initOperationsResources(compDefName, clusterName) By("create a first horizontal opsRequest") ops1 := createHorizontalScaling(clusterName, appsv1alpha1.HorizontalScaling{ - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, ScaleIn: &appsv1alpha1.ScaleIn{ ReplicaChanger: appsv1alpha1.ReplicaChanger{ReplicaChanges: pointer.Int32(1)}, }, @@ -264,7 +264,7 @@ var _ = Describe("OpsUtil functions", func() { By("create another horizontal opsRequest with force flag and dependent the first opsRequest") ops2 := createHorizontalScaling(clusterName, appsv1alpha1.HorizontalScaling{ - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, ScaleOut: &appsv1alpha1.ScaleOut{ ReplicaChanger: appsv1alpha1.ReplicaChanger{ReplicaChanges: pointer.Int32(1)}, }, @@ -303,8 +303,8 @@ var _ = Describe("OpsUtil functions", func() { It("Test EnqueueOnForce=true", func() { By("init operations resources ") - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) - testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) + opsRes, _, _ := initOperationsResources(compDefName, clusterName) + testapps.MockInstanceSetComponent(&testCtx, clusterName, defaultCompName) By("mock cluster phase to Updating") Expect(testapps.ChangeObjStatus(&testCtx, opsRes.Cluster, func() { @@ -313,7 +313,7 @@ var _ = Describe("OpsUtil functions", func() { By("expect the ops phase is failed") opsRes.OpsRequest = createHorizontalScaling(clusterName, appsv1alpha1.HorizontalScaling{ - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, Replicas: pointer.Int32(1), }) reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx} @@ -322,7 +322,7 @@ var _ = Describe("OpsUtil functions", func() { By("Test EnqueueOnForce=true") opsRes.OpsRequest = createHorizontalScaling(clusterName, appsv1alpha1.HorizontalScaling{ - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, Replicas: pointer.Int32(1), }) opsRes.OpsRequest.Spec.Force = true diff --git a/controllers/apps/operations/rebuild_instance_test.go b/controllers/apps/operations/rebuild_instance_test.go index 3673d3dfa6a3..e9829ceee779 100644 --- a/controllers/apps/operations/rebuild_instance_test.go +++ b/controllers/apps/operations/rebuild_instance_test.go @@ -34,6 +34,7 @@ import ( dpv1alpha1 "github.com/apecloud/kubeblocks/apis/dataprotection/v1alpha1" "github.com/apecloud/kubeblocks/pkg/common" "github.com/apecloud/kubeblocks/pkg/constant" + "github.com/apecloud/kubeblocks/pkg/controller/component" intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" dptypes "github.com/apecloud/kubeblocks/pkg/dataprotection/types" "github.com/apecloud/kubeblocks/pkg/generics" @@ -45,10 +46,10 @@ import ( var _ = Describe("OpsUtil functions", func() { var ( - randomStr = testCtx.GetRandomStr() - clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterName = "cluster-for-ops-" + randomStr - rebuildInstanceCount = 2 + randomStr = testCtx.GetRandomStr() + compDefName = "test-compdef-" + randomStr + clusterName = "test-cluster-" + randomStr + rebuildInstanceCount = 2 ) cleanEnv := func() { @@ -59,7 +60,7 @@ var _ = Describe("OpsUtil functions", func() { By("clean resources") // delete cluster(and all dependent sub-resources), cluster definition - testapps.ClearClusterResources(&testCtx) + testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest resources inNS := client.InNamespace(testCtx.DefaultNamespace) @@ -73,6 +74,7 @@ var _ = Describe("OpsUtil functions", func() { testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.PersistentVolumeClaimSignature, true, inNS, ml) testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.PersistentVolumeSignature, true, ml) testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.ActionSetSignature, true, ml) + testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.ComponentSignature, true, inNS, ml) } BeforeEach(cleanEnv) @@ -92,7 +94,7 @@ var _ = Describe("OpsUtil functions", func() { } ops.Spec.RebuildFrom = []appsv1alpha1.RebuildInstance{ { - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, Instances: instances, BackupName: backupName, InPlace: inPlace, @@ -103,14 +105,23 @@ var _ = Describe("OpsUtil functions", func() { return opsRequest } + createComponentObject := func(ops *OpsResource) { + // mock create the component object + cluster := ops.Cluster + comp, err := component.BuildComponent(cluster, &cluster.Spec.ComponentSpecs[0], nil, nil) + Expect(err).Should(BeNil()) + Expect(testCtx.CreateObj(ctx, comp)).Should(Succeed()) + } + prepareOpsRes := func(backupName string, inPlace bool) *OpsResource { - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) - podList := initInstanceSetPods(ctx, k8sClient, opsRes) + opsRes, _, _ := initOperationsResources(compDefName, clusterName) + createComponentObject(opsRes) + podList := initInstanceSetPods(ctx, k8sClient, opsRes) // fake to create the source pvc. for i := range podList { pvcName := fmt.Sprintf("%s-%s", testapps.DataVolumeName, podList[i].Name) - testapps.NewPersistentVolumeClaimFactory(podList[i].Namespace, pvcName, clusterName, consensusComp, testapps.DataVolumeName). + testapps.NewPersistentVolumeClaimFactory(podList[i].Namespace, pvcName, clusterName, defaultCompName, testapps.DataVolumeName). SetStorage("20Gi").Create(&testCtx) } @@ -122,8 +133,8 @@ var _ = Describe("OpsUtil functions", func() { fakePVCSByRestore := func(opsRequest *appsv1alpha1.OpsRequest) *corev1.PersistentVolumeClaimList { pvcList := &corev1.PersistentVolumeClaimList{} for i := 0; i < 2; i++ { - pvcName := fmt.Sprintf("rebuild-%s-%s-%d", opsRequest.UID[:8], common.CutString(consensusComp+"-"+testapps.DataVolumeName, 30), i) - pv := testapps.NewPersistentVolumeClaimFactory(testCtx.DefaultNamespace, pvcName, clusterName, consensusComp, testapps.DataVolumeName). + pvcName := fmt.Sprintf("rebuild-%s-%s-%d", opsRequest.UID[:8], common.CutString(defaultCompName+"-"+testapps.DataVolumeName, 30), i) + pv := testapps.NewPersistentVolumeClaimFactory(testCtx.DefaultNamespace, pvcName, clusterName, defaultCompName, testapps.DataVolumeName). AddAnnotations(rebuildFromAnnotation, opsRequest.Name). SetStorage("20Gi").Create(&testCtx).GetObject() pvcList.Items = append(pvcList.Items, *pv) @@ -167,14 +178,14 @@ var _ = Describe("OpsUtil functions", func() { By("expect for opsRequest phase is Failed if the phase of component is not matched") _, _ = GetOpsManager().Do(reqCtx, k8sClient, opsRes) Expect(opsRes.OpsRequest.Status.Phase).Should(Equal(appsv1alpha1.OpsFailedPhase)) - Expect(opsRes.OpsRequest.Status.Conditions[0].Message).Should(ContainSubstring(fmt.Sprintf(`the phase of component "%s" can not be %s`, consensusComp, appsv1alpha1.RunningClusterCompPhase))) + Expect(opsRes.OpsRequest.Status.Conditions[0].Message).Should(ContainSubstring(fmt.Sprintf(`the phase of component "%s" can not be %s`, defaultCompName, appsv1alpha1.RunningClusterCompPhase))) By("fake component phase to Abnormal") opsRes.OpsRequest.Status.Phase = appsv1alpha1.OpsCreatingPhase Expect(testapps.ChangeObjStatus(&testCtx, opsRes.Cluster, func() { - compStatus := opsRes.Cluster.Status.Components[consensusComp] + compStatus := opsRes.Cluster.Status.Components[defaultCompName] compStatus.Phase = appsv1alpha1.AbnormalClusterCompPhase - opsRes.Cluster.Status.Components[consensusComp] = compStatus + opsRes.Cluster.Status.Components[defaultCompName] = compStatus })).Should(Succeed()) By("expect for opsRequest phase is Failed due to the pod is Available") @@ -206,7 +217,7 @@ var _ = Describe("OpsUtil functions", func() { })) } - Expect(k8sClient.List(ctx, pvcList, client.MatchingLabels{constant.KBAppComponentLabelKey: consensusComp}, client.InNamespace(opsRes.OpsRequest.Namespace))).Should(Succeed()) + Expect(k8sClient.List(ctx, pvcList, client.MatchingLabels{constant.KBAppComponentLabelKey: defaultCompName}, client.InNamespace(opsRes.OpsRequest.Namespace))).Should(Succeed()) reCreatePVCCount := 0 for i := range pvcList.Items { pvc := &pvcList.Items[i] @@ -224,7 +235,7 @@ var _ = Describe("OpsUtil functions", func() { waitForInstanceToAvailable := func(reqCtx intctrlutil.RequestCtx, opsRes *OpsResource, ignoreRoleCheck bool) { By("waiting for the rebuild instance to ready") Eventually(testapps.CheckObj(&testCtx, client.ObjectKeyFromObject(opsRes.OpsRequest), func(g Gomega, ops *appsv1alpha1.OpsRequest) { - compStatus := ops.Status.Components[consensusComp] + compStatus := ops.Status.Components[defaultCompName] g.Expect(compStatus.ProgressDetails[0].Message).Should(Equal(waitingForInstanceReadyMessage)) g.Expect(compStatus.ProgressDetails[1].Message).Should(Equal(waitingForInstanceReadyMessage)) })) @@ -259,7 +270,7 @@ var _ = Describe("OpsUtil functions", func() { Expect(k8sClient.List(ctx, podList, matchingLabels, client.InNamespace(opsRes.OpsRequest.Namespace))).Should(Succeed()) Expect(podList.Items).Should(HaveLen(rebuildInstanceCount)) pvcList := &corev1.PersistentVolumeClaimList{} - Expect(k8sClient.List(ctx, pvcList, client.MatchingLabels{constant.KBAppComponentLabelKey: consensusComp}, client.InNamespace(opsRes.OpsRequest.Namespace))).Should(Succeed()) + Expect(k8sClient.List(ctx, pvcList, client.MatchingLabels{constant.KBAppComponentLabelKey: defaultCompName}, client.InNamespace(opsRes.OpsRequest.Namespace))).Should(Succeed()) tmpPVCCount := 0 for i := range pvcList.Items { if _, ok := pvcList.Items[i].Annotations[rebuildFromAnnotation]; ok { @@ -377,18 +388,19 @@ var _ = Describe("OpsUtil functions", func() { It("rebuild instance with horizontal scaling", func() { By("init operations resources ") - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) - its := testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) - podList := testapps.MockInstanceSetPods(&testCtx, its, opsRes.Cluster, consensusComp) + opsRes, _, _ := initOperationsResources(compDefName, clusterName) + createComponentObject(opsRes) + its := testapps.MockInstanceSetComponent(&testCtx, clusterName, defaultCompName) + podList := testapps.MockInstanceSetPods(&testCtx, its, opsRes.Cluster, defaultCompName) opsRes.OpsRequest = createRebuildInstanceOps("", false, podList[1].Name, podList[2].Name) By("mock cluster/component phase to Abnormal") opsRes.OpsRequest.Status.Phase = appsv1alpha1.OpsCreatingPhase Expect(testapps.ChangeObjStatus(&testCtx, opsRes.Cluster, func() { - compStatus := opsRes.Cluster.Status.Components[consensusComp] + compStatus := opsRes.Cluster.Status.Components[defaultCompName] compStatus.Phase = appsv1alpha1.AbnormalClusterCompPhase opsRes.Cluster.Status.Phase = appsv1alpha1.AbnormalClusterPhase - opsRes.Cluster.Status.Components[consensusComp] = compStatus + opsRes.Cluster.Status.Components[defaultCompName] = compStatus })).Should(Succeed()) By("mock pods are available") @@ -420,16 +432,16 @@ var _ = Describe("OpsUtil functions", func() { By("expect to scale out two replicas ") opsRes.OpsRequest.Status.Phase = appsv1alpha1.OpsRunningPhase _, _ = GetOpsManager().Reconcile(reqCtx, k8sClient, opsRes) - Expect(opsRes.Cluster.Spec.GetComponentByName(consensusComp).Replicas).Should(BeEquivalentTo(5)) + Expect(opsRes.Cluster.Spec.GetComponentByName(defaultCompName).Replicas).Should(BeEquivalentTo(5)) By("mock the new pods to available") - podPrefix := constant.GenerateWorkloadNamePattern(clusterName, consensusComp) - testapps.MockInstanceSetPod(&testCtx, nil, clusterName, consensusComp, podPrefix+"-3", "follower", "Readonly") - testapps.MockInstanceSetPod(&testCtx, nil, clusterName, consensusComp, podPrefix+"-4", "follower", "Readonly") + podPrefix := constant.GenerateWorkloadNamePattern(clusterName, defaultCompName) + testapps.MockInstanceSetPod(&testCtx, nil, clusterName, defaultCompName, podPrefix+"-3", "follower", "Readonly") + testapps.MockInstanceSetPod(&testCtx, nil, clusterName, defaultCompName, podPrefix+"-4", "follower", "Readonly") By("expect specified instances to take offline") _, _ = GetOpsManager().Reconcile(reqCtx, k8sClient, opsRes) - compSpec := opsRes.Cluster.Spec.GetComponentByName(consensusComp) + compSpec := opsRes.Cluster.Spec.GetComponentByName(defaultCompName) Expect(compSpec.Replicas).Should(BeEquivalentTo(3)) Expect(slices.Contains(compSpec.OfflineInstances, podList[1].Name)).Should(BeTrue()) Expect(slices.Contains(compSpec.OfflineInstances, podList[2].Name)).Should(BeTrue()) diff --git a/controllers/apps/operations/reconfigure_test.go b/controllers/apps/operations/reconfigure_test.go index 1a9b2392c4cd..d08d52d00096 100644 --- a/controllers/apps/operations/reconfigure_test.go +++ b/controllers/apps/operations/reconfigure_test.go @@ -142,7 +142,7 @@ var _ = Describe("Reconfigure OpsRequest", func() { assureMockReconfigureData := func(policyName string) (*OpsResource, *appsv1alpha1.Configuration, *corev1.ConfigMap) { By("init operations resources ") - opsRes, compDef, clusterObject := initOperationsResources2(compDefName, clusterName) + opsRes, compDef, clusterObject := initOperationsResources(compDefName, clusterName) By("Test Reconfigure") { diff --git a/controllers/apps/operations/restart_test.go b/controllers/apps/operations/restart_test.go index 99eb5e6dcc70..87ed873a07b6 100644 --- a/controllers/apps/operations/restart_test.go +++ b/controllers/apps/operations/restart_test.go @@ -34,9 +34,9 @@ import ( var _ = Describe("Restart OpsRequest", func() { var ( - randomStr = testCtx.GetRandomStr() - clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterName = "cluster-for-ops-" + randomStr + randomStr = testCtx.GetRandomStr() + compDefName = "test-compdef-" + randomStr + clusterName = "test-cluster-" + randomStr ) cleanEnv := func() { @@ -47,7 +47,7 @@ var _ = Describe("Restart OpsRequest", func() { By("clean resources") // delete cluster(and all dependent sub-resources), cluster definition - testapps.ClearClusterResources(&testCtx) + testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest resources inNS := client.InNamespace(testCtx.DefaultNamespace) @@ -66,16 +66,17 @@ var _ = Describe("Restart OpsRequest", func() { cluster *appsv1alpha1.Cluster reqCtx intctrlutil.RequestCtx ) + BeforeEach(func() { By("init operations resources ") - opsRes, _, cluster = initOperationsResources(clusterDefinitionName, clusterName) + opsRes, _, cluster = initOperationsResources(compDefName, clusterName) reqCtx = intctrlutil.RequestCtx{Ctx: testCtx.Ctx} }) It("Test restart OpsRequest", func() { By("create Restart opsRequest") opsRes.OpsRequest = createRestartOpsObj(clusterName, "restart-ops-"+randomStr) - mockComponentIsOperating(opsRes.Cluster, appsv1alpha1.UpdatingClusterCompPhase, consensusComp, statelessComp) + mockComponentIsOperating(opsRes.Cluster, appsv1alpha1.UpdatingClusterCompPhase, defaultCompName) By("mock restart OpsRequest is Running") _, err := GetOpsManager().Do(reqCtx, k8sClient, opsRes) @@ -113,8 +114,7 @@ func createRestartOpsObj(clusterName, restartOpsName string) *appsv1alpha1.OpsRe ops := testapps.NewOpsRequestObj(restartOpsName, testCtx.DefaultNamespace, clusterName, appsv1alpha1.RestartType) ops.Spec.RestartList = []appsv1alpha1.ComponentOps{ - {ComponentName: consensusComp}, - {ComponentName: statelessComp}, + {ComponentName: defaultCompName}, } opsRequest := testapps.CreateOpsRequest(ctx, testCtx, ops) opsRequest.Status.Phase = appsv1alpha1.OpsPendingPhase diff --git a/controllers/apps/operations/restore_test.go b/controllers/apps/operations/restore_test.go index aead8ad2c315..b49c37db93e1 100644 --- a/controllers/apps/operations/restore_test.go +++ b/controllers/apps/operations/restore_test.go @@ -41,12 +41,12 @@ import ( var _ = Describe("Restore OpsRequest", func() { var ( - randomStr = testCtx.GetRandomStr() - clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterName = "cluster-for-ops-" + randomStr - restoreClusterName = "restore-cluster" - backupName = "backup-for-ops-" + randomStr - nodePort = int32(31212) + randomStr = testCtx.GetRandomStr() + compDefName = "test-compdef-" + randomStr + clusterName = "test-cluster-" + randomStr + restoreClusterName = "restore-cluster" + backupName = "backup-for-ops-" + randomStr + nodePort = int32(31212) ) cleanEnv := func() { @@ -57,7 +57,7 @@ var _ = Describe("Restore OpsRequest", func() { By("clean resources") // delete cluster(and all dependent sub-resources), cluster definition - testapps.ClearClusterResources(&testCtx) + testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest resources inNS := client.InNamespace(testCtx.DefaultNamespace) @@ -79,7 +79,7 @@ var _ = Describe("Restore OpsRequest", func() { ) BeforeEach(func() { By("init operations resources ") - opsRes, _, _ = initOperationsResources(clusterDefinitionName, clusterName) + opsRes, _, _ = initOperationsResources(compDefName, clusterName) reqCtx = intctrlutil.RequestCtx{Ctx: testCtx.Ctx} By("create Backup") @@ -120,7 +120,7 @@ var _ = Describe("Restore OpsRequest", func() { By("mock backup annotations and labels") opsRes.Cluster.Spec.Services = []appsv1alpha1.ClusterService{ { - ComponentSelector: consensusComp, + ComponentSelector: defaultCompName, Service: appsv1alpha1.Service{ Name: "svc", Spec: corev1.ServiceSpec{ @@ -131,7 +131,7 @@ var _ = Describe("Restore OpsRequest", func() { }, }, { - ComponentSelector: consensusComp, + ComponentSelector: defaultCompName, Service: appsv1alpha1.Service{ Name: "svc-2", ServiceName: "svc-2", @@ -146,7 +146,7 @@ var _ = Describe("Restore OpsRequest", func() { Expect(testapps.ChangeObj(&testCtx, backup, func(backup *dpv1alpha1.Backup) { backup.Labels = map[string]string{ dptypes.BackupTypeLabelKey: string(dpv1alpha1.BackupTypeFull), - constant.KBAppComponentLabelKey: consensusComp, + constant.KBAppComponentLabelKey: defaultCompName, } opsRes.Cluster.ResourceVersion = "" clusterBytes, _ := json.Marshal(opsRes.Cluster) diff --git a/controllers/apps/operations/start_test.go b/controllers/apps/operations/start_test.go index 09754d4bc9e6..6fcae5df6eec 100644 --- a/controllers/apps/operations/start_test.go +++ b/controllers/apps/operations/start_test.go @@ -34,9 +34,9 @@ import ( var _ = Describe("Start OpsRequest", func() { var ( - randomStr = testCtx.GetRandomStr() - clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterName = "cluster-for-ops-" + randomStr + randomStr = testCtx.GetRandomStr() + compDefName = "test-compdef-" + randomStr + clusterName = "test-luster-" + randomStr ) cleanEnv := func() { @@ -47,7 +47,7 @@ var _ = Describe("Start OpsRequest", func() { By("clean resources") // delete cluster(and all dependent sub-resources), cluster definition - testapps.ClearClusterResources(&testCtx) + testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest resources inNS := client.InNamespace(testCtx.DefaultNamespace) @@ -65,10 +65,8 @@ var _ = Describe("Start OpsRequest", func() { It("Test start OpsRequest", func() { By("init operations resources ") reqCtx := intctrlutil.RequestCtx{Ctx: ctx} - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) - testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) - testapps.MockInstanceSetComponent(&testCtx, clusterName, statelessComp) - testapps.MockInstanceSetComponent(&testCtx, clusterName, statefulComp) + opsRes, _, _ := initOperationsResources(compDefName, clusterName) + testapps.MockInstanceSetComponent(&testCtx, clusterName, defaultCompName) By("create Start opsRequest") ops := testapps.NewOpsRequestObj("start-ops-"+randomStr, testCtx.DefaultNamespace, clusterName, appsv1alpha1.StartType) @@ -93,7 +91,7 @@ var _ = Describe("Start OpsRequest", func() { Expect(v.Stop).Should(BeNil()) } _, err = GetOpsManager().Reconcile(reqCtx, k8sClient, opsRes) - Expect(err == nil).Should(BeTrue()) + Expect(err).Should(BeNil()) }) }) }) diff --git a/controllers/apps/operations/stop_test.go b/controllers/apps/operations/stop_test.go index 494fe371be78..5ede899c87b4 100644 --- a/controllers/apps/operations/stop_test.go +++ b/controllers/apps/operations/stop_test.go @@ -33,9 +33,9 @@ import ( var _ = Describe("Stop OpsRequest", func() { var ( - randomStr = testCtx.GetRandomStr() - clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterName = "cluster-for-ops-" + randomStr + randomStr = testCtx.GetRandomStr() + compDefName = "test-compdef-" + randomStr + clusterName = "test-cluster-" + randomStr ) cleanEnv := func() { @@ -46,7 +46,7 @@ var _ = Describe("Stop OpsRequest", func() { By("clean resources") // delete cluster(and all dependent sub-resources), cluster definition - testapps.ClearClusterResources(&testCtx) + testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest resources inNS := client.InNamespace(testCtx.DefaultNamespace) @@ -63,10 +63,8 @@ var _ = Describe("Stop OpsRequest", func() { Context("Test OpsRequest", func() { It("Test stop OpsRequest", func() { reqCtx := intctrlutil.RequestCtx{Ctx: ctx} - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) - testapps.MockInstanceSetComponent(&testCtx, clusterName, consensusComp) - testapps.MockInstanceSetComponent(&testCtx, clusterName, statelessComp) - testapps.MockInstanceSetComponent(&testCtx, clusterName, statefulComp) + opsRes, _, _ := initOperationsResources(compDefName, clusterName) + testapps.MockInstanceSetComponent(&testCtx, clusterName, defaultCompName) By("create Stop opsRequest") ops := testapps.NewOpsRequestObj("stop-ops-"+randomStr, testCtx.DefaultNamespace, clusterName, appsv1alpha1.StopType) @@ -87,7 +85,7 @@ var _ = Describe("Stop OpsRequest", func() { Expect(*v.Stop).Should(BeTrue()) } _, err = GetOpsManager().Reconcile(reqCtx, k8sClient, opsRes) - Expect(err == nil).Should(BeTrue()) + Expect(err).Should(BeNil()) }) }) }) diff --git a/controllers/apps/operations/suite_test.go b/controllers/apps/operations/suite_test.go index 5b6d51f81cec..2f0f58fa7372 100644 --- a/controllers/apps/operations/suite_test.go +++ b/controllers/apps/operations/suite_test.go @@ -55,6 +55,10 @@ import ( // These tests use Ginkgo (BDD-style Go testing framework). Refer to // http://onsi.github.io/ginkgo/ to learn more about Ginkgo. +const ( + defaultCompName = "default" +) + var cfg *rest.Config var k8sClient client.Client var testEnv *envtest.Environment @@ -64,13 +68,6 @@ var k8sManager ctrl.Manager var testCtx testutil.TestContext var eventRecorder record.EventRecorder -const ( - statelessComp = "stateless" - statefulComp = "stateful" - consensusComp = "consensus" - defaultCompName = "default" -) - func init() { viper.AutomaticEnv() viper.SetDefault(constant.KBToolsImage, "apecloud/kubeblocks-tools:latest") @@ -149,35 +146,7 @@ var _ = AfterSuite(func() { Expect(err).NotTo(HaveOccurred()) }) -// initOperationsResources inits the operations resources. -func initOperationsResources(clusterDefinitionName, clusterName string) (*OpsResource, *appsv1alpha1.ClusterDefinition, *appsv1alpha1.Cluster) { - clusterDef, clusterObject := testapps.InitClusterWithHybridComps(&testCtx, clusterDefinitionName, - clusterName, statelessComp, statefulComp, consensusComp) - opsRes := &OpsResource{ - Cluster: clusterObject, - Recorder: k8sManager.GetEventRecorderFor("opsrequest-controller"), - } - - By("mock cluster is Running and the status operations") - Expect(testapps.ChangeObjStatus(&testCtx, clusterObject, func() { - clusterObject.Status.Phase = appsv1alpha1.RunningClusterPhase - clusterObject.Status.Components = map[string]appsv1alpha1.ClusterComponentStatus{ - consensusComp: { - Phase: appsv1alpha1.RunningClusterCompPhase, - }, - statelessComp: { - Phase: appsv1alpha1.RunningClusterCompPhase, - }, - statefulComp: { - Phase: appsv1alpha1.RunningClusterCompPhase, - }, - } - })).Should(Succeed()) - opsRes.Cluster = clusterObject - return opsRes, clusterDef, clusterObject -} - -func initOperationsResources2(compDefName, clusterName string) (*OpsResource, *appsv1alpha1.ComponentDefinition, *appsv1alpha1.Cluster) { +func initOperationsResources(compDefName, clusterName string) (*OpsResource, *appsv1alpha1.ComponentDefinition, *appsv1alpha1.Cluster) { compDef := testapps.NewComponentDefinitionFactory(compDefName). SetDefaultSpec(). Create(&testCtx). @@ -185,8 +154,8 @@ func initOperationsResources2(compDefName, clusterName string) (*OpsResource, *a pvcSpec := testapps.NewPVCSpec("1Gi") clusterObject := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). - AddComponentV2(defaultCompName, compDef.GetName()). - SetReplicas(1). + AddComponent(defaultCompName, compDef.GetName()). + SetReplicas(3). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). Create(&testCtx). GetObject() @@ -211,8 +180,8 @@ func initOperationsResources2(compDefName, clusterName string) (*OpsResource, *a func initInstanceSetPods(ctx context.Context, cli client.Client, opsRes *OpsResource) []*corev1.Pod { // mock the pods of consensusSet component - testapps.MockInstanceSetPods(&testCtx, nil, opsRes.Cluster, consensusComp) - pods, err := intctrlcomp.ListOwnedPods(ctx, cli, opsRes.Cluster.Namespace, opsRes.Cluster.Name, consensusComp) + testapps.MockInstanceSetPods(&testCtx, nil, opsRes.Cluster, defaultCompName) + pods, err := intctrlcomp.ListOwnedPods(ctx, cli, opsRes.Cluster.Namespace, opsRes.Cluster.Name, defaultCompName) Expect(err).Should(Succeed()) // the opsRequest will use startTime to check some condition. // if there is no sleep for 1 second, unstable error may occur. diff --git a/controllers/apps/operations/switchover_test.go b/controllers/apps/operations/switchover_test.go index d6f58963ba8a..0bad677155b9 100644 --- a/controllers/apps/operations/switchover_test.go +++ b/controllers/apps/operations/switchover_test.go @@ -37,15 +37,13 @@ import ( testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" ) -var ( - clusterDefObj *appsv1alpha1.ClusterDefinition - clusterObj *appsv1alpha1.Cluster -) - var _ = Describe("", func() { var ( randomStr = testCtx.GetRandomStr() - clusterName = "cluster-for-ops-" + randomStr + compDefName = "test-compdef-" + randomStr + clusterName = "test-cluster-" + randomStr + compDefObj *appsv1alpha1.ComponentDefinition + clusterObj *appsv1alpha1.Cluster ) defaultRole := func(index int32) string { @@ -79,7 +77,7 @@ var _ = Describe("", func() { By("clean resources") // delete cluster(and all dependent sub-resources), cluster definition - testapps.ClearClusterResources(&testCtx) + testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest resources inNS := client.InNamespace(testCtx.DefaultNamespace) @@ -94,43 +92,23 @@ var _ = Describe("", func() { Context("Test OpsRequest", func() { BeforeEach(func() { - By("Create a clusterDefinition obj with switchoverSpec.") - commandExecutorEnvItem := &appsv1alpha1.CommandExecutorEnvItem{ - Image: testapps.ApeCloudMySQLImage, - } - commandExecutorItem := &appsv1alpha1.CommandExecutorItem{ - Command: []string{"echo", "hello"}, - Args: []string{}, - } - switchoverSpec := &appsv1alpha1.SwitchoverSpec{ - WithCandidate: &appsv1alpha1.SwitchoverAction{ - CmdExecutorConfig: &appsv1alpha1.CmdExecutorConfig{ - CommandExecutorEnvItem: *commandExecutorEnvItem, - CommandExecutorItem: *commandExecutorItem, - }, - }, - WithoutCandidate: &appsv1alpha1.SwitchoverAction{ - CmdExecutorConfig: &appsv1alpha1.CmdExecutorConfig{ - CommandExecutorEnvItem: *commandExecutorEnvItem, - CommandExecutorItem: *commandExecutorItem, - }, - }, - } - clusterDefObj = testapps.NewClusterDefFactory(consensusComp). - AddComponentDef(testapps.ConsensusMySQLComponent, consensusComp). - AddSwitchoverSpec(switchoverSpec). - Create(&testCtx).GetObject() + By("Create a componentDefinition obj.") + compDefObj = testapps.NewComponentDefinitionFactory(compDefName). + SetDefaultSpec(). + Create(&testCtx). + GetObject() }) - It("Test switchover OpsRequest", func() { + // TODO(v1.0): workload and switchover have been removed from CD/CV. + PIt("Test switchover OpsRequest", func() { reqCtx := intctrlutil.RequestCtx{ Ctx: testCtx.Ctx, Recorder: k8sManager.GetEventRecorderFor("opsrequest-controller"), } By("Creating a cluster with consensus .") - clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). + clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). WithRandomName(). - AddComponent(consensusComp, consensusComp). + AddComponent(defaultCompName, compDefObj.GetName()). SetReplicas(2). Create(&testCtx).GetObject() @@ -141,16 +119,16 @@ var _ = Describe("", func() { ImagePullPolicy: corev1.PullIfNotPresent, } its := testapps.NewInstanceSetFactory(testCtx.DefaultNamespace, - clusterObj.Name+"-"+consensusComp, clusterObj.Name, consensusComp). + clusterObj.Name+"-"+defaultCompName, clusterObj.Name, defaultCompName). AddFinalizers([]string{constant.DBClusterFinalizerName}). AddContainer(container). AddAppInstanceLabel(clusterObj.Name). - AddAppComponentLabel(consensusComp). + AddAppComponentLabel(defaultCompName). AddAppManagedByLabel(). SetReplicas(2). Create(&testCtx).GetObject() - By("Creating Pods of replication workloadType.") + By("Creating Pods of replication.") var ( leaderPod *corev1.Pod followerPod *corev1.Pod @@ -176,7 +154,7 @@ var _ = Describe("", func() { Expect(testapps.ChangeObjStatus(&testCtx, clusterObj, func() { clusterObj.Status.Phase = appsv1alpha1.RunningClusterPhase clusterObj.Status.Components = map[string]appsv1alpha1.ClusterComponentStatus{ - consensusComp: { + defaultCompName: { Phase: appsv1alpha1.RunningClusterCompPhase, }, } @@ -188,8 +166,8 @@ var _ = Describe("", func() { clusterObj.Name, appsv1alpha1.SwitchoverType) ops.Spec.SwitchoverList = []appsv1alpha1.Switchover{ { - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, - InstanceName: fmt.Sprintf("%s-%s-%d", clusterObj.Name, consensusComp, 1), + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, + InstanceName: fmt.Sprintf("%s-%s-%d", clusterObj.Name, defaultCompName, 1), }, } opsRes.OpsRequest = testapps.CreateOpsRequest(ctx, testCtx, ops) @@ -212,7 +190,7 @@ var _ = Describe("", func() { Expect(err.Error()).Should(ContainSubstring("requeue to waiting for job")) By("mock job status to success.") - jobName := fmt.Sprintf("%s-%s-%s-%d", KBSwitchoverJobNamePrefix, opsRes.Cluster.Name, consensusComp, opsRes.Cluster.Generation) + jobName := fmt.Sprintf("%s-%s-%s-%d", KBSwitchoverJobNamePrefix, opsRes.Cluster.Name, defaultCompName, opsRes.Cluster.Generation) key := types.NamespacedName{ Name: jobName, Namespace: clusterObj.Namespace, diff --git a/controllers/apps/operations/switchover_util.go b/controllers/apps/operations/switchover_util.go index ec0b75e33f71..e9b3b9b36f2a 100644 --- a/controllers/apps/operations/switchover_util.go +++ b/controllers/apps/operations/switchover_util.go @@ -46,7 +46,6 @@ const ( KBSwitchoverCandidateInstanceForAnyPod = "*" - KBJobTTLSecondsAfterFinished = 5 KBSwitchoverJobLabelKey = "kubeblocks.io/switchover-job" KBSwitchoverJobLabelValue = "kb-switchover-job" KBSwitchoverJobNamePrefix = "kb-switchover-job" @@ -57,14 +56,6 @@ const ( KBSwitchoverCandidateName = "KB_SWITCHOVER_CANDIDATE_NAME" KBSwitchoverCandidateFqdn = "KB_SWITCHOVER_CANDIDATE_FQDN" - // KBSwitchoverReplicationPrimaryPodIP and the others Replication and Consensus switchover constants will be deprecated in the future, use KBSwitchoverLeaderPodIP instead. - KBSwitchoverReplicationPrimaryPodIP = "KB_REPLICATION_PRIMARY_POD_IP" - KBSwitchoverReplicationPrimaryPodName = "KB_REPLICATION_PRIMARY_POD_NAME" - KBSwitchoverReplicationPrimaryPodFqdn = "KB_REPLICATION_PRIMARY_POD_FQDN" - KBSwitchoverConsensusLeaderPodIP = "KB_CONSENSUS_LEADER_POD_IP" - KBSwitchoverConsensusLeaderPodName = "KB_CONSENSUS_LEADER_POD_NAME" - KBSwitchoverConsensusLeaderPodFqdn = "KB_CONSENSUS_LEADER_POD_FQDN" - KBSwitchoverLeaderPodIP = "KB_LEADER_POD_IP" KBSwitchoverLeaderPodName = "KB_LEADER_POD_NAME" KBSwitchoverLeaderPodFqdn = "KB_LEADER_POD_FQDN" @@ -414,34 +405,6 @@ func buildSwitchoverWorkloadEnvs(ctx context.Context, }, }...) - // TODO(xingran): backward compatibility for the old env based on workloadType, it will be removed in the future - workloadEnvs = append(workloadEnvs, []corev1.EnvVar{ - { - Name: KBSwitchoverReplicationPrimaryPodIP, - Value: pod.Status.PodIP, - }, - { - Name: KBSwitchoverReplicationPrimaryPodName, - Value: pod.Name, - }, - { - Name: KBSwitchoverReplicationPrimaryPodFqdn, - Value: fmt.Sprintf("%s.%s", pod.Name, svcName), - }, - { - Name: KBSwitchoverConsensusLeaderPodIP, - Value: pod.Status.PodIP, - }, - { - Name: KBSwitchoverConsensusLeaderPodName, - Value: pod.Name, - }, - { - Name: KBSwitchoverConsensusLeaderPodFqdn, - Value: fmt.Sprintf("%s.%s", pod.Name, svcName), - }, - }...) - // add the first container's environment variables of the primary pod workloadEnvs = append(workloadEnvs, pod.Spec.Containers[0].Env...) return workloadEnvs, nil diff --git a/controllers/apps/operations/switchover_util_test.go b/controllers/apps/operations/switchover_util_test.go deleted file mode 100644 index ee27b520eab3..000000000000 --- a/controllers/apps/operations/switchover_util_test.go +++ /dev/null @@ -1,242 +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 operations - -import ( - "fmt" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - corev1 "k8s.io/api/core/v1" - "sigs.k8s.io/controller-runtime/pkg/client" - - appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" - "github.com/apecloud/kubeblocks/pkg/constant" - "github.com/apecloud/kubeblocks/pkg/controller/component" - intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" - "github.com/apecloud/kubeblocks/pkg/generics" - testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" -) - -var _ = Describe("Switchover Util", func() { - - var ( - clusterName = "test-cluster-repl" - clusterDefName = "test-cluster-def-repl" - ) - - var ( - clusterDefObj *appsv1alpha1.ClusterDefinition - clusterObj *appsv1alpha1.Cluster - ) - - defaultRole := func(index int32) string { - role := constant.Secondary - if index == 0 { - role = constant.Primary - } - return role - } - - cleanAll := 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, - // in race conditions, it will find the existence of old objects, resulting failure to - // create the new objects. - By("clean resources") - // delete cluster(and all dependent sub-resources), cluster definition - testapps.ClearClusterResources(&testCtx) - - // clear rest resources - inNS := client.InNamespace(testCtx.DefaultNamespace) - ml := client.HasLabels{testCtx.TestObjLabelKey} - // namespaced resources - testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.InstanceSetSignature, true, inNS, ml) - testapps.ClearResources(&testCtx, generics.PodSignature, inNS, ml, client.GracePeriodSeconds(0)) - } - - BeforeEach(cleanAll) - - AfterEach(cleanAll) - - testNeedDoSwitchover := func() { - By("Creating a cluster with replication workloadType.") - clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). - WithRandomName(). - AddComponent(testapps.DefaultRedisCompSpecName, testapps.DefaultRedisCompDefName). - SetReplicas(testapps.DefaultReplicationReplicas). - Create(&testCtx).GetObject() - - By("Creating a statefulSet of replication workloadType.") - container := corev1.Container{ - Name: "mock-redis-container", - Image: testapps.DefaultRedisImageName, - ImagePullPolicy: corev1.PullIfNotPresent, - } - its := testapps.NewInstanceSetFactory(testCtx.DefaultNamespace, - clusterObj.Name+"-"+testapps.DefaultRedisCompSpecName, clusterObj.Name, testapps.DefaultRedisCompSpecName). - AddFinalizers([]string{constant.DBClusterFinalizerName}). - AddContainer(container). - AddAppInstanceLabel(clusterObj.Name). - AddAppComponentLabel(testapps.DefaultRedisCompSpecName). - AddAppManagedByLabel(). - SetReplicas(2). - Create(&testCtx).GetObject() - - By("Creating Pods of replication workloadType.") - for i := int32(0); i < *its.Spec.Replicas; i++ { - _ = testapps.NewPodFactory(testCtx.DefaultNamespace, fmt.Sprintf("%s-%d", its.Name, i)). - AddContainer(container). - AddLabelsInMap(its.Labels). - AddRoleLabel(defaultRole(i)). - Create(&testCtx).GetObject() - } - - opsSwitchover := &appsv1alpha1.Switchover{ - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: testapps.DefaultRedisCompSpecName}, - InstanceName: fmt.Sprintf("%s-%s-%d", clusterObj.Name, testapps.DefaultRedisCompSpecName, 0), - } - - reqCtx := intctrlutil.RequestCtx{ - Ctx: testCtx.Ctx, - } - compSpec := clusterObj.Spec.GetComponentByName(opsSwitchover.ComponentName) - synthesizedComp, err := component.BuildSynthesizedComponentWrapper(reqCtx, k8sClient, clusterObj, compSpec) - Expect(err).Should(Succeed()) - Expect(synthesizedComp).ShouldNot(BeNil()) - - By("Test opsSwitchover.Instance is already primary, and do not need to do switchover.") - needSwitchover, err := needDoSwitchover(testCtx.Ctx, k8sClient, synthesizedComp, opsSwitchover) - Expect(err).Should(Succeed()) - Expect(needSwitchover).Should(BeFalse()) - - By("Test opsSwitchover.Instance is not primary, and need to do switchover.") - opsSwitchover.InstanceName = fmt.Sprintf("%s-%s-%d", clusterObj.Name, testapps.DefaultRedisCompSpecName, 1) - needSwitchover, err = needDoSwitchover(testCtx.Ctx, k8sClient, synthesizedComp, opsSwitchover) - Expect(err).Should(Succeed()) - Expect(needSwitchover).Should(BeTrue()) - - By("Test opsSwitchover.Instance is *, and need to do switchover.") - opsSwitchover.InstanceName = "*" - needSwitchover, err = needDoSwitchover(testCtx.Ctx, k8sClient, synthesizedComp, opsSwitchover) - Expect(err).Should(Succeed()) - Expect(needSwitchover).Should(BeTrue()) - } - - testDoSwitchover := func() { - By("Creating a cluster with replication workloadType.") - clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). - WithRandomName(). - AddComponent(testapps.DefaultRedisCompSpecName, testapps.DefaultRedisCompDefName). - SetReplicas(testapps.DefaultReplicationReplicas). - Create(&testCtx).GetObject() - - By("Creating a statefulSet of replication workloadType.") - container := corev1.Container{ - Name: "mock-redis-container", - Image: testapps.DefaultRedisImageName, - ImagePullPolicy: corev1.PullIfNotPresent, - } - its := testapps.NewInstanceSetFactory(testCtx.DefaultNamespace, - clusterObj.Name+"-"+testapps.DefaultRedisCompSpecName, clusterObj.Name, testapps.DefaultRedisCompSpecName). - AddFinalizers([]string{constant.DBClusterFinalizerName}). - AddContainer(container). - AddAppInstanceLabel(clusterObj.Name). - AddAppComponentLabel(testapps.DefaultRedisCompSpecName). - AddAppManagedByLabel(). - SetReplicas(2). - Create(&testCtx).GetObject() - - By("Creating Pods of replication workloadType.") - for i := int32(0); i < *its.Spec.Replicas; i++ { - _ = testapps.NewPodFactory(testCtx.DefaultNamespace, fmt.Sprintf("%s-%d", its.Name, i)). - AddContainer(container). - AddLabelsInMap(its.Labels). - AddRoleLabel(defaultRole(i)). - Create(&testCtx).GetObject() - } - opsSwitchover := &appsv1alpha1.Switchover{ - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: testapps.DefaultRedisCompSpecName}, - InstanceName: fmt.Sprintf("%s-%s-%d", clusterObj.Name, testapps.DefaultRedisCompSpecName, 1), - } - reqCtx := intctrlutil.RequestCtx{ - Ctx: testCtx.Ctx, - Recorder: k8sManager.GetEventRecorderFor("opsrequest-controller"), - } - By("Test create a job to do switchover") - compSpec := clusterObj.Spec.GetComponentByName(opsSwitchover.ComponentName) - synthesizedComp, err := component.BuildSynthesizedComponentWrapper(reqCtx, k8sClient, clusterObj, compSpec) - Expect(err).Should(Succeed()) - Expect(synthesizedComp).ShouldNot(BeNil()) - err = createSwitchoverJob(reqCtx, k8sClient, clusterObj, synthesizedComp, opsSwitchover) - Expect(err).Should(Succeed()) - } - - // Scenarios - Context("test switchover util", func() { - BeforeEach(func() { - By("Create a clusterDefinition obj with replication workloadType.") - commandExecutorEnvItem := &appsv1alpha1.CommandExecutorEnvItem{ - Image: testapps.DefaultRedisImageName, - } - commandExecutorItem := &appsv1alpha1.CommandExecutorItem{ - Command: []string{"echo", "hello"}, - Args: []string{}, - } - scriptSpecSelectors := []appsv1alpha1.ScriptSpecSelector{ - { - Name: "test-mock-cm", - }, - { - Name: "test-mock-cm-2", - }, - } - switchoverSpec := &appsv1alpha1.SwitchoverSpec{ - WithCandidate: &appsv1alpha1.SwitchoverAction{ - CmdExecutorConfig: &appsv1alpha1.CmdExecutorConfig{ - CommandExecutorEnvItem: *commandExecutorEnvItem, - CommandExecutorItem: *commandExecutorItem, - }, - ScriptSpecSelectors: scriptSpecSelectors, - }, - WithoutCandidate: &appsv1alpha1.SwitchoverAction{ - CmdExecutorConfig: &appsv1alpha1.CmdExecutorConfig{ - CommandExecutorEnvItem: *commandExecutorEnvItem, - CommandExecutorItem: *commandExecutorItem, - }, - ScriptSpecSelectors: scriptSpecSelectors, - }, - } - clusterDefObj = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.ReplicationRedisComponent, testapps.DefaultRedisCompDefName). - AddSwitchoverSpec(switchoverSpec). - Create(&testCtx).GetObject() - }) - - It("Test needDoSwitchover with different conditions", func() { - testNeedDoSwitchover() - }) - - It("Test doSwitchover when opsRequest triggers", func() { - testDoSwitchover() - }) - }) -}) diff --git a/controllers/apps/operations/upgrade_test.go b/controllers/apps/operations/upgrade_test.go index 0e363b95e638..1c6034fa3957 100644 --- a/controllers/apps/operations/upgrade_test.go +++ b/controllers/apps/operations/upgrade_test.go @@ -55,18 +55,13 @@ var _ = Describe("Upgrade OpsRequest", func() { By("clean resources") // delete cluster(and all dependent sub-resources), cluster definition - testapps.ClearClusterResources(&testCtx) + testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest resources inNS := client.InNamespace(testCtx.DefaultNamespace) ml := client.HasLabels{testCtx.TestObjLabelKey} // namespaced testapps.ClearResources(&testCtx, generics.OpsRequestSignature, inNS, ml) - - // non-namespaced - testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.ComponentDefinitionSignature, true, ml) - testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.ComponentVersionSignature, true, ml) - } BeforeEach(cleanEnv) @@ -81,15 +76,14 @@ var _ = Describe("Upgrade OpsRequest", func() { // do upgrade _, err = GetOpsManager().Do(reqCtx, k8sClient, opsRes) Expect(err).ShouldNot(HaveOccurred()) - mockComponentIsOperating(opsRes.Cluster, appsv1alpha1.UpdatingClusterCompPhase, - consensusComp, statelessComp, statefulComp) + mockComponentIsOperating(opsRes.Cluster, appsv1alpha1.UpdatingClusterCompPhase, defaultCompName) } mockClusterRunning := func(clusterObject *appsv1alpha1.Cluster) { Expect(testapps.ChangeObjStatus(&testCtx, clusterObject, func() { clusterObject.Status.Phase = appsv1alpha1.RunningClusterPhase clusterObject.Status.Components = map[string]appsv1alpha1.ClusterComponentStatus{ - consensusComp: { + defaultCompName: { Phase: appsv1alpha1.RunningClusterCompPhase, }, } @@ -184,7 +178,7 @@ var _ = Describe("Upgrade OpsRequest", func() { } // create the cluster with no clusterDefinition clusterObject := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). - AddComponentV2(consensusComp, compDef1.Name). + AddComponent(defaultCompName, compDef1.Name). SetServiceVersion(testapps.ServiceVersion("v0")). SetReplicas(int32(3)).Create(&testCtx).GetObject() opsRes := &OpsResource{ @@ -215,7 +209,7 @@ var _ = Describe("Upgrade OpsRequest", func() { } mockPodsAppliedImage := func(cluster *appsv1alpha1.Cluster, releaseVersion string) { - pods := testapps.MockInstanceSetPods(&testCtx, nil, cluster, consensusComp) + pods := testapps.MockInstanceSetPods(&testCtx, nil, cluster, defaultCompName) image := testapps.AppImage(testapps.AppName, releaseVersion) for i := range pods { pod := pods[i] @@ -243,7 +237,7 @@ var _ = Describe("Upgrade OpsRequest", func() { opsRes.OpsRequest = createUpgradeOpsRequest(opsRes.Cluster, appsv1alpha1.Upgrade{ Components: []appsv1alpha1.UpgradeComponent{ { - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, ComponentDefinitionName: &compDef2.Name, }, }, @@ -253,12 +247,12 @@ var _ = Describe("Upgrade OpsRequest", func() { reqCtx := intctrlutil.RequestCtx{Ctx: ctx} makeUpgradeOpsIsRunning(reqCtx, opsRes) Eventually(testapps.CheckObj(&testCtx, client.ObjectKeyFromObject(opsRes.OpsRequest), func(g Gomega, ops *appsv1alpha1.OpsRequest) { - g.Expect(ops.Status.LastConfiguration.Components[consensusComp].ComponentDefinitionName).Should(Equal(compDef1.Name)) + g.Expect(ops.Status.LastConfiguration.Components[defaultCompName].ComponentDefinitionName).Should(Equal(compDef1.Name)) })).Should(Succeed()) By("expect upgrade successfully with the image that is provided in the specified componentDefinition") mockPodsAppliedImage(opsRes.Cluster, release2) - expectOpsSucceed(reqCtx, opsRes, consensusComp) + expectOpsSucceed(reqCtx, opsRes, defaultCompName) }) It("Test upgrade OpsRequest with ComponentDef and ComponentVersion", func() { @@ -269,7 +263,7 @@ var _ = Describe("Upgrade OpsRequest", func() { opsRes.OpsRequest = createUpgradeOpsRequest(opsRes.Cluster, appsv1alpha1.Upgrade{ Components: []appsv1alpha1.UpgradeComponent{ { - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, ServiceVersion: pointer.String(serviceVer2), ComponentDefinitionName: &compDef2.Name, }, @@ -286,7 +280,7 @@ var _ = Describe("Upgrade OpsRequest", func() { By("expect upgrade successfully") mockPodsAppliedImage(opsRes.Cluster, release3) - expectOpsSucceed(reqCtx, opsRes, consensusComp) + expectOpsSucceed(reqCtx, opsRes, defaultCompName) }) It("Test upgrade OpsRequest without ComponentDefinitionName but the cluster is created without clusterDefinition", func() { @@ -297,7 +291,7 @@ var _ = Describe("Upgrade OpsRequest", func() { opsRes.OpsRequest = createUpgradeOpsRequest(opsRes.Cluster, appsv1alpha1.Upgrade{ Components: []appsv1alpha1.UpgradeComponent{ { - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, ComponentDefinitionName: pointer.String(""), ServiceVersion: pointer.String(serviceVer1), }, @@ -314,7 +308,7 @@ var _ = Describe("Upgrade OpsRequest", func() { By("expect upgrade successfully with the latest release of the specified serviceVersion") mockPodsAppliedImage(opsRes.Cluster, release4) - expectOpsSucceed(reqCtx, opsRes, consensusComp) + expectOpsSucceed(reqCtx, opsRes, defaultCompName) }) It("Test upgrade OpsRequest when specified serviceVersion is empty", func() { @@ -325,7 +319,7 @@ var _ = Describe("Upgrade OpsRequest", func() { opsRes.OpsRequest = createUpgradeOpsRequest(opsRes.Cluster, appsv1alpha1.Upgrade{ Components: []appsv1alpha1.UpgradeComponent{ { - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, ComponentDefinitionName: pointer.String(compDef1.Name), ServiceVersion: pointer.String(""), }, @@ -342,7 +336,7 @@ var _ = Describe("Upgrade OpsRequest", func() { By("looking forward to using the latest serviceVersion and releaseVersion") mockPodsAppliedImage(opsRes.Cluster, release4) - expectOpsSucceed(reqCtx, opsRes, consensusComp) + expectOpsSucceed(reqCtx, opsRes, defaultCompName) }) It("Test upgrade OpsRequest when serviceVersion is nil", func() { @@ -353,7 +347,7 @@ var _ = Describe("Upgrade OpsRequest", func() { opsRes.OpsRequest = createUpgradeOpsRequest(opsRes.Cluster, appsv1alpha1.Upgrade{ Components: []appsv1alpha1.UpgradeComponent{ { - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, ComponentDefinitionName: pointer.String(compDef2.Name), }, }, @@ -376,7 +370,7 @@ var _ = Describe("Upgrade OpsRequest", func() { opsRes.OpsRequest = createUpgradeOpsRequest(opsRes.Cluster, appsv1alpha1.Upgrade{ Components: []appsv1alpha1.UpgradeComponent{ { - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, ServiceVersion: pointer.String(""), }, }, diff --git a/controllers/apps/operations/util/common_util_test.go b/controllers/apps/operations/util/common_util_test.go index d87c54aa02a9..08c3668fbe32 100644 --- a/controllers/apps/operations/util/common_util_test.go +++ b/controllers/apps/operations/util/common_util_test.go @@ -34,10 +34,10 @@ import ( var _ = Describe("OpsRequest Controller", func() { var ( - randomStr = testCtx.GetRandomStr() - clusterDefinitionName = "cluster-definition-" + randomStr - clusterName = "cluster-" + randomStr - consensusCompName = "consensus" + randomStr = testCtx.GetRandomStr() + compDefName = "test-compdef-" + randomStr + clusterName = "test-cluster-" + randomStr + defaultCompName = "mysql" ) cleanupObjects := func() { @@ -59,14 +59,13 @@ var _ = Describe("OpsRequest Controller", func() { Context("Test OpsRequest", func() { It("Should Test all OpsRequest", func() { - cluster := testapps.CreateConsensusMysqlCluster(&testCtx, clusterDefinitionName, - clusterName, "consensus", consensusCompName) + cluster := testapps.CreateDefaultMysqlCluster(&testCtx, clusterName, compDefName, defaultCompName) By("init restart OpsRequest") testOpsName := "restart-" + randomStr ops := testapps.NewOpsRequestObj(testOpsName, testCtx.DefaultNamespace, clusterName, appsv1alpha1.RestartType) ops.Spec.RestartList = []appsv1alpha1.ComponentOps{ - {ComponentName: consensusCompName}, + {ComponentName: defaultCompName}, } testapps.CreateOpsRequest(ctx, testCtx, ops) diff --git a/controllers/apps/operations/vertical_scaling_test.go b/controllers/apps/operations/vertical_scaling_test.go index becba4bda50d..e75e5cc8ae6b 100644 --- a/controllers/apps/operations/vertical_scaling_test.go +++ b/controllers/apps/operations/vertical_scaling_test.go @@ -42,11 +42,12 @@ import ( var _ = Describe("VerticalScaling OpsRequest", func() { var ( - randomStr = testCtx.GetRandomStr() - clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterName = "cluster-for-ops-" + randomStr - reqCtx intctrlutil.RequestCtx + randomStr = testCtx.GetRandomStr() + compDefName = "test-compdef-" + randomStr + clusterName = "test-cluster-" + randomStr + reqCtx intctrlutil.RequestCtx ) + cleanEnv := func() { reqCtx = intctrlutil.RequestCtx{Ctx: ctx} // must wait till resources deleted and no longer existed before the testcases start, @@ -55,7 +56,7 @@ var _ = Describe("VerticalScaling OpsRequest", func() { // create the new objects. By("clean resources") // delete cluster(and all dependent sub-resources), cluster definition - testapps.ClearClusterResources(&testCtx) + testapps.ClearClusterResourcesWithRemoveFinalizerOption(&testCtx) // delete rest resources inNS := client.InNamespace(testCtx.DefaultNamespace) @@ -72,7 +73,7 @@ var _ = Describe("VerticalScaling OpsRequest", func() { testVerticalScaling := func(verticalScaling []appsv1alpha1.VerticalScaling) *OpsResource { By("init operations resources ") - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) + opsRes, _, _ := initOperationsResources(compDefName, clusterName) By("create VerticalScaling ops") ops := testapps.NewOpsRequestObj("vertical-scaling-ops-"+randomStr, testCtx.DefaultNamespace, @@ -99,7 +100,7 @@ var _ = Describe("VerticalScaling OpsRequest", func() { It("vertical scaling by resource", func() { verticalScaling := []appsv1alpha1.VerticalScaling{ { - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, ResourceRequirements: corev1.ResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("400m"), @@ -118,7 +119,7 @@ var _ = Describe("VerticalScaling OpsRequest", func() { It("cancel vertical scaling opsRequest", func() { By("init operations resources with CLusterDefinition/Hybrid components Cluster/consensus Pods") reqCtx := intctrlutil.RequestCtx{Ctx: ctx} - opsRes, _, _ := initOperationsResources(clusterDefinitionName, clusterName) + opsRes, _, _ := initOperationsResources(compDefName, clusterName) podList := initInstanceSetPods(ctx, k8sClient, opsRes) By("create VerticalScaling ops") @@ -126,7 +127,7 @@ var _ = Describe("VerticalScaling OpsRequest", func() { clusterName, appsv1alpha1.VerticalScalingType) ops.Spec.VerticalScalingList = []appsv1alpha1.VerticalScaling{ { - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, ResourceRequirements: corev1.ResourceRequirements{ Limits: corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("400m"), @@ -138,7 +139,7 @@ var _ = Describe("VerticalScaling OpsRequest", func() { opsRes.OpsRequest = testapps.CreateOpsRequest(ctx, testCtx, ops) By("mock opsRequest is Running") - mockComponentIsOperating(opsRes.Cluster, appsv1alpha1.UpdatingClusterCompPhase, consensusComp) + mockComponentIsOperating(opsRes.Cluster, appsv1alpha1.UpdatingClusterCompPhase, defaultCompName) Expect(testapps.ChangeObjStatus(&testCtx, opsRes.OpsRequest, func() { opsRes.OpsRequest.Status.Phase = appsv1alpha1.OpsRunningPhase opsRes.OpsRequest.Status.StartTimestamp = metav1.Time{Time: time.Now()} @@ -149,7 +150,7 @@ var _ = Describe("VerticalScaling OpsRequest", func() { pod.Kind = constant.PodKind testk8s.MockPodIsTerminating(ctx, testCtx, pod) testk8s.RemovePodFinalizer(ctx, testCtx, pod) - testapps.MockInstanceSetPod(&testCtx, nil, clusterName, consensusComp, + testapps.MockInstanceSetPod(&testCtx, nil, clusterName, defaultCompName, pod.Name, "leader", "ReadWrite", ops.Spec.VerticalScalingList[0].ResourceRequirements) } @@ -161,7 +162,7 @@ var _ = Describe("VerticalScaling OpsRequest", func() { Expect(err).ShouldNot(HaveOccurred()) By("the progress status of pod[0] should be Succeed ") - progressDetails := opsRes.OpsRequest.Status.Components[consensusComp].ProgressDetails + progressDetails := opsRes.OpsRequest.Status.Components[defaultCompName].ProgressDetails progressDetail := findStatusProgressDetail(progressDetails, getProgressObjectKey(constant.PodKind, podList[0].Name)) Expect(progressDetail.Status).Should(Equal(appsv1alpha1.SucceedProgressStatus)) @@ -180,7 +181,7 @@ var _ = Describe("VerticalScaling OpsRequest", func() { opsRequest := opsRes.OpsRequest Expect(opsRequest.Status.Phase).Should(Equal(appsv1alpha1.OpsCancelledPhase)) Expect(opsRequest.Status.Progress).Should(Equal("1/1")) - progressDetails = opsRequest.Status.Components[consensusComp].ProgressDetails + progressDetails = opsRequest.Status.Components[defaultCompName].ProgressDetails Expect(len(progressDetails)).Should(Equal(1)) progressDetail = findStatusProgressDetail(progressDetails, getProgressObjectKey(constant.PodKind, podList[0].Name)) Expect(progressDetail.Status).Should(Equal(appsv1alpha1.SucceedProgressStatus)) @@ -191,7 +192,7 @@ var _ = Describe("VerticalScaling OpsRequest", func() { By("create the first vertical scaling") verticalScaling1 := []appsv1alpha1.VerticalScaling{ { - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, ResourceRequirements: corev1.ResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("400m"), @@ -216,7 +217,7 @@ var _ = Describe("VerticalScaling OpsRequest", func() { ops.Spec.Force = true ops.Spec.VerticalScalingList = []appsv1alpha1.VerticalScaling{ { - ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusComp}, + ComponentOps: appsv1alpha1.ComponentOps{ComponentName: defaultCompName}, ResourceRequirements: corev1.ResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("400m"), diff --git a/controllers/apps/operations/volume_expansion_test.go b/controllers/apps/operations/volume_expansion_test.go index 7da6f5ce5301..f10cad99bb3c 100644 --- a/controllers/apps/operations/volume_expansion_test.go +++ b/controllers/apps/operations/volume_expansion_test.go @@ -42,11 +42,10 @@ import ( var _ = Describe("OpsRequest Controller Volume Expansion Handler", func() { var ( - // waitDuration = time.Second * 3 - randomStr = testCtx.GetRandomStr() - clusterDefinitionName = "cluster-definition-for-ops-" + randomStr - clusterName = "cluster-for-ops-" + randomStr - storageClassName = "csi-hostpath-sc-" + randomStr + randomStr = testCtx.GetRandomStr() + compDefName = "test-compdef-" + randomStr + clusterName = "test-cluster-" + randomStr + storageClassName = "csi-hostpath-sc-" + randomStr ) const ( @@ -218,8 +217,7 @@ var _ = Describe("OpsRequest Controller Volume Expansion Handler", func() { Context("Test VolumeExpansion", func() { It("VolumeExpansion should work", func() { reqCtx := intctrlutil.RequestCtx{Ctx: ctx} - _, clusterObject := testapps.InitConsensusMysql(&testCtx, clusterDefinitionName, - clusterName, "consensus", consensusCompName) + _, clusterObject := testapps.InitConsensusMysql(&testCtx, clusterName, compDefName, consensusCompName) // init storageClass sc := testapps.CreateStorageClass(&testCtx, storageClassName, true) Expect(testapps.ChangeObj(&testCtx, sc, func(lsc *storagev1.StorageClass) { diff --git a/controllers/apps/opsrequest_controller_test.go b/controllers/apps/opsrequest_controller_test.go index 3e49d66a7186..3b2d052fce1b 100644 --- a/controllers/apps/opsrequest_controller_test.go +++ b/controllers/apps/opsrequest_controller_test.go @@ -52,9 +52,8 @@ import ( ) var _ = Describe("OpsRequest Controller", func() { - const clusterDefName = "test-clusterdef" + const compDefName = "test-compdef" const clusterNamePrefix = "test-cluster" - const mysqlCompDefName = "mysql" const mysqlCompName = "mysql" const defaultMinReadySeconds = 10 @@ -101,9 +100,9 @@ var _ = Describe("OpsRequest Controller", func() { }) var ( - clusterDefObj *appsv1alpha1.ClusterDefinition - clusterObj *appsv1alpha1.Cluster - clusterKey types.NamespacedName + compDefObj *appsv1alpha1.ComponentDefinition + clusterObj *appsv1alpha1.Cluster + clusterKey types.NamespacedName ) mockSetClusterStatusPhaseToRunning := func(namespacedName types.NamespacedName) { @@ -133,13 +132,13 @@ var _ = Describe("OpsRequest Controller", func() { target corev1.ResourceRequirements } - testVerticalScaleCPUAndMemory := func(workloadType testapps.ComponentDefTplType, scalingCtx verticalScalingContext) { + testVerticalScaleCPUAndMemory := func(scalingCtx verticalScalingContext) { const opsName = "mysql-verticalscaling" By("Create a cluster obj") - clusterFactory := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterNamePrefix, clusterDefObj.Name). + clusterFactory := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterNamePrefix, ""). WithRandomName(). - AddComponent(mysqlCompName, mysqlCompDefName). + AddComponent(mysqlCompName, compDefName). SetReplicas(1). SetResources(scalingCtx.source) clusterObj = clusterFactory.Create(&testCtx).GetObject() @@ -152,15 +151,15 @@ var _ = Describe("OpsRequest Controller", func() { podName := fmt.Sprintf("%s-%s-0", clusterObj.Name, mysqlCompName) pod := testapps.MockInstanceSetPod(&testCtx, nil, clusterObj.Name, mysqlCompName, podName, "leader", "ReadWrite") + // the opsRequest will use startTime to check some condition. // if there is no sleep for 1 second, unstable error may occur. time.Sleep(time.Second) - if workloadType == testapps.StatefulMySQLComponent { - lastTransTime := metav1.NewTime(time.Now().Add(-1 * (defaultMinReadySeconds + 1) * time.Second)) - Expect(testapps.ChangeObjStatus(&testCtx, pod, func() { - testk8s.MockPodAvailable(pod, lastTransTime) - })).ShouldNot(HaveOccurred()) - } + lastTransTime := metav1.NewTime(time.Now().Add(-1 * (defaultMinReadySeconds + 1) * time.Second)) + Expect(testapps.ChangeObjStatus(&testCtx, pod, func() { + testk8s.MockPodAvailable(pod, lastTransTime) + })).ShouldNot(HaveOccurred()) + itsList := testk8s.ListAndCheckInstanceSetWithComponent(&testCtx, clusterKey, mysqlCompName) mysqlIts := &itsList.Items[0] Expect(testapps.ChangeObjStatus(&testCtx, mysqlIts, func() { @@ -235,10 +234,11 @@ var _ = Describe("OpsRequest Controller", func() { // TODO: should focus on OpsRequest control actions, and iterator through all component workload types. Context("with Cluster which has MySQL Component", func() { BeforeEach(func() { - By("Create a clusterDefinition obj") - clusterDefObj = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). - Create(&testCtx).GetObject() + By("Create a componentDefinition obj") + compDefObj = testapps.NewComponentDefinitionFactory(compDefName). + SetDefaultSpec(). + Create(&testCtx). + GetObject() }) It("create cluster by resource, vertical scaling by resource", func() { @@ -246,20 +246,20 @@ var _ = Describe("OpsRequest Controller", func() { source: corev1.ResourceRequirements{Requests: _1c1g, Limits: _1c1g}, target: corev1.ResourceRequirements{Requests: _2c4g, Limits: _2c4g}, } - testVerticalScaleCPUAndMemory(testapps.StatefulMySQLComponent, ctx) + testVerticalScaleCPUAndMemory(ctx) }) }) Context("with Cluster which has MySQL ConsensusSet", func() { BeforeEach(func() { - By("Create a clusterDefinition obj") testk8s.MockEnableVolumeSnapshot(&testCtx, testk8s.DefaultStorageClassName) - clusterDefObj = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.ConsensusMySQLComponent, mysqlCompDefName). - AddHorizontalScalePolicy(appsv1alpha1.HorizontalScalePolicy{ - Type: appsv1alpha1.HScaleDataClonePolicyCloneVolume, - BackupPolicyTemplateName: backupPolicyTPLName, - }).Create(&testCtx).GetObject() + + By("Create a componentDefinition obj") + compDefObj = testapps.NewComponentDefinitionFactory(compDefName). + AddAnnotations(constant.HorizontalScaleBackupPolicyTemplateKey, backupPolicyTPLName). + SetDefaultSpec(). + Create(&testCtx). + GetObject() By("Mock lorry client for the default transformer of system accounts provision") mockLorryClientDefault() @@ -307,21 +307,23 @@ var _ = Describe("OpsRequest Controller", func() { } createMysqlCluster := func(replicas int32) { - createBackupPolicyTpl(clusterDefObj, mysqlCompDefName) + createBackupPolicyTpl(compDefObj.GetName()) By("set component to horizontal with snapshot policy and create a cluster") testk8s.MockEnableVolumeSnapshot(&testCtx, testk8s.DefaultStorageClassName) - if clusterDefObj.Spec.ComponentDefs[0].HorizontalScalePolicy == nil { - Expect(testapps.GetAndChangeObj(&testCtx, client.ObjectKeyFromObject(clusterDefObj), - func(clusterDef *appsv1alpha1.ClusterDefinition) { - clusterDef.Spec.ComponentDefs[0].HorizontalScalePolicy = - &appsv1alpha1.HorizontalScalePolicy{Type: appsv1alpha1.HScaleDataClonePolicyCloneVolume} - })()).ShouldNot(HaveOccurred()) - } + // TODO(v1.0): bpt + // if clusterDefObj.Spec.ComponentDefs[0].HorizontalScalePolicy == nil { + // Expect(testapps.GetAndChangeObj(&testCtx, client.ObjectKeyFromObject(clusterDefObj), + // func(clusterDef *appsv1alpha1.ClusterDefinition) { + // clusterDef.Spec.ComponentDefs[0].HorizontalScalePolicy = + // &appsv1alpha1.HorizontalScalePolicy{Type: appsv1alpha1.HScaleDataClonePolicyCloneVolume} + // })()).ShouldNot(HaveOccurred()) + // } pvcSpec := testapps.NewPVCSpec("1Gi") - clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterNamePrefix, clusterDefObj.Name). + clusterObj = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterNamePrefix, ""). WithRandomName(). - AddComponent(mysqlCompName, mysqlCompDefName). + AddComponent(mysqlCompName, compDefObj.GetName()). + SetServiceVersion(compDefObj.Spec.ServiceVersion). SetReplicas(replicas). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). Create(&testCtx).GetObject() @@ -374,7 +376,7 @@ var _ = Describe("OpsRequest Controller", func() { source: corev1.ResourceRequirements{Requests: _1c1g, Limits: _1c1g}, target: corev1.ResourceRequirements{Requests: _2c4g, Limits: _2c4g}, } - testVerticalScaleCPUAndMemory(testapps.ConsensusMySQLComponent, ctx) + testVerticalScaleCPUAndMemory(ctx) }) It("HorizontalScaling when not support snapshot", func() { diff --git a/controllers/apps/transformer_cluster_api_normalization.go b/controllers/apps/transformer_cluster_api_normalization.go index 48c442414711..cb927ddeb598 100644 --- a/controllers/apps/transformer_cluster_api_normalization.go +++ b/controllers/apps/transformer_cluster_api_normalization.go @@ -29,7 +29,6 @@ import ( appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" "github.com/apecloud/kubeblocks/pkg/constant" - "github.com/apecloud/kubeblocks/pkg/controller/apiconversion" "github.com/apecloud/kubeblocks/pkg/controller/component" "github.com/apecloud/kubeblocks/pkg/controller/graph" "github.com/apecloud/kubeblocks/pkg/controller/model" @@ -101,7 +100,8 @@ func (t *ClusterAPINormalizationTransformer) buildCompSpecs(transCtx *clusterTra return t.buildCompSpecs4Specified(transCtx, cluster) } if withClusterSimplifiedAPI(cluster) { - return t.buildCompSpecs4SimplifiedAPI(transCtx.ClusterDef, cluster), nil + // TODO(v1.0): check component definition + return nil, fmt.Errorf("simplified API is not supported") } return nil, nil } @@ -177,11 +177,6 @@ func (t *ClusterAPINormalizationTransformer) buildCompSpecs4Sharding(transCtx *c return compSpecs, nil } -func (t *ClusterAPINormalizationTransformer) buildCompSpecs4SimplifiedAPI(clusterDef *appsv1alpha1.ClusterDefinition, - cluster *appsv1alpha1.Cluster) []*appsv1alpha1.ClusterComponentSpec { - return []*appsv1alpha1.ClusterComponentSpec{apiconversion.HandleSimplifiedClusterAPI(clusterDef, cluster)} -} - func (t *ClusterAPINormalizationTransformer) buildCompLabelsInheritedFromCluster(transCtx *clusterTransformContext, cluster *appsv1alpha1.Cluster) map[string]map[string]string { clusterLabels := filterReservedLabels(cluster.Labels) @@ -227,23 +222,11 @@ func (t *ClusterAPINormalizationTransformer) resolveCompDefinitions(transCtx *cl func (t *ClusterAPINormalizationTransformer) resolveCompDefinitionNServiceVersion(transCtx *clusterTransformContext, compSpec *appsv1alpha1.ClusterComponentSpec) (*appsv1alpha1.ComponentDefinition, string, error) { if withClusterLegacyDefinition(transCtx.Cluster) || withClusterSimplifiedAPI(transCtx.Cluster) { - compDef, err := t.buildCompDefinition4Legacy(transCtx, compSpec) - // compDef.Name = "" - return compDef, "", err + return nil, "", fmt.Errorf("legacy cluster definition or simplified API are not supported") } return t.resolveCompDefinitionNServiceVersionWithUpgrade(transCtx, compSpec) } -func (t *ClusterAPINormalizationTransformer) buildCompDefinition4Legacy(transCtx *clusterTransformContext, - compSpec *appsv1alpha1.ClusterComponentSpec) (*appsv1alpha1.ComponentDefinition, error) { - compDef, err := component.BuildComponentDefinition(transCtx.ClusterDef, compSpec) - if err != nil { - return nil, err - } - compDef.Name = constant.GenerateVirtualComponentDefinition(compSpec.ComponentDefRef) - return compDef, nil -} - func (t *ClusterAPINormalizationTransformer) resolveCompDefinitionNServiceVersionWithUpgrade(transCtx *clusterTransformContext, compSpec *appsv1alpha1.ClusterComponentSpec) (*appsv1alpha1.ComponentDefinition, string, error) { var ( diff --git a/controllers/apps/transformer_cluster_deletion_test.go b/controllers/apps/transformer_cluster_deletion_test.go index 8c07e29ac3d0..400110e3ea09 100644 --- a/controllers/apps/transformer_cluster_deletion_test.go +++ b/controllers/apps/transformer_cluster_deletion_test.go @@ -68,9 +68,9 @@ var _ = Describe("clusterDeletionTransformer", func() { cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, "test-cluster", clusterDef.Name). SetTopology(clusterDef.Spec.Topologies[0].Name). - AddComponentV2("comp1", "compdef1"). - AddComponentV2("comp2", "compdef2"). - AddComponentV2("comp3", "compdef3"). + AddComponent("comp1", "compdef1"). + AddComponent("comp2", "compdef2"). + AddComponent("comp3", "compdef3"). GetObject() cluster.DeletionTimestamp = &metav1.Time{Time: time.Now()} diff --git a/controllers/apps/transformer_cluster_load_resources.go b/controllers/apps/transformer_cluster_load_resources.go index a3c9ce3a7bfa..a7c093281a45 100644 --- a/controllers/apps/transformer_cluster_load_resources.go +++ b/controllers/apps/transformer_cluster_load_resources.go @@ -25,7 +25,6 @@ import ( "k8s.io/apimachinery/pkg/types" appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" - "github.com/apecloud/kubeblocks/pkg/controller/apiconversion" "github.com/apecloud/kubeblocks/pkg/controller/graph" "github.com/apecloud/kubeblocks/pkg/generics" ) @@ -136,7 +135,14 @@ func withClusterLegacyDefinition(cluster *appsv1alpha1.Cluster) bool { } func withClusterSimplifiedAPI(cluster *appsv1alpha1.Cluster) bool { - return apiconversion.HasSimplifiedClusterAPI(cluster) + return cluster.Spec.Replicas != nil || + !cluster.Spec.Resources.CPU.IsZero() || + !cluster.Spec.Resources.Memory.IsZero() || + !cluster.Spec.Storage.Size.IsZero() || + // cluster.Spec.Monitor.MonitoringInterval != nil || + cluster.Spec.Network != nil || + len(cluster.Spec.Tenancy) > 0 || + len(cluster.Spec.AvailabilityPolicy) > 0 } func clusterCompCnt(cluster *appsv1alpha1.Cluster) int { diff --git a/controllers/apps/transformer_cluster_service.go b/controllers/apps/transformer_cluster_service.go index 54b62dcc84fd..258db31a696a 100644 --- a/controllers/apps/transformer_cluster_service.go +++ b/controllers/apps/transformer_cluster_service.go @@ -127,45 +127,37 @@ func (t *clusterServiceTransformer) convertLegacyClusterCompSpecServices(transCt continue } - clusterCompDef := transCtx.ClusterDef.GetComponentDefByName(compSpec.ComponentDefRef) - if clusterCompDef == nil { - continue - } - - for _, item := range compSpec.Services { - legacyService := &appsv1alpha1.ClusterService{ - Service: appsv1alpha1.Service{ - Name: constant.GenerateClusterServiceName(cluster.Name, item.Name), - ServiceName: constant.GenerateClusterServiceName(cluster.Name, item.Name), - Annotations: item.Annotations, - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{}, - Type: item.ServiceType, - }, - }, - ComponentSelector: compSpec.Name, - } - legacyServiceName := constant.GenerateComponentServiceName(cluster.Name, compSpec.Name, item.Name) - legacyServiceExist, err := checkLegacyServiceExist(transCtx, legacyServiceName, cluster.Namespace) - if err != nil { - return nil, err - } - // the generation converted service name is different with the exist legacy service name, if the legacy service exist, we should use the legacy service name - if legacyServiceExist { - legacyService.Name = legacyServiceName - legacyService.ServiceName = legacyServiceName - } - switch clusterCompDef.WorkloadType { - case appsv1alpha1.Replication: - legacyService.RoleSelector = constant.Primary - case appsv1alpha1.Consensus: - legacyService.RoleSelector = constant.Leader - if clusterCompDef.ConsensusSpec != nil { - legacyService.RoleSelector = clusterCompDef.ConsensusSpec.Leader.Name - } - } - convertedServices = append(convertedServices, *legacyService) - } + // TODO(v1.0): compatible with legacy cluster services + // clusterCompDef := transCtx.ClusterDef.GetComponentDefByName(compSpec.ComponentDefRef) + // if clusterCompDef == nil { + // continue + // } + // + // for _, item := range compSpec.Services { + // legacyService := &appsv1alpha1.ClusterService{ + // Service: appsv1alpha1.Service{ + // Name: constant.GenerateClusterServiceName(cluster.Name, item.Name), + // ServiceName: constant.GenerateClusterServiceName(cluster.Name, item.Name), + // Annotations: item.Annotations, + // Spec: corev1.ServiceSpec{ + // Ports: []corev1.ServicePort{}, + // Type: item.ServiceType, + // }, + // }, + // ComponentSelector: compSpec.Name, + // } + // legacyServiceName := constant.GenerateComponentServiceName(cluster.Name, compSpec.Name, item.Name) + // legacyServiceExist, err := checkLegacyServiceExist(transCtx, legacyServiceName, cluster.Namespace) + // if err != nil { + // return nil, err + // } + // // the generation converted service name is different with the exist legacy service name, if the legacy service exist, we should use the legacy service name + // if legacyServiceExist { + // legacyService.Name = legacyServiceName + // legacyService.ServiceName = legacyServiceName + // } + // convertedServices = append(convertedServices, *legacyService) + // } } return convertedServices, nil } @@ -367,20 +359,20 @@ func resolveServiceDefaultFields(obj, objCopy *corev1.ServiceSpec) { } } -func checkLegacyServiceExist(ctx graph.TransformContext, serviceName, namespace string) (bool, error) { - key := types.NamespacedName{ - Namespace: namespace, - Name: serviceName, - } - obj := &corev1.Service{} - if err := ctx.GetClient().Get(ctx.GetContext(), key, obj); err != nil { - if apierrors.IsNotFound(err) { - return false, nil - } - return false, err - } - return true, nil -} +// func checkLegacyServiceExist(ctx graph.TransformContext, serviceName, namespace string) (bool, error) { +// key := types.NamespacedName{ +// Namespace: namespace, +// Name: serviceName, +// } +// obj := &corev1.Service{} +// if err := ctx.GetClient().Get(ctx.GetContext(), key, obj); err != nil { +// if apierrors.IsNotFound(err) { +// return false, nil +// } +// return false, err +// } +// return true, nil +// } func enableShardService(cluster *appsv1alpha1.Cluster, shardingName string) bool { enableShardSvcList, ok := cluster.Annotations[constant.ShardSvcAnnotationKey] diff --git a/controllers/apps/transformer_component_rbac_test.go b/controllers/apps/transformer_component_rbac_test.go index fe461c83c35b..5df5e4ed0b86 100644 --- a/controllers/apps/transformer_component_rbac_test.go +++ b/controllers/apps/transformer_component_rbac_test.go @@ -65,7 +65,7 @@ var _ = Describe("object rbac transformer test.", func() { By("Creating a cluster") cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). WithRandomName(). - AddComponentV2(compName, compDefName). + AddComponent(compName, compDefName). SetReplicas(1). SetServiceAccountName(serviceAccountName). GetObject() diff --git a/controllers/apps/transformer_component_tls_test.go b/controllers/apps/transformer_component_tls_test.go index c1d3c8c775c3..b968193b44c3 100644 --- a/controllers/apps/transformer_component_tls_test.go +++ b/controllers/apps/transformer_component_tls_test.go @@ -140,7 +140,7 @@ var _ = Describe("TLS self-signed cert function", func() { By("create cluster obj") clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterNamePrefix, ""). WithRandomName(). - AddComponentV2(defaultCompName, compDefObj.Name). + AddComponent(defaultCompName, compDefObj.Name). SetReplicas(3). SetTLS(true). SetIssuer(tlsIssuer). @@ -158,7 +158,7 @@ var _ = Describe("TLS self-signed cert function", func() { By("create cluster with tls disabled") clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterNamePrefix, ""). WithRandomName(). - AddComponentV2(defaultCompName, compDefObj.Name). + AddComponent(defaultCompName, compDefObj.Name). SetReplicas(3). SetTLS(false). Create(&testCtx). diff --git a/controllers/apps/transformer_component_workload.go b/controllers/apps/transformer_component_workload.go index 98890ba9d1c4..95637db4f9e7 100644 --- a/controllers/apps/transformer_component_workload.go +++ b/controllers/apps/transformer_component_workload.go @@ -387,6 +387,10 @@ func checkNRollbackProtoImages(itsObj, itsProto *workloads.InstanceSet) { for i, cc := range [][]corev1.Container{itsObj.Spec.Template.Spec.InitContainers, itsObj.Spec.Template.Spec.Containers} { images[i] = make(map[string]string) for _, c := range cc { + // skip the lorry container + if c.Name == constant.LorryInitContainerName || c.Name == constant.LorryContainerName { + continue + } images[i][c.Name] = c.Image } } diff --git a/controllers/extensions/addon_controller_test.go b/controllers/extensions/addon_controller_test.go index d44b1029c9ca..e63ce76ce4ea 100644 --- a/controllers/extensions/addon_controller_test.go +++ b/controllers/extensions/addon_controller_test.go @@ -839,7 +839,7 @@ var _ = Describe("Addon controller", func() { fakeInstallationCompletedJob(2) By("By creating cluster with addon") - clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, "test-cd"). + clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). AddComponent(addon.Name, addon.Name).SetReplicas(1). WithRandomName(). AddLabels(constant.ClusterDefLabelKey, addon.Name). @@ -879,7 +879,7 @@ var _ = Describe("Addon controller", func() { fakeInstallationCompletedJob(2) By("By creating cluster with addon") - clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, "test-cd"). + clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). AddComponent(addon.Name, addon.Name).SetReplicas(1). WithRandomName(). AddLabels(constant.ClusterDefLabelKey, addon.Name). diff --git a/controllers/k8score/event_controller_test.go b/controllers/k8score/event_controller_test.go index 6020aedaa4d6..6d3f1e3acd2e 100644 --- a/controllers/k8score/event_controller_test.go +++ b/controllers/k8score/event_controller_test.go @@ -118,21 +118,22 @@ var _ = Describe("Event Controller", func() { Context("When receiving role changed event", func() { It("should handle it properly", func() { - By("create cluster & clusterDef") - clusterDefName := "foo" - consensusCompName := "consensus" - consensusCompDefName := "consensus" - clusterDefObj := testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.ConsensusMySQLComponent, consensusCompDefName). - Create(&testCtx).GetObject() - clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, "", clusterDefObj.Name). + By("create cluster & compdef") + compDefName := "test-compdef" + clusterName := "test-cluster" + defaultCompName := "mysql" + compDefObj := testapps.NewComponentDefinitionFactory(compDefName). + SetDefaultSpec(). + Create(&testCtx). + GetObject() + clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). WithRandomName(). - AddComponent(consensusCompName, consensusCompDefName). + AddComponent(defaultCompName, compDefObj.GetName()). Create(&testCtx).GetObject() Eventually(testapps.CheckObjExists(&testCtx, client.ObjectKeyFromObject(clusterObj), &appsv1alpha1.Cluster{}, true)).Should(Succeed()) - itsName := fmt.Sprintf("%s-%s", clusterObj.Name, consensusCompName) - its := testapps.NewInstanceSetFactory(clusterObj.Namespace, itsName, clusterObj.Name, consensusCompName). + itsName := fmt.Sprintf("%s-%s", clusterObj.Name, defaultCompName) + its := testapps.NewInstanceSetFactory(clusterObj.Namespace, itsName, clusterObj.Name, defaultCompName). SetReplicas(int32(3)). AddContainer(corev1.Container{Name: testapps.DefaultMySQLContainerName, Image: testapps.ApeCloudMySQLImage}). Create(&testCtx).GetObject() @@ -155,7 +156,7 @@ var _ = Describe("Event Controller", func() { By("create involved pod") var uid types.UID podName := fmt.Sprintf("%s-%d", itsName, 0) - pod := createInvolvedPod(podName, clusterObj.Name, consensusCompName, itsName) + pod := createInvolvedPod(podName, clusterObj.Name, defaultCompName, itsName) Expect(testCtx.CreateObj(ctx, pod)).Should(Succeed()) Eventually(func() error { p := &corev1.Pod{} diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml index e433b1d10397..a626e4fb3762 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_clusterdefinitions.yaml @@ -71,8437 +71,6 @@ spec: spec: description: ClusterDefinitionSpec defines the desired state of ClusterDefinition. properties: - componentDefs: - description: |- - Provides the definitions for the cluster components. - - - Deprecated since v0.9. - Components should now be individually defined using ComponentDefinition and - collectively referenced via `topology.components`. - This field is maintained for backward compatibility and its use is discouraged. - Existing usage should be updated to the current preferred approach to avoid compatibility issues in future releases. - items: - description: |- - ClusterComponentDefinition defines a Component within a ClusterDefinition but is deprecated and - has been replaced by ComponentDefinition. - - - Deprecated: Use ComponentDefinition instead. This type is deprecated as of version 0.8. - properties: - consensusSpec: - description: Defines spec for `Consensus` workloads. It's required - if the workload type is `Consensus`. - properties: - followers: - description: Members of the consensus set that have voting - rights but are not the leader. - items: - description: ConsensusMember is deprecated since v0.7. - properties: - accessMode: - default: ReadWrite - description: Specifies the services that this member - is capable of providing. - enum: - - None - - Readonly - - ReadWrite - type: string - name: - default: leader - description: Specifies the name of the consensus member. - type: string - replicas: - default: 0 - description: |- - Indicates the number of Pods that perform this role. - The default is 1 for `Leader`, 0 for `Learner`, others for `Followers`. - format: int32 - minimum: 0 - type: integer - required: - - accessMode - - name - type: object - type: array - leader: - description: Represents a single leader in the consensus - set. - properties: - accessMode: - default: ReadWrite - description: Specifies the services that this member - is capable of providing. - enum: - - None - - Readonly - - ReadWrite - type: string - name: - default: leader - description: Specifies the name of the consensus member. - type: string - replicas: - default: 0 - description: |- - Indicates the number of Pods that perform this role. - The default is 1 for `Leader`, 0 for `Learner`, others for `Followers`. - format: int32 - minimum: 0 - type: integer - required: - - accessMode - - name - type: object - learner: - description: Represents a member of the consensus set that - does not have voting rights. - properties: - accessMode: - default: ReadWrite - description: Specifies the services that this member - is capable of providing. - enum: - - None - - Readonly - - ReadWrite - type: string - name: - default: leader - description: Specifies the name of the consensus member. - type: string - replicas: - default: 0 - description: |- - Indicates the number of Pods that perform this role. - The default is 1 for `Leader`, 0 for `Learner`, others for `Followers`. - format: int32 - minimum: 0 - type: integer - required: - - accessMode - - name - type: object - llPodManagementPolicy: - description: |- - Controls the creation of pods during initial scale up, replacement of pods on nodes, and scaling down. - - - - `OrderedReady`: Creates pods in increasing order (pod-0, then pod-1, etc). The controller waits until each pod - is ready before continuing. Pods are removed in reverse order when scaling down. - - `Parallel`: Creates pods in parallel to match the desired scale without waiting. All pods are deleted at once - when scaling down. - type: string - llUpdateStrategy: - description: |- - Specifies the low-level StatefulSetUpdateStrategy to be used when updating Pods in the StatefulSet upon a - revision to the Template. - `UpdateStrategy` will be ignored if this is provided. - properties: - rollingUpdate: - description: RollingUpdate is used to communicate parameters - when Type is RollingUpdateStatefulSetStrategyType. - properties: - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of pods that can be unavailable during the update. - Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - Absolute number is calculated from percentage by rounding up. This can not be 0. - Defaults to 1. This field is alpha-level and is only honored by servers that enable the - MaxUnavailableStatefulSet feature. The field applies to all pods in the range 0 to - Replicas-1. That means if there is any unavailable pod in the range 0 to Replicas-1, it - will be counted towards MaxUnavailable. - x-kubernetes-int-or-string: true - partition: - description: |- - Partition indicates the ordinal at which the StatefulSet should be partitioned - for updates. During a rolling update, all pods from ordinal Replicas-1 to - Partition are updated. All pods from ordinal Partition-1 to 0 remain untouched. - This is helpful in being able to do a canary based deployment. The default value is 0. - format: int32 - type: integer - type: object - type: - description: |- - Type indicates the type of the StatefulSetUpdateStrategy. - Default is RollingUpdate. - type: string - type: object - updateStrategy: - default: Serial - description: |- - Specifies the strategy for updating Pods. - For workloadType=`Consensus`, the update strategy can be one of the following: - - - - `Serial`: Updates Members sequentially to minimize component downtime. - - `BestEffortParallel`: Updates Members in parallel to minimize component write downtime. Majority remains online - at all times. - - `Parallel`: Forces parallel updates. - enum: - - Serial - - BestEffortParallel - - Parallel - type: string - required: - - leader - type: object - horizontalScalePolicy: - description: Defines the behavior of horizontal scale. - properties: - backupPolicyTemplateName: - description: Refers to the backup policy template. - type: string - type: - default: None - description: |- - Determines the data synchronization method when a component scales out. - The policy can be one of the following: {None, CloneVolume}. The default policy is `None`. - - - - `None`: This is the default policy. It creates an empty volume without data cloning. - - `CloneVolume`: This policy clones data to newly scaled pods. It first tries to use a volume snapshot. - If volume snapshot is not enabled, it will attempt to use a backup tool. If neither method works, it will report an error. - - `Snapshot`: This policy is deprecated and is an alias for CloneVolume. - enum: - - None - - CloneVolume - - Snapshot - type: string - volumeMountsName: - description: |- - Specifies the volumeMount of the container to backup. - This only works if Type is not None. If not specified, the first volumeMount will be selected. - type: string - type: object - name: - description: |- - This name could be used as default name of `cluster.spec.componentSpecs.name`, and needs to conform with same - validation rules as `cluster.spec.componentSpecs.name`, currently complying with IANA Service Naming rule. - This name will apply to cluster objects as the value of label "apps.kubeblocks.io/component-name". - maxLength: 22 - pattern: ^[a-z]([a-z0-9\-]*[a-z0-9])?$ - type: string - podSpec: - description: Defines the pod spec template of component. - properties: - activeDeadlineSeconds: - description: |- - Optional duration in seconds the pod may be active on the node relative to - StartTime before the system will actively try to mark it failed and kill associated containers. - Value must be a positive integer. - format: int64 - type: integer - affinity: - description: If specified, the pod's scheduling constraints - properties: - nodeAffinity: - description: Describes node affinity scheduling rules - for the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node matches the corresponding matchExpressions; the - node(s) with the highest sum are the most preferred. - items: - description: |- - An empty preferred scheduling term matches all objects with implicit weight 0 - (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). - properties: - preference: - description: A node selector term, associated - with the corresponding weight. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - x-kubernetes-map-type: atomic - weight: - description: Weight associated with matching - the corresponding nodeSelectorTerm, in the - range 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. - properties: - nodeSelectorTerms: - description: Required. A list of node selector - terms. The terms are ORed. - items: - description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - x-kubernetes-map-type: atomic - type: array - required: - - nodeSelectorTerms - type: object - x-kubernetes-map-type: atomic - type: object - podAffinity: - description: Describes pod affinity scheduling rules - (e.g. co-locate this pod in the same node, zone, etc. - as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched - WeightedPodAffinityTerm fields are added per-node - to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. - properties: - labelSelector: - description: A label query over a set - of resources, in this case pods. - properties: - matchExpressions: - description: matchExpressions is a - list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a - list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling - rules (e.g. avoid putting this pod in the same node, - zone, etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the anti-affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched - WeightedPodAffinityTerm fields are added per-node - to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. - properties: - labelSelector: - description: A label query over a set - of resources, in this case pods. - properties: - matchExpressions: - description: matchExpressions is a - list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a - list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the anti-affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the anti-affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - type: object - type: object - automountServiceAccountToken: - description: AutomountServiceAccountToken indicates whether - a service account token should be automatically mounted. - type: boolean - containers: - description: |- - List of containers belonging to the pod. - Containers cannot currently be added or removed. - There must be at least one container in a Pod. - Cannot be updated. - items: - description: A single application container that you want - to run within a pod. - properties: - args: - description: |- - Arguments to the entrypoint. - The container image's CMD is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - command: - description: |- - Entrypoint array. Not executed within a shell. - The container image's ENTRYPOINT is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - env: - description: |- - List of environment variables to set in the container. - Cannot be updated. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, - defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults - to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - description: |- - List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple - sources, the value associated with the last source will take precedence. - Values defined by an Env with a duplicate key will take precedence. - Cannot be updated. - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - lifecycle: - description: |- - Actions that the management system should take in response to container lifecycle events. - Cannot be updated. - properties: - postStart: - description: |- - PostStart is called immediately after a container is created. If the handler fails, - the container is terminated and restarted according to its restart policy. - Other management of the container blocks until the hook completes. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: |- - PreStop is called immediately before a container is terminated due to an - API request or management event such as liveness/startup probe failure, - preemption, resource contention, etc. The handler is not called if the - container crashes or exits. The Pod's termination grace period countdown begins before the - PreStop hook is executed. Regardless of the outcome of the handler, the - container will eventually terminate within the Pod's termination grace - period (unless delayed by finalizers). Other management of the container blocks until the hook completes - or until the termination grace period is reached. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: |- - Periodic probe of container liveness. - Container will be restarted if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - name: - description: |- - Name of the container specified as a DNS_LABEL. - Each container in a pod must have a unique name (DNS_LABEL). - Cannot be updated. - type: string - ports: - description: |- - List of ports to expose from the container. Not specifying a port here - DOES NOT prevent that port from being exposed. Any port which is - listening on the default "0.0.0.0" address inside a container will be - accessible from the network. - Modifying this array with strategic merge patch may corrupt the data. - For more information See https://github.com/kubernetes/kubernetes/issues/108255. - Cannot be updated. - items: - description: ContainerPort represents a network - port in a single container. - properties: - containerPort: - description: |- - Number of port to expose on the pod's IP address. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external - port to. - type: string - hostPort: - description: |- - Number of port to expose on the host. - If specified, this must be a valid port number, 0 < x < 65536. - If HostNetwork is specified, this must match ContainerPort. - Most containers do not need this. - format: int32 - type: integer - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - protocol: - default: TCP - description: |- - Protocol for port. Must be UDP, TCP, or SCTP. - Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: |- - Periodic probe of container service readiness. - Container will be removed from service endpoints if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - resizePolicy: - description: Resources resize policy for the container. - items: - description: ContainerResizePolicy represents resource - resize policy for the container. - properties: - resourceName: - description: |- - Name of the resource to which this resource resize policy applies. - Supported values: cpu, memory. - type: string - restartPolicy: - description: |- - Restart policy to apply when specified resource is resized. - If not specified, it defaults to NotRequired. - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Compute Resources required by this container. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - restartPolicy: - description: |- - RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, - the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: - this init container will be continually restarted on - exit until all regular containers have terminated. Once all regular - containers have completed, all init containers with restartPolicy "Always" - will be shut down. This lifecycle differs from normal init containers and - is often referred to as a "sidecar" container. Although this init - container still starts in the init container sequence, it does not wait - for the container to complete before proceeding to the next init - container. Instead, the next init container starts immediately after this - init container is started, or after any startupProbe has successfully - completed. - type: string - securityContext: - description: |- - SecurityContext defines the security options the container should be run with. - If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - properties: - allowPrivilegeEscalation: - description: |- - AllowPrivilegeEscalation controls whether a process can gain more - privileges than its parent process. This bool directly controls if - the no_new_privs flag will be set on the container process. - AllowPrivilegeEscalation is true always when the container is: - 1) run as Privileged - 2) has CAP_SYS_ADMIN - Note that this field cannot be set when spec.os.name is windows. - type: boolean - capabilities: - description: |- - The capabilities to add/drop when running containers. - Defaults to the default set of capabilities granted by the container runtime. - Note that this field cannot be set when spec.os.name is windows. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - drop: - description: Removed capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - type: object - privileged: - description: |- - Run container in privileged mode. - Processes in privileged containers are essentially equivalent to root on the host. - Defaults to false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - procMount: - description: |- - procMount denotes the type of proc mount to use for the containers. - The default is DefaultProcMount which uses the container runtime defaults for - readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. - Note that this field cannot be set when spec.os.name is windows. - type: string - readOnlyRootFilesystem: - description: |- - Whether this container has a read-only root filesystem. - Default is false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to the container. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label - that applies to the container. - type: string - role: - description: Role is a SELinux role label - that applies to the container. - type: string - type: - description: Type is a SELinux type label - that applies to the container. - type: string - user: - description: User is a SELinux user label - that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by this container. If seccomp options are - provided at both the pod & container level, the container options - override the pod options. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options from the PodSecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the - name of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: |- - StartupProbe indicates that the Pod has successfully initialized. - If specified, no other probes are executed until this completes successfully. - If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. - This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, - when it might take a long time to load data or warm a cache, than during steady-state operation. - This cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - stdin: - description: |- - Whether this container should allocate a buffer for stdin in the container runtime. If this - is not set, reads from stdin in the container will always result in EOF. - Default is false. - type: boolean - stdinOnce: - description: |- - Whether the container runtime should close the stdin channel after it has been opened by - a single attach. When stdin is true the stdin stream will remain open across multiple attach - sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - first client attaches to stdin, and then remains open and accepts data until the client disconnects, - at which time stdin is closed and remains closed until the container is restarted. If this - flag is false, a container processes that reads from stdin will never receive an EOF. - Default is false - type: boolean - terminationMessagePath: - description: |- - Optional: Path at which the file to which the container's termination message - will be written is mounted into the container's filesystem. - Message written is intended to be brief final status, such as an assertion failure message. - Will be truncated by the node if greater than 4096 bytes. The total message length across - all containers will be limited to 12kb. - Defaults to /dev/termination-log. - Cannot be updated. - type: string - terminationMessagePolicy: - description: |- - Indicate how the termination message should be populated. File will use the contents of - terminationMessagePath to populate the container status message on both success and failure. - FallbackToLogsOnError will use the last chunk of container log output if the termination - message file is empty and the container exited with an error. - The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - Defaults to File. - Cannot be updated. - type: string - tty: - description: |- - Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices - to be used by the container. - items: - description: volumeDevice describes a mapping of - a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside of - the container that the device will be mapped - to. - type: string - name: - description: name must match the name of a persistentVolumeClaim - in the pod - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - description: |- - Pod volumes to mount into the container's filesystem. - Cannot be updated. - items: - description: VolumeMount describes a mounting of - a Volume within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - workingDir: - description: |- - Container's working directory. - If not specified, the container runtime's default will be used, which - might be configured in the container image. - Cannot be updated. - type: string - required: - - name - type: object - type: array - dnsConfig: - description: |- - Specifies the DNS parameters of a pod. - Parameters specified here will be merged to the generated DNS - configuration based on DNSPolicy. - properties: - nameservers: - description: |- - A list of DNS name server IP addresses. - This will be appended to the base nameservers generated from DNSPolicy. - Duplicated nameservers will be removed. - items: - type: string - type: array - options: - description: |- - A list of DNS resolver options. - This will be merged with the base options generated from DNSPolicy. - Duplicated entries will be removed. Resolution options given in Options - will override those that appear in the base DNSPolicy. - items: - description: PodDNSConfigOption defines DNS resolver - options of a pod. - properties: - name: - description: Required. - type: string - value: - type: string - type: object - type: array - searches: - description: |- - A list of DNS search domains for host-name lookup. - This will be appended to the base search paths generated from DNSPolicy. - Duplicated search paths will be removed. - items: - type: string - type: array - type: object - dnsPolicy: - description: |- - Set DNS policy for the pod. - Defaults to "ClusterFirst". - Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. - DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. - To have DNS options set along with hostNetwork, you have to specify DNS policy - explicitly to 'ClusterFirstWithHostNet'. - type: string - enableServiceLinks: - description: |- - EnableServiceLinks indicates whether information about services should be injected into pod's - environment variables, matching the syntax of Docker links. - Optional: Defaults to true. - type: boolean - ephemeralContainers: - description: |- - List of ephemeral containers run in this pod. Ephemeral containers may be run in an existing - pod to perform user-initiated actions such as debugging. This list cannot be specified when - creating a pod, and it cannot be modified by updating the pod spec. In order to add an - ephemeral container to an existing pod, use the pod's ephemeralcontainers subresource. - items: - description: |- - An EphemeralContainer is a temporary container that you may add to an existing Pod for - user-initiated activities such as debugging. Ephemeral containers have no resource or - scheduling guarantees, and they will not be restarted when they exit or when a Pod is - removed or restarted. The kubelet may evict a Pod if an ephemeral container causes the - Pod to exceed its resource allocation. - - - To add an ephemeral container, use the ephemeralcontainers subresource of an existing - Pod. Ephemeral containers may not be removed or restarted. - properties: - args: - description: |- - Arguments to the entrypoint. - The image's CMD is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - command: - description: |- - Entrypoint array. Not executed within a shell. - The image's ENTRYPOINT is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - env: - description: |- - List of environment variables to set in the container. - Cannot be updated. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, - defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults - to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - description: |- - List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple - sources, the value associated with the last source will take precedence. - Values defined by an Env with a duplicate key will take precedence. - Cannot be updated. - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - lifecycle: - description: Lifecycle is not allowed for ephemeral - containers. - properties: - postStart: - description: |- - PostStart is called immediately after a container is created. If the handler fails, - the container is terminated and restarted according to its restart policy. - Other management of the container blocks until the hook completes. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: |- - PreStop is called immediately before a container is terminated due to an - API request or management event such as liveness/startup probe failure, - preemption, resource contention, etc. The handler is not called if the - container crashes or exits. The Pod's termination grace period countdown begins before the - PreStop hook is executed. Regardless of the outcome of the handler, the - container will eventually terminate within the Pod's termination grace - period (unless delayed by finalizers). Other management of the container blocks until the hook completes - or until the termination grace period is reached. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: Probes are not allowed for ephemeral - containers. - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - name: - description: |- - Name of the ephemeral container specified as a DNS_LABEL. - This name must be unique among all containers, init containers and ephemeral containers. - type: string - ports: - description: Ports are not allowed for ephemeral containers. - items: - description: ContainerPort represents a network - port in a single container. - properties: - containerPort: - description: |- - Number of port to expose on the pod's IP address. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external - port to. - type: string - hostPort: - description: |- - Number of port to expose on the host. - If specified, this must be a valid port number, 0 < x < 65536. - If HostNetwork is specified, this must match ContainerPort. - Most containers do not need this. - format: int32 - type: integer - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - protocol: - default: TCP - description: |- - Protocol for port. Must be UDP, TCP, or SCTP. - Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: Probes are not allowed for ephemeral - containers. - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - resizePolicy: - description: Resources resize policy for the container. - items: - description: ContainerResizePolicy represents resource - resize policy for the container. - properties: - resourceName: - description: |- - Name of the resource to which this resource resize policy applies. - Supported values: cpu, memory. - type: string - restartPolicy: - description: |- - Restart policy to apply when specified resource is resized. - If not specified, it defaults to NotRequired. - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Resources are not allowed for ephemeral containers. Ephemeral containers use spare resources - already allocated to the pod. - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - restartPolicy: - description: |- - Restart policy for the container to manage the restart behavior of each - container within a pod. - This may only be set for init containers. You cannot set this field on - ephemeral containers. - type: string - securityContext: - description: |- - Optional: SecurityContext defines the security options the ephemeral container should be run with. - If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - properties: - allowPrivilegeEscalation: - description: |- - AllowPrivilegeEscalation controls whether a process can gain more - privileges than its parent process. This bool directly controls if - the no_new_privs flag will be set on the container process. - AllowPrivilegeEscalation is true always when the container is: - 1) run as Privileged - 2) has CAP_SYS_ADMIN - Note that this field cannot be set when spec.os.name is windows. - type: boolean - capabilities: - description: |- - The capabilities to add/drop when running containers. - Defaults to the default set of capabilities granted by the container runtime. - Note that this field cannot be set when spec.os.name is windows. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - drop: - description: Removed capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - type: object - privileged: - description: |- - Run container in privileged mode. - Processes in privileged containers are essentially equivalent to root on the host. - Defaults to false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - procMount: - description: |- - procMount denotes the type of proc mount to use for the containers. - The default is DefaultProcMount which uses the container runtime defaults for - readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. - Note that this field cannot be set when spec.os.name is windows. - type: string - readOnlyRootFilesystem: - description: |- - Whether this container has a read-only root filesystem. - Default is false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to the container. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label - that applies to the container. - type: string - role: - description: Role is a SELinux role label - that applies to the container. - type: string - type: - description: Type is a SELinux type label - that applies to the container. - type: string - user: - description: User is a SELinux user label - that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by this container. If seccomp options are - provided at both the pod & container level, the container options - override the pod options. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options from the PodSecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the - name of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: Probes are not allowed for ephemeral - containers. - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - stdin: - description: |- - Whether this container should allocate a buffer for stdin in the container runtime. If this - is not set, reads from stdin in the container will always result in EOF. - Default is false. - type: boolean - stdinOnce: - description: |- - Whether the container runtime should close the stdin channel after it has been opened by - a single attach. When stdin is true the stdin stream will remain open across multiple attach - sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - first client attaches to stdin, and then remains open and accepts data until the client disconnects, - at which time stdin is closed and remains closed until the container is restarted. If this - flag is false, a container processes that reads from stdin will never receive an EOF. - Default is false - type: boolean - targetContainerName: - description: |- - If set, the name of the container from PodSpec that this ephemeral container targets. - The ephemeral container will be run in the namespaces (IPC, PID, etc) of this container. - If not set then the ephemeral container uses the namespaces configured in the Pod spec. - - - The container runtime must implement support for this feature. If the runtime does not - support namespace targeting then the result of setting this field is undefined. - type: string - terminationMessagePath: - description: |- - Optional: Path at which the file to which the container's termination message - will be written is mounted into the container's filesystem. - Message written is intended to be brief final status, such as an assertion failure message. - Will be truncated by the node if greater than 4096 bytes. The total message length across - all containers will be limited to 12kb. - Defaults to /dev/termination-log. - Cannot be updated. - type: string - terminationMessagePolicy: - description: |- - Indicate how the termination message should be populated. File will use the contents of - terminationMessagePath to populate the container status message on both success and failure. - FallbackToLogsOnError will use the last chunk of container log output if the termination - message file is empty and the container exited with an error. - The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - Defaults to File. - Cannot be updated. - type: string - tty: - description: |- - Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices - to be used by the container. - items: - description: volumeDevice describes a mapping of - a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside of - the container that the device will be mapped - to. - type: string - name: - description: name must match the name of a persistentVolumeClaim - in the pod - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - description: |- - Pod volumes to mount into the container's filesystem. Subpath mounts are not allowed for ephemeral containers. - Cannot be updated. - items: - description: VolumeMount describes a mounting of - a Volume within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - workingDir: - description: |- - Container's working directory. - If not specified, the container runtime's default will be used, which - might be configured in the container image. - Cannot be updated. - type: string - required: - - name - type: object - type: array - hostAliases: - description: |- - HostAliases is an optional list of hosts and IPs that will be injected into the pod's hosts - file if specified. This is only valid for non-hostNetwork pods. - items: - description: |- - HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the - pod's hosts file. - properties: - hostnames: - description: Hostnames for the above IP address. - items: - type: string - type: array - ip: - description: IP address of the host file entry. - type: string - type: object - type: array - hostIPC: - description: |- - Use the host's ipc namespace. - Optional: Default to false. - type: boolean - hostNetwork: - description: |- - Host networking requested for this pod. Use the host's network namespace. - If this option is set, the ports that will be used must be specified. - Default to false. - type: boolean - hostPID: - description: |- - Use the host's pid namespace. - Optional: Default to false. - type: boolean - hostUsers: - description: |- - Use the host's user namespace. - Optional: Default to true. - If set to true or not present, the pod will be run in the host user namespace, useful - for when the pod needs a feature only available to the host user namespace, such as - loading a kernel module with CAP_SYS_MODULE. - When set to false, a new userns is created for the pod. Setting false is useful for - mitigating container breakout vulnerabilities even allowing users to run their - containers as root without actually having root privileges on the host. - This field is alpha-level and is only honored by servers that enable the UserNamespacesSupport feature. - type: boolean - hostname: - description: |- - Specifies the hostname of the Pod - If not specified, the pod's hostname will be set to a system-defined value. - type: string - imagePullSecrets: - description: |- - ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. - If specified, these secrets will be passed to individual puller implementations for them to use. - More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod - items: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - type: array - initContainers: - description: |- - List of initialization containers belonging to the pod. - Init containers are executed in order prior to containers being started. If any - init container fails, the pod is considered to have failed and is handled according - to its restartPolicy. The name for an init container or normal container must be - unique among all containers. - Init containers may not have Lifecycle actions, Readiness probes, Liveness probes, or Startup probes. - The resourceRequirements of an init container are taken into account during scheduling - by finding the highest request/limit for each resource type, and then using the max of - of that value or the sum of the normal containers. Limits are applied to init containers - in a similar fashion. - Init containers cannot currently be added or removed. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ - items: - description: A single application container that you want - to run within a pod. - properties: - args: - description: |- - Arguments to the entrypoint. - The container image's CMD is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - command: - description: |- - Entrypoint array. Not executed within a shell. - The container image's ENTRYPOINT is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - env: - description: |- - List of environment variables to set in the container. - Cannot be updated. - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, - defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults - to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - description: |- - List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple - sources, the value associated with the last source will take precedence. - Values defined by an Env with a duplicate key will take precedence. - Cannot be updated. - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - lifecycle: - description: |- - Actions that the management system should take in response to container lifecycle events. - Cannot be updated. - properties: - postStart: - description: |- - PostStart is called immediately after a container is created. If the handler fails, - the container is terminated and restarted according to its restart policy. - Other management of the container blocks until the hook completes. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: |- - PreStop is called immediately before a container is terminated due to an - API request or management event such as liveness/startup probe failure, - preemption, resource contention, etc. The handler is not called if the - container crashes or exits. The Pod's termination grace period countdown begins before the - PreStop hook is executed. Regardless of the outcome of the handler, the - container will eventually terminate within the Pod's termination grace - period (unless delayed by finalizers). Other management of the container blocks until the hook completes - or until the termination grace period is reached. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies the action to - take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in - the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a - custom header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP - server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for the backward compatibility. There are no validation of this field and - lifecycle hooks will fail in runtime when tcp handler is specified. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: |- - Periodic probe of container liveness. - Container will be restarted if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - name: - description: |- - Name of the container specified as a DNS_LABEL. - Each container in a pod must have a unique name (DNS_LABEL). - Cannot be updated. - type: string - ports: - description: |- - List of ports to expose from the container. Not specifying a port here - DOES NOT prevent that port from being exposed. Any port which is - listening on the default "0.0.0.0" address inside a container will be - accessible from the network. - Modifying this array with strategic merge patch may corrupt the data. - For more information See https://github.com/kubernetes/kubernetes/issues/108255. - Cannot be updated. - items: - description: ContainerPort represents a network - port in a single container. - properties: - containerPort: - description: |- - Number of port to expose on the pod's IP address. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external - port to. - type: string - hostPort: - description: |- - Number of port to expose on the host. - If specified, this must be a valid port number, 0 < x < 65536. - If HostNetwork is specified, this must match ContainerPort. - Most containers do not need this. - format: int32 - type: integer - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - protocol: - default: TCP - description: |- - Protocol for port. Must be UDP, TCP, or SCTP. - Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: |- - Periodic probe of container service readiness. - Container will be removed from service endpoints if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - resizePolicy: - description: Resources resize policy for the container. - items: - description: ContainerResizePolicy represents resource - resize policy for the container. - properties: - resourceName: - description: |- - Name of the resource to which this resource resize policy applies. - Supported values: cpu, memory. - type: string - restartPolicy: - description: |- - Restart policy to apply when specified resource is resized. - If not specified, it defaults to NotRequired. - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Compute Resources required by this container. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - restartPolicy: - description: |- - RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, - the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: - this init container will be continually restarted on - exit until all regular containers have terminated. Once all regular - containers have completed, all init containers with restartPolicy "Always" - will be shut down. This lifecycle differs from normal init containers and - is often referred to as a "sidecar" container. Although this init - container still starts in the init container sequence, it does not wait - for the container to complete before proceeding to the next init - container. Instead, the next init container starts immediately after this - init container is started, or after any startupProbe has successfully - completed. - type: string - securityContext: - description: |- - SecurityContext defines the security options the container should be run with. - If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - properties: - allowPrivilegeEscalation: - description: |- - AllowPrivilegeEscalation controls whether a process can gain more - privileges than its parent process. This bool directly controls if - the no_new_privs flag will be set on the container process. - AllowPrivilegeEscalation is true always when the container is: - 1) run as Privileged - 2) has CAP_SYS_ADMIN - Note that this field cannot be set when spec.os.name is windows. - type: boolean - capabilities: - description: |- - The capabilities to add/drop when running containers. - Defaults to the default set of capabilities granted by the container runtime. - Note that this field cannot be set when spec.os.name is windows. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - drop: - description: Removed capabilities - items: - description: Capability represent POSIX - capabilities type - type: string - type: array - type: object - privileged: - description: |- - Run container in privileged mode. - Processes in privileged containers are essentially equivalent to root on the host. - Defaults to false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - procMount: - description: |- - procMount denotes the type of proc mount to use for the containers. - The default is DefaultProcMount which uses the container runtime defaults for - readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. - Note that this field cannot be set when spec.os.name is windows. - type: string - readOnlyRootFilesystem: - description: |- - Whether this container has a read-only root filesystem. - Default is false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to the container. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label - that applies to the container. - type: string - role: - description: Role is a SELinux role label - that applies to the container. - type: string - type: - description: Type is a SELinux type label - that applies to the container. - type: string - user: - description: User is a SELinux user label - that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by this container. If seccomp options are - provided at both the pod & container level, the container options - override the pod options. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options from the PodSecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the - name of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: |- - StartupProbe indicates that the Pod has successfully initialized. - If specified, no other probes are executed until this completes successfully. - If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. - This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, - when it might take a long time to load data or warm a cache, than during steady-state operation. - This cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies the action to take. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies an action involving - a GRPC port. - properties: - port: - description: Port number of the gRPC service. - Number must be in the range 1 to 65535. - format: int32 - type: integer - service: - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies an action involving - a TCP port. - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - stdin: - description: |- - Whether this container should allocate a buffer for stdin in the container runtime. If this - is not set, reads from stdin in the container will always result in EOF. - Default is false. - type: boolean - stdinOnce: - description: |- - Whether the container runtime should close the stdin channel after it has been opened by - a single attach. When stdin is true the stdin stream will remain open across multiple attach - sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - first client attaches to stdin, and then remains open and accepts data until the client disconnects, - at which time stdin is closed and remains closed until the container is restarted. If this - flag is false, a container processes that reads from stdin will never receive an EOF. - Default is false - type: boolean - terminationMessagePath: - description: |- - Optional: Path at which the file to which the container's termination message - will be written is mounted into the container's filesystem. - Message written is intended to be brief final status, such as an assertion failure message. - Will be truncated by the node if greater than 4096 bytes. The total message length across - all containers will be limited to 12kb. - Defaults to /dev/termination-log. - Cannot be updated. - type: string - terminationMessagePolicy: - description: |- - Indicate how the termination message should be populated. File will use the contents of - terminationMessagePath to populate the container status message on both success and failure. - FallbackToLogsOnError will use the last chunk of container log output if the termination - message file is empty and the container exited with an error. - The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - Defaults to File. - Cannot be updated. - type: string - tty: - description: |- - Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices - to be used by the container. - items: - description: volumeDevice describes a mapping of - a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside of - the container that the device will be mapped - to. - type: string - name: - description: name must match the name of a persistentVolumeClaim - in the pod - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - description: |- - Pod volumes to mount into the container's filesystem. - Cannot be updated. - items: - description: VolumeMount describes a mounting of - a Volume within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - workingDir: - description: |- - Container's working directory. - If not specified, the container runtime's default will be used, which - might be configured in the container image. - Cannot be updated. - type: string - required: - - name - type: object - type: array - nodeName: - description: |- - NodeName is a request to schedule this pod onto a specific node. If it is non-empty, - the scheduler simply schedules this pod onto that node, assuming that it fits resource - requirements. - type: string - nodeSelector: - additionalProperties: - type: string - description: |- - NodeSelector is a selector which must be true for the pod to fit on a node. - Selector which must match a node's labels for the pod to be scheduled on that node. - More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - type: object - x-kubernetes-map-type: atomic - os: - description: |- - Specifies the OS of the containers in the pod. - Some pod and container fields are restricted if this is set. - - - If the OS field is set to linux, the following fields must be unset: - -securityContext.windowsOptions - - - If the OS field is set to windows, following fields must be unset: - - spec.hostPID - - spec.hostIPC - - spec.hostUsers - - spec.securityContext.seLinuxOptions - - spec.securityContext.seccompProfile - - spec.securityContext.fsGroup - - spec.securityContext.fsGroupChangePolicy - - spec.securityContext.sysctls - - spec.shareProcessNamespace - - spec.securityContext.runAsUser - - spec.securityContext.runAsGroup - - spec.securityContext.supplementalGroups - - spec.containers[*].securityContext.seLinuxOptions - - spec.containers[*].securityContext.seccompProfile - - spec.containers[*].securityContext.capabilities - - spec.containers[*].securityContext.readOnlyRootFilesystem - - spec.containers[*].securityContext.privileged - - spec.containers[*].securityContext.allowPrivilegeEscalation - - spec.containers[*].securityContext.procMount - - spec.containers[*].securityContext.runAsUser - - spec.containers[*].securityContext.runAsGroup - properties: - name: - description: |- - Name is the name of the operating system. The currently supported values are linux and windows. - Additional value may be defined in future and can be one of: - https://github.com/opencontainers/runtime-spec/blob/master/config.md#platform-specific-configuration - Clients should expect to handle additional values and treat unrecognized values in this field as os: null - type: string - required: - - name - type: object - overhead: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Overhead represents the resource overhead associated with running a pod for a given RuntimeClass. - This field will be autopopulated at admission time by the RuntimeClass admission controller. If - the RuntimeClass admission controller is enabled, overhead must not be set in Pod create requests. - The RuntimeClass admission controller will reject Pod create requests which have the overhead already - set. If RuntimeClass is configured and selected in the PodSpec, Overhead will be set to the value - defined in the corresponding RuntimeClass, otherwise it will remain unset and treated as zero. - More info: https://git.k8s.io/enhancements/keps/sig-node/688-pod-overhead/README.md - type: object - preemptionPolicy: - description: |- - PreemptionPolicy is the Policy for preempting pods with lower priority. - One of Never, PreemptLowerPriority. - Defaults to PreemptLowerPriority if unset. - type: string - priority: - description: |- - The priority value. Various system components use this field to find the - priority of the pod. When Priority Admission Controller is enabled, it - prevents users from setting this field. The admission controller populates - this field from PriorityClassName. - The higher the value, the higher the priority. - format: int32 - type: integer - priorityClassName: - description: |- - If specified, indicates the pod's priority. "system-node-critical" and - "system-cluster-critical" are two special keywords which indicate the - highest priorities with the former being the highest priority. Any other - name must be defined by creating a PriorityClass object with that name. - If not specified, the pod priority will be default or zero if there is no - default. - type: string - readinessGates: - description: |- - If specified, all readiness gates will be evaluated for pod readiness. - A pod is ready when all its containers are ready AND - all conditions specified in the readiness gates have status equal to "True" - More info: https://git.k8s.io/enhancements/keps/sig-network/580-pod-readiness-gates - items: - description: PodReadinessGate contains the reference to - a pod condition - properties: - conditionType: - description: ConditionType refers to a condition in - the pod's condition list with matching type. - type: string - required: - - conditionType - type: object - type: array - resourceClaims: - description: |- - ResourceClaims defines which ResourceClaims must be allocated - and reserved before the Pod is allowed to start. The resources - will be made available to those containers which consume them - by name. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. - items: - description: |- - PodResourceClaim references exactly one ResourceClaim through a ClaimSource. - It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. - Containers that need access to the ResourceClaim reference it with this name. - properties: - name: - description: |- - Name uniquely identifies this resource claim inside the pod. - This must be a DNS_LABEL. - type: string - source: - description: Source describes where to find the ResourceClaim. - properties: - resourceClaimName: - description: |- - ResourceClaimName is the name of a ResourceClaim object in the same - namespace as this pod. - type: string - resourceClaimTemplateName: - description: |- - ResourceClaimTemplateName is the name of a ResourceClaimTemplate - object in the same namespace as this pod. - - - The template will be used to create a new ResourceClaim, which will - be bound to this pod. When this pod is deleted, the ResourceClaim - will also be deleted. The pod name and resource name, along with a - generated component, will be used to form a unique name for the - ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses. - - - This field is immutable and no changes will be made to the - corresponding ResourceClaim by the control plane after creating the - ResourceClaim. - type: string - type: object - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - restartPolicy: - description: |- - Restart policy for all containers within the pod. - One of Always, OnFailure, Never. In some contexts, only a subset of those values may be permitted. - Default to Always. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy - type: string - runtimeClassName: - description: |- - RuntimeClassName refers to a RuntimeClass object in the node.k8s.io group, which should be used - to run this pod. If no RuntimeClass resource matches the named class, the pod will not be run. - If unset or empty, the "legacy" RuntimeClass will be used, which is an implicit class with an - empty definition that uses the default runtime handler. - More info: https://git.k8s.io/enhancements/keps/sig-node/585-runtime-class - type: string - schedulerName: - description: |- - If specified, the pod will be dispatched by specified scheduler. - If not specified, the pod will be dispatched by default scheduler. - type: string - schedulingGates: - description: |- - SchedulingGates is an opaque list of values that if specified will block scheduling the pod. - If schedulingGates is not empty, the pod will stay in the SchedulingGated state and the - scheduler will not attempt to schedule the pod. - - - SchedulingGates can only be set at pod creation time, and be removed only afterwards. - - - This is a beta feature enabled by the PodSchedulingReadiness feature gate. - items: - description: PodSchedulingGate is associated to a Pod - to guard its scheduling. - properties: - name: - description: |- - Name of the scheduling gate. - Each scheduling gate must have a unique name field. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - securityContext: - description: |- - SecurityContext holds pod-level security attributes and common container settings. - Optional: Defaults to empty. See type description for default values of each field. - properties: - fsGroup: - description: |- - A special supplemental group that applies to all containers in a pod. - Some volume types allow the Kubelet to change the ownership of that volume - to be owned by the pod: - - - 1. The owning GID will be the FSGroup - 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) - 3. The permission bits are OR'd with rw-rw---- - - - If unset, the Kubelet will not modify the ownership and permissions of any volume. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - fsGroupChangePolicy: - description: |- - fsGroupChangePolicy defines behavior of changing ownership and permission of the volume - before being exposed inside Pod. This field will only apply to - volume types which support fsGroup based ownership(and permissions). - It will have no effect on ephemeral volume types such as: secret, configmaps - and emptydir. - Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. - Note that this field cannot be set when spec.os.name is windows. - type: string - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to all containers. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in SecurityContext. If set in - both SecurityContext and PodSecurityContext, the value specified in SecurityContext - takes precedence for that container. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label that applies - to the container. - type: string - role: - description: Role is a SELinux role label that applies - to the container. - type: string - type: - description: Type is a SELinux type label that applies - to the container. - type: string - user: - description: User is a SELinux user label that applies - to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by the containers in this pod. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - supplementalGroups: - description: |- - A list of groups applied to the first process run in each container, in addition - to the container's primary GID, the fsGroup (if specified), and group memberships - defined in the container image for the uid of the container process. If unspecified, - no additional groups are added to any container. Note that group memberships - defined in the container image for the uid of the container process are still effective, - even if they are not included in this list. - Note that this field cannot be set when spec.os.name is windows. - items: - format: int64 - type: integer - type: array - sysctls: - description: |- - Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported - sysctls (by the container runtime) might fail to launch. - Note that this field cannot be set when spec.os.name is windows. - items: - description: Sysctl defines a kernel parameter to - be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options within a container's SecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name - of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - serviceAccount: - description: |- - DeprecatedServiceAccount is a depreciated alias for ServiceAccountName. - Deprecated: Use serviceAccountName instead. - type: string - serviceAccountName: - description: |- - ServiceAccountName is the name of the ServiceAccount to use to run this pod. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ - type: string - setHostnameAsFQDN: - description: |- - If true the pod's hostname will be configured as the pod's FQDN, rather than the leaf name (the default). - In Linux containers, this means setting the FQDN in the hostname field of the kernel (the nodename field of struct utsname). - In Windows containers, this means setting the registry value of hostname for the registry key HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters to FQDN. - If a pod does not have FQDN, this has no effect. - Default to false. - type: boolean - shareProcessNamespace: - description: |- - Share a single process namespace between all of the containers in a pod. - When this is set containers will be able to view and signal processes from other containers - in the same pod, and the first process in each container will not be assigned PID 1. - HostPID and ShareProcessNamespace cannot both be set. - Optional: Default to false. - type: boolean - subdomain: - description: |- - If specified, the fully qualified Pod hostname will be "...svc.". - If not specified, the pod will not have a domainname at all. - type: string - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - If this value is nil, the default grace period will be used instead. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - Defaults to 30 seconds. - format: int64 - type: integer - tolerations: - description: If specified, the pod's tolerations. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - topologySpreadConstraints: - description: |- - TopologySpreadConstraints describes how a group of pods ought to spread across topology - domains. Scheduler will schedule pods in a way which abides by the constraints. - All topologySpreadConstraints are ANDed. - items: - description: TopologySpreadConstraint specifies how to - spread matching pods among the given topology. - properties: - labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - MatchLabelKeys cannot be set when LabelSelector isn't set. - Keys that don't exist in the incoming pod labels will - be ignored. A null or empty list means only match against labelSelector. - - - This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. - The global minimum is the minimum number of matching pods in an eligible domain - or zero if the number of eligible domains is less than MinDomains. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 2/2/1: - In this case, the global minimum is 1. - | zone1 | zone2 | zone3 | - | P P | P P | P | - - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 2/2/2; - scheduling it onto zone1(zone2) would make the ActualSkew(3-1) on zone1(zone2) - violate MaxSkew(1). - - if MaxSkew is 2, incoming pod can be scheduled onto any zone. - When `whenUnsatisfiable=ScheduleAnyway`, it is used to give higher precedence - to topologies that satisfy it. - It's a required field. Default value is 1 and 0 is not allowed. - format: int32 - type: integer - minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. - And when the number of eligible domains with matching topology keys equals or greater than minDomains, - this value has no effect on scheduling. - As a result, when the number of eligible domains is less than minDomains, - scheduler won't schedule more than maxSkew Pods to those domains. - If value is nil, the constraint behaves as if MinDomains is equal to 1. - Valid values are integers greater than 0. - When value is not nil, WhenUnsatisfiable must be DoNotSchedule. - - - For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same - labelSelector spread as 2/2/2: - | zone1 | zone2 | zone3 | - | P P | P P | P P | - The number of domains is less than 5(MinDomains), so "global minimum" is treated as 0. - In this situation, new pod with the same labelSelector cannot be scheduled, - because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, - it will violate MaxSkew. - - - This is a beta field and requires the MinDomainsInPodTopologySpread feature gate to be enabled (enabled by default). - format: int32 - type: integer - nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. - - - If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. - type: string - nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. - - - If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. - type: string - topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. - Also, we define an eligible domain as a domain whose nodes meet the requirements of - nodeAffinityPolicy and nodeTaintsPolicy. - e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. - And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. - It's a required field. - type: string - whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. - A constraint is considered "Unsatisfiable" for an incoming pod - if and only if every possible node assignment for that pod would violate - "MaxSkew" on some topology. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 3/1/1: - | zone1 | zone2 | zone3 | - | P P P | P | P | - If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled - to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies - MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler - won't make it *more* imbalanced. - It's a required field. - type: string - required: - - maxSkew - - topologyKey - - whenUnsatisfiable - type: object - type: array - x-kubernetes-list-map-keys: - - topologyKey - - whenUnsatisfiable - x-kubernetes-list-type: map - volumes: - description: |- - List of volumes that can be mounted by containers belonging to the pod. - More info: https://kubernetes.io/docs/concepts/storage/volumes - items: - description: Volume represents a named volume in a pod - that may be accessed by any container in the pod. - properties: - awsElasticBlockStore: - description: |- - awsElasticBlockStore represents an AWS Disk resource that is attached to a - kubelet's host machine and then exposed to the pod. - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - properties: - fsType: - description: |- - fsType is the filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - TODO: how do we prevent errors in the filesystem from compromising the machine - type: string - partition: - description: |- - partition is the partition in the volume that you want to mount. - If omitted, the default is to mount by volume name. - Examples: For volume /dev/sda1, you specify the partition as "1". - Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty). - format: int32 - type: integer - readOnly: - description: |- - readOnly value true will force the readOnly setting in VolumeMounts. - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - type: boolean - volumeID: - description: |- - volumeID is unique ID of the persistent disk resource in AWS (Amazon EBS volume). - More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - type: string - required: - - volumeID - type: object - azureDisk: - description: azureDisk represents an Azure Data Disk - mount on the host and bind mount to the pod. - properties: - cachingMode: - description: 'cachingMode is the Host Caching - mode: None, Read Only, Read Write.' - type: string - diskName: - description: diskName is the Name of the data - disk in the blob storage - type: string - diskURI: - description: diskURI is the URI of data disk in - the blob storage - type: string - fsType: - description: |- - fsType is Filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - kind: - description: 'kind expected values are Shared: - multiple blob disks per storage account Dedicated: - single blob disk per storage account Managed: - azure managed data disk (only in managed availability - set). defaults to shared' - type: string - readOnly: - description: |- - readOnly Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - required: - - diskName - - diskURI - type: object - azureFile: - description: azureFile represents an Azure File Service - mount on the host and bind mount to the pod. - properties: - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretName: - description: secretName is the name of secret - that contains Azure Storage Account Name and - Key - type: string - shareName: - description: shareName is the azure share Name - type: string - required: - - secretName - - shareName - type: object - cephfs: - description: cephFS represents a Ceph FS mount on - the host that shares a pod's lifetime - properties: - monitors: - description: |- - monitors is Required: Monitors is a collection of Ceph monitors - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - items: - type: string - type: array - path: - description: 'path is Optional: Used as the mounted - root, rather than the full Ceph tree, default - is /' - type: string - readOnly: - description: |- - readOnly is Optional: Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - type: boolean - secretFile: - description: |- - secretFile is Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - type: string - secretRef: - description: |- - secretRef is Optional: SecretRef is reference to the authentication secret for User, default is empty. - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - user: - description: |- - user is optional: User is the rados user name, default is admin - More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it - type: string - required: - - monitors - type: object - cinder: - description: |- - cinder represents a cinder volume attached and mounted on kubelets host machine. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - type: boolean - secretRef: - description: |- - secretRef is optional: points to a secret object containing parameters used to connect - to OpenStack. - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - volumeID: - description: |- - volumeID used to identify the volume in cinder. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - type: string - required: - - volumeID - type: object - configMap: - description: configMap represents a configMap that - should populate this volume - properties: - defaultMode: - description: |- - defaultMode is optional: mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - Defaults to 0644. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the ConfigMap, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: optional specify whether the ConfigMap - or its keys must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - csi: - description: csi (Container Storage Interface) represents - ephemeral storage that is handled by certain external - CSI drivers (Beta feature). - properties: - driver: - description: |- - driver is the name of the CSI driver that handles this volume. - Consult with your admin for the correct name as registered in the cluster. - type: string - fsType: - description: |- - fsType to mount. Ex. "ext4", "xfs", "ntfs". - If not provided, the empty value is passed to the associated CSI driver - which will determine the default filesystem to apply. - type: string - nodePublishSecretRef: - description: |- - nodePublishSecretRef is a reference to the secret object containing - sensitive information to pass to the CSI driver to complete the CSI - NodePublishVolume and NodeUnpublishVolume calls. - This field is optional, and may be empty if no secret is required. If the - secret object contains more than one secret, all secret references are passed. - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - readOnly: - description: |- - readOnly specifies a read-only configuration for the volume. - Defaults to false (read/write). - type: boolean - volumeAttributes: - additionalProperties: - type: string - description: |- - volumeAttributes stores driver-specific properties that are passed to the CSI - driver. Consult your driver's documentation for supported values. - type: object - required: - - driver - type: object - downwardAPI: - description: downwardAPI represents downward API about - the pod that should populate this volume - properties: - defaultMode: - description: |- - Optional: mode bits to use on created files by default. Must be a - Optional: mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - Defaults to 0644. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - items: - description: Items is a list of downward API volume - file - items: - description: DownwardAPIVolumeFile represents - information to create the file containing - the pod field - properties: - fieldRef: - description: 'Required: Selects a field - of the pod: only annotations, labels, - name and namespace are supported.' - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, - defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - mode: - description: |- - Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: 'Required: Path is the relative - path name of the file to be created. Must - not be absolute or contain the ''..'' - path. Must be utf-8 encoded. The first - item of the relative path must not start - with ''..''' - type: string - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults - to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - required: - - path - type: object - type: array - type: object - emptyDir: - description: |- - emptyDir represents a temporary directory that shares a pod's lifetime. - More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir - properties: - medium: - description: |- - medium represents what type of storage medium should back this directory. - The default is "" which means to use the node's default medium. - Must be an empty string (default) or Memory. - More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir - type: string - sizeLimit: - anyOf: - - type: integer - - type: string - description: |- - sizeLimit is the total amount of local storage required for this EmptyDir volume. - The size limit is also applicable for memory medium. - The maximum usage on memory medium EmptyDir would be the minimum value between - the SizeLimit specified here and the sum of memory limits of all containers in a pod. - The default is nil which means that the limit is undefined. - More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - ephemeral: - description: |- - ephemeral represents a volume that is handled by a cluster storage driver. - The volume's lifecycle is tied to the pod that defines it - it will be created before the pod starts, - and deleted when the pod is removed. - - - Use this if: - a) the volume is only needed while the pod runs, - b) features of normal volumes like restoring from snapshot or capacity - tracking are needed, - c) the storage driver is specified through a storage class, and - d) the storage driver supports dynamic volume provisioning through - a PersistentVolumeClaim (see EphemeralVolumeSource for more - information on the connection between this volume type - and PersistentVolumeClaim). - - - Use PersistentVolumeClaim or one of the vendor-specific - APIs for volumes that persist for longer than the lifecycle - of an individual pod. - - - Use CSI for light-weight local ephemeral volumes if the CSI driver is meant to - be used that way - see the documentation of the driver for - more information. - - - A pod can use both types of ephemeral volumes and - persistent volumes at the same time. - properties: - volumeClaimTemplate: - description: |- - Will be used to create a stand-alone PVC to provision the volume. - The pod in which this EphemeralVolumeSource is embedded will be the - owner of the PVC, i.e. the PVC will be deleted together with the - pod. The name of the PVC will be `-` where - `` is the name from the `PodSpec.Volumes` array - entry. Pod validation will reject the pod if the concatenated name - is not valid for a PVC (for example, too long). - - - An existing PVC with that name that is not owned by the pod - will *not* be used for the pod to avoid using an unrelated - volume by mistake. Starting the pod is then blocked until - the unrelated PVC is removed. If such a pre-created PVC is - meant to be used by the pod, the PVC has to updated with an - owner reference to the pod once the pod exists. Normally - this should not be necessary, but it may be useful when - manually reconstructing a broken cluster. - - - This field is read-only and no changes will be made by Kubernetes - to the PVC after it has been created. - - - Required, must not be nil. - properties: - metadata: - description: |- - May contain labels and annotations that will be copied into the PVC - when creating it. No other fields are allowed and will be rejected during - validation. - properties: - annotations: - additionalProperties: - type: string - type: object - finalizers: - items: - type: string - type: array - labels: - additionalProperties: - type: string - type: object - name: - type: string - namespace: - type: string - type: object - spec: - description: |- - The specification for the PersistentVolumeClaim. The entire content is - copied unchanged into the PVC that gets created from this - template. The same fields as in a PersistentVolumeClaim - are also valid here. - properties: - accessModes: - description: |- - accessModes contains the desired access modes the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 - items: - type: string - type: array - dataSource: - description: |- - dataSource field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) - * An existing PVC (PersistentVolumeClaim) - If the provisioner or an external controller can support the specified data source, - it will create a new volume based on the contents of the specified data source. - When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, - and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. - If the namespace is specified, then dataSourceRef will not be copied to dataSource. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource - being referenced - type: string - name: - description: Name is the name of resource - being referenced - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - description: |- - dataSourceRef specifies the object from which to populate the volume with data, if a non-empty - volume is desired. This may be any object from a non-empty API group (non - core object) or a PersistentVolumeClaim object. - When this field is specified, volume binding will only succeed if the type of - the specified object matches some installed volume populator or dynamic - provisioner. - This field will replace the functionality of the dataSource field and as such - if both fields are non-empty, they must have the same value. For backwards - compatibility, when namespace isn't specified in dataSourceRef, - both fields (dataSource and dataSourceRef) will be set to the same - value automatically if one of them is empty and the other is non-empty. - When namespace is specified in dataSourceRef, - dataSource isn't set to the same value and must be empty. - There are three important differences between dataSource and dataSourceRef: - * While dataSource only allows two specific types of objects, dataSourceRef - allows any non-core object, as well as PersistentVolumeClaim objects. - * While dataSource ignores disallowed values (dropping them), dataSourceRef - preserves all values, and generates an error if a disallowed value is - specified. - * While dataSource only allows local objects, dataSourceRef allows objects - in any namespaces. - (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. - (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource - being referenced - type: string - name: - description: Name is the name of resource - being referenced - type: string - namespace: - description: |- - Namespace is the namespace of resource being referenced - Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. - (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. - type: string - required: - - kind - - name - type: object - resources: - description: |- - resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements - that are lower than previous value but must still be higher than capacity recorded in the - status field of the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - selector: - description: selector is a label query - over volumes to consider for binding. - properties: - matchExpressions: - description: matchExpressions is a - list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - description: |- - storageClassName is the name of the StorageClass required by the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 - type: string - volumeMode: - description: |- - volumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. - type: string - volumeName: - description: volumeName is the binding - reference to the PersistentVolume backing - this claim. - type: string - type: object - required: - - spec - type: object - type: object - fc: - description: fc represents a Fibre Channel resource - that is attached to a kubelet's host machine and - then exposed to the pod. - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - TODO: how do we prevent errors in the filesystem from compromising the machine - type: string - lun: - description: 'lun is Optional: FC target lun number' - format: int32 - type: integer - readOnly: - description: |- - readOnly is Optional: Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - targetWWNs: - description: 'targetWWNs is Optional: FC target - worldwide names (WWNs)' - items: - type: string - type: array - wwids: - description: |- - wwids Optional: FC volume world wide identifiers (wwids) - Either wwids or combination of targetWWNs and lun must be set, but not both simultaneously. - items: - type: string - type: array - type: object - flexVolume: - description: |- - flexVolume represents a generic volume resource that is - provisioned/attached using an exec based plugin. - properties: - driver: - description: driver is the name of the driver - to use for this volume. - type: string - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". The default filesystem depends on FlexVolume script. - type: string - options: - additionalProperties: - type: string - description: 'options is Optional: this field - holds extra command options if any.' - type: object - readOnly: - description: |- - readOnly is Optional: defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef is Optional: secretRef is reference to the secret object containing - sensitive information to pass to the plugin scripts. This may be - empty if no secret object is specified. If the secret object - contains more than one secret, all secrets are passed to the plugin - scripts. - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - required: - - driver - type: object - flocker: - description: flocker represents a Flocker volume attached - to a kubelet's host machine. This depends on the - Flocker control service being running - properties: - datasetName: - description: |- - datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker - should be considered as deprecated - type: string - datasetUUID: - description: datasetUUID is the UUID of the dataset. - This is unique identifier of a Flocker dataset - type: string - type: object - gcePersistentDisk: - description: |- - gcePersistentDisk represents a GCE Disk resource that is attached to a - kubelet's host machine and then exposed to the pod. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - properties: - fsType: - description: |- - fsType is filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - TODO: how do we prevent errors in the filesystem from compromising the machine - type: string - partition: - description: |- - partition is the partition in the volume that you want to mount. - If omitted, the default is to mount by volume name. - Examples: For volume /dev/sda1, you specify the partition as "1". - Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty). - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - format: int32 - type: integer - pdName: - description: |- - pdName is unique name of the PD resource in GCE. Used to identify the disk in GCE. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - type: string - readOnly: - description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. - More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - type: boolean - required: - - pdName - type: object - gitRepo: - description: |- - gitRepo represents a git repository at a particular revision. - DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an - EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir - into the Pod's container. - properties: - directory: - description: |- - directory is the target directory name. - Must not contain or start with '..'. If '.' is supplied, the volume directory will be the - git repository. Otherwise, if specified, the volume will contain the git repository in - the subdirectory with the given name. - type: string - repository: - description: repository is the URL - type: string - revision: - description: revision is the commit hash for the - specified revision. - type: string - required: - - repository - type: object - glusterfs: - description: |- - glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. - More info: https://examples.k8s.io/volumes/glusterfs/README.md - properties: - endpoints: - description: |- - endpoints is the endpoint name that details Glusterfs topology. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod - type: string - path: - description: |- - path is the Glusterfs volume path. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod - type: string - readOnly: - description: |- - readOnly here will force the Glusterfs volume to be mounted with read-only permissions. - Defaults to false. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod - type: boolean - required: - - endpoints - - path - type: object - hostPath: - description: |- - hostPath represents a pre-existing file or directory on the host - machine that is directly exposed to the container. This is generally - used for system agents or other privileged things that are allowed - to see the host machine. Most containers will NOT need this. - More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - --- - TODO(jonesdl) We need to restrict who can use host directory mounts and who can/can not - mount host directories as read/write. - properties: - path: - description: |- - path of the directory on the host. - If the path is a symlink, it will follow the link to the real path. - More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - type: string - type: - description: |- - type for HostPath Volume - Defaults to "" - More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - type: string - required: - - path - type: object - iscsi: - description: |- - iscsi represents an ISCSI Disk resource that is attached to a - kubelet's host machine and then exposed to the pod. - More info: https://examples.k8s.io/volumes/iscsi/README.md - properties: - chapAuthDiscovery: - description: chapAuthDiscovery defines whether - support iSCSI Discovery CHAP authentication - type: boolean - chapAuthSession: - description: chapAuthSession defines whether support - iSCSI Session CHAP authentication - type: boolean - fsType: - description: |- - fsType is the filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi - TODO: how do we prevent errors in the filesystem from compromising the machine - type: string - initiatorName: - description: |- - initiatorName is the custom iSCSI Initiator Name. - If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface - : will be created for the connection. - type: string - iqn: - description: iqn is the target iSCSI Qualified - Name. - type: string - iscsiInterface: - description: |- - iscsiInterface is the interface Name that uses an iSCSI transport. - Defaults to 'default' (tcp). - type: string - lun: - description: lun represents iSCSI Target Lun number. - format: int32 - type: integer - portals: - description: |- - portals is the iSCSI Target Portal List. The portal is either an IP or ip_addr:port if the port - is other than default (typically TCP ports 860 and 3260). - items: - type: string - type: array - readOnly: - description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. - type: boolean - secretRef: - description: secretRef is the CHAP Secret for - iSCSI target and initiator authentication - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - targetPortal: - description: |- - targetPortal is iSCSI Target Portal. The Portal is either an IP or ip_addr:port if the port - is other than default (typically TCP ports 860 and 3260). - type: string - required: - - iqn - - lun - - targetPortal - type: object - name: - description: |- - name of the volume. - Must be a DNS_LABEL and unique within the pod. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - nfs: - description: |- - nfs represents an NFS mount on the host that shares a pod's lifetime - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - properties: - path: - description: |- - path that is exported by the NFS server. - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - type: string - readOnly: - description: |- - readOnly here will force the NFS export to be mounted with read-only permissions. - Defaults to false. - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - type: boolean - server: - description: |- - server is the hostname or IP address of the NFS server. - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - type: string - required: - - path - - server - type: object - persistentVolumeClaim: - description: |- - persistentVolumeClaimVolumeSource represents a reference to a - PersistentVolumeClaim in the same namespace. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - properties: - claimName: - description: |- - claimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - type: string - readOnly: - description: |- - readOnly Will force the ReadOnly setting in VolumeMounts. - Default false. - type: boolean - required: - - claimName - type: object - photonPersistentDisk: - description: photonPersistentDisk represents a PhotonController - persistent disk attached and mounted on kubelets - host machine - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - pdID: - description: pdID is the ID that identifies Photon - Controller persistent disk - type: string - required: - - pdID - type: object - portworxVolume: - description: portworxVolume represents a portworx - volume attached and mounted on kubelets host machine - properties: - fsType: - description: |- - fSType represents the filesystem type to mount - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified. - type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - volumeID: - description: volumeID uniquely identifies a Portworx - volume - type: string - required: - - volumeID - type: object - projected: - description: projected items for all in one resources - secrets, configmaps, and downward API - properties: - defaultMode: - description: |- - defaultMode are the mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - sources: - description: sources is the list of volume projections - items: - description: Projection that may be projected - along with other supported volume types - properties: - configMap: - description: configMap information about - the configMap data to project - properties: - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the ConfigMap, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to - a path within a volume. - properties: - key: - description: key is the key to - project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: optional specify whether - the ConfigMap or its keys must be - defined - type: boolean - type: object - x-kubernetes-map-type: atomic - downwardAPI: - description: downwardAPI information about - the downwardAPI data to project - properties: - items: - description: Items is a list of DownwardAPIVolume - file - items: - description: DownwardAPIVolumeFile - represents information to create - the file containing the pod field - properties: - fieldRef: - description: 'Required: Selects - a field of the pod: only annotations, - labels, name and namespace are - supported.' - properties: - apiVersion: - description: Version of the - schema the FieldPath is - written in terms of, defaults - to "v1". - type: string - fieldPath: - description: Path of the field - to select in the specified - API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - mode: - description: |- - Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: 'Required: Path is the - relative path name of the file - to be created. Must not be absolute - or contain the ''..'' path. - Must be utf-8 encoded. The first - item of the relative path must - not start with ''..''' - type: string - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported. - properties: - containerName: - description: 'Container name: - required for volumes, optional - for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the - output format of the exposed - resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource - to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - required: - - path - type: object - type: array - type: object - secret: - description: secret information about the - secret data to project - properties: - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to - a path within a volume. - properties: - key: - description: key is the key to - project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: optional field specify - whether the Secret or its key must - be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - serviceAccountToken: - description: serviceAccountToken is information - about the serviceAccountToken data to - project - properties: - audience: - description: |- - audience is the intended audience of the token. A recipient of a token - must identify itself with an identifier specified in the audience of the - token, and otherwise should reject the token. The audience defaults to the - identifier of the apiserver. - type: string - expirationSeconds: - description: |- - expirationSeconds is the requested duration of validity of the service - account token. As the token approaches expiration, the kubelet volume - plugin will proactively rotate the service account token. The kubelet will - start trying to rotate the token if the token is older than 80 percent of - its time to live or if the token is older than 24 hours.Defaults to 1 hour - and must be at least 10 minutes. - format: int64 - type: integer - path: - description: |- - path is the path relative to the mount point of the file to project the - token into. - type: string - required: - - path - type: object - type: object - type: array - type: object - quobyte: - description: quobyte represents a Quobyte mount on - the host that shares a pod's lifetime - properties: - group: - description: |- - group to map volume access to - Default is no group - type: string - readOnly: - description: |- - readOnly here will force the Quobyte volume to be mounted with read-only permissions. - Defaults to false. - type: boolean - registry: - description: |- - registry represents a single or multiple Quobyte Registry services - specified as a string as host:port pair (multiple entries are separated with commas) - which acts as the central registry for volumes - type: string - tenant: - description: |- - tenant owning the given Quobyte volume in the Backend - Used with dynamically provisioned Quobyte volumes, value is set by the plugin - type: string - user: - description: |- - user to map volume access to - Defaults to serivceaccount user - type: string - volume: - description: volume is a string that references - an already created Quobyte volume by name. - type: string - required: - - registry - - volume - type: object - rbd: - description: |- - rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. - More info: https://examples.k8s.io/volumes/rbd/README.md - properties: - fsType: - description: |- - fsType is the filesystem type of the volume that you want to mount. - Tip: Ensure that the filesystem type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd - TODO: how do we prevent errors in the filesystem from compromising the machine - type: string - image: - description: |- - image is the rados image name. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - keyring: - description: |- - keyring is the path to key ring for RBDUser. - Default is /etc/ceph/keyring. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - monitors: - description: |- - monitors is a collection of Ceph monitors. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - items: - type: string - type: array - pool: - description: |- - pool is the rados pool name. - Default is rbd. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - readOnly: - description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: boolean - secretRef: - description: |- - secretRef is name of the authentication secret for RBDUser. If provided - overrides keyring. - Default is nil. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - user: - description: |- - user is the rados user name. - Default is admin. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - required: - - image - - monitors - type: object - scaleIO: - description: scaleIO represents a ScaleIO persistent - volume attached and mounted on Kubernetes nodes. - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". - Default is "xfs". - type: string - gateway: - description: gateway is the host address of the - ScaleIO API Gateway. - type: string - protectionDomain: - description: protectionDomain is the name of the - ScaleIO Protection Domain for the configured - storage. - type: string - readOnly: - description: |- - readOnly Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef references to the secret for ScaleIO user and other - sensitive information. If this is not provided, Login operation will fail. - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - sslEnabled: - description: sslEnabled Flag enable/disable SSL - communication with Gateway, default false - type: boolean - storageMode: - description: |- - storageMode indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. - Default is ThinProvisioned. - type: string - storagePool: - description: storagePool is the ScaleIO Storage - Pool associated with the protection domain. - type: string - system: - description: system is the name of the storage - system as configured in ScaleIO. - type: string - volumeName: - description: |- - volumeName is the name of a volume already created in the ScaleIO system - that is associated with this volume source. - type: string - required: - - gateway - - secretRef - - system - type: object - secret: - description: |- - secret represents a secret that should populate this volume. - More info: https://kubernetes.io/docs/concepts/storage/volumes#secret - properties: - defaultMode: - description: |- - defaultMode is Optional: mode bits used to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values - for mode bits. Defaults to 0644. - Directories within the path are not affected by this setting. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - items: - description: |- - items If unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - optional: - description: optional field specify whether the - Secret or its keys must be defined - type: boolean - secretName: - description: |- - secretName is the name of the secret in the pod's namespace to use. - More info: https://kubernetes.io/docs/concepts/storage/volumes#secret - type: string - type: object - storageos: - description: storageOS represents a StorageOS volume - attached and mounted on Kubernetes nodes. - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef specifies the secret to use for obtaining the StorageOS API - credentials. If not specified, default values will be attempted. - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - type: object - x-kubernetes-map-type: atomic - volumeName: - description: |- - volumeName is the human-readable name of the StorageOS volume. Volume - names are only unique within a namespace. - type: string - volumeNamespace: - description: |- - volumeNamespace specifies the scope of the volume within StorageOS. If no - namespace is specified then the Pod's namespace will be used. This allows the - Kubernetes name scoping to be mirrored within StorageOS for tighter integration. - Set VolumeName to any name to override the default behaviour. - Set to "default" if you are not using namespaces within StorageOS. - Namespaces that do not pre-exist within StorageOS will be created. - type: string - type: object - vsphereVolume: - description: vsphereVolume represents a vSphere volume - attached and mounted on kubelets host machine - properties: - fsType: - description: |- - fsType is filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - storagePolicyID: - description: storagePolicyID is the storage Policy - Based Management (SPBM) profile ID associated - with the StoragePolicyName. - type: string - storagePolicyName: - description: storagePolicyName is the storage - Policy Based Management (SPBM) profile name. - type: string - volumePath: - description: volumePath is the path that identifies - vSphere volume vmdk - type: string - required: - - volumePath - type: object - required: - - name - type: object - type: array - required: - - containers - type: object - x-kubernetes-preserve-unknown-fields: true - probes: - description: Settings for health checks. - properties: - roleProbe: - description: Specifies the probe used for checking the role - of the component. - properties: - commands: - description: Commands used to execute for probe. - properties: - queries: - description: Defines read checks that are executed - on the probe sidecar. - items: - type: string - type: array - writes: - description: Defines write checks that are executed - on the probe sidecar. - items: - type: string - type: array - type: object - failureThreshold: - default: 3 - description: Minimum consecutive failures for the probe - to be considered failed after having succeeded. - format: int32 - minimum: 2 - type: integer - periodSeconds: - default: 1 - description: How often (in seconds) to perform the probe. - format: int32 - minimum: 1 - type: integer - timeoutSeconds: - default: 1 - description: Number of seconds after which the probe - times out. Defaults to 1 second. - format: int32 - minimum: 1 - type: integer - type: object - roleProbeTimeoutAfterPodsReady: - description: |- - Defines the timeout (in seconds) for the role probe after all pods of the component are ready. - The system will check if the application is available in the pod. - If pods exceed the InitializationTimeoutSeconds time without a role label, this component will enter the - Failed/Abnormal phase. - - - Note that this configuration will only take effect if the component supports RoleProbe - and will not affect the life cycle of the pod. default values are 60 seconds. - format: int32 - minimum: 30 - type: integer - runningProbe: - description: Specifies the probe used for checking the running - status of the component. - properties: - commands: - description: Commands used to execute for probe. - properties: - queries: - description: Defines read checks that are executed - on the probe sidecar. - items: - type: string - type: array - writes: - description: Defines write checks that are executed - on the probe sidecar. - items: - type: string - type: array - type: object - failureThreshold: - default: 3 - description: Minimum consecutive failures for the probe - to be considered failed after having succeeded. - format: int32 - minimum: 2 - type: integer - periodSeconds: - default: 1 - description: How often (in seconds) to perform the probe. - format: int32 - minimum: 1 - type: integer - timeoutSeconds: - default: 1 - description: Number of seconds after which the probe - times out. Defaults to 1 second. - format: int32 - minimum: 1 - type: integer - type: object - statusProbe: - description: Specifies the probe used for checking the status - of the component. - properties: - commands: - description: Commands used to execute for probe. - properties: - queries: - description: Defines read checks that are executed - on the probe sidecar. - items: - type: string - type: array - writes: - description: Defines write checks that are executed - on the probe sidecar. - items: - type: string - type: array - type: object - failureThreshold: - default: 3 - description: Minimum consecutive failures for the probe - to be considered failed after having succeeded. - format: int32 - minimum: 2 - type: integer - periodSeconds: - default: 1 - description: How often (in seconds) to perform the probe. - format: int32 - minimum: 1 - type: integer - timeoutSeconds: - default: 1 - description: Number of seconds after which the probe - times out. Defaults to 1 second. - format: int32 - minimum: 1 - type: integer - type: object - type: object - replicationSpec: - description: Defines spec for `Replication` workloads. - properties: - llPodManagementPolicy: - description: |- - Controls the creation of pods during initial scale up, replacement of pods on nodes, and scaling down. - - - - `OrderedReady`: Creates pods in increasing order (pod-0, then pod-1, etc). The controller waits until each pod - is ready before continuing. Pods are removed in reverse order when scaling down. - - `Parallel`: Creates pods in parallel to match the desired scale without waiting. All pods are deleted at once - when scaling down. - type: string - llUpdateStrategy: - description: |- - Specifies the low-level StatefulSetUpdateStrategy to be used when updating Pods in the StatefulSet upon a - revision to the Template. - `UpdateStrategy` will be ignored if this is provided. - properties: - rollingUpdate: - description: RollingUpdate is used to communicate parameters - when Type is RollingUpdateStatefulSetStrategyType. - properties: - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of pods that can be unavailable during the update. - Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - Absolute number is calculated from percentage by rounding up. This can not be 0. - Defaults to 1. This field is alpha-level and is only honored by servers that enable the - MaxUnavailableStatefulSet feature. The field applies to all pods in the range 0 to - Replicas-1. That means if there is any unavailable pod in the range 0 to Replicas-1, it - will be counted towards MaxUnavailable. - x-kubernetes-int-or-string: true - partition: - description: |- - Partition indicates the ordinal at which the StatefulSet should be partitioned - for updates. During a rolling update, all pods from ordinal Replicas-1 to - Partition are updated. All pods from ordinal Partition-1 to 0 remain untouched. - This is helpful in being able to do a canary based deployment. The default value is 0. - format: int32 - type: integer - type: object - type: - description: |- - Type indicates the type of the StatefulSetUpdateStrategy. - Default is RollingUpdate. - type: string - type: object - updateStrategy: - default: Serial - description: |- - Specifies the strategy for updating Pods. - For workloadType=`Consensus`, the update strategy can be one of the following: - - - - `Serial`: Updates Members sequentially to minimize component downtime. - - `BestEffortParallel`: Updates Members in parallel to minimize component write downtime. Majority remains online - at all times. - - `Parallel`: Forces parallel updates. - enum: - - Serial - - BestEffortParallel - - Parallel - type: string - type: object - rsmSpec: - description: |- - Defines workload spec of this component. - From KB 0.7.0, RSM(InstanceSetSpec) will be the underlying CR which powers all kinds of workload in KB. - RSM is an enhanced stateful workload extension dedicated for heavy-state workloads like databases. - properties: - memberUpdateStrategy: - description: |- - Describes the strategy for updating Members (Pods). - - - - `Serial`: Updates Members sequentially to ensure minimum component downtime. - - `BestEffortParallel`: Updates Members in parallel to ensure minimum component write downtime. - - `Parallel`: Forces parallel updates. - enum: - - Serial - - BestEffortParallel - - Parallel - type: string - membershipReconfiguration: - description: Indicates the actions required for dynamic - membership reconfiguration. - properties: - logSyncAction: - description: |- - Defines the action to trigger the new member to start log syncing. - If the Image is not configured, the Image from the previous non-nil action will be used. - properties: - args: - description: Additional parameters used to perform - specific statements. This field is optional. - items: - type: string - type: array - command: - description: A set of instructions that will be - executed within the Container to retrieve or process - role information. This field is required. - items: - type: string - type: array - image: - description: Refers to the utility image that contains - the command which can be utilized to retrieve - or process role information. - type: string - required: - - command - type: object - memberJoinAction: - description: |- - Defines the action to add a member. - If the Image is not configured, the Image from the previous non-nil action will be used. - properties: - args: - description: Additional parameters used to perform - specific statements. This field is optional. - items: - type: string - type: array - command: - description: A set of instructions that will be - executed within the Container to retrieve or process - role information. This field is required. - items: - type: string - type: array - image: - description: Refers to the utility image that contains - the command which can be utilized to retrieve - or process role information. - type: string - required: - - command - type: object - memberLeaveAction: - description: |- - Defines the action to remove a member. - If the Image is not configured, the Image from the previous non-nil action will be used. - properties: - args: - description: Additional parameters used to perform - specific statements. This field is optional. - items: - type: string - type: array - command: - description: A set of instructions that will be - executed within the Container to retrieve or process - role information. This field is required. - items: - type: string - type: array - image: - description: Refers to the utility image that contains - the command which can be utilized to retrieve - or process role information. - type: string - required: - - command - type: object - promoteAction: - description: |- - Defines the action to inform the cluster that the new member can join voting now. - If the Image is not configured, the Image from the previous non-nil action will be used. - properties: - args: - description: Additional parameters used to perform - specific statements. This field is optional. - items: - type: string - type: array - command: - description: A set of instructions that will be - executed within the Container to retrieve or process - role information. This field is required. - items: - type: string - type: array - image: - description: Refers to the utility image that contains - the command which can be utilized to retrieve - or process role information. - type: string - required: - - command - type: object - switchoverAction: - description: |- - Specifies the environment variables that can be used in all following Actions: - - KB_ITS_USERNAME: Represents the username part of the credential - - KB_ITS_PASSWORD: Represents the password part of the credential - - KB_ITS_LEADER_HOST: Represents the leader host - - KB_ITS_TARGET_HOST: Represents the target host - - KB_ITS_SERVICE_PORT: Represents the service port - - - Defines the action to perform a switchover. - If the Image is not configured, the latest [BusyBox](https://busybox.net/) image will be used. - properties: - args: - description: Additional parameters used to perform - specific statements. This field is optional. - items: - type: string - type: array - command: - description: A set of instructions that will be - executed within the Container to retrieve or process - role information. This field is required. - items: - type: string - type: array - image: - description: Refers to the utility image that contains - the command which can be utilized to retrieve - or process role information. - type: string - required: - - command - type: object - type: object - roleProbe: - description: Defines the method used to probe a role. - properties: - builtinHandlerName: - description: |- - Specifies the builtin handler name to use to probe the role of the main container. - Available handlers include: mysql, postgres, mongodb, redis, etcd, kafka. - Use CustomHandler to define a custom role probe function if none of the built-in handlers meet the requirement. - type: string - customHandler: - description: |- - Defines a custom method for role probing. - If the BuiltinHandler meets the requirement, use it instead. - Actions defined here are executed in series. - Upon completion of all actions, the final output should be a single string representing the role name defined in spec.Roles. - The latest [BusyBox](https://busybox.net/) image will be used if Image is not configured. - Environment variables can be used in Command: - - v_KB_ITS_LAST_STDOUT: stdout from the last action, watch for 'v_' prefix - - KB_ITS_USERNAME: username part of the credential - - KB_ITS_PASSWORD: password part of the credential - items: - properties: - args: - description: Additional parameters used to perform - specific statements. This field is optional. - items: - type: string - type: array - command: - description: A set of instructions that will be - executed within the Container to retrieve or - process role information. This field is required. - items: - type: string - type: array - image: - description: Refers to the utility image that - contains the command which can be utilized to - retrieve or process role information. - type: string - required: - - command - type: object - type: array - failureThreshold: - default: 3 - description: Specifies the minimum number of consecutive - failures for the probe to be considered failed after - having succeeded. - format: int32 - minimum: 1 - type: integer - initialDelaySeconds: - default: 0 - description: Specifies the number of seconds to wait - after the container has started before initiating - role probing. - format: int32 - minimum: 0 - type: integer - periodSeconds: - default: 2 - description: Specifies the frequency (in seconds) of - probe execution. - format: int32 - minimum: 1 - type: integer - roleUpdateMechanism: - default: ReadinessProbeEventUpdate - description: Specifies the method for updating the pod - role label. - enum: - - ReadinessProbeEventUpdate - - DirectAPIServerEventUpdate - type: string - successThreshold: - default: 1 - description: Specifies the minimum number of consecutive - successes for the probe to be considered successful - after having failed. - format: int32 - minimum: 1 - type: integer - timeoutSeconds: - default: 1 - description: Specifies the number of seconds after which - the probe times out. - format: int32 - minimum: 1 - type: integer - type: object - roles: - description: Specifies a list of roles defined within the - system. - items: - properties: - accessMode: - default: ReadWrite - description: Specifies the service capabilities of - this member. - enum: - - None - - Readonly - - ReadWrite - type: string - canVote: - default: true - description: Indicates if this member has voting rights. - type: boolean - isLeader: - default: false - description: Determines if this member is the leader. - type: boolean - name: - default: leader - description: Defines the role name of the replica. - type: string - required: - - accessMode - - name - type: object - type: array - type: object - statefulSpec: - description: Defines spec for `Stateful` workloads. - properties: - llPodManagementPolicy: - description: |- - Controls the creation of pods during initial scale up, replacement of pods on nodes, and scaling down. - - - - `OrderedReady`: Creates pods in increasing order (pod-0, then pod-1, etc). The controller waits until each pod - is ready before continuing. Pods are removed in reverse order when scaling down. - - `Parallel`: Creates pods in parallel to match the desired scale without waiting. All pods are deleted at once - when scaling down. - type: string - llUpdateStrategy: - description: |- - Specifies the low-level StatefulSetUpdateStrategy to be used when updating Pods in the StatefulSet upon a - revision to the Template. - `UpdateStrategy` will be ignored if this is provided. - properties: - rollingUpdate: - description: RollingUpdate is used to communicate parameters - when Type is RollingUpdateStatefulSetStrategyType. - properties: - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of pods that can be unavailable during the update. - Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - Absolute number is calculated from percentage by rounding up. This can not be 0. - Defaults to 1. This field is alpha-level and is only honored by servers that enable the - MaxUnavailableStatefulSet feature. The field applies to all pods in the range 0 to - Replicas-1. That means if there is any unavailable pod in the range 0 to Replicas-1, it - will be counted towards MaxUnavailable. - x-kubernetes-int-or-string: true - partition: - description: |- - Partition indicates the ordinal at which the StatefulSet should be partitioned - for updates. During a rolling update, all pods from ordinal Replicas-1 to - Partition are updated. All pods from ordinal Partition-1 to 0 remain untouched. - This is helpful in being able to do a canary based deployment. The default value is 0. - format: int32 - type: integer - type: object - type: - description: |- - Type indicates the type of the StatefulSetUpdateStrategy. - Default is RollingUpdate. - type: string - type: object - updateStrategy: - default: Serial - description: |- - Specifies the strategy for updating Pods. - For workloadType=`Consensus`, the update strategy can be one of the following: - - - - `Serial`: Updates Members sequentially to minimize component downtime. - - `BestEffortParallel`: Updates Members in parallel to minimize component write downtime. Majority remains online - at all times. - - `Parallel`: Forces parallel updates. - enum: - - Serial - - BestEffortParallel - - Parallel - type: string - type: object - statelessSpec: - description: Defines spec for `Stateless` workloads. - properties: - updateStrategy: - description: Specifies the deployment strategy that will - be used to replace existing pods with new ones. - properties: - rollingUpdate: - description: |- - Rolling update config params. Present only if DeploymentStrategyType = - RollingUpdate. - --- - TODO: Update this to follow our convention for oneOf, whatever we decide it - to be. - properties: - maxSurge: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of pods that can be scheduled above the desired number of - pods. - Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - This can not be 0 if MaxUnavailable is 0. - Absolute number is calculated from percentage by rounding up. - Defaults to 25%. - Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when - the rolling update starts, such that the total number of old and new pods do not exceed - 130% of desired pods. Once old pods have been killed, - new ReplicaSet can be scaled up further, ensuring that total number of pods running - at any time during the update is at most 130% of desired pods. - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of pods that can be unavailable during the update. - Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - Absolute number is calculated from percentage by rounding down. - This can not be 0 if MaxSurge is 0. - Defaults to 25%. - Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods - immediately when the rolling update starts. Once new pods are ready, old ReplicaSet - can be scaled down further, followed by scaling up the new ReplicaSet, ensuring - that the total number of pods available at all times during the update is at - least 70% of desired pods. - x-kubernetes-int-or-string: true - type: object - type: - description: Type of deployment. Can be "Recreate" or - "RollingUpdate". Default is RollingUpdate. - type: string - type: object - type: object - switchoverSpec: - description: |- - Defines command to do switchover. - In particular, when workloadType=Replication, the command defined in switchoverSpec will only be executed under - the condition of cluster.componentSpecs[x].SwitchPolicy.type=Noop. - properties: - withCandidate: - description: Represents the action of switching over to - a specified candidate primary or leader instance. - properties: - cmdExecutorConfig: - description: Specifies the switchover command. - properties: - args: - description: Additional parameters used in the execution - of the command. - items: - type: string - type: array - command: - description: The command to be executed. - items: - type: string - minItems: 1 - type: array - env: - description: A list of environment variables that - will be injected into the command execution context. - items: - description: EnvVar represents an environment - variable present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema - the FieldPath is written in terms - of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to - select in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output - format of the exposed resources, - defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret - in the pod's namespace - properties: - key: - description: The key of the secret - to select from. Must be a valid - secret key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-preserve-unknown-fields: true - image: - description: Specifies the image used to execute - the command. - type: string - required: - - command - - image - type: object - scriptSpecSelectors: - description: |- - Used to select the script that need to be referenced. - When defined, the scripts defined in scriptSpecs can be referenced within the SwitchoverAction.CmdExecutorConfig. - items: - properties: - name: - description: Represents the name of the ScriptSpec - referent. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - required: - - name - type: object - type: array - required: - - cmdExecutorConfig - type: object - withoutCandidate: - description: Represents the action of switching over without - specifying a candidate primary or leader instance. - properties: - cmdExecutorConfig: - description: Specifies the switchover command. - properties: - args: - description: Additional parameters used in the execution - of the command. - items: - type: string - type: array - command: - description: The command to be executed. - items: - type: string - minItems: 1 - type: array - env: - description: A list of environment variables that - will be injected into the command execution context. - items: - description: EnvVar represents an environment - variable present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema - the FieldPath is written in terms - of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to - select in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output - format of the exposed resources, - defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret - in the pod's namespace - properties: - key: - description: The key of the secret - to select from. Must be a valid - secret key. - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-preserve-unknown-fields: true - image: - description: Specifies the image used to execute - the command. - type: string - required: - - command - - image - type: object - scriptSpecSelectors: - description: |- - Used to select the script that need to be referenced. - When defined, the scripts defined in scriptSpecs can be referenced within the SwitchoverAction.CmdExecutorConfig. - items: - properties: - name: - description: Represents the name of the ScriptSpec - referent. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - required: - - name - type: object - type: array - required: - - cmdExecutorConfig - type: object - type: object - workloadType: - description: |- - Defines the type of the workload. - - - - `Stateless` describes stateless applications. - - `Stateful` describes common stateful applications. - - `Consensus` describes applications based on consensus protocols, such as raft and paxos. - - `Replication` describes applications based on the primary-secondary data replication protocol. - enum: - - Stateless - - Stateful - - Consensus - - Replication - type: string - required: - - name - - workloadType - type: object - x-kubernetes-validations: - - message: componentDefs.consensusSpec(deprecated) or componentDefs.rsmSpec(recommended) - is required when componentDefs.workloadType is Consensus, and - forbidden otherwise - rule: 'has(self.workloadType) && self.workloadType == ''Consensus'' - ? (has(self.consensusSpec) || has(self.rsmSpec)) : !has(self.consensusSpec)' - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map topologies: description: Topologies defines all possible topologies within the cluster. diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml index 0abe99e9e9af..a1bb7628553b 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml @@ -5230,7 +5230,7 @@ spec: type: boolean switchPolicy: description: |- - Defines the strategy for switchover and failover when workloadType is Replication. + Defines the strategy for switchover and failover. Deprecated since v0.9. @@ -13930,7 +13930,7 @@ spec: type: boolean switchPolicy: description: |- - Defines the strategy for switchover and failover when workloadType is Replication. + Defines the strategy for switchover and failover. Deprecated since v0.9. diff --git a/deploy/helm/crds/apps.kubeblocks.io_opsrequests.yaml b/deploy/helm/crds/apps.kubeblocks.io_opsrequests.yaml index 282a58c7a9ee..7c703b54575e 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_opsrequests.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_opsrequests.yaml @@ -5022,16 +5022,6 @@ spec: in its current state. maxLength: 1024 type: string - workloadType: - description: |- - Records the workload type of Component in ClusterDefinition. - Deprecated and should be removed in the future version. - enum: - - Stateless - - Stateful - - Consensus - - Replication - type: string type: object description: Records the status information of Components changed due to the OpsRequest. diff --git a/docs/developer_docs/api-reference/cluster.md b/docs/developer_docs/api-reference/cluster.md index dd11a84eab44..67b194735bef 100644 --- a/docs/developer_docs/api-reference/cluster.md +++ b/docs/developer_docs/api-reference/cluster.md @@ -512,25 +512,6 @@ ClusterDefinitionSpec - - - - @@ -2825,9 +2806,6 @@ ServiceDescriptorStatus
    -componentDefs
    - - -[]ClusterComponentDefinition - - -
    -(Optional) -

    Provides the definitions for the cluster components.

    -

    Deprecated since v0.9. -Components should now be individually defined using ComponentDefinition and -collectively referenced via topology.components. -This field is maintained for backward compatibility and its use is discouraged. -Existing usage should be updated to the current preferred approach to avoid compatibility issues in future releases.

    -
    topologies
    @@ -2551,7 +2532,7 @@ bool
    (Optional) -

    Indicates whether opsRequest should continue to queue and run when ‘force’ is set to true.

    +

    Indicates whether opsRequest should continue to queue when ‘force’ is set to true.

    AccessMode (string alias)

    -

    -(Appears on:ConsensusMember) -

    AccessMode defines the modes of access granted to the SVC. The modes can be None, Readonly, or ReadWrite.

    @@ -3968,188 +3946,6 @@ Kubernetes core/v1.ConfigMapVolumeSource -

    ClusterComponentDefinition -

    -

    -(Appears on:ClusterDefinitionSpec) -

    -
    -

    ClusterComponentDefinition defines a Component within a ClusterDefinition but is deprecated and -has been replaced by ComponentDefinition.

    -

    Deprecated: Use ComponentDefinition instead. This type is deprecated as of version 0.8.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -name
    - -string - -
    -

    This name could be used as default name of cluster.spec.componentSpecs.name, and needs to conform with same -validation rules as cluster.spec.componentSpecs.name, currently complying with IANA Service Naming rule. -This name will apply to cluster objects as the value of label “apps.kubeblocks.io/component-name”.

    -
    -workloadType
    - - -WorkloadType - - -
    -

    Defines the type of the workload.

    -
      -
    • Stateless describes stateless applications.
    • -
    • Stateful describes common stateful applications.
    • -
    • Consensus describes applications based on consensus protocols, such as raft and paxos.
    • -
    • Replication describes applications based on the primary-secondary data replication protocol.
    • -
    -
    -probes
    - - -ClusterDefinitionProbes - - -
    -(Optional) -

    Settings for health checks.

    -
    -podSpec
    - - -Kubernetes core/v1.PodSpec - - -
    -(Optional) -

    Defines the pod spec template of component.

    -
    -statelessSpec
    - - -StatelessSetSpec - - -
    -(Optional) -

    Defines spec for Stateless workloads.

    -
    -statefulSpec
    - - -StatefulSetSpec - - -
    -(Optional) -

    Defines spec for Stateful workloads.

    -
    -consensusSpec
    - - -ConsensusSetSpec - - -
    -(Optional) -

    Defines spec for Consensus workloads. It’s required if the workload type is Consensus.

    -
    -replicationSpec
    - - -ReplicationSetSpec - - -
    -(Optional) -

    Defines spec for Replication workloads.

    -
    -rsmSpec
    - - -RSMSpec - - -
    -(Optional) -

    Defines workload spec of this component. -From KB 0.7.0, RSM(InstanceSetSpec) will be the underlying CR which powers all kinds of workload in KB. -RSM is an enhanced stateful workload extension dedicated for heavy-state workloads like databases.

    -
    -horizontalScalePolicy
    - - -HorizontalScalePolicy - - -
    -(Optional) -

    Defines the behavior of horizontal scale.

    -
    -switchoverSpec
    - - -SwitchoverSpec - - -
    -(Optional) -

    Defines command to do switchover. -In particular, when workloadType=Replication, the command defined in switchoverSpec will only be executed under -the condition of cluster.componentSpecs[x].SwitchPolicy.type=Noop.

    -

    ClusterComponentPhase (string alias)

    @@ -4609,7 +4405,7 @@ ClusterSwitchPolicy (Optional) -

    Defines the strategy for switchover and failover when workloadType is Replication.

    +

    Defines the strategy for switchover and failover.

    Deprecated since v0.9. This field is maintained for backward compatibility and its use is discouraged. Existing usage should be updated to the current preferred approach to avoid compatibility issues in future releases.

    @@ -5052,190 +4848,6 @@ Kubernetes core/v1.PersistentVolumeMode -

    ClusterDefinitionProbe -

    -

    -(Appears on:ClusterDefinitionProbes) -

    -
    -

    ClusterDefinitionProbe is deprecated since v0.8.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -periodSeconds
    - -int32 - -
    -

    How often (in seconds) to perform the probe.

    -
    -timeoutSeconds
    - -int32 - -
    -

    Number of seconds after which the probe times out. Defaults to 1 second.

    -
    -failureThreshold
    - -int32 - -
    -

    Minimum consecutive failures for the probe to be considered failed after having succeeded.

    -
    -commands
    - - -ClusterDefinitionProbeCMDs - - -
    -(Optional) -

    Commands used to execute for probe.

    -
    -

    ClusterDefinitionProbeCMDs -

    -

    -(Appears on:ClusterDefinitionProbe) -

    -
    -

    ClusterDefinitionProbeCMDs is deprecated since v0.8.

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -writes
    - -[]string - -
    -(Optional) -

    Defines write checks that are executed on the probe sidecar.

    -
    -queries
    - -[]string - -
    -(Optional) -

    Defines read checks that are executed on the probe sidecar.

    -
    -

    ClusterDefinitionProbes -

    -

    -(Appears on:ClusterComponentDefinition) -

    -
    -

    ClusterDefinitionProbes is deprecated since v0.8.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -runningProbe
    - - -ClusterDefinitionProbe - - -
    -(Optional) -

    Specifies the probe used for checking the running status of the component.

    -
    -statusProbe
    - - -ClusterDefinitionProbe - - -
    -(Optional) -

    Specifies the probe used for checking the status of the component.

    -
    -roleProbe
    - - -ClusterDefinitionProbe - - -
    -(Optional) -

    Specifies the probe used for checking the role of the component.

    -
    -roleProbeTimeoutAfterPodsReady
    - -int32 - -
    -(Optional) -

    Defines the timeout (in seconds) for the role probe after all pods of the component are ready. -The system will check if the application is available in the pod. -If pods exceed the InitializationTimeoutSeconds time without a role label, this component will enter the -Failed/Abnormal phase.

    -

    Note that this configuration will only take effect if the component supports RoleProbe -and will not affect the life cycle of the pod. default values are 60 seconds.

    -

    ClusterDefinitionSpec

    @@ -5254,25 +4866,6 @@ and will not affect the life cycle of the pod. default values are 60 seconds.

    -componentDefs
    - - -[]ClusterComponentDefinition - - - - -(Optional) -

    Provides the definitions for the cluster components.

    -

    Deprecated since v0.9. -Components should now be individually defined using ComponentDefinition and -collectively referenced via topology.components. -This field is maintained for backward compatibility and its use is discouraged. -Existing usage should be updated to the current preferred approach to avoid compatibility issues in future releases.

    - - - - topologies
    @@ -6260,172 +5853,17 @@ This approach allows:

    -

    ClusterTopologyOrders -

    -

    -(Appears on:ClusterTopology) -

    -
    -

    ClusterTopologyOrders manages the lifecycle of components within a cluster by defining their provisioning, -terminating, and updating sequences. -It organizes components into stages or groups, where each group indicates a set of components -that can be managed concurrently. -These groups are processed sequentially, allowing precise control based on component dependencies and requirements.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -provision
    - -[]string - -
    -(Optional) -

    Specifies the order for creating and initializing components. -This is designed for components that depend on one another. Components without dependencies can be grouped together.

    -

    Components that can be provisioned independently or have no dependencies can be listed together in the same stage, -separated by commas.

    -
    -terminate
    - -[]string - -
    -(Optional) -

    Outlines the order for stopping and deleting components. -This sequence is designed for components that require a graceful shutdown or have interdependencies.

    -

    Components that can be terminated independently or have no dependencies can be listed together in the same stage, -separated by commas.

    -
    -update
    - -[]string - -
    -(Optional) -

    Update determines the order for updating components’ specifications, such as image upgrades or resource scaling. -This sequence is designed for components that have dependencies or require specific update procedures.

    -

    Components that can be updated independently or have no dependencies can be listed together in the same stage, -separated by commas.

    -
    -

    CmdExecutorConfig -

    -

    -(Appears on:SwitchoverAction) -

    -
    -

    CmdExecutorConfig specifies how to perform creation and deletion statements.

    -

    Deprecated since v0.8.

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -CommandExecutorEnvItem
    - - -CommandExecutorEnvItem - - -
    -

    -(Members of CommandExecutorEnvItem are embedded into this type.) -

    -
    -CommandExecutorItem
    - - -CommandExecutorItem - - -
    -

    -(Members of CommandExecutorItem are embedded into this type.) -

    -
    -

    CommandExecutorEnvItem -

    -

    -(Appears on:CmdExecutorConfig) -

    -
    -

    CommandExecutorEnvItem is deprecated since v0.8.

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -image
    - -string - -
    -

    Specifies the image used to execute the command.

    -
    -env
    - - -[]Kubernetes core/v1.EnvVar - - -
    -(Optional) -

    A list of environment variables that will be injected into the command execution context.

    -
    -

    CommandExecutorItem +

    ClusterTopologyOrders

    -(Appears on:CmdExecutorConfig) +(Appears on:ClusterTopology)

    -

    CommandExecutorItem is deprecated since v0.8.

    +

    ClusterTopologyOrders manages the lifecycle of components within a cluster by defining their provisioning, +terminating, and updating sequences. +It organizes components into stages or groups, where each group indicates a set of components +that can be managed concurrently. +These groups are processed sequentially, allowing precise control based on component dependencies and requirements.

    @@ -6437,25 +5875,47 @@ string + + + + @@ -10214,135 +9674,6 @@ string
    -command
    +provision
    []string
    -

    The command to be executed.

    +(Optional) +

    Specifies the order for creating and initializing components. +This is designed for components that depend on one another. Components without dependencies can be grouped together.

    +

    Components that can be provisioned independently or have no dependencies can be listed together in the same stage, +separated by commas.

    -args
    +terminate
    []string
    (Optional) -

    Additional parameters used in the execution of the command.

    +

    Outlines the order for stopping and deleting components. +This sequence is designed for components that require a graceful shutdown or have interdependencies.

    +

    Components that can be terminated independently or have no dependencies can be listed together in the same stage, +separated by commas.

    +
    +update
    + +[]string + +
    +(Optional) +

    Update determines the order for updating components’ specifications, such as image upgrades or resource scaling. +This sequence is designed for components that have dependencies or require specific update procedures.

    +

    Components that can be updated independently or have no dependencies can be listed together in the same stage, +separated by commas.

    -

    ConsensusMember -

    -

    -(Appears on:ConsensusSetSpec) -

    -
    -

    ConsensusMember is deprecated since v0.7.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -name
    - -string - -
    -

    Specifies the name of the consensus member.

    -
    -accessMode
    - - -AccessMode - - -
    -

    Specifies the services that this member is capable of providing.

    -
    -replicas
    - -int32 - -
    -(Optional) -

    Indicates the number of Pods that perform this role. -The default is 1 for Leader, 0 for Learner, others for Followers.

    -
    -

    ConsensusSetSpec -

    -

    -(Appears on:ClusterComponentDefinition) -

    -
    -

    ConsensusSetSpec is deprecated since v0.7.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -StatefulSetSpec
    - - -StatefulSetSpec - - -
    -

    -(Members of StatefulSetSpec are embedded into this type.) -

    -
    -leader
    - - -ConsensusMember - - -
    -

    Represents a single leader in the consensus set.

    -
    -followers
    - - -[]ConsensusMember - - -
    -(Optional) -

    Members of the consensus set that have voting rights but are not the leader.

    -
    -learner
    - - -ConsensusMember - - -
    -(Optional) -

    Represents a member of the consensus set that does not have voting rights.

    -

    ContainerVars

    @@ -11182,98 +10513,6 @@ in each OpsService definition.

    -

    HScaleDataClonePolicyType -(string alias)

    -

    -(Appears on:HorizontalScalePolicy) -

    -
    -

    HScaleDataClonePolicyType defines the data clone policy to be used during horizontal scaling. -This policy determines how data is handled when new nodes are added to the cluster. -The policy can be set to None, CloneVolume, or Snapshot.

    -
    - - - - - - - - - - - - - - -
    ValueDescription

    "CloneVolume"

    HScaleDataClonePolicyCloneVolume indicates that data will be cloned from existing volumes during horizontal scaling.

    -

    "Snapshot"

    HScaleDataClonePolicyFromSnapshot indicates that data will be cloned from a snapshot during horizontal scaling.

    -

    "None"

    HScaleDataClonePolicyNone indicates that no data cloning will occur during horizontal scaling.

    -
    -

    HorizontalScalePolicy -

    -

    -(Appears on:ClusterComponentDefinition) -

    -
    -

    HorizontalScalePolicy is deprecated since v0.8.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -type
    - - -HScaleDataClonePolicyType - - -
    -(Optional) -

    Determines the data synchronization method when a component scales out. -The policy can be one of the following: {None, CloneVolume}. The default policy is None.

    -
      -
    • None: This is the default policy. It creates an empty volume without data cloning.
    • -
    • CloneVolume: This policy clones data to newly scaled pods. It first tries to use a volume snapshot. -If volume snapshot is not enabled, it will attempt to use a backup tool. If neither method works, it will report an error.
    • -
    • Snapshot: This policy is deprecated and is an alias for CloneVolume.
    • -
    -
    -backupPolicyTemplateName
    - -string - -
    -(Optional) -

    Refers to the backup policy template.

    -
    -volumeMountsName
    - -string - -
    -(Optional) -

    Specifies the volumeMount of the container to backup. -This only works if Type is not None. If not specified, the first volumeMount will be selected.

    -

    HorizontalScaling

    @@ -13235,21 +12474,6 @@ PreCheckResult -workloadType
    - - -WorkloadType - - - - -(Optional) -

    Records the workload type of Component in ClusterDefinition. -Deprecated and should be removed in the future version.

    - - - - reason
    string @@ -13355,7 +12579,7 @@ bool (Optional) -

    Indicates whether opsRequest should continue to queue and run when ‘force’ is set to true.

    +

    Indicates whether opsRequest should continue to queue when ‘force’ is set to true.

    @@ -15213,59 +14437,19 @@ int (Optional) -

    Defines the high watermark threshold for the volume, it will override the component level threshold. -If the value is invalid, it will be ignored and the component level threshold will be used.

    - - - - -

    ProvisionSecretRef -

    -

    -(Appears on:ComponentSystemAccount, SystemAccount) -

    -
    -

    ProvisionSecretRef represents the reference to a secret.

    -
    - - - - - - - - - - - - - - -
    FieldDescription
    -name
    - -string - -
    -

    The unique identifier of the secret.

    -
    -namespace
    - -string - -
    -

    The namespace where the secret is located.

    +

    Defines the high watermark threshold for the volume, it will override the component level threshold. +If the value is invalid, it will be ignored and the component level threshold will be used.

    -

    RSMSpec +

    ProvisionSecretRef

    -(Appears on:ClusterComponentDefinition) +(Appears on:ComponentSystemAccount, SystemAccount)

    -

    RSMSpec is deprecated since v0.8.

    +

    ProvisionSecretRef represents the reference to a secret.

    @@ -15277,63 +14461,24 @@ string - - - - - - - - @@ -15891,39 +15036,6 @@ int32
    -roles
    - - -[]ReplicaRole - - -
    -(Optional) -

    Specifies a list of roles defined within the system.

    -
    -roleProbe
    - - -RoleProbe - - -
    -(Optional) -

    Defines the method used to probe a role.

    -
    -membershipReconfiguration
    +name
    - -MembershipReconfiguration - +string
    -(Optional) -

    Indicates the actions required for dynamic membership reconfiguration.

    +

    The unique identifier of the secret.

    -memberUpdateStrategy
    +namespace
    - -MemberUpdateStrategy - +string
    -(Optional) -

    Describes the strategy for updating Members (Pods).

    -
      -
    • Serial: Updates Members sequentially to ensure minimum component downtime.
    • -
    • BestEffortParallel: Updates Members in parallel to ensure minimum component write downtime.
    • -
    • Parallel: Forces parallel updates.
    • -
    +

    The namespace where the secret is located.

    -

    ReplicationSetSpec -

    -

    -(Appears on:ClusterComponentDefinition) -

    -
    -

    ReplicationSetSpec is deprecated since v0.7.

    -
    - - - - - - - - - - - - - -
    FieldDescription
    -StatefulSetSpec
    - - -StatefulSetSpec - - -
    -

    -(Members of StatefulSetSpec are embedded into this type.) -

    -

    RerenderResourceType (string alias)

    @@ -16688,7 +15800,7 @@ In these cases, the script must be executed on all replica Pods matching the sel

    ScriptSpecSelector

    -(Appears on:ComponentSwitchover, SwitchoverAction) +(Appears on:ComponentSwitchover)

    @@ -18364,118 +17476,11 @@ CustomOps -

    StatefulSetSpec -

    -

    -(Appears on:ClusterComponentDefinition, ConsensusSetSpec, ReplicationSetSpec) -

    -
    -

    StatefulSetSpec is deprecated since v0.7.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -updateStrategy
    - - -UpdateStrategy - - -
    -(Optional) -

    Specifies the strategy for updating Pods. -For workloadType=Consensus, the update strategy can be one of the following:

    -
      -
    • Serial: Updates Members sequentially to minimize component downtime.
    • -
    • BestEffortParallel: Updates Members in parallel to minimize component write downtime. Majority remains online -at all times.
    • -
    • Parallel: Forces parallel updates.
    • -
    -
    -llPodManagementPolicy
    - - -Kubernetes apps/v1.PodManagementPolicyType - - -
    -(Optional) -

    Controls the creation of pods during initial scale up, replacement of pods on nodes, and scaling down.

    -
      -
    • OrderedReady: Creates pods in increasing order (pod-0, then pod-1, etc). The controller waits until each pod -is ready before continuing. Pods are removed in reverse order when scaling down.
    • -
    • Parallel: Creates pods in parallel to match the desired scale without waiting. All pods are deleted at once -when scaling down.
    • -
    -
    -llUpdateStrategy
    - - -Kubernetes apps/v1.StatefulSetUpdateStrategy - - -
    -(Optional) -

    Specifies the low-level StatefulSetUpdateStrategy to be used when updating Pods in the StatefulSet upon a -revision to the Template. -UpdateStrategy will be ignored if this is provided.

    -

    StatefulSetWorkload

    StatefulSetWorkload interface

    -

    StatelessSetSpec -

    -

    -(Appears on:ClusterComponentDefinition) -

    -
    -

    StatelessSetSpec is deprecated since v0.7.

    -
    - - - - - - - - - - - - - -
    FieldDescription
    -updateStrategy
    - - -Kubernetes apps/v1.DeploymentStrategy - - -
    -(Optional) -

    Specifies the deployment strategy that will be used to replace existing pods with new ones.

    -

    SwitchPolicyType (string alias)

    @@ -18574,98 +17579,6 @@ string -

    SwitchoverAction -

    -

    -(Appears on:SwitchoverSpec) -

    -
    -

    SwitchoverAction is deprecated since v0.8.

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -cmdExecutorConfig
    - - -CmdExecutorConfig - - -
    -

    Specifies the switchover command.

    -
    -scriptSpecSelectors
    - - -[]ScriptSpecSelector - - -
    -(Optional) -

    Used to select the script that need to be referenced. -When defined, the scripts defined in scriptSpecs can be referenced within the SwitchoverAction.CmdExecutorConfig.

    -
    -

    SwitchoverSpec -

    -

    -(Appears on:ClusterComponentDefinition) -

    -
    -

    SwitchoverSpec is deprecated since v0.8.

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -withCandidate
    - - -SwitchoverAction - - -
    -(Optional) -

    Represents the action of switching over to a specified candidate primary or leader instance.

    -
    -withoutCandidate
    - - -SwitchoverAction - - -
    -(Optional) -

    Represents the action of switching over without specifying a candidate primary or leader instance.

    -

    SystemAccount

    @@ -19097,7 +18010,7 @@ string

    UpdateStrategy (string alias)

    -(Appears on:ClusterComponentSpec, ComponentDefinitionSpec, StatefulSetSpec) +(Appears on:ClusterComponentSpec, ComponentDefinitionSpec)

    UpdateStrategy defines the update strategy for cluster components. This strategy determines how updates are applied @@ -19762,38 +18675,6 @@ as read-only. And after that, if all volumes’ space usage drops under the -

    WorkloadType -(string alias)

    -

    -(Appears on:ClusterComponentDefinition, OpsRequestComponentStatus) -

    -
    -

    WorkloadType defines the type of workload for the components of the ClusterDefinition. -It can be one of the following: Stateless, Stateful, Consensus, or Replication.

    -

    Deprecated since v0.8.

    -
    - - - - - - - - - - - - - - - - -
    ValueDescription

    "Consensus"

    Consensus represents a workload type involving distributed consensus algorithms for coordinated decision-making.

    -

    "Replication"

    Replication represents a workload type that involves replication, typically used for achieving high availability -and fault tolerance.

    -

    "Stateful"

    Stateful represents a workload type where components maintain state, and each instance has a unique identity.

    -

    "Stateless"

    Stateless represents a workload type where components do not maintain state, and instances are interchangeable.

    -

    apps.kubeblocks.io/v1beta1

    @@ -22782,7 +21663,7 @@ ReplicaRole

    MemberUpdateStrategy (string alias)

    -(Appears on:RSMSpec, InstanceSetSpec) +(Appears on:InstanceSetSpec)

    MemberUpdateStrategy defines Cluster Component update strategy.

    @@ -22805,7 +21686,7 @@ ReplicaRole

    MembershipReconfiguration

    -(Appears on:RSMSpec, InstanceSetSpec) +(Appears on:InstanceSetSpec)

    @@ -23006,7 +21887,7 @@ int32

    ReplicaRole

    -(Appears on:RSMSpec, InstanceSetSpec, MemberStatus) +(Appears on:InstanceSetSpec, MemberStatus)

    @@ -23071,7 +21952,7 @@ bool

    RoleProbe

    -(Appears on:RSMSpec, InstanceSetSpec) +(Appears on:InstanceSetSpec)

    RoleProbe defines how to observe role

    diff --git a/pkg/constant/labels.go b/pkg/constant/labels.go index ebe156088d00..739307ff00c9 100644 --- a/pkg/constant/labels.go +++ b/pkg/constant/labels.go @@ -50,7 +50,6 @@ const ( VolumeClaimTemplateNameLabelKey = "apps.kubeblocks.io/vct-name" KBAppComponentInstanceTemplateLabelKey = "apps.kubeblocks.io/instance-template" KBAppServiceVersionKey = "apps.kubeblocks.io/service-version" - WorkloadTypeLabelKey = "apps.kubeblocks.io/workload-type" KBAppPodNameLabelKey = "apps.kubeblocks.io/pod-name" ClusterDefLabelKey = "clusterdefinition.kubeblocks.io/name" ComponentDefinitionLabelKey = "componentdefinition.kubeblocks.io/name" @@ -131,14 +130,6 @@ func GetShardingNameLabel(shardingName string) map[string]string { } } -// GetClusterCompDefLabel returns the label for ClusterComponentDefinition (refer clusterDefinition.Spec.ComponentDefs[*].Name) -// TODO:ClusterCompDef will be deprecated in the future -func GetClusterCompDefLabel(clusterCompDefName string) map[string]string { - return map[string]string{ - AppComponentLabelKey: clusterCompDefName, - } -} - // GetKBReservedLabelKeys returns the reserved label keys for KubeBlocks func GetKBReservedLabelKeys() []string { return []string{ diff --git a/pkg/constant/pattern.go b/pkg/constant/pattern.go index ba466a90c367..3e2255b2ddea 100644 --- a/pkg/constant/pattern.go +++ b/pkg/constant/pattern.go @@ -89,11 +89,6 @@ func GeneratePodName(clusterName, compName string, ordinal int) string { return fmt.Sprintf("%s-%d", GenerateClusterComponentName(clusterName, compName), ordinal) } -// GenerateVirtualComponentDefinition generates the virtual component definition name. -func GenerateVirtualComponentDefinition(compDefSuffix string) string { - return fmt.Sprintf("%s-%s", KBGeneratedVirtualCompDefPrefix, compDefSuffix) -} - // GenerateResourceNameWithScalingSuffix generates name with '-scaling' suffix. func GenerateResourceNameWithScalingSuffix(name string) string { return fmt.Sprintf("%s-%s", name, SlashScalingLowerSuffix) diff --git a/pkg/controller/apiconversion/simplified_cluster_api.go b/pkg/controller/apiconversion/simplified_cluster_api.go deleted file mode 100644 index 4eeeec23c660..000000000000 --- a/pkg/controller/apiconversion/simplified_cluster_api.go +++ /dev/null @@ -1,193 +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 apiconversion - -import ( - "strings" - - "github.com/spf13/viper" - corev1 "k8s.io/api/core/v1" - - appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" - "github.com/apecloud/kubeblocks/pkg/constant" -) - -// HandleSimplifiedClusterAPI handles simplified api for legacy cluster. -func HandleSimplifiedClusterAPI(clusterDef *appsv1alpha1.ClusterDefinition, cluster *appsv1alpha1.Cluster) *appsv1alpha1.ClusterComponentSpec { - if hasClusterCompDefined(cluster) { - return nil - } - if !HasSimplifiedClusterAPI(cluster) { - return nil - } - if len(clusterDef.Spec.ComponentDefs) == 0 { - return nil - } - // fill simplified api only to first defined component - return fillSimplifiedClusterAPI(cluster, &clusterDef.Spec.ComponentDefs[0]) -} - -func hasClusterCompDefined(cluster *appsv1alpha1.Cluster) bool { - return cluster.Spec.ComponentSpecs != nil && len(cluster.Spec.ComponentSpecs) > 0 -} - -func HasSimplifiedClusterAPI(cluster *appsv1alpha1.Cluster) bool { - return cluster.Spec.Replicas != nil || - !cluster.Spec.Resources.CPU.IsZero() || - !cluster.Spec.Resources.Memory.IsZero() || - !cluster.Spec.Storage.Size.IsZero() || - // cluster.Spec.Monitor.MonitoringInterval != nil || - cluster.Spec.Network != nil || - len(cluster.Spec.Tenancy) > 0 || - len(cluster.Spec.AvailabilityPolicy) > 0 -} - -func fillSimplifiedClusterAPI(cluster *appsv1alpha1.Cluster, clusterCompDef *appsv1alpha1.ClusterComponentDefinition) *appsv1alpha1.ClusterComponentSpec { - clusterCompSpec := &appsv1alpha1.ClusterComponentSpec{ - Name: clusterCompDef.Name, - ComponentDefRef: clusterCompDef.Name, - } - if cluster.Spec.Replicas != nil { - clusterCompSpec.Replicas = *cluster.Spec.Replicas - } - dataVolumeName := "data" - if !cluster.Spec.Resources.CPU.IsZero() || !cluster.Spec.Resources.Memory.IsZero() { - clusterCompSpec.Resources.Limits = corev1.ResourceList{} - } - if !cluster.Spec.Resources.CPU.IsZero() { - clusterCompSpec.Resources.Limits["cpu"] = cluster.Spec.Resources.CPU - } - if !cluster.Spec.Resources.Memory.IsZero() { - clusterCompSpec.Resources.Limits["memory"] = cluster.Spec.Resources.Memory - } - if !cluster.Spec.Storage.Size.IsZero() { - clusterCompSpec.VolumeClaimTemplates = []appsv1alpha1.ClusterComponentVolumeClaimTemplate{ - { - Name: dataVolumeName, - Spec: appsv1alpha1.PersistentVolumeClaimSpec{ - AccessModes: []corev1.PersistentVolumeAccessMode{ - corev1.ReadWriteOnce, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - "storage": cluster.Spec.Storage.Size, - }, - }, - }, - }, - } - } - // if cluster.Spec.Monitor.MonitoringInterval != nil { - // if len(cluster.Spec.Monitor.MonitoringInterval.StrVal) == 0 && cluster.Spec.Monitor.MonitoringInterval.IntVal == 0 { - // clusterCompSpec.Monitor = false - // } else { - // clusterCompSpec.Monitor = true - // // TODO: should also set interval - // } - // } - if cluster.Spec.Network != nil { - clusterCompSpec.Services = []appsv1alpha1.ClusterComponentService{} - if cluster.Spec.Network.HostNetworkAccessible { - svc := appsv1alpha1.ClusterComponentService{ - Name: "vpc", - ServiceType: "LoadBalancer", - } - switch getCloudProvider() { - case cloudProviderAWS: - svc.Annotations = map[string]string{ - "service.beta.kubernetes.io/aws-load-balancer-type": "nlb", - "service.beta.kubernetes.io/aws-load-balancer-internal": "true", - } - case cloudProviderGCP: - svc.Annotations = map[string]string{ - "networking.gke.io/load-balancer-type": "Internal", - } - case cloudProviderAliyun: - svc.Annotations = map[string]string{ - "service.beta.kubernetes.io/alibaba-cloud-loadbalancer-address-type": "intranet", - } - case cloudProviderAzure: - svc.Annotations = map[string]string{ - "service.beta.kubernetes.io/azure-load-balancer-internal": "true", - } - } - clusterCompSpec.Services = append(clusterCompSpec.Services, svc) - } - if cluster.Spec.Network.PubliclyAccessible { - svc := appsv1alpha1.ClusterComponentService{ - Name: "public", - ServiceType: "LoadBalancer", - } - switch getCloudProvider() { - case cloudProviderAWS: - svc.Annotations = map[string]string{ - "service.beta.kubernetes.io/aws-load-balancer-type": "nlb", - "service.beta.kubernetes.io/aws-load-balancer-internal": "false", - } - case cloudProviderAliyun: - svc.Annotations = map[string]string{ - "service.beta.kubernetes.io/alibaba-cloud-loadbalancer-address-type": "internet", - } - case cloudProviderAzure: - svc.Annotations = map[string]string{ - "service.beta.kubernetes.io/azure-load-balancer-internal": "false", - } - } - clusterCompSpec.Services = append(clusterCompSpec.Services, svc) - } - } - - if len(cluster.Spec.Tenancy) > 0 || len(cluster.Spec.AvailabilityPolicy) > 0 { - clusterCompSpec.Affinity = &appsv1alpha1.Affinity{ - PodAntiAffinity: appsv1alpha1.Preferred, - TopologyKeys: []string{affinityTopologyKey(cluster.Spec.AvailabilityPolicy)}, - Tenancy: cluster.Spec.Tenancy, - } - } - - return clusterCompSpec -} - -func getCloudProvider() cloudProvider { - k8sVersion := viper.GetString(constant.CfgKeyServerInfo) - if strings.Contains(k8sVersion, "eks") { - return cloudProviderAWS - } - if strings.Contains(k8sVersion, "gke") { - return cloudProviderGCP - } - if strings.Contains(k8sVersion, "aliyun") { - return cloudProviderAliyun - } - if strings.Contains(k8sVersion, "tke") { - return cloudProviderTencent - } - return cloudProviderUnknown -} - -func affinityTopologyKey(policyType appsv1alpha1.AvailabilityPolicyType) string { - switch policyType { - case appsv1alpha1.AvailabilityPolicyZone: - return "topology.kubernetes.io/zone" - case appsv1alpha1.AvailabilityPolicyNode: - return "kubernetes.io/hostname" - } - return "" -} diff --git a/pkg/controller/apiconversion/type.go b/pkg/controller/apiconversion/type.go deleted file mode 100644 index cdf6e554f6fb..000000000000 --- a/pkg/controller/apiconversion/type.go +++ /dev/null @@ -1,31 +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 apiconversion - -type cloudProvider string - -const ( - cloudProviderAWS cloudProvider = "aws" - cloudProviderGCP cloudProvider = "gcp" - cloudProviderAliyun cloudProvider = "aliyun" - cloudProviderAzure cloudProvider = "azure" - cloudProviderTencent cloudProvider = "tencent" - cloudProviderUnknown cloudProvider = "unknown" -) diff --git a/pkg/controller/component/action_post_provision_test.go b/pkg/controller/component/action_post_provision_test.go index cc6f2b02bd3f..6f555f0b291c 100644 --- a/pkg/controller/component/action_post_provision_test.go +++ b/pkg/controller/component/action_post_provision_test.go @@ -41,25 +41,24 @@ import ( var _ = Describe("Component PostProvision Test", func() { Context("has the BuildComponent function", func() { const ( - clusterDefName = "test-clusterdef" - clusterName = "test-cluster" - mysqlCompDefName = "replicasets" - mysqlCompName = "mysql" + compDefName = "test-compdef" + clusterName = "test-cluster" + mysqlCompName = "mysql" ) var ( - clusterDef *appsv1alpha1.ClusterDefinition - cluster *appsv1alpha1.Cluster + compDef *appsv1alpha1.ComponentDefinition + cluster *appsv1alpha1.Cluster ) BeforeEach(func() { - clusterDef = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). + compDef = testapps.NewComponentDefinitionFactory(compDefName). + SetDefaultSpec(). GetObject() pvcSpec := testapps.NewPVCSpec("1Gi") - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). SetUID(clusterName). - AddComponent(mysqlCompName, mysqlCompDefName). + AddComponent(mysqlCompName, compDefName). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). GetObject() }) @@ -101,22 +100,17 @@ var _ = Describe("Component PostProvision Test", func() { Ctx: ctx, Log: tlog, } - synthesizeComp, err := BuildSynthesizedComponentWrapper4Test( - reqCtx, - testCtx.Cli, - clusterDef, - cluster, - &cluster.Spec.ComponentSpecs[0]) - Expect(err).Should(Succeed()) - Expect(synthesizeComp).ShouldNot(BeNil()) - Expect(synthesizeComp.LifecycleActions).ShouldNot(BeNil()) - Expect(synthesizeComp.LifecycleActions.PostProvision).Should(BeNil()) - // graphCli := model.NewGraphClient(k8sClient) comp, err := BuildComponent(cluster, &cluster.Spec.ComponentSpecs[0], nil, nil) - comp.UID = cluster.UID Expect(err).Should(Succeed()) Expect(comp).ShouldNot(BeNil()) + comp.UID = cluster.UID + + synthesizeComp, err := BuildSynthesizedComponent(reqCtx, testCtx.Cli, cluster, compDef, comp) + Expect(err).Should(Succeed()) + Expect(synthesizeComp).ShouldNot(BeNil()) + Expect(synthesizeComp.LifecycleActions).ShouldNot(BeNil()) + Expect(synthesizeComp.LifecycleActions.PostProvision).ShouldNot(BeNil()) dag := graph.NewDAG() dag.AddVertex(&model.ObjectVertex{Obj: cluster, Action: model.ActionUpdatePtr()}) diff --git a/pkg/controller/component/action_pre_terminate_test.go b/pkg/controller/component/action_pre_terminate_test.go index a8c7f5cc8c56..eb3db743b485 100644 --- a/pkg/controller/component/action_pre_terminate_test.go +++ b/pkg/controller/component/action_pre_terminate_test.go @@ -41,25 +41,24 @@ import ( var _ = Describe("Component PreTerminate Test", func() { Context("has the BuildComponent function", func() { const ( - clusterDefName = "test-clusterdef" - clusterName = "test-cluster" - mysqlCompDefName = "replicasets" - mysqlCompName = "mysql" + compDefName = "test-compdef" + clusterName = "test-cluster" + mysqlCompName = "mysql" ) var ( - clusterDef *appsv1alpha1.ClusterDefinition - cluster *appsv1alpha1.Cluster + compDef *appsv1alpha1.ComponentDefinition + cluster *appsv1alpha1.Cluster ) BeforeEach(func() { - clusterDef = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). + compDef = testapps.NewComponentDefinitionFactory(compDefName). + SetDefaultSpec(). GetObject() pvcSpec := testapps.NewPVCSpec("1Gi") - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). SetUID(clusterName). - AddComponent(mysqlCompName, mysqlCompDefName). + AddComponent(mysqlCompName, compDefName). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). GetObject() }) @@ -101,16 +100,6 @@ var _ = Describe("Component PreTerminate Test", func() { Ctx: ctx, Log: tlog, } - synthesizeComp, err := BuildSynthesizedComponentWrapper4Test( - reqCtx, - testCtx.Cli, - clusterDef, - cluster, - &cluster.Spec.ComponentSpecs[0]) - Expect(err).Should(Succeed()) - Expect(synthesizeComp).ShouldNot(BeNil()) - Expect(synthesizeComp.LifecycleActions).ShouldNot(BeNil()) - Expect(synthesizeComp.LifecycleActions.PreTerminate).Should(BeNil()) comp, err := BuildComponent(cluster, &cluster.Spec.ComponentSpecs[0], nil, nil) comp.UID = cluster.UID @@ -118,6 +107,12 @@ var _ = Describe("Component PreTerminate Test", func() { Expect(comp).ShouldNot(BeNil()) // graphCli := model.NewGraphClient(k8sClient) + synthesizeComp, err := BuildSynthesizedComponent(reqCtx, testCtx.Cli, cluster, compDef, comp) + Expect(err).Should(Succeed()) + Expect(synthesizeComp).ShouldNot(BeNil()) + Expect(synthesizeComp.LifecycleActions).ShouldNot(BeNil()) + Expect(synthesizeComp.LifecycleActions.PreTerminate).ShouldNot(BeNil()) + By("test component without preTerminate action and no need to do PreTerminate action") dag := graph.NewDAG() dag.AddVertex(&model.ObjectVertex{Obj: cluster, Action: model.ActionUpdatePtr()}) diff --git a/pkg/controller/component/action_utils_test.go b/pkg/controller/component/action_utils_test.go index 7a204e100d60..9bf6718ae0c3 100644 --- a/pkg/controller/component/action_utils_test.go +++ b/pkg/controller/component/action_utils_test.go @@ -43,25 +43,24 @@ var tlog = ctrl.Log.WithName("component_testing") var _ = Describe("Component LifeCycle Action Utils Test", func() { Context("has the BuildComponent function", func() { const ( - clusterDefName = "test-clusterdef" - clusterName = "test-cluster" - mysqlCompDefName = "replicasets" - mysqlCompName = "mysql" + compDefName = "test-compdef" + clusterName = "test-cluster" + mysqlCompName = "mysql" ) var ( - clusterDef *appsv1alpha1.ClusterDefinition - cluster *appsv1alpha1.Cluster + compDef *appsv1alpha1.ComponentDefinition + cluster *appsv1alpha1.Cluster ) BeforeEach(func() { - clusterDef = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). + compDef = testapps.NewComponentDefinitionFactory(compDefName). + SetDefaultSpec(). GetObject() pvcSpec := testapps.NewPVCSpec("1Gi") - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). SetUID(clusterName). - AddComponent(mysqlCompName, mysqlCompDefName). + AddComponent(mysqlCompName, compDefName). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). GetObject() }) @@ -103,22 +102,18 @@ var _ = Describe("Component LifeCycle Action Utils Test", func() { Ctx: ctx, Log: tlog, } - synthesizeComp, err := BuildSynthesizedComponentWrapper4Test( - reqCtx, - testCtx.Cli, - clusterDef, - cluster, - &cluster.Spec.ComponentSpecs[0]) - Expect(err).Should(Succeed()) - Expect(synthesizeComp).ShouldNot(BeNil()) - Expect(synthesizeComp.LifecycleActions).ShouldNot(BeNil()) - Expect(synthesizeComp.LifecycleActions.PostProvision).Should(BeNil()) comp, err := BuildComponent(cluster, &cluster.Spec.ComponentSpecs[0], nil, nil) comp.UID = cluster.UID Expect(err).Should(Succeed()) Expect(comp).ShouldNot(BeNil()) + synthesizeComp, err := BuildSynthesizedComponent(reqCtx, testCtx.Cli, cluster, compDef, comp) + Expect(err).Should(Succeed()) + Expect(synthesizeComp).ShouldNot(BeNil()) + Expect(synthesizeComp.LifecycleActions).ShouldNot(BeNil()) + Expect(synthesizeComp.LifecycleActions.PostProvision).ShouldNot(BeNil()) + dag := graph.NewDAG() dag.AddVertex(&model.ObjectVertex{Obj: cluster, Action: model.ActionUpdatePtr()}) actionCtx, err := NewActionContext(cluster, comp, nil, synthesizeComp.LifecycleActions, synthesizeComp.ScriptTemplates, PostProvisionAction) diff --git a/pkg/controller/component/component.go b/pkg/controller/component/component.go index 705086b597c4..49474c039797 100644 --- a/pkg/controller/component/component.go +++ b/pkg/controller/component/component.go @@ -32,7 +32,6 @@ import ( appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" "github.com/apecloud/kubeblocks/pkg/common" "github.com/apecloud/kubeblocks/pkg/constant" - "github.com/apecloud/kubeblocks/pkg/controller/apiconversion" "github.com/apecloud/kubeblocks/pkg/controller/builder" "github.com/apecloud/kubeblocks/pkg/controller/scheduling" intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" @@ -121,25 +120,12 @@ func BuildComponent(cluster *appsv1alpha1.Cluster, compSpec *appsv1alpha1.Cluste return compBuilder.GetObject(), nil } -func BuildComponentDefinition(clusterDef *appsv1alpha1.ClusterDefinition, - clusterCompSpec *appsv1alpha1.ClusterComponentSpec) (*appsv1alpha1.ComponentDefinition, error) { - clusterCompDef, err := getClusterCompDef(clusterDef, clusterCompSpec) - if err != nil { - return nil, err - } - compDef, err := buildComponentDefinitionByConversion(clusterCompDef) - if err != nil { - return nil, err - } - return compDef, nil -} - func getOrBuildComponentDefinition(ctx context.Context, cli client.Reader, clusterDef *appsv1alpha1.ClusterDefinition, cluster *appsv1alpha1.Cluster, clusterCompSpec *appsv1alpha1.ClusterComponentSpec) (*appsv1alpha1.ComponentDefinition, error) { - if len(cluster.Spec.ClusterDefRef) > 0 && len(clusterCompSpec.ComponentDefRef) > 0 { - return BuildComponentDefinition(clusterDef, clusterCompSpec) + if len(cluster.Spec.ClusterDefRef) > 0 && len(clusterCompSpec.ComponentDefRef) > 0 && len(clusterCompSpec.ComponentDef) == 0 { + return nil, fmt.Errorf("legacy cluster component definition is not supported any more") } if len(clusterCompSpec.ComponentDef) > 0 { compDef := &appsv1alpha1.ComponentDefinition{} @@ -172,18 +158,6 @@ func getClusterReferencedResources(ctx context.Context, cli client.Reader, return clusterDef, nil } -func getClusterCompDef(clusterDef *appsv1alpha1.ClusterDefinition, - clusterCompSpec *appsv1alpha1.ClusterComponentSpec) (*appsv1alpha1.ClusterComponentDefinition, error) { - if len(clusterCompSpec.ComponentDefRef) == 0 { - return nil, fmt.Errorf("cluster component definition ref is empty: %s", clusterCompSpec.Name) - } - clusterCompDef := clusterDef.GetComponentDefByName(clusterCompSpec.ComponentDefRef) - if clusterCompDef == nil { - return nil, fmt.Errorf("referenced cluster component definition is not defined: %s", clusterCompSpec.ComponentDefRef) - } - return clusterCompDef, nil -} - func getClusterCompSpec4Component(ctx context.Context, cli client.Reader, clusterDef *appsv1alpha1.ClusterDefinition, cluster *appsv1alpha1.Cluster, comp *appsv1alpha1.Component) (*appsv1alpha1.ClusterComponentSpec, error) { @@ -198,7 +172,7 @@ func getClusterCompSpec4Component(ctx context.Context, cli client.Reader, if compSpec != nil { return compSpec, nil } - return apiconversion.HandleSimplifiedClusterAPI(clusterDef, cluster), nil + return nil, fmt.Errorf("cluster component spec is not found for component: %s", comp.Name) } func getCompLabelValue(comp *appsv1alpha1.Component, label string) (string, error) { diff --git a/pkg/controller/component/component_test.go b/pkg/controller/component/component_test.go index 781b54cf32d1..4cc13ce42f5c 100644 --- a/pkg/controller/component/component_test.go +++ b/pkg/controller/component/component_test.go @@ -54,7 +54,7 @@ var _ = Describe("Component", func() { SetDefaultSpec(). GetObject() cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). - AddComponentV2(mysqlCompName, compDef.GetName()). + AddComponent(mysqlCompName, compDef.GetName()). AddVolumeClaimTemplate(testapps.DataVolumeName, testapps.NewPVCSpec("1Gi")). GetObject() diff --git a/pkg/controller/component/definition_convertor.go b/pkg/controller/component/definition_convertor.go deleted file mode 100644 index 54d6756821f5..000000000000 --- a/pkg/controller/component/definition_convertor.go +++ /dev/null @@ -1,497 +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 ( - "fmt" - - appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" - workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" - "github.com/apecloud/kubeblocks/pkg/apiutil" - "github.com/apecloud/kubeblocks/pkg/constant" -) - -// TODO(component): type check - -// buildComponentDefinitionByConversion builds a ComponentDefinition from a ClusterComponentDefinition and a ClusterComponentVersion. -func buildComponentDefinitionByConversion(clusterCompDef *appsv1alpha1.ClusterComponentDefinition) (*appsv1alpha1.ComponentDefinition, error) { - if clusterCompDef == nil { - return nil, nil - } - convertors := map[string]convertor{ - "provider": &compDefProviderConvertor{}, - "description": &compDefDescriptionConvertor{}, - "servicekind": &compDefServiceKindConvertor{}, - "serviceversion": &compDefServiceVersionConvertor{}, - "runtime": &compDefRuntimeConvertor{}, - "vars": &compDefVarsConvertor{}, - "volumes": &compDefVolumesConvertor{}, - "hostnetwork": &compDefHostNetworkConvertor{}, - "services": &compDefServicesConvertor{}, - "configs": &compDefConfigsConvertor{}, - "logconfigs": &compDefLogConfigsConvertor{}, - "scripts": &compDefScriptsConvertor{}, - "policyrules": &compDefPolicyRulesConvertor{}, - "labels": &compDefLabelsConvertor{}, - "replicasLimit": &compDefReplicasLimitConvertor{}, - "systemaccounts": &compDefSystemAccountsConvertor{}, - "updatestrategy": &compDefUpdateStrategyConvertor{}, - "roles": &compDefRolesConvertor{}, - "lifecycleactions": &compDefLifecycleActionsConvertor{}, - "servicerefdeclarations": &compDefServiceRefDeclarationsConvertor{}, - "exporter": &compDefExporterConvertor{}, - } - compDef := &appsv1alpha1.ComponentDefinition{} - if err := covertObject(convertors, &compDef.Spec, clusterCompDef); err != nil { - return nil, err - } - return compDef, nil -} - -// compDefProviderConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.Provider. -type compDefProviderConvertor struct{} - -func (c *compDefProviderConvertor) convert(args ...any) (any, error) { - return "", nil -} - -// compDefDescriptionConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.Description. -type compDefDescriptionConvertor struct{} - -func (c *compDefDescriptionConvertor) convert(args ...any) (any, error) { - return "", nil -} - -// compDefServiceKindConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.ServiceKind. -type compDefServiceKindConvertor struct{} - -func (c *compDefServiceKindConvertor) convert(args ...any) (any, error) { - return "", nil -} - -// compDefServiceVersionConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.ServiceVersion. -type compDefServiceVersionConvertor struct{} - -func (c *compDefServiceVersionConvertor) convert(args ...any) (any, error) { - return "", nil -} - -// compDefRuntimeConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.Runtime. -type compDefRuntimeConvertor struct{} - -func (c *compDefRuntimeConvertor) convert(args ...any) (any, error) { - clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - if clusterCompDef.PodSpec == nil { - return nil, fmt.Errorf("no pod spec") - } - podSpec := clusterCompDef.PodSpec.DeepCopy() - return *podSpec, nil -} - -type compDefVarsConvertor struct{} - -func (c *compDefVarsConvertor) convert(args ...any) (any, error) { - clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - return c.convertHostNetworkVars(clusterCompDef), nil -} - -func (c *compDefVarsConvertor) convertHostNetworkVars(clusterCompDef *appsv1alpha1.ClusterComponentDefinition) []appsv1alpha1.EnvVar { - hostNetwork, err := convertHostNetwork(clusterCompDef) - if err != nil || hostNetwork == nil || len(hostNetwork.ContainerPorts) == 0 { - return nil - } - vars := make([]appsv1alpha1.EnvVar, 0) - for _, cc := range hostNetwork.ContainerPorts { - for _, port := range cc.Ports { - vars = append(vars, appsv1alpha1.EnvVar{ - Name: apiutil.HostNetworkDynamicPortVarName(cc.Container, port), - ValueFrom: &appsv1alpha1.VarSource{ - HostNetworkVarRef: &appsv1alpha1.HostNetworkVarSelector{ - ClusterObjectReference: appsv1alpha1.ClusterObjectReference{ - Optional: func() *bool { optional := false; return &optional }(), - }, - HostNetworkVars: appsv1alpha1.HostNetworkVars{ - Container: &appsv1alpha1.ContainerVars{ - Name: cc.Container, - Port: &appsv1alpha1.NamedVar{ - Name: port, - Option: &appsv1alpha1.VarRequired, - }, - }, - }, - }, - }, - }) - } - } - return vars -} - -// compDefVolumesConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.Volumes. -type compDefVolumesConvertor struct{} - -func (c *compDefVolumesConvertor) convert(args ...any) (any, error) { - return nil, nil -} - -// compDefHostNetworkConvertor converts the given object into ComponentDefinition.Spec.HostNetwork. -type compDefHostNetworkConvertor struct{} - -func (c *compDefHostNetworkConvertor) convert(args ...any) (any, error) { - clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - return convertHostNetwork(clusterCompDef) -} - -func convertHostNetwork(clusterCompDef *appsv1alpha1.ClusterComponentDefinition) (*appsv1alpha1.HostNetwork, error) { - if clusterCompDef.PodSpec == nil || !clusterCompDef.PodSpec.HostNetwork { - return nil, nil - } - - hostNetwork := &appsv1alpha1.HostNetwork{ - ContainerPorts: []appsv1alpha1.HostNetworkContainerPort{}, - } - for _, container := range clusterCompDef.PodSpec.Containers { - cp := appsv1alpha1.HostNetworkContainerPort{ - Container: container.Name, - Ports: []string{}, - } - for _, port := range container.Ports { - if apiutil.IsHostNetworkDynamicPort(port.ContainerPort) { - cp.Ports = append(cp.Ports, port.Name) - } - } - if len(cp.Ports) > 0 { - hostNetwork.ContainerPorts = append(hostNetwork.ContainerPorts, cp) - } - } - return hostNetwork, nil -} - -// compDefServicesConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.Services. -type compDefServicesConvertor struct{} - -func (c *compDefServicesConvertor) convert(args ...any) (any, error) { - return nil, nil -} - -// compDefConfigsConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.Configs. -type compDefConfigsConvertor struct{} - -func (c *compDefConfigsConvertor) convert(args ...any) (any, error) { - return nil, nil -} - -// compDefLogConfigsConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.LogConfigs. -type compDefLogConfigsConvertor struct{} - -func (c *compDefLogConfigsConvertor) convert(args ...any) (any, error) { - return nil, nil -} - -// compDefScriptsConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.Scripts. -type compDefScriptsConvertor struct{} - -func (c *compDefScriptsConvertor) convert(args ...any) (any, error) { - return nil, nil -} - -// compDefPolicyRulesConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.PolicyRules. -type compDefPolicyRulesConvertor struct{} - -func (c *compDefPolicyRulesConvertor) convert(args ...any) (any, error) { - return nil, nil -} - -// compDefLabelsConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.Labels. -type compDefLabelsConvertor struct{} - -func (c *compDefLabelsConvertor) convert(args ...any) (any, error) { - return nil, nil -} - -type compDefReplicasLimitConvertor struct{} - -func (c *compDefReplicasLimitConvertor) convert(args ...any) (any, error) { - return nil, nil -} - -// compDefSystemAccountsConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.SystemAccounts. -type compDefSystemAccountsConvertor struct{} - -func (c *compDefSystemAccountsConvertor) convert(args ...any) (any, error) { - return nil, nil -} - -// compDefUpdateStrategyConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.UpdateStrategy. -type compDefUpdateStrategyConvertor struct{} - -func (c *compDefUpdateStrategyConvertor) convert(args ...any) (any, error) { - clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - var strategy *appsv1alpha1.UpdateStrategy - switch clusterCompDef.WorkloadType { - case appsv1alpha1.Consensus: - if clusterCompDef.RSMSpec != nil && clusterCompDef.RSMSpec.MemberUpdateStrategy != nil { - strategy = func() *appsv1alpha1.UpdateStrategy { - s := appsv1alpha1.UpdateStrategy(*clusterCompDef.RSMSpec.MemberUpdateStrategy) - return &s - }() - } - if clusterCompDef.ConsensusSpec != nil { - strategy = &clusterCompDef.ConsensusSpec.UpdateStrategy - } - case appsv1alpha1.Replication: - // be compatible with the behaviour of RSM in 0.7, set SerialStrategy for Replication workloads by default. - serialStrategy := appsv1alpha1.SerialStrategy - strategy = &serialStrategy - // be compatible with the behaviour of RSM in 0.7, don't set update strategy for Stateful and Stateless workloads. - case appsv1alpha1.Stateful: - // do nothing - case appsv1alpha1.Stateless: - // do nothing - default: - panic(fmt.Sprintf("unknown workload type: %s", clusterCompDef.WorkloadType)) - } - return strategy, nil -} - -// compDefRolesConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.Roles. -type compDefRolesConvertor struct{} - -func (c *compDefRolesConvertor) convert(args ...any) (any, error) { - clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - - // if rsm spec is not nil, convert rsm role first. - if clusterCompDef.RSMSpec != nil { - return c.convertInstanceSetRole(clusterCompDef) - } - - switch clusterCompDef.WorkloadType { - case appsv1alpha1.Consensus: - return c.convertConsensusRole(clusterCompDef) - case appsv1alpha1.Replication: - defaultRoles := []appsv1alpha1.ReplicaRole{ - { - Name: constant.Primary, - Serviceable: true, - Writable: true, - Votable: true, - }, - { - Name: constant.Secondary, - Serviceable: true, - Writable: false, - Votable: true, - }, - } - return defaultRoles, nil - case appsv1alpha1.Stateful: - return nil, nil - case appsv1alpha1.Stateless: - return nil, nil - default: - panic(fmt.Sprintf("unknown workload type: %s", clusterCompDef.WorkloadType)) - } -} - -func (c *compDefRolesConvertor) convertInstanceSetRole(clusterCompDef *appsv1alpha1.ClusterComponentDefinition) (any, error) { - if clusterCompDef.RSMSpec == nil { - return nil, nil - } - - roles := make([]appsv1alpha1.ReplicaRole, 0) - for _, workloadRole := range clusterCompDef.RSMSpec.Roles { - roles = append(roles, appsv1alpha1.ReplicaRole{ - Name: workloadRole.Name, - Serviceable: workloadRole.AccessMode != workloads.NoneMode, - Writable: workloadRole.AccessMode == workloads.ReadWriteMode, - Votable: workloadRole.CanVote, - }) - } - - return roles, nil -} - -func (c *compDefRolesConvertor) convertConsensusRole(clusterCompDef *appsv1alpha1.ClusterComponentDefinition) (any, error) { - if clusterCompDef.ConsensusSpec == nil { - return nil, nil - } - - roles := make([]appsv1alpha1.ReplicaRole, 0) - addRole := func(member appsv1alpha1.ConsensusMember, votable bool) { - roles = append(roles, appsv1alpha1.ReplicaRole{ - Name: member.Name, - Serviceable: member.AccessMode != appsv1alpha1.None, - Writable: member.AccessMode == appsv1alpha1.ReadWrite, - Votable: votable, - }) - } - - addRole(clusterCompDef.ConsensusSpec.Leader, true) - for _, follower := range clusterCompDef.ConsensusSpec.Followers { - addRole(follower, true) - } - if clusterCompDef.ConsensusSpec.Learner != nil { - addRole(*clusterCompDef.ConsensusSpec.Learner, false) - } - - return roles, nil -} - -// compDefServiceRefDeclarationsConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.ServiceRefDeclarations. -type compDefServiceRefDeclarationsConvertor struct{} - -func (c *compDefServiceRefDeclarationsConvertor) convert(args ...any) (any, error) { - return nil, nil -} - -// compDefLifecycleActionsConvertor is an implementation of the convertor interface, used to convert the given object into ComponentDefinition.Spec.LifecycleActions. -type compDefLifecycleActionsConvertor struct{} - -func (c *compDefLifecycleActionsConvertor) convert(args ...any) (any, error) { - clusterCompDef := args[0].(*appsv1alpha1.ClusterComponentDefinition) - - lifecycleActions := &appsv1alpha1.ComponentLifecycleActions{} - - // RoleProbe can be defined in RSMSpec or ClusterComponentDefinition.Probes. - if (clusterCompDef.RSMSpec != nil && clusterCompDef.RSMSpec.RoleProbe != nil) || (clusterCompDef.Probes != nil && clusterCompDef.Probes.RoleProbe != nil) { - lifecycleActions.RoleProbe = c.convertRoleProbe(clusterCompDef) - } - - if clusterCompDef.SwitchoverSpec != nil { - lifecycleActions.Switchover = c.convertSwitchover(clusterCompDef.SwitchoverSpec) - } - - lifecycleActions.PreTerminate = nil - lifecycleActions.MemberJoin = nil - lifecycleActions.MemberLeave = nil - lifecycleActions.Readonly = nil - lifecycleActions.Readwrite = nil - lifecycleActions.DataDump = nil - lifecycleActions.DataLoad = nil - lifecycleActions.Reconfigure = nil - lifecycleActions.AccountProvision = nil - - return lifecycleActions, nil // TODO -} - -func (c *compDefLifecycleActionsConvertor) convertRoleProbe(clusterCompDef *appsv1alpha1.ClusterComponentDefinition) *appsv1alpha1.Probe { - builtinHandler := appsv1alpha1.UnknownBuiltinActionHandler - // if RSMSpec has role probe CustomHandler, use it first. - if clusterCompDef.RSMSpec != nil && clusterCompDef.RSMSpec.RoleProbe != nil && len(clusterCompDef.RSMSpec.RoleProbe.CustomHandler) > 0 { - // TODO(xingran): RSMSpec.RoleProbe.CustomHandler support multiple images and commands, but ComponentDefinition.LifeCycleAction.RoleProbe only support one image and command now. - return &appsv1alpha1.Probe{ - BuiltinHandler: &builtinHandler, - Action: appsv1alpha1.Action{ - Exec: &appsv1alpha1.ExecAction{ - Image: clusterCompDef.RSMSpec.RoleProbe.CustomHandler[0].Image, - Command: clusterCompDef.RSMSpec.RoleProbe.CustomHandler[0].Command, - Args: clusterCompDef.RSMSpec.RoleProbe.CustomHandler[0].Args, - }, - }, - } - } - - if clusterCompDef == nil || clusterCompDef.Probes == nil || clusterCompDef.Probes.RoleProbe == nil { - return nil - } - - clusterCompDefRoleProbe := clusterCompDef.Probes.RoleProbe - roleProbe := &appsv1alpha1.Probe{ - Action: appsv1alpha1.Action{ - TimeoutSeconds: clusterCompDefRoleProbe.TimeoutSeconds, - }, - PeriodSeconds: clusterCompDefRoleProbe.PeriodSeconds, - } - - roleProbe.BuiltinHandler = &builtinHandler - if clusterCompDefRoleProbe.Commands == nil || len(clusterCompDefRoleProbe.Commands.Queries) == 0 { - return roleProbe - } - - commands := clusterCompDefRoleProbe.Commands.Writes - if len(clusterCompDefRoleProbe.Commands.Writes) == 0 { - commands = clusterCompDefRoleProbe.Commands.Queries - } - roleProbe.Action.Exec = &appsv1alpha1.ExecAction{ - Command: commands, - } - return roleProbe -} - -func (c *compDefLifecycleActionsConvertor) convertSwitchover(switchover *appsv1alpha1.SwitchoverSpec) *appsv1alpha1.ComponentSwitchover { - spec := *switchover - if spec.WithCandidate == nil && spec.WithoutCandidate == nil { - return nil - } - - var ( - withCandidateAction *appsv1alpha1.Action - withoutCandidateAction *appsv1alpha1.Action - ) - if spec.WithCandidate != nil && spec.WithCandidate.CmdExecutorConfig != nil { - withCandidateAction = &appsv1alpha1.Action{ - Exec: &appsv1alpha1.ExecAction{ - Image: spec.WithCandidate.CmdExecutorConfig.Image, - Command: spec.WithCandidate.CmdExecutorConfig.Command, - Args: spec.WithCandidate.CmdExecutorConfig.Args, - Env: spec.WithCandidate.CmdExecutorConfig.Env, - }, - } - } - if spec.WithoutCandidate != nil && spec.WithoutCandidate.CmdExecutorConfig != nil { - withoutCandidateAction = &appsv1alpha1.Action{ - Exec: &appsv1alpha1.ExecAction{ - Image: spec.WithoutCandidate.CmdExecutorConfig.Image, - Command: spec.WithoutCandidate.CmdExecutorConfig.Command, - Args: spec.WithoutCandidate.CmdExecutorConfig.Args, - Env: spec.WithoutCandidate.CmdExecutorConfig.Env, - }, - } - } - - mergeScriptSpec := func() []appsv1alpha1.ScriptSpecSelector { - if len(spec.WithCandidate.ScriptSpecSelectors) == 0 && len(spec.WithoutCandidate.ScriptSpecSelectors) == 0 { - return nil - } - - mergeScriptSpecMap := map[appsv1alpha1.ScriptSpecSelector]bool{} - for _, val := range append(spec.WithCandidate.ScriptSpecSelectors, spec.WithoutCandidate.ScriptSpecSelectors...) { - mergeScriptSpecMap[val] = true - } - - scriptSpecList := make([]appsv1alpha1.ScriptSpecSelector, 0, len(mergeScriptSpecMap)) - for key := range mergeScriptSpecMap { - scriptSpecList = append(scriptSpecList, key) - } - return scriptSpecList - } - - return &appsv1alpha1.ComponentSwitchover{ - WithCandidate: withCandidateAction, - WithoutCandidate: withoutCandidateAction, - ScriptSpecSelectors: mergeScriptSpec(), - } -} - -type compDefExporterConvertor struct{} - -func (c *compDefExporterConvertor) convert(args ...any) (any, error) { - return nil, nil -} diff --git a/pkg/controller/component/definition_convertor_test.go b/pkg/controller/component/definition_convertor_test.go deleted file mode 100644 index 1da59d5df5cc..000000000000 --- a/pkg/controller/component/definition_convertor_test.go +++ /dev/null @@ -1,574 +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 ( - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - corev1 "k8s.io/api/core/v1" - - appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" - workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" - "github.com/apecloud/kubeblocks/pkg/apiutil" - "github.com/apecloud/kubeblocks/pkg/constant" - testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" -) - -var _ = Describe("Component Definition Convertor", func() { - Context("convertors", func() { - var ( - clusterCompDef *appsv1alpha1.ClusterComponentDefinition - - clusterName = "mysql-test" - - dataVolumeName = "data" - logVolumeName = "log" - - runAsUser = int64(0) - runAsNonRoot = false - ) - - commandExecutorEnvItem := &appsv1alpha1.CommandExecutorEnvItem{ - Image: testapps.ApeCloudMySQLImage, - Env: []corev1.EnvVar{ - { - Name: "user", - }, - }, - } - commandExecutorItem := &appsv1alpha1.CommandExecutorItem{ - Command: []string{"foo", "bar"}, - Args: []string{"zoo", "boo"}, - } - - BeforeEach(func() { - clusterCompDef = &appsv1alpha1.ClusterComponentDefinition{ - Name: "mysql", - WorkloadType: appsv1alpha1.Consensus, - Probes: &appsv1alpha1.ClusterDefinitionProbes{ - RoleProbe: &appsv1alpha1.ClusterDefinitionProbe{ - FailureThreshold: 3, - PeriodSeconds: 1, - TimeoutSeconds: 5, - }, - }, - PodSpec: &corev1.PodSpec{ - Volumes: []corev1.Volume{}, - Containers: []corev1.Container{ - { - Name: "mysql", - Command: []string{"/entrypoint.sh"}, - Env: []corev1.EnvVar{ - { - Name: "port", - Value: "3306", - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: dataVolumeName, - MountPath: "/data/mysql", - }, - { - Name: logVolumeName, - MountPath: "/data/log", - }, - }, - Ports: []corev1.ContainerPort{ - { - Name: "mysql", - ContainerPort: 3306, - }, - { - Name: "paxos", - ContainerPort: 13306, - }, - }, - SecurityContext: &corev1.SecurityContext{ - RunAsUser: &runAsUser, - RunAsNonRoot: &runAsNonRoot, - }, - Lifecycle: &corev1.Lifecycle{ - PreStop: &corev1.LifecycleHandler{ - Exec: &corev1.ExecAction{ - Command: []string{"/pre-stop.sh"}, - }, - }, - }, - }, - }, - }, - StatelessSpec: nil, - StatefulSpec: nil, - ConsensusSpec: &appsv1alpha1.ConsensusSetSpec{ - Leader: appsv1alpha1.ConsensusMember{ - Name: constant.Leader, - AccessMode: appsv1alpha1.ReadWrite, - }, - Followers: []appsv1alpha1.ConsensusMember{ - { - Name: constant.Follower, - AccessMode: appsv1alpha1.Readonly, - }, - }, - Learner: &appsv1alpha1.ConsensusMember{ - Name: constant.Learner, - AccessMode: appsv1alpha1.Readonly, - }, - }, - ReplicationSpec: nil, - HorizontalScalePolicy: &appsv1alpha1.HorizontalScalePolicy{}, - } - }) - - It("provider", func() { - convertor := &compDefProviderConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).Should(BeEmpty()) - }) - - It("description", func() { - convertor := &compDefDescriptionConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).Should(BeEmpty()) - }) - - It("service kind", func() { - convertor := &compDefServiceKindConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).Should(BeEmpty()) - }) - - It("service version", func() { - convertor := &compDefServiceVersionConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).Should(BeEmpty()) - }) - - Context("runtime", func() { - It("w/o pod spec", func() { - clusterCompDefCopy := clusterCompDef.DeepCopy() - clusterCompDefCopy.PodSpec = nil - - convertor := &compDefRuntimeConvertor{} - res, err := convertor.convert(clusterCompDefCopy) - Expect(err).Should(HaveOccurred()) - Expect(res).Should(BeNil()) - }) - }) - - Context("vars", func() { - It("host network ports", func() { - clusterCompDef.PodSpec.HostNetwork = true - // default ports are 3306 and 13306 - clusterCompDef.PodSpec.Containers[0].Ports[0].ContainerPort = 36 - - convertor := &compDefVarsConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).ShouldNot(BeNil()) - - vars, ok := res.([]appsv1alpha1.EnvVar) - Expect(ok).Should(BeTrue()) - Expect(vars).Should(HaveLen(1)) - - container := clusterCompDef.PodSpec.Containers[0] - expectedVar := appsv1alpha1.EnvVar{ - Name: apiutil.HostNetworkDynamicPortVarName(container.Name, container.Ports[0].Name), - ValueFrom: &appsv1alpha1.VarSource{ - HostNetworkVarRef: &appsv1alpha1.HostNetworkVarSelector{ - ClusterObjectReference: appsv1alpha1.ClusterObjectReference{ - Optional: func() *bool { optional := false; return &optional }(), - }, - HostNetworkVars: appsv1alpha1.HostNetworkVars{ - Container: &appsv1alpha1.ContainerVars{ - Name: container.Name, - Port: &appsv1alpha1.NamedVar{ - Name: container.Ports[0].Name, - Option: &appsv1alpha1.VarRequired, - }, - }, - }, - }, - }, - } - Expect(vars[0]).Should(BeEquivalentTo(expectedVar)) - }) - }) - - Context("volumes", func() { - It("ok", func() { - convertor := &compDefVolumesConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).Should(BeNil()) - }) - }) - - Context("host network", func() { - It("w/o pod spec", func() { - clusterCompDef.PodSpec = nil - - convertor := &compDefHostNetworkConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).Should(BeNil()) - }) - - It("host network disabled", func() { - clusterCompDef.PodSpec.HostNetwork = false - - convertor := &compDefHostNetworkConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).Should(BeNil()) - }) - - It("empty container ports", func() { - clusterCompDef.PodSpec.HostNetwork = true - for i := range clusterCompDef.PodSpec.Containers { - clusterCompDef.PodSpec.Containers[i].Ports = nil - } - - convertor := &compDefHostNetworkConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).ShouldNot(BeNil()) - - hostNetwork, ok := res.(*appsv1alpha1.HostNetwork) - Expect(ok).Should(BeTrue()) - Expect(hostNetwork.ContainerPorts).Should(HaveLen(0)) - }) - - It("no dynamic ports", func() { - clusterCompDef.PodSpec.HostNetwork = true - // default ports are 3306 and 13306 - - convertor := &compDefHostNetworkConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).ShouldNot(BeNil()) - - hostNetwork, ok := res.(*appsv1alpha1.HostNetwork) - Expect(ok).Should(BeTrue()) - Expect(hostNetwork.ContainerPorts).Should(HaveLen(0)) - }) - - It("part dynamic ports", func() { - clusterCompDef.PodSpec.HostNetwork = true - // default ports are 3306 and 13306 - container := clusterCompDef.PodSpec.Containers[0] - clusterCompDef.PodSpec.Containers[0].Ports[0].ContainerPort = 36 - - convertor := &compDefHostNetworkConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).ShouldNot(BeNil()) - - hostNetwork, ok := res.(*appsv1alpha1.HostNetwork) - Expect(ok).Should(BeTrue()) - Expect(hostNetwork.ContainerPorts).Should(HaveLen(1)) - Expect(hostNetwork.ContainerPorts[0].Container).Should(Equal(container.Name)) - Expect(hostNetwork.ContainerPorts[0].Ports).Should(HaveLen(1)) - Expect(hostNetwork.ContainerPorts[0].Ports[0]).Should(Equal(container.Ports[0].Name)) - }) - }) - - Context("services", func() { - It("ok", func() { - convertor := &compDefServicesConvertor{} - res, err := convertor.convert(clusterCompDef, clusterName) - Expect(err).Should(Succeed()) - Expect(res).Should(BeNil()) - }) - }) - - It("configs", func() { - convertor := &compDefConfigsConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).Should(BeNil()) - }) - - It("scripts", func() { - convertor := &compDefScriptsConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).Should(BeNil()) - }) - - It("log configs", func() { - convertor := &compDefLogConfigsConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).Should(BeNil()) - }) - - It("policy rules", func() { - convertor := &compDefPolicyRulesConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).Should(BeNil()) - }) - - It("labels", func() { - convertor := &compDefLabelsConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).Should(BeNil()) - }) - - Context("system accounts", func() { - It("ok", func() { - convertor := &compDefSystemAccountsConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).Should(BeNil()) - }) - }) - - Context("update strategy", func() { - It("w/o workload spec", func() { - clusterCompDef.ConsensusSpec = nil - - convertor := &compDefUpdateStrategyConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - - strategy := res.(*appsv1alpha1.UpdateStrategy) - Expect(strategy).Should(BeNil()) - }) - - It("ok", func() { - convertor := &compDefUpdateStrategyConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - - strategy := res.(*appsv1alpha1.UpdateStrategy) - Expect(*strategy).Should(BeEquivalentTo(clusterCompDef.ConsensusSpec.UpdateStrategy)) - }) - }) - - Context("roles", func() { - It("non-consensus workload", func() { - clusterCompDef.WorkloadType = appsv1alpha1.Stateful - - convertor := &compDefRolesConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).Should(BeNil()) - }) - - It("w/o roles", func() { - clusterCompDef.ConsensusSpec = nil - - convertor := &compDefRolesConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).Should(BeNil()) - }) - - It("w/ roles", func() { - convertor := &compDefRolesConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - - expectedRoles := []appsv1alpha1.ReplicaRole{ - { - Name: "leader", - Serviceable: true, - Writable: true, - Votable: true, - }, - { - Name: "follower", - Serviceable: true, - Writable: false, - Votable: true, - }, - { - Name: "learner", - Serviceable: true, - Writable: false, - Votable: false, - }, - } - Expect(res).Should(BeEquivalentTo(expectedRoles)) - }) - - It("InstanceSet spec roles convertor", func() { - convertor := &compDefRolesConvertor{} - clusterCompDef.RSMSpec = &appsv1alpha1.RSMSpec{ - Roles: []workloads.ReplicaRole{ - { - Name: "mock-leader", - AccessMode: workloads.ReadWriteMode, - CanVote: true, - IsLeader: true, - }, - { - Name: "mock-follower", - AccessMode: workloads.ReadonlyMode, - CanVote: true, - IsLeader: false, - }, - }, - } - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - - expectedRoles := []appsv1alpha1.ReplicaRole{ - { - Name: "mock-leader", - Serviceable: true, - Writable: true, - Votable: true, - }, - { - Name: "mock-follower", - Serviceable: true, - Writable: false, - Votable: true, - }, - } - Expect(res).Should(BeEquivalentTo(expectedRoles)) - }) - }) - - Context("lifecycle actions", func() { - It("ok", func() { - clusterCompDef.Probes.RoleProbe = nil - - convertor := &compDefLifecycleActionsConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - - actions := res.(*appsv1alpha1.ComponentLifecycleActions) - expectedActions := &appsv1alpha1.ComponentLifecycleActions{} - Expect(*actions).Should(BeEquivalentTo(*expectedActions)) - }) - - It("switchover", func() { - clusterCompDef.Probes.RoleProbe = nil - convertor := &compDefLifecycleActionsConvertor{} - clusterCompDef.SwitchoverSpec = &appsv1alpha1.SwitchoverSpec{ - WithCandidate: &appsv1alpha1.SwitchoverAction{ - CmdExecutorConfig: &appsv1alpha1.CmdExecutorConfig{ - CommandExecutorEnvItem: *commandExecutorEnvItem, - CommandExecutorItem: *commandExecutorItem, - }, - ScriptSpecSelectors: []appsv1alpha1.ScriptSpecSelector{ - { - Name: "with-candidate", - }, - }, - }, - WithoutCandidate: &appsv1alpha1.SwitchoverAction{ - CmdExecutorConfig: &appsv1alpha1.CmdExecutorConfig{ - CommandExecutorEnvItem: *commandExecutorEnvItem, - CommandExecutorItem: *commandExecutorItem, - }, - ScriptSpecSelectors: []appsv1alpha1.ScriptSpecSelector{ - { - Name: "without-candidate", - }, - }, - }, - } - - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - actions := res.(*appsv1alpha1.ComponentLifecycleActions) - Expect(actions.Switchover).ShouldNot(BeNil()) - Expect(len(actions.Switchover.ScriptSpecSelectors)).Should(BeEquivalentTo(2)) - Expect(actions.Switchover.WithCandidate).ShouldNot(BeNil()) - Expect(actions.Switchover.WithCandidate.Exec.Image).Should(BeEquivalentTo(commandExecutorEnvItem.Image)) - Expect(actions.Switchover.WithCandidate.Exec.Env).Should(BeEquivalentTo(commandExecutorEnvItem.Env)) - Expect(actions.Switchover.WithCandidate.Exec.Command).Should(BeEquivalentTo(commandExecutorItem.Command)) - Expect(actions.Switchover.WithCandidate.Exec.Args).Should(BeEquivalentTo(commandExecutorItem.Args)) - Expect(actions.Switchover.WithoutCandidate).ShouldNot(BeNil()) - }) - - It("role probe", func() { - convertor := &compDefLifecycleActionsConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - - actions := res.(*appsv1alpha1.ComponentLifecycleActions) - builtinHandler := func() *appsv1alpha1.BuiltinActionHandlerType { - handler := appsv1alpha1.UnknownBuiltinActionHandler - return &handler - } - expectedRoleProbe := &appsv1alpha1.Probe{ - BuiltinHandler: builtinHandler(), - Action: appsv1alpha1.Action{ - TimeoutSeconds: clusterCompDef.Probes.RoleProbe.TimeoutSeconds, - }, - PeriodSeconds: clusterCompDef.Probes.RoleProbe.PeriodSeconds, - } - Expect(actions.RoleProbe).ShouldNot(BeNil()) - Expect(*actions.RoleProbe).Should(BeEquivalentTo(*expectedRoleProbe)) - }) - - It("ITS spec role probe convertor", func() { - convertor := &compDefLifecycleActionsConvertor{} - mockCommand := []string{ - "mock-its-role-probe-command", - } - mockArgs := []string{ - "mock-its-role-probe-args", - } - clusterCompDef.RSMSpec = &appsv1alpha1.RSMSpec{ - RoleProbe: &workloads.RoleProbe{ - CustomHandler: []workloads.Action{ - { - Image: "mock-its-role-probe-image", - Command: mockCommand, - Args: mockArgs, - }, - }, - }, - } - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - - actions := res.(*appsv1alpha1.ComponentLifecycleActions) - Expect(actions.RoleProbe).ShouldNot(BeNil()) - Expect(*actions.RoleProbe.BuiltinHandler).Should(BeEquivalentTo(appsv1alpha1.UnknownBuiltinActionHandler)) - Expect(actions.RoleProbe.Exec).ShouldNot(BeNil()) - Expect(actions.RoleProbe.Exec.Image).Should(BeEquivalentTo("mock-its-role-probe-image")) - Expect(actions.RoleProbe.Exec.Command).Should(BeEquivalentTo(mockCommand)) - Expect(actions.RoleProbe.Exec.Args).Should(BeEquivalentTo(mockArgs)) - }) - }) - - It("service ref declarations", func() { - convertor := &compDefServiceRefDeclarationsConvertor{} - res, err := convertor.convert(clusterCompDef) - Expect(err).Should(Succeed()) - Expect(res).Should(BeNil()) - }) - }) -}) diff --git a/pkg/controller/component/synthesize_component.go b/pkg/controller/component/synthesize_component.go index 239c13587bb2..7d23833e7976 100644 --- a/pkg/controller/component/synthesize_component.go +++ b/pkg/controller/component/synthesize_component.go @@ -25,7 +25,6 @@ import ( "strconv" "strings" - appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -34,7 +33,6 @@ import ( appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" "github.com/apecloud/kubeblocks/pkg/constant" - "github.com/apecloud/kubeblocks/pkg/controller/apiconversion" "github.com/apecloud/kubeblocks/pkg/controller/scheduling" intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" ) @@ -85,25 +83,13 @@ func BuildSynthesizedComponentWrapper(reqCtx intctrlutil.RequestCtx, cli client.Reader, cluster *appsv1alpha1.Cluster, clusterCompSpec *appsv1alpha1.ClusterComponentSpec) (*SynthesizedComponent, error) { + if clusterCompSpec == nil { + return nil, fmt.Errorf("cluster component spec is not provided") + } clusterDef, err := getClusterReferencedResources(reqCtx.Ctx, cli, cluster) if err != nil { return nil, err } - return BuildSynthesizedComponentWrapper4Test(reqCtx, cli, clusterDef, cluster, clusterCompSpec) -} - -// BuildSynthesizedComponentWrapper4Test builds a new SynthesizedComponent object with a given ClusterComponentSpec. -func BuildSynthesizedComponentWrapper4Test(reqCtx intctrlutil.RequestCtx, - cli client.Reader, - clusterDef *appsv1alpha1.ClusterDefinition, - cluster *appsv1alpha1.Cluster, - clusterCompSpec *appsv1alpha1.ClusterComponentSpec) (*SynthesizedComponent, error) { - if clusterCompSpec == nil { - clusterCompSpec = apiconversion.HandleSimplifiedClusterAPI(clusterDef, cluster) - } - if clusterCompSpec == nil { - return nil, nil - } compDef, err := getOrBuildComponentDefinition(reqCtx.Ctx, cli, clusterDef, cluster, clusterCompSpec) if err != nil { return nil, err @@ -185,17 +171,7 @@ func buildSynthesizedComponent(reqCtx intctrlutil.RequestCtx, EnabledLogs: comp.Spec.EnabledLogs, } - // build backward compatible fields, including workload, services, componentRefEnvs, clusterDefName, clusterCompDefName, etc. - // if cluster referenced a clusterDefinition, for backward compatibility, we need to merge the clusterDefinition into the component - // TODO(xingran): it will be removed in the future - if clusterDef != nil && cluster != nil && clusterCompSpec != nil { - if err = buildBackwardCompatibleFields(reqCtx, clusterDef, cluster, clusterCompSpec, synthesizeComp); err != nil { - return nil, err - } - } - if synthesizeComp.HorizontalScalePolicy == nil { - buildCompatibleHorizontalScalePolicy(compDefObj, synthesizeComp) - } + buildCompatibleHorizontalScalePolicy(compDefObj, synthesizeComp) if err = mergeUserDefinedEnv(synthesizeComp, comp); err != nil { return nil, err @@ -235,7 +211,7 @@ func buildSynthesizedComponent(reqCtx intctrlutil.RequestCtx, buildRuntimeClassName(synthesizeComp, comp) // build lorryContainer - // TODO(xingran): buildLorryContainers relies on synthesizeComp.CharacterType and synthesizeComp.WorkloadType, which will be deprecated in the future. + // TODO(xingran): buildLorryContainers relies on synthesizeComp.CharacterType, which will be deprecated in the future. if err := buildLorryContainers(reqCtx, synthesizeComp, clusterCompSpec); err != nil { reqCtx.Log.Error(err, "build lorry containers failed.") return nil, err @@ -601,80 +577,11 @@ func buildRuntimeClassName(synthesizeComp *SynthesizedComponent, comp *appsv1alp synthesizeComp.PodSpec.RuntimeClassName = comp.Spec.RuntimeClassName } -// buildBackwardCompatibleFields builds backward compatible fields for component which referenced a clusterComponentDefinition and clusterComponentVersion -// TODO(xingran): it will be removed in the future -func buildBackwardCompatibleFields(reqCtx intctrlutil.RequestCtx, - clusterDef *appsv1alpha1.ClusterDefinition, - cluster *appsv1alpha1.Cluster, - clusterCompSpec *appsv1alpha1.ClusterComponentSpec, - synthesizeComp *SynthesizedComponent) error { - if clusterCompSpec.ComponentDefRef == "" { - return nil // no need to build backward compatible fields - } - - clusterCompDef := clusterDef.GetComponentDefByName(clusterCompSpec.ComponentDefRef) - if clusterCompDef == nil { - return fmt.Errorf("referenced cluster component definition does not exist, cluster: %s, component: %s, component definition ref:%s", - cluster.Name, clusterCompSpec.Name, clusterCompSpec.ComponentDefRef) - } - - buildWorkload := func() { - synthesizeComp.ClusterDefName = clusterDef.Name - synthesizeComp.ClusterCompDefName = clusterCompDef.Name - synthesizeComp.HorizontalScalePolicy = clusterCompDef.HorizontalScalePolicy - } - - buildClusterCompServices := func() { - if len(synthesizeComp.ComponentServices) > 0 { - service := corev1.Service{ - Spec: corev1.ServiceSpec{ - Ports: synthesizeComp.ComponentServices[0].Spec.Ports, - }, - } - for _, item := range clusterCompSpec.Services { - svc := appsv1alpha1.ComponentService{ - Service: appsv1alpha1.Service{ - Name: item.Name, - ServiceName: item.Name, - Annotations: item.Annotations, - Spec: *service.Spec.DeepCopy(), - }, - } - svc.Spec.Type = item.ServiceType - synthesizeComp.ComponentServices = append(synthesizeComp.ComponentServices, svc) - } - } - } - - buildPodManagementPolicy := func() { - var podManagementPolicy appsv1.PodManagementPolicyType - w := clusterCompDef.GetStatefulSetWorkload() - if w == nil { - podManagementPolicy = "" - } else { - podManagementPolicy, _ = w.FinalStsUpdateStrategy() - } - synthesizeComp.PodManagementPolicy = &podManagementPolicy - } - - // build workload - buildWorkload() - - buildClusterCompServices() - - // build pod management policy - buildPodManagementPolicy() - - return nil -} - func buildCompatibleHorizontalScalePolicy(compDef *appsv1alpha1.ComponentDefinition, synthesizeComp *SynthesizedComponent) { if compDef.Annotations != nil { - if templateName, ok := compDef.Annotations[constant.HorizontalScaleBackupPolicyTemplateKey]; ok { - synthesizeComp.HorizontalScalePolicy = &appsv1alpha1.HorizontalScalePolicy{ - Type: appsv1alpha1.HScaleDataClonePolicyCloneVolume, - BackupPolicyTemplateName: templateName, - } + templateName, ok := compDef.Annotations[constant.HorizontalScaleBackupPolicyTemplateKey] + if ok { + synthesizeComp.HorizontalScaleBackupPolicyTemplate = &templateName } } } diff --git a/pkg/controller/component/type.go b/pkg/controller/component/type.go index cf611905e692..32e8a957230a 100644 --- a/pkg/controller/component/type.go +++ b/pkg/controller/component/type.go @@ -76,8 +76,7 @@ type SynthesizedComponent struct { Stop *bool // TODO(xingran): The following fields will be deprecated after KubeBlocks version 0.8.0 - ClusterDefName string `json:"clusterDefName,omitempty"` // the name of the clusterDefinition - ClusterCompDefName string `json:"clusterCompDefName,omitempty"` // the name of the clusterDefinition.Spec.ComponentDefs[*].Name - HorizontalScalePolicy *v1alpha1.HorizontalScalePolicy `json:"horizontalScalePolicy,omitempty"` - EnabledLogs []string `json:"enabledLogs,omitempty"` + ClusterDefName string `json:"clusterDefName,omitempty"` // the name of the clusterDefinition + EnabledLogs []string `json:"enabledLogs,omitempty"` + HorizontalScaleBackupPolicyTemplate *string } diff --git a/pkg/controller/configuration/config_template_test.go b/pkg/controller/configuration/config_template_test.go index ee901ed8d2a4..ebd98e082df9 100644 --- a/pkg/controller/configuration/config_template_test.go +++ b/pkg/controller/configuration/config_template_test.go @@ -149,10 +149,9 @@ single_thread_memory = 294912 }, } component = &ctrlcomp.SynthesizedComponent{ - ClusterDefName: "mysql-three-node-definition", - Name: "replicasets", - ClusterCompDefName: "replicasets", - Replicas: 5, + ClusterDefName: "mysql-three-node-definition", + Name: "replicasets", + Replicas: 5, VolumeClaimTemplates: []corev1.PersistentVolumeClaimTemplate{ { ObjectMeta: metav1.ObjectMeta{ diff --git a/pkg/controller/configuration/configuration_test.go b/pkg/controller/configuration/configuration_test.go index 4f033edd3d6a..6b69c1c505cd 100644 --- a/pkg/controller/configuration/configuration_test.go +++ b/pkg/controller/configuration/configuration_test.go @@ -65,7 +65,7 @@ func newAllFieldsClusterObj(compDef *appsv1alpha1.ComponentDefinition, create bo } pvcSpec := testapps.NewPVCSpec("1Gi") clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). - AddComponentV2(mysqlCompName, compDef.Name). + AddComponent(mysqlCompName, compDef.Name). SetReplicas(1). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). AddComponentService(testapps.ServiceVPCName, corev1.ServiceTypeLoadBalancer). diff --git a/pkg/controller/configuration/envfrom_utils_test.go b/pkg/controller/configuration/envfrom_utils_test.go index 5c340a35968e..9e2d94fc18be 100644 --- a/pkg/controller/configuration/envfrom_utils_test.go +++ b/pkg/controller/configuration/envfrom_utils_test.go @@ -67,7 +67,7 @@ var _ = Describe("ConfigEnvFrom test", func() { pvcSpec := testapps.NewPVCSpec("1Gi") cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). - AddComponentV2(mysqlCompName, compDef.Name). + AddComponent(mysqlCompName, compDef.Name). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). GetObject() diff --git a/pkg/controller/configuration/resource_wrapper_test.go b/pkg/controller/configuration/resource_wrapper_test.go index 9d806abe420c..8cb26e91ffdd 100644 --- a/pkg/controller/configuration/resource_wrapper_test.go +++ b/pkg/controller/configuration/resource_wrapper_test.go @@ -37,29 +37,25 @@ import ( var _ = Describe("resource Fetcher", func() { const ( - clusterDefName = "test-clusterdef" - clusterName = "test-cluster" - - mysqlCompDefName = "replicasets" - mysqlCompName = "mysql" - mysqlConfigName = "mysql-config-template" - mysqlVolumeName = "mysql-config" + compDefName = "test-compdef" + clusterName = "test-cluster" + mysqlCompName = "mysql" + mysqlConfigName = "mysql-config-template" ) var ( k8sMockClient *testutil.K8sClientMockHelper - clusterDef *appsv1alpha1.ClusterDefinition cluster *appsv1alpha1.Cluster ) BeforeEach(func() { k8sMockClient = testutil.NewK8sMockClient() - clusterDef = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). + testapps.NewComponentDefinitionFactory(compDefName). + SetDefaultSpec(). GetObject() pvcSpec := testapps.NewPVCSpec("1Gi") - cluster = testapps.NewClusterFactory("default", clusterName, clusterDef.Name). - AddComponent(mysqlCompName, mysqlCompDefName). + cluster = testapps.NewClusterFactory("default", clusterName, ""). + AddComponent(mysqlCompName, compDefName). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). GetObject() }) @@ -72,7 +68,6 @@ var _ = Describe("resource Fetcher", func() { It("Should succeed with no error", func() { k8sMockClient.MockGetMethod(testutil.WithGetReturned(testutil.WithConstructSimpleGetResult( []client.Object{ - clusterDef, cluster, testapps.NewConfigMap("default", cfgcore.GetComponentCfgName(clusterName, mysqlCompName, mysqlConfigName)), &appsv1beta1.ConfigConstraint{ @@ -84,7 +79,6 @@ var _ = Describe("resource Fetcher", func() { ), testutil.WithAnyTimes())) err := NewTest(k8sMockClient.Client(), ctx). Cluster(). - ClusterDef(). ComponentSpec(). ConfigMap(mysqlConfigName). ConfigConstraints(mysqlConfigName). diff --git a/pkg/controller/factory/builder.go b/pkg/controller/factory/builder.go index 0f482735fe4e..f92393fce81f 100644 --- a/pkg/controller/factory/builder.go +++ b/pkg/controller/factory/builder.go @@ -48,21 +48,14 @@ import ( // BuildInstanceSet builds an InstanceSet object from SynthesizedComponent. func BuildInstanceSet(synthesizedComp *component.SynthesizedComponent, componentDef *appsv1alpha1.ComponentDefinition) (*workloads.InstanceSet, error) { var ( - clusterDefName = synthesizedComp.ClusterDefName - clusterCompDefName = synthesizedComp.ClusterCompDefName - compDefName = synthesizedComp.CompDefName - namespace = synthesizedComp.Namespace - clusterName = synthesizedComp.ClusterName - compName = synthesizedComp.Name + compDefName = synthesizedComp.CompDefName + namespace = synthesizedComp.Namespace + clusterName = synthesizedComp.ClusterName + compName = synthesizedComp.Name ) // build labels labels := constant.GetKBWellKnownLabelsWithCompDef(compDefName, clusterName, compName) compDefLabel := constant.GetComponentDefLabel(compDefName) - if len(compDefName) == 0 { - // TODO(xingran): for backward compatibility in kubeBlocks version 0.8.0, it will be removed in the future. - labels = constant.GetKBWellKnownLabels(clusterDefName, clusterName, compName) - compDefLabel = constant.GetClusterCompDefLabel(clusterCompDefName) - } mergeLabels := intctrlutil.MergeMetadataMaps(labels, compDefLabel, synthesizedComp.Labels) // build annotations @@ -302,7 +295,7 @@ func BuildConfigMapWithTemplate(cluster *appsv1alpha1.Cluster, cmName string, configTemplateSpec appsv1alpha1.ComponentTemplateSpec) *corev1.ConfigMap { wellKnownLabels := constant.GetKBWellKnownLabels(component.ClusterDefName, cluster.Name, component.Name) - wellKnownLabels[constant.AppComponentLabelKey] = component.ClusterCompDefName + wellKnownLabels[constant.AppComponentLabelKey] = component.CompDefName return builder.NewConfigMapBuilder(cluster.Namespace, cmName). AddLabelsInMap(wellKnownLabels). AddLabels(constant.CMConfigurationTypeLabelKey, constant.ConfigInstanceType). diff --git a/pkg/controller/factory/builder_test.go b/pkg/controller/factory/builder_test.go index 059a2c34918c..889e250e36d5 100644 --- a/pkg/controller/factory/builder_test.go +++ b/pkg/controller/factory/builder_test.go @@ -26,7 +26,6 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "golang.org/x/exp/slices" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -44,22 +43,19 @@ import ( ) var _ = Describe("builder", func() { - const clusterDefName = "test-clusterdef" + const compDefName = "test-compdef" const clusterName = "test-cluster" - const mysqlCompDefName = "replicasets" - const proxyCompDefName = "proxy" const mysqlCompName = "mysql" - allFieldsClusterDefObj := func(needCreate bool) *appsv1alpha1.ClusterDefinition { - By("By assure an clusterDefinition obj") - clusterDefObj := testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). - AddComponentDef(testapps.StatelessNginxComponent, proxyCompDefName). + allFieldsCompDefObj := func(needCreate bool) *appsv1alpha1.ComponentDefinition { + By("By assure an componentDefinition obj") + compDebObj := testapps.NewComponentDefinitionFactory(compDefName). + SetDefaultSpec(). GetObject() if needCreate { - Expect(testCtx.CreateObj(testCtx.Ctx, clusterDefObj)).Should(Succeed()) + Expect(testCtx.CreateObj(testCtx.Ctx, compDebObj)).Should(Succeed()) } - return clusterDefObj + return compDebObj } newExtraEnvs := func() map[string]string { @@ -71,24 +67,25 @@ var _ = Describe("builder", func() { } } - newAllFieldsClusterObj := func(clusterDefObj *appsv1alpha1.ClusterDefinition, needCreate bool) (*appsv1alpha1.Cluster, *appsv1alpha1.ClusterDefinition, types.NamespacedName) { - // setup Cluster obj requires default ClusterDefinition object - if clusterDefObj == nil { - clusterDefObj = allFieldsClusterDefObj(needCreate) + newAllFieldsClusterObj := func(compDefObj *appsv1alpha1.ComponentDefinition, create bool) (*appsv1alpha1.Cluster, *appsv1alpha1.ComponentDefinition, types.NamespacedName) { + // setup Cluster obj requires default ComponentDefinition object + if compDefObj == nil { + compDefObj = allFieldsCompDefObj(create) } pvcSpec := testapps.NewPVCSpec("1Gi") - clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). + clusterObj := testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). AddAnnotationsInMap(newExtraEnvs()). - AddComponent(mysqlCompName, mysqlCompDefName).SetReplicas(1). + AddComponent(mysqlCompName, compDefObj.GetName()). + SetReplicas(1). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). AddComponentService(testapps.ServiceVPCName, corev1.ServiceTypeLoadBalancer). AddComponentService(testapps.ServiceInternetName, corev1.ServiceTypeLoadBalancer). GetObject() key := client.ObjectKeyFromObject(clusterObj) - if needCreate { + if create { Expect(testCtx.CreateObj(testCtx.Ctx, clusterObj)).Should(Succeed()) } - return clusterObj, clusterDefObj, key + return clusterObj, compDefObj, key } newItsObj := func() *workloads.InstanceSet { @@ -109,6 +106,7 @@ var _ = Describe("builder", func() { Spec: testapps.NewPVC("1Gi"), }).GetObject() } + newReqCtx := func() intctrlutil.RequestCtx { reqCtx := intctrlutil.RequestCtx{ Ctx: testCtx.Ctx, @@ -117,11 +115,13 @@ var _ = Describe("builder", func() { } return reqCtx } - newAllFieldsSynthesizedComponent := func(clusterDef *appsv1alpha1.ClusterDefinition, cluster *appsv1alpha1.Cluster) *component.SynthesizedComponent { + + newAllFieldsSynthesizedComponent := func(compDef *appsv1alpha1.ComponentDefinition, cluster *appsv1alpha1.Cluster) *component.SynthesizedComponent { reqCtx := newReqCtx() By("assign every available fields") - synthesizeComp, err := component.BuildSynthesizedComponentWrapper4Test(reqCtx, testCtx.Cli, - clusterDef, cluster, &cluster.Spec.ComponentSpecs[0]) + 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) Expect(err).Should(Succeed()) Expect(synthesizeComp).ShouldNot(BeNil()) // to resolve and inject env vars @@ -131,10 +131,11 @@ var _ = Describe("builder", func() { component.InjectEnvVars(synthesizeComp, envVars, nil) return synthesizeComp } - newClusterObjs := func(clusterDefObj *appsv1alpha1.ClusterDefinition) (*appsv1alpha1.ClusterDefinition, *appsv1alpha1.Cluster, *component.SynthesizedComponent) { - cluster, clusterDef, _ := newAllFieldsClusterObj(clusterDefObj, false) - synthesizedComponent := newAllFieldsSynthesizedComponent(clusterDef, cluster) - return clusterDef, cluster, synthesizedComponent + + newClusterObjs := func(compDefObj *appsv1alpha1.ComponentDefinition) (*appsv1alpha1.ComponentDefinition, *appsv1alpha1.Cluster, *component.SynthesizedComponent) { + cluster, compDef, _ := newAllFieldsClusterObj(compDefObj, false) + synthesizedComponent := newAllFieldsSynthesizedComponent(compDef, cluster) + return compDef, cluster, synthesizedComponent } Context("has helper function which builds specific object from cue template", func() { @@ -154,7 +155,7 @@ var _ = Describe("builder", func() { }) It("builds InstanceSet correctly", func() { - clusterDef, cluster, synthesizedComponent := newClusterObjs(nil) + compDef, cluster, synthesizedComponent := newClusterObjs(nil) its, err := BuildInstanceSet(synthesizedComponent, nil) Expect(err).Should(BeNil()) @@ -168,60 +169,16 @@ var _ = Describe("builder", func() { Expect(its).ShouldNot(BeNil()) Expect(*its.Spec.Replicas).Should(Equal(int32(0))) - By("set workload type to Replication") - clusterDef.Spec.ComponentDefs[0].WorkloadType = appsv1alpha1.Replication - clusterDef.Spec.ComponentDefs[0].ReplicationSpec = &appsv1alpha1.ReplicationSetSpec{ - StatefulSetSpec: appsv1alpha1.StatefulSetSpec{ - UpdateStrategy: appsv1alpha1.SerialStrategy, - }, - } + By("set replicas = 2") cluster.Spec.ComponentSpecs[0].Replicas = 2 - replComponent := newAllFieldsSynthesizedComponent(clusterDef, cluster) - its, err = BuildInstanceSet(replComponent, nil) + synthesizedComp := newAllFieldsSynthesizedComponent(compDef, cluster) + its, err = BuildInstanceSet(synthesizedComp, nil) Expect(err).Should(BeNil()) Expect(its).ShouldNot(BeNil()) Expect(*its.Spec.Replicas).Should(BeEquivalentTo(2)) - // test extra envs - Expect(its.Spec.Template.Spec.Containers).ShouldNot(BeEmpty()) - for _, container := range its.Spec.Template.Spec.Containers { - isContainEnv := false - for _, env := range container.Env { - if env.Name == "mock-key" && env.Value == "mock-value" { - isContainEnv = true - break - } - } - Expect(isContainEnv).Should(BeTrue()) - } - - // test roles - Expect(its.Spec.Roles).Should(HaveLen(2)) - for _, roleName := range []string{constant.Primary, constant.Secondary} { - Expect(slices.IndexFunc(its.Spec.Roles, func(role workloads.ReplicaRole) bool { - return role.Name == roleName - })).Should(BeNumerically(">", -1)) - } - - // test role probe - Expect(its.Spec.RoleProbe).ShouldNot(BeNil()) - - // test member update strategy - Expect(its.Spec.MemberUpdateStrategy).ShouldNot(BeNil()) - Expect(*its.Spec.MemberUpdateStrategy).Should(BeEquivalentTo(workloads.SerialUpdateStrategy)) - - By("set workload type to Consensus") - clusterDef.Spec.ComponentDefs[0].WorkloadType = appsv1alpha1.Consensus - clusterDef.Spec.ComponentDefs[0].ConsensusSpec = appsv1alpha1.NewConsensusSetSpec() - clusterDef.Spec.ComponentDefs[0].ConsensusSpec.UpdateStrategy = appsv1alpha1.BestEffortParallelStrategy - cluster.Spec.ComponentSpecs[0].Replicas = 3 - csComponent := newAllFieldsSynthesizedComponent(clusterDef, cluster) - its, err = BuildInstanceSet(csComponent, nil) - Expect(err).Should(BeNil()) - Expect(its).ShouldNot(BeNil()) // test roles - Expect(its.Spec.Roles).Should(HaveLen(1)) - Expect(its.Spec.Roles[0].Name).Should(Equal(appsv1alpha1.DefaultLeader.Name)) + Expect(its.Spec.Roles).Should(HaveLen(len(compDef.Spec.Roles))) // test role probe Expect(its.Spec.RoleProbe).ShouldNot(BeNil()) diff --git a/pkg/controller/job/job_utils_test.go b/pkg/controller/job/job_utils_test.go index 4d7e71f00257..3e213bee0da6 100644 --- a/pkg/controller/job/job_utils_test.go +++ b/pkg/controller/job/job_utils_test.go @@ -37,16 +37,14 @@ var _ = Describe("Job Utils Test", func() { Context("Job Utils Test function", func() { const ( - clusterDefName = "test-clusterdef" - clusterName = "test-cluster" - mysqlCompDefName = "replicasets" - mysqlCompName = "mysql" - labelKey = "test-label" + compDefName = "test-compdef" + clusterName = "test-cluster" + mysqlCompName = "mysql" + labelKey = "test-label" ) var ( - clusterDef *appsv1alpha1.ClusterDefinition - cluster *appsv1alpha1.Cluster + cluster *appsv1alpha1.Cluster ) createJob := func(name string, keys ...string) *batchv1.Job { @@ -77,11 +75,8 @@ var _ = Describe("Job Utils Test", func() { } BeforeEach(func() { - clusterDef = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). - GetObject() - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). - AddComponent(mysqlCompName, mysqlCompDefName). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). + AddComponent(mysqlCompName, compDefName). GetObject() }) diff --git a/pkg/controller/plan/prepare_test.go b/pkg/controller/plan/prepare_test.go index 19e7e59a17e2..29d6774c30de 100644 --- a/pkg/controller/plan/prepare_test.go +++ b/pkg/controller/plan/prepare_test.go @@ -37,7 +37,6 @@ import ( ) var _ = Describe("Prepare Test", func() { - cleanEnv := func() { // must wait until resources deleted and no longer exist before the testcases start, // otherwise if later it needs to create some new resource objects with the same name, @@ -64,15 +63,12 @@ var _ = Describe("Prepare Test", func() { }) const ( - clusterDefName = "test-clusterdef" - clusterName = "test-cluster" - - mysqlClusterCompDefName = "mysql-cluster-comp-def" - mysqlCompDefName = "mysql-comp-def" - mysqlCompName = "mysql" + compDefName = "test-compdef" + clusterName = "test-cluster" + mysqlCompName = "mysql" ) + var ( - clusterDefObj *appsv1alpha1.ClusterDefinition compDefObj *appsv1alpha1.ComponentDefinition cluster *appsv1alpha1.Cluster comp *appsv1alpha1.Component @@ -80,14 +76,9 @@ var _ = Describe("Prepare Test", func() { ) Context("create cluster with component and component definition API, testing render configuration", func() { - createAllWorkloadTypesClusterDef := func() { - By("Create a clusterDefinition obj") - clusterDefObj = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.ConsensusMySQLComponent, mysqlClusterCompDefName). - Create(&testCtx).GetObject() - + createAllTypesClusterDef := func() { By("Create a componentDefinition obj") - compDefObj = testapps.NewComponentDefinitionFactory(mysqlCompDefName). + compDefObj = testapps.NewComponentDefinitionFactory(compDefName). WithRandomName(). SetDefaultSpec(). AddConfigs(testapps.DefaultCompDefConfigs). @@ -98,21 +89,23 @@ var _ = Describe("Prepare Test", func() { } BeforeEach(func() { - createAllWorkloadTypesClusterDef() + createAllTypesClusterDef() testapps.CreateCustomizedObj(&testCtx, "config/envfrom-config.yaml", &corev1.ConfigMap{}, testCtx.UseDefaultNamespace()) tpl := testapps.CreateCustomizedObj(&testCtx, "config/envfrom-constraint.yaml", &appsv1beta1.ConfigConstraint{}) configSpecName = tpl.Name pvcSpec := testapps.NewPVCSpec("1Gi") - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefObj.Name). - AddComponentV2(mysqlCompName, compDefObj.Name). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). + AddComponent(mysqlCompName, compDefObj.Name). SetReplicas(1). AddVolumeClaimTemplate(testapps.DataVolumeName, pvcSpec). Create(&testCtx). GetObject() - comp, _ = component.BuildComponent(cluster, &cluster.Spec.ComponentSpecs[0], nil, nil) + var err error + comp, err = component.BuildComponent(cluster, &cluster.Spec.ComponentSpecs[0], nil, nil) + Expect(err).Should(Succeed()) comp.SetUID("test-uid") }) @@ -121,7 +114,8 @@ var _ = Describe("Prepare Test", func() { Ctx: ctx, Log: logger, } - synthesizeComp, err := component.BuildSynthesizedComponentWrapper(reqCtx, testCtx.Cli, cluster, &cluster.Spec.ComponentSpecs[0]) + + synthesizeComp, err := component.BuildSynthesizedComponent(reqCtx, testCtx.Cli, cluster, compDefObj, comp) Expect(err).Should(Succeed()) Expect(synthesizeComp.PodSpec).ShouldNot(BeNil()) resCtx := &configuration.ResourceCtx{ @@ -134,8 +128,6 @@ var _ = Describe("Prepare Test", func() { err = RenderConfigNScriptFiles(resCtx, cluster, comp, synthesizeComp, synthesizeComp.PodSpec, nil) Expect(err).Should(Succeed()) Expect(configuration.CheckEnvFrom(&synthesizeComp.PodSpec.Containers[0], cfgcore.GenerateEnvFromName(cfgcore.GetComponentCfgName(cluster.Name, synthesizeComp.Name, configSpecName)))).Should(BeFalse()) - // TODO(xingran): add more test cases - // Expect(len(synthesizeComp.PodSpec.Containers) >= 3).Should(BeTrue()) }) }) }) diff --git a/pkg/controller/plan/restore_test.go b/pkg/controller/plan/restore_test.go index ed9fe400992e..d3070167f98f 100644 --- a/pkg/controller/plan/restore_test.go +++ b/pkg/controller/plan/restore_test.go @@ -91,17 +91,15 @@ var _ = Describe("Restore", func() { Context("Cluster Restore", func() { const ( - clusterDefName = "test-clusterdef" - mysqlCompType = "replicasets" - mysqlCompName = "mysql" - nginxCompType = "proxy" - topologyKey = "testTopologyKey" - labelKey = "testNodeLabelKey" - labelValue = "testLabelValue" + compDefName = "test-compdef" + defaultCompName = "mysql" + topologyKey = "testTopologyKey" + labelKey = "testNodeLabelKey" + labelValue = "testLabelValue" ) var ( - clusterDef *appsv1alpha1.ClusterDefinition + compDef *appsv1alpha1.ComponentDefinition cluster *appsv1alpha1.Cluster synthesizedComponent *component.SynthesizedComponent compObj *appsv1alpha1.Component @@ -112,13 +110,13 @@ var _ = Describe("Restore", func() { ) BeforeEach(func() { - clusterDef = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.ConsensusMySQLComponent, mysqlCompType). - AddComponentDef(testapps.StatelessNginxComponent, nginxCompType). + compDef = testapps.NewComponentDefinitionFactory(compDefName). + SetDefaultSpec(). Create(&testCtx).GetObject() + pvcSpec := testapps.NewPVCSpec("1Gi") - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). - AddComponent(mysqlCompName, mysqlCompType). + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). + AddComponent(defaultCompName, compDefName). SetReplicas(3). SetClusterAffinity(&appsv1alpha1.Affinity{ PodAntiAffinity: appsv1alpha1.Required, @@ -132,16 +130,16 @@ var _ = Describe("Restore", func() { By("By mocking a pvc") pvc = testapps.NewPersistentVolumeClaimFactory( - testCtx.DefaultNamespace, "data-"+clusterName+"-"+mysqlCompName+"-0", clusterName, mysqlCompName, "data"). + testCtx.DefaultNamespace, "data-"+clusterName+"-"+defaultCompName+"-0", clusterName, defaultCompName, "data"). SetStorage("1Gi"). Create(&testCtx).GetObject() By("By mocking a pod") volume := corev1.Volume{Name: pvc.Name, VolumeSource: corev1.VolumeSource{ PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ClaimName: pvc.Name}}} - _ = testapps.NewPodFactory(testCtx.DefaultNamespace, clusterName+"-"+mysqlCompName+"-0"). + _ = testapps.NewPodFactory(testCtx.DefaultNamespace, clusterName+"-"+defaultCompName+"-0"). AddAppInstanceLabel(clusterName). - AddAppComponentLabel(mysqlCompName). + AddAppComponentLabel(defaultCompName). AddAppManagedByLabel(). AddVolume(volume). AddLabels(constant.ConsensusSetAccessModeLabelKey, string(appsv1alpha1.ReadWrite)). @@ -154,23 +152,18 @@ var _ = Describe("Restore", func() { fullBackupActionSetName = fullBackupActionSet.Name By("By creating backup policyTemplate: ") - backupTplLabels := map[string]string{ - constant.ClusterDefLabelKey: clusterDefName, - } _ = testapps.NewBackupPolicyTemplateFactory("backup-policy-template"). - WithRandomName().SetLabels(backupTplLabels). - AddBackupPolicy(mysqlCompName). - SetClusterDefRef(clusterDefName). + WithRandomName(). + AddBackupPolicy(defaultCompName). + SetComponentDef(compDef.Name). AddBackupMethod(testdp.BackupMethodName, false, fullBackupActionSetName). SetBackupMethodVolumeMounts(testapps.DataVolumeName, "/data") - clusterCompDefObj := clusterDef.Spec.ComponentDefs[0] synthesizedComponent = &component.SynthesizedComponent{ - PodSpec: clusterCompDefObj.PodSpec, - HorizontalScalePolicy: clusterCompDefObj.HorizontalScalePolicy, - VolumeClaimTemplates: cluster.Spec.ComponentSpecs[0].ToVolumeClaimTemplates(), - Name: mysqlCompName, - Replicas: 1, + PodSpec: &compDef.Spec.Runtime, + VolumeClaimTemplates: cluster.Spec.ComponentSpecs[0].ToVolumeClaimTemplates(), + Name: defaultCompName, + Replicas: 1, Roles: []appsv1alpha1.ReplicaRole{ { Name: "leader", @@ -196,14 +189,14 @@ var _ = Describe("Restore", func() { By("By creating remote pvc: ") remotePVC := testapps.NewPersistentVolumeClaimFactory( - testCtx.DefaultNamespace, "remote-pvc", clusterName, mysqlCompName, "log"). + testCtx.DefaultNamespace, "remote-pvc", clusterName, defaultCompName, "log"). SetStorage("1Gi"). Create(&testCtx).GetObject() By("By creating base backup: ") backupLabels := map[string]string{ constant.AppInstanceLabelKey: sourceCluster, - constant.KBAppComponentLabelKey: mysqlCompName, + constant.KBAppComponentLabelKey: defaultCompName, } backup = testdp.NewBackupFactory(testCtx.DefaultNamespace, backupName). WithRandomName().SetLabels(backupLabels). @@ -224,7 +217,7 @@ var _ = Describe("Restore", func() { It("Test restore", func() { By("restore from backup") - restoreFromBackup := fmt.Sprintf(`{"%s": {"name":"%s"}}`, mysqlCompName, backup.Name) + restoreFromBackup := fmt.Sprintf(`{"%s": {"name":"%s"}}`, defaultCompName, backup.Name) Expect(testapps.ChangeObj(&testCtx, cluster, func(tmpCluster *appsv1alpha1.Cluster) { tmpCluster.Annotations = map[string]string{ constant.RestoreFromBackupAnnotationKey: restoreFromBackup, @@ -246,7 +239,7 @@ var _ = Describe("Restore", func() { Expect(testapps.ChangeObjStatus(&testCtx, cluster, func() { cluster.Status.Phase = appsv1alpha1.RunningClusterPhase cluster.Status.Components = map[string]appsv1alpha1.ClusterComponentStatus{ - mysqlCompName: { + defaultCompName: { Phase: appsv1alpha1.RunningClusterCompPhase, }, } @@ -275,7 +268,6 @@ var _ = Describe("Restore", func() { g.Expect(tmpCluster.Annotations[constant.RestoreFromBackupAnnotationKey]).Should(BeEmpty()) })).Should(Succeed()) }) - }) }) diff --git a/pkg/controller/scheduling/scheduling_utils.go b/pkg/controller/scheduling/scheduling_utils.go index b1e42009c578..288b37f300b7 100644 --- a/pkg/controller/scheduling/scheduling_utils.go +++ b/pkg/controller/scheduling/scheduling_utils.go @@ -226,21 +226,9 @@ func buildNewAffinity4Legacy(clusterName, compName string, compAffinity *appsv1a } } // Add pod PodAffinityTerm for dedicated node - if compAffinity.Tenancy == appsv1alpha1.DedicatedNode { - var labelSelectorReqs []metav1.LabelSelectorRequirement - labelSelectorReqs = append(labelSelectorReqs, metav1.LabelSelectorRequirement{ - Key: constant.WorkloadTypeLabelKey, - Operator: metav1.LabelSelectorOpIn, - Values: appsv1alpha1.WorkloadTypes, - }) - podAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution = append( - podAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution, corev1.PodAffinityTerm{ - TopologyKey: corev1.LabelHostname, - LabelSelector: &metav1.LabelSelector{ - MatchExpressions: labelSelectorReqs, - }, - }) - } + // if compAffinity.Tenancy == appsv1alpha1.DedicatedNode { + // // TODO(v1.0): workload type has been removed + // } affinity.PodAntiAffinity = podAntiAffinity return affinity } diff --git a/pkg/controllerutil/cluster_utils_test.go b/pkg/controllerutil/cluster_utils_test.go index e900cbdd1ab6..107c79b9b565 100644 --- a/pkg/controllerutil/cluster_utils_test.go +++ b/pkg/controllerutil/cluster_utils_test.go @@ -55,29 +55,25 @@ var _ = Describe("cluster utils test", func() { Context("cluster utils test", func() { const ( - clusterDefName = "test-clusterdef" + compDefName = "test-compdef" clusterName = "test-cls" - mysqlCompDefName = "replicasets" mysqlCompName = "mysql" mysqlShardingName = "mysql-sharding" mysqlShardingCompName = "mysql-sharding-comp" ) var ( - clusterDef *appsv1alpha1.ClusterDefinition - cluster *appsv1alpha1.Cluster + cluster *appsv1alpha1.Cluster ) BeforeEach(func() { cleanEnv() - clusterDef = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). - GetObject() - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). + testapps.NewComponentDefinitionFactory(compDefName).SetDefaultSpec().GetObject() + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). SetUID(clusterName). - AddComponent(mysqlCompName, mysqlCompDefName). - AddShardingSpecV2(mysqlShardingName, mysqlCompDefName). + AddComponent(mysqlCompName, compDefName). + AddShardingSpec(mysqlShardingName, compDefName). SetShards(0). Create(&testCtx).GetObject() }) diff --git a/pkg/controllerutil/sharding_utils_test.go b/pkg/controllerutil/sharding_utils_test.go index d43b8a71f1b0..6d98ca93a909 100644 --- a/pkg/controllerutil/sharding_utils_test.go +++ b/pkg/controllerutil/sharding_utils_test.go @@ -55,29 +55,25 @@ var _ = Describe("cluster shard component", func() { Context("cluster shard component", func() { const ( - clusterDefName = "test-clusterdef" + compDefName = "test-compdef" clusterName = "test-cluster" - mysqlCompDefName = "replicasets" mysqlCompName = "mysql" mysqlShardingName = "mysql-sharding" mysqlShardingCompName = "mysql-sharding-comp" ) var ( - clusterDef *appsv1alpha1.ClusterDefinition - cluster *appsv1alpha1.Cluster + cluster *appsv1alpha1.Cluster ) BeforeEach(func() { cleanEnv() - clusterDef = testapps.NewClusterDefFactory(clusterDefName). - AddComponentDef(testapps.StatefulMySQLComponent, mysqlCompDefName). - GetObject() - cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDef.Name). + testapps.NewComponentDefinitionFactory(compDefName).SetDefaultSpec().GetObject() + cluster = testapps.NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). SetUID(clusterName). - AddComponent(mysqlCompName, mysqlCompDefName). - AddShardingSpecV2(mysqlShardingName, mysqlCompDefName). + AddComponent(mysqlCompName, compDefName). + AddShardingSpec(mysqlShardingName, compDefName). SetShards(1). Create(&testCtx).GetObject() }) diff --git a/pkg/testutil/apps/cluster_factory.go b/pkg/testutil/apps/cluster_factory.go index d1fe15aeaca7..4dbc385b9c06 100644 --- a/pkg/testutil/apps/cluster_factory.go +++ b/pkg/testutil/apps/cluster_factory.go @@ -68,20 +68,6 @@ func (factory *MockClusterFactory) AddClusterToleration(toleration corev1.Tolera } func (factory *MockClusterFactory) AddShardingSpec(shardingName string, compDefName string) *MockClusterFactory { - shardingSpec := appsv1alpha1.ShardingSpec{ - Template: appsv1alpha1.ClusterComponentSpec{ - Name: "fake", - ComponentDefRef: compDefName, - Replicas: 1, - }, - Name: shardingName, - Shards: 1, - } - factory.Get().Spec.ShardingSpecs = append(factory.Get().Spec.ShardingSpecs, shardingSpec) - return factory -} - -func (factory *MockClusterFactory) AddShardingSpecV2(shardingName string, compDefName string) *MockClusterFactory { shardingSpec := appsv1alpha1.ShardingSpec{ Template: appsv1alpha1.ClusterComponentSpec{ Name: "fake", @@ -96,15 +82,6 @@ func (factory *MockClusterFactory) AddShardingSpecV2(shardingName string, compDe } func (factory *MockClusterFactory) AddComponent(compName string, compDefName string) *MockClusterFactory { - comp := appsv1alpha1.ClusterComponentSpec{ - Name: compName, - ComponentDefRef: compDefName, - } - factory.Get().Spec.ComponentSpecs = append(factory.Get().Spec.ComponentSpecs, comp) - return factory -} - -func (factory *MockClusterFactory) AddComponentV2(compName string, compDefName string) *MockClusterFactory { comp := appsv1alpha1.ClusterComponentSpec{ Name: compName, ComponentDef: compDefName, diff --git a/pkg/testutil/apps/cluster_instance_set_test_util.go b/pkg/testutil/apps/cluster_instance_set_test_util.go index 036ec641fe39..a264cd9b42c3 100644 --- a/pkg/testutil/apps/cluster_instance_set_test_util.go +++ b/pkg/testutil/apps/cluster_instance_set_test_util.go @@ -40,43 +40,33 @@ import ( ) const ( - errorLogName = "error" - ConsensusReplicas = 3 + errorLogName = "error" + replicas = 3 ) -// InitConsensusMysql initializes a cluster environment which only contains a component of ConsensusSet type for testing, -// includes ClusterDefinition/Cluster resources. -func InitConsensusMysql(testCtx *testutil.TestContext, - clusterDefName, - clusterName, - consensusCompType, - consensusCompName string) (*appsv1alpha1.ClusterDefinition, *appsv1alpha1.Cluster) { - clusterDef := CreateConsensusMysqlClusterDef(testCtx, clusterDefName, consensusCompType) - cluster := CreateConsensusMysqlCluster(testCtx, clusterDefName, clusterName, consensusCompType, consensusCompName) - return clusterDef, cluster +func InitConsensusMysql(testCtx *testutil.TestContext, clusterName, compDefName, compName string) (*appsv1alpha1.ComponentDefinition, *appsv1alpha1.Cluster) { + compDef := createCompDef(testCtx, compDefName) + cluster := CreateDefaultMysqlCluster(testCtx, clusterName, compDef.GetName(), compName) + return compDef, cluster } -// CreateConsensusMysqlCluster creates a mysql cluster with a component of ConsensusSet type. -func CreateConsensusMysqlCluster( - testCtx *testutil.TestContext, - clusterDefName, - clusterName, - workloadType, - consensusCompName string, pvcSize ...string) *appsv1alpha1.Cluster { +func CreateDefaultMysqlCluster(testCtx *testutil.TestContext, clusterName, compDefName, compName string, pvcSize ...string) *appsv1alpha1.Cluster { size := "2Gi" if len(pvcSize) > 0 { size = pvcSize[0] } pvcSpec := NewPVCSpec(size) - return NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefName). - AddComponent(consensusCompName, workloadType).SetReplicas(ConsensusReplicas).SetEnabledLogs(errorLogName). - AddVolumeClaimTemplate("data", pvcSpec).Create(testCtx).GetObject() + return NewClusterFactory(testCtx.DefaultNamespace, clusterName, ""). + AddComponent(compName, compDefName). + SetReplicas(replicas). + SetEnabledLogs(errorLogName). + AddVolumeClaimTemplate("data", pvcSpec). + Create(testCtx). + GetObject() } -// CreateConsensusMysqlClusterDef creates a mysql clusterDefinition with a component of ConsensusSet type. -func CreateConsensusMysqlClusterDef(testCtx *testutil.TestContext, clusterDefName, componentDefName string) *appsv1alpha1.ClusterDefinition { - return NewClusterDefFactory(clusterDefName).AddComponentDef(ConsensusMySQLComponent, componentDefName). - Create(testCtx).GetObject() +func createCompDef(testCtx *testutil.TestContext, compDefName string) *appsv1alpha1.ComponentDefinition { + return NewComponentDefinitionFactory(compDefName).SetDefaultSpec().Create(testCtx).GetObject() } // MockInstanceSetComponent mocks the ITS component, just using in envTest @@ -85,7 +75,7 @@ func MockInstanceSetComponent( clusterName, itsCompName string) *workloads.InstanceSet { itsName := clusterName + "-" + itsCompName - return NewInstanceSetFactory(testCtx.DefaultNamespace, itsName, clusterName, itsCompName).SetReplicas(ConsensusReplicas). + return NewInstanceSetFactory(testCtx.DefaultNamespace, itsName, clusterName, itsCompName).SetReplicas(replicas). AddContainer(corev1.Container{Name: DefaultMySQLContainerName, Image: ApeCloudMySQLImage}). SetRoles([]workloads.ReplicaRole{ {Name: "leader", AccessMode: workloads.ReadWriteMode, CanVote: true, IsLeader: true}, @@ -98,10 +88,10 @@ func MockInstanceSetPods( testCtx *testutil.TestContext, its *workloads.InstanceSet, cluster *appsv1alpha1.Cluster, - consensusCompName string) []*corev1.Pod { + compName string) []*corev1.Pod { getReplicas := func() int { if its == nil || its.Spec.Replicas == nil { - return ConsensusReplicas + return replicas } return int(*its.Spec.Replicas) } @@ -130,7 +120,7 @@ func MockInstanceSetPods( replicas := getReplicas() replicasStr := strconv.Itoa(replicas) podList := make([]*corev1.Pod, replicas) - podNames := generatePodNames(cluster, consensusCompName) + podNames := generatePodNames(cluster, compName) for i, pName := range podNames { var podRole, accessMode string if its != nil && len(its.Spec.Roles) > 0 { @@ -142,7 +132,7 @@ func MockInstanceSetPods( accessMode = string(noneLeaderRole.AccessMode) } } - pod := MockInstanceSetPod(testCtx, its, cluster.Name, consensusCompName, pName, podRole, accessMode) + pod := MockInstanceSetPod(testCtx, its, cluster.Name, compName, pName, podRole, accessMode) annotations := pod.Annotations if annotations == nil { annotations = make(map[string]string) diff --git a/pkg/testutil/apps/cluster_util.go b/pkg/testutil/apps/cluster_util.go index 14304eb5cdba..43edc1f84a09 100644 --- a/pkg/testutil/apps/cluster_util.go +++ b/pkg/testutil/apps/cluster_util.go @@ -32,30 +32,6 @@ import ( "github.com/apecloud/kubeblocks/pkg/testutil" ) -// InitClusterWithHybridComps initializes a cluster environment for testing, includes ClusterDefinition/Cluster resources. -func InitClusterWithHybridComps( - testCtx *testutil.TestContext, - clusterDefName, - clusterName, - statelessCompDefName, - statefulCompDefName, - consensusCompDefName string) (*appsv1alpha1.ClusterDefinition, *appsv1alpha1.Cluster) { - clusterDef := NewClusterDefFactory(clusterDefName). - AddComponentDef(StatelessNginxComponent, statelessCompDefName). - AddComponentDef(ConsensusMySQLComponent, consensusCompDefName). - AddComponentDef(StatefulMySQLComponent, statefulCompDefName). - Create(testCtx).GetObject() - pvcSpec := NewPVCSpec("1Gi") - cluster := NewClusterFactory(testCtx.DefaultNamespace, clusterName, clusterDefName). - AddComponent(statelessCompDefName, statelessCompDefName).SetReplicas(1). - AddComponent(consensusCompDefName, consensusCompDefName).SetReplicas(3). - AddVolumeClaimTemplate(DataVolumeName, pvcSpec). - AddComponent(statefulCompDefName, statefulCompDefName).SetReplicas(3). - AddVolumeClaimTemplate(DataVolumeName, pvcSpec). - Create(testCtx).GetObject() - return clusterDef, cluster -} - func CreateK8sResource(testCtx *testutil.TestContext, obj client.Object) client.Object { gomega.Expect(testCtx.CreateObj(testCtx.Ctx, obj)).Should(gomega.Succeed()) // wait until cluster created diff --git a/pkg/testutil/apps/clusterdef_factory.go b/pkg/testutil/apps/clusterdef_factory.go index 112854422da5..66adb7448b1c 100644 --- a/pkg/testutil/apps/clusterdef_factory.go +++ b/pkg/testutil/apps/clusterdef_factory.go @@ -20,20 +20,9 @@ along with this program. If not, see . package apps import ( - corev1 "k8s.io/api/core/v1" - appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" ) -type ComponentDefTplType string - -const ( - StatefulMySQLComponent ComponentDefTplType = "stateful-mysql" - ConsensusMySQLComponent ComponentDefTplType = "consensus-mysql" - ReplicationRedisComponent ComponentDefTplType = "replication-redis" - StatelessNginxComponent ComponentDefTplType = "stateless-nginx" -) - type MockClusterDefFactory struct { BaseFactory[appsv1alpha1.ClusterDefinition, *appsv1alpha1.ClusterDefinition, MockClusterDefFactory] } @@ -42,133 +31,12 @@ func NewClusterDefFactory(name string) *MockClusterDefFactory { f := &MockClusterDefFactory{} f.Init("", name, &appsv1alpha1.ClusterDefinition{ - Spec: appsv1alpha1.ClusterDefinitionSpec{ - ComponentDefs: []appsv1alpha1.ClusterComponentDefinition{}, - }, + Spec: appsv1alpha1.ClusterDefinitionSpec{}, }, f) return f } -func (factory *MockClusterDefFactory) AddComponentDef(tplType ComponentDefTplType, compDefName string) *MockClusterDefFactory { - var component *appsv1alpha1.ClusterComponentDefinition - switch tplType { - case StatefulMySQLComponent: - component = &statefulMySQLComponent - case ConsensusMySQLComponent: - component = &consensusMySQLComponent - case ReplicationRedisComponent: - component = &replicationRedisComponent - case StatelessNginxComponent: - component = &statelessNginxComponent - } - factory.Get().Spec.ComponentDefs = append(factory.Get().Spec.ComponentDefs, *component) - comp := factory.getLastCompDef() - comp.Name = compDefName - return factory -} - -func (factory *MockClusterDefFactory) AddContainerEnv(containerName string, envVar corev1.EnvVar) *MockClusterDefFactory { - comp := factory.getLastCompDef() - if comp == nil { - return nil - } - for i, container := range comp.PodSpec.Containers { - if container.Name == containerName { - c := comp.PodSpec.Containers[i] - c.Env = append(c.Env, envVar) - comp.PodSpec.Containers[i] = c - break - } - } - return factory -} - -func (factory *MockClusterDefFactory) AddHorizontalScalePolicy(policy appsv1alpha1.HorizontalScalePolicy) *MockClusterDefFactory { - comp := factory.getLastCompDef() - if comp == nil { - return nil - } - comp.HorizontalScalePolicy = &policy - return factory -} - -func (factory *MockClusterDefFactory) getLastCompDef() *appsv1alpha1.ClusterComponentDefinition { - l := len(factory.Get().Spec.ComponentDefs) - if l == 0 { - return nil - } - comps := factory.Get().Spec.ComponentDefs - return &comps[l-1] -} - -func (factory *MockClusterDefFactory) AddSwitchoverSpec(switchoverSpec *appsv1alpha1.SwitchoverSpec) *MockClusterDefFactory { - comp := factory.getLastCompDef() - if comp == nil { - return factory - } - comp.SwitchoverSpec = switchoverSpec - return factory -} - -func (factory *MockClusterDefFactory) AddInitContainerVolumeMounts(containerName string, volumeMounts []corev1.VolumeMount) *MockClusterDefFactory { - comp := factory.getLastCompDef() - if comp == nil { - return factory - } - comp.PodSpec.InitContainers = appendContainerVolumeMounts(comp.PodSpec.InitContainers, containerName, volumeMounts) - return factory -} - -func (factory *MockClusterDefFactory) AddContainerVolumeMounts(containerName string, volumeMounts []corev1.VolumeMount) *MockClusterDefFactory { - comp := factory.getLastCompDef() - if comp == nil { - return factory - } - comp.PodSpec.Containers = appendContainerVolumeMounts(comp.PodSpec.Containers, containerName, volumeMounts) - return factory -} - -func (factory *MockClusterDefFactory) AddReplicationSpec(replicationSpec *appsv1alpha1.ReplicationSetSpec) *MockClusterDefFactory { - comp := factory.getLastCompDef() - if comp == nil { - return factory - } - comp.ReplicationSpec = replicationSpec - return factory -} - func (factory *MockClusterDefFactory) AddClusterTopology(topology appsv1alpha1.ClusterTopology) *MockClusterDefFactory { factory.Get().Spec.Topologies = append(factory.Get().Spec.Topologies, topology) return factory } - -// There are default volumeMounts for containers in clusterdefinition in pusrpose of a simple & fast creation, -// but when mounts specified volumes in certain mountPaths, they may conflict with the default volumeMounts, -// so here provides a way to overwrite the default volumeMounts. -func appendContainerVolumeMounts(containers []corev1.Container, targetContainerName string, volumeMounts []corev1.VolumeMount) []corev1.Container { - for index := range containers { - c := &containers[index] - // remove the duplicated volumeMounts and overwrite the default mount path - if c.Name == targetContainerName { - mergedAddVolumeMounts(c, volumeMounts) - break - } - } - return containers -} - -func mergedAddVolumeMounts(c *corev1.Container, volumeMounts []corev1.VolumeMount) { - table := make(map[string]corev1.VolumeMount) - for _, v := range c.VolumeMounts { - table[v.Name] = v - } - for _, v := range volumeMounts { - table[v.Name] = v - } - - mounts := make([]corev1.VolumeMount, 0) - for _, v := range table { - mounts = append(mounts, v) - } - c.VolumeMounts = mounts -} diff --git a/pkg/testutil/apps/componentdefinition_factory.go b/pkg/testutil/apps/componentdefinition_factory.go index 78af67ccc69c..f29e00f2cf70 100644 --- a/pkg/testutil/apps/componentdefinition_factory.go +++ b/pkg/testutil/apps/componentdefinition_factory.go @@ -337,3 +337,19 @@ func (f *MockComponentDefinitionFactory) AddServiceRef(name, serviceKind, servic f.Get().Spec.ServiceRefDeclarations = append(f.Get().Spec.ServiceRefDeclarations, serviceRef) return f } + +func mergedAddVolumeMounts(c *corev1.Container, volumeMounts []corev1.VolumeMount) { + table := make(map[string]corev1.VolumeMount) + for _, v := range c.VolumeMounts { + table[v.Name] = v + } + for _, v := range volumeMounts { + table[v.Name] = v + } + + mounts := make([]corev1.VolumeMount, 0) + for _, v := range table { + mounts = append(mounts, v) + } + c.VolumeMounts = mounts +} diff --git a/pkg/testutil/apps/constant.go b/pkg/testutil/apps/constant.go index e9f0c1f9cfe3..4ae38fa0d51e 100644 --- a/pkg/testutil/apps/constant.go +++ b/pkg/testutil/apps/constant.go @@ -38,22 +38,12 @@ const ( ServiceVPCName = "vpc-lb" ServiceInternetName = "internet-lb" - ReplicationPodRoleVolume = "pod-role" - ReplicationRoleLabelFieldPath = "metadata.labels['kubeblocks.io/role']" - DefaultReplicationReplicas = 2 - ApeCloudMySQLImage = "docker.io/apecloud/apecloud-mysql-server:latest" DefaultMySQLContainerName = "mysql" NginxImage = "nginx" DefaultNginxContainerName = "nginx" - DefaultRedisCompDefName = "redis" - DefaultRedisCompSpecName = "redis-rsts" - DefaultRedisImageName = "redis:7.0.5" - DefaultRedisContainerName = "redis" - DefaultRedisInitContainerName = "redis-init-container" - DefaultConfigSpecName = "config-cm" DefaultConfigSpecTplRef = "env-from-config-tpl" DefaultConfigSpecVolumeName = "volume" @@ -76,24 +66,6 @@ var ( }, } - statelessNginxComponent = appsv1alpha1.ClusterComponentDefinition{ - WorkloadType: appsv1alpha1.Stateless, - Probes: &appsv1alpha1.ClusterDefinitionProbes{ - RoleProbe: &appsv1alpha1.ClusterDefinitionProbe{ - FailureThreshold: 3, - PeriodSeconds: 1, - TimeoutSeconds: 5, - }, - }, - PodSpec: &corev1.PodSpec{ - Containers: []corev1.Container{{ - Name: DefaultNginxContainerName, - Image: NginxImage, - Resources: zeroResRequirements, - }}, - }, - } - defaultMySQLContainer = corev1.Container{ Name: DefaultMySQLContainerName, Image: ApeCloudMySQLImage, @@ -129,53 +101,6 @@ var ( Command: []string{"/scripts/setup.sh"}, } - statefulMySQLComponent = appsv1alpha1.ClusterComponentDefinition{ - WorkloadType: appsv1alpha1.Stateful, - Probes: &appsv1alpha1.ClusterDefinitionProbes{ - RoleProbe: &appsv1alpha1.ClusterDefinitionProbe{ - FailureThreshold: 3, - PeriodSeconds: 1, - TimeoutSeconds: 5, - }, - }, - PodSpec: &corev1.PodSpec{ - Containers: []corev1.Container{ - defaultMySQLContainer, - }, - }, - } - - defaultConsensusSpec = appsv1alpha1.ConsensusSetSpec{ - Leader: appsv1alpha1.ConsensusMember{ - Name: "leader", - AccessMode: appsv1alpha1.ReadWrite, - }, - Followers: []appsv1alpha1.ConsensusMember{{ - Name: "follower", - AccessMode: appsv1alpha1.Readonly, - }}, - StatefulSetSpec: appsv1alpha1.StatefulSetSpec{ - UpdateStrategy: appsv1alpha1.BestEffortParallelStrategy, - }, - } - - consensusMySQLComponent = appsv1alpha1.ClusterComponentDefinition{ - WorkloadType: appsv1alpha1.Consensus, - ConsensusSpec: &defaultConsensusSpec, - Probes: &appsv1alpha1.ClusterDefinitionProbes{ - RoleProbe: &appsv1alpha1.ClusterDefinitionProbe{ - FailureThreshold: 3, - PeriodSeconds: 1, - TimeoutSeconds: 5, - }, - }, - PodSpec: &corev1.PodSpec{ - Containers: []corev1.Container{ - defaultMySQLContainer, - }, - }, - } - defaultComponentDefSpec = appsv1alpha1.ComponentDefinitionSpec{ Provider: "kubeblocks.io", Description: "ApeCloud MySQL is a database that is compatible with MySQL syntax and achieves high availability\n through the utilization of the RAFT consensus protocol.", @@ -276,6 +201,7 @@ var ( }, }, }, + UpdateStrategy: &[]appsv1alpha1.UpdateStrategy{appsv1alpha1.BestEffortParallelStrategy}[0], Roles: []appsv1alpha1.ReplicaRole{ { Name: "leader", @@ -342,95 +268,6 @@ var ( }, } - defaultReplicationRedisVolumeMounts = []corev1.VolumeMount{ - { - Name: DataVolumeName, - MountPath: "/data", - }, - { - Name: ScriptsVolumeName, - MountPath: "/scripts", - }, - { - Name: ConfVolumeName, - MountPath: "/etc/conf", - }, - { - Name: ReplicationPodRoleVolume, - MountPath: "/etc/conf/role", - }, - } - - defaultRedisInitContainer = corev1.Container{ - Name: DefaultRedisInitContainerName, - Image: DefaultRedisImageName, - ImagePullPolicy: corev1.PullIfNotPresent, - VolumeMounts: defaultReplicationRedisVolumeMounts, - Command: []string{"/scripts/init.sh"}, - Resources: zeroResRequirements, - } - - defaultRedisContainer = corev1.Container{ - Name: DefaultRedisContainerName, - Image: DefaultRedisImageName, - ImagePullPolicy: corev1.PullIfNotPresent, - Ports: []corev1.ContainerPort{ - { - Name: "redis", - Protocol: corev1.ProtocolTCP, - ContainerPort: 6379, - }, - }, - VolumeMounts: defaultReplicationRedisVolumeMounts, - Args: []string{"/etc/conf/redis.conf"}, - Lifecycle: &corev1.Lifecycle{ - PostStart: &corev1.LifecycleHandler{ - Exec: &corev1.ExecAction{ - Command: []string{"/scripts/setup.sh"}, - }, - }, - }, - Resources: zeroResRequirements, - } - - replicationRedisComponent = appsv1alpha1.ClusterComponentDefinition{ - WorkloadType: appsv1alpha1.Replication, - Probes: &appsv1alpha1.ClusterDefinitionProbes{ - RoleProbe: &appsv1alpha1.ClusterDefinitionProbe{ - FailureThreshold: 3, - PeriodSeconds: 1, - TimeoutSeconds: 5, - }, - }, - PodSpec: &corev1.PodSpec{ - Volumes: []corev1.Volume{ - { - Name: ConfVolumeName, - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: ReplicationPodRoleVolume, - VolumeSource: corev1.VolumeSource{ - DownwardAPI: &corev1.DownwardAPIVolumeSource{ - Items: []corev1.DownwardAPIVolumeFile{ - { - Path: "labels", - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: ReplicationRoleLabelFieldPath, - }, - }, - }, - }, - }, - }, - }, - InitContainers: []corev1.Container{defaultRedisInitContainer}, - Containers: []corev1.Container{defaultRedisContainer}, - }, - } - defaultComponentVerSpec = func(compDef string) appsv1alpha1.ComponentVersionSpec { return appsv1alpha1.ComponentVersionSpec{ CompatibilityRules: []appsv1alpha1.ComponentVersionCompatibilityRule{ diff --git a/pkg/testutil/dataprotection/backup_utils.go b/pkg/testutil/dataprotection/backup_utils.go index 8deed3a928ab..a756f5c5a3a2 100644 --- a/pkg/testutil/dataprotection/backup_utils.go +++ b/pkg/testutil/dataprotection/backup_utils.go @@ -177,9 +177,10 @@ func NewFakeCluster(testCtx *testutil.TestContext) *BackupClusterInfo { } By("mocking a cluster") - cluster := testapps.NewClusterFactory(testCtx.DefaultNamespace, ClusterName, "test-cd"). + cluster := testapps.NewClusterFactory(testCtx.DefaultNamespace, ClusterName, ""). AddLabels(constant.AppInstanceLabelKey, ClusterName). - AddComponent("test-cmp", "test-cmpd").AddSystemAccount("test-account", nil, nil). + AddComponent("test-cmp", "test-cmpd"). + AddSystemAccount("test-account", nil, nil). Create(testCtx).GetObject() podName := ClusterName + "-" + ComponentName From 643cfb1262f13bb533c1fb0378ce442305b6d340 Mon Sep 17 00:00:00 2001 From: wanglong <46259301+gnolong@users.noreply.github.com> Date: Wed, 7 Aug 2024 17:20:58 +0800 Subject: [PATCH 42/45] fix: use len function to check targetPods slice (#7936) --- controllers/dataprotection/utils.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/controllers/dataprotection/utils.go b/controllers/dataprotection/utils.go index f31462452a25..f1c0e5493ad2 100644 --- a/controllers/dataprotection/utils.go +++ b/controllers/dataprotection/utils.go @@ -199,7 +199,10 @@ func GetTargetPods(reqCtx intctrlutil.RequestCtx, if err != nil { return nil, err } - if selector.Strategy == dpv1alpha1.PodSelectionStrategyAll || targetPods != nil || + // if selector.LabelSelector fails to filter a available target pod or the selected target pod, + // use selector.FallbackLabelSelector to filter, and selector.FallbackLabelSelector only takes effect + // when selector.Strategy equals to dpv1alpha1.PodSelectionStrategyAny. + if selector.Strategy == dpv1alpha1.PodSelectionStrategyAll || len(targetPods) > 0 || selector.FallbackLabelSelector == nil { return targetPods, nil } From 513f2abfd72641559578cb2eb1ca0f3c1a615c11 Mon Sep 17 00:00:00 2001 From: free6om Date: Wed, 7 Aug 2024 17:28:49 +0800 Subject: [PATCH 43/45] chore: remove dependency on pkg k8s.io/kubernetes (#7937) --- apis/apps/v1alpha1/cluster_types.go | 2 +- cmd/manager/main.go | 1 + .../bases/apps.kubeblocks.io_clusters.yaml | 1377 +++++++++++++---- ...ps.kubeblocks.io_componentdefinitions.yaml | 351 ++++- .../bases/apps.kubeblocks.io_components.yaml | 613 ++++++-- .../apps.kubeblocks.io_opsdefinitions.yaml | 357 ++++- .../bases/apps.kubeblocks.io_opsrequests.yaml | 630 ++++++-- ...dataprotection.kubeblocks.io_restores.yaml | 226 ++- .../workloads.kubeblocks.io_instancesets.yaml | 794 ++++++++-- controllers/apps/transform_utils.go | 10 +- controllers/apps/transform_utils_test.go | 2 +- .../crds/apps.kubeblocks.io_clusters.yaml | 1377 +++++++++++++---- ...ps.kubeblocks.io_componentdefinitions.yaml | 351 ++++- .../crds/apps.kubeblocks.io_components.yaml | 613 ++++++-- .../apps.kubeblocks.io_opsdefinitions.yaml | 357 ++++- .../crds/apps.kubeblocks.io_opsrequests.yaml | 630 ++++++-- ...dataprotection.kubeblocks.io_restores.yaml | 226 ++- .../workloads.kubeblocks.io_instancesets.yaml | 794 ++++++++-- deploy/helm/templates/deployment.yaml | 2 + deploy/helm/values.yaml | 2 + docs/developer_docs/api-reference/cluster.md | 8 +- go.mod | 139 +- go.sum | 497 +++--- .../informers/externalversions/factory.go | 10 + pkg/constant/flag.go | 4 + .../builder/builder_instance_set_test.go | 4 +- pkg/controller/builder/builder_pvc.go | 2 +- pkg/controller/builder/builder_pvc_test.go | 2 +- .../builder/builder_stateful_set_test.go | 4 +- .../configuration/config_template_test.go | 2 +- .../instanceset/in_place_update_util.go | 4 +- .../instanceset/instance_util_test.go | 4 +- pkg/controller/instanceset/suite_test.go | 2 +- .../kubebuilderx/plan_builder_test.go | 2 +- pkg/controllerutil/pod_utils_test.go | 6 +- pkg/lorry/client/k8sexec_client.go | 2 +- pkg/testutil/apps/cluster_util.go | 2 +- pkg/testutil/apps/native_object_util.go | 2 +- pkg/testutil/apps/pvc_factoy.go | 2 +- .../dataprotection/restore_factory.go | 2 +- test/e2e/e2e_suite_test.go | 14 +- test/e2e/util/client.go | 8 +- test/e2e/util/common.go | 2 +- 43 files changed, 7381 insertions(+), 2058 deletions(-) diff --git a/apis/apps/v1alpha1/cluster_types.go b/apis/apps/v1alpha1/cluster_types.go index 026fe1cf25b4..cd2d179d1407 100644 --- a/apis/apps/v1alpha1/cluster_types.go +++ b/apis/apps/v1alpha1/cluster_types.go @@ -993,7 +993,7 @@ type PersistentVolumeClaimSpec struct { // // +kubebuilder:pruning:PreserveUnknownFields // +optional - Resources corev1.ResourceRequirements `json:"resources,omitempty" protobuf:"bytes,2,opt,name=resources"` + Resources corev1.VolumeResourceRequirements `json:"resources,omitempty" protobuf:"bytes,2,opt,name=resources"` // The name of the StorageClass required by the claim. // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1. diff --git a/cmd/manager/main.go b/cmd/manager/main.go index c7f0a003954e..b4a7d5713859 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -146,6 +146,7 @@ func init() { viper.SetDefault(constant.CfgKBReconcileWorkers, 8) viper.SetDefault(constant.FeatureGateIgnoreConfigTemplateDefaultMode, false) viper.SetDefault(constant.FeatureGateComponentReplicasAnnotation, true) + viper.SetDefault(constant.FeatureGateInPlacePodVerticalScaling, false) } type flagName string diff --git a/config/crd/bases/apps.kubeblocks.io_clusters.yaml b/config/crd/bases/apps.kubeblocks.io_clusters.yaml index a1bb7628553b..50e115068a06 100644 --- a/config/crd/bases/apps.kubeblocks.io_clusters.yaml +++ b/config/crd/bases/apps.kubeblocks.io_clusters.yaml @@ -1123,9 +1123,9 @@ spec: weight. properties: labelSelector: - description: A label query over - a set of resources, in this case - pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -1171,6 +1171,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1273,8 +1303,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is @@ -1319,6 +1350,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1419,9 +1480,9 @@ spec: weight. properties: labelSelector: - description: A label query over - a set of resources, in this case - pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -1467,6 +1528,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1569,8 +1660,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is @@ -1615,6 +1707,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1985,34 +2107,6 @@ spec: are lower than the previous value but must still be higher than the capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources. properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2700,34 +2794,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2805,6 +2871,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -3215,6 +3296,102 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the + volume root to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -4179,8 +4356,9 @@ spec: associated with the corresponding weight. properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a @@ -4225,6 +4403,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -4326,8 +4534,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -4371,6 +4580,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -4469,8 +4708,9 @@ spec: associated with the corresponding weight. properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a @@ -4515,6 +4755,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -4616,8 +4886,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -4661,6 +4932,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5648,34 +5949,6 @@ spec: are lower than the previous value but must still be higher than the capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources. properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -6310,34 +6583,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -6414,6 +6659,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -6819,6 +7079,101 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -7646,8 +8001,9 @@ spec: with the corresponding weight. properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -7691,6 +8047,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -7791,8 +8177,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -7836,6 +8223,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -7934,8 +8351,9 @@ spec: with the corresponding weight. properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -7979,6 +8397,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -8079,8 +8527,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -8124,6 +8573,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -8735,7 +9214,7 @@ spec: * Kubernetes-defined prefixed names: - * 'kubernetes.io/h2c' - HTTP/2 over cleartext as described in https://www.rfc-editor.org/rfc/rfc7540 + * 'kubernetes.io/h2c' - HTTP/2 prior knowledge over cleartext as described in https://www.rfc-editor.org/rfc/rfc9113.html#name-starting-http-2-with-prior- * 'kubernetes.io/ws' - WebSocket over cleartext as described in https://www.rfc-editor.org/rfc/rfc6455 * 'kubernetes.io/wss' - WebSocket over TLS as described in https://www.rfc-editor.org/rfc/rfc6455 @@ -9771,9 +10250,9 @@ spec: weight. properties: labelSelector: - description: A label query over - a set of resources, in this - case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -9820,6 +10299,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -9923,9 +10432,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over - a set of resources, in this case - pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -9971,6 +10480,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -10073,9 +10612,9 @@ spec: weight. properties: labelSelector: - description: A label query over - a set of resources, in this - case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -10122,6 +10661,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -10225,9 +10794,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over - a set of resources, in this case - pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -10273,6 +10842,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -10646,34 +11245,6 @@ spec: are lower than the previous value but must still be higher than the capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources. properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -11369,35 +11940,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim - references one entry in - PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -11477,6 +12019,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -11891,6 +12448,104 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from + the volume root to write the + bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -12870,8 +13525,9 @@ spec: weight. properties: labelSelector: - description: A label query over a - set of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -12917,6 +13573,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -13019,8 +13705,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a @@ -13065,6 +13752,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -13165,8 +13882,9 @@ spec: weight. properties: labelSelector: - description: A label query over a - set of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -13212,6 +13930,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -13314,8 +14062,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a @@ -13360,6 +14109,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -14353,34 +15132,6 @@ spec: are lower than the previous value but must still be higher than the capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources. properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one - entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -15020,34 +15771,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -15125,6 +15848,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -15532,6 +16270,101 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the + volume root to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project diff --git a/config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml b/config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml index c714cf2fbfb5..54897077a10f 100644 --- a/config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml +++ b/config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml @@ -5364,8 +5364,9 @@ spec: with the corresponding weight. properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -5409,6 +5410,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5509,8 +5540,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -5554,6 +5586,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5652,8 +5714,9 @@ spec: with the corresponding weight. properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -5697,6 +5760,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5797,8 +5890,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -5842,6 +5936,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -6209,6 +6333,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -6307,6 +6443,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -7591,6 +7739,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -7689,6 +7849,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -8968,6 +9140,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -9066,6 +9250,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -11261,34 +11457,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -11365,6 +11533,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -11770,6 +11953,100 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -12847,7 +13124,7 @@ spec: * Kubernetes-defined prefixed names: - * 'kubernetes.io/h2c' - HTTP/2 over cleartext as described in https://www.rfc-editor.org/rfc/rfc7540 + * 'kubernetes.io/h2c' - HTTP/2 prior knowledge over cleartext as described in https://www.rfc-editor.org/rfc/rfc9113.html#name-starting-http-2-with-prior- * 'kubernetes.io/ws' - WebSocket over cleartext as described in https://www.rfc-editor.org/rfc/rfc6455 * 'kubernetes.io/wss' - WebSocket over TLS as described in https://www.rfc-editor.org/rfc/rfc6455 diff --git a/config/crd/bases/apps.kubeblocks.io_components.yaml b/config/crd/bases/apps.kubeblocks.io_components.yaml index f34bcbc6a439..fbe8afc4f849 100644 --- a/config/crd/bases/apps.kubeblocks.io_components.yaml +++ b/config/crd/bases/apps.kubeblocks.io_components.yaml @@ -862,8 +862,9 @@ spec: associated with the corresponding weight. properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a @@ -908,6 +909,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1009,8 +1040,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -1054,6 +1086,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1152,8 +1214,9 @@ spec: associated with the corresponding weight. properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a @@ -1198,6 +1261,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1299,8 +1392,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -1344,6 +1438,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1713,34 +1837,6 @@ spec: are lower than the previous value but must still be higher than the capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources. properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2422,34 +2518,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2526,6 +2594,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -2931,6 +3014,101 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -3801,8 +3979,9 @@ spec: with the corresponding weight. properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -3846,6 +4025,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -3946,8 +4155,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -3991,6 +4201,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -4089,8 +4329,9 @@ spec: with the corresponding weight. properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -4134,6 +4375,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -4234,8 +4505,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -4279,6 +4551,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5103,7 +5405,7 @@ spec: * Kubernetes-defined prefixed names: - * 'kubernetes.io/h2c' - HTTP/2 over cleartext as described in https://www.rfc-editor.org/rfc/rfc7540 + * 'kubernetes.io/h2c' - HTTP/2 prior knowledge over cleartext as described in https://www.rfc-editor.org/rfc/rfc9113.html#name-starting-http-2-with-prior- * 'kubernetes.io/ws' - WebSocket over cleartext as described in https://www.rfc-editor.org/rfc/rfc6455 * 'kubernetes.io/wss' - WebSocket over TLS as described in https://www.rfc-editor.org/rfc/rfc6455 @@ -5482,34 +5784,6 @@ spec: are lower than the previous value but must still be higher than the capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources. properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry in - PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -6139,34 +6413,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one - entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -6243,6 +6489,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -6646,6 +6907,100 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions is a list of + label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume root + to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project diff --git a/config/crd/bases/apps.kubeblocks.io_opsdefinitions.yaml b/config/crd/bases/apps.kubeblocks.io_opsdefinitions.yaml index 1d4b9468209e..f4809619b1e0 100644 --- a/config/crd/bases/apps.kubeblocks.io_opsdefinitions.yaml +++ b/config/crd/bases/apps.kubeblocks.io_opsdefinitions.yaml @@ -500,8 +500,9 @@ spec: weight. properties: labelSelector: - description: A label query over a - set of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -547,6 +548,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -649,8 +680,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a @@ -695,6 +727,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -795,8 +857,9 @@ spec: weight. properties: labelSelector: - description: A label query over a - set of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -842,6 +905,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -944,8 +1037,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a @@ -990,6 +1084,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1371,6 +1495,19 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration + that the container should sleep before + being terminated. + properties: + seconds: + description: Seconds is the number + of seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -1475,6 +1612,19 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration + that the container should sleep before + being terminated. + properties: + seconds: + description: Seconds is the number + of seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -2785,6 +2935,19 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration + that the container should sleep before + being terminated. + properties: + seconds: + description: Seconds is the number + of seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -2889,6 +3052,19 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration + that the container should sleep before + being terminated. + properties: + seconds: + description: Seconds is the number + of seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -4197,6 +4373,19 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration + that the container should sleep before + being terminated. + properties: + seconds: + description: Seconds is the number + of seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -4301,6 +4490,19 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration + that the container should sleep before + being terminated. + properties: + seconds: + description: Seconds is the number + of seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -6524,34 +6726,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -6630,6 +6804,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -7042,6 +7231,102 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from + the volume root to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project diff --git a/config/crd/bases/apps.kubeblocks.io_opsrequests.yaml b/config/crd/bases/apps.kubeblocks.io_opsrequests.yaml index 7c703b54575e..5551e540d88b 100644 --- a/config/crd/bases/apps.kubeblocks.io_opsrequests.yaml +++ b/config/crd/bases/apps.kubeblocks.io_opsrequests.yaml @@ -422,7 +422,7 @@ spec: * Kubernetes-defined prefixed names: - * 'kubernetes.io/h2c' - HTTP/2 over cleartext as described in https://www.rfc-editor.org/rfc/rfc7540 + * 'kubernetes.io/h2c' - HTTP/2 prior knowledge over cleartext as described in https://www.rfc-editor.org/rfc/rfc9113.html#name-starting-http-2-with-prior- * 'kubernetes.io/ws' - WebSocket over cleartext as described in https://www.rfc-editor.org/rfc/rfc6455 * 'kubernetes.io/wss' - WebSocket over TLS as described in https://www.rfc-editor.org/rfc/rfc6455 @@ -1099,9 +1099,9 @@ spec: weight. properties: labelSelector: - description: A label query over - a set of resources, in this - case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -1148,6 +1148,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1251,9 +1281,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over - a set of resources, in this case - pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -1299,6 +1329,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1401,9 +1461,9 @@ spec: weight. properties: labelSelector: - description: A label query over - a set of resources, in this - case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -1450,6 +1510,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1553,9 +1643,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over - a set of resources, in this case - pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -1601,6 +1691,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1974,34 +2094,6 @@ spec: are lower than the previous value but must still be higher than the capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources. properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2697,35 +2789,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim - references one entry in - PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2805,6 +2868,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -3219,6 +3297,104 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from + the volume root to write the + bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -5613,9 +5789,9 @@ spec: weight. properties: labelSelector: - description: A label query over - a set of resources, in this - case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -5662,6 +5838,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5765,9 +5971,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over - a set of resources, in this case - pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -5813,6 +6019,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5915,9 +6151,9 @@ spec: weight. properties: labelSelector: - description: A label query over - a set of resources, in this - case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -5964,6 +6200,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -6067,9 +6333,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over - a set of resources, in this case - pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -6115,6 +6381,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -6488,34 +6784,6 @@ spec: are lower than the previous value but must still be higher than the capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources. properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -7211,35 +7479,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim - references one entry in - PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -7319,6 +7558,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -7733,6 +7987,104 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from + the volume root to write the + bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project diff --git a/config/crd/bases/dataprotection.kubeblocks.io_restores.yaml b/config/crd/bases/dataprotection.kubeblocks.io_restores.yaml index bcd3ca3b0af6..7558c29bef53 100644 --- a/config/crd/bases/dataprotection.kubeblocks.io_restores.yaml +++ b/config/crd/bases/dataprotection.kubeblocks.io_restores.yaml @@ -549,8 +549,9 @@ spec: associated with the corresponding weight. properties: labelSelector: - description: A label query over a set of - resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -595,6 +596,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -696,8 +727,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -741,6 +773,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -839,8 +901,9 @@ spec: associated with the corresponding weight. properties: labelSelector: - description: A label query over a set of - resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -885,6 +948,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -986,8 +1079,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -1031,6 +1125,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1495,34 +1619,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -1598,6 +1694,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -1772,34 +1883,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one - entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -1876,6 +1959,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. diff --git a/config/crd/bases/workloads.kubeblocks.io_instancesets.yaml b/config/crd/bases/workloads.kubeblocks.io_instancesets.yaml index 3e86dca55a8d..4107840c4484 100644 --- a/config/crd/bases/workloads.kubeblocks.io_instancesets.yaml +++ b/config/crd/bases/workloads.kubeblocks.io_instancesets.yaml @@ -806,8 +806,9 @@ spec: associated with the corresponding weight. properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a @@ -852,6 +853,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -953,8 +984,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -998,6 +1030,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1096,8 +1158,9 @@ spec: associated with the corresponding weight. properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a @@ -1142,6 +1205,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1243,8 +1336,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -1288,6 +1382,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1761,34 +1885,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -1865,6 +1961,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -2021,6 +2132,41 @@ spec: - type type: object type: array + currentVolumeAttributesClassName: + description: |- + currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using. + When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim + This is an alpha field and requires enabling VolumeAttributesClass feature. + type: string + modifyVolumeStatus: + description: |- + ModifyVolumeStatus represents the status object of ControllerModifyVolume operation. + When this is unset, there is no ModifyVolume operation being attempted. + This is an alpha field and requires enabling VolumeAttributesClass feature. + properties: + status: + description: "status is the status of the ControllerModifyVolume + operation. It can be in any of following states:\n + - Pending\n Pending indicates that the PersistentVolumeClaim + cannot be modified due to unmet requirements, + such as\n the specified VolumeAttributesClass + not existing.\n - InProgress\n InProgress + indicates that the volume is being modified.\n + - Infeasible\n Infeasible indicates that the + request has been rejected as invalid by the + CSI driver. To\n\t resolve the error, a valid + VolumeAttributesClass needs to be specified.\nNote: + New statuses can be added in the future. Consumers + should check for unknown statuses and fail appropriately." + type: string + targetVolumeAttributesClassName: + description: targetVolumeAttributesClassName is + the name of the VolumeAttributesClass the PVC + currently being reconciled + type: string + required: + - status + type: object phase: description: phase represents the current phase of PersistentVolumeClaim. @@ -2669,34 +2815,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2773,6 +2891,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -3178,6 +3311,101 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -4364,7 +4592,7 @@ spec: * Kubernetes-defined prefixed names: - * 'kubernetes.io/h2c' - HTTP/2 over cleartext as described in https://www.rfc-editor.org/rfc/rfc7540 + * 'kubernetes.io/h2c' - HTTP/2 prior knowledge over cleartext as described in https://www.rfc-editor.org/rfc/rfc9113.html#name-starting-http-2-with-prior- * 'kubernetes.io/ws' - WebSocket over cleartext as described in https://www.rfc-editor.org/rfc/rfc6455 * 'kubernetes.io/wss' - WebSocket over TLS as described in https://www.rfc-editor.org/rfc/rfc6455 @@ -4600,6 +4828,15 @@ spec: IP is set for load-balancer ingress points that are IP based (typically GCE or OpenStack load-balancers) type: string + ipMode: + description: |- + IPMode specifies how the load-balancer IP behaves, and may only be specified when the ip field is specified. + Setting this to "VIP" indicates that traffic is delivered to the node with + the destination set to the load-balancer's IP and port. + Setting this to "Proxy" indicates that traffic is delivered to the node or pod with + the destination set to the node's IP and node port or the pod's IP and port. + Service implementations may use this information to adjust traffic routing. + type: string ports: description: |- Ports is a list of records of service ports @@ -4900,8 +5137,9 @@ spec: associated with the corresponding weight. properties: labelSelector: - description: A label query over a set of - resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -4946,6 +5184,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5047,8 +5315,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -5092,6 +5361,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5190,8 +5489,9 @@ spec: associated with the corresponding weight. properties: labelSelector: - description: A label query over a set of - resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -5236,6 +5536,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5337,8 +5667,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -5382,6 +5713,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5753,6 +6114,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -5852,6 +6225,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -7145,6 +7530,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -7244,6 +7641,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -8531,6 +8940,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -8630,6 +9051,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -10834,34 +11267,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -10939,6 +11344,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -11344,6 +11764,101 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions is a + list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -12064,34 +12579,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry in - PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -12167,6 +12654,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -12315,6 +12817,40 @@ spec: - type type: object type: array + currentVolumeAttributesClassName: + description: |- + currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using. + When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim + This is an alpha field and requires enabling VolumeAttributesClass feature. + type: string + modifyVolumeStatus: + description: |- + ModifyVolumeStatus represents the status object of ControllerModifyVolume operation. + When this is unset, there is no ModifyVolume operation being attempted. + This is an alpha field and requires enabling VolumeAttributesClass feature. + properties: + status: + description: "status is the status of the ControllerModifyVolume + operation. It can be in any of following states:\n + - Pending\n Pending indicates that the PersistentVolumeClaim + cannot be modified due to unmet requirements, such + as\n the specified VolumeAttributesClass not existing.\n + - InProgress\n InProgress indicates that the volume + is being modified.\n - Infeasible\n Infeasible indicates + that the request has been rejected as invalid by the + CSI driver. To\n\t resolve the error, a valid VolumeAttributesClass + needs to be specified.\nNote: New statuses can be + added in the future. Consumers should check for unknown + statuses and fail appropriately." + type: string + targetVolumeAttributesClassName: + description: targetVolumeAttributesClassName is the + name of the VolumeAttributesClass the PVC currently + being reconciled + type: string + required: + - status + type: object phase: description: phase represents the current phase of PersistentVolumeClaim. type: string diff --git a/controllers/apps/transform_utils.go b/controllers/apps/transform_utils.go index 535cbcce6822..eaf9db33e41c 100644 --- a/controllers/apps/transform_utils.go +++ b/controllers/apps/transform_utils.go @@ -131,6 +131,10 @@ func sendWarningEventWithError( recorder.Event(obj, corev1.EventTypeWarning, reason, err.Error()) } +func isVolumeResourceRequirementsEqual(a, b corev1.VolumeResourceRequirements) bool { + return isResourceEqual(a.Requests, b.Requests) && isResourceEqual(a.Limits, b.Limits) +} + func isResourceRequirementsEqual(a, b corev1.ResourceRequirements) bool { return isResourceEqual(a.Requests, b.Requests) && isResourceEqual(a.Limits, b.Limits) } @@ -156,13 +160,13 @@ func isVolumeClaimTemplatesEqual(a, b []appsv1alpha1.ClusterComponentVolumeClaim // first check resource requirements c := a[i].DeepCopy() d := b[i].DeepCopy() - if !isResourceRequirementsEqual(c.Spec.Resources, d.Spec.Resources) { + if !isVolumeResourceRequirementsEqual(c.Spec.Resources, d.Spec.Resources) { return false } // then clear resource requirements and check other fields - c.Spec.Resources = corev1.ResourceRequirements{} - d.Spec.Resources = corev1.ResourceRequirements{} + c.Spec.Resources = corev1.VolumeResourceRequirements{} + d.Spec.Resources = corev1.VolumeResourceRequirements{} if !reflect.DeepEqual(c, d) { return false } diff --git a/controllers/apps/transform_utils_test.go b/controllers/apps/transform_utils_test.go index 71927274d9dd..7445add26116 100644 --- a/controllers/apps/transform_utils_test.go +++ b/controllers/apps/transform_utils_test.go @@ -70,7 +70,7 @@ func TestIsVolumeClaimTemplatesEqual(t *testing.T) { { Name: "data", Spec: appsv1alpha1.PersistentVolumeClaimSpec{ - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceStorage: resource.MustParse(size), }, diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml index a1bb7628553b..50e115068a06 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml @@ -1123,9 +1123,9 @@ spec: weight. properties: labelSelector: - description: A label query over - a set of resources, in this case - pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -1171,6 +1171,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1273,8 +1303,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is @@ -1319,6 +1350,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1419,9 +1480,9 @@ spec: weight. properties: labelSelector: - description: A label query over - a set of resources, in this case - pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -1467,6 +1528,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1569,8 +1660,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is @@ -1615,6 +1707,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1985,34 +2107,6 @@ spec: are lower than the previous value but must still be higher than the capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources. properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2700,34 +2794,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2805,6 +2871,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -3215,6 +3296,102 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the + volume root to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -4179,8 +4356,9 @@ spec: associated with the corresponding weight. properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a @@ -4225,6 +4403,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -4326,8 +4534,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -4371,6 +4580,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -4469,8 +4708,9 @@ spec: associated with the corresponding weight. properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a @@ -4515,6 +4755,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -4616,8 +4886,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -4661,6 +4932,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5648,34 +5949,6 @@ spec: are lower than the previous value but must still be higher than the capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources. properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -6310,34 +6583,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -6414,6 +6659,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -6819,6 +7079,101 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -7646,8 +8001,9 @@ spec: with the corresponding weight. properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -7691,6 +8047,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -7791,8 +8177,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -7836,6 +8223,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -7934,8 +8351,9 @@ spec: with the corresponding weight. properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -7979,6 +8397,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -8079,8 +8527,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -8124,6 +8573,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -8735,7 +9214,7 @@ spec: * Kubernetes-defined prefixed names: - * 'kubernetes.io/h2c' - HTTP/2 over cleartext as described in https://www.rfc-editor.org/rfc/rfc7540 + * 'kubernetes.io/h2c' - HTTP/2 prior knowledge over cleartext as described in https://www.rfc-editor.org/rfc/rfc9113.html#name-starting-http-2-with-prior- * 'kubernetes.io/ws' - WebSocket over cleartext as described in https://www.rfc-editor.org/rfc/rfc6455 * 'kubernetes.io/wss' - WebSocket over TLS as described in https://www.rfc-editor.org/rfc/rfc6455 @@ -9771,9 +10250,9 @@ spec: weight. properties: labelSelector: - description: A label query over - a set of resources, in this - case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -9820,6 +10299,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -9923,9 +10432,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over - a set of resources, in this case - pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -9971,6 +10480,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -10073,9 +10612,9 @@ spec: weight. properties: labelSelector: - description: A label query over - a set of resources, in this - case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -10122,6 +10661,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -10225,9 +10794,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over - a set of resources, in this case - pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -10273,6 +10842,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -10646,34 +11245,6 @@ spec: are lower than the previous value but must still be higher than the capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources. properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -11369,35 +11940,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim - references one entry in - PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -11477,6 +12019,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -11891,6 +12448,104 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from + the volume root to write the + bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -12870,8 +13525,9 @@ spec: weight. properties: labelSelector: - description: A label query over a - set of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -12917,6 +13573,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -13019,8 +13705,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a @@ -13065,6 +13752,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -13165,8 +13882,9 @@ spec: weight. properties: labelSelector: - description: A label query over a - set of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -13212,6 +13930,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -13314,8 +14062,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a @@ -13360,6 +14109,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -14353,34 +15132,6 @@ spec: are lower than the previous value but must still be higher than the capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources. properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one - entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -15020,34 +15771,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -15125,6 +15848,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -15532,6 +16270,101 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the + volume root to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project diff --git a/deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml b/deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml index c714cf2fbfb5..54897077a10f 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml @@ -5364,8 +5364,9 @@ spec: with the corresponding weight. properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -5409,6 +5410,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5509,8 +5540,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -5554,6 +5586,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5652,8 +5714,9 @@ spec: with the corresponding weight. properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -5697,6 +5760,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5797,8 +5890,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -5842,6 +5936,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -6209,6 +6333,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -6307,6 +6443,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -7591,6 +7739,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -7689,6 +7849,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -8968,6 +9140,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -9066,6 +9250,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -11261,34 +11457,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -11365,6 +11533,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -11770,6 +11953,100 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -12847,7 +13124,7 @@ spec: * Kubernetes-defined prefixed names: - * 'kubernetes.io/h2c' - HTTP/2 over cleartext as described in https://www.rfc-editor.org/rfc/rfc7540 + * 'kubernetes.io/h2c' - HTTP/2 prior knowledge over cleartext as described in https://www.rfc-editor.org/rfc/rfc9113.html#name-starting-http-2-with-prior- * 'kubernetes.io/ws' - WebSocket over cleartext as described in https://www.rfc-editor.org/rfc/rfc6455 * 'kubernetes.io/wss' - WebSocket over TLS as described in https://www.rfc-editor.org/rfc/rfc6455 diff --git a/deploy/helm/crds/apps.kubeblocks.io_components.yaml b/deploy/helm/crds/apps.kubeblocks.io_components.yaml index f34bcbc6a439..fbe8afc4f849 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_components.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_components.yaml @@ -862,8 +862,9 @@ spec: associated with the corresponding weight. properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a @@ -908,6 +909,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1009,8 +1040,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -1054,6 +1086,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1152,8 +1214,9 @@ spec: associated with the corresponding weight. properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a @@ -1198,6 +1261,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1299,8 +1392,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -1344,6 +1438,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1713,34 +1837,6 @@ spec: are lower than the previous value but must still be higher than the capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources. properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2422,34 +2518,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2526,6 +2594,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -2931,6 +3014,101 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -3801,8 +3979,9 @@ spec: with the corresponding weight. properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -3846,6 +4025,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -3946,8 +4155,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -3991,6 +4201,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -4089,8 +4329,9 @@ spec: with the corresponding weight. properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -4134,6 +4375,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -4234,8 +4505,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -4279,6 +4551,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5103,7 +5405,7 @@ spec: * Kubernetes-defined prefixed names: - * 'kubernetes.io/h2c' - HTTP/2 over cleartext as described in https://www.rfc-editor.org/rfc/rfc7540 + * 'kubernetes.io/h2c' - HTTP/2 prior knowledge over cleartext as described in https://www.rfc-editor.org/rfc/rfc9113.html#name-starting-http-2-with-prior- * 'kubernetes.io/ws' - WebSocket over cleartext as described in https://www.rfc-editor.org/rfc/rfc6455 * 'kubernetes.io/wss' - WebSocket over TLS as described in https://www.rfc-editor.org/rfc/rfc6455 @@ -5482,34 +5784,6 @@ spec: are lower than the previous value but must still be higher than the capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources. properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry in - PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -6139,34 +6413,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one - entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -6243,6 +6489,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -6646,6 +6907,100 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions is a list of + label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume root + to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project diff --git a/deploy/helm/crds/apps.kubeblocks.io_opsdefinitions.yaml b/deploy/helm/crds/apps.kubeblocks.io_opsdefinitions.yaml index 1d4b9468209e..f4809619b1e0 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_opsdefinitions.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_opsdefinitions.yaml @@ -500,8 +500,9 @@ spec: weight. properties: labelSelector: - description: A label query over a - set of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -547,6 +548,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -649,8 +680,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a @@ -695,6 +727,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -795,8 +857,9 @@ spec: weight. properties: labelSelector: - description: A label query over a - set of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -842,6 +905,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -944,8 +1037,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a @@ -990,6 +1084,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1371,6 +1495,19 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration + that the container should sleep before + being terminated. + properties: + seconds: + description: Seconds is the number + of seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -1475,6 +1612,19 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration + that the container should sleep before + being terminated. + properties: + seconds: + description: Seconds is the number + of seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -2785,6 +2935,19 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration + that the container should sleep before + being terminated. + properties: + seconds: + description: Seconds is the number + of seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -2889,6 +3052,19 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration + that the container should sleep before + being terminated. + properties: + seconds: + description: Seconds is the number + of seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -4197,6 +4373,19 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration + that the container should sleep before + being terminated. + properties: + seconds: + description: Seconds is the number + of seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -4301,6 +4490,19 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration + that the container should sleep before + being terminated. + properties: + seconds: + description: Seconds is the number + of seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -6524,34 +6726,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -6630,6 +6804,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -7042,6 +7231,102 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from + the volume root to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project diff --git a/deploy/helm/crds/apps.kubeblocks.io_opsrequests.yaml b/deploy/helm/crds/apps.kubeblocks.io_opsrequests.yaml index 7c703b54575e..5551e540d88b 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_opsrequests.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_opsrequests.yaml @@ -422,7 +422,7 @@ spec: * Kubernetes-defined prefixed names: - * 'kubernetes.io/h2c' - HTTP/2 over cleartext as described in https://www.rfc-editor.org/rfc/rfc7540 + * 'kubernetes.io/h2c' - HTTP/2 prior knowledge over cleartext as described in https://www.rfc-editor.org/rfc/rfc9113.html#name-starting-http-2-with-prior- * 'kubernetes.io/ws' - WebSocket over cleartext as described in https://www.rfc-editor.org/rfc/rfc6455 * 'kubernetes.io/wss' - WebSocket over TLS as described in https://www.rfc-editor.org/rfc/rfc6455 @@ -1099,9 +1099,9 @@ spec: weight. properties: labelSelector: - description: A label query over - a set of resources, in this - case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -1148,6 +1148,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1251,9 +1281,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over - a set of resources, in this case - pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -1299,6 +1329,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1401,9 +1461,9 @@ spec: weight. properties: labelSelector: - description: A label query over - a set of resources, in this - case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -1450,6 +1510,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1553,9 +1643,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over - a set of resources, in this case - pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -1601,6 +1691,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1974,34 +2094,6 @@ spec: are lower than the previous value but must still be higher than the capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources. properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2697,35 +2789,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim - references one entry in - PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2805,6 +2868,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -3219,6 +3297,104 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from + the volume root to write the + bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -5613,9 +5789,9 @@ spec: weight. properties: labelSelector: - description: A label query over - a set of resources, in this - case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -5662,6 +5838,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5765,9 +5971,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over - a set of resources, in this case - pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -5813,6 +6019,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5915,9 +6151,9 @@ spec: weight. properties: labelSelector: - description: A label query over - a set of resources, in this - case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -5964,6 +6200,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -6067,9 +6333,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over - a set of resources, in this case - pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions @@ -6115,6 +6381,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -6488,34 +6784,6 @@ spec: are lower than the previous value but must still be higher than the capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources. properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -7211,35 +7479,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim - references one entry in - PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -7319,6 +7558,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -7733,6 +7987,104 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from + the volume root to write the + bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project diff --git a/deploy/helm/crds/dataprotection.kubeblocks.io_restores.yaml b/deploy/helm/crds/dataprotection.kubeblocks.io_restores.yaml index bcd3ca3b0af6..7558c29bef53 100644 --- a/deploy/helm/crds/dataprotection.kubeblocks.io_restores.yaml +++ b/deploy/helm/crds/dataprotection.kubeblocks.io_restores.yaml @@ -549,8 +549,9 @@ spec: associated with the corresponding weight. properties: labelSelector: - description: A label query over a set of - resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -595,6 +596,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -696,8 +727,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -741,6 +773,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -839,8 +901,9 @@ spec: associated with the corresponding weight. properties: labelSelector: - description: A label query over a set of - resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -885,6 +948,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -986,8 +1079,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -1031,6 +1125,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1495,34 +1619,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -1598,6 +1694,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -1772,34 +1883,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one - entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -1876,6 +1959,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. diff --git a/deploy/helm/crds/workloads.kubeblocks.io_instancesets.yaml b/deploy/helm/crds/workloads.kubeblocks.io_instancesets.yaml index 3e86dca55a8d..4107840c4484 100644 --- a/deploy/helm/crds/workloads.kubeblocks.io_instancesets.yaml +++ b/deploy/helm/crds/workloads.kubeblocks.io_instancesets.yaml @@ -806,8 +806,9 @@ spec: associated with the corresponding weight. properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a @@ -852,6 +853,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -953,8 +984,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -998,6 +1030,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1096,8 +1158,9 @@ spec: associated with the corresponding weight. properties: labelSelector: - description: A label query over a set - of resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a @@ -1142,6 +1205,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1243,8 +1336,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -1288,6 +1382,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -1761,34 +1885,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -1865,6 +1961,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -2021,6 +2132,41 @@ spec: - type type: object type: array + currentVolumeAttributesClassName: + description: |- + currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using. + When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim + This is an alpha field and requires enabling VolumeAttributesClass feature. + type: string + modifyVolumeStatus: + description: |- + ModifyVolumeStatus represents the status object of ControllerModifyVolume operation. + When this is unset, there is no ModifyVolume operation being attempted. + This is an alpha field and requires enabling VolumeAttributesClass feature. + properties: + status: + description: "status is the status of the ControllerModifyVolume + operation. It can be in any of following states:\n + - Pending\n Pending indicates that the PersistentVolumeClaim + cannot be modified due to unmet requirements, + such as\n the specified VolumeAttributesClass + not existing.\n - InProgress\n InProgress + indicates that the volume is being modified.\n + - Infeasible\n Infeasible indicates that the + request has been rejected as invalid by the + CSI driver. To\n\t resolve the error, a valid + VolumeAttributesClass needs to be specified.\nNote: + New statuses can be added in the future. Consumers + should check for unknown statuses and fail appropriately." + type: string + targetVolumeAttributesClassName: + description: targetVolumeAttributesClassName is + the name of the VolumeAttributesClass the PVC + currently being reconciled + type: string + required: + - status + type: object phase: description: phase represents the current phase of PersistentVolumeClaim. @@ -2669,34 +2815,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2773,6 +2891,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -3178,6 +3311,101 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -4364,7 +4592,7 @@ spec: * Kubernetes-defined prefixed names: - * 'kubernetes.io/h2c' - HTTP/2 over cleartext as described in https://www.rfc-editor.org/rfc/rfc7540 + * 'kubernetes.io/h2c' - HTTP/2 prior knowledge over cleartext as described in https://www.rfc-editor.org/rfc/rfc9113.html#name-starting-http-2-with-prior- * 'kubernetes.io/ws' - WebSocket over cleartext as described in https://www.rfc-editor.org/rfc/rfc6455 * 'kubernetes.io/wss' - WebSocket over TLS as described in https://www.rfc-editor.org/rfc/rfc6455 @@ -4600,6 +4828,15 @@ spec: IP is set for load-balancer ingress points that are IP based (typically GCE or OpenStack load-balancers) type: string + ipMode: + description: |- + IPMode specifies how the load-balancer IP behaves, and may only be specified when the ip field is specified. + Setting this to "VIP" indicates that traffic is delivered to the node with + the destination set to the load-balancer's IP and port. + Setting this to "Proxy" indicates that traffic is delivered to the node or pod with + the destination set to the node's IP and node port or the pod's IP and port. + Service implementations may use this information to adjust traffic routing. + type: string ports: description: |- Ports is a list of records of service ports @@ -4900,8 +5137,9 @@ spec: associated with the corresponding weight. properties: labelSelector: - description: A label query over a set of - resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -4946,6 +5184,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5047,8 +5315,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -5092,6 +5361,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5190,8 +5489,9 @@ spec: associated with the corresponding weight. properties: labelSelector: - description: A label query over a set of - resources, in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -5236,6 +5536,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5337,8 +5667,9 @@ spec: a pod of the set of pods is running properties: labelSelector: - description: A label query over a set of resources, - in this case pods. + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -5382,6 +5713,36 @@ spec: type: object type: object x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: |- A label query over the set of namespaces that the term applies to. @@ -5753,6 +6114,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -5852,6 +6225,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -7145,6 +7530,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -7244,6 +7641,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -8531,6 +8940,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -8630,6 +9051,18 @@ spec: required: - port type: object + sleep: + description: Sleep represents the duration that + the container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds + to sleep. + format: int64 + type: integer + required: + - seconds + type: object tcpSocket: description: |- Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept @@ -10834,34 +11267,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -10939,6 +11344,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -11344,6 +11764,101 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions is a + list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -12064,34 +12579,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry in - PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -12167,6 +12654,21 @@ spec: storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + type: string volumeMode: description: |- volumeMode defines what type of volume is required by the claim. @@ -12315,6 +12817,40 @@ spec: - type type: object type: array + currentVolumeAttributesClassName: + description: |- + currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using. + When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim + This is an alpha field and requires enabling VolumeAttributesClass feature. + type: string + modifyVolumeStatus: + description: |- + ModifyVolumeStatus represents the status object of ControllerModifyVolume operation. + When this is unset, there is no ModifyVolume operation being attempted. + This is an alpha field and requires enabling VolumeAttributesClass feature. + properties: + status: + description: "status is the status of the ControllerModifyVolume + operation. It can be in any of following states:\n + - Pending\n Pending indicates that the PersistentVolumeClaim + cannot be modified due to unmet requirements, such + as\n the specified VolumeAttributesClass not existing.\n + - InProgress\n InProgress indicates that the volume + is being modified.\n - Infeasible\n Infeasible indicates + that the request has been rejected as invalid by the + CSI driver. To\n\t resolve the error, a valid VolumeAttributesClass + needs to be specified.\nNote: New statuses can be + added in the future. Consumers should check for unknown + statuses and fail appropriately." + type: string + targetVolumeAttributesClassName: + description: targetVolumeAttributesClassName is the + name of the VolumeAttributesClass the PVC currently + being reconciled + type: string + required: + - status + type: object phase: description: phase represents the current phase of PersistentVolumeClaim. type: string diff --git a/deploy/helm/templates/deployment.yaml b/deploy/helm/templates/deployment.yaml index f603fc178ba1..7141e5884e2e 100644 --- a/deploy/helm/templates/deployment.yaml +++ b/deploy/helm/templates/deployment.yaml @@ -183,6 +183,8 @@ spec: {{- end }} - name: COMPONENT_REPLICAS_ANNOTATION value: {{ .Values.featureGates.componentReplicasAnnotation.enabled | quote }} + - name: IN_PLACE_POD_VERTICAL_SCALING + value: {{ .Values.featureGates.inPlacePodVerticalScaling.enabled | quote }} {{- with .Values.securityContext }} securityContext: {{- toYaml . | nindent 12 }} diff --git a/deploy/helm/values.yaml b/deploy/helm/values.yaml index f915a9eb105a..04003b1dd686 100644 --- a/deploy/helm/values.yaml +++ b/deploy/helm/values.yaml @@ -1925,6 +1925,8 @@ featureGates: enabled: false componentReplicasAnnotation: enabled: true + inPlacePodVerticalScaling: + enabled: false vmagent: diff --git a/docs/developer_docs/api-reference/cluster.md b/docs/developer_docs/api-reference/cluster.md index 67b194735bef..84e23144ca82 100644 --- a/docs/developer_docs/api-reference/cluster.md +++ b/docs/developer_docs/api-reference/cluster.md @@ -4803,8 +4803,8 @@ More info: -Kubernetes core/v1.ResourceRequirements + +Kubernetes core/v1.VolumeResourceRequirements
    @@ -13685,8 +13685,8 @@ More info: -Kubernetes core/v1.ResourceRequirements + +Kubernetes core/v1.VolumeResourceRequirements
    diff --git a/go.mod b/go.mod index 268c914154e1..9d99bf79f4a7 100644 --- a/go.mod +++ b/go.mod @@ -28,13 +28,13 @@ require ( github.com/hashicorp/vault/sdk v0.9.2 github.com/imdario/mergo v0.3.14 github.com/jackc/pgx/v5 v5.5.4 - github.com/klauspost/compress v1.17.6 + github.com/klauspost/compress v1.17.8 github.com/kubernetes-csi/external-snapshotter/client/v3 v3.0.0 github.com/kubernetes-csi/external-snapshotter/client/v6 v6.2.0 github.com/magiconair/properties v1.8.7 github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 - github.com/onsi/ginkgo/v2 v2.14.0 - github.com/onsi/gomega v1.30.0 + github.com/onsi/ginkgo/v2 v2.15.0 + github.com/onsi/gomega v1.31.0 github.com/opencontainers/image-spec v1.1.0 github.com/pashagolub/pgxmock/v2 v2.11.0 github.com/pkg/errors v0.9.1 @@ -52,40 +52,38 @@ require ( github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.16.0 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 github.com/sykesm/zap-logfmt v0.0.4 github.com/valyala/fasthttp v1.50.0 - github.com/vmware-tanzu/velero v1.10.1 + github.com/vmware-tanzu/velero v1.13.2 go.etcd.io/etcd/client/v3 v3.5.10 go.etcd.io/etcd/server/v3 v3.5.10 go.mongodb.org/mongo-driver v1.11.6 go.uber.org/automaxprocs v1.5.2 - go.uber.org/zap v1.26.0 - golang.org/x/crypto v0.21.0 + go.uber.org/zap v1.27.0 + golang.org/x/crypto v0.22.0 golang.org/x/exp v0.0.0-20240119083558-1b970713d09a - golang.org/x/net v0.23.0 + golang.org/x/net v0.24.0 golang.org/x/text v0.14.0 - google.golang.org/grpc v1.61.0 + google.golang.org/grpc v1.63.2 google.golang.org/protobuf v1.33.0 gopkg.in/ini.v1 v1.67.0 gopkg.in/yaml.v2 v2.4.0 helm.sh/helm/v3 v3.12.3 - k8s.io/api v0.29.0 + k8s.io/api v0.29.2 k8s.io/apiextensions-apiserver v0.29.0 - k8s.io/apimachinery v0.29.0 - k8s.io/apiserver v0.29.0 - k8s.io/cli-runtime v0.28.3 - k8s.io/client-go v12.0.0+incompatible - k8s.io/code-generator v0.28.3 - k8s.io/component-helpers v0.28.3 - k8s.io/cri-api v0.28.3 + k8s.io/apimachinery v0.29.2 + k8s.io/cli-runtime v0.29.0 + k8s.io/client-go v0.29.2 + k8s.io/code-generator v0.29.0 + k8s.io/component-helpers v0.29.0 + k8s.io/cri-api v0.29.0 k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 k8s.io/klog v1.0.0 - k8s.io/klog/v2 v2.110.1 - k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 - k8s.io/kubectl v0.28.2 - k8s.io/kubelet v0.26.1 - k8s.io/kubernetes v1.28.3 + k8s.io/klog/v2 v2.120.1 + k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 + k8s.io/kubectl v0.29.0 + k8s.io/kubelet v0.29.0 k8s.io/utils v0.0.0-20231127182322-b307cd553661 sigs.k8s.io/controller-runtime v0.17.2 sigs.k8s.io/yaml v1.4.0 @@ -95,8 +93,6 @@ require ( cuelabs.dev/go/oci/ociregistry v0.0.0-20240314152124-224736b49f2e // indirect github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect - github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 // indirect - github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect github.com/BurntSushi/toml v1.3.2 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect @@ -145,37 +141,38 @@ require ( github.com/go-errors/errors v1.4.2 // indirect github.com/go-gorp/gorp/v3 v3.0.5 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.4 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gobwas/glob v0.2.3 // indirect + github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.1.2 // indirect - github.com/google/cel-go v0.17.7 // indirect + github.com/google/cel-go v0.17.8 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20230323073829-e72429f035bd // indirect + github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/mux v1.8.0 // indirect + github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/gosuri/uitable v0.0.4 // indirect github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c99 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-kms-wrapping/v2 v2.0.8 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.4.8 // indirect + github.com/hashicorp/go-plugin v1.6.0 // indirect github.com/hashicorp/go-secure-stdlib/base62 v0.1.2 // indirect github.com/hashicorp/go-secure-stdlib/mlock v0.1.2 // indirect github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect @@ -196,9 +193,7 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect - github.com/klauspost/cpuid/v2 v2.2.4 // indirect - github.com/kopia/kopia v0.10.7 // indirect - github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0 // indirect + github.com/kubernetes-csi/external-snapshotter/client/v7 v7.0.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/lib/pq v1.10.9 // indirect @@ -223,6 +218,7 @@ require ( github.com/montanaflynn/stats v0.6.6 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/oklog/run v1.1.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect @@ -230,8 +226,8 @@ require ( github.com/pierrec/lz4 v2.6.1+incompatible // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect - github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.52.3 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/protocolbuffers/txtpbfmt v0.0.0-20230328191034-3462fbc510c0 // indirect github.com/rivo/uniseg v0.4.6 // indirect @@ -269,36 +265,37 @@ require ( go.etcd.io/etcd/client/v2 v2.305.10 // indirect go.etcd.io/etcd/pkg/v3 v3.5.10 // indirect go.etcd.io/etcd/raft/v3 v3.5.10 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect - go.opentelemetry.io/otel v1.22.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0 // indirect - go.opentelemetry.io/otel/metric v1.22.0 // indirect - go.opentelemetry.io/otel/sdk v1.21.0 // indirect - go.opentelemetry.io/otel/trace v1.22.0 // indirect - go.opentelemetry.io/proto/otlp v1.0.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.25.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.25.0 // indirect + go.opentelemetry.io/otel/sdk v1.25.0 // indirect + go.opentelemetry.io/otel/trace v1.25.0 // indirect + go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/mod v0.16.0 // indirect - golang.org/x/oauth2 v0.18.0 // indirect - golang.org/x/sync v0.6.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/term v0.18.0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/oauth2 v0.19.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/term v0.19.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.19.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/api v0.161.0 // indirect - google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe // indirect + google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240314234333-6e1732d8331c // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.0 // indirect + k8s.io/apiserver v0.29.0 // indirect k8s.io/component-base v0.29.0 // indirect + k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 // indirect + k8s.io/metrics v0.29.0 // indirect oras.land/oras-go v1.2.4 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect @@ -306,36 +303,4 @@ require ( sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect ) -replace ( - golang.org/x/exp => golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb - k8s.io/api => k8s.io/api v0.28.3 - k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.28.3 - k8s.io/apimachinery => k8s.io/apimachinery v0.28.3 - k8s.io/apiserver => k8s.io/apiserver v0.28.3 - k8s.io/cli-runtime => k8s.io/cli-runtime v0.28.3 - k8s.io/client-go => k8s.io/client-go v0.28.3 - k8s.io/cloud-provider => k8s.io/cloud-provider v0.28.3 - k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.28.3 - k8s.io/code-generator => k8s.io/code-generator v0.28.3 - k8s.io/component-base => k8s.io/component-base v0.28.3 - k8s.io/component-helpers => k8s.io/component-helpers v0.28.3 - k8s.io/controller-manager => k8s.io/controller-manager v0.28.3 - k8s.io/cri-api => k8s.io/cri-api v0.28.3 - k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.28.3 - k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.28.3 - k8s.io/endpointslice => k8s.io/endpointslice v0.28.3 - k8s.io/kms => k8s.io/kms v0.28.3 - k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.28.3 - k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.28.3 - k8s.io/kube-proxy => k8s.io/kube-proxy v0.28.3 - k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.28.3 - k8s.io/kubectl => k8s.io/kubectl v0.28.3 - k8s.io/kubelet => k8s.io/kubelet v0.28.3 - k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.28.3 - k8s.io/metrics => k8s.io/metrics v0.28.3 - k8s.io/mount-utils => k8s.io/mount-utils v0.28.3 - k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.28.3 - k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.28.3 - k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.28.3 - k8s.io/sample-controller => k8s.io/sample-controller v0.28.3 -) +replace golang.org/x/exp => golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb diff --git a/go.sum b/go.sum index 043f501e9dc9..9dae71786b39 100644 --- a/go.sum +++ b/go.sum @@ -7,6 +7,7 @@ cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxK cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= @@ -20,24 +21,15 @@ cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPT cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= -cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= -cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= -cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI= -cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -48,52 +40,25 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.27.0 h1:YOO045NZI9RKfCj1c5A/ZtuuENUc8OAW+gHdGnDgyMQ= -cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= cuelabs.dev/go/oci/ociregistry v0.0.0-20240314152124-224736b49f2e h1:GwCVItFUPxwdsEYnlUcJ6PJxOjTeFFCKOh6QWg4oAzQ= cuelabs.dev/go/oci/ociregistry v0.0.0-20240314152124-224736b49f2e/go.mod h1:ApHceQLLwcOkCEXM1+DyCXTHEJhNGDpJ2kmV6axsx24= cuelang.org/go v0.8.0 h1:fO1XPe/SUGtc7dhnGnTPbpIDoQm/XxhDtoSF7jzO01c= cuelang.org/go v0.8.0/go.mod h1:CoDbYolfMms4BhWUlhD+t5ORnihR7wvjcfgyO9lL5FI= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U= -github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k= -github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= -github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1 h1:qoVeMsc9/fh/yhxVaA0obYjVH/oI/ihrOoMwsLS9KSA= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1/go.mod h1:fBF9PQNqB8scdgpZ3ufzaLntG0AG7C1WjPMsiFOmfHM= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3 h1:E+m3SkZCN0Bf5q7YdTs5lSm2CYY3CK4spn5OmUIiQtk= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3/go.mod h1:KLF4gFr6DcKFZwSuH8w8yEK6DpFl3LP5rhdvAb7Yz5I= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0 h1:Px2UA+2RvSSvv+RvJNuUB6n7rs5Wsel4dXLe90Um2n4= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0/go.mod h1:tPaiy8S5bQ+S5sOiDlINkp7+Ef339+Nz5L5XO+cnOHo= -github.com/Azure/azure-storage-blob-go v0.14.0 h1:1BCg74AmVdYwO3dlKwtFU1V0wU2PZdREkXvAmZJRUlM= -github.com/Azure/azure-storage-blob-go v0.14.0/go.mod h1:SMqIBi+SuiQH32bvyjngEewEeXoPfKMgWlBDaYf6fck= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= -github.com/Azure/go-autorest/autorest v0.11.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw= -github.com/Azure/go-autorest/autorest v0.11.29/go.mod h1:ZtEzC4Jy2JDrZLxvWs8LrBWEBycl1hbT1eknI8MtfAs= -github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/adal v0.9.23 h1:Yepx8CvFxwNKpH6ja7RZ+sKX+DWYNldbLiALMC3BTz8= -github.com/Azure/go-autorest/autorest/adal v0.9.23/go.mod h1:5pcMqFkdPhviJdlEy3kC/v1ZLnQl0MH6XA5YCcMhy4c= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 h1:wkAZRgT/pn8HhFyzfe9UnqOjJYqlembgCTi72Bm/xKk= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.12/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.5/go.mod h1:ADQAXrkgm7acgWVUNamOgh8YNrv4p27l3Wc55oVfpzg= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 h1:w77/uPk80ZET2F+AfQExZyEWtn+0Rk/uw17m9fv5Ajc= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.6/go.mod h1:piCfgPho7BiIDdEQ1+g4VmKyD5y+p/XtSNqE6Hc4QD0= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= -github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= -github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac= -github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= @@ -119,6 +84,10 @@ github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7 github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/StudioSol/set v1.0.0 h1:G27J71la+Da08WidabBkoRrvPLTa4cdCn0RjvyJ5WKQ= @@ -143,7 +112,6 @@ github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/authzed/controller-idioms v0.7.0 h1:HhNMUBb8hJzYqY3mhen3B2AC5nsIem3fBe0tC/AAOHo= @@ -170,6 +138,8 @@ github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao= github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y= github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/bugsnag/bugsnag-go v2.1.2+incompatible h1:E7dor84qzwUO8KdCM68CZwq9QOSR7HXlLx3Wj5vui2s= github.com/bugsnag/bugsnag-go v2.1.2+incompatible/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/panicwrap v1.3.4 h1:A6sXFtDGsgU/4BLf5JT0o5uYg3EeKgGx3Sfs+/uk3pU= @@ -183,8 +153,6 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= -github.com/chmduquesne/rollinghash v4.0.0+incompatible h1:hnREQO+DXjqIw3rUTzWN7/+Dpw+N5Um8zpKV0JOEgbo= -github.com/chmduquesne/rollinghash v4.0.0+incompatible/go.mod h1:Uc2I36RRfTAf7Dge82bi3RU0OQUmXT9iweIcPqvr8A0= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -196,8 +164,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY= -github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA= @@ -242,8 +208,6 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= -github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2 h1:aBfCb7iqHmDEIp6fBvC/hQUddQfg+3qdYjwzaiP9Hnc= github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2/go.mod h1:WHNsWjnIn2V1LYOrME7e8KxSeKunYHsxEm4am0BUtcI= github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0= @@ -266,10 +230,13 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= +github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emicklei/proto v1.10.0 h1:pDGyFRVV5RvV+nkBK9iy3q67FBy9Xa7vwrOTE+g5aGw= @@ -281,9 +248,7 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= -github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.8.0 h1:lRj6N9Nci7MvzrXuX6HFzU8XjmhPiXPlsKEy1u0KQro= @@ -314,6 +279,7 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= @@ -327,24 +293,31 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= @@ -354,7 +327,6 @@ github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= @@ -369,22 +341,17 @@ github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godror/godror v0.24.2/go.mod h1:wZv/9vPiUib6tkoDl+AZ/QLf5YZgMravZ7jxH2eQWAE= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= -github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -418,7 +385,6 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -428,11 +394,10 @@ github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/cel-go v0.17.7 h1:6ebJFzu1xO2n7TLtN+UBqShGBhlD85bhvglh5DpcfqQ= -github.com/google/cel-go v0.17.7/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY= +github.com/google/cel-go v0.17.8 h1:j9m730pMZt1Fc4oKhCLUHfjj6527LuhYcYw0Rl8gqto= +github.com/google/cel-go v0.17.8/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -471,13 +436,9 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230323073829-e72429f035bd h1:r8yyd+DJDmsUhGrRBxH5Pj7KeFK5l+Y3FsgT8keqKtk= -github.com/google/pprof v0.0.0-20230323073829-e72429f035bd/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= +github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 h1:hR7/MlvK23p6+lIw9SN1TigNLn9ZnF3W4SYRKq2gAHs= +github.com/google/pprof v0.0.0-20230602150820-91b7bce49751/go.mod h1:Jh3hGz2jkYak8qXPD19ryItVnUgpgeqzdkY/D0EaeuA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= -github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -485,18 +446,15 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= -github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= -github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= @@ -514,8 +472,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c9 github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -534,8 +492,8 @@ github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iP github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.4.8 h1:CHGwpxYDOttQOY7HOWgETU9dyVjOXzniXDqJcYJE1zM= -github.com/hashicorp/go-plugin v1.4.8/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= +github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= +github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-secure-stdlib/base62 v0.1.2 h1:ET4pqyjiGmY09R5y+rSd70J2w45CtbWDNvGqWp/R3Ng= @@ -579,7 +537,7 @@ github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/imdario/mergo v0.3.14 h1:fOqeC1+nCuuk6PKQdg9YmosXX7Y7mHX6R/0ZldI9iHo= @@ -595,16 +553,14 @@ github.com/jackc/pgx/v5 v5.5.4 h1:Xp2aQS8uXButQdnCMWNmvx6UysWQQC+u1EoizjguY+8= github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= -github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= -github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= +github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= -github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= -github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.3.0 h1:9BSCMi8C+0qdApAp4auwX0RkLGUjs956h0EkuQymUhg= github.com/jonboulle/clockwork v0.3.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= @@ -613,6 +569,7 @@ github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFF github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= @@ -622,22 +579,16 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= +github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw= github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= -github.com/karrick/godirwalk v1.17.0 h1:b4kY7nqDdioR/6qnbHQyDvmA17u5G1cZ6J+CZXwSWoI= -github.com/karrick/godirwalk v1.17.0/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI= -github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= -github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= -github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= -github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= -github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kopia/kopia v0.10.7 h1:6s0ZIZW3Ge2ozzefddASy7CIUadp/5tF9yCDKQfAKKI= -github.com/kopia/kopia v0.10.7/go.mod h1:0d9THPD+jwomPcXvPbCdmLyX6phQVP7AqcCcDEajfNA= github.com/kortschak/utter v1.0.1/go.mod h1:vSmSjbyrlKjjsL71193LmzBOKgwePk9DH6uFaWHIInc= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -648,15 +599,16 @@ github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NB github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kubernetes-csi/external-snapshotter/client/v3 v3.0.0 h1:OYDCOjVcx/5wNzlZ/At8otRibUlw0T6R0xOD31f32bw= github.com/kubernetes-csi/external-snapshotter/client/v3 v3.0.0/go.mod h1:Q7VUue/CIrKbtpBdF04a1yjGGgsMaDws1HUxtjzgnEY= -github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0 h1:nHHjmvjitIiyPlUHk/ofpgvBcNcawJLtf4PYHORLjAA= -github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0/go.mod h1:YBCo4DoEeDndqvAn6eeu0vWM7QdXmHEeI9cFWplmBys= github.com/kubernetes-csi/external-snapshotter/client/v6 v6.2.0 h1:cMM5AB37e9aRGjErygVT6EuBPB6s5a+l95OPERmSlVM= github.com/kubernetes-csi/external-snapshotter/client/v6 v6.2.0/go.mod h1:VQVLCPGDX5l6V5PezjlDXLa+SpCbWSVU7B16cFWVVeE= +github.com/kubernetes-csi/external-snapshotter/client/v7 v7.0.0 h1:j3YK74myEQRxR/srciTpOrm221SAvz6J5OVWbyfeXFo= +github.com/kubernetes-csi/external-snapshotter/client/v7 v7.0.0/go.mod h1:FlyYFe32mPxKEPaRXKNxfX576d1AoCzstYDoOOnyMA4= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= @@ -675,6 +627,10 @@ github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= @@ -689,8 +645,6 @@ github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-ieproxy v0.0.1 h1:qiyop7gCflfhwCzGyeT0gro3sF9AIg9HU98JORTkqfI= -github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= @@ -712,19 +666,12 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= -github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= -github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= -github.com/minio/minio-go/v7 v7.0.23 h1:NleyGQvAn9VQMU+YHVrgV4CX+EPtxPt/78lHOOTncy4= -github.com/minio/minio-go/v7 v7.0.23/go.mod h1:ei5JjmxwHaMrgsMrn4U/+Nmg+d8MKS1U2DAn1ou4+Do= -github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= -github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.1.5/go.mod h1:v8+iFts2sPIKUV1ltktPXMCC8fumSKFItNcD2cLtRR4= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= @@ -768,53 +715,23 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0A= -github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM= github.com/nelsam/hel/v2 v2.3.2/go.mod h1:1ZTGfU2PFTOd5mx22i5O0Lc2GY933lQ2wb/ggy+rL3w= github.com/nelsam/hel/v2 v2.3.3/go.mod h1:1ZTGfU2PFTOd5mx22i5O0Lc2GY933lQ2wb/ggy+rL3w= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= -github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= -github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0= -github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= -github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw= -github.com/onsi/ginkgo/v2 v2.7.0/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo= -github.com/onsi/ginkgo/v2 v2.8.1/go.mod h1:N1/NbDngAFcSLdyZ+/aYTYGSlq9qMCS/cNKGJjy+csc= -github.com/onsi/ginkgo/v2 v2.9.0/go.mod h1:4xkjoL/tZv4SMWeww56BU5kAt19mVB47gTWxmrTcxyk= -github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo= -github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts= -github.com/onsi/ginkgo/v2 v2.9.4/go.mod h1:gCQYp2Q+kSoIj7ykSVb9nskRSsR6PUj4AiLywzIhbKM= -github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY= -github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= -github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= -github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM= -github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= -github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= -github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= -github.com/onsi/gomega v1.27.1/go.mod h1:aHX5xOykVYzWOV4WqQy0sy8BQptgukenXpCXfadcIAw= -github.com/onsi/gomega v1.27.3/go.mod h1:5vG284IBtfDAmDyrK+eGyZmUgUlmi+Wngqo557cZ6Gw= -github.com/onsi/gomega v1.27.4/go.mod h1:riYq/GJKh8hhoM01HN6Vmuy93AarCXCBGpvFDK3q3fQ= -github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= -github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= -github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY= +github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.31.0 h1:54UJxxj6cPInHS3a35wm6BK/F9nHYueZ1NVujHDrnXE= +github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= @@ -868,16 +785,16 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1: github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= -github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/common v0.52.3 h1:5f8uj6ZwHSscOGNdIQg6OiZv/ybiK2CO2q2drVZAQSA= +github.com/prometheus/common v0.52.3/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -902,11 +819,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4= -github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rubenv/sql-migrate v1.3.1 h1:Vx+n4Du8X8VTYuXbhNxdEUoh6wiJERA0GlWocR5FrbA= github.com/rubenv/sql-migrate v1.3.1/go.mod h1:YzG/Vh82CwyhTFXy+Mf5ahAiiEOpAlHurg+23VEzcsk= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -961,6 +875,7 @@ github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyh github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= @@ -972,9 +887,11 @@ github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ai github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -985,10 +902,10 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= @@ -1010,8 +927,8 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.50.0 h1:H7fweIlBm0rXLs2q0XbalvJ6r0CUPFWK3/bB4N13e9M= github.com/valyala/fasthttp v1.50.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= -github.com/vmware-tanzu/velero v1.10.1 h1:6WYOolZIygHb8FOZtpp8vCqCuy5Mk3qBF1S65L5cjuo= -github.com/vmware-tanzu/velero v1.10.1/go.mod h1:N0J+j8xGSmanGpy1zCRMH2DMGPpwkUj9EZIUXfOlanY= +github.com/vmware-tanzu/velero v1.13.2 h1:72Rw+11HJB6XUYfH9/M/jle6duSLyGhMisMMYFr/1qs= +github.com/vmware-tanzu/velero v1.13.2/go.mod h1:yHFPyr+iwpKRf66xJ88MriAHiX58tTnKmQXY2FQZClM= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= @@ -1040,7 +957,6 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= @@ -1050,8 +966,6 @@ github.com/yvasiyarov/gorelic v0.0.7 h1:4DTF1WOM2ZZS/xMOkTFBOcb6XiHu/PKn3rVo6dbe github.com/yvasiyarov/gorelic v0.0.7/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20160601141957-9c099fbc30e9 h1:AsFN8kXcCVkUFHyuzp1FtYbzp1nCO/H6+1uPSGEyPzM= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20160601141957-9c099fbc30e9/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= -github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg= -github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= @@ -1083,24 +997,24 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw= -go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= -go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0 h1:DeFD0VgTZ+Cj6hxravYYZE2W4GlneVH81iAOPjZkzk8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0/go.mod h1:GijYcYmNpX1KazD5JmWGsi4P7dDTTTnfv1UbGn84MnU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0 h1:gvmNvqrPYovvyRmCSygkUDyL8lC5Tl845MLEwqpxhEU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0/go.mod h1:vNUq47TGFioo+ffTSnKNdob241vePmtNZnAODKapKd0= -go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= -go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= -go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= -go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= -go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= -go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.25.0 h1:gldB5FfhRl7OJQbUHt/8s0a7cE8fbsPAtdpRaApKy4k= +go.opentelemetry.io/otel v1.25.0/go.mod h1:Wa2ds5NOXEMkCmUou1WA7ZBfLTHWIsp034OVD7AO+Vg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM= +go.opentelemetry.io/otel/metric v1.25.0 h1:LUKbS7ArpFL/I2jJHdJcqMGxkRdxpPHE0VU/D4NuEwA= +go.opentelemetry.io/otel/metric v1.25.0/go.mod h1:rkDLUSd2lC5lq2dFNrX9LGAbINP5B7WBkC78RXCpH5s= +go.opentelemetry.io/otel/sdk v1.25.0 h1:PDryEJPC8YJZQSyLY5eqLeafHtG+X7FWnf3aXMtxbqo= +go.opentelemetry.io/otel/sdk v1.25.0/go.mod h1:oFgzCM2zdsxKzz6zwpTZYLLQsFwc+K0daArPdIhuxkw= +go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1Dq6RM= +go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I= +go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= +go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -1123,30 +1037,30 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.12.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb h1:xIApU0ow1zwMa2uL1VDNeQlNVFTWMQxZUZCMDy0Q4Us= golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1168,16 +1082,11 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= -golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1197,6 +1106,7 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1207,7 +1117,6 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= @@ -1222,27 +1131,16 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1255,9 +1153,8 @@ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= -golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= -golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= +golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg= +golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1270,9 +1167,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1287,14 +1183,13 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1310,6 +1205,7 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1317,7 +1213,6 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1334,44 +1229,28 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1383,24 +1262,20 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -1410,6 +1285,7 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1439,6 +1315,7 @@ golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= @@ -1448,7 +1325,6 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1457,20 +1333,14 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -1495,8 +1365,6 @@ google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjR google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= -google.golang.org/api v0.161.0 h1:oYzk/bs26WN10AV7iU7MVJVXBH8oCPS2hHyBiEeFoSU= -google.golang.org/api v0.161.0/go.mod h1:0mu0TpK33qnydLvWqbImq2b1eQ5FHRSDCBzAxX9ZHyw= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1504,8 +1372,6 @@ google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1550,12 +1416,12 @@ google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe h1:USL2DhxfgRchafRvt/wYyyQNzwgL7ZiURcozOE/Pkvo= -google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= -google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe h1:0poefMBYvYbs7g5UkjS6HcxBPaTRAmznle9jnxYoAI8= -google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe h1:bQnxqljG/wqi4NTXu2+DJ3n7APcEA882QZ1JvhQAq9o= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= +google.golang.org/genproto/googleapis/api v0.0.0-20240314234333-6e1732d8331c h1:kaI7oewGK5YnVwj+Y+EJBO/YN1ht8iTL9XkFHtVZLsc= +google.golang.org/genproto/googleapis/api v0.0.0-20240314234333-6e1732d8331c/go.mod h1:VQW3tUculP/D4B+xVCo+VgSq8As6wA9ZjHl//pmk+6s= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -1578,8 +1444,8 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0= -google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1592,9 +1458,6 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -1613,7 +1476,6 @@ gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1642,51 +1504,52 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.28.3 h1:Gj1HtbSdB4P08C8rs9AR94MfSGpRhJgsS+GF9V26xMM= -k8s.io/api v0.28.3/go.mod h1:MRCV/jr1dW87/qJnZ57U5Pak65LGmQVkKTzf3AtKFHc= -k8s.io/apiextensions-apiserver v0.28.3 h1:Od7DEnhXHnHPZG+W9I97/fSQkVpVPQx2diy+2EtmY08= -k8s.io/apiextensions-apiserver v0.28.3/go.mod h1:NE1XJZ4On0hS11aWWJUTNkmVB03j9LM7gJSisbRt8Lc= -k8s.io/apimachinery v0.28.3 h1:B1wYx8txOaCQG0HmYF6nbpU8dg6HvA06x5tEffvOe7A= -k8s.io/apimachinery v0.28.3/go.mod h1:uQTKmIqs+rAYaq+DFaoD2X7pcjLOqbQX2AOiO0nIpb8= -k8s.io/apiserver v0.28.3 h1:8Ov47O1cMyeDzTXz0rwcfIIGAP/dP7L8rWbEljRcg5w= -k8s.io/apiserver v0.28.3/go.mod h1:YIpM+9wngNAv8Ctt0rHG4vQuX/I5rvkEMtZtsxW2rNM= -k8s.io/cli-runtime v0.28.3 h1:lvuJYVkwCqHEvpS6KuTZsUVwPePFjBfSGvuaLl2SxzA= -k8s.io/cli-runtime v0.28.3/go.mod h1:jeX37ZPjIcENVuXDDTskG3+FnVuZms5D9omDXS/2Jjc= -k8s.io/client-go v0.28.3 h1:2OqNb72ZuTZPKCl+4gTKvqao0AMOl9f3o2ijbAj3LI4= -k8s.io/client-go v0.28.3/go.mod h1:LTykbBp9gsA7SwqirlCXBWtK0guzfhpoW4qSm7i9dxo= -k8s.io/code-generator v0.28.3 h1:I847QvdpYx7xKiG2KVQeCSyNF/xU9TowaDAg601mvlw= -k8s.io/code-generator v0.28.3/go.mod h1:A2EAHTRYvCvBrb/MM2zZBNipeCk3f8NtpdNIKawC43M= -k8s.io/component-base v0.28.3 h1:rDy68eHKxq/80RiMb2Ld/tbH8uAE75JdCqJyi6lXMzI= -k8s.io/component-base v0.28.3/go.mod h1:fDJ6vpVNSk6cRo5wmDa6eKIG7UlIQkaFmZN2fYgIUD8= -k8s.io/component-helpers v0.28.3 h1:te9ieTGzcztVktUs92X53P6BamAoP73MK0qQP0WmDqc= -k8s.io/component-helpers v0.28.3/go.mod h1:oJR7I9ist5UAQ3y/CTdbw6CXxdMZ1Lw2Ua/EZEwnVLs= -k8s.io/cri-api v0.28.3 h1:84ifk56rAy7yYI1zYqTjLLishpFgs3q7BkCKhoLhmFA= -k8s.io/cri-api v0.28.3/go.mod h1:MTdJO2fikImnX+YzE2Ccnosj3Hw2Cinw2fXYV3ppUIE= -k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/api v0.19.0/go.mod h1:I1K45XlvTrDjmj5LoM5LuP/KYrhWbjUKT/SoPG0qTjw= +k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A= +k8s.io/api v0.29.2/go.mod h1:sdIaaKuU7P44aoyyLlikSLayT6Vb7bvJNCX105xZXY0= +k8s.io/apiextensions-apiserver v0.29.0 h1:0VuspFG7Hj+SxyF/Z/2T0uFbI5gb5LRgEyUVE3Q4lV0= +k8s.io/apiextensions-apiserver v0.29.0/go.mod h1:TKmpy3bTS0mr9pylH0nOt/QzQRrW7/h7yLdRForMZwc= +k8s.io/apimachinery v0.19.0/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= +k8s.io/apimachinery v0.29.2 h1:EWGpfJ856oj11C52NRCHuU7rFDwxev48z+6DSlGNsV8= +k8s.io/apimachinery v0.29.2/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU= +k8s.io/apiserver v0.29.0 h1:Y1xEMjJkP+BIi0GSEv1BBrf1jLU9UPfAnnGGbbDdp7o= +k8s.io/apiserver v0.29.0/go.mod h1:31n78PsRKPmfpee7/l9NYEv67u6hOL6AfcE761HapDM= +k8s.io/cli-runtime v0.29.0 h1:q2kC3cex4rOBLfPOnMSzV2BIrrQlx97gxHJs21KxKS4= +k8s.io/cli-runtime v0.29.0/go.mod h1:VKudXp3X7wR45L+nER85YUzOQIru28HQpXr0mTdeCrk= +k8s.io/client-go v0.19.0/go.mod h1:H9E/VT95blcFQnlyShFgnFT9ZnJOAceiUHM3MlRC+mU= +k8s.io/client-go v0.29.2 h1:FEg85el1TeZp+/vYJM7hkDlSTFZ+c5nnK44DJ4FyoRg= +k8s.io/client-go v0.29.2/go.mod h1:knlvFZE58VpqbQpJNbCbctTVXcd35mMyAAwBdpt4jrA= +k8s.io/code-generator v0.19.0/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= +k8s.io/code-generator v0.29.0 h1:2LQfayGDhaIlaamXjIjEQlCMy4JNCH9lrzas4DNW1GQ= +k8s.io/code-generator v0.29.0/go.mod h1:5bqIZoCxs2zTRKMWNYqyQWW/bajc+ah4rh0tMY8zdGA= +k8s.io/component-base v0.29.0 h1:T7rjd5wvLnPBV1vC4zWd/iWRbV8Mdxs+nGaoaFzGw3s= +k8s.io/component-base v0.29.0/go.mod h1:sADonFTQ9Zc9yFLghpDpmNXEdHyQmFIGbiuZbqAXQ1M= +k8s.io/component-helpers v0.29.0 h1:Y8W70NGeitKxWwhsPo/vEQbQx5VqJV+3xfLpP3V1VxU= +k8s.io/component-helpers v0.29.0/go.mod h1:j2coxVfmzTOXWSE6sta0MTgNSr572Dcx68F6DD+8fWc= +k8s.io/cri-api v0.29.0 h1:atenAqOltRsFqcCQlFFpDnl/R4aGfOELoNLTDJfd7t8= +k8s.io/cri-api v0.29.0/go.mod h1:Rls2JoVwfC7kW3tndm7267kriuRukQ02qfht0PCRuIc= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 h1:pWEwq4Asjm4vjW7vcsmijwBhOr1/shsbSYiWXmNGlks= k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 h1:NGrVE502P0s0/1hudf8zjgwki1X/TByhmAoILTarmzo= +k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70/go.mod h1:VH3AT8AaQOqiGjMF9p0/IM1Dj+82ZwjfxUP1IxaHE+8= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= -k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= -k8s.io/kube-aggregator v0.28.3 h1:CVbj3+cpshSHR5dWPzLYx3sVpIDEPLlzMSxY/lAc9cM= -k8s.io/kube-aggregator v0.28.3/go.mod h1:5DyLevbRTcWnT1f9b+lB3BfbXC1w7gDa/OtB6kKInCw= -k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= -k8s.io/kubectl v0.28.3 h1:H1Peu1O3EbN9zHkJCcvhiJ4NUj6lb88sGPO5wrWIM6k= -k8s.io/kubectl v0.28.3/go.mod h1:RDAudrth/2wQ3Sg46fbKKl4/g+XImzvbsSRZdP2RiyE= -k8s.io/kubelet v0.28.3 h1:bp/uIf1R5F61BlFvFtzc4PDEiK7TtFcw3wFJlc0V0LM= -k8s.io/kubelet v0.28.3/go.mod h1:E3NHYbp/v45Ao6AD0EOZnqO3L0R6Haks6Nm0+bnFwtU= -k8s.io/kubernetes v1.28.3 h1:XTci6gzk+JR51UZuZQCFJ4CsyUkfivSjLI4O1P9z6LY= -k8s.io/kubernetes v1.28.3/go.mod h1:NhAysZWvHtNcJFFHic87ofxQN7loylCQwg3ZvXVDbag= -k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= +k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= +k8s.io/kubectl v0.29.0 h1:Oqi48gXjikDhrBF67AYuZRTcJV4lg2l42GmvsP7FmYI= +k8s.io/kubectl v0.29.0/go.mod h1:0jMjGWIcMIQzmUaMgAzhSELv5WtHo2a8pq67DtviAJs= +k8s.io/kubelet v0.29.0 h1:SX5hlznTBcGIrS1scaf8r8p6m3e475KMifwt9i12iOk= +k8s.io/kubelet v0.29.0/go.mod h1:kvKS2+Bz2tgDOG1S1q0TH2z1DasNuVF+8p6Aw7xvKkI= +k8s.io/metrics v0.29.0 h1:a6dWcNM+EEowMzMZ8trka6wZtSRIfEA/9oLjuhBksGc= +k8s.io/metrics v0.29.0/go.mod h1:UCuTT4dC/x/x6ODSk87IWIZQnuAfcwxOjb1gjWJdjMA= +k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20231127182322-b307cd553661 h1:FepOBzJ0GXm8t0su67ln2wAZjbQ6RxQGZDnzuLcrUTI= k8s.io/utils v0.0.0-20231127182322-b307cd553661/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= oras.land/oras-go v1.2.4 h1:djpBY2/2Cs1PV87GSJlxv4voajVOMZxqqtq9AB8YNvY= @@ -1694,6 +1557,8 @@ oras.land/oras-go v1.2.4/go.mod h1:DYcGfb3YF1nKjcezfX2SNlDAeQFKSXmf+qrFmrh4324= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.0 h1:TgtAeesdhpm2SGwkQasmbeqDo8th5wOBA5h/AjTKA4I= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.0/go.mod h1:VHVDI/KrK4fjnV61bE2g3sA7tiETLn8sooImelsCx3Y= sigs.k8s.io/controller-runtime v0.17.2 h1:FwHwD1CTUemg0pW2otk7/U5/i5m2ymzvOXdbeGOUvw0= sigs.k8s.io/controller-runtime v0.17.2/go.mod h1:+MngTvIQQQhfXtwfdGw/UOQ/aIaqsYywfCINOtwMO/s= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= @@ -1702,10 +1567,10 @@ sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 h1:XX3Ajgzov2RKU sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3/go.mod h1:9n16EZKMhXBNSiUC5kSdFQJkdH3zbxS/JoO619G1VAY= sigs.k8s.io/kustomize/kyaml v0.14.3 h1:WpabVAKZe2YEp/irTSHwD6bfjwZnTtSDewd2BVJGMZs= sigs.k8s.io/kustomize/kyaml v0.14.3/go.mod h1:npvh9epWysfQ689Rtt/U+dpOJDTBn8kUnF1O6VzvmZA= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/pkg/client/informers/externalversions/factory.go b/pkg/client/informers/externalversions/factory.go index 0817693b0d54..d29649cf7a14 100644 --- a/pkg/client/informers/externalversions/factory.go +++ b/pkg/client/informers/externalversions/factory.go @@ -46,6 +46,7 @@ type sharedInformerFactory struct { lock sync.Mutex defaultResync time.Duration customResync map[reflect.Type]time.Duration + transform cache.TransformFunc informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -84,6 +85,14 @@ func WithNamespace(namespace string) SharedInformerOption { } } +// WithTransform sets a transform on all informers. +func WithTransform(transform cache.TransformFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.transform = transform + return factory + } +} + // NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { return NewSharedInformerFactoryWithOptions(client, defaultResync) @@ -188,6 +197,7 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal } informer = newFunc(f.client, resyncPeriod) + informer.SetTransform(f.transform) f.informers[informerType] = informer return informer diff --git a/pkg/constant/flag.go b/pkg/constant/flag.go index 10cc739bc0c7..c905c114f6f1 100644 --- a/pkg/constant/flag.go +++ b/pkg/constant/flag.go @@ -40,4 +40,8 @@ const ( // FeatureGateComponentReplicasAnnotation tells whether to add and update the annotation "component-replicas" to all pods of a Component FeatureGateComponentReplicasAnnotation = "COMPONENT_REPLICAS_ANNOTATION" + + // FeatureGateInPlacePodVerticalScaling specifies to enable in-place pod vertical scaling + // NOTE: This feature depends on the InPlacePodVerticalScaling feature of the K8s cluster in which the KubeBlocks runs. + FeatureGateInPlacePodVerticalScaling = "IN_PLACE_POD_VERTICAL_SCALING" ) diff --git a/pkg/controller/builder/builder_instance_set_test.go b/pkg/controller/builder/builder_instance_set_test.go index cc1ddbc29284..522439d183e0 100644 --- a/pkg/controller/builder/builder_instance_set_test.go +++ b/pkg/controller/builder/builder_instance_set_test.go @@ -85,7 +85,7 @@ var _ = Describe("instance_set builder", func() { }, Spec: corev1.PersistentVolumeClaimSpec{ VolumeName: "foo-1", - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("500m"), }, @@ -100,7 +100,7 @@ var _ = Describe("instance_set builder", func() { }, Spec: corev1.PersistentVolumeClaimSpec{ VolumeName: "foo-2", - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("600m"), }, diff --git a/pkg/controller/builder/builder_pvc.go b/pkg/controller/builder/builder_pvc.go index 0868f821c99a..8512deb3cced 100644 --- a/pkg/controller/builder/builder_pvc.go +++ b/pkg/controller/builder/builder_pvc.go @@ -31,7 +31,7 @@ func NewPVCBuilder(namespace, name string) *PVCBuilder { return builder } -func (builder *PVCBuilder) SetResources(resources corev1.ResourceRequirements) *PVCBuilder { +func (builder *PVCBuilder) SetResources(resources corev1.VolumeResourceRequirements) *PVCBuilder { builder.get().Spec.Resources = resources return builder } diff --git a/pkg/controller/builder/builder_pvc_test.go b/pkg/controller/builder/builder_pvc_test.go index b3073cbc90af..7edd015cf2da 100644 --- a/pkg/controller/builder/builder_pvc_test.go +++ b/pkg/controller/builder/builder_pvc_test.go @@ -33,7 +33,7 @@ var _ = Describe("pvc builder", func() { name = "foo" ns = "default" ) - resources := corev1.ResourceRequirements{ + resources := corev1.VolumeResourceRequirements{ Requests: map[corev1.ResourceName]resource.Quantity{ "CPU": resource.MustParse("500m"), }, diff --git a/pkg/controller/builder/builder_stateful_set_test.go b/pkg/controller/builder/builder_stateful_set_test.go index 26d97e11dc90..103944cfe140 100644 --- a/pkg/controller/builder/builder_stateful_set_test.go +++ b/pkg/controller/builder/builder_stateful_set_test.go @@ -70,7 +70,7 @@ var _ = Describe("stateful_set builder", func() { }, Spec: corev1.PersistentVolumeClaimSpec{ VolumeName: "foo-1", - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("500m"), }, @@ -85,7 +85,7 @@ var _ = Describe("stateful_set builder", func() { }, Spec: corev1.PersistentVolumeClaimSpec{ VolumeName: "foo-2", - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("600m"), }, diff --git a/pkg/controller/configuration/config_template_test.go b/pkg/controller/configuration/config_template_test.go index ebd98e082df9..57ff07c107aa 100644 --- a/pkg/controller/configuration/config_template_test.go +++ b/pkg/controller/configuration/config_template_test.go @@ -158,7 +158,7 @@ single_thread_memory = 294912 Name: "data", }, Spec: corev1.PersistentVolumeClaimSpec{ - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceStorage: resource.MustParse("10Gi"), }, diff --git a/pkg/controller/instanceset/in_place_update_util.go b/pkg/controller/instanceset/in_place_update_util.go index 1a8495ab774d..92c78de4f564 100644 --- a/pkg/controller/instanceset/in_place_update_util.go +++ b/pkg/controller/instanceset/in_place_update_util.go @@ -27,8 +27,6 @@ import ( "golang.org/x/exp/slices" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" - utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/kubernetes/pkg/features" workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" "github.com/apecloud/kubeblocks/pkg/constant" @@ -45,7 +43,7 @@ const ( ) func supportPodVerticalScaling() bool { - return utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) + return viper.GetBool(constant.FeatureGateInPlacePodVerticalScaling) } func filterInPlaceFields(src *corev1.PodTemplateSpec) *corev1.PodTemplateSpec { diff --git a/pkg/controller/instanceset/instance_util_test.go b/pkg/controller/instanceset/instance_util_test.go index 3592d78bc703..fbd2e5bfcd25 100644 --- a/pkg/controller/instanceset/instance_util_test.go +++ b/pkg/controller/instanceset/instance_util_test.go @@ -321,12 +321,12 @@ var _ = Describe("instance util test", func() { By("merge pvc") oldPvc := builder.NewPVCBuilder(namespace, name). - SetResources(corev1.ResourceRequirements{Requests: map[corev1.ResourceName]resource.Quantity{ + SetResources(corev1.VolumeResourceRequirements{Requests: map[corev1.ResourceName]resource.Quantity{ corev1.ResourceStorage: resource.MustParse("1G"), }}). GetObject() newPvc := builder.NewPVCBuilder(namespace, name). - SetResources(corev1.ResourceRequirements{Requests: map[corev1.ResourceName]resource.Quantity{ + SetResources(corev1.VolumeResourceRequirements{Requests: map[corev1.ResourceName]resource.Quantity{ corev1.ResourceStorage: resource.MustParse("2G"), }}). GetObject() diff --git a/pkg/controller/instanceset/suite_test.go b/pkg/controller/instanceset/suite_test.go index 250e9835781e..9f59ed2a8ab2 100644 --- a/pkg/controller/instanceset/suite_test.go +++ b/pkg/controller/instanceset/suite_test.go @@ -133,7 +133,7 @@ var ( Name: "data", }, Spec: corev1.PersistentVolumeClaimSpec{ - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: map[corev1.ResourceName]resource.Quantity{ corev1.ResourceStorage: resource.MustParse("2G"), }, diff --git a/pkg/controller/kubebuilderx/plan_builder_test.go b/pkg/controller/kubebuilderx/plan_builder_test.go index c41cfa553ffc..8aaa44691a67 100644 --- a/pkg/controller/kubebuilderx/plan_builder_test.go +++ b/pkg/controller/kubebuilderx/plan_builder_test.go @@ -126,7 +126,7 @@ var _ = Describe("plan builder test", func() { It("should update pvc object", func() { pvcOrig := builder.NewPVCBuilder(namespace, name).GetObject() pvc := pvcOrig.DeepCopy() - pvc.Spec.Resources = corev1.ResourceRequirements{ + pvc.Spec.Resources = corev1.VolumeResourceRequirements{ Requests: map[corev1.ResourceName]resource.Quantity{ corev1.ResourceStorage: resource.MustParse("500m"), }, diff --git a/pkg/controllerutil/pod_utils_test.go b/pkg/controllerutil/pod_utils_test.go index 447dc4da6410..0427ef9035b2 100644 --- a/pkg/controllerutil/pod_utils_test.go +++ b/pkg/controllerutil/pod_utils_test.go @@ -390,7 +390,7 @@ var _ = Describe("pod utils", func() { // memory unit: Gi { pvc: corev1.PersistentVolumeClaimSpec{ - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceStorage: resource.MustParse("100Gi"), }, @@ -401,7 +401,7 @@ var _ = Describe("pod utils", func() { // memory unit: G { pvc: corev1.PersistentVolumeClaimSpec{ - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceStorage: resource.MustParse("100G"), }, @@ -412,7 +412,7 @@ var _ = Describe("pod utils", func() { // memory unit: no { pvc: corev1.PersistentVolumeClaimSpec{ - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceStorage: resource.MustParse("10000"), }, diff --git a/pkg/lorry/client/k8sexec_client.go b/pkg/lorry/client/k8sexec_client.go index 1e10f4d7fafd..33f8d897e843 100644 --- a/pkg/lorry/client/k8sexec_client.go +++ b/pkg/lorry/client/k8sexec_client.go @@ -193,7 +193,7 @@ func (cli *K8sExecClient) k8sExec(cmd []string, outWriter io.Writer, errWriter i TTY: t.Raw, }, scheme.ParameterCodec) - return cli.Executor.Execute("POST", req.URL(), cli.restConfig, cli.In, outWriter, errWriter, t.Raw, sizeQueue) + return cli.Executor.Execute(req.URL(), cli.restConfig, cli.In, outWriter, errWriter, t.Raw, sizeQueue) } if err := t.Safe(fn); err != nil { diff --git a/pkg/testutil/apps/cluster_util.go b/pkg/testutil/apps/cluster_util.go index 43edc1f84a09..ed1cf244b49b 100644 --- a/pkg/testutil/apps/cluster_util.go +++ b/pkg/testutil/apps/cluster_util.go @@ -89,7 +89,7 @@ func GetClusterObservedGeneration(testCtx *testutil.TestContext, clusterKey type func NewPVCSpec(size string) appsv1alpha1.PersistentVolumeClaimSpec { return appsv1alpha1.PersistentVolumeClaimSpec{ AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceStorage: resource.MustParse(size), }, diff --git a/pkg/testutil/apps/native_object_util.go b/pkg/testutil/apps/native_object_util.go index 619f7276314a..de0f85db4469 100644 --- a/pkg/testutil/apps/native_object_util.go +++ b/pkg/testutil/apps/native_object_util.go @@ -61,7 +61,7 @@ func SetConfigMapData(key string, value string) func(*corev1.ConfigMap) { func NewPVC(size string) corev1.PersistentVolumeClaimSpec { return corev1.PersistentVolumeClaimSpec{ AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceStorage: resource.MustParse(size), }, diff --git a/pkg/testutil/apps/pvc_factoy.go b/pkg/testutil/apps/pvc_factoy.go index 055025ccf4e9..13dbcd3b4679 100644 --- a/pkg/testutil/apps/pvc_factoy.go +++ b/pkg/testutil/apps/pvc_factoy.go @@ -62,7 +62,7 @@ func (factory *MockPersistentVolumeClaimFactory) SetStorageClass(storageClassNam } func (factory *MockPersistentVolumeClaimFactory) SetStorage(storageSize string) *MockPersistentVolumeClaimFactory { - factory.Get().Spec.Resources = corev1.ResourceRequirements{ + factory.Get().Spec.Resources = corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceStorage: resource.MustParse(storageSize), }, diff --git a/pkg/testutil/dataprotection/restore_factory.go b/pkg/testutil/dataprotection/restore_factory.go index 8e4163cfb4d4..80a5098e94ca 100644 --- a/pkg/testutil/dataprotection/restore_factory.go +++ b/pkg/testutil/dataprotection/restore_factory.go @@ -102,7 +102,7 @@ func (f *MockRestoreFactory) buildRestoreVolumeClaim(name, volumeSource, mountPa }, VolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ StorageClassName: &storageClass, - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceStorage: resource.MustParse("20Gi"), }, diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go index e3d606112de9..ffd783f8978f 100644 --- a/test/e2e/e2e_suite_test.go +++ b/test/e2e/e2e_suite_test.go @@ -27,8 +27,8 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - . "github.com/vmware-tanzu/velero/test/e2e" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" + "github.com/vmware-tanzu/velero/test" + . "github.com/vmware-tanzu/velero/test/util/k8s" "github.com/onsi/ginkgo/v2/reporters" "go.uber.org/zap/zapcore" @@ -84,15 +84,15 @@ func TestE2e(t *testing.T) { func GetKubeconfigContext() error { var err error var tcDefault TestClient - tcDefault, err = NewTestClient(VeleroCfg.DefaultCluster) - VeleroCfg.DefaultClient = &tcDefault - VeleroCfg.ClientToInstallVelero = VeleroCfg.DefaultClient + tcDefault, err = NewTestClient(test.VeleroCfg.DefaultCluster) + test.VeleroCfg.DefaultClient = &tcDefault + test.VeleroCfg.ClientToInstallVelero = test.VeleroCfg.DefaultClient if err != nil { return err } - if VeleroCfg.DefaultCluster != "" { - err = KubectlConfigUseContext(context.Background(), VeleroCfg.DefaultCluster) + if test.VeleroCfg.DefaultCluster != "" { + err = KubectlConfigUseContext(context.Background(), test.VeleroCfg.DefaultCluster) if err != nil { return err } diff --git a/test/e2e/util/client.go b/test/e2e/util/client.go index b25b922a7b1a..c13e0e22e234 100644 --- a/test/e2e/util/client.go +++ b/test/e2e/util/client.go @@ -34,17 +34,17 @@ type TestClient struct { } // NewTestClient returns a set of ready-to-use API clients. -func NewTestClient(kubecontext string) (TestClient, error) { - return InitTestClient(kubecontext) +func NewTestClient() (TestClient, error) { + return InitTestClient() } // InitTestClient inits different type clients -func InitTestClient(kubecontext string) (TestClient, error) { +func InitTestClient() (TestClient, error) { config, err := client.LoadConfig() if err != nil { return TestClient{}, err } - f := client.NewFactory("e2e", kubecontext, config) + f := client.NewFactory("e2e", config) clientGo, err := f.KubeClient() if err != nil { return TestClient{}, err diff --git a/test/e2e/util/common.go b/test/e2e/util/common.go index e3f71240c4e0..ae2e0425357e 100644 --- a/test/e2e/util/common.go +++ b/test/e2e/util/common.go @@ -26,7 +26,7 @@ import ( "github.com/pkg/errors" "github.com/vmware-tanzu/velero/pkg/builder" veleroexec "github.com/vmware-tanzu/velero/pkg/util/exec" - "github.com/vmware-tanzu/velero/test/e2e/util/common" + "github.com/vmware-tanzu/velero/test/util/common" "golang.org/x/net/context" corev1api "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" From 1bccc47a617b2004890f3433277b6b75d193f765 Mon Sep 17 00:00:00 2001 From: Leon Date: Thu, 8 Aug 2024 10:45:40 +0800 Subject: [PATCH 44/45] chore: remove cd ref from backup policy template (#7940) --- .../v1alpha1/backuppolicytemplate_types.go | 53 +------- apis/apps/v1alpha1/zz_generated.deepcopy.go | 40 +----- ...s.kubeblocks.io_backuppolicytemplates.yaml | 78 ----------- .../apps/backuppolicytemplate_controller.go | 6 - .../backuppolicytemplate_controller_test.go | 8 +- controllers/apps/cluster_controller_test.go | 1 - .../apps/component_hscale_volume_populator.go | 4 +- .../apps/componentdefinition_controller.go | 6 - .../apps/transformer_cluster_backup_policy.go | 38 +++--- .../apps/transformer_component_rbac.go | 12 +- ...s.kubeblocks.io_backuppolicytemplates.yaml | 78 ----------- docs/developer_docs/api-reference/cluster.md | 124 ------------------ pkg/constant/labels.go | 3 +- pkg/controller/plan/restore_test.go | 3 +- .../apps/backuppolicytemplate_factory.go | 15 +-- 15 files changed, 30 insertions(+), 439 deletions(-) diff --git a/apis/apps/v1alpha1/backuppolicytemplate_types.go b/apis/apps/v1alpha1/backuppolicytemplate_types.go index 200e9fb5428a..982d02697326 100644 --- a/apis/apps/v1alpha1/backuppolicytemplate_types.go +++ b/apis/apps/v1alpha1/backuppolicytemplate_types.go @@ -24,15 +24,6 @@ import ( // BackupPolicyTemplateSpec contains the settings in a BackupPolicyTemplate. type BackupPolicyTemplateSpec struct { - // Specifies the name of a ClusterDefinition. - // This is an immutable attribute that cannot be changed after creation. - // And this field is deprecated since v0.9, consider using the ComponentDef instead. - // - // +kubebuilder:validation:Pattern:=`^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$` - // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="clusterDefinitionRef is immutable" - // +kubebuilder:deprecatedversion:warning="This field has been deprecated since 0.9.0, consider using the ComponentDef instead" - ClusterDefRef string `json:"clusterDefinitionRef,omitempty"` - // Represents an array of BackupPolicy templates, with each template corresponding to a specified ComponentDefinition // or to a group of ComponentDefinitions that are different versions of definitions of the same component. // @@ -56,18 +47,6 @@ type BackupPolicyTemplateSpec struct { // BackupPolicy is the template corresponding to a specified ComponentDefinition // or to a group of ComponentDefinitions that are different versions of definitions of the same component. type BackupPolicy struct { - // Specifies the name of ClusterComponentDefinition defined in the ClusterDefinition. - // Must comply with the IANA Service Naming rule. - // - // Deprecated since v0.9, should use `componentDefs` instead. - // This field is maintained for backward compatibility and its use is discouraged. - // Existing usage should be updated to the current preferred approach to avoid compatibility issues in future releases. - // - // +kubebuilder:validation:MaxLength=22 - // +kubebuilder:validation:Pattern:=`^[a-z]([a-z0-9\-]*[a-z0-9])?$` - // +optional - ComponentDefRef string `json:"componentDefRef,omitempty"` - // Specifies a list of names of ComponentDefinitions that the specified ClusterDefinition references. // They should be different versions of definitions of the same component, // thus allowing them to share a single BackupPolicy. @@ -220,9 +199,6 @@ type TargetInstance struct { // This account must match one listed in `componentDefinition.spec.systemAccounts[*].name`. // The corresponding secret created by this account is used to connect to the database. // - // If `backupPolicy.componentDefRef` (a legacy and deprecated API) is set, the secret defined in - // `clusterDefinition.spec.ConnectionCredential` is used instead. - // // +optional Account string `json:"account,omitempty"` @@ -235,37 +211,10 @@ type TargetInstance struct { // // +optional Strategy dpv1alpha1.PodSelectionStrategy `json:"strategy,omitempty"` - - // Specifies the keys of the connection credential secret defined in `clusterDefinition.spec.ConnectionCredential`. - // It will be ignored when the `account` is set. - // - // +optional - ConnectionCredentialKey ConnectionCredentialKey `json:"connectionCredentialKey,omitempty"` -} - -type ConnectionCredentialKey struct { - // Represents the key of the password in the connection credential secret. - // If not specified, the default key "password" is used. - // - // +optional - PasswordKey *string `json:"passwordKey,omitempty"` - - // Represents the key of the username in the connection credential secret. - // If not specified, the default key "username" is used. - // - // +optional - UsernameKey *string `json:"usernameKey,omitempty"` - - // Defines the key of the host in the connection credential secret. - HostKey *string `json:"hostKey,omitempty"` - - // Indicates map key of the port in the connection credential secret. - PortKey *string `json:"portKey,omitempty"` } // BackupPolicyTemplateStatus defines the observed state of BackupPolicyTemplate. -type BackupPolicyTemplateStatus struct { -} +type BackupPolicyTemplateStatus struct{} // BackupPolicyTemplate should be provided by addon developers and is linked to a ClusterDefinition // and its associated ComponentDefinitions. diff --git a/apis/apps/v1alpha1/zz_generated.deepcopy.go b/apis/apps/v1alpha1/zz_generated.deepcopy.go index 89d4cb36cf79..7459d1255783 100644 --- a/apis/apps/v1alpha1/zz_generated.deepcopy.go +++ b/apis/apps/v1alpha1/zz_generated.deepcopy.go @@ -128,7 +128,7 @@ func (in *BackupMethod) DeepCopyInto(out *BackupMethod) { if in.Target != nil { in, out := &in.Target, &out.Target *out = new(TargetInstance) - (*in).DeepCopyInto(*out) + **out = **in } if in.EnvMapping != nil { in, out := &in.EnvMapping, &out.EnvMapping @@ -157,7 +157,7 @@ func (in *BackupPolicy) DeepCopyInto(out *BackupPolicy) { *out = make([]string, len(*in)) copy(*out, *in) } - in.Target.DeepCopyInto(&out.Target) + out.Target = in.Target if in.Schedules != nil { in, out := &in.Schedules, &out.Schedules *out = make([]SchedulePolicy, len(*in)) @@ -2436,41 +2436,6 @@ func (in *ConnectionCredentialAuth) DeepCopy() *ConnectionCredentialAuth { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConnectionCredentialKey) DeepCopyInto(out *ConnectionCredentialKey) { - *out = *in - if in.PasswordKey != nil { - in, out := &in.PasswordKey, &out.PasswordKey - *out = new(string) - **out = **in - } - if in.UsernameKey != nil { - in, out := &in.UsernameKey, &out.UsernameKey - *out = new(string) - **out = **in - } - if in.HostKey != nil { - in, out := &in.HostKey, &out.HostKey - *out = new(string) - **out = **in - } - if in.PortKey != nil { - in, out := &in.PortKey, &out.PortKey - *out = new(string) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConnectionCredentialKey. -func (in *ConnectionCredentialKey) DeepCopy() *ConnectionCredentialKey { - if in == nil { - return nil - } - out := new(ConnectionCredentialKey) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ContainerVars) DeepCopyInto(out *ContainerVars) { *out = *in @@ -5192,7 +5157,6 @@ func (in *TLSSecretRef) DeepCopy() *TLSSecretRef { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TargetInstance) DeepCopyInto(out *TargetInstance) { *out = *in - in.ConnectionCredentialKey.DeepCopyInto(&out.ConnectionCredentialKey) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetInstance. diff --git a/config/crd/bases/apps.kubeblocks.io_backuppolicytemplates.yaml b/config/crd/bases/apps.kubeblocks.io_backuppolicytemplates.yaml index d9fee4b254ad..1ea97ded6d23 100644 --- a/config/crd/bases/apps.kubeblocks.io_backuppolicytemplates.yaml +++ b/config/crd/bases/apps.kubeblocks.io_backuppolicytemplates.yaml @@ -355,10 +355,6 @@ spec: If `backupPolicy.componentDefs` is set, this field is required to specify the system account name. This account must match one listed in `componentDefinition.spec.systemAccounts[*].name`. The corresponding secret created by this account is used to connect to the database. - - - If `backupPolicy.componentDefRef` (a legacy and deprecated API) is set, the secret defined in - `clusterDefinition.spec.ConnectionCredential` is used instead. type: string connectionCredential: description: Specifies the connection credential to @@ -392,30 +388,6 @@ spec: required: - secretName type: object - connectionCredentialKey: - description: |- - Specifies the keys of the connection credential secret defined in `clusterDefinition.spec.ConnectionCredential`. - It will be ignored when the `account` is set. - properties: - hostKey: - description: Defines the key of the host in the - connection credential secret. - type: string - passwordKey: - description: |- - Represents the key of the password in the connection credential secret. - If not specified, the default key "password" is used. - type: string - portKey: - description: Indicates map key of the port in - the connection credential secret. - type: string - usernameKey: - description: |- - Represents the key of the username in the connection credential secret. - If not specified, the default key "username" is used. - type: string - type: object fallbackRole: description: |- Specifies the fallback role to select one replica for backup, this only takes effect when the @@ -920,18 +892,6 @@ spec: - name type: object type: array - componentDefRef: - description: |- - Specifies the name of ClusterComponentDefinition defined in the ClusterDefinition. - Must comply with the IANA Service Naming rule. - - - Deprecated since v0.9, should use `componentDefs` instead. - This field is maintained for backward compatibility and its use is discouraged. - Existing usage should be updated to the current preferred approach to avoid compatibility issues in future releases. - maxLength: 22 - pattern: ^[a-z]([a-z0-9\-]*[a-z0-9])?$ - type: string componentDefs: description: |- Specifies a list of names of ComponentDefinitions that the specified ClusterDefinition references. @@ -986,35 +946,7 @@ spec: If `backupPolicy.componentDefs` is set, this field is required to specify the system account name. This account must match one listed in `componentDefinition.spec.systemAccounts[*].name`. The corresponding secret created by this account is used to connect to the database. - - - If `backupPolicy.componentDefRef` (a legacy and deprecated API) is set, the secret defined in - `clusterDefinition.spec.ConnectionCredential` is used instead. type: string - connectionCredentialKey: - description: |- - Specifies the keys of the connection credential secret defined in `clusterDefinition.spec.ConnectionCredential`. - It will be ignored when the `account` is set. - properties: - hostKey: - description: Defines the key of the host in the connection - credential secret. - type: string - passwordKey: - description: |- - Represents the key of the password in the connection credential secret. - If not specified, the default key "password" is used. - type: string - portKey: - description: Indicates map key of the port in the connection - credential secret. - type: string - usernameKey: - description: |- - Represents the key of the username in the connection credential secret. - If not specified, the default key "username" is used. - type: string - type: object fallbackRole: description: |- Specifies the fallback role to select one replica for backup, this only takes effect when the @@ -1055,16 +987,6 @@ spec: type: object minItems: 1 type: array - clusterDefinitionRef: - description: |- - Specifies the name of a ClusterDefinition. - This is an immutable attribute that cannot be changed after creation. - And this field is deprecated since v0.9, consider using the ComponentDef instead. - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - x-kubernetes-validations: - - message: clusterDefinitionRef is immutable - rule: self == oldSelf identifier: description: |- Specifies a unique identifier for the BackupPolicyTemplate. diff --git a/controllers/apps/backuppolicytemplate_controller.go b/controllers/apps/backuppolicytemplate_controller.go index 849d5bd51544..ea1a6f7c12fb 100644 --- a/controllers/apps/backuppolicytemplate_controller.go +++ b/controllers/apps/backuppolicytemplate_controller.go @@ -27,7 +27,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" - "github.com/apecloud/kubeblocks/pkg/constant" intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" ) @@ -54,11 +53,6 @@ func (r *BackupPolicyTemplateReconciler) Reconcile(ctx context.Context, req reco return intctrlutil.CheckedRequeueWithError(err, reqCtx.Log, "") } - // infer clusterDefRef from spec.clusterDefRef - if backupPolicyTemplate.Spec.ClusterDefRef != "" { - backupPolicyTemplate.Labels[constant.ClusterDefLabelKey] = backupPolicyTemplate.Spec.ClusterDefRef - } - for _, backupPolicy := range backupPolicyTemplate.Spec.BackupPolicies { for _, compDef := range backupPolicy.ComponentDefs { backupPolicyTemplate.Labels[compDef] = compDef diff --git a/controllers/apps/backuppolicytemplate_controller_test.go b/controllers/apps/backuppolicytemplate_controller_test.go index e492e46c1456..dc7e6726f3bd 100644 --- a/controllers/apps/backuppolicytemplate_controller_test.go +++ b/controllers/apps/backuppolicytemplate_controller_test.go @@ -23,7 +23,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" - "github.com/apecloud/kubeblocks/pkg/constant" intctrlutil "github.com/apecloud/kubeblocks/pkg/generics" testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" ) @@ -31,8 +30,6 @@ import ( var _ = Describe("", func() { var ( BackupPolicyTemplateName = "test-bpt" - ClusterDefName = "test-cd" - BackupPolicyName = "test-bp" BackupMethod = "test-bm" ActionSetName = "test-as" VsBackupMethodName = "test-vs-bm" @@ -63,9 +60,7 @@ var _ = Describe("", func() { compDef1 := "compDef1" compDef2 := "compDef2" bpt := testapps.NewBackupPolicyTemplateFactory(BackupPolicyTemplateName). - SetClusterDefRef(ClusterDefName). - AddBackupPolicy(BackupPolicyName). - SetComponentDef(compDef1, compDef2). + AddBackupPolicy(compDef1, compDef2). AddBackupMethod(BackupMethod, false, ActionSetName). SetBackupMethodVolumeMounts("data", "/data"). AddBackupMethod(VsBackupMethodName, true, ""). @@ -75,7 +70,6 @@ var _ = Describe("", func() { Create(&testCtx).GetObject() key := client.ObjectKeyFromObject(bpt) Eventually(testapps.CheckObj(&testCtx, key, func(g Gomega, pobj *v1alpha1.BackupPolicyTemplate) { - g.Expect(pobj.GetLabels()[constant.ClusterDefLabelKey]).To(Equal(bpt.Spec.ClusterDefRef)) g.Expect(pobj.GetLabels()[compDef1]).To(Equal(compDef1)) g.Expect(pobj.GetLabels()[compDef2]).To(Equal(compDef2)) })).Should(Succeed()) diff --git a/controllers/apps/cluster_controller_test.go b/controllers/apps/cluster_controller_test.go index 1077b7cdb3b4..6c093ac7c370 100644 --- a/controllers/apps/cluster_controller_test.go +++ b/controllers/apps/cluster_controller_test.go @@ -1413,7 +1413,6 @@ func createBackupPolicyTpl(compDef string) { ttl := "7d" bpt = bpt.AddBackupPolicy(compDef). AddBackupMethod(backupMethodName, false, actionSetName). - SetComponentDef(compDef). SetBackupMethodVolumeMounts("data", "/data"). AddBackupMethod(vsBackupMethodName, true, ""). SetBackupMethodVolumes([]string{"data"}). diff --git a/controllers/apps/component_hscale_volume_populator.go b/controllers/apps/component_hscale_volume_populator.go index 072d546da638..7c33c3ffc341 100644 --- a/controllers/apps/component_hscale_volume_populator.go +++ b/controllers/apps/component_hscale_volume_populator.go @@ -445,8 +445,8 @@ func getBackupPolicyFromTemplate(reqCtx intctrlutil.RequestCtx, if err := cli.List(reqCtx.Ctx, backupPolicyList, client.InNamespace(cluster.Namespace), client.MatchingLabels{ - constant.AppInstanceLabelKey: cluster.Name, - constant.KBAppComponentDefRefLabelKey: componentDef, + constant.AppInstanceLabelKey: cluster.Name, + constant.ComponentDefinitionLabelKey: componentDef, }); err != nil { return nil, err } diff --git a/controllers/apps/componentdefinition_controller.go b/controllers/apps/componentdefinition_controller.go index adec2693747e..0f68eac2033b 100644 --- a/controllers/apps/componentdefinition_controller.go +++ b/controllers/apps/componentdefinition_controller.go @@ -191,7 +191,6 @@ func (r *ComponentDefinitionReconciler) validate(cli client.Client, rctx intctrl r.validateSystemAccounts, r.validateReplicaRoles, r.validateLifecycleActions, - r.validateComponentDefRef, } { if err := validator(cli, rctx, cmpd); err != nil { return err @@ -398,11 +397,6 @@ func (r *ComponentDefinitionReconciler) validateLifecycleActionBuiltInHandlers(l return nil } -func (r *ComponentDefinitionReconciler) validateComponentDefRef(cli client.Client, reqCtx intctrlutil.RequestCtx, - cmpd *appsv1alpha1.ComponentDefinition) error { - return nil -} - func (r *ComponentDefinitionReconciler) immutableCheck(cmpd *appsv1alpha1.ComponentDefinition) error { if r.skipImmutableCheck(cmpd) { return nil diff --git a/controllers/apps/transformer_cluster_backup_policy.go b/controllers/apps/transformer_cluster_backup_policy.go index 49ad32b562ae..65aab038e4d8 100644 --- a/controllers/apps/transformer_cluster_backup_policy.go +++ b/controllers/apps/transformer_cluster_backup_policy.go @@ -22,6 +22,7 @@ package apps import ( "encoding/json" "fmt" + "strings" "golang.org/x/exp/slices" corev1 "k8s.io/api/core/v1" @@ -189,17 +190,10 @@ func (r *clusterBackupPolicyTransformer) Transform(ctx graph.TransformContext, d // getBackupPolicyTemplates gets the backupPolicyTemplate for the cluster. func (r *clusterBackupPolicyTransformer) getBackupPolicyTemplates() (*appsv1alpha1.BackupPolicyTemplateList, error) { backupPolicyTPLs := &appsv1alpha1.BackupPolicyTemplateList{} - if r.ClusterDef != nil && r.ClusterDef.Name != "" { - if err := r.Client.List(r.Context, backupPolicyTPLs, - client.MatchingLabels{constant.ClusterDefLabelKey: r.ClusterDef.Name}); err != nil { - return nil, err - } - return backupPolicyTPLs, nil - } - // get the backupPolicyTemplate if not exists spec.clusterDefRef tplMap := map[string]sets.Empty{} for _, v := range r.ComponentDefs { tmpTPLs := &appsv1alpha1.BackupPolicyTemplateList{} + // TODO: prefix match for componentDef name? if err := r.Client.List(r.Context, tmpTPLs, client.MatchingLabels{v.Name: v.Name}); err != nil { return nil, err } @@ -641,12 +635,17 @@ func (r *clusterBackupPolicyTransformer) mergeClusterBackup( return backupSchedule } -// getClusterComponentSpec returns the component which matches the componentDef or componentDefRef. func (r *clusterBackupPolicyTransformer) getClusterComponentItems() []componentItem { matchedCompDef := func(compSpec appsv1alpha1.ClusterComponentSpec) bool { // TODO: support to create bp when using cluster topology and componentDef is empty - return (compSpec.ComponentDefRef != "" && compSpec.ComponentDefRef == r.backupPolicy.ComponentDefRef) || - (compSpec.ComponentDef != "" && slices.Contains(r.backupPolicy.ComponentDefs, compSpec.ComponentDef)) + if len(compSpec.ComponentDef) > 0 { + for _, compDef := range r.backupPolicy.ComponentDefs { + if strings.HasPrefix(compSpec.ComponentDef, compDef) || strings.HasPrefix(compDef, compSpec.ComponentDef) { + return true + } + } + } + return false } var compSpecItems []componentItem for i, v := range r.clusterTransformContext.Cluster.Spec.ComponentSpecs { @@ -693,12 +692,11 @@ func (r *clusterBackupPolicyTransformer) buildAnnotations() map[string]string { return annotations } -func (r *clusterBackupPolicyTransformer) buildLabels(compItem componentItem, - policy *dpv1alpha1.BackupPolicy) map[string]string { +func (r *clusterBackupPolicyTransformer) buildLabels(compItem componentItem, policy *dpv1alpha1.BackupPolicy) map[string]string { labels := map[string]string{ - constant.AppInstanceLabelKey: r.OrigCluster.Name, - constant.KBAppComponentDefRefLabelKey: r.compDefName(compItem.compSpec, policy), - constant.AppManagedByLabelKey: constant.AppName, + constant.AppManagedByLabelKey: constant.AppName, + constant.AppInstanceLabelKey: r.OrigCluster.Name, + constant.ComponentDefinitionLabelKey: r.compDefName(compItem.compSpec, policy), } if compItem.isSharding { labels[constant.KBAppShardingNameLabelKey] = compItem.componentName @@ -721,17 +719,13 @@ func (r *clusterBackupPolicyTransformer) compDefName(comp *appsv1alpha1.ClusterC } func (r *clusterBackupPolicyTransformer) compDefNameFromSpec(comp *appsv1alpha1.ClusterComponentSpec) string { - compDefName := comp.ComponentDef - if compDefName == "" { - compDefName = comp.ComponentDefRef - } - return compDefName + return comp.ComponentDef } func (r *clusterBackupPolicyTransformer) compDefNameFromPolicy(policy *dpv1alpha1.BackupPolicy) string { compDefName := "" if policy.Labels != nil { - compDefName = policy.Labels[constant.KBAppComponentDefRefLabelKey] + compDefName = policy.Labels[constant.ComponentDefinitionLabelKey] } return compDefName } diff --git a/controllers/apps/transformer_component_rbac.go b/controllers/apps/transformer_component_rbac.go index d3cd4cd5be49..50d10b36db90 100644 --- a/controllers/apps/transformer_component_rbac.go +++ b/controllers/apps/transformer_component_rbac.go @@ -21,6 +21,7 @@ package apps import ( "fmt" + "strings" "time" corev1 "k8s.io/api/core/v1" @@ -112,15 +113,10 @@ func isLifecycleActionsEnabled(compDef *appsv1alpha1.ComponentDefinition) bool { } func isDataProtectionEnabled(backupTpl *appsv1alpha1.BackupPolicyTemplate, cluster *appsv1alpha1.Cluster, comp *appsv1alpha1.Component) bool { - if backupTpl != nil { + if backupTpl != nil && len(comp.Spec.CompDef) > 0 { for _, policy := range backupTpl.Spec.BackupPolicies { - // TODO(component): the definition of component referenced by backup policy. - if policy.ComponentDefRef == comp.Spec.CompDef { - return true - } - // TODO: Compatibility handling, remove it if the clusterDefinition is removed. - for _, v := range cluster.Spec.ComponentSpecs { - if v.ComponentDefRef == policy.ComponentDefRef { + for _, compDef := range policy.ComponentDefs { + if strings.HasPrefix(comp.Spec.CompDef, compDef) { return true } } diff --git a/deploy/helm/crds/apps.kubeblocks.io_backuppolicytemplates.yaml b/deploy/helm/crds/apps.kubeblocks.io_backuppolicytemplates.yaml index d9fee4b254ad..1ea97ded6d23 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_backuppolicytemplates.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_backuppolicytemplates.yaml @@ -355,10 +355,6 @@ spec: If `backupPolicy.componentDefs` is set, this field is required to specify the system account name. This account must match one listed in `componentDefinition.spec.systemAccounts[*].name`. The corresponding secret created by this account is used to connect to the database. - - - If `backupPolicy.componentDefRef` (a legacy and deprecated API) is set, the secret defined in - `clusterDefinition.spec.ConnectionCredential` is used instead. type: string connectionCredential: description: Specifies the connection credential to @@ -392,30 +388,6 @@ spec: required: - secretName type: object - connectionCredentialKey: - description: |- - Specifies the keys of the connection credential secret defined in `clusterDefinition.spec.ConnectionCredential`. - It will be ignored when the `account` is set. - properties: - hostKey: - description: Defines the key of the host in the - connection credential secret. - type: string - passwordKey: - description: |- - Represents the key of the password in the connection credential secret. - If not specified, the default key "password" is used. - type: string - portKey: - description: Indicates map key of the port in - the connection credential secret. - type: string - usernameKey: - description: |- - Represents the key of the username in the connection credential secret. - If not specified, the default key "username" is used. - type: string - type: object fallbackRole: description: |- Specifies the fallback role to select one replica for backup, this only takes effect when the @@ -920,18 +892,6 @@ spec: - name type: object type: array - componentDefRef: - description: |- - Specifies the name of ClusterComponentDefinition defined in the ClusterDefinition. - Must comply with the IANA Service Naming rule. - - - Deprecated since v0.9, should use `componentDefs` instead. - This field is maintained for backward compatibility and its use is discouraged. - Existing usage should be updated to the current preferred approach to avoid compatibility issues in future releases. - maxLength: 22 - pattern: ^[a-z]([a-z0-9\-]*[a-z0-9])?$ - type: string componentDefs: description: |- Specifies a list of names of ComponentDefinitions that the specified ClusterDefinition references. @@ -986,35 +946,7 @@ spec: If `backupPolicy.componentDefs` is set, this field is required to specify the system account name. This account must match one listed in `componentDefinition.spec.systemAccounts[*].name`. The corresponding secret created by this account is used to connect to the database. - - - If `backupPolicy.componentDefRef` (a legacy and deprecated API) is set, the secret defined in - `clusterDefinition.spec.ConnectionCredential` is used instead. type: string - connectionCredentialKey: - description: |- - Specifies the keys of the connection credential secret defined in `clusterDefinition.spec.ConnectionCredential`. - It will be ignored when the `account` is set. - properties: - hostKey: - description: Defines the key of the host in the connection - credential secret. - type: string - passwordKey: - description: |- - Represents the key of the password in the connection credential secret. - If not specified, the default key "password" is used. - type: string - portKey: - description: Indicates map key of the port in the connection - credential secret. - type: string - usernameKey: - description: |- - Represents the key of the username in the connection credential secret. - If not specified, the default key "username" is used. - type: string - type: object fallbackRole: description: |- Specifies the fallback role to select one replica for backup, this only takes effect when the @@ -1055,16 +987,6 @@ spec: type: object minItems: 1 type: array - clusterDefinitionRef: - description: |- - Specifies the name of a ClusterDefinition. - This is an immutable attribute that cannot be changed after creation. - And this field is deprecated since v0.9, consider using the ComponentDef instead. - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - x-kubernetes-validations: - - message: clusterDefinitionRef is immutable - rule: self == oldSelf identifier: description: |- Specifies a unique identifier for the BackupPolicyTemplate. diff --git a/docs/developer_docs/api-reference/cluster.md b/docs/developer_docs/api-reference/cluster.md index 84e23144ca82..ab9eb053d9cf 100644 --- a/docs/developer_docs/api-reference/cluster.md +++ b/docs/developer_docs/api-reference/cluster.md @@ -3397,22 +3397,6 @@ or to a group of ComponentDefinitions that are different versions of definitions -componentDefRef
    - -string - - - -(Optional) -

    Specifies the name of ClusterComponentDefinition defined in the ClusterDefinition. -Must comply with the IANA Service Naming rule.

    -

    Deprecated since v0.9, should use componentDefs instead. -This field is maintained for backward compatibility and its use is discouraged. -Existing usage should be updated to the current preferred approach to avoid compatibility issues in future releases.

    - - - - componentDefs
    []string @@ -3532,19 +3516,6 @@ BackupPolicyTemplateSpec - - - - - - - -
    -clusterDefinitionRef
    - -string - -
    -

    Specifies the name of a ClusterDefinition. -This is an immutable attribute that cannot be changed after creation. -And this field is deprecated since v0.9, consider using the ComponentDef instead.

    -
    backupPolicies
    @@ -3610,19 +3581,6 @@ BackupPolicyTemplateStatus
    -clusterDefinitionRef
    - -string - -
    -

    Specifies the name of a ClusterDefinition. -This is an immutable attribute that cannot be changed after creation. -And this field is deprecated since v0.9, consider using the ComponentDef instead.

    -
    backupPolicies
    @@ -9609,71 +9567,6 @@ CredentialVar
    -

    ConnectionCredentialKey -

    -

    -(Appears on:TargetInstance) -

    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -passwordKey
    - -string - -
    -(Optional) -

    Represents the key of the password in the connection credential secret. -If not specified, the default key “password” is used.

    -
    -usernameKey
    - -string - -
    -(Optional) -

    Represents the key of the username in the connection credential secret. -If not specified, the default key “username” is used.

    -
    -hostKey
    - -string - -
    -

    Defines the key of the host in the connection credential secret.

    -
    -portKey
    - -string - -
    -

    Indicates map key of the port in the connection credential secret.

    -

    ContainerVars

    @@ -17839,8 +17732,6 @@ string

    If backupPolicy.componentDefs is set, this field is required to specify the system account name. This account must match one listed in componentDefinition.spec.systemAccounts[*].name. The corresponding secret created by this account is used to connect to the database.

    -

    If backupPolicy.componentDefRef (a legacy and deprecated API) is set, the secret defined in -clusterDefinition.spec.ConnectionCredential is used instead.

    @@ -17861,21 +17752,6 @@ Valid values are:

    - - -connectionCredentialKey
    - - -ConnectionCredentialKey - - - - -(Optional) -

    Specifies the keys of the connection credential secret defined in clusterDefinition.spec.ConnectionCredential. -It will be ignored when the account is set.

    - -

    TargetPodSelector diff --git a/pkg/constant/labels.go b/pkg/constant/labels.go index 739307ff00c9..d4ae2d50bbda 100644 --- a/pkg/constant/labels.go +++ b/pkg/constant/labels.go @@ -44,8 +44,7 @@ const ( KBAppClusterUIDLabelKey = "apps.kubeblocks.io/cluster-uid" KBAppComponentLabelKey = "apps.kubeblocks.io/component-name" KBAppShardingNameLabelKey = "apps.kubeblocks.io/sharding-name" - KBAppComponentDefRefLabelKey = "apps.kubeblocks.io/component-def-ref" // refer clusterDefinition.Spec.ComponentDefs[*].Name before KubeBlocks Version 0.8.0 or refer ComponentDefinition.Name after KubeBlocks Version 0.8.0 - KBManagedByKey = "apps.kubeblocks.io/managed-by" // KBManagedByKey marks resources that auto created + KBManagedByKey = "apps.kubeblocks.io/managed-by" // KBManagedByKey marks resources that auto created PVCNameLabelKey = "apps.kubeblocks.io/pvc-name" VolumeClaimTemplateNameLabelKey = "apps.kubeblocks.io/vct-name" KBAppComponentInstanceTemplateLabelKey = "apps.kubeblocks.io/instance-template" diff --git a/pkg/controller/plan/restore_test.go b/pkg/controller/plan/restore_test.go index d3070167f98f..414df349e619 100644 --- a/pkg/controller/plan/restore_test.go +++ b/pkg/controller/plan/restore_test.go @@ -154,8 +154,7 @@ var _ = Describe("Restore", func() { By("By creating backup policyTemplate: ") _ = testapps.NewBackupPolicyTemplateFactory("backup-policy-template"). WithRandomName(). - AddBackupPolicy(defaultCompName). - SetComponentDef(compDef.Name). + AddBackupPolicy(compDef.Name). AddBackupMethod(testdp.BackupMethodName, false, fullBackupActionSetName). SetBackupMethodVolumeMounts(testapps.DataVolumeName, "/data") diff --git a/pkg/testutil/apps/backuppolicytemplate_factory.go b/pkg/testutil/apps/backuppolicytemplate_factory.go index 1e6eb97fc06b..c0633b073534 100644 --- a/pkg/testutil/apps/backuppolicytemplate_factory.go +++ b/pkg/testutil/apps/backuppolicytemplate_factory.go @@ -38,11 +38,6 @@ func NewBackupPolicyTemplateFactory(name string) *MockBackupPolicyTemplateFactor return f } -func (f *MockBackupPolicyTemplateFactory) SetClusterDefRef(clusterDefRef string) *MockBackupPolicyTemplateFactory { - f.Get().Spec.ClusterDefRef = clusterDefRef - return f -} - func (f *MockBackupPolicyTemplateFactory) getLastBackupPolicy() *appsv1alpha1.BackupPolicy { l := len(f.Get().Spec.BackupPolicies) if l == 0 { @@ -62,9 +57,9 @@ func (f *MockBackupPolicyTemplateFactory) getLastBackupMethod() *dpv1alpha1.Back return &backupMethods[l-1].BackupMethod } -func (f *MockBackupPolicyTemplateFactory) AddBackupPolicy(componentDef string) *MockBackupPolicyTemplateFactory { +func (f *MockBackupPolicyTemplateFactory) AddBackupPolicy(compDefs ...string) *MockBackupPolicyTemplateFactory { f.Get().Spec.BackupPolicies = append(f.Get().Spec.BackupPolicies, appsv1alpha1.BackupPolicy{ - ComponentDefRef: componentDef, + ComponentDefs: compDefs, }) return f } @@ -103,12 +98,6 @@ func (f *MockBackupPolicyTemplateFactory) AddBackupMethod(name string, snapshotV return f } -func (f *MockBackupPolicyTemplateFactory) SetComponentDef(compDefs ...string) *MockBackupPolicyTemplateFactory { - backupPolicy := f.getLastBackupPolicy() - backupPolicy.ComponentDefs = compDefs - return f -} - func (f *MockBackupPolicyTemplateFactory) SetBackupMethodVolumes(names []string) *MockBackupPolicyTemplateFactory { backupMethod := f.getLastBackupMethod() backupMethod.TargetVolumes.Volumes = names From a22856f45bc2ace1bb7dbf920c9b92115b32a816 Mon Sep 17 00:00:00 2001 From: Liang Deng <283304489@qq.com> Date: Thu, 8 Aug 2024 14:20:09 +0800 Subject: [PATCH 45/45] fix: when ParallelPodManagementConcurrency is nil, scaling down to 0 fails (#7948) Signed-off-by: Liang Deng <283304489@qq.com> --- pkg/controller/instanceset/utils.go | 2 +- pkg/controller/instanceset/utils_test.go | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/pkg/controller/instanceset/utils.go b/pkg/controller/instanceset/utils.go index 0b8c175346dd..c3d2419f938a 100644 --- a/pkg/controller/instanceset/utils.go +++ b/pkg/controller/instanceset/utils.go @@ -260,7 +260,7 @@ func GetPodNameSetFromInstanceSetCondition(its *workloads.InstanceSet, condition // if concurrency is nil, concurrency will be treated as 100%. func CalculateConcurrencyReplicas(concurrency *intstr.IntOrString, replicas int) (int, error) { if concurrency == nil { - return replicas, nil + return integer.IntMax(replicas, 1), nil } // 'roundUp=true' will ensure at least 1 pod is reserved if concurrency > "0%" and replicas > 0. diff --git a/pkg/controller/instanceset/utils_test.go b/pkg/controller/instanceset/utils_test.go index 9f35bbea7f8f..3cfc7cf4df89 100644 --- a/pkg/controller/instanceset/utils_test.go +++ b/pkg/controller/instanceset/utils_test.go @@ -335,6 +335,20 @@ var _ = Describe("utils test", func() { concurrencyReplicas, err = CalculateConcurrencyReplicas(concurrent, replicas) Expect(err).Should(BeNil()) Expect(concurrencyReplicas).Should(Equal(10)) + + By("concurrent is nil, replicas = 10") + replicas = 10 + concurrent = nil + concurrencyReplicas, err = CalculateConcurrencyReplicas(concurrent, replicas) + Expect(err).Should(BeNil()) + Expect(concurrencyReplicas).Should(Equal(10)) + + By("concurrent is nil, replicas = 0") + replicas = 0 + concurrent = nil + concurrencyReplicas, err = CalculateConcurrencyReplicas(concurrent, replicas) + Expect(err).Should(BeNil()) + Expect(concurrencyReplicas).Should(Equal(1)) }) }) })