Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: standby tenant #81

Merged
merged 15 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 4 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -210,15 +210,9 @@ commit-hook: $(GOLANGCI_LINT) ## Install commit hook.
.PHONY: connect
connect:
ifdef TENANT
mysql -h$(shell kubectl get pods -o jsonpath='{.items[0].status.podIP}') -P2881 -A -uroot@${TENANT}
$(eval nodeHost = $(shell kubectl get pods -o jsonpath='{.items[1].status.podIP}'))
$(eval pwd = $(shell kubectl get secret $(shell kubectl get obtenant ${TENANT} -o jsonpath='{.status.credentials.root}') -o jsonpath='{.data.password}' | base64 -d))
$(if $(strip $(pwd)), mysql -h$(nodeHost) -P2881 -A -uroot@${TENANT} -p$(pwd) -Doceanbase, mysql -h$(nodeHost) -P2881 -A -uroot@${TENANT} -Doceanbase)
else
mysql -h$(shell kubectl get pods -o jsonpath='{.items[0].status.podIP}') -P2881 -A -uroot -p
endif

.PHONY: connectob
connectob:
ifdef TENANT
mysql -h$(shell kubectl get pods -o jsonpath='{.items[0].status.podIP}') -P2881 -A -uroot@${TENANT} -Doceanbase
else
mysql -h$(shell kubectl get pods -o jsonpath='{.items[0].status.podIP}') -P2881 -A -uroot -p -Doceanbase
mysql -h$(shell kubectl get pods -o jsonpath='{.items[1].status.podIP}') -P2881 -A -uroot -p -Doceanbase
endif
4 changes: 4 additions & 0 deletions PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,8 @@ resources:
kind: OBTenantOperation
path: github.com/oceanbase/ob-operator/api/v1alpha1
version: v1alpha1
webhooks:
defaulting: true
validation: true
webhookVersion: v1
version: "3"
67 changes: 26 additions & 41 deletions api/constants/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,62 +12,47 @@ See the Mulan PSL v2 for more details.

package constants

type BackupJobType string
import "github.com/oceanbase/ob-operator/api/types"

const (
BackupJobTypeFull BackupJobType = "FULL"
BackupJobTypeIncr BackupJobType = "INC"
BackupJobTypeClean BackupJobType = "CLEAN"
BackupJobTypeArchive BackupJobType = "ARCHIVE"
BackupJobTypeFull types.BackupJobType = "FULL"
BackupJobTypeIncr types.BackupJobType = "INC"
BackupJobTypeClean types.BackupJobType = "CLEAN"
BackupJobTypeArchive types.BackupJobType = "ARCHIVE"
)

type BackupJobStatus string

const (
BackupJobStatusRunning BackupJobStatus = "RUNNING"
BackupJobStatusInitializing BackupJobStatus = "INITIALIZING"
BackupJobStatusSuccessful BackupJobStatus = "SUCCESSFUL"
BackupJobStatusFailed BackupJobStatus = "FAILED"
BackupJobStatusCanceled BackupJobStatus = "CANCELED"
BackupJobStatusStopped BackupJobStatus = "STOPPED"
BackupJobStatusSuspend BackupJobStatus = "SUSPEND"
BackupJobStatusRunning types.BackupJobStatus = "RUNNING"
BackupJobStatusInitializing types.BackupJobStatus = "INITIALIZING"
BackupJobStatusSuccessful types.BackupJobStatus = "SUCCESSFUL"
BackupJobStatusFailed types.BackupJobStatus = "FAILED"
BackupJobStatusCanceled types.BackupJobStatus = "CANCELED"
BackupJobStatusStopped types.BackupJobStatus = "STOPPED"
BackupJobStatusSuspend types.BackupJobStatus = "SUSPEND"
)

type BackupPolicyStatusType string

