github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/apis/apps/v1alpha1/opsrequest_types.go (about)

     1  /*
     2  Copyright (C) 2022-2023 ApeCloud Co., Ltd
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package v1alpha1
    18  
    19  import (
    20  	corev1 "k8s.io/api/core/v1"
    21  	"k8s.io/apimachinery/pkg/api/resource"
    22  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    23  )
    24  
    25  // TODO: @wangyelei could refactor to ops group
    26  
    27  // OpsRequestSpec defines the desired state of OpsRequest
    28  // +kubebuilder:validation:XValidation:rule="has(self.cancel) && self.cancel ? (self.type in ['VerticalScaling', 'HorizontalScaling']) : true",message="forbidden to cancel the opsRequest which type not in ['VerticalScaling','HorizontalScaling']"
    29  type OpsRequestSpec struct {
    30  	// clusterRef references clusterDefinition.
    31  	// +kubebuilder:validation:Required
    32  	// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="forbidden to update spec.clusterRef"
    33  	ClusterRef string `json:"clusterRef"`
    34  
    35  	// cancel defines the action to cancel the Pending/Creating/Running opsRequest, supported types: [VerticalScaling, HorizontalScaling].
    36  	// once cancel is set to true, this opsRequest will be canceled and modifying this property again will not take effect.
    37  	// +optional
    38  	Cancel bool `json:"cancel,omitempty"`
    39  
    40  	// type defines the operation type.
    41  	// +kubebuilder:validation:Required
    42  	// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="forbidden to update spec.type"
    43  	Type OpsType `json:"type"`
    44  
    45  	// ttlSecondsAfterSucceed OpsRequest will be deleted after TTLSecondsAfterSucceed second when OpsRequest.status.phase is Succeed.
    46  	// +optional
    47  	TTLSecondsAfterSucceed int32 `json:"ttlSecondsAfterSucceed,omitempty"`
    48  
    49  	// upgrade specifies the cluster version by specifying clusterVersionRef.
    50  	// +optional
    51  	// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="forbidden to update spec.upgrade"
    52  	Upgrade *Upgrade `json:"upgrade,omitempty"`
    53  
    54  	// Deprecate: replace by update cluster command
    55  
    56  	// horizontalScaling defines what component need to horizontal scale the specified replicas.
    57  	// +optional
    58  	// +patchMergeKey=componentName
    59  	// +patchStrategy=merge,retainKeys
    60  	// +listType=map
    61  	// +listMapKey=componentName
    62  	// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="forbidden to update spec.horizontalScaling"
    63  	HorizontalScalingList []HorizontalScaling `json:"horizontalScaling,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"componentName"`
    64  
    65  	// Deprecate: replace by update cluster command.
    66  	// Note: Quantity struct can not do immutable check by CEL.
    67  
    68  	// volumeExpansion defines what component and volumeClaimTemplate need to expand the specified storage.
    69  	// +optional
    70  	// +patchMergeKey=componentName
    71  	// +patchStrategy=merge,retainKeys
    72  	// +listType=map
    73  	// +listMapKey=componentName
    74  	VolumeExpansionList []VolumeExpansion `json:"volumeExpansion,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"componentName"`
    75  
    76  	// restart the specified components.
    77  	// +optional
    78  	// +patchMergeKey=componentName
    79  	// +patchStrategy=merge,retainKeys
    80  	// +listType=map
    81  	// +listMapKey=componentName
    82  	// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="forbidden to update spec.restart"
    83  	RestartList []ComponentOps `json:"restart,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"componentName"`
    84  
    85  	// switchover the specified components.
    86  	// +optional
    87  	// +patchMergeKey=componentName
    88  	// +patchStrategy=merge,retainKeys
    89  	// +listType=map
    90  	// +listMapKey=componentName
    91  	// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="forbidden to update spec.switchover"
    92  	SwitchoverList []Switchover `json:"switchover,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"componentName"`
    93  
    94  	// Deprecate: replace by update cluster command.
    95  	// Note: Quantity struct can not do immutable check by CEL.
    96  
    97  	// verticalScaling defines what component need to vertical scale the specified compute resources.
    98  	// +optional
    99  	// +patchMergeKey=componentName
   100  	// +patchStrategy=merge,retainKeys
   101  	// +listType=map
   102  	// +listMapKey=componentName
   103  	VerticalScalingList []VerticalScaling `json:"verticalScaling,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"componentName"`
   104  
   105  	// reconfigure defines the variables that need to input when updating configuration.
   106  	// +optional
   107  	// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="forbidden to update spec.reconfigure"
   108  	// +kubebuilder:validation:XValidation:rule="self.configurations.size() > 0", message="Value can not be empty"
   109  	Reconfigure *Reconfigure `json:"reconfigure,omitempty"`
   110  
   111  	// expose defines services the component needs to expose.
   112  	// +optional
   113  	// +patchMergeKey=componentName
   114  	// +patchStrategy=merge,retainKeys
   115  	// +listType=map
   116  	// +listMapKey=componentName
   117  	// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="forbidden to update spec.expose"
   118  	ExposeList []Expose `json:"expose,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"componentName"`
   119  
   120  	// cluster RestoreFrom backup or point in time
   121  	// +optional
   122  	// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="forbidden to update spec.restoreFrom"
   123  	RestoreFrom *RestoreFromSpec `json:"restoreFrom,omitempty"`
   124  
   125  	// ttlSecondsBeforeAbort OpsRequest will wait at most TTLSecondsBeforeAbort seconds for start-conditions to be met.
   126  	// If not specified, the default value is 0, which means that the start-conditions must be met immediately.
   127  	// +kubebuilder:default=0
   128  	// +optional
   129  	TTLSecondsBeforeAbort *int32 `json:"ttlSecondsBeforeAbort,omitempty"`
   130  
   131  	// scriptSpec defines the script to be executed.
   132  	// +optional
   133  	ScriptSpec *ScriptSpec `json:"scriptSpec,omitempty"`
   134  
   135  	// backupSpec defines how to backup the cluster.
   136  	// +optional
   137  	BackupSpec *BackupSpec `json:"backupSpec,omitempty"`
   138  }
   139  
   140  // ComponentOps defines the common variables of component scope operations.
   141  type ComponentOps struct {
   142  	// componentName cluster component name.
   143  	// +kubebuilder:validation:Required
   144  	ComponentName string `json:"componentName"`
   145  }
   146  
   147  type Switchover struct {
   148  	ComponentOps `json:",inline"`
   149  
   150  	// instanceName is used to specify the candidate primary or leader instanceName for switchover.
   151  	// If instanceName is set to "*", it means that no specific primary or leader is specified for the switchover,
   152  	// and the switchoverAction defined in clusterDefinition.componentDefs[x].switchoverSpec.withoutCandidate will be executed,
   153  	// It is required that clusterDefinition.componentDefs[x].switchoverSpec.withoutCandidate is not empty.
   154  	// If instanceName is set to a valid instanceName other than "*", it means that a specific candidate primary or leader is specified for the switchover.
   155  	// the value of instanceName can be obtained using `kbcli cluster list-instances`, any other value is invalid.
   156  	// In this case, the `switchoverAction` defined in clusterDefinition.componentDefs[x].switchoverSpec.withCandidate will be executed,
   157  	// and it is required that clusterDefinition.componentDefs[x].switchoverSpec.withCandidate is not empty.
   158  	// +kubebuilder:validation:Required
   159  	InstanceName string `json:"instanceName"`
   160  }
   161  
   162  // Upgrade defines the variables of upgrade operation.
   163  type Upgrade struct {
   164  	// clusterVersionRef references ClusterVersion name.
   165  	// +kubebuilder:validation:Required
   166  	ClusterVersionRef string `json:"clusterVersionRef"`
   167  }
   168  
   169  // VerticalScaling defines the variables that need to input when scaling compute resources.
   170  type VerticalScaling struct {
   171  	ComponentOps `json:",inline"`
   172  
   173  	// resources specifies the computing resource size of verticalScaling.
   174  	// +kubebuilder:pruning:PreserveUnknownFields
   175  	corev1.ResourceRequirements `json:",inline"`
   176  
   177  	// classDefRef reference class defined in ComponentClassDefinition.
   178  	// +optional
   179  	ClassDefRef *ClassDefRef `json:"classDefRef,omitempty"`
   180  }
   181  
   182  // VolumeExpansion defines the variables of volume expansion operation.
   183  type VolumeExpansion struct {
   184  	ComponentOps `json:",inline"`
   185  
   186  	// volumeClaimTemplates specifies the storage size and volumeClaimTemplate name.
   187  	// +kubebuilder:validation:Required
   188  	// +patchMergeKey=name
   189  	// +patchStrategy=merge,retainKeys
   190  	// +listType=map
   191  	// +listMapKey=name
   192  	VolumeClaimTemplates []OpsRequestVolumeClaimTemplate `json:"volumeClaimTemplates" patchStrategy:"merge,retainKeys" patchMergeKey:"name"`
   193  }
   194  
   195  type OpsRequestVolumeClaimTemplate struct {
   196  	// Request storage size.
   197  	// +kubebuilder:validation:Required
   198  	Storage resource.Quantity `json:"storage"`
   199  
   200  	// name references volumeClaimTemplate name from cluster components.
   201  	// +kubebuilder:validation:Required
   202  	Name string `json:"name"`
   203  }
   204  
   205  // HorizontalScaling defines the variables of horizontal scaling operation
   206  type HorizontalScaling struct {
   207  	ComponentOps `json:",inline"`
   208  
   209  	// replicas for the workloads.
   210  	// +kubebuilder:validation:Required
   211  	// +kubebuilder:validation:Minimum=0
   212  	Replicas int32 `json:"replicas"`
   213  }
   214  
   215  // Reconfigure defines the variables that need to input when updating configuration.
   216  type Reconfigure struct {
   217  	ComponentOps `json:",inline"`
   218  
   219  	// configurations defines which components perform the operation.
   220  	// +kubebuilder:validation:Required
   221  	// +kubebuilder:validation:MinItems=1
   222  	// +patchMergeKey=name
   223  	// +patchStrategy=merge,retainKeys
   224  	// +listType=map
   225  	// +listMapKey=name
   226  	Configurations []ConfigurationItem `json:"configurations" patchStrategy:"merge,retainKeys" patchMergeKey:"name"`
   227  
   228  	// TTL(Time to Live) defines the time period during which changing parameters is valid.
   229  	// +optional
   230  	// TTL *int64 `json:"ttl,omitempty"`
   231  
   232  	// triggeringTime defines the time at which the changing parameter to be applied.
   233  	// +kubebuilder:validation:MaxLength=19
   234  	// +kubebuilder:validation:MinLength=19
   235  	// +kubebuilder:validation:Pattern:=`^([0-9]{2})/([0-9]{2})/([0-9]{4}) ([0-9]{2}):([0-9]{2}):([0-9]{2})$`
   236  	// +optional
   237  	// TriggeringTime *string `json:"triggeringTime,omitempty"`
   238  
   239  	// selector indicates the component for reconfigure
   240  	// +optional
   241  	// Selector *metav1.LabelSelector `json:"selector,omitempty"`
   242  }
   243  
   244  type ConfigurationItem struct {
   245  	// name is a config template name.
   246  	// +kubebuilder:validation:Required
   247  	// +kubebuilder:validation:MaxLength=63
   248  	// +kubebuilder:validation:Pattern:=`^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$`
   249  	Name string `json:"name"`
   250  
   251  	// policy defines the upgrade policy.
   252  	// +optional
   253  	Policy *UpgradePolicy `json:"policy,omitempty"`
   254  
   255  	// keys is used to set the parameters to be updated.
   256  	// +kubebuilder:validation:Required
   257  	// +kubebuilder:validation:MinItems=1
   258  	// +patchMergeKey=key
   259  	// +patchStrategy=merge,retainKeys
   260  	// +listType=map
   261  	// +listMapKey=key
   262  	Keys []ParameterConfig `json:"keys" patchStrategy:"merge,retainKeys" patchMergeKey:"key"`
   263  }
   264  
   265  type ParameterPair struct {
   266  	// key is name of the parameter to be updated.
   267  	// +kubebuilder:validation:Required
   268  	Key string `json:"key"`
   269  
   270  	// parameter values to be updated.
   271  	// if set nil, the parameter defined by the key field will be deleted from the configuration file.
   272  	// +optional
   273  	Value *string `json:"value"`
   274  }
   275  
   276  type ParameterConfig struct {
   277  	// key indicates the key name of ConfigMap.
   278  	// +kubebuilder:validation:Required
   279  	Key string `json:"key"`
   280  
   281  	// Setting the list of parameters for a single configuration file.
   282  	// update specified the parameters.
   283  	// +optional
   284  	Parameters []ParameterPair `json:"parameters,omitempty"`
   285  
   286  	// fileContent indicates the configuration file content.
   287  	// update whole file.
   288  	// +optional
   289  	FileContent string `json:"fileContent,omitempty"`
   290  }
   291  
   292  type Expose struct {
   293  	ComponentOps `json:",inline"`
   294  
   295  	// Setting the list of services to be exposed.
   296  	// +kubebuilder:validation:Required
   297  	// +kubebuilder:validation:Minitems=0
   298  	Services []ClusterComponentService `json:"services"`
   299  }
   300  
   301  type RestoreFromSpec struct {
   302  	// use the backup name and component name for restore, support for multiple components' recovery.
   303  	// +optional
   304  	Backup []BackupRefSpec `json:"backup,omitempty"`
   305  
   306  	// specified the point in time to recovery
   307  	// +optional
   308  	PointInTime *PointInTimeRefSpec `json:"pointInTime,omitempty"`
   309  }
   310  
   311  type RefNamespaceName struct {
   312  	// specified the name
   313  	// +optional
   314  	Name string `json:"name,omitempty"`
   315  
   316  	// specified the namespace
   317  	// +optional
   318  	Namespace string `json:"namespace,omitempty"`
   319  }
   320  
   321  type BackupRefSpec struct {
   322  	// specify a reference backup to restore
   323  	// +optional
   324  	Ref RefNamespaceName `json:"ref,omitempty"`
   325  }
   326  
   327  type PointInTimeRefSpec struct {
   328  	// specify the time point to restore, with UTC as the time zone.
   329  	// +optional
   330  	Time *metav1.Time `json:"time,omitempty"`
   331  
   332  	// specify a reference source cluster to restore
   333  	// +optional
   334  	Ref RefNamespaceName `json:"ref,omitempty"`
   335  }
   336  
   337  // ScriptSpec defines the script to be executed. It is not a general purpose script executor.
   338  // It is designed to execute the script to perform some specific operations, such as create database, create user, etc.
   339  // It is applicable for engines, such as MySQL, PostgreSQL, Redis, MongoDB, etc.
   340  type ScriptSpec struct {
   341  	ComponentOps `json:",inline"`
   342  	// exec command with image, by default use the image of kubeblocks-datascript.
   343  	// +optional
   344  	Image string `json:"image,omitempty"`
   345  	// secret defines the secret to be used to execute the script.
   346  	// If not specified, the default cluster root credential secret will be used.
   347  	// +optional
   348  	Secret *ScriptSecret `json:"secret,omitempty"`
   349  	// script defines the script to be executed.
   350  	// +optional
   351  	// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="forbidden to update spec.scriptSpec.script"
   352  	Script []string `json:"script,omitempty"`
   353  	// scriptFrom defines the script to be executed from configMap or secret.
   354  	// +optional
   355  	// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="forbidden to update spec.scriptSpec.scriptFrom"
   356  	ScriptFrom *ScriptFrom `json:"scriptFrom,omitempty"`
   357  	// KubeBlocks, by default, will execute the script on the primary pod, with role=leader.
   358  	// There are some exceptions, such as Redis, which does not synchronize accounts info between primary and secondary.
   359  	// In this case, we need to execute the script on all pods, matching the selector.
   360  	// selector indicates the components on which the script is executed.
   361  	// +optional
   362  	// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="forbidden to update spec.scriptSpec.script.selector"
   363  	Selector *metav1.LabelSelector `json:"selector,omitempty"`
   364  }
   365  
   366  type BackupSpec struct {
   367  	// backupName is the name of the backup.
   368  	// +optional
   369  	BackupName string `json:"backupName,omitempty"`
   370  
   371  	// Which backupPolicy is applied to perform this backup
   372  	// +optional
   373  	BackupPolicyName string `json:"backupPolicyName,omitempty"`
   374  
   375  	// Backup method name that is defined in backupPolicy.
   376  	// +optional
   377  	BackupMethod string `json:"backupMethod,omitempty"`
   378  
   379  	// deletionPolicy determines whether the backup contents stored in backup repository
   380  	// should be deleted when the backup custom resource is deleted.
   381  	// Supported values are "Retain" and "Delete".
   382  	// "Retain" means that the backup content and its physical snapshot on backup repository are kept.
   383  	// "Delete" means that the backup content and its physical snapshot on backup repository are deleted.
   384  	// +kubebuilder:validation:Enum=Delete;Retain
   385  	// +kubebuilder:validation:Required
   386  	// +kubebuilder:default=Delete
   387  	// +optional
   388  	DeletionPolicy string `json:"deletionPolicy,omitempty"`
   389  
   390  	// retentionPeriod determines a duration up to which the backup should be kept.
   391  	// Controller will remove all backups that are older than the RetentionPeriod.
   392  	// For example, RetentionPeriod of `30d` will keep only the backups of last 30 days.
   393  	// Sample duration format:
   394  	// - years: 	2y
   395  	// - months: 	6mo
   396  	// - days: 		30d
   397  	// - hours: 	12h
   398  	// - minutes: 	30m
   399  	// You can also combine the above durations. For example: 30d12h30m.
   400  	// If not set, the backup will be kept forever.
   401  	// +optional
   402  	RetentionPeriod string `json:"retentionPeriod,omitempty"`
   403  
   404  	// if backupType is incremental, parentBackupName is required.
   405  	// +optional
   406  	ParentBackupName string `json:"parentBackupName,omitempty"`
   407  }
   408  
   409  // ScriptSecret defines the secret to be used to execute the script.
   410  type ScriptSecret struct {
   411  	// name is the name of the secret.
   412  	// +kubebuilder:validation:Required
   413  	// +kubebuilder:validation:MaxLength=63
   414  	// +kubebuilder:validation:Pattern:=`^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$`
   415  	Name string `json:"name"`
   416  	// usernameKey field is used to specify the username of the secret.
   417  	// +kubebuilder:default:="username"
   418  	// +optional
   419  	UsernameKey string `json:"usernameKey,omitempty"`
   420  	// passwordKey field is used to specify the password of the secret.
   421  	// +kubebuilder:default:="password"
   422  	// +optional
   423  	PasswordKey string `json:"passwordKey,omitempty"`
   424  }
   425  
   426  // ScriptFrom defines the script to be executed from configMap or secret.
   427  type ScriptFrom struct {
   428  	// configMapRef defines the configMap to be executed.
   429  	// +optional
   430  	// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="forbidden to update spec.scriptSpec.scriptFrom.configMapRef"
   431  	ConfigMapRef []corev1.ConfigMapKeySelector `json:"configMapRef,omitempty"`
   432  	// secretRef defines the secret to be executed.
   433  	// +optional
   434  	// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="forbidden to update spec.scriptSpec.scriptFrom.secretRef"
   435  	SecretRef []corev1.SecretKeySelector `json:"secretRef,omitempty"`
   436  }
   437  
   438  // OpsRequestStatus defines the observed state of OpsRequest
   439  type OpsRequestStatus struct {
   440  
   441  	// ClusterGeneration records the cluster generation after handling the opsRequest action.
   442  	// +optional
   443  	ClusterGeneration int64 `json:"clusterGeneration,omitempty"`
   444  
   445  	// phase describes OpsRequest phase.
   446  	Phase OpsPhase `json:"phase,omitempty"`
   447  
   448  	// +kubebuilder:validation:Pattern:=`^(\d+|\-)/(\d+|\-)$`
   449  	// +kubebuilder:default=-/-
   450  	Progress string `json:"progress"`
   451  
   452  	// lastConfiguration records the last configuration before this operation take effected.
   453  	// +optional
   454  	LastConfiguration LastConfiguration `json:"lastConfiguration,omitempty"`
   455  
   456  	// components defines the recorded the status information of changed components for operation request.
   457  	// +optional
   458  	Components map[string]OpsRequestComponentStatus `json:"components,omitempty"`
   459  
   460  	// startTimestamp The time when the OpsRequest started processing.
   461  	// +optional
   462  	StartTimestamp metav1.Time `json:"startTimestamp,omitempty"`
   463  
   464  	// completionTimestamp defines the OpsRequest completion time.
   465  	// +optional
   466  	CompletionTimestamp metav1.Time `json:"completionTimestamp,omitempty"`
   467  
   468  	// CancelTimestamp defines cancel time.
   469  	// +optional
   470  	CancelTimestamp metav1.Time `json:"cancelTimestamp,omitempty"`
   471  
   472  	// reconfiguringStatus defines the status information of reconfiguring.
   473  	// +optional
   474  	ReconfiguringStatus *ReconfiguringStatus `json:"reconfiguringStatus,omitempty"`
   475  
   476  	// conditions describes opsRequest detail status.
   477  	// +optional
   478  	// +patchMergeKey=type
   479  	// +patchStrategy=merge
   480  	// +listType=map
   481  	// +listMapKey=type
   482  	Conditions []metav1.Condition `json:"conditions,omitempty"`
   483  }
   484  
   485  type ProgressStatusDetail struct {
   486  	// group describes which group the current object belongs to.
   487  	// if the objects of a component belong to the same group, we can ignore it.
   488  	// +optional
   489  	Group string `json:"group,omitempty"`
   490  
   491  	// objectKey is the unique key of the object.
   492  	// +kubebuilder:validation:Required
   493  	ObjectKey string `json:"objectKey"`
   494  
   495  	// status describes the state of processing the object.
   496  	// +kubebuilder:validation:Required
   497  	Status ProgressStatus `json:"status"`
   498  
   499  	// message is a human readable message indicating details about the object condition.
   500  	// +optional
   501  	Message string `json:"message,omitempty"`
   502  
   503  	// startTime is the start time of object processing.
   504  	// +optional
   505  	StartTime metav1.Time `json:"startTime,omitempty"`
   506  
   507  	// endTime is the completion time of object processing.
   508  	// +optional
   509  	EndTime metav1.Time `json:"endTime,omitempty"`
   510  }
   511  
   512  type LastComponentConfiguration struct {
   513  	// replicas are the last replicas of the component.
   514  	// +optional
   515  	Replicas *int32 `json:"replicas,omitempty"`
   516  
   517  	// the last resources of the component.
   518  	// +kubebuilder:pruning:PreserveUnknownFields
   519  	// +optional
   520  	corev1.ResourceRequirements `json:",inline,omitempty"`
   521  
   522  	// classDefRef reference class defined in ComponentClassDefinition.
   523  	// +optional
   524  	ClassDefRef *ClassDefRef `json:"classDefRef,omitempty"`
   525  
   526  	// volumeClaimTemplates records the last volumeClaimTemplates of the component.
   527  	// +optional
   528  	VolumeClaimTemplates []OpsRequestVolumeClaimTemplate `json:"volumeClaimTemplates,omitempty"`
   529  
   530  	// services records the last services of the component.
   531  	// +optional
   532  	Services []ClusterComponentService `json:"services,omitempty"`
   533  
   534  	// targetResources records the affecting target resources information for the component.
   535  	// resource key is in list of [pods].
   536  	// +optional
   537  	TargetResources map[ComponentResourceKey][]string `json:"targetResources,omitempty"`
   538  }
   539  
   540  type LastConfiguration struct {
   541  	// clusterVersionRef references ClusterVersion name.
   542  	// +optional
   543  	ClusterVersionRef string `json:"clusterVersionRef,omitempty"`
   544  
   545  	// components records last configuration of the component.
   546  	// +optional
   547  	Components map[string]LastComponentConfiguration `json:"components,omitempty"`
   548  }
   549  
   550  type OpsRequestComponentStatus struct {
   551  	// phase describes the component phase, reference Cluster.status.component.phase.
   552  	// +optional
   553  	Phase ClusterComponentPhase `json:"phase,omitempty"`
   554  
   555  	// lastFailedTime is the last time the component phase transitioned to Failed or Abnormal.
   556  	// +optional
   557  	LastFailedTime metav1.Time `json:"lastFailedTime,omitempty"`
   558  
   559  	// progressDetails describes the progress details of the component for this operation.
   560  	// +optional
   561  	ProgressDetails []ProgressStatusDetail `json:"progressDetails,omitempty"`
   562  
   563  	// workloadType references workload type of component in ClusterDefinition.
   564  	// +optional
   565  	WorkloadType WorkloadType `json:"workloadType,omitempty"`
   566  
   567  	// reason describes the reason for the component phase.
   568  	// +kubebuilder:validation:MaxLength=1024
   569  	// +optional
   570  	Reason string `json:"reason,omitempty" protobuf:"bytes,5,opt,name=reason"`
   571  
   572  	// message is a human-readable message indicating details about this operation.
   573  	// +kubebuilder:validation:MaxLength=32768
   574  	// +optional
   575  	Message string `json:"message,omitempty" protobuf:"bytes,6,opt,name=message"`
   576  }
   577  
   578  type ReconfiguringStatus struct {
   579  	// configurationStatus describes the status of the component reconfiguring.
   580  	// +kubebuilder:validation:Required
   581  	// +kubebuilder:validation:MinItems=1
   582  	// +patchMergeKey=name
   583  	// +patchStrategy=merge,retainKeys
   584  	// +listType=map
   585  	// +listMapKey=name
   586  	ConfigurationStatus []ConfigurationItemStatus `json:"configurationStatus"`
   587  }
   588  
   589  type ConfigurationItemStatus struct {
   590  	// name is a config template name.
   591  	// +kubebuilder:validation:Required
   592  	// +kubebuilder:validation:MaxLength=63
   593  	// +kubebuilder:validation:Pattern:=`^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$`
   594  	Name string `json:"name"`
   595  
   596  	// updatePolicy describes the policy of reconfiguring.
   597  	// +optional
   598  	UpdatePolicy UpgradePolicy `json:"updatePolicy,omitempty"`
   599  
   600  	// status describes the current state of the reconfiguring state machine.
   601  	// +optional
   602  	Status string `json:"status,omitempty"`
   603  
   604  	// message describes the details about this operation.
   605  	// +optional
   606  	Message string `json:"message,omitempty"`
   607  
   608  	// succeedCount describes the number of successful reconfiguring.
   609  	// +kubebuilder:default=0
   610  	// +optional
   611  	SucceedCount int32 `json:"succeedCount"`
   612  
   613  	// expectedCount describes the number of expected reconfiguring.
   614  	// +kubebuilder:default=-1
   615  	// +optional
   616  	ExpectedCount int32 `json:"expectedCount"`
   617  
   618  	// lastStatus describes the last status for the reconfiguring controller.
   619  	// +optional
   620  	LastAppliedStatus string `json:"lastStatus,omitempty"`
   621  
   622  	// LastAppliedConfiguration describes the last configuration.
   623  	// +optional
   624  	LastAppliedConfiguration map[string]string `json:"lastAppliedConfiguration,omitempty"`
   625  
   626  	// updatedParameters describes the updated parameters.
   627  	// +optional
   628  	UpdatedParameters UpdatedParameters `json:"updatedParameters"`
   629  }
   630  
   631  type UpdatedParameters struct {
   632  	// addedKeys describes the key added.
   633  	// +optional
   634  	AddedKeys map[string]string `json:"addedKeys,omitempty"`
   635  
   636  	// deletedKeys describes the key deleted.
   637  	// +optional
   638  	DeletedKeys map[string]string `json:"deletedKeys,omitempty"`
   639  
   640  	// updatedKeys describes the key updated.
   641  	// +optional
   642  	UpdatedKeys map[string]string `json:"updatedKeys,omitempty"`
   643  }
   644  
   645  // +genclient
   646  // +k8s:openapi-gen=true
   647  // +kubebuilder:object:root=true
   648  // +kubebuilder:subresource:status
   649  // +kubebuilder:resource:categories={kubeblocks,all},shortName=ops
   650  // +kubebuilder:printcolumn:name="TYPE",type="string",JSONPath=".spec.type",description="Operation request type."
   651  // +kubebuilder:printcolumn:name="CLUSTER",type="string",JSONPath=".spec.clusterRef",description="Operand cluster."
   652  // +kubebuilder:printcolumn:name="STATUS",type="string",JSONPath=".status.phase",description="Operation status phase."
   653  // +kubebuilder:printcolumn:name="PROGRESS",type="string",JSONPath=".status.progress",description="Operation processing progress."
   654  // +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
   655  
   656  // OpsRequest is the Schema for the opsrequests API
   657  type OpsRequest struct {
   658  	metav1.TypeMeta   `json:",inline"`
   659  	metav1.ObjectMeta `json:"metadata,omitempty"`
   660  
   661  	Spec   OpsRequestSpec   `json:"spec,omitempty"`
   662  	Status OpsRequestStatus `json:"status,omitempty"`
   663  }
   664  
   665  // +kubebuilder:object:root=true
   666  
   667  // OpsRequestList contains a list of OpsRequest
   668  type OpsRequestList struct {
   669  	metav1.TypeMeta `json:",inline"`
   670  	metav1.ListMeta `json:"metadata,omitempty"`
   671  	Items           []OpsRequest `json:"items"`
   672  }
   673  
   674  func init() {
   675  	SchemeBuilder.Register(&OpsRequest{}, &OpsRequestList{})
   676  }
   677  
   678  // GetRestartComponentNameSet gets the component name map with restart operation.
   679  func (r OpsRequestSpec) GetRestartComponentNameSet() ComponentNameSet {
   680  	set := make(ComponentNameSet)
   681  	for _, v := range r.RestartList {
   682  		set[v.ComponentName] = struct{}{}
   683  	}
   684  	return set
   685  }
   686  
   687  // GetSwitchoverComponentNameSet gets the component name map with switchover operation.
   688  func (r OpsRequestSpec) GetSwitchoverComponentNameSet() ComponentNameSet {
   689  	set := make(ComponentNameSet)
   690  	for _, v := range r.SwitchoverList {
   691  		set[v.ComponentName] = struct{}{}
   692  	}
   693  	return set
   694  }
   695  
   696  // GetVerticalScalingComponentNameSet gets the component name map with vertical scaling operation.
   697  func (r OpsRequestSpec) GetVerticalScalingComponentNameSet() ComponentNameSet {
   698  	set := make(ComponentNameSet)
   699  	for _, v := range r.VerticalScalingList {
   700  		set[v.ComponentName] = struct{}{}
   701  	}
   702  	return set
   703  }
   704  
   705  // ToVerticalScalingListToMap converts OpsRequest.spec.verticalScaling list to map
   706  func (r OpsRequestSpec) ToVerticalScalingListToMap() map[string]VerticalScaling {
   707  	verticalScalingMap := make(map[string]VerticalScaling)
   708  	for _, v := range r.VerticalScalingList {
   709  		verticalScalingMap[v.ComponentName] = v
   710  	}
   711  	return verticalScalingMap
   712  }
   713  
   714  // GetHorizontalScalingComponentNameSet gets the component name map with horizontal scaling operation.
   715  func (r OpsRequestSpec) GetHorizontalScalingComponentNameSet() ComponentNameSet {
   716  	set := make(ComponentNameSet)
   717  	for _, v := range r.HorizontalScalingList {
   718  		set[v.ComponentName] = struct{}{}
   719  	}
   720  	return set
   721  }
   722  
   723  // ToHorizontalScalingListToMap converts OpsRequest.spec.horizontalScaling list to map
   724  func (r OpsRequestSpec) ToHorizontalScalingListToMap() map[string]HorizontalScaling {
   725  	verticalScalingMap := make(map[string]HorizontalScaling)
   726  	for _, v := range r.HorizontalScalingList {
   727  		verticalScalingMap[v.ComponentName] = v
   728  	}
   729  	return verticalScalingMap
   730  }
   731  
   732  // GetVolumeExpansionComponentNameSet gets the component name map with volume expansion operation.
   733  func (r OpsRequestSpec) GetVolumeExpansionComponentNameSet() ComponentNameSet {
   734  	set := make(ComponentNameSet)
   735  	for _, v := range r.VolumeExpansionList {
   736  		set[v.ComponentName] = struct{}{}
   737  	}
   738  	return set
   739  }
   740  
   741  // GetDataScriptComponentNameSet gets the component name map with switchover operation.
   742  func (r OpsRequestSpec) GetDataScriptComponentNameSet() ComponentNameSet {
   743  	set := make(ComponentNameSet)
   744  	set[r.ScriptSpec.ComponentName] = struct{}{}
   745  	return set
   746  }
   747  
   748  // ToVolumeExpansionListToMap converts volumeExpansionList to map
   749  func (r OpsRequestSpec) ToVolumeExpansionListToMap() map[string]VolumeExpansion {
   750  	volumeExpansionMap := make(map[string]VolumeExpansion)
   751  	for _, v := range r.VolumeExpansionList {
   752  		volumeExpansionMap[v.ComponentName] = v
   753  	}
   754  	return volumeExpansionMap
   755  }
   756  
   757  // ToExposeListToMap build expose map
   758  func (r OpsRequestSpec) ToExposeListToMap() map[string]Expose {
   759  	exposeMap := make(map[string]Expose)
   760  	for _, v := range r.ExposeList {
   761  		exposeMap[v.ComponentName] = v
   762  	}
   763  	return exposeMap
   764  }
   765  
   766  // GetReconfiguringComponentNameSet gets the component name map with reconfiguring operation.
   767  func (r OpsRequestSpec) GetReconfiguringComponentNameSet() ComponentNameSet {
   768  	if r.Reconfigure == nil {
   769  		return nil
   770  	}
   771  	return ComponentNameSet{
   772  		r.Reconfigure.ComponentName: {},
   773  	}
   774  }
   775  
   776  func (r OpsRequestSpec) GetExposeComponentNameSet() ComponentNameSet {
   777  	set := make(ComponentNameSet)
   778  	for _, v := range r.ExposeList {
   779  		set[v.ComponentName] = struct{}{}
   780  	}
   781  	return set
   782  }
   783  
   784  // GetUpgradeComponentNameSet gets the component name map with upgrade operation.
   785  func (r *OpsRequest) GetUpgradeComponentNameSet() ComponentNameSet {
   786  	if r == nil || r.Spec.Upgrade == nil {
   787  		return nil
   788  	}
   789  	set := make(ComponentNameSet)
   790  	for k := range r.Status.Components {
   791  		set[k] = struct{}{}
   792  	}
   793  	return set
   794  }
   795  
   796  // GetComponentNameSet if the operations are within the scope of component, this function should be implemented
   797  func (r *OpsRequest) GetComponentNameSet() ComponentNameSet {
   798  	switch r.Spec.Type {
   799  	case RestartType:
   800  		return r.Spec.GetRestartComponentNameSet()
   801  	case VerticalScalingType:
   802  		return r.Spec.GetVerticalScalingComponentNameSet()
   803  	case HorizontalScalingType:
   804  		return r.Spec.GetHorizontalScalingComponentNameSet()
   805  	case VolumeExpansionType:
   806  		return r.Spec.GetVolumeExpansionComponentNameSet()
   807  	case UpgradeType:
   808  		return r.GetUpgradeComponentNameSet()
   809  	case ReconfiguringType:
   810  		return r.Spec.GetReconfiguringComponentNameSet()
   811  	case ExposeType:
   812  		return r.Spec.GetExposeComponentNameSet()
   813  	case SwitchoverType:
   814  		return r.Spec.GetSwitchoverComponentNameSet()
   815  	case DataScriptType:
   816  		return r.Spec.GetDataScriptComponentNameSet()
   817  	default:
   818  		return nil
   819  	}
   820  }
   821  
   822  func (p *ProgressStatusDetail) SetStatusAndMessage(status ProgressStatus, message string) {
   823  	p.Message = message
   824  	p.Status = status
   825  }