Skip to content

Commit

Permalink
Feature: Cluster Operation CRD that supports many common operations. (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
powerfooI authored Jun 5, 2024
1 parent 81dca7c commit cc50a52
Show file tree
Hide file tree
Showing 88 changed files with 8,075 additions and 583 deletions.
13 changes: 13 additions & 0 deletions PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,17 @@ resources:
defaulting: true
validation: true
webhookVersion: v1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: oceanbase.com
group: oceanbase
kind: OBClusterOperation
path: github.com/oceanbase/ob-operator/api/v1alpha1
version: v1alpha1
webhooks:
defaulting: true
validation: true
webhookVersion: v1
version: "3"
32 changes: 32 additions & 0 deletions api/constants/cluster.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
Copyright (c) 2024 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

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

const (
ClusterOpTypeAddZones types.ClusterOperationType = "AddZones"
ClusterOpTypeDeleteZones types.ClusterOperationType = "DeleteZones"
ClusterOpTypeAdjustReplicas types.ClusterOperationType = "AdjustReplicas"
ClusterOpTypeUpgrade types.ClusterOperationType = "Upgrade"
ClusterOpTypeRestartOBServers types.ClusterOperationType = "RestartOBServers"
ClusterOpTypeModifyOBServers types.ClusterOperationType = "ModifyOBServers"
ClusterOpTypeSetParameters types.ClusterOperationType = "SetParameters"
)

const (
ClusterOpStatusPending types.ClusterOperationStatus = "Pending"
ClusterOpStatusRunning types.ClusterOperationStatus = "Running"
ClusterOpStatusSucceeded types.ClusterOperationStatus = "Succeeded"
ClusterOpStatusFailed types.ClusterOperationStatus = "Failed"
)
3 changes: 3 additions & 0 deletions api/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ type RestoreJobStatus string
type TenantRole string
type TenantOperationStatus string
type TenantOperationType string

type ClusterOperationType string
type ClusterOperationStatus string
1 change: 0 additions & 1 deletion api/v1alpha1/obcluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ type OBClusterStatus struct {
//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
//+kubebuilder:printcolumn:name="Tasks",type="string",JSONPath=".status.operationContext.tasks",priority=1
//+kubebuilder:printcolumn:name="Task",type="string",JSONPath=".status.operationContext.task",priority=1
//+kubebuilder:printcolumn:name="TaskIdx",type="string",JSONPath=".status.operationContext.idx",priority=1

// OBCluster is the Schema for the obclusters API
type OBCluster struct {
Expand Down
8 changes: 4 additions & 4 deletions api/v1alpha1/obcluster_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,13 +234,13 @@ func (r *OBCluster) ValidateUpdate(old runtime.Object) (admission.Warnings, erro
newStorage := r.Spec.OBServerTemplate.Storage
oldStorage := oldCluster.Spec.OBServerTemplate.Storage
if newStorage.DataStorage.Size.Cmp(oldStorage.DataStorage.Size) > 0 {
err = errors.Join(err, r.validateStorageClassAllowExpansion(newStorage.DataStorage.StorageClass))
err = errors.Join(err, validateStorageClassAllowExpansion(newStorage.DataStorage.StorageClass))
}
if newStorage.LogStorage.Size.Cmp(oldStorage.LogStorage.Size) > 0 {
err = errors.Join(err, r.validateStorageClassAllowExpansion(newStorage.LogStorage.StorageClass))
err = errors.Join(err, validateStorageClassAllowExpansion(newStorage.LogStorage.StorageClass))
}
if newStorage.RedoLogStorage.Size.Cmp(oldStorage.RedoLogStorage.Size) > 0 {
err = errors.Join(err, r.validateStorageClassAllowExpansion(newStorage.RedoLogStorage.StorageClass))
err = errors.Join(err, validateStorageClassAllowExpansion(newStorage.RedoLogStorage.StorageClass))
}
if err != nil {
return nil, err
Expand Down Expand Up @@ -484,7 +484,7 @@ func (r *OBCluster) createDefaultUserSecret(secretName string) error {
})
}

func (r *OBCluster) validateStorageClassAllowExpansion(storageClassName string) error {
func validateStorageClassAllowExpansion(storageClassName string) error {
sc := storagev1.StorageClass{}
err := clt.Get(context.Background(), types.NamespacedName{
Name: storageClassName,
Expand Down
132 changes: 132 additions & 0 deletions api/v1alpha1/obclusteroperation_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
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 (
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

apitypes "github.com/oceanbase/ob-operator/api/types"
tasktypes "github.com/oceanbase/ob-operator/pkg/task/types"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.

// OBClusterOperationSpec defines the desired state of OBClusterOperation
type OBClusterOperationSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file

OBCluster string `json:"obcluster"`
Type apitypes.ClusterOperationType `json:"type"`
Force bool `json:"force,omitempty"`
//+kubebuilder:default=7
TTLDays int `json:"ttlDays,omitempty"`
AddZones []apitypes.OBZoneTopology `json:"addZones,omitempty"`
DeleteZones []string `json:"deleteZones,omitempty"`
AdjustReplicas []AlterZoneReplicas `json:"adjustReplicas,omitempty"`
RestartOBServers *RestartOBServersConfig `json:"restartOBServers,omitempty"`
Upgrade *UpgradeConfig `json:"upgrade,omitempty"`
ModifyOBServers *ModifyOBServersConfig `json:"modifyOBServers,omitempty"`
SetParameters []apitypes.Parameter `json:"setParameters,omitempty"`
}

type ModifyOBServersConfig struct {
Resource *apitypes.ResourceSpec `json:"resource,omitempty"`
ExpandStorageSize *ExpandStorageSizeConfig `json:"expandStorageSize,omitempty"`
ModifyStorageClass *ModifyStorageClassConfig `json:"modifyStorageClass,omitempty"`
AddingMonitor *apitypes.MonitorTemplate `json:"addingMonitor,omitempty"`
RemoveMonitor bool `json:"removeMonitor,omitempty"`
AddingBackupVolume *apitypes.BackupVolumeSpec `json:"addingBackupVolume,omitempty"`
RemoveBackupVolume bool `json:"removeBackupVolume,omitempty"`
}

type RestartOBServersConfig struct {
OBServers []string `json:"observers,omitempty"`
OBZones []string `json:"obzones,omitempty"`
All bool `json:"all,omitempty"`
}

type ExpandStorageSizeConfig struct {
DataStorage *resource.Quantity `json:"dataStorage,omitempty"`
LogStorage *resource.Quantity `json:"logStorage,omitempty"`
RedoLogStorage *resource.Quantity `json:"redoLogStorage,omitempty"`
}

type ModifyStorageClassConfig struct {
DataStorage string `json:"dataStorage,omitempty"`
LogStorage string `json:"logStorage,omitempty"`
RedoLogStorage string `json:"redoLogStorage,omitempty"`
}

type UpgradeConfig struct {
Image string `json:"image"`
}

type AlterZoneReplicas struct {
Zones []string `json:"zones"`
To int `json:"to,omitempty"`
}

// OBClusterOperationStatus defines the observed state of OBClusterOperation
type OBClusterOperationStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
Status apitypes.ClusterOperationStatus `json:"status"`
OperationContext *tasktypes.OperationContext `json:"operationContext,omitempty"`
ClusterSnapshot *OBClusterSnapshot `json:"clusterSnapshot,omitempty"`
}

type OBClusterSnapshot struct {
Spec *OBClusterSpec `json:"spec,omitempty"`
Status *OBClusterStatus `json:"status,omitempty"`
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:printcolumn:name="Type",type=string,JSONPath=`.spec.type`
//+kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.status"
//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
//+kubebuilder:printcolumn:name="Tasks",type="string",JSONPath=".status.operationContext.tasks",priority=1
//+kubebuilder:printcolumn:name="Task",type="string",JSONPath=".status.operationContext.task",priority=1

// OBClusterOperation is the Schema for the obclusteroperations API
type OBClusterOperation struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec OBClusterOperationSpec `json:"spec,omitempty"`
Status OBClusterOperationStatus `json:"status,omitempty"`
}

//+kubebuilder:object:root=true

// OBClusterOperationList contains a list of OBClusterOperation
type OBClusterOperationList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []OBClusterOperation `json:"items"`
}

func init() {
SchemeBuilder.Register(&OBClusterOperation{}, &OBClusterOperationList{})
}

func (o *OBClusterOperation) ShouldBeCleaned() bool {
return o.CreationTimestamp.AddDate(0, 0, o.Spec.TTLDays).Before(metav1.Now().Time)
}
Loading

0 comments on commit cc50a52

Please sign in to comment.