const (
BackupPolicyStatusPreparing BackupPolicyStatusType = "PREPARING"
BackupPolicyStatusPrepared BackupPolicyStatusType = "PREPARED"
BackupPolicyStatusRunning BackupPolicyStatusType = "RUNNING"
BackupPolicyStatusFailed BackupPolicyStatusType = "FAILED"
BackupPolicyStatusPausing BackupPolicyStatusType = "PAUSING"
BackupPolicyStatusPaused BackupPolicyStatusType = "PAUSED"
BackupPolicyStatusStopped BackupPolicyStatusType = "STOPPED"
BackupPolicyStatusResuming BackupPolicyStatusType = "RESUMING"
BackupPolicyStatusPreparing types.BackupPolicyStatusType = "PREPARING"
BackupPolicyStatusPrepared types.BackupPolicyStatusType = "PREPARED"
BackupPolicyStatusRunning types.BackupPolicyStatusType = "RUNNING"
BackupPolicyStatusFailed types.BackupPolicyStatusType = "FAILED"
BackupPolicyStatusPausing types.BackupPolicyStatusType = "PAUSING"
BackupPolicyStatusPaused types.BackupPolicyStatusType = "PAUSED"
BackupPolicyStatusStopped types.BackupPolicyStatusType = "STOPPED"
BackupPolicyStatusResuming types.BackupPolicyStatusType = "RESUMING"
)

type BackupDestination struct {
Type BackupDestType `json:"type,omitempty"`
Path string `json:"path,omitempty"`
}

type BackupDestType string

const (
BackupDestTypeOSS BackupDestType = "OSS"
BackupDestTypeNFS BackupDestType = "NFS"
BackupDestTypeOSS types.BackupDestType = "OSS"
BackupDestTypeNFS types.BackupDestType = "NFS"
)

type LogArchiveDestState string

const (
LogArchiveDestStateEnable LogArchiveDestState = "ENABLE"
LogArchiveDestStateDefer LogArchiveDestState = "DEFER"
LogArchiveDestStateEnable types.LogArchiveDestState = "ENABLE"
LogArchiveDestStateDefer types.LogArchiveDestState = "DEFER"
)

type ArchiveBinding string

const (
ArchiveBindingOptional = "Optional"
ArchiveBindingMandatory = "Mandatory"
ArchiveBindingOptional types.ArchiveBinding = "Optional"
ArchiveBindingMandatory types.ArchiveBinding = "Mandatory"
)
16 changes: 8 additions & 8 deletions api/constants/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ See the Mulan PSL v2 for more details.

package constants

type RestoreJobStatus string
import "github.com/oceanbase/ob-operator/api/types"

const (
RestoreJobStarting RestoreJobStatus = "STARTING"
RestoreJobRunning RestoreJobStatus = "RUNNING"
RestoreJobFailed RestoreJobStatus = "FAILED"
RestoreJobSuccessful RestoreJobStatus = "SUCCESSFUL"
RestoreJobCanceled RestoreJobStatus = "CANCELED"
RestoreJobStarting types.RestoreJobStatus = "STARTING"
RestoreJobRunning types.RestoreJobStatus = "RUNNING"
RestoreJobFailed types.RestoreJobStatus = "FAILED"
RestoreJobSuccessful types.RestoreJobStatus = "SUCCESSFUL"
RestoreJobCanceled types.RestoreJobStatus = "CANCELED"

RestoreJobStatusActivating RestoreJobStatus = "ACTIVATING"
RestoreJobStatusReplaying RestoreJobStatus = "REPLAYING"
RestoreJobStatusActivating types.RestoreJobStatus = "ACTIVATING"
RestoreJobStatusReplaying types.RestoreJobStatus = "REPLAYING"
)
25 changes: 11 additions & 14 deletions api/constants/tenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,23 @@ See the Mulan PSL v2 for more details.

package constants

type TenantRole string
import "github.com/oceanbase/ob-operator/api/types"

const (
TenantRolePrimary TenantRole = "PRIMARY"
TenantRoleStandby TenantRole = "STANDBY"
TenantRolePrimary types.TenantRole = "PRIMARY"
TenantRoleStandby types.TenantRole = "STANDBY"
)

type TenantOperationType string

const (
TenantOpSwitchover TenantOperationType = "SWITCHOVER"
TenantOpFailover TenantOperationType = "FAILOVER"
TenantOpChangePwd TenantOperationType = "CHANGE_PASSWORD"
TenantOpSwitchover types.TenantOperationType = "SWITCHOVER"
TenantOpFailover types.TenantOperationType = "FAILOVER"
TenantOpChangePwd types.TenantOperationType = "CHANGE_PASSWORD"
)

type TenantOperationStatus string

