diff --git a/.golangci.yaml b/.golangci.yaml index eaa07d81e..8b3099880 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -6,7 +6,7 @@ linters: - gocritic - gofmt - goimports - - gosimple + # - gosimple - govet - ineffassign - misspell @@ -16,7 +16,7 @@ linters: - sqlclosecheck - staticcheck - typecheck - - unused + # - unused issues: exclude-rules: @@ -35,6 +35,16 @@ linters-settings: revive: enable-all-rules: true rules: + - name: struct-tag + disabled: true + - name: var-naming + disabled: true + - name: comment-spacings + disabled: true + - name: exported + disabled: true + - name: unused-receiver + disabled: true - name: file-header disabled: true - name: line-length-limit diff --git a/PROJECT b/PROJECT index f6b0e1855..4a519005a 100644 --- a/PROJECT +++ b/PROJECT @@ -65,6 +65,10 @@ resources: kind: OBTenant path: github.com/oceanbase/ob-operator/api/v1alpha1 version: v1alpha1 + webhooks: + defaulting: true + validation: true + webhookVersion: v1 - api: crdVersion: v1 namespaced: true diff --git a/api/constants/restore.go b/api/constants/restore.go new file mode 100644 index 000000000..8aef68fa2 --- /dev/null +++ b/api/constants/restore.go @@ -0,0 +1,24 @@ +/* +Copyright (c) 2023 OceanBase +ob-operator is licensed under Mulan PSL v2. +You can use this software according to the terms and conditions of the Mulan PSL v2. +You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +See the Mulan PSL v2 for more details. +*/ + +package constants + +type RestoreJobStatus string + +const ( + RestoreJobStarting RestoreJobStatus = "STARTING" + RestoreJobRunning RestoreJobStatus = "RUNNING" + RestoreJobFailed RestoreJobStatus = "FAILED" + RestoreJobCanceling RestoreJobStatus = "CANCELING" + RestoreJobSuccessful RestoreJobStatus = "SUCCESSFUL" + RestoreJobCanceled RestoreJobStatus = "CANCELED" +) diff --git a/api/v1alpha1/obtenant_types.go b/api/v1alpha1/obtenant_types.go index 6584d0865..7fd24d01e 100644 --- a/api/v1alpha1/obtenant_types.go +++ b/api/v1alpha1/obtenant_types.go @@ -17,7 +17,6 @@ limitations under the License. package v1alpha1 import ( - corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -47,9 +46,14 @@ type OBTenantSpec struct { Pools []ResourcePoolSpec `json:"pools"` //+kubebuilder:default=PRIMARY - TenantRole constants.TenantRole `json:"tenantRole,omitempty"` - Source *TenantSourceSpec `json:"source,omitempty"` - Credentials []corev1.SecretReference `json:"credentials,omitempty"` + TenantRole constants.TenantRole `json:"tenantRole,omitempty"` + Source *TenantSourceSpec `json:"source,omitempty"` + Credentials TenantCredentials `json:"credentials,omitempty"` +} + +type TenantCredentials struct { + Root string `json:"root,omitempty"` + StandbyRO string `json:"standbyRo,omitempty"` } // Source for restoring or creating standby diff --git a/api/v1alpha1/obtenant_webhook.go b/api/v1alpha1/obtenant_webhook.go new file mode 100644 index 000000000..54baf92ab --- /dev/null +++ b/api/v1alpha1/obtenant_webhook.go @@ -0,0 +1,91 @@ +/* +Copyright 2023. + +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 ( + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation/field" + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + + "github.com/oceanbase/ob-operator/api/constants" +) + +// log is for logging in this package. +var _ = logf.Log.WithName("obtenant-resource") + +func (r *OBTenant) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +//+kubebuilder:webhook:path=/mutate-oceanbase-oceanbase-com-v1alpha1-obtenant,mutating=true,failurePolicy=fail,sideEffects=None,groups=oceanbase.oceanbase.com,resources=obtenants,verbs=create;update,versions=v1alpha1,name=mobtenant.kb.io,admissionReviewVersions=v1 + +var _ webhook.Defaulter = &OBTenant{} + +// Default implements webhook.Defaulter so a webhook will be registered for the type +func (r *OBTenant) Default() { + if r.Spec.TenantRole == "" { + r.Spec.TenantRole = constants.TenantRolePrimary + } +} + +// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +//+kubebuilder:webhook:path=/validate-oceanbase-oceanbase-com-v1alpha1-obtenant,mutating=false,failurePolicy=fail,sideEffects=None,groups=oceanbase.oceanbase.com,resources=obtenants,verbs=create;update,versions=v1alpha1,name=vobtenant.kb.io,admissionReviewVersions=v1 + +var _ webhook.Validator = &OBTenant{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *OBTenant) ValidateCreate() (admission.Warnings, error) { + // TODO(user): fill in your validation logic upon object creation. + return nil, r.validateMutation() +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *OBTenant) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { + _ = old + // TODO(user): fill in your validation logic upon object update. + return nil, r.validateMutation() +} + +func (r *OBTenant) validateMutation() error { + var allErrs field.ErrorList + + // 1. Standby tenant must have a source + if r.Spec.TenantRole == constants.TenantRoleStandby { + if r.Spec.Source == nil { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("source"), r.Spec.Source, "Standby tenant must have non-nil source field")) + } else if r.Spec.Source.Restore == nil && r.Spec.Source.Tenant == nil { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("tenantRole"), r.Spec.TenantRole, "Standby must have a source option, but both restore and tenantRef are nil now")) + } + } + + if len(allErrs) == 0 { + return nil + } + return apierrors.NewInvalid(GroupVersion.WithKind("OBTenant").GroupKind(), r.Name, allErrs) +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *OBTenant) ValidateDelete() (admission.Warnings, error) { + // TODO(user): fill in your validation logic upon object deletion. + return nil, nil +} diff --git a/api/v1alpha1/obtenantbackup_types.go b/api/v1alpha1/obtenantbackup_types.go index e25c7d05a..18a4a0deb 100644 --- a/api/v1alpha1/obtenantbackup_types.go +++ b/api/v1alpha1/obtenantbackup_types.go @@ -15,9 +15,10 @@ See the Mulan PSL v2 for more details. package v1alpha1 import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + constants "github.com/oceanbase/ob-operator/api/constants" "github.com/oceanbase/ob-operator/pkg/oceanbase/model" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! diff --git a/api/v1alpha1/obtenantbackuppolicy_types.go b/api/v1alpha1/obtenantbackuppolicy_types.go index 726e86d6e..97644e353 100644 --- a/api/v1alpha1/obtenantbackuppolicy_types.go +++ b/api/v1alpha1/obtenantbackuppolicy_types.go @@ -15,9 +15,10 @@ See the Mulan PSL v2 for more details. package v1alpha1 import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + constants "github.com/oceanbase/ob-operator/api/constants" "github.com/oceanbase/ob-operator/pkg/oceanbase/model" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! diff --git a/api/v1alpha1/obtenantbackuppolicy_webhook.go b/api/v1alpha1/obtenantbackuppolicy_webhook.go index 106be7d47..f7eddcdea 100644 --- a/api/v1alpha1/obtenantbackuppolicy_webhook.go +++ b/api/v1alpha1/obtenantbackuppolicy_webhook.go @@ -20,7 +20,6 @@ import ( "errors" "regexp" - "github.com/oceanbase/ob-operator/api/constants" "github.com/robfig/cron/v3" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" @@ -29,10 +28,12 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + + "github.com/oceanbase/ob-operator/api/constants" ) // log is for logging in this package. -var obtenantbackuppolicylog = logf.Log.WithName("obtenantbackuppolicy-resource") +var _ = logf.Log.WithName("obtenantbackuppolicy-resource") func (r *OBTenantBackupPolicy) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). @@ -76,6 +77,7 @@ func (r *OBTenantBackupPolicy) ValidateCreate() (admission.Warnings, error) { // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type func (r *OBTenantBackupPolicy) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { + _ = old return nil, r.validateBackupPolicy() } diff --git a/api/v1alpha1/obtenantoperation_types.go b/api/v1alpha1/obtenantoperation_types.go index 02d7c4444..ad1d17fea 100644 --- a/api/v1alpha1/obtenantoperation_types.go +++ b/api/v1alpha1/obtenantoperation_types.go @@ -17,7 +17,6 @@ limitations under the License. package v1alpha1 import ( - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/oceanbase/ob-operator/api/constants" @@ -47,8 +46,8 @@ type OBTenantOpFailoverSpec struct { } type OBTenantOpChangePwdSpec struct { - Tenant string `json:"tenant"` - SecretRef corev1.SecretReference `json:"secretRef"` + Tenant string `json:"tenant"` + SecretRef string `json:"secretRef"` } // OBTenantOperationStatus defines the observed state of OBTenantOperation diff --git a/api/v1alpha1/obtenantrestore_types.go b/api/v1alpha1/obtenantrestore_types.go index df3db43c6..fbdb1e771 100644 --- a/api/v1alpha1/obtenantrestore_types.go +++ b/api/v1alpha1/obtenantrestore_types.go @@ -13,9 +13,10 @@ See the Mulan PSL v2 for more details. package v1alpha1 import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/oceanbase/ob-operator/api/constants" "github.com/oceanbase/ob-operator/pkg/oceanbase/model" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! @@ -37,9 +38,9 @@ type OBTenantRestoreSpec struct { type OBTenantRestoreStatus struct { // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster // Important: Run "make" to regenerate code after modifying this file - Status RestoreJobStatus `json:"status"` - RestoreProgress *model.RestoreHistory `json:"restoreProgress,omitempty"` - OperationContext *OperationContext `json:"operationContext,omitempty"` + Status constants.RestoreJobStatus `json:"status"` + RestoreProgress *model.RestoreHistory `json:"restoreProgress,omitempty"` + OperationContext *OperationContext `json:"operationContext,omitempty"` } func (in *OBTenantRestoreStatus) DeepCopyInto(out *OBTenantRestoreStatus) { @@ -81,19 +82,3 @@ type OBTenantRestoreList struct { func init() { SchemeBuilder.Register(&OBTenantRestore{}, &OBTenantRestoreList{}) } - -type RestoreJobType string - -const ( - RestoreJobRestore RestoreJobType = "RESTORE" - RestoreJobActivate RestoreJobType = "ACTIVATE" -) - -type RestoreJobStatus string - -const ( - RestoreJobRunning RestoreJobStatus = "RUNNING" - RestoreJobFailed RestoreJobStatus = "FAILED" - RestoreJobSuccessful RestoreJobStatus = "SUCCESSFUL" - RestoreJobCanceled RestoreJobStatus = "CANCELED" -) diff --git a/api/v1alpha1/webhook_suite_test.go b/api/v1alpha1/webhook_suite_test.go index 0d2c5c5fe..662a15a8a 100644 --- a/api/v1alpha1/webhook_suite_test.go +++ b/api/v1alpha1/webhook_suite_test.go @@ -102,6 +102,9 @@ var _ = BeforeSuite(func() { err = (&OBTenantBackupPolicy{}).SetupWebhookWithManager(mgr) Expect(err).NotTo(HaveOccurred()) + err = (&OBTenant{}).SetupWebhookWithManager(mgr) + Expect(err).NotTo(HaveOccurred()) + //+kubebuilder:scaffold:webhook go func() { diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 835ece71b..d09d7886d 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -934,7 +934,6 @@ func (in *OBTenantList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OBTenantOpChangePwdSpec) DeepCopyInto(out *OBTenantOpChangePwdSpec) { *out = *in - out.SecretRef = in.SecretRef } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OBTenantOpChangePwdSpec. @@ -1176,11 +1175,7 @@ func (in *OBTenantSpec) DeepCopyInto(out *OBTenantSpec) { *out = new(TenantSourceSpec) (*in).DeepCopyInto(*out) } - if in.Credentials != nil { - in, out := &in.Credentials, &out.Credentials - *out = make([]v1.SecretReference, len(*in)) - copy(*out, *in) - } + out.Credentials = in.Credentials } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OBTenantSpec. @@ -1704,6 +1699,21 @@ func (in *StorageSpec) DeepCopy() *StorageSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TenantCredentials) DeepCopyInto(out *TenantCredentials) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TenantCredentials. +func (in *TenantCredentials) DeepCopy() *TenantCredentials { + if in == nil { + return nil + } + out := new(TenantCredentials) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TenantRecordInfo) DeepCopyInto(out *TenantRecordInfo) { *out = *in @@ -1744,6 +1754,16 @@ func (in *TenantSourceSpec) DeepCopy() *TenantSourceSpec { return out } +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TenantSourceStatus. +func (in *TenantSourceStatus) DeepCopy() *TenantSourceStatus { + if in == nil { + return nil + } + out := new(TenantSourceStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *UnitConfig) DeepCopyInto(out *UnitConfig) { *out = *in diff --git a/cmd/main.go b/cmd/main.go index b72d40015..69bfebc48 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -206,6 +206,10 @@ func main() { setupLog.Error(err, "unable to create controller", "controller", "OBTenantOperation") os.Exit(1) } + if err = (&v1alpha1.OBTenant{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "OBTenant") + os.Exit(1) + } //+kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { diff --git a/config/crd/bases/oceanbase.oceanbase.com_obtenantoperations.yaml b/config/crd/bases/oceanbase.oceanbase.com_obtenantoperations.yaml index af6becb86..0caf377cf 100644 --- a/config/crd/bases/oceanbase.oceanbase.com_obtenantoperations.yaml +++ b/config/crd/bases/oceanbase.oceanbase.com_obtenantoperations.yaml @@ -37,19 +37,7 @@ spec: changePwd: properties: secretRef: - description: SecretReference represents a Secret Reference. It - has enough information to retrieve secret in any namespace - properties: - name: - description: name is unique within a namespace to reference - a secret resource. - type: string - namespace: - description: namespace defines the space within which the - secret name must be unique. - type: string - type: object - x-kubernetes-map-type: atomic + type: string tenant: type: string required: diff --git a/config/crd/bases/oceanbase.oceanbase.com_obtenants.yaml b/config/crd/bases/oceanbase.oceanbase.com_obtenants.yaml index 9087bc50e..d5e0446a4 100644 --- a/config/crd/bases/oceanbase.oceanbase.com_obtenants.yaml +++ b/config/crd/bases/oceanbase.oceanbase.com_obtenants.yaml @@ -69,21 +69,12 @@ spec: default: '%' type: string credentials: - items: - description: SecretReference represents a Secret Reference. It has - enough information to retrieve secret in any namespace - properties: - name: - description: name is unique within a namespace to reference - a secret resource. - type: string - namespace: - description: namespace defines the space within which the secret - name must be unique. - type: string - type: object - x-kubernetes-map-type: atomic - type: array + properties: + root: + type: string + standbyRo: + type: string + type: object forceDelete: default: false type: boolean @@ -348,94 +339,143 @@ spec: source: properties: restore: - description: RestoreHistory is the history of restore job, matches - view CDB_OB_RESTORE_HISTORY + description: OBTenantRestoreStatus defines the observed state + of OBTenantRestore properties: - backup_cluster_name: - type: string - backup_cluster_version: - type: string - backup_dest: - type: string - backup_piece_list: - type: string - backup_set_list: - type: string - backup_tenant_id: - format: int64 - type: integer - backup_tenant_name: - type: string - description: - type: string - finish_bytes: - format: int64 - type: integer - finish_bytes_display: - type: string - finish_ls_count: - format: int64 - type: integer - finish_tablet_count: - format: int64 - type: integer - finish_timestamp: - type: string - job_id: - format: int64 - type: integer - ls_count: - format: int64 - type: integer - restore_option: - type: string - restore_scn: - format: int64 - type: integer - restore_scn_display: - type: string - restore_tenant_id: - format: int64 - type: integer - restore_tenant_name: - type: string - start_timestamp: - type: string + operationContext: + properties: + failureRule: + properties: + failureStatus: + type: string + failureStrategy: + type: string + required: + - failureStatus + - failureStrategy + type: object + idx: + type: integer + name: + type: string + targetStatus: + type: string + task: + type: string + taskId: + type: string + taskStatus: + type: string + tasks: + items: + type: string + type: array + required: + - idx + - name + - targetStatus + - task + - taskId + - taskStatus + - tasks + type: object + restoreProgress: + description: RestoreHistory is the history of restore job, + matches view CDB_OB_RESTORE_HISTORY + properties: + backup_cluster_name: + type: string + backup_cluster_version: + type: string + backup_dest: + type: string + backup_piece_list: + type: string + backup_set_list: + type: string + backup_tenant_id: + format: int64 + type: integer + backup_tenant_name: + type: string + description: + type: string + finish_bytes: + format: int64 + type: integer + finish_bytes_display: + type: string + finish_ls_count: + format: int64 + type: integer + finish_tablet_count: + format: int64 + type: integer + finish_timestamp: + type: string + job_id: + format: int64 + type: integer + ls_count: + format: int64 + type: integer + restore_option: + type: string + restore_scn: + format: int64 + type: integer + restore_scn_display: + type: string + restore_tenant_id: + format: int64 + type: integer + restore_tenant_name: + type: string + start_timestamp: + type: string + status: + type: string + tablet_count: + format: int64 + type: integer + tenant_id: + format: int64 + type: integer + total_bytes: + format: int64 + type: integer + total_bytes_display: + type: string + required: + - backup_cluster_name + - backup_cluster_version + - backup_dest + - backup_piece_list + - backup_set_list + - backup_tenant_id + - backup_tenant_name + - finish_ls_count + - finish_tablet_count + - finish_timestamp + - job_id + - ls_count + - restore_option + - restore_scn + - restore_scn_display + - restore_tenant_id + - restore_tenant_name + - start_timestamp + - status + - tablet_count + - tenant_id + type: object status: - type: string - tablet_count: - format: int64 - type: integer - tenant_id: - format: int64 - type: integer - total_bytes: - format: int64 - type: integer - total_bytes_display: + description: 'INSERT ADDITIONAL STATUS FIELD - define observed + state of cluster Important: Run "make" to regenerate code + after modifying this file' type: string required: - - backup_cluster_name - - backup_cluster_version - - backup_dest - - backup_piece_list - - backup_set_list - - backup_tenant_id - - backup_tenant_name - - finish_ls_count - - finish_tablet_count - - finish_timestamp - - job_id - - ls_count - - restore_option - - restore_scn - - restore_scn_display - - restore_tenant_id - - restore_tenant_name - - start_timestamp - status - - tablet_count - - tenant_id type: object tenant: type: string diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index ab19cedc4..097614999 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -4,6 +4,26 @@ kind: MutatingWebhookConfiguration metadata: name: mutating-webhook-configuration webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-oceanbase-oceanbase-com-v1alpha1-obtenant + failurePolicy: Fail + name: mobtenant.kb.io + rules: + - apiGroups: + - oceanbase.oceanbase.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - obtenants + sideEffects: None - admissionReviewVersions: - v1 clientConfig: @@ -30,6 +50,26 @@ kind: ValidatingWebhookConfiguration metadata: name: validating-webhook-configuration webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-oceanbase-oceanbase-com-v1alpha1-obtenant + failurePolicy: Fail + name: vobtenant.kb.io + rules: + - apiGroups: + - oceanbase.oceanbase.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - obtenants + sideEffects: None - admissionReviewVersions: - v1 clientConfig: diff --git a/pkg/controller/obcluster_controller_test.go b/pkg/controller/obcluster_controller_test.go index 31f84816d..1b32f6944 100644 --- a/pkg/controller/obcluster_controller_test.go +++ b/pkg/controller/obcluster_controller_test.go @@ -17,13 +17,14 @@ import ( "fmt" "time" - "github.com/oceanbase/ob-operator/api/v1alpha1" - clusterstatus "github.com/oceanbase/ob-operator/pkg/const/status/obcluster" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" kubeerrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" logf "sigs.k8s.io/controller-runtime/pkg/log" + + "github.com/oceanbase/ob-operator/api/v1alpha1" + clusterstatus "github.com/oceanbase/ob-operator/pkg/const/status/obcluster" ) const ( diff --git a/pkg/controller/obcluster_test_helper.go b/pkg/controller/obcluster_test_helper.go index cd14869b6..f7214ee1d 100644 --- a/pkg/controller/obcluster_test_helper.go +++ b/pkg/controller/obcluster_test_helper.go @@ -15,9 +15,10 @@ package controller import ( "fmt" - "github.com/oceanbase/ob-operator/api/v1alpha1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/oceanbase/ob-operator/api/v1alpha1" ) const ( @@ -64,7 +65,6 @@ func newOBCluster(name string, zoneNum int, serverNum int) *v1alpha1.OBCluster { Replica: serverNum, } topology[i] = zoneTopology - } userSecrets := &v1alpha1.OBUserSecrets{ diff --git a/pkg/controller/obclusterbackup_controller.go b/pkg/controller/obclusterbackup_controller.go index a3591a610..39a653d5e 100644 --- a/pkg/controller/obclusterbackup_controller.go +++ b/pkg/controller/obclusterbackup_controller.go @@ -52,6 +52,7 @@ type OBClusterBackupReconciler struct { // 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 *OBClusterBackupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + _ = req _ = log.FromContext(ctx) // TODO(user): your logic here diff --git a/pkg/controller/obclusterrestore_controller.go b/pkg/controller/obclusterrestore_controller.go index ca42d910e..432df30d5 100644 --- a/pkg/controller/obclusterrestore_controller.go +++ b/pkg/controller/obclusterrestore_controller.go @@ -49,6 +49,7 @@ type OBClusterRestoreReconciler struct { // 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 *OBClusterRestoreReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + _ = req _ = log.FromContext(ctx) // TODO(user): your logic here diff --git a/pkg/controller/obtenant_controller.go b/pkg/controller/obtenant_controller.go index c761ca4f5..c0cd6d93d 100644 --- a/pkg/controller/obtenant_controller.go +++ b/pkg/controller/obtenant_controller.go @@ -19,8 +19,6 @@ package controller import ( "context" - "github.com/oceanbase/ob-operator/pkg/resource" - "github.com/oceanbase/ob-operator/pkg/util/codec" kubeerrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/tools/record" @@ -28,6 +26,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" + "github.com/oceanbase/ob-operator/pkg/resource" + "github.com/oceanbase/ob-operator/pkg/util/codec" + v1alpha1 "github.com/oceanbase/ob-operator/api/v1alpha1" ) diff --git a/pkg/controller/obtenantbackup_controller.go b/pkg/controller/obtenantbackup_controller.go index 7e2391dc2..843fc659c 100644 --- a/pkg/controller/obtenantbackup_controller.go +++ b/pkg/controller/obtenantbackup_controller.go @@ -21,7 +21,6 @@ import ( "fmt" "time" - "github.com/oceanbase/ob-operator/pkg/resource" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/record" @@ -29,11 +28,14 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" + "github.com/oceanbase/ob-operator/pkg/resource" + + "github.com/pkg/errors" + "github.com/oceanbase/ob-operator/api/constants" v1alpha1 "github.com/oceanbase/ob-operator/api/v1alpha1" "github.com/oceanbase/ob-operator/pkg/oceanbase/model" "github.com/oceanbase/ob-operator/pkg/oceanbase/operation" - "github.com/pkg/errors" ) // OBTenantBackupReconciler reconciles a OBTenantBackup object @@ -141,12 +143,12 @@ func (r *OBTenantBackupReconciler) maintainRunningBackupJob(ctx context.Context, } // archive log and data clean job should not be here } else { - modelJob, err := con.GetBackupJobWithId(job.Status.BackupJob.JobId) + modelJob, err := con.GetBackupJobWithId(job.Status.BackupJob.JobID) if err != nil { return err } if modelJob == nil { - return errors.New(fmt.Sprintf("backup job with id %d not found", job.Status.BackupJob.JobId)) + return fmt.Errorf("backup job with id %d not found", job.Status.BackupJob.JobID) } job.Status.BackupJob = modelJob targetJob = modelJob diff --git a/pkg/controller/obtenantoperation_controller.go b/pkg/controller/obtenantoperation_controller.go index 7c782abbd..e3f1b6660 100644 --- a/pkg/controller/obtenantoperation_controller.go +++ b/pkg/controller/obtenantoperation_controller.go @@ -46,6 +46,7 @@ type OBTenantOperationReconciler struct { // For more details, check Reconcile and its Result here: // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.15.0/pkg/reconcile func (r *OBTenantOperationReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + _ = req _ = log.FromContext(ctx) // TODO(user): your logic here diff --git a/pkg/controller/obtenantrestore_controller.go b/pkg/controller/obtenantrestore_controller.go index b240a8d3f..1077742a9 100644 --- a/pkg/controller/obtenantrestore_controller.go +++ b/pkg/controller/obtenantrestore_controller.go @@ -47,6 +47,7 @@ type OBTenantRestoreReconciler struct { // 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 *OBTenantRestoreReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + _ = req _ = log.FromContext(ctx) // TODO(user): your logic here diff --git a/pkg/controller/obunit_controller.go b/pkg/controller/obunit_controller.go index 88524697f..200395a05 100644 --- a/pkg/controller/obunit_controller.go +++ b/pkg/controller/obunit_controller.go @@ -49,6 +49,7 @@ type OBUnitReconciler struct { // 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 *OBUnitReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + _ = req _ = log.FromContext(ctx) // TODO(user): your logic here diff --git a/pkg/controller/suite_test.go b/pkg/controller/suite_test.go index eaa211ffd..4acff34dd 100644 --- a/pkg/controller/suite_test.go +++ b/pkg/controller/suite_test.go @@ -24,7 +24,6 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/oceanbase/ob-operator/pkg/controller/config" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" ctrl "sigs.k8s.io/controller-runtime" @@ -33,6 +32,8 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" + "github.com/oceanbase/ob-operator/pkg/controller/config" + v1alpha1 "github.com/oceanbase/ob-operator/api/v1alpha1" //+kubebuilder:scaffold:imports ) diff --git a/pkg/oceanbase/connector/datasource.go b/pkg/oceanbase/connector/datasource.go index d2dbb9245..42c5eac16 100644 --- a/pkg/oceanbase/connector/datasource.go +++ b/pkg/oceanbase/connector/datasource.go @@ -65,25 +65,25 @@ func (ds *OceanBaseDataSource) GetDatabase() string { return ds.Database } -func (s *OceanBaseDataSource) DataSourceName() string { +func (ds *OceanBaseDataSource) DataSourceName() string { passwordPart := "" tenantPart := "" - if s.Password != "" { - passwordPart = fmt.Sprintf(":%s", s.Password) + if ds.Password != "" { + passwordPart = fmt.Sprintf(":%s", ds.Password) } - if !(s.Tenant == "" || s.Tenant == oceanbaseconst.SysTenant) { + if !(ds.Tenant == "" || ds.Tenant == oceanbaseconst.SysTenant) { // fix: bootstrap stage will fail if concat this part after v4.2.0 - tenantPart = fmt.Sprintf("@%s", s.Tenant) + tenantPart = fmt.Sprintf("@%s", ds.Tenant) } - if s.Database != "" { - return fmt.Sprintf("%s%s%s@tcp(%s:%d)/%s?multiStatements=true&interpolateParams=true", s.User, tenantPart, passwordPart, s.Address, s.Port, s.Database) + if ds.Database != "" { + return fmt.Sprintf("%s%s%s@tcp(%s:%d)/%s?multiStatements=true&interpolateParams=true", ds.User, tenantPart, passwordPart, ds.Address, ds.Port, ds.Database) } - return fmt.Sprintf("%s%s%s@tcp(%s:%d)/", s.User, tenantPart, passwordPart, s.Address, s.Port) + return fmt.Sprintf("%s%s%s@tcp(%s:%d)/", ds.User, tenantPart, passwordPart, ds.Address, ds.Port) } -func (s *OceanBaseDataSource) ID() string { +func (ds *OceanBaseDataSource) ID() string { h := md5.New() - key := fmt.Sprintf("%s@%s@%s:%d/%s", s.User, s.Tenant, s.Address, s.Port, s.Database) + key := fmt.Sprintf("%s@%s@%s:%d/%s", ds.User, ds.Tenant, ds.Address, ds.Port, ds.Database) _, err := h.Write([]byte(key)) if err != nil { return key @@ -91,6 +91,6 @@ func (s *OceanBaseDataSource) ID() string { return hex.EncodeToString(h.Sum(nil)) } -func (s *OceanBaseDataSource) String() string { - return fmt.Sprintf("address: %s, port: %d, user: %s, tenant: %s, database: %s", s.Address, s.Port, s.User, s.Tenant, s.Database) +func (ds *OceanBaseDataSource) String() string { + return fmt.Sprintf("address: %s, port: %d, user: %s, tenant: %s, database: %s", ds.Address, ds.Port, ds.User, ds.Tenant, ds.Database) } diff --git a/pkg/oceanbase/operation/backup.go b/pkg/oceanbase/operation/backup.go index 4707dfa20..9b618936a 100644 --- a/pkg/oceanbase/operation/backup.go +++ b/pkg/oceanbase/operation/backup.go @@ -13,10 +13,11 @@ See the Mulan PSL v2 for more details. package operation import ( + "github.com/pkg/errors" + "github.com/oceanbase/ob-operator/api/constants" "github.com/oceanbase/ob-operator/pkg/oceanbase/const/sql" "github.com/oceanbase/ob-operator/pkg/oceanbase/model" - "github.com/pkg/errors" ) func (m *OceanbaseOperationManager) SetLogArchiveDestForTenant(uri string) error { @@ -204,7 +205,7 @@ func (m *OceanbaseOperationManager) GetLatestBackupJobOfTypeAndPath(jobType cons return m.getLatestBackupJob([]string{sql.QueryLatestBackupJobOfTypeAndPath, sql.QueryLatestBackupJobHistoryOfTypeAndPath}, jobType, path) } -func (m *OceanbaseOperationManager) getLatestBackupJob(statements []string, params ...interface{}) (*model.OBBackupJob, error) { +func (m *OceanbaseOperationManager) getLatestBackupJob(statements []string, params ...any) (*model.OBBackupJob, error) { if len(statements) != 2 { return nil, errors.New("unexpected # of statements, require exactly 2 statement") } diff --git a/pkg/oceanbase/operation/cluster.go b/pkg/oceanbase/operation/cluster.go index d7a792982..378cf11ce 100644 --- a/pkg/oceanbase/operation/cluster.go +++ b/pkg/oceanbase/operation/cluster.go @@ -16,10 +16,11 @@ import ( "fmt" "strings" + "github.com/pkg/errors" + "github.com/oceanbase/ob-operator/pkg/oceanbase/const/config" "github.com/oceanbase/ob-operator/pkg/oceanbase/const/sql" "github.com/oceanbase/ob-operator/pkg/oceanbase/model" - "github.com/pkg/errors" ) // TODO @@ -54,9 +55,8 @@ func (m *OceanbaseOperationManager) GetVersion() (*model.OBVersion, error) { } if version != nil && version.Compare(v) != 0 { return nil, errors.Errorf("Version %s of observer %s:%d is not consistent with other observer", observer.BuildVersion, observer.Ip, observer.Port) - } else { - version = v } + version = v } return version, nil } diff --git a/pkg/oceanbase/operation/manager.go b/pkg/oceanbase/operation/manager.go index 42ec5c871..a1bb78458 100644 --- a/pkg/oceanbase/operation/manager.go +++ b/pkg/oceanbase/operation/manager.go @@ -18,10 +18,11 @@ import ( "time" "github.com/go-logr/logr" + "github.com/pkg/errors" + "github.com/oceanbase/ob-operator/pkg/database" "github.com/oceanbase/ob-operator/pkg/oceanbase/connector" "github.com/oceanbase/ob-operator/pkg/oceanbase/const/config" - "github.com/pkg/errors" ) type OceanbaseOperationManager struct { diff --git a/pkg/oceanbase/operation/parameter.go b/pkg/oceanbase/operation/parameter.go index d0f6b5f36..272731575 100644 --- a/pkg/oceanbase/operation/parameter.go +++ b/pkg/oceanbase/operation/parameter.go @@ -32,7 +32,7 @@ func (m *OceanbaseOperationManager) GetParameter(name string, scope *param.Scope return parameters, err } -func (m *OceanbaseOperationManager) SetParameter(name string, value interface{}, scope *param.Scope) error { +func (m *OceanbaseOperationManager) SetParameter(name string, value any, scope *param.Scope) error { if scope == nil { setParameterSql := fmt.Sprintf(sql.SetParameter, name) return m.ExecWithDefaultTimeout(setParameterSql, value) diff --git a/pkg/oceanbase/operation/restore.go b/pkg/oceanbase/operation/restore.go index 323f5f44b..de5a63907 100644 --- a/pkg/oceanbase/operation/restore.go +++ b/pkg/oceanbase/operation/restore.go @@ -16,9 +16,10 @@ import ( "fmt" "time" + "github.com/pkg/errors" + "github.com/oceanbase/ob-operator/pkg/oceanbase/const/sql" "github.com/oceanbase/ob-operator/pkg/oceanbase/model" - "github.com/pkg/errors" ) func (m *OceanbaseOperationManager) SetRestorePassword(password string) error { @@ -30,7 +31,7 @@ func (m *OceanbaseOperationManager) SetRestorePassword(password string) error { return nil } -func (m *OceanbaseOperationManager) StartRestoreWithLimit(tenantName, uri, limitKey, restoreOption string, limitValue interface{}) error { +func (m *OceanbaseOperationManager) StartRestoreWithLimit(tenantName, uri, limitKey, restoreOption string, limitValue any) error { sqlStatement := fmt.Sprintf(sql.StartRestoreWithLimit, tenantName, limitKey) err := m.ExecWithDefaultTimeout(sqlStatement, uri, limitValue, restoreOption) if err != nil { diff --git a/pkg/oceanbase/operation/server.go b/pkg/oceanbase/operation/server.go index ac1ef73a5..cf0feb74b 100644 --- a/pkg/oceanbase/operation/server.go +++ b/pkg/oceanbase/operation/server.go @@ -15,9 +15,10 @@ package operation import ( "fmt" + "github.com/pkg/errors" + "github.com/oceanbase/ob-operator/pkg/oceanbase/const/sql" "github.com/oceanbase/ob-operator/pkg/oceanbase/model" - "github.com/pkg/errors" ) func (m *OceanbaseOperationManager) GetServer(s *model.ServerInfo) (*model.OBServer, error) { diff --git a/pkg/oceanbase/operation/tenant.go b/pkg/oceanbase/operation/tenant.go index 5d5f0bb66..a97359a38 100644 --- a/pkg/oceanbase/operation/tenant.go +++ b/pkg/oceanbase/operation/tenant.go @@ -17,10 +17,11 @@ import ( "strings" "time" + "github.com/pkg/errors" + "github.com/oceanbase/ob-operator/pkg/oceanbase/const/config" "github.com/oceanbase/ob-operator/pkg/oceanbase/const/sql" "github.com/oceanbase/ob-operator/pkg/oceanbase/model" - "github.com/pkg/errors" ) // Incompatible with model.Tenant struct which contains only essential fields for tenant management @@ -205,7 +206,6 @@ func (m *OceanbaseOperationManager) CheckRsJobExistByTenantID(tenantName int) (b // ------------ add ------------ func (m *OceanbaseOperationManager) AddTenant(tenantSQLParam model.TenantSQLParam) error { - preparedSQL, params := preparedSQLForAddTenant(tenantSQLParam) err := m.ExecWithTimeout(config.TenantSqlTimeout, preparedSQL, params...) if err != nil { @@ -296,9 +296,9 @@ func (m *OceanbaseOperationManager) SetTenant(tenantSQLParam model.TenantSQLPara // ---------- replacer sql and collect params ---------- -func preparedSQLForAddUnitConfigV4(unitConfigV4 *model.UnitConfigV4SQLParam) (string, []interface{}) { +func preparedSQLForAddUnitConfigV4(unitConfigV4 *model.UnitConfigV4SQLParam) (string, []any) { var optionSql string - params := make([]interface{}, 0) + params := make([]any, 0) params = append(params, unitConfigV4.MaxCPU, unitConfigV4.MemorySize) if unitConfigV4.MinCPU != 0 { optionSql = fmt.Sprint(optionSql, ", min_cpu ?") @@ -323,16 +323,16 @@ func preparedSQLForAddUnitConfigV4(unitConfigV4 *model.UnitConfigV4SQLParam) (st return fmt.Sprintf(sql.AddUnitConfigV4, unitConfigV4.UnitConfigName, optionSql), params } -func preparedSQLForAddPool(poolSQLParam model.PoolSQLParam) (string, []interface{}) { - params := make([]interface{}, 0) +func preparedSQLForAddPool(poolSQLParam model.PoolSQLParam) (string, []any) { + params := make([]any, 0) params = append(params, poolSQLParam.UnitName, poolSQLParam.UnitNum, poolSQLParam.ZoneList) return fmt.Sprintf(sql.AddPool, poolSQLParam.PoolName), params } -func preparedSQLForAddTenant(tenantSQLParam model.TenantSQLParam) (string, []interface{}) { +func preparedSQLForAddTenant(tenantSQLParam model.TenantSQLParam) (string, []any) { var option string var variableList string - params := make([]interface{}, 0) + params := make([]any, 0) params = append(params, tenantSQLParam.Charset, tenantSQLParam.PrimaryZone) symbols := make([]string, 0) @@ -352,9 +352,9 @@ func preparedSQLForAddTenant(tenantSQLParam model.TenantSQLParam) (string, []int return fmt.Sprintf(sql.AddTenant, tenantSQLParam.TenantName, strings.Join(symbols, ", "), option, variableList), params } -func preparedSQLForSetTenant(tenantSQLParam model.TenantSQLParam) (string, []interface{}) { +func preparedSQLForSetTenant(tenantSQLParam model.TenantSQLParam) (string, []any) { var alterItemStr string - params := make([]interface{}, 0) + params := make([]any, 0) alterItemList := make([]string, 0) if tenantSQLParam.PrimaryZone != "" { alterItemList = append(alterItemList, "PRIMARY_ZONE=?") @@ -380,9 +380,9 @@ func preparedSQLForSetTenant(tenantSQLParam model.TenantSQLParam) (string, []int return fmt.Sprintf(sql.SetTenant, tenantSQLParam.TenantName, alterItemStr), params } -func preparedSQLForSetUnitConfigV4(unitConfigV4 *model.UnitConfigV4SQLParam) (string, []interface{}) { +func preparedSQLForSetUnitConfigV4(unitConfigV4 *model.UnitConfigV4SQLParam) (string, []any) { var alterItemStr string - params := make([]interface{}, 0) + params := make([]any, 0) alterItemList := make([]string, 0) if unitConfigV4.MaxCPU != 0 { alterItemList = append(alterItemList, "max_cpu=?") @@ -442,33 +442,31 @@ func (m *OceanbaseOperationManager) AlterPool(poolParam *model.PoolParam) error return nil } -func (m *OceanbaseOperationManager) preparedSQLForSetTenantVariable(tenantName, variableList string) (string, []interface{}) { - params := make([]interface{}, 0) +func (m *OceanbaseOperationManager) preparedSQLForSetTenantVariable(tenantName, variableList string) (string, []any) { + params := make([]any, 0) return fmt.Sprintf(sql.SetTenantVariable, tenantName, variableList), params } -func (m *OceanbaseOperationManager) preparedSQLForSetTenantUnitNum(tenantNum string, unitNum int) (string, []interface{}) { - params := make([]interface{}, 0) +func (m *OceanbaseOperationManager) preparedSQLForSetTenantUnitNum(tenantNum string, unitNum int) (string, []any) { + params := make([]any, 0) params = append(params, unitNum) return fmt.Sprintf(sql.SetTenantUnitNum, tenantNum), params - } -func (m *OceanbaseOperationManager) preparedSQLForDeleteTenant(tenantName string, force bool) (string, []interface{}) { - params := make([]interface{}, 0) +func (m *OceanbaseOperationManager) preparedSQLForDeleteTenant(tenantName string, force bool) (string, []any) { + params := make([]any, 0) if force { return fmt.Sprintf(sql.DeleteTenant, tenantName, "force"), params - } else { - return fmt.Sprintf(sql.DeleteTenant, tenantName, ""), params } + return fmt.Sprintf(sql.DeleteTenant, tenantName, ""), params } -func (m *OceanbaseOperationManager) preparedSQLForDeletePool(poolName string) (string, []interface{}) { - params := make([]interface{}, 0) +func (m *OceanbaseOperationManager) preparedSQLForDeletePool(poolName string) (string, []any) { + params := make([]any, 0) return fmt.Sprintf(sql.DeletePool, poolName), params } -func (m *OceanbaseOperationManager) preparedSQLForDeleteUnitConfig(unitConfigName string) (string, []interface{}) { - params := make([]interface{}, 0) +func (m *OceanbaseOperationManager) preparedSQLForDeleteUnitConfig(unitConfigName string) (string, []any) { + params := make([]any, 0) return fmt.Sprintf(sql.DeleteUnitConfig, unitConfigName), params } diff --git a/pkg/oceanbase/operation/user.go b/pkg/oceanbase/operation/user.go index 08fb45062..24df6d786 100644 --- a/pkg/oceanbase/operation/user.go +++ b/pkg/oceanbase/operation/user.go @@ -15,8 +15,9 @@ package operation import ( "fmt" - "github.com/oceanbase/ob-operator/pkg/oceanbase/const/sql" "github.com/pkg/errors" + + "github.com/oceanbase/ob-operator/pkg/oceanbase/const/sql" ) func (m *OceanbaseOperationManager) CreateUser(userName string) error { diff --git a/pkg/oceanbase/operation/zone.go b/pkg/oceanbase/operation/zone.go index 260057ca9..fcaafedd9 100644 --- a/pkg/oceanbase/operation/zone.go +++ b/pkg/oceanbase/operation/zone.go @@ -13,10 +13,11 @@ See the Mulan PSL v2 for more details. package operation import ( + "github.com/pkg/errors" + "github.com/oceanbase/ob-operator/pkg/oceanbase/const/sql" zonestatus "github.com/oceanbase/ob-operator/pkg/oceanbase/const/status/zone" "github.com/oceanbase/ob-operator/pkg/oceanbase/model" - "github.com/pkg/errors" ) func (m *OceanbaseOperationManager) AddZone(zoneName string) error { diff --git a/pkg/oceanbase/test/backup_test.go b/pkg/oceanbase/test/backup_test.go index 7238fccf9..b416affc7 100644 --- a/pkg/oceanbase/test/backup_test.go +++ b/pkg/oceanbase/test/backup_test.go @@ -17,11 +17,12 @@ import ( "time" "github.com/go-logr/logr" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/oceanbase/ob-operator/api/constants" "github.com/oceanbase/ob-operator/pkg/oceanbase/connector" "github.com/oceanbase/ob-operator/pkg/oceanbase/operation" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" ) var _ = Describe("Test Backup Operation", Label("backup"), func() { @@ -135,10 +136,10 @@ var _ = Describe("Test Backup Operation", Label("backup"), func() { // Query tasks at once will get empty result time.Sleep(time.Second) - By(fmt.Sprintf("Query BackupJob with ID %d", job.JobId)) - tasks, err := con.ListBackupTaskWithJobId(job.JobId) + By(fmt.Sprintf("Query BackupJob with ID %d", job.JobID)) + tasks, err := con.ListBackupTaskWithJobId(job.JobID) Expect(err).To(BeNil()) - printSlice(tasks, fmt.Sprintf("BackupTasks of Job %d", job.JobId)) + printSlice(tasks, fmt.Sprintf("BackupTasks of Job %d", job.JobID)) }) It("Get Log Archive dest info", func() { diff --git a/pkg/oceanbase/test/misc_test.go b/pkg/oceanbase/test/misc_test.go index 8c0e44dec..31231a635 100644 --- a/pkg/oceanbase/test/misc_test.go +++ b/pkg/oceanbase/test/misc_test.go @@ -18,12 +18,13 @@ import ( "strings" "time" - "github.com/oceanbase/ob-operator/api/constants" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/robfig/cron/v3" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" + + "github.com/oceanbase/ob-operator/api/constants" ) var _ = Describe("Test Miscellaneous Operation", func() { diff --git a/pkg/oceanbase/test/operation_suite_test.go b/pkg/oceanbase/test/operation_suite_test.go index 313b88c0c..6a5da4ce9 100644 --- a/pkg/oceanbase/test/operation_suite_test.go +++ b/pkg/oceanbase/test/operation_suite_test.go @@ -48,7 +48,7 @@ func TestOperation(t *testing.T) { RunSpecs(t, "Operation Suite") } -func printSlice[T any](s []T, extraMsg ...interface{}) { +func printSlice[T any](s []T, extraMsg ...any) { for _, msg := range extraMsg { GinkgoWriter.Println("[TEST INFO]", msg) } @@ -57,7 +57,7 @@ func printSlice[T any](s []T, extraMsg ...interface{}) { } } -func printObject[T any](o T, extraMsg ...interface{}) { +func printObject[T any](o T, extraMsg ...any) { for _, msg := range extraMsg { GinkgoWriter.Println("[TEST INFO]", msg) } diff --git a/pkg/oceanbase/test/system_test.go b/pkg/oceanbase/test/system_test.go index 6eff8a81e..d4f0b976e 100644 --- a/pkg/oceanbase/test/system_test.go +++ b/pkg/oceanbase/test/system_test.go @@ -16,10 +16,11 @@ import ( "fmt" "github.com/go-logr/logr" - "github.com/oceanbase/ob-operator/pkg/oceanbase/connector" - "github.com/oceanbase/ob-operator/pkg/oceanbase/operation" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + + "github.com/oceanbase/ob-operator/pkg/oceanbase/connector" + "github.com/oceanbase/ob-operator/pkg/oceanbase/operation" ) var _ = Describe("Test System Operation", func() { diff --git a/pkg/resource/const/condition/condition.go b/pkg/resource/const/condition/condition.go index ca26be1de..eda6bcf04 100644 --- a/pkg/resource/const/condition/condition.go +++ b/pkg/resource/const/condition/condition.go @@ -16,7 +16,7 @@ type Condition string const ( New Condition = "new" - Modified = "modified" - Operating = "operating" - Satisfied = "satisfied" + Modified Condition = "modified" + Operating Condition = "operating" + Satisfied Condition = "satisfied" ) diff --git a/pkg/resource/coordinator.go b/pkg/resource/coordinator.go index b81a23887..964f88338 100644 --- a/pkg/resource/coordinator.go +++ b/pkg/resource/coordinator.go @@ -105,16 +105,14 @@ func (c *Coordinator) executeTaskFlow(f *task.TaskFlow) { c.Logger.Error(err, "Get task result got error", "task id", f.OperationContext.TaskId) c.Manager.PrintErrEvent(err) f.OperationContext.TaskStatus = taskstatus.Failed - } else { - if taskResult != nil { - c.Logger.Info("Task finished", "task id", f.OperationContext.TaskId, "task result", taskResult) - f.OperationContext.TaskStatus = taskResult.Status - if taskResult.Error != nil { - c.Manager.PrintErrEvent(taskResult.Error) - } - } else { - // Didn't get task result, task is still running" + } else if taskResult != nil { + c.Logger.Info("Task finished", "task id", f.OperationContext.TaskId, "task result", taskResult) + f.OperationContext.TaskStatus = taskResult.Status + if taskResult.Error != nil { + c.Manager.PrintErrEvent(taskResult.Error) } + + // Didn't get task result, task is still running" } case taskstatus.Successful: // clean operation context and set status to target status diff --git a/pkg/resource/obcluster_task.go b/pkg/resource/obcluster_task.go index 4402d4923..be09dab9b 100644 --- a/pkg/resource/obcluster_task.go +++ b/pkg/resource/obcluster_task.go @@ -19,9 +19,6 @@ import ( "time" "github.com/google/uuid" - obagentconst "github.com/oceanbase/ob-operator/pkg/const/obagent" - oceanbaseconst "github.com/oceanbase/ob-operator/pkg/const/oceanbase" - zonestatus "github.com/oceanbase/ob-operator/pkg/const/status/obzone" "github.com/pkg/errors" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" @@ -29,6 +26,10 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" + obagentconst "github.com/oceanbase/ob-operator/pkg/const/obagent" + oceanbaseconst "github.com/oceanbase/ob-operator/pkg/const/oceanbase" + zonestatus "github.com/oceanbase/ob-operator/pkg/const/status/obzone" + v1alpha1 "github.com/oceanbase/ob-operator/api/v1alpha1" "github.com/oceanbase/ob-operator/pkg/oceanbase/model" "github.com/oceanbase/ob-operator/pkg/oceanbase/operation" @@ -53,7 +54,7 @@ func (m *OBClusterManager) generateZoneName(zone string) string { } func (m *OBClusterManager) generateParameterName(name string) string { - return fmt.Sprintf("%s-%d-%s", m.OBCluster.Spec.ClusterName, m.OBCluster.Spec.ClusterId, strings.Replace(name, "_", "-", -1)) + return fmt.Sprintf("%s-%d-%s", m.OBCluster.Spec.ClusterName, m.OBCluster.Spec.ClusterId, strings.ReplaceAll(name, "_", "-")) } func (m *OBClusterManager) WaitOBZoneTopologyMatch() error { @@ -92,9 +93,8 @@ func (m *OBClusterManager) WaitOBZoneDeleted() error { } if waitSuccess { return nil - } else { - return errors.Errorf("OBCluster %s zone still not deleted when timeout", m.OBCluster.Name) } + return errors.Errorf("OBCluster %s zone still not deleted when timeout", m.OBCluster.Name) } func (m *OBClusterManager) generateWaitOBZoneStatusFunc(status string, timeoutSeconds int) func() error { @@ -248,7 +248,7 @@ func (m *OBClusterManager) Bootstrap() error { return errors.Wrap(err, "list obzones") } m.Logger.Info("successfully get obzone list", "obzone list", obzoneList) - if len(obzoneList.Items) <= 0 { + if len(obzoneList.Items) == 0 { return errors.Wrap(err, "no obzone belongs to this cluster") } var manager *operation.OceanbaseOperationManager @@ -466,7 +466,7 @@ func (m *OBClusterManager) ValidateUpgradeInfo() error { if err != nil { return errors.Wrapf(err, "Failed to get operation manager of obcluster %s", m.OBCluster.Name) } - //version, err := oceanbaseOperationManager.GetVersion() + // version, err := oceanbaseOperationManager.GetVersion() version, err := oceanbaseOperationManager.GetVersion() if err != nil { return errors.Wrapf(err, "Failed to get version of obcluster %s", m.OBCluster.Name) @@ -812,6 +812,6 @@ func (m *OBClusterManager) RestoreEssentialParameters() error { return errors.Wrapf(err, "Failed to set parameter %s to %s:%d", parameter.Name, parameter.SvrIp, parameter.SvrPort) } } - m.Client.Delete(m.Ctx, contextSecret) + _ = m.Client.Delete(m.Ctx, contextSecret) return nil } diff --git a/pkg/resource/obparameter_manager.go b/pkg/resource/obparameter_manager.go index 1edb14386..b61465221 100644 --- a/pkg/resource/obparameter_manager.go +++ b/pkg/resource/obparameter_manager.go @@ -17,9 +17,6 @@ import ( "fmt" "github.com/go-logr/logr" - "github.com/oceanbase/ob-operator/pkg/oceanbase/operation" - taskstatus "github.com/oceanbase/ob-operator/pkg/task/const/task/status" - "github.com/oceanbase/ob-operator/pkg/task/strategy" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" @@ -27,6 +24,10 @@ import ( "k8s.io/client-go/util/retry" "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/oceanbase/ob-operator/pkg/oceanbase/operation" + taskstatus "github.com/oceanbase/ob-operator/pkg/task/const/task/status" + "github.com/oceanbase/ob-operator/pkg/task/strategy" + v1alpha1 "github.com/oceanbase/ob-operator/api/v1alpha1" oceanbaseconst "github.com/oceanbase/ob-operator/pkg/const/oceanbase" clusterstatus "github.com/oceanbase/ob-operator/pkg/const/status/obcluster" diff --git a/pkg/resource/observer_manager.go b/pkg/resource/observer_manager.go index 7c385d7d4..e3c22dd49 100644 --- a/pkg/resource/observer_manager.go +++ b/pkg/resource/observer_manager.go @@ -19,7 +19,6 @@ import ( taskstatus "github.com/oceanbase/ob-operator/pkg/task/const/task/status" "github.com/oceanbase/ob-operator/pkg/task/strategy" - oceanbaseconst "github.com/oceanbase/ob-operator/pkg/const/oceanbase" corev1 "k8s.io/api/core/v1" kubeerrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" @@ -28,6 +27,8 @@ import ( apipod "k8s.io/kubernetes/pkg/api/v1/pod" "sigs.k8s.io/controller-runtime/pkg/client" + oceanbaseconst "github.com/oceanbase/ob-operator/pkg/const/oceanbase" + "github.com/go-logr/logr" "github.com/pkg/errors" diff --git a/pkg/resource/observer_task.go b/pkg/resource/observer_task.go index d09b78590..222cf3c15 100644 --- a/pkg/resource/observer_task.go +++ b/pkg/resource/observer_task.go @@ -16,6 +16,11 @@ import ( "fmt" "time" + "github.com/pkg/errors" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + obagentconst "github.com/oceanbase/ob-operator/pkg/const/obagent" oceanbaseconst "github.com/oceanbase/ob-operator/pkg/const/oceanbase" podconst "github.com/oceanbase/ob-operator/pkg/const/pod" @@ -24,10 +29,6 @@ import ( observerstatus "github.com/oceanbase/ob-operator/pkg/oceanbase/const/status/server" "github.com/oceanbase/ob-operator/pkg/oceanbase/model" "github.com/oceanbase/ob-operator/pkg/oceanbase/operation" - "github.com/pkg/errors" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" "github.com/oceanbase/ob-operator/api/v1alpha1" ) @@ -141,6 +142,7 @@ func (m *OBServerManager) CreateOBPod() error { } func (m *OBServerManager) generatePVCSpec(name string, storageSpec *v1alpha1.StorageSpec) corev1.PersistentVolumeClaimSpec { + _ = name pvcSpec := &corev1.PersistentVolumeClaimSpec{} requestsResources := corev1.ResourceList{} requestsResources["storage"] = storageSpec.Size @@ -511,6 +513,9 @@ func (m *OBServerManager) DeleteOBServerInCluster() error { Port: oceanbaseconst.RpcPort, } observer, err := operationManager.GetServer(observerInfo) + if err != nil { + return err + } if observer != nil && observer.Status != "deleting" { if observer.Status == "deleting" { m.Logger.Info("observer is deleting", "observer", observerInfo.Ip) @@ -532,8 +537,7 @@ func (m *OBServerManager) AnnotateOBServerPod() error { if err != nil { return errors.Wrapf(err, "Failed to get pod of observer %s", m.OBServer.Name) } - switch m.OBServer.Status.CNI { - case oceanbaseconst.CNICalico: + if m.OBServer.Status.CNI == oceanbaseconst.CNICalico { m.Logger.Info("Update pod annotation, cni is calico") observerPod.Annotations[oceanbaseconst.AnnotationCalicoIpAddrs] = fmt.Sprintf("[\"%s\"]", m.OBServer.Status.PodIp) } @@ -616,9 +620,8 @@ func (m *OBServerManager) WaitOBServerActiveInCluster() error { if !active { m.Logger.Info("Wait observer active timeout") return errors.Errorf("Wait observer %s active timeout", observerInfo.Ip) - } else { - m.Logger.Info("observer active", "observer", observerInfo) } + m.Logger.Info("observer active", "observer", observerInfo) return nil } @@ -647,8 +650,7 @@ func (m *OBServerManager) WaitOBServerDeletedInCluster() error { if !deleted { m.Logger.Info("Wait observer deleted timeout") return errors.Errorf("Wait observer %s deleted timeout", observerInfo.Ip) - } else { - m.Logger.Info("observer deleted", "observer", observerInfo) } + m.Logger.Info("observer deleted", "observer", observerInfo) return nil } diff --git a/pkg/resource/obtenant_manager.go b/pkg/resource/obtenant_manager.go index b85d50218..c7af0a8c7 100644 --- a/pkg/resource/obtenant_manager.go +++ b/pkg/resource/obtenant_manager.go @@ -20,6 +20,15 @@ import ( "strings" "github.com/go-logr/logr" + "github.com/pkg/errors" + corev1 "k8s.io/api/core/v1" + kubeerrors "k8s.io/apimachinery/pkg/api/errors" + kuberesource "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/tools/record" + "k8s.io/client-go/util/retry" + "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/oceanbase/ob-operator/api/constants" "github.com/oceanbase/ob-operator/api/v1alpha1" "github.com/oceanbase/ob-operator/pkg/const/status/tenantstatus" @@ -31,14 +40,6 @@ import ( taskname "github.com/oceanbase/ob-operator/pkg/task/const/task/name" taskstatus "github.com/oceanbase/ob-operator/pkg/task/const/task/status" "github.com/oceanbase/ob-operator/pkg/task/strategy" - "github.com/pkg/errors" - corev1 "k8s.io/api/core/v1" - kubeerrors "k8s.io/apimachinery/pkg/api/errors" - kuberesource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/tools/record" - "k8s.io/client-go/util/retry" - "sigs.k8s.io/controller-runtime/pkg/client" ) type OBTenantManager struct { @@ -124,7 +125,7 @@ func (m *OBTenantManager) retryUpdateStatus() error { return client.IgnoreNotFound(err) } return retry.RetryOnConflict(retry.DefaultRetry, func() error { - obtenant.Status = *m.OBTenant.Status.DeepCopy() + m.OBTenant.Status.DeepCopyInto(&obtenant.Status) return m.Client.Status().Update(m.Ctx, obtenant) }) } @@ -398,8 +399,7 @@ func (m *OBTenantManager) hasModifiedUnitConfig() (bool, error) { m.Logger.Error(err, "maintain tenant failed, check and apply unitConfigV4", "tenantName", tenantName) return false, err } - switch string(version[0]) { - case tenant.Version4: + if string(version[0]) == tenant.Version4 { return m.hasModifiedUnitConfigV4(), nil } return false, errors.New("no match version for check and set unit config") @@ -492,7 +492,7 @@ func (m *OBTenantManager) buildTenantStatus() (*v1alpha1.OBTenantStatus, error) return nil, err } if !tenantExist { - return nil, errors.New(fmt.Sprintf("Tenant not exist, Tenant name: %s", tenantName)) + return nil, fmt.Errorf("Tenant not exist, Tenant name: %s", tenantName) } obtenant, err := m.getTenantByName(tenantName) if err != nil { @@ -543,7 +543,6 @@ func (m *OBTenantManager) buildTenantStatus() (*v1alpha1.OBTenantStatus, error) } func (m *OBTenantManager) buildPoolStatusList(obTenant *model.Tenant) ([]v1alpha1.ResourcePoolStatus, error) { - var poolStatusList []v1alpha1.ResourcePoolStatus var locality string var primaryZone string @@ -618,7 +617,7 @@ func (m *OBTenantManager) generateStatusZone(tenantID int64) ([]string, error) { zoneMap[unit.Zone] = unit.Zone } } - for k, _ := range zoneMap { + for k := range zoneMap { zoneList = append(zoneList, k) } return zoneList, nil diff --git a/pkg/resource/obtenant_task.go b/pkg/resource/obtenant_task.go index 91325ef89..f3bbd5d11 100644 --- a/pkg/resource/obtenant_task.go +++ b/pkg/resource/obtenant_task.go @@ -20,11 +20,12 @@ import ( "strings" "time" + "github.com/pkg/errors" + "github.com/oceanbase/ob-operator/api/v1alpha1" "github.com/oceanbase/ob-operator/pkg/oceanbase/const/config" "github.com/oceanbase/ob-operator/pkg/oceanbase/const/status/tenant" "github.com/oceanbase/ob-operator/pkg/oceanbase/model" - "github.com/pkg/errors" ) // ---------- task entry point ---------- @@ -162,8 +163,7 @@ func (m *OBTenantManager) MaintainUnitConfigTask() error { m.Logger.Error(err, "maintain tenant failed, check and apply unitConfigV4", "tenantName", tenantName) return err } - switch string(version[0]) { - case tenant.Version4: + if string(version[0]) == tenant.Version4 { return m.CheckAndApplyUnitConfigV4() } return errors.New("no match version for check and set unit config") @@ -464,8 +464,8 @@ func (m *OBTenantManager) tenantAddPool(poolAdd v1alpha1.ResourcePoolSpec) error Type: poolAdd.Type, UnitNumber: m.OBTenant.Spec.UnitNumber, } - - resourcePoolStatusList := append(m.OBTenant.Status.Pools, poolStatusAdd) + resourcePoolStatusList := m.OBTenant.Status.Pools + resourcePoolStatusList = append(resourcePoolStatusList, poolStatusAdd) statusLocalityMap := m.generateStatusLocalityMap(resourcePoolStatusList) localityList := m.generateLocalityList(statusLocalityMap) poolList := m.generateStatusPoolList(resourcePoolStatusList) @@ -501,7 +501,6 @@ func (m *OBTenantManager) tenantAddPool(poolAdd v1alpha1.ResourcePoolSpec) error } func (m *OBTenantManager) TenantDeletePool(poolDelete v1alpha1.ResourcePoolStatus) error { - tenantName := m.OBTenant.Spec.TenantName poolName := m.generatePoolName(poolDelete.ZoneList) unitName := m.generateUnitName(poolDelete.ZoneList) @@ -815,9 +814,8 @@ func (m *OBTenantManager) generateLocality(zones []v1alpha1.ResourcePoolSpec) st func (m *OBTenantManager) generateWhiteListInVariableForm(whiteList string) string { if whiteList == "" { return fmt.Sprintf("%s = '%s'", tenant.OBTcpInvitedNodes, tenant.DefaultOBTcpInvitedNodes) - } else { - return fmt.Sprintf("%s = '%s'", tenant.OBTcpInvitedNodes, whiteList) } + return fmt.Sprintf("%s = '%s'", tenant.OBTcpInvitedNodes, whiteList) } func (m *OBTenantManager) generateStatusTypeMapFromLocalityStr(locality string) map[string]v1alpha1.LocalityType { @@ -846,7 +844,7 @@ func (m *OBTenantManager) generateStatusPriorityMap(primaryZone string) map[stri for _, zone := range zoneList { priorityMap[zone] = priority } - priority -= 1 + priority-- } return priorityMap } diff --git a/pkg/resource/obtenantbackuppolicy_manager.go b/pkg/resource/obtenantbackuppolicy_manager.go index b608d3394..33312f06f 100644 --- a/pkg/resource/obtenantbackuppolicy_manager.go +++ b/pkg/resource/obtenantbackuppolicy_manager.go @@ -17,14 +17,6 @@ import ( "time" "github.com/go-logr/logr" - "github.com/oceanbase/ob-operator/api/constants" - v1alpha1 "github.com/oceanbase/ob-operator/api/v1alpha1" - "github.com/oceanbase/ob-operator/pkg/oceanbase/operation" - "github.com/oceanbase/ob-operator/pkg/task" - flow "github.com/oceanbase/ob-operator/pkg/task/const/flow/name" - taskname "github.com/oceanbase/ob-operator/pkg/task/const/task/name" - taskstatus "github.com/oceanbase/ob-operator/pkg/task/const/task/status" - "github.com/oceanbase/ob-operator/pkg/task/strategy" "github.com/pkg/errors" "github.com/robfig/cron/v3" corev1 "k8s.io/api/core/v1" @@ -33,6 +25,15 @@ import ( "k8s.io/client-go/util/retry" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + + "github.com/oceanbase/ob-operator/api/constants" + v1alpha1 "github.com/oceanbase/ob-operator/api/v1alpha1" + "github.com/oceanbase/ob-operator/pkg/oceanbase/operation" + "github.com/oceanbase/ob-operator/pkg/task" + flow "github.com/oceanbase/ob-operator/pkg/task/const/flow/name" + taskname "github.com/oceanbase/ob-operator/pkg/task/const/task/name" + taskstatus "github.com/oceanbase/ob-operator/pkg/task/const/task/status" + "github.com/oceanbase/ob-operator/pkg/task/strategy" ) type ObTenantBackupPolicyManager struct { @@ -99,7 +100,7 @@ func (m *ObTenantBackupPolicyManager) UpdateStatus() error { m.BackupPolicy.Status.Status = constants.BackupPolicyStatusResuming } else if m.BackupPolicy.Status.Status == constants.BackupPolicyStatusRunning { if m.BackupPolicy.Status.TenantInfo == nil { - tenant, err := m.getTenantInfo() + tenant, err := m.getTenantRecord() if err != nil { return err } @@ -131,6 +132,9 @@ func (m *ObTenantBackupPolicyManager) UpdateStatus() error { var lastFullBackupFinishedAt time.Time if latestFull.EndTimestamp != nil { lastFullBackupFinishedAt, err = time.ParseInLocation(time.DateTime, *latestFull.EndTimestamp, time.Local) + if err != nil { + return err + } } nextFull := fullCron.Next(lastFullBackupFinishedAt) m.BackupPolicy.Status.NextFull = nextFull.Format(time.DateTime) @@ -145,6 +149,9 @@ func (m *ObTenantBackupPolicyManager) UpdateStatus() error { var lastIncrBackupFinishedAt time.Time if latestIncr.EndTimestamp != nil { lastIncrBackupFinishedAt, err = time.ParseInLocation(time.DateTime, *latestIncr.EndTimestamp, time.Local) + if err != nil { + return err + } } m.BackupPolicy.Status.NextIncremental = incrCron.Next(lastIncrBackupFinishedAt).Format(time.DateTime) } diff --git a/pkg/resource/obtenantbackuppolicy_task.go b/pkg/resource/obtenantbackuppolicy_task.go index 44d857505..eaf68119c 100644 --- a/pkg/resource/obtenantbackuppolicy_task.go +++ b/pkg/resource/obtenantbackuppolicy_task.go @@ -19,11 +19,6 @@ import ( "strings" "time" - constants "github.com/oceanbase/ob-operator/api/constants" - "github.com/oceanbase/ob-operator/api/v1alpha1" - oceanbaseconst "github.com/oceanbase/ob-operator/pkg/const/oceanbase" - "github.com/oceanbase/ob-operator/pkg/oceanbase/model" - "github.com/oceanbase/ob-operator/pkg/oceanbase/operation" "github.com/pkg/errors" cron "github.com/robfig/cron/v3" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -31,6 +26,12 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" + + constants "github.com/oceanbase/ob-operator/api/constants" + "github.com/oceanbase/ob-operator/api/v1alpha1" + oceanbaseconst "github.com/oceanbase/ob-operator/pkg/const/oceanbase" + "github.com/oceanbase/ob-operator/pkg/oceanbase/model" + "github.com/oceanbase/ob-operator/pkg/oceanbase/operation" ) const backupVolumePath = oceanbaseconst.BackupPath @@ -41,7 +42,7 @@ func (m *ObTenantBackupPolicyManager) ConfigureServerForBackup() error { if err != nil { return err } - tenantInfo, err := m.getTenantInfo() + tenantInfo, err := m.getTenantRecord() if err != nil { return err } @@ -147,7 +148,7 @@ func (m *ObTenantBackupPolicyManager) ConfigureServerForBackup() error { func (m *ObTenantBackupPolicyManager) GetTenantInfo() error { // Admission Control - _, err := m.getTenantInfo() + _, err := m.getTenantRecord() if err != nil { return err } @@ -160,7 +161,7 @@ func (m *ObTenantBackupPolicyManager) StartBackup() error { if err != nil { return err } - tenantInfo, err := m.getTenantInfo() + tenantInfo, err := m.getTenantRecord() if err != nil { return err } @@ -287,6 +288,7 @@ func (m *ObTenantBackupPolicyManager) CheckAndSpawnJobs() error { } } else if latestIncr.Status == "INIT" || latestIncr.Status == "DOING" { // do nothing + _ = latestIncr } else { m.Logger.Info("Incremental BackupJob are in status " + latestIncr.Status) } @@ -301,6 +303,7 @@ func (m *ObTenantBackupPolicyManager) CheckAndSpawnJobs() error { } } else if latestFull.Status == "INIT" || latestFull.Status == "DOING" { // do nothing + _ = latestFull } else { m.Logger.Info("BackupJob are in status " + latestFull.Status) } @@ -330,6 +333,9 @@ func (m *ObTenantBackupPolicyManager) CleanOldBackupJobs() error { Selector: fieldSelector, }, client.InNamespace(m.BackupPolicy.Namespace)) + if err != nil { + return err + } if len(jobs.Items) == 0 { return nil } @@ -475,10 +481,8 @@ func (m *ObTenantBackupPolicyManager) getArchiveDestPath() string { dest = "file://" + path.Join(backupVolumePath, m.BackupPolicy.Spec.TenantName, targetDest.Path) } return dest - - } else { - return targetDest.Path } + return targetDest.Path } func (m *ObTenantBackupPolicyManager) getArchiveDestSettingValue() string { @@ -498,12 +502,10 @@ func (m *ObTenantBackupPolicyManager) getBackupDestPath() string { if targetDest.Type == constants.BackupDestTypeNFS || isZero(targetDest.Type) { if targetDest.Path == "" { return "file://" + path.Join(backupVolumePath, m.BackupPolicy.Spec.TenantName, "data_backup") - } else { - return "file://" + path.Join(backupVolumePath, m.BackupPolicy.Spec.TenantName, targetDest.Path) } - } else { - return targetDest.Path + return "file://" + path.Join(backupVolumePath, m.BackupPolicy.Spec.TenantName, targetDest.Path) } + return targetDest.Path } func (m *ObTenantBackupPolicyManager) createBackupJob(jobType constants.BackupJobType) error { @@ -589,8 +591,8 @@ func (m *ObTenantBackupPolicyManager) noRunningJobs(jobType constants.BackupJobT return true, nil } -// getTenantInfo return tenant info from status if exists, otherwise query from database view -func (m *ObTenantBackupPolicyManager) getTenantInfo() (*model.OBTenant, error) { +// getTenantRecord return tenant info from status if exists, otherwise query from database view +func (m *ObTenantBackupPolicyManager) getTenantRecord() (*model.OBTenant, error) { if m.BackupPolicy.Status.TenantInfo != nil { return m.BackupPolicy.Status.TenantInfo, nil } diff --git a/pkg/resource/obtenantrestore_manager.go b/pkg/resource/obtenantrestore_manager.go new file mode 100644 index 000000000..fa66e8202 --- /dev/null +++ b/pkg/resource/obtenantrestore_manager.go @@ -0,0 +1,139 @@ +/* +Copyright (c) 2023 OceanBase +ob-operator is licensed under Mulan PSL v2. +You can use this software according to the terms and conditions of the Mulan PSL v2. +You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +See the Mulan PSL v2 for more details. +*/ + +package resource + +import ( + "context" + + "github.com/go-logr/logr" + corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/tools/record" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/oceanbase/ob-operator/api/constants" + v1alpha1 "github.com/oceanbase/ob-operator/api/v1alpha1" + "github.com/oceanbase/ob-operator/pkg/oceanbase/operation" + "github.com/oceanbase/ob-operator/pkg/task" + flow "github.com/oceanbase/ob-operator/pkg/task/const/flow/name" + taskname "github.com/oceanbase/ob-operator/pkg/task/const/task/name" + "github.com/oceanbase/ob-operator/pkg/task/strategy" +) + +type ObTenantRestoreManager struct { + ResourceManager + + Ctx context.Context + Resource *v1alpha1.OBTenantRestore + Client client.Client + Recorder record.EventRecorder + Logger *logr.Logger + + con *operation.OceanbaseOperationManager +} + +func (m ObTenantRestoreManager) IsNewResource() bool { + return m.Resource.Status.Status == "" +} + +func (m ObTenantRestoreManager) IsDeleting() bool { + return m.Resource.GetDeletionTimestamp() != nil +} + +func (m ObTenantRestoreManager) CheckAndUpdateFinalizers() error { + return nil +} + +func (m ObTenantRestoreManager) InitStatus() { + m.Resource.Status.Status = constants.RestoreJobRunning +} + +func (m ObTenantRestoreManager) SetOperationContext(c *v1alpha1.OperationContext) { + m.Resource.Status.OperationContext = c +} + +func (m ObTenantRestoreManager) ClearTaskInfo() { + m.Resource.Status.Status = constants.RestoreJobRunning + m.Resource.Status.OperationContext = nil +} + +func (m ObTenantRestoreManager) FinishTask() { + m.Resource.Status.Status = constants.RestoreJobStatus(m.Resource.Status.OperationContext.TargetStatus) + m.Resource.Status.OperationContext = nil +} + +func (m ObTenantRestoreManager) HandleFailure() { + +} + +func (m ObTenantRestoreManager) UpdateStatus() error { + return m.Client.Status().Update(m.Ctx, m.Resource) +} + +func (m ObTenantRestoreManager) GetTaskFunc(name string) (func() error, error) { + switch name { + case taskname.StartRestoreJob: + return m.StartRestoreJobInOB, nil + case taskname.StartLogReplay: + return m.StartLogReplay, nil + case taskname.CancelRestoreJob: + return m.CancelRestoreJob, nil + case taskname.ActivateStandby: + return m.ActivateStandby, nil + case taskname.CheckRestoreProgress: + return m.CheckRestoreProgress, nil + } + return nil, nil +} + +func (m ObTenantRestoreManager) GetTaskFlow() (*task.TaskFlow, error) { + if m.Resource.Status.OperationContext != nil { + return task.NewTaskFlow(m.Resource.Status.OperationContext), nil + } + var taskFlow *task.TaskFlow + var err error + status := m.Resource.Status.Status + // get task flow depending on BackupPolicy status + switch status { + case constants.RestoreJobStarting: + taskFlow, err = task.GetRegistry().Get(flow.PrepareBackupPolicy) + case constants.RestoreJobRunning: + taskFlow, err = task.GetRegistry().Get(flow.PrepareBackupPolicy) + case constants.RestoreJobCanceling: + taskFlow, err = task.GetRegistry().Get(flow.PrepareBackupPolicy) + case constants.RestoreJobCanceled: + fallthrough + case constants.RestoreJobSuccessful: + fallthrough + case constants.RestoreJobFailed: + fallthrough + default: + return nil, nil + } + + if err != nil { + return nil, err + } + + if taskFlow.OperationContext.OnFailure.Strategy == "" { + taskFlow.OperationContext.OnFailure.Strategy = strategy.StartOver + if taskFlow.OperationContext.OnFailure.NextTryStatus == "" { + taskFlow.OperationContext.OnFailure.NextTryStatus = string(status) + } + } + + return taskFlow, nil +} + +func (m ObTenantRestoreManager) PrintErrEvent(err error) { + m.Recorder.Event(m.Resource, corev1.EventTypeWarning, "task exec failed", err.Error()) +} diff --git a/pkg/resource/obtenantrestore_task.go b/pkg/resource/obtenantrestore_task.go new file mode 100644 index 000000000..99e556673 --- /dev/null +++ b/pkg/resource/obtenantrestore_task.go @@ -0,0 +1,148 @@ +/* +Copyright (c) 2023 OceanBase +ob-operator is licensed under Mulan PSL v2. +You can use this software according to the terms and conditions of the Mulan PSL v2. +You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +See the Mulan PSL v2 for more details. +*/ + +package resource + +import ( + "time" + + "github.com/pkg/errors" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/oceanbase/ob-operator/api/constants" + "github.com/oceanbase/ob-operator/api/v1alpha1" + oceanbaseconst "github.com/oceanbase/ob-operator/pkg/const/oceanbase" + "github.com/oceanbase/ob-operator/pkg/oceanbase/operation" +) + +// Restore progress: +// 1. create unit (in tenant manager) +// 2. create resource pool (in tenant manager) +// 3. trigger restore job +// 4. wait for finishing +// 5. activate or replay log + +// OBTenantManager tasks completion + +func (m *OBTenantManager) CreateTenantRestoreJob() error { + var existingJobs v1alpha1.OBTenantRestoreList + var err error + + err = m.Client.List(m.Ctx, &existingJobs, + client.MatchingLabels{ + oceanbaseconst.LabelRefOBCluster: m.OBTenant.Spec.ClusterName, + oceanbaseconst.LabelTenantName: m.OBTenant.Spec.TenantName, + }, + client.InNamespace(m.OBTenant.Namespace)) + if err != nil { + return err + } + + if len(existingJobs.Items) != 0 { + return errors.New("There is already at least one restore job for this tenant") + } + + restoreJob := &v1alpha1.OBTenantRestore{ + ObjectMeta: metav1.ObjectMeta{ + Name: m.OBTenant.Spec.TenantName + "-restore", + Namespace: m.OBTenant.GetNamespace(), + OwnerReferences: []metav1.OwnerReference{{ + APIVersion: m.OBTenant.APIVersion, + Kind: m.OBTenant.Kind, + Name: m.OBTenant.Name, + UID: m.OBTenant.GetUID(), + BlockOwnerDeletion: getRef(true)}}, + Labels: map[string]string{ + oceanbaseconst.LabelRefOBCluster: m.OBTenant.Spec.ClusterName, + oceanbaseconst.LabelTenantName: m.OBTenant.Spec.TenantName, + oceanbaseconst.LabelRefUID: string(m.OBTenant.GetUID()), + }}, + Spec: v1alpha1.OBTenantRestoreSpec{ + TargetTenant: m.OBTenant.Spec.TenantName, + TargetCluster: m.OBTenant.Spec.ClusterName, + RestoreRole: m.OBTenant.Spec.TenantRole, + Source: *m.OBTenant.Spec.Source, + }, + } + err = m.Client.Create(m.Ctx, restoreJob) + if err != nil { + return err + } + return nil +} + +func (m *OBTenantManager) WatchRestoreJobToFinish() error { + var err error + for { + runningRestore := &v1alpha1.OBTenantRestore{} + err = m.Client.Get(m.Ctx, types.NamespacedName{ + Namespace: m.OBTenant.GetNamespace(), + Name: m.OBTenant.Spec.TenantName + "-restore", + }, runningRestore) + if err != nil { + return err + } + if runningRestore.Status.Status == constants.RestoreJobSuccessful { + break + } else if runningRestore.Status.Status == constants.RestoreJobFailed { + return errors.New("Restore job failed") + } + time.Sleep(5 * time.Second) + } + return nil +} + +// OBTenantRestore tasks + +func (m *ObTenantRestoreManager) StartRestoreJobInOB() error { + return nil +} + +func (m *ObTenantRestoreManager) CheckRestoreProgress() error { + return nil +} + +func (m *ObTenantRestoreManager) StartLogReplay() error { + return nil +} + +func (m *ObTenantRestoreManager) ActivateStandby() error { + return nil +} + +func (m *ObTenantRestoreManager) CancelRestoreJob() error { + return nil +} + +// get operation manager to exec sql +func (m *ObTenantRestoreManager) getOperationManager() (*operation.OceanbaseOperationManager, error) { + if m.con != nil { + return m.con, nil + } + obcluster := &v1alpha1.OBCluster{} + err := m.Client.Get(m.Ctx, types.NamespacedName{ + Namespace: m.Resource.Namespace, + Name: m.Resource.Spec.TargetCluster, + }, obcluster) + if err != nil { + return nil, errors.Wrap(err, "get obcluster") + } + con, err := GetOceanbaseOperationManagerFromOBCluster(m.Client, m.Logger, obcluster) + if err != nil { + return nil, errors.Wrap(err, "get oceanbase operation manager") + } + m.con = con + return con, nil +} diff --git a/pkg/resource/obzone_manager.go b/pkg/resource/obzone_manager.go index cb315947f..e13cede0e 100644 --- a/pkg/resource/obzone_manager.go +++ b/pkg/resource/obzone_manager.go @@ -108,9 +108,8 @@ func (m *OBZoneManager) GetTaskFlow() (*task.TaskFlow, error) { } if len(obcluster.Status.OBZoneStatus) >= 3 { return task.GetRegistry().Get(flowname.UpgradeOBZone) - } else { - return task.GetRegistry().Get(flowname.ForceUpgradeOBZone) } + return task.GetRegistry().Get(flowname.ForceUpgradeOBZone) // TODO upgrade default: m.Logger.Info("no need to run anything for obzone") @@ -190,7 +189,7 @@ func (m *OBZoneManager) UpdateStatus() error { Status: observer.Status.Status, }) if observer.Status.Status != serverstatus.Unrecoverable { - availableReplica = availableReplica + 1 + availableReplica++ } if observer.Status.Image != m.OBZone.Spec.OBServerTemplate.Image { m.Logger.Info("Found observer image not match") @@ -215,9 +214,9 @@ func (m *OBZoneManager) UpdateStatus() error { } else if m.OBZone.Spec.Topology.Replica < len(m.OBZone.Status.OBServerStatus) { m.Logger.Info("Compare topology need delete observer") m.OBZone.Status.Status = zonestatus.DeleteOBServer - } else { - // do nothing when observer match topology replica } + // do nothing when observer match topology replica + // TODO resource change require pod restart, and since oceanbase is a distributed system, resource can be scaled by add more servers if m.OBZone.Status.Status == zonestatus.Running { if m.OBZone.Status.Image != m.OBZone.Spec.OBServerTemplate.Image { diff --git a/pkg/resource/obzone_task.go b/pkg/resource/obzone_task.go index 980ae06f0..087b65e0e 100644 --- a/pkg/resource/obzone_task.go +++ b/pkg/resource/obzone_task.go @@ -18,11 +18,12 @@ import ( "time" "github.com/google/uuid" + "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + oceanbaseconst "github.com/oceanbase/ob-operator/pkg/const/oceanbase" serverstatus "github.com/oceanbase/ob-operator/pkg/const/status/observer" "github.com/oceanbase/ob-operator/pkg/oceanbase/operation" - "github.com/pkg/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1alpha1 "github.com/oceanbase/ob-operator/api/v1alpha1" ) @@ -99,7 +100,7 @@ func (m *OBZoneManager) CreateOBServer() error { currentReplica := 0 for _, observerStatus := range m.OBZone.Status.OBServerStatus { if observerStatus.Status != serverstatus.Unrecoverable { - currentReplica = currentReplica + 1 + currentReplica++ } } for i := currentReplica; i < m.OBZone.Spec.Topology.Replica; i++ { @@ -156,7 +157,7 @@ func (m *OBZoneManager) DeleteOBServer() error { } continue } - observerCount += 1 + observerCount++ } return nil } @@ -237,7 +238,7 @@ func (m *OBZoneManager) OBClusterHealthCheck() error { if err != nil { return errors.Wrap(err, "Get obcluster from K8s") } - ExecuteUpgradeScript(m.Client, m.Logger, obcluster, oceanbaseconst.UpgradeHealthCheckerScriptPath, "") + _ = ExecuteUpgradeScript(m.Client, m.Logger, obcluster, oceanbaseconst.UpgradeHealthCheckerScriptPath, "") return nil } @@ -247,7 +248,7 @@ func (m *OBZoneManager) OBZoneHealthCheck() error { return errors.Wrap(err, "Get obcluster from K8s") } zoneOpt := fmt.Sprintf("-z '%s'", m.OBZone.Spec.Topology.Zone) - ExecuteUpgradeScript(m.Client, m.Logger, obcluster, oceanbaseconst.UpgradeHealthCheckerScriptPath, zoneOpt) + _ = ExecuteUpgradeScript(m.Client, m.Logger, obcluster, oceanbaseconst.UpgradeHealthCheckerScriptPath, zoneOpt) return nil } diff --git a/pkg/resource/template_manager.go b/pkg/resource/template_manager.go new file mode 100644 index 000000000..bf58be220 --- /dev/null +++ b/pkg/resource/template_manager.go @@ -0,0 +1,84 @@ +/* +Copyright (c) 2023 OceanBase +ob-operator is licensed under Mulan PSL v2. +You can use this software according to the terms and conditions of the Mulan PSL v2. +You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +See the Mulan PSL v2 for more details. +*/ + +package resource + +import ( + "context" + + "github.com/go-logr/logr" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/tools/record" + "sigs.k8s.io/controller-runtime/pkg/client" + + v1alpha1 "github.com/oceanbase/ob-operator/api/v1alpha1" + "github.com/oceanbase/ob-operator/pkg/oceanbase/operation" + "github.com/oceanbase/ob-operator/pkg/task" +) + +type Resource interface { + client.Object + runtime.Object +} + +type ObResourceManager[T Resource] struct { + ResourceManager + + Ctx context.Context + Resource T + Client client.Client + Recorder record.EventRecorder + Logger *logr.Logger + + con *operation.OceanbaseOperationManager +} + +func (m *ObResourceManager[T]) IsNewResource() bool { + return false +} + +func (m *ObResourceManager[T]) IsDeleting() bool { + return false +} + +func (m *ObResourceManager[T]) CheckAndUpdateFinalizers() error { + return nil +} + +func (m *ObResourceManager[T]) InitStatus() {} + +func (m *ObResourceManager[T]) SetOperationContext(*v1alpha1.OperationContext) { + +} + +func (m *ObResourceManager[T]) ClearTaskInfo() {} + +func (m *ObResourceManager[T]) HandleFailure() {} + +func (m *ObResourceManager[T]) FinishTask() {} + +func (m *ObResourceManager[T]) UpdateStatus() error { + return m.Client.Status().Update(m.Ctx, m.Resource) +} + +func (m *ObResourceManager[T]) GetTaskFunc(string) (func() error, error) { + return nil, nil +} + +func (m *ObResourceManager[T]) GetTaskFlow() (*task.TaskFlow, error) { + return nil, nil +} + +func (m *ObResourceManager[T]) PrintErrEvent(err error) { + m.Recorder.Event(m.Resource, corev1.EventTypeWarning, "task exec failed", err.Error()) +} diff --git a/pkg/resource/util.go b/pkg/resource/util.go index 22a8fd9ef..fc4b90736 100644 --- a/pkg/resource/util.go +++ b/pkg/resource/util.go @@ -20,6 +20,13 @@ import ( "github.com/go-logr/logr" "github.com/google/uuid" + "github.com/pkg/errors" + batchv1 "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/oceanbase/ob-operator/api/v1alpha1" oceanbaseconst "github.com/oceanbase/ob-operator/pkg/const/oceanbase" secretconst "github.com/oceanbase/ob-operator/pkg/const/secret" @@ -27,12 +34,6 @@ import ( "github.com/oceanbase/ob-operator/pkg/oceanbase/connector" "github.com/oceanbase/ob-operator/pkg/oceanbase/model" "github.com/oceanbase/ob-operator/pkg/oceanbase/operation" - "github.com/pkg/errors" - batchv1 "k8s.io/api/batch/v1" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" ) func ReadPassword(c client.Client, namespace, secretName string) (string, error) { @@ -63,7 +64,7 @@ func getOperationClient(c client.Client, logger *logr.Logger, obcluster *v1alpha if err != nil { return nil, errors.Wrap(err, "Get observer list") } - if len(observerList.Items) <= 0 { + if len(observerList.Items) == 0 { return nil, errors.Errorf("No observer belongs to cluster %s", obcluster.Name) } @@ -127,7 +128,7 @@ func ExecuteUpgradeScript(c client.Client, logger *logr.Logger, obcluster *v1alp parts := strings.Split(uuid.New().String(), "-") suffix := parts[len(parts)-1] jobName := fmt.Sprintf("%s-%s", "script-runner", suffix) - var backoffLimit int32 = 0 + var backoffLimit int32 var ttl int32 = 300 container := corev1.Container{ Name: "script-runner", diff --git a/pkg/task/const/flow/name/task_flow_names.go b/pkg/task/const/flow/name/task_flow_names.go index 0f8baea23..408b8fea4 100644 --- a/pkg/task/const/flow/name/task_flow_names.go +++ b/pkg/task/const/flow/name/task_flow_names.go @@ -81,4 +81,15 @@ const ( MaintainUnitConfig = "maintain unit config" DeleteTenant = "delete tenant" + + // tenant restore + RestoreTenant = "Restore tenant" +) + +// tenant-level restore +const ( + StartRestoreFlow = "start restore" + RestoreAsStandbyFlow = "restore as standby" + RestoreAsPrimaryFlow = "restore as primary" + CancelRestoreFlow = "cancel restore" ) diff --git a/pkg/task/const/task/name/backup.go b/pkg/task/const/task/name/backup.go index 510053c54..77237d819 100644 --- a/pkg/task/const/task/name/backup.go +++ b/pkg/task/const/task/name/backup.go @@ -22,10 +22,3 @@ const ( PauseBackup = "pause backup" ResumeBackup = "resume backup" ) - -const ( - StartRestoreJob = "start restore job" - StartLogReplay = "start log replay" - CancelRestoreJob = "cancel restore job" - ActivateStandby = "activate standby" -) diff --git a/pkg/task/const/task/name/restore.go b/pkg/task/const/task/name/restore.go new file mode 100644 index 000000000..7c9ef3507 --- /dev/null +++ b/pkg/task/const/task/name/restore.go @@ -0,0 +1,21 @@ +/* +Copyright (c) 2023 OceanBase +ob-operator is licensed under Mulan PSL v2. +You can use this software according to the terms and conditions of the Mulan PSL v2. +You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +See the Mulan PSL v2 for more details. +*/ + +package name + +const ( + StartRestoreJob = "start restore job" + StartLogReplay = "start log replay" + CancelRestoreJob = "cancel restore job" + ActivateStandby = "activate standby" + CheckRestoreProgress = "check restore progress" +) diff --git a/pkg/task/const/task/name/task_names.go b/pkg/task/const/task/name/task_names.go index 1aa6a3755..3e0ded213 100644 --- a/pkg/task/const/task/name/task_names.go +++ b/pkg/task/const/task/name/task_names.go @@ -83,7 +83,7 @@ const ( CheckPoolAndUnitConfig = "create pool and unit config check" CreateTenant = "create tenant" CreateResourcePoolAndUnitConfig = "create resource pool and unit config" - //AddFinalizer = "add finalizer" + // AddFinalizer = "add finalizer" // maintain tenant MaintainWhiteList = "maintain white list" @@ -100,4 +100,8 @@ const ( MaintainUnitConfig = "maintain unit config" DeleteTenant = "delete tenant" + + // tenant restore + CreateRestoreJob = "create restore job" + WatchRestoreJobToFinish = "watch restore job to finish" ) diff --git a/pkg/task/obtenant_flow.go b/pkg/task/obtenant_flow.go index fdc791029..f03d1f7f9 100644 --- a/pkg/task/obtenant_flow.go +++ b/pkg/task/obtenant_flow.go @@ -126,3 +126,22 @@ func DeleteTenant() *TaskFlow { }, } } + +func RestoreTenant() *TaskFlow { + return &TaskFlow{ + OperationContext: &v1alpha1.OperationContext{ + Name: flowname.RestoreTenant, + Tasks: []string{ + taskname.CheckTenant, + taskname.CheckPoolAndUnitConfig, + taskname.CreateResourcePoolAndUnitConfig, + taskname.CreateRestoreJob, + taskname.WatchRestoreJobToFinish, + }, + TargetStatus: tenantstatus.Running, + OnFailure: strategy.FailureRule{ + NextTryStatus: tenantstatus.Restoring, + }, + }, + } +} diff --git a/pkg/task/task_flow.go b/pkg/task/task_flow.go index 54b3cc6ae..19a1f8468 100644 --- a/pkg/task/task_flow.go +++ b/pkg/task/task_flow.go @@ -33,7 +33,7 @@ func (f *TaskFlow) NextTask() string { } else { f.OperationContext.TaskStatus = taskstatus.Pending f.OperationContext.Task = f.OperationContext.Tasks[f.OperationContext.Idx] - f.OperationContext.Idx = f.OperationContext.Idx + 1 + f.OperationContext.Idx++ f.OperationContext.TaskId = "" } return f.OperationContext.Task diff --git a/pkg/task/task_manager.go b/pkg/task/task_manager.go index e4350b159..cc690fe18 100644 --- a/pkg/task/task_manager.go +++ b/pkg/task/task_manager.go @@ -19,9 +19,10 @@ import ( "github.com/go-logr/logr" "github.com/google/uuid" - taskstatus "github.com/oceanbase/ob-operator/pkg/task/const/task/status" "github.com/pkg/errors" "sigs.k8s.io/controller-runtime/pkg/log" + + taskstatus "github.com/oceanbase/ob-operator/pkg/task/const/task/status" ) var taskManager *TaskManager @@ -52,10 +53,10 @@ type TaskManager struct { func (m *TaskManager) Submit(f func() error) string { retCh := make(chan *TaskResult, 1) - TaskId := uuid.New().String() + taskId := uuid.New().String() // TODO add lock to keep ResultMap safe - m.ResultMap[TaskId] = retCh - m.TaskResultCache[TaskId] = nil + m.ResultMap[taskId] = retCh + m.TaskResultCache[taskId] = nil go func() { defer func() { if r := recover(); r != nil { @@ -67,7 +68,7 @@ func (m *TaskManager) Submit(f func() error) string { }() err := f() if err != nil { - m.Logger.Error(err, "Run task got error", "taskId", TaskId) + m.Logger.Error(err, "Run task got error", "taskId", taskId) retCh <- &TaskResult{ Status: taskstatus.Failed, Error: err, @@ -78,7 +79,7 @@ func (m *TaskManager) Submit(f func() error) string { Error: nil, } }() - return TaskId + return taskId } func (m *TaskManager) GetTaskResult(taskId string) (*TaskResult, error) { diff --git a/pkg/util/codec/json.go b/pkg/util/codec/json.go index c6b64dbde..f05393653 100644 --- a/pkg/util/codec/json.go +++ b/pkg/util/codec/json.go @@ -16,13 +16,13 @@ import ( "encoding/json" ) -func EncodeToJSON(element interface{}) string { +func EncodeToJSON(element any) string { tempJSON, _ := json.Marshal(element) return string(tempJSON) } -func ParseFromJSON(content string) (map[string]interface{}, error) { - ret := make(map[string]interface{}) +func ParseFromJSON(content string) (map[string]any, error) { + ret := make(map[string]any) err := json.Unmarshal([]byte(content), &ret) return ret, err }