const (
TenantOpStarting TenantOperationStatus = "STARTING"
TenantOpRunning TenantOperationStatus = "RUNNING"
TenantOpSuccessful TenantOperationStatus = "SUCCESSFUL"
TenantOpFailed TenantOperationStatus = "FAILED"
TenantOpStarting types.TenantOperationStatus = "STARTING"
TenantOpRunning types.TenantOperationStatus = "RUNNING"
TenantOpSuccessful types.TenantOperationStatus = "SUCCESSFUL"
TenantOpFailed types.TenantOperationStatus = "FAILED"
TenantOpReverting types.TenantOperationStatus = "REVERTING"
)
30 changes: 30 additions & 0 deletions api/types/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
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 types

type BackupJobType string
type BackupJobStatus string
type BackupPolicyStatusType string
type BackupDestType string
type LogArchiveDestState string
type ArchiveBinding string
type BackupDestination struct {
Type BackupDestType `json:"type,omitempty"`
Path string `json:"path,omitempty"`
}

type RestoreJobStatus string

type TenantRole string
type TenantOperationStatus string
type TenantOperationType string
2 changes: 2 additions & 0 deletions api/v1alpha1/obcluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ type OBClusterStatus struct {

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.status"
//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
powerfooI marked this conversation as resolved.
Show resolved Hide resolved

// OBCluster is the Schema for the obclusters API
type OBCluster struct {
Expand Down
4 changes: 4 additions & 0 deletions api/v1alpha1/observer_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ type OBServerStatus struct {

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:printcolumn:name="PodIP",type="string",JSONPath=".status.podIp"
//+kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.status"
//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
powerfooI marked this conversation as resolved.
Show resolved Hide resolved
//+kubebuilder:printcolumn:name="OBStatus",type="string",JSONPath=".status.obStatus"

// OBServer is the Schema for the observers API
type OBServer struct {
Expand Down
14 changes: 8 additions & 6 deletions api/v1alpha1/obtenant_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/oceanbase/ob-operator/api/constants"
apitypes "github.com/oceanbase/ob-operator/api/types"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
Expand All @@ -46,9 +46,9 @@ type OBTenantSpec struct {
Pools []ResourcePoolSpec `json:"pools"`

//+kubebuilder:default=PRIMARY
TenantRole constants.TenantRole `json:"tenantRole,omitempty"`
Source *TenantSourceSpec `json:"source,omitempty"`
Credentials TenantCredentials `json:"credentials,omitempty"`
TenantRole apitypes.TenantRole `json:"tenantRole,omitempty"`
Source *TenantSourceSpec `json:"source,omitempty"`
Credentials TenantCredentials `json:"credentials,omitempty"`
}

type TenantCredentials struct {
Expand Down Expand Up @@ -113,8 +113,9 @@ type OBTenantStatus struct {
OperationContext *OperationContext `json:"operationContext,omitempty"`
TenantRecordInfo TenantRecordInfo `json:"tenantRecordInfo,omitempty"`

TenantRole constants.TenantRole `json:"tenantRole,omitempty"`
Source *TenantSourceStatus `json:"source,omitempty"`
TenantRole apitypes.TenantRole `json:"tenantRole,omitempty"`
Source *TenantSourceStatus `json:"source,omitempty"`
Credentials TenantCredentials `json:"credentials,omitempty"`
}

type TenantSourceStatus struct {
Expand Down Expand Up @@ -196,6 +197,7 @@ type TenantRecordInfo struct {
//+kubebuilder:subresource:status
//+kubebuilder:printcolumn:name="status",type="string",JSONPath=".status.status"
//+kubebuilder:printcolumn:name="tenantName",type="string",JSONPath=".spec.tenantName"
//+kubebuilder:printcolumn:name="tenantRole",type="string",JSONPath=".status.tenantRole"
//+kubebuilder:printcolumn:name="clusterName",type="string",JSONPath=".spec.obcluster"
//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
//+kubebuilder:printcolumn:name="locality",type="string",JSONPath=".status.tenantRecordInfo.locality",priority=1
Expand Down
34 changes: 33 additions & 1 deletion api/v1alpha1/obtenant_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,15 @@ limitations under the License.
package v1alpha1

import (
"context"

apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/validation/field"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
Expand All @@ -29,9 +34,11 @@ import (
)

// log is for logging in this package.
var _ = logf.Log.WithName("obtenant-resource")
var tenantlog = logf.Log.WithName("obtenant-resource")
var tenantClt client.Client

func (r *OBTenant) SetupWebhookWithManager(mgr ctrl.Manager) error {
tenantClt = mgr.GetClient()
return ctrl.NewWebhookManagedBy(mgr).
For(r).
Complete()
Expand All @@ -43,6 +50,23 @@ var _ webhook.Defaulter = &OBTenant{}

// Default implements webhook.Defaulter so a webhook will be registered for the type
func (r *OBTenant) Default() {
cluster := &OBCluster{}
err := tenantClt.Get(context.Background(), types.NamespacedName{
Namespace: r.GetNamespace(),
Name: r.Spec.ClusterName,
}, cluster)
if err != nil {
tenantlog.Error(err, "Failed to get cluster")
} else {
tenantlog.Info("Get cluster", "cluster", cluster)
r.SetOwnerReferences([]metav1.OwnerReference{{
APIVersion: cluster.APIVersion,
Kind: cluster.Kind,
Name: cluster.GetObjectMeta().GetName(),
UID: cluster.GetObjectMeta().GetUID(),
}})
}

if r.Spec.TenantRole == "" {
r.Spec.TenantRole = constants.TenantRolePrimary
}
Expand All @@ -69,6 +93,13 @@ func (r *OBTenant) ValidateUpdate(old runtime.Object) (admission.Warnings, error
func (r *OBTenant) validateMutation() error {
var allErrs field.ErrorList

if r.Spec.Credentials.Root == "" {
powerfooI marked this conversation as resolved.
Show resolved Hide resolved
allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("credentials").Child("root"), r.Spec.Credentials.Root, "Root password user secretref must be set"))
}
if r.Spec.Credentials.StandbyRO == "" {
allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("credentials").Child("standbyRo"), r.Spec.Credentials.StandbyRO, "Standby read-only user password secretref must be set"))
}

// 1. Standby tenant must have a source
if r.Spec.TenantRole == constants.TenantRoleStandby {
if r.Spec.Source == nil {
Expand All @@ -77,6 +108,7 @@ func (r *OBTenant) validateMutation() error {
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"))
}
}

// 2. Restore until with some limit must have a limit key
if r.Spec.Source != nil && r.Spec.Source.Restore != nil {
untilSpec := r.Spec.Source.Restore.Until
Expand Down
28 changes: 14 additions & 14 deletions api/v1alpha1/obtenantbackup_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

constants "github.com/oceanbase/ob-operator/api/constants"
apitypes "github.com/oceanbase/ob-operator/api/types"
"github.com/oceanbase/ob-operator/pkg/oceanbase/model"
)

Expand All @@ -30,26 +30,26 @@ type OBTenantBackupSpec struct {
// Important: Run "make" to regenerate code after modifying this file

// Foo is an example field of OBTenantBackup. Edit obtenantbackup_types.go to remove/update
Type constants.BackupJobType `json:"type"`
TenantName string `json:"tenantName"`
TenantSecret string `json:"tenantSecret"`
ObClusterName string `json:"obClusterName"`
Path string `json:"path,omitempty"`
Type apitypes.BackupJobType `json:"type"`
TenantName string `json:"tenantName"`
TenantSecret string `json:"tenantSecret"`
ObClusterName string `json:"obClusterName"`
Path string `json:"path,omitempty"`
}

// +kubebuilder:object:generate=false
// OBTenantBackupStatus defines the observed state of OBTenantBackup
type OBTenantBackupStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
Status constants.BackupJobStatus `json:"status"`
Progress string `json:"progress,omitempty"`
OperationContext *OperationContext `json:"operationContext,omitempty"`
StartedAt string `json:"startedAt,omitempty"`
EndedAt string `json:"endedAt,omitempty"`
BackupJob *model.OBBackupJob `json:"backupJob,omitempty"`
ArchiveLogJob *model.OBArchiveLogJob `json:"archiveLogJob,omitempty"`
DataCleanJob *model.OBBackupCleanJob `json:"dataCleanJob,omitempty"`
Status apitypes.BackupJobStatus `json:"status"`
Progress string `json:"progress,omitempty"`
OperationContext *OperationContext `json:"operationContext,omitempty"`
StartedAt string `json:"startedAt,omitempty"`
EndedAt string `json:"endedAt,omitempty"`
BackupJob *model.OBBackupJob `json:"backupJob,omitempty"`
ArchiveLogJob *model.OBArchiveLogJob `json:"archiveLogJob,omitempty"`
DataCleanJob *model.OBBackupCleanJob `json:"dataCleanJob,omitempty"`
}

// fix: implementation of DeepCopyInto needed by zz_generated.deepcopy.go
Expand Down
Loading