diff --git a/apis/apps/v1/componentdefinition_types.go b/apis/apps/v1/componentdefinition_types.go index f9bb51652d0..5f56af5ed39 100644 --- a/apis/apps/v1/componentdefinition_types.go +++ b/apis/apps/v1/componentdefinition_types.go @@ -401,6 +401,13 @@ type ComponentDefinitionSpec struct { // +optional ReplicasLimit *ReplicasLimit `json:"replicasLimit,omitempty"` + // Specifies the strategies for determining the available status of the Component. + // + // This field is immutable. + // + // +optional + Available *ComponentAvailable `json:"available,omitempty"` + // Enumerate all possible roles assigned to each replica of the Component, influencing its behavior. // // A replica can have zero to multiple roles. @@ -1240,6 +1247,129 @@ type ReplicasLimit struct { MaxReplicas int32 `json:"maxReplicas"` } +// ComponentAvailable defines the strategies for determining whether the component is available. +type ComponentAvailable struct { + // Specifies the phases that the component will go through to be considered available. + // + // This field is immutable once set. + // + // +optional + WithPhases *string `json:"withPhases,omitempty"` + + // Specifies the strategies for determining whether the component is available based on the available probe. + // + // This field is immutable once set. + // + // +optional + WithProbe *ComponentAvailableWithProbe `json:"withProbe,omitempty"` +} + +type ComponentAvailableWithProbe struct { + // This field is immutable once set. + // + // +optional + TimeWindowSeconds *int32 `json:"timeWindowSeconds,omitempty"` + + // Specifies the conditions that the component will go through to be considered available. + // + // This field is immutable once set. + // + // +optional + Condition *ComponentAvailableCondition `json:"condition,omitempty"` + + // A brief description for the condition when the component is available. + // + // +optional + Description string `json:"description,omitempty"` +} + +type ComponentAvailableCondition struct { + ComponentAvailableExpression `json:",inline"` + + // Logical And to combine multiple expressions. + // + // This field is immutable once set. + // + // +optional + And []ComponentAvailableExpression `json:"and,omitempty"` + + // Logical Or to combine multiple expressions. + // + // This field is immutable once set. + // + // +optional + Or []ComponentAvailableExpression `json:"or,omitempty"` + + // Logical Not to negate the expression. + // + // This field is immutable once set. + // + // +optional + Not *ComponentAvailableExpression `json:"not,omitempty"` +} + +type ComponentAvailableExpression struct { + // All replicas must satisfy the assertion. + // + // This field is immutable once set. + // + // +optional + All *ComponentAvailableProbeAssertion `json:"all,omitempty"` + + // At least one replica must satisfy the assertion. + // + // This field is immutable once set. + // + // +optional + Any *ComponentAvailableProbeAssertion `json:"any,omitempty"` + + // None of the replicas must satisfy the assertion. + // + // This field is immutable once set. + // + // +optional + None *ComponentAvailableProbeAssertion `json:"none,omitempty"` + + // Majority replicas must satisfy the assertion. + // + // This field is immutable once set. + // + // +optional + Majority *ComponentAvailableProbeAssertion `json:"majority,omitempty"` +} + +type ComponentAvailableProbeAssertion struct { + ActionAssertion `json:",inline"` + + // Logical And to combine multiple assertions. + // + // This field is immutable once set. + // + // +optional + And []ActionAssertion `json:"and,omitempty"` + + // Logical Or to combine multiple assertions. + // + // This field is immutable once set. + // + // +optional + Or []ActionAssertion `json:"or,omitempty"` + + // Logical Not to negate the assertions. + // + // This field is immutable once set. + // + // +optional + Not *ActionAssertion `json:"not,omitempty"` + + // Specifies whether apply the assertions strictly to all replicas. + // + // This field is immutable once set. + // + // +optional + Strict *bool `json:"strict,omitempty"` +} + // ReplicaRole represents a role that can be assumed by a component instance. type ReplicaRole struct { // Defines the role's identifier. It is used to set the "apps.kubeblocks.io/role" label value @@ -1369,6 +1499,13 @@ type ComponentLifecycleActions struct { // +optional RoleProbe *Probe `json:"roleProbe,omitempty"` + // Defines the procedure which is invoked regularly to assess the availability of the component. + // + // Note: This field is immutable once it has been set. + // + // +optional + AvailableProbe *Probe `json:"availableProbe,omitempty"` + // Defines the procedure for a controlled transition of leadership from the current leader to a new replica. // This approach aims to minimize downtime and maintain availability in systems with a leader-follower topology, // during events such as planned maintenance or when performing stop, shutdown, restart, or upgrade operations @@ -1786,6 +1923,47 @@ type Probe struct { FailureThreshold int32 `json:"failureThreshold,omitempty"` } +// ActionAssertion defines the custom assertions for evaluating the success or failure of an action. +type ActionAssertion struct { + // Whether the action should succeed or fail. + // + // This field is immutable once set. + // + // +optional + Succeed *bool `json:"succeed,omitempty"` + + // Specifies the stdout matcher for the action. + // + // This field is immutable once set. + // + // +optional + Stdout *ActionOutputMatcher `json:"stdout,omitempty"` + + // Specifies the stderr matcher for the action. + // + // This field is immutable once set. + // + // +optional + Stderr *ActionOutputMatcher `json:"stderr,omitempty"` +} + +// ActionOutputMatcher defines the matcher for the output of an action. +type ActionOutputMatcher struct { + // The output of the action should be equal to the specified value. + // + // This field is immutable once set. + // + // +optional + EqualTo *string `json:"equalTo,omitempty"` + + // The output of the action should contain the specified value. + // + // This field is immutable once set. + // + // +optional + Contains *string `json:"contains,omitempty"` +} + // ServiceRefDeclaration represents a reference to a service that can be either provided by a KubeBlocks Cluster // or an external service. // It acts as a placeholder for the actual service reference, which is determined later when a Cluster is created. diff --git a/apis/apps/v1/types.go b/apis/apps/v1/types.go index fc725cb390b..da58b7d75be 100644 --- a/apis/apps/v1/types.go +++ b/apis/apps/v1/types.go @@ -81,6 +81,7 @@ const ( ConditionTypeProvisioningStarted = "ProvisioningStarted" // ConditionTypeProvisioningStarted the operator starts resource provisioning to create or change the cluster ConditionTypeApplyResources = "ApplyResources" // ConditionTypeApplyResources the operator start to apply resources to create or change the cluster ConditionTypeReady = "Ready" // ConditionTypeReady all components and shardings are running + ConditionTypeAvailable = "Available" // ConditionTypeAvailable indicates whether the target object is available for serving. ) type ServiceRef struct { diff --git a/apis/apps/v1/zz_generated.deepcopy.go b/apis/apps/v1/zz_generated.deepcopy.go index d5fca0443ba..8c0d243f383 100644 --- a/apis/apps/v1/zz_generated.deepcopy.go +++ b/apis/apps/v1/zz_generated.deepcopy.go @@ -62,6 +62,61 @@ func (in *Action) DeepCopy() *Action { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActionAssertion) DeepCopyInto(out *ActionAssertion) { + *out = *in + if in.Succeed != nil { + in, out := &in.Succeed, &out.Succeed + *out = new(bool) + **out = **in + } + if in.Stdout != nil { + in, out := &in.Stdout, &out.Stdout + *out = new(ActionOutputMatcher) + (*in).DeepCopyInto(*out) + } + if in.Stderr != nil { + in, out := &in.Stderr, &out.Stderr + *out = new(ActionOutputMatcher) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActionAssertion. +func (in *ActionAssertion) DeepCopy() *ActionAssertion { + if in == nil { + return nil + } + out := new(ActionAssertion) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActionOutputMatcher) DeepCopyInto(out *ActionOutputMatcher) { + *out = *in + if in.EqualTo != nil { + in, out := &in.EqualTo, &out.EqualTo + *out = new(string) + **out = **in + } + if in.Contains != nil { + in, out := &in.Contains, &out.Contains + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActionOutputMatcher. +func (in *ActionOutputMatcher) DeepCopy() *ActionOutputMatcher { + if in == nil { + return nil + } + out := new(ActionOutputMatcher) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Cluster) DeepCopyInto(out *Cluster) { *out = *in @@ -788,6 +843,166 @@ func (in *Component) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComponentAvailable) DeepCopyInto(out *ComponentAvailable) { + *out = *in + if in.WithPhases != nil { + in, out := &in.WithPhases, &out.WithPhases + *out = new(string) + **out = **in + } + if in.WithProbe != nil { + in, out := &in.WithProbe, &out.WithProbe + *out = new(ComponentAvailableWithProbe) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentAvailable. +func (in *ComponentAvailable) DeepCopy() *ComponentAvailable { + if in == nil { + return nil + } + out := new(ComponentAvailable) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComponentAvailableCondition) DeepCopyInto(out *ComponentAvailableCondition) { + *out = *in + in.ComponentAvailableExpression.DeepCopyInto(&out.ComponentAvailableExpression) + if in.And != nil { + in, out := &in.And, &out.And + *out = make([]ComponentAvailableExpression, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Or != nil { + in, out := &in.Or, &out.Or + *out = make([]ComponentAvailableExpression, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Not != nil { + in, out := &in.Not, &out.Not + *out = new(ComponentAvailableExpression) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentAvailableCondition. +func (in *ComponentAvailableCondition) DeepCopy() *ComponentAvailableCondition { + if in == nil { + return nil + } + out := new(ComponentAvailableCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComponentAvailableExpression) DeepCopyInto(out *ComponentAvailableExpression) { + *out = *in + if in.All != nil { + in, out := &in.All, &out.All + *out = new(ComponentAvailableProbeAssertion) + (*in).DeepCopyInto(*out) + } + if in.Any != nil { + in, out := &in.Any, &out.Any + *out = new(ComponentAvailableProbeAssertion) + (*in).DeepCopyInto(*out) + } + if in.None != nil { + in, out := &in.None, &out.None + *out = new(ComponentAvailableProbeAssertion) + (*in).DeepCopyInto(*out) + } + if in.Majority != nil { + in, out := &in.Majority, &out.Majority + *out = new(ComponentAvailableProbeAssertion) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentAvailableExpression. +func (in *ComponentAvailableExpression) DeepCopy() *ComponentAvailableExpression { + if in == nil { + return nil + } + out := new(ComponentAvailableExpression) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComponentAvailableProbeAssertion) DeepCopyInto(out *ComponentAvailableProbeAssertion) { + *out = *in + in.ActionAssertion.DeepCopyInto(&out.ActionAssertion) + if in.And != nil { + in, out := &in.And, &out.And + *out = make([]ActionAssertion, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Or != nil { + in, out := &in.Or, &out.Or + *out = make([]ActionAssertion, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Not != nil { + in, out := &in.Not, &out.Not + *out = new(ActionAssertion) + (*in).DeepCopyInto(*out) + } + if in.Strict != nil { + in, out := &in.Strict, &out.Strict + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentAvailableProbeAssertion. +func (in *ComponentAvailableProbeAssertion) DeepCopy() *ComponentAvailableProbeAssertion { + if in == nil { + return nil + } + out := new(ComponentAvailableProbeAssertion) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComponentAvailableWithProbe) DeepCopyInto(out *ComponentAvailableWithProbe) { + *out = *in + if in.TimeWindowSeconds != nil { + in, out := &in.TimeWindowSeconds, &out.TimeWindowSeconds + *out = new(int32) + **out = **in + } + if in.Condition != nil { + in, out := &in.Condition, &out.Condition + *out = new(ComponentAvailableCondition) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentAvailableWithProbe. +func (in *ComponentAvailableWithProbe) DeepCopy() *ComponentAvailableWithProbe { + if in == nil { + return nil + } + out := new(ComponentAvailableWithProbe) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ComponentConfigSpec) DeepCopyInto(out *ComponentConfigSpec) { *out = *in @@ -966,6 +1181,11 @@ func (in *ComponentDefinitionSpec) DeepCopyInto(out *ComponentDefinitionSpec) { *out = new(ReplicasLimit) **out = **in } + if in.Available != nil { + in, out := &in.Available, &out.Available + *out = new(ComponentAvailable) + (*in).DeepCopyInto(*out) + } if in.Roles != nil { in, out := &in.Roles, &out.Roles *out = make([]ReplicaRole, len(*in)) @@ -1050,6 +1270,11 @@ func (in *ComponentLifecycleActions) DeepCopyInto(out *ComponentLifecycleActions *out = new(Probe) (*in).DeepCopyInto(*out) } + if in.AvailableProbe != nil { + in, out := &in.AvailableProbe, &out.AvailableProbe + *out = new(Probe) + (*in).DeepCopyInto(*out) + } if in.Switchover != nil { in, out := &in.Switchover, &out.Switchover *out = new(Action) diff --git a/config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml b/config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml index 54164157d4a..d43b2f699de 100644 --- a/config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml +++ b/config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml @@ -100,335 +100,4722 @@ spec: This field is immutable. type: object - configs: + available: description: |- - Specifies the configuration file templates and volume mount parameters used by the Component. - It also includes descriptions of the parameters in the ConfigMaps, such as value range limitations. + Specifies the strategies for determining the available status of the Component. - This field specifies a list of templates that will be rendered into Component containers' configuration files. - Each template is represented as a ConfigMap and may contain multiple configuration files, - with each file being a key in the ConfigMap. + This field is immutable. + properties: + withPhases: + description: |- + Specifies the phases that the component will go through to be considered available. - The rendered configuration files will be mounted into the Component's containers - according to the specified volume mount parameters. + This field is immutable once set. + type: string + withProbe: + description: |- + Specifies the strategies for determining whether the component is available based on the available probe. - This field is immutable. - items: - properties: - asEnvFrom: - description: |- - Specifies the containers to inject the ConfigMap parameters as environment variables. + This field is immutable once set. + properties: + condition: + description: |- + Specifies the conditions that the component will go through to be considered available. - This is useful when application images accept parameters through environment variables and - generate the final configuration file in the startup script based on these variables. + This field is immutable once set. + properties: + all: + description: |- + All replicas must satisfy the assertion. - This field allows users to specify a list of container names, and KubeBlocks will inject the environment - variables converted from the ConfigMap into these designated containers. This provides a flexible way to - pass the configuration items from the ConfigMap to the container without modifying the image. + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. - Deprecated: `asEnvFrom` has been deprecated since 0.9.0 and will be removed in 0.10.0. - Use `injectEnvTo` instead. - items: - type: string - type: array - x-kubernetes-list-type: set - asSecret: - description: Whether to store the final rendered parameters - as a secret. - type: boolean - constraintRef: - description: Specifies the name of the referenced configuration - constraints object. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - defaultMode: - description: |- - The operator attempts to set default file permissions for scripts (0555) and configurations (0444). - However, certain database engines may require different file permissions. - You can specify the desired file permissions here. + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. - Must be specified as an octal value between 0000 and 0777 (inclusive), - or as a decimal value between 0 and 511 (inclusive). - YAML supports both octal and decimal values for file permissions. + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. - Please note that this setting only affects the permissions of the files themselves. - Directories within the specified path are not impacted by this setting. - It's important to be aware that this setting might conflict with other options - that influence the file mode, such as fsGroup. - In such cases, the resulting file mode may have additional bits set. - Refers to documents of k8s.ConfigMapVolumeSource.defaultMode for more information. - format: int32 - type: integer - injectEnvTo: - description: |- - Specifies the containers to inject the ConfigMap parameters as environment variables. + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. - This is useful when application images accept parameters through environment variables and - generate the final configuration file in the startup script based on these variables. + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. - This field allows users to specify a list of container names, and KubeBlocks will inject the environment - variables converted from the ConfigMap into these designated containers. This provides a flexible way to - pass the configuration items from the ConfigMap to the container without modifying the image. - items: - type: string - type: array - x-kubernetes-list-type: set - keys: - description: |- - Specifies the configuration files within the ConfigMap that support dynamic updates. + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. - A configuration template (provided in the form of a ConfigMap) may contain templates for multiple - configuration files. - Each configuration file corresponds to a key in the ConfigMap. - Some of these configuration files may support dynamic modification and reloading without requiring - a pod restart. + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. - If empty or omitted, all configuration files in the ConfigMap are assumed to support dynamic updates, - and ConfigConstraint applies to all keys. - items: - type: string - type: array - x-kubernetes-list-type: set - legacyRenderedConfigSpec: - description: |- - Specifies the secondary rendered config spec for pod-specific customization. + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. - The template is rendered inside the pod (by the "config-manager" sidecar container) and merged with the main - template's render result to generate the final configuration file. + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. - This field is intended to handle scenarios where different pods within the same Component have - varying configurations. It allows for pod-specific customization of the configuration. + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. - Note: This field will be deprecated in future versions, and the functionality will be moved to - `cluster.spec.componentSpecs[*].instances[*]`. - properties: - namespace: - default: default - description: |- - Specifies the namespace of the referenced configuration template ConfigMap object. - An empty namespace is equivalent to the "default" namespace. - pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ - type: string - policy: - default: none - description: Defines the strategy for merging externally - imported templates into component templates. - enum: - - patch - - replace - - none - type: string - templateRef: - description: Specifies the name of the referenced configuration - template ConfigMap object. - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - required: - - templateRef - type: object - name: - description: Specifies the name of the configuration template. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - namespace: - default: default - description: |- - Specifies the namespace of the referenced configuration template ConfigMap object. - An empty namespace is equivalent to the "default" namespace. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ - type: string - reRenderResourceTypes: - description: |- - Specifies whether the configuration needs to be re-rendered after v-scale or h-scale operations to reflect changes. + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + and: + description: |- + Logical And to combine multiple expressions. + + + This field is immutable once set. + items: + properties: + all: + description: |- + All replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + any: + description: |- + At least one replica must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + majority: + description: |- + Majority replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + none: + description: |- + None of the replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: object + type: array + any: + description: |- + At least one replica must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + majority: + description: |- + Majority replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + none: + description: |- + None of the replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + not: + description: |- + Logical Not to negate the expression. + + + This field is immutable once set. + properties: + all: + description: |- + All replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + any: + description: |- + At least one replica must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + majority: + description: |- + Majority replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + none: + description: |- + None of the replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: object + or: + description: |- + Logical Or to combine multiple expressions. + + + This field is immutable once set. + items: + properties: + all: + description: |- + All replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + any: + description: |- + At least one replica must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + majority: + description: |- + Majority replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + none: + description: |- + None of the replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: object + type: array + type: object + description: + description: A brief description for the condition when the + component is available. + type: string + timeWindowSeconds: + description: This field is immutable once set. + format: int32 + type: integer + type: object + type: object + configs: + description: |- + Specifies the configuration file templates and volume mount parameters used by the Component. + It also includes descriptions of the parameters in the ConfigMaps, such as value range limitations. + + + This field specifies a list of templates that will be rendered into Component containers' configuration files. + Each template is represented as a ConfigMap and may contain multiple configuration files, + with each file being a key in the ConfigMap. + + + The rendered configuration files will be mounted into the Component's containers + according to the specified volume mount parameters. + + + This field is immutable. + items: + properties: + asEnvFrom: + description: |- + Specifies the containers to inject the ConfigMap parameters as environment variables. + + + This is useful when application images accept parameters through environment variables and + generate the final configuration file in the startup script based on these variables. + + + This field allows users to specify a list of container names, and KubeBlocks will inject the environment + variables converted from the ConfigMap into these designated containers. This provides a flexible way to + pass the configuration items from the ConfigMap to the container without modifying the image. + + + Deprecated: `asEnvFrom` has been deprecated since 0.9.0 and will be removed in 0.10.0. + Use `injectEnvTo` instead. + items: + type: string + type: array + x-kubernetes-list-type: set + asSecret: + description: Whether to store the final rendered parameters + as a secret. + type: boolean + constraintRef: + description: Specifies the name of the referenced configuration + constraints object. + maxLength: 63 + pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ + type: string + defaultMode: + description: |- + The operator attempts to set default file permissions for scripts (0555) and configurations (0444). + However, certain database engines may require different file permissions. + You can specify the desired file permissions here. + + + Must be specified as an octal value between 0000 and 0777 (inclusive), + or as a decimal value between 0 and 511 (inclusive). + YAML supports both octal and decimal values for file permissions. + + + Please note that this setting only affects the permissions of the files themselves. + Directories within the specified path are not impacted by this setting. + It's important to be aware that this setting might conflict with other options + that influence the file mode, such as fsGroup. + In such cases, the resulting file mode may have additional bits set. + Refers to documents of k8s.ConfigMapVolumeSource.defaultMode for more information. + format: int32 + type: integer + injectEnvTo: + description: |- + Specifies the containers to inject the ConfigMap parameters as environment variables. + + + This is useful when application images accept parameters through environment variables and + generate the final configuration file in the startup script based on these variables. + + + This field allows users to specify a list of container names, and KubeBlocks will inject the environment + variables converted from the ConfigMap into these designated containers. This provides a flexible way to + pass the configuration items from the ConfigMap to the container without modifying the image. + items: + type: string + type: array + x-kubernetes-list-type: set + keys: + description: |- + Specifies the configuration files within the ConfigMap that support dynamic updates. + + + A configuration template (provided in the form of a ConfigMap) may contain templates for multiple + configuration files. + Each configuration file corresponds to a key in the ConfigMap. + Some of these configuration files may support dynamic modification and reloading without requiring + a pod restart. + + + If empty or omitted, all configuration files in the ConfigMap are assumed to support dynamic updates, + and ConfigConstraint applies to all keys. + items: + type: string + type: array + x-kubernetes-list-type: set + legacyRenderedConfigSpec: + description: |- + Specifies the secondary rendered config spec for pod-specific customization. + + + The template is rendered inside the pod (by the "config-manager" sidecar container) and merged with the main + template's render result to generate the final configuration file. + + + This field is intended to handle scenarios where different pods within the same Component have + varying configurations. It allows for pod-specific customization of the configuration. + + + Note: This field will be deprecated in future versions, and the functionality will be moved to + `cluster.spec.componentSpecs[*].instances[*]`. + properties: + namespace: + default: default + description: |- + Specifies the namespace of the referenced configuration template ConfigMap object. + An empty namespace is equivalent to the "default" namespace. + pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ + type: string + policy: + default: none + description: Defines the strategy for merging externally + imported templates into component templates. + enum: + - patch + - replace + - none + type: string + templateRef: + description: Specifies the name of the referenced configuration + template ConfigMap object. + pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ + type: string + required: + - templateRef + type: object + name: + description: Specifies the name of the configuration template. + maxLength: 63 + pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ + type: string + namespace: + default: default + description: |- + Specifies the namespace of the referenced configuration template ConfigMap object. + An empty namespace is equivalent to the "default" namespace. + maxLength: 63 + pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ + type: string + reRenderResourceTypes: + description: |- + Specifies whether the configuration needs to be re-rendered after v-scale or h-scale operations to reflect changes. + + + In some scenarios, the configuration may need to be updated to reflect the changes in resource allocation + or cluster topology. Examples: + + + - Redis: adjust maxmemory after v-scale operation. + - MySQL: increase max connections after v-scale operation. + - Zookeeper: update zoo.cfg with new node addresses after h-scale operation. + items: + description: RerenderResourceType defines the resource requirements + for a component. + enum: + - vscale + - hscale + - tls + type: string + type: array + x-kubernetes-list-type: set + templateRef: + description: Specifies the name of the referenced configuration + template ConfigMap object. + maxLength: 63 + pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ + type: string + volumeName: + description: |- + Refers to the volume name of PodTemplate. The configuration file produced through the configuration + template will be mounted to the corresponding volume. Must be a DNS_LABEL name. + The volume name must be defined in podSpec.containers[*].volumeMounts. + maxLength: 63 + pattern: ^[a-z]([a-z0-9\-]*[a-z0-9])?$ + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + description: + description: |- + Provides a brief and concise explanation of the Component's purpose, functionality, and any relevant details. + It serves as a quick reference for users to understand the Component's role and characteristics. + maxLength: 256 + type: string + exporter: + description: Defines the built-in metrics exporter container. + properties: + containerName: + description: Specifies the name of the built-in metrics exporter + container. + type: string + scrapePath: + description: |- + Specifies the http/https url path to scrape for metrics. + If empty, Prometheus uses the default value (e.g. `/metrics`). + type: string + scrapePort: + description: Specifies the port name to scrape for metrics. + type: string + scrapeScheme: + description: |- + Specifies the schema to use for scraping. + `http` and `https` are the expected values unless you rewrite the `__scheme__` label via relabeling. + If empty, Prometheus uses the default value `http`. + enum: + - http + - https + type: string + type: object + hostNetwork: + description: |- + Specifies the host network configuration for the Component. + + + When `hostNetwork` option is enabled, the Pods share the host's network namespace and can directly access + the host's network interfaces. + This means that if multiple Pods need to use the same port, they cannot run on the same host simultaneously + due to port conflicts. + + + The DNSPolicy field in the Pod spec determines how containers within the Pod perform DNS resolution. + When using hostNetwork, the operator will set the DNSPolicy to 'ClusterFirstWithHostNet'. + With this policy, DNS queries will first go through the K8s cluster's DNS service. + If the query fails, it will fall back to the host's DNS settings. + + + If set, the DNS policy will be automatically set to "ClusterFirstWithHostNet". + + + This field is immutable. + properties: + containerPorts: + description: The list of container ports that are required by + the component. + items: + properties: + container: + description: Container specifies the target container within + the Pod. + type: string + ports: + description: |- + Ports are named container ports within the specified container. + These container ports must be defined in the container for proper port allocation. + items: + type: string + minItems: 1 + type: array + required: + - container + - ports + type: object + type: array + type: object + labels: + additionalProperties: + type: string + description: |- + Specifies static labels that will be patched to all Kubernetes resources created for the Component. + + + Note: If a label key in the `labels` field conflicts with any system labels or user-specified labels, + it will be silently ignored to avoid overriding higher-priority labels. + + + This field is immutable. + type: object + lifecycleActions: + description: |- + Defines a set of hooks and procedures that customize the behavior of a Component throughout its lifecycle. + Actions are triggered at specific lifecycle stages: + + + - `postProvision`: Defines the hook to be executed after the creation of a Component, + with `preCondition` specifying when the action should be fired relative to the Component's lifecycle stages: + `Immediately`, `RuntimeReady`, `ComponentReady`, and `ClusterReady`. + - `preTerminate`: Defines the hook to be executed before terminating a Component. + - `roleProbe`: Defines the procedure which is invoked regularly to assess the role of replicas. + - `switchover`: Defines the procedure for a controlled transition of leadership from the current leader to a new replica. + This approach aims to minimize downtime and maintain availability in systems with a leader-follower topology, + such as before planned maintenance or upgrades on the current leader node. + - `memberJoin`: Defines the procedure to add a new replica to the replication group. + - `memberLeave`: Defines the method to remove a replica from the replication group. + - `readOnly`: Defines the procedure to switch a replica into the read-only state. + - `readWrite`: transition a replica from the read-only state back to the read-write state. + - `dataDump`: Defines the procedure to export the data from a replica. + - `dataLoad`: Defines the procedure to import data into a replica. + - `reconfigure`: Defines the procedure that update a replica with new configuration file. + - `accountProvision`: Defines the procedure to generate a new database account. + + + This field is immutable. + properties: + accountProvision: + description: |- + Defines the procedure to generate a new database account. + + + Use Case: + This action is designed to create system accounts that are utilized for replication, monitoring, backup, + and other administrative tasks. + + + The container executing this action has access to following variables: + + + - KB_ACCOUNT_NAME: The name of the system account to be created. + - KB_ACCOUNT_PASSWORD: The password for the system account. // TODO: how to pass the password securely? + - KB_ACCOUNT_STATEMENT: The statement used to create the system account. + + + Note: This field is immutable once it has been set. + properties: + exec: + description: |- + Defines the command to run. + + + This field cannot be updated. + properties: + args: + description: Args represents the arguments that are passed + to the `command` for execution. + items: + type: string + type: array + command: + description: |- + Specifies the command to be executed inside the container. + The working directory for this command is the container's root directory('/'). + Commands are executed directly without a shell environment, meaning shell-specific syntax ('|', etc.) is not supported. + If the shell is required, it must be explicitly invoked in the command. + + + A successful execution is indicated by an exit status of 0; any non-zero status signifies a failure. + items: + type: string + type: array + container: + description: |- + Specifies the name of the container within the same pod whose resources will be shared with the action. + This allows the action to utilize the specified container's resources without executing within it. + + + The name must match one of the containers defined in `componentDefinition.spec.runtime`. + + + The resources that can be shared are included: + + + - volume mounts + + + This field cannot be updated. + type: string + env: + description: |- + Represents a list of environment variables that will be injected into the container. + These variables enable the container to adapt its behavior based on the environment it's running in. + + + This field cannot be updated. + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid? + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for + volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the + pod's namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid? + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: |- + Specifies the container image to be used for running the Action. - In some scenarios, the configuration may need to be updated to reflect the changes in resource allocation - or cluster topology. Examples: + When specified, a dedicated container will be created using this image to execute the Action. + All actions with same image will share the same container. - - Redis: adjust maxmemory after v-scale operation. - - MySQL: increase max connections after v-scale operation. - - Zookeeper: update zoo.cfg with new node addresses after h-scale operation. - items: - description: RerenderResourceType defines the resource requirements - for a component. - enum: - - vscale - - hscale - - tls - type: string - type: array - x-kubernetes-list-type: set - templateRef: - description: Specifies the name of the referenced configuration - template ConfigMap object. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - volumeName: - description: |- - Refers to the volume name of PodTemplate. The configuration file produced through the configuration - template will be mounted to the corresponding volume. Must be a DNS_LABEL name. - The volume name must be defined in podSpec.containers[*].volumeMounts. - maxLength: 63 - pattern: ^[a-z]([a-z0-9\-]*[a-z0-9])?$ - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - description: - description: |- - Provides a brief and concise explanation of the Component's purpose, functionality, and any relevant details. - It serves as a quick reference for users to understand the Component's role and characteristics. - maxLength: 256 - type: string - exporter: - description: Defines the built-in metrics exporter container. - properties: - containerName: - description: Specifies the name of the built-in metrics exporter - container. - type: string - scrapePath: - description: |- - Specifies the http/https url path to scrape for metrics. - If empty, Prometheus uses the default value (e.g. `/metrics`). - type: string - scrapePort: - description: Specifies the port name to scrape for metrics. - type: string - scrapeScheme: - description: |- - Specifies the schema to use for scraping. - `http` and `https` are the expected values unless you rewrite the `__scheme__` label via relabeling. - If empty, Prometheus uses the default value `http`. - enum: - - http - - https - type: string - type: object - hostNetwork: - description: |- - Specifies the host network configuration for the Component. + This field cannot be updated. + type: string + matchingKey: + description: |- + Used in conjunction with the `targetPodSelector` field to refine the selection of target pod(s) for Action execution. + The impact of this field depends on the `targetPodSelector` value: - When `hostNetwork` option is enabled, the Pods share the host's network namespace and can directly access - the host's network interfaces. - This means that if multiple Pods need to use the same port, they cannot run on the same host simultaneously - due to port conflicts. + - When `targetPodSelector` is set to `Any` or `All`, this field will be ignored. + - When `targetPodSelector` is set to `Role`, only those replicas whose role matches the `matchingKey` + will be selected for the Action. - The DNSPolicy field in the Pod spec determines how containers within the Pod perform DNS resolution. - When using hostNetwork, the operator will set the DNSPolicy to 'ClusterFirstWithHostNet'. - With this policy, DNS queries will first go through the K8s cluster's DNS service. - If the query fails, it will fall back to the host's DNS settings. + This field cannot be updated. + type: string + targetPodSelector: + description: |- + Defines the criteria used to select the target Pod(s) for executing the Action. + This is useful when there is no default target replica identified. + It allows for precise control over which Pod(s) the Action should run in. - If set, the DNS policy will be automatically set to "ClusterFirstWithHostNet". + If not specified, the Action will be executed in the pod where the Action is triggered, such as the pod + to be removed or added; or a random pod if the Action is triggered at the component level, such as + post-provision or pre-terminate of the component. - This field is immutable. - properties: - containerPorts: - description: The list of container ports that are required by - the component. - items: - properties: - container: - description: Container specifies the target container within - the Pod. - type: string - ports: - description: |- - Ports are named container ports within the specified container. - These container ports must be defined in the container for proper port allocation. - items: + This field cannot be updated. + enum: + - Any + - All + - Role + - Ordinal type: string - minItems: 1 - type: array - required: - - container - - ports - type: object - type: array - type: object - labels: - additionalProperties: - type: string - description: |- - Specifies static labels that will be patched to all Kubernetes resources created for the Component. + type: object + preCondition: + description: |- + Specifies the state that the cluster must reach before the Action is executed. + Currently, this is only applicable to the `postProvision` action. - Note: If a label key in the `labels` field conflicts with any system labels or user-specified labels, - it will be silently ignored to avoid overriding higher-priority labels. + The conditions are as follows: - This field is immutable. - type: object - lifecycleActions: - description: |- - Defines a set of hooks and procedures that customize the behavior of a Component throughout its lifecycle. - Actions are triggered at specific lifecycle stages: + - `Immediately`: Executed right after the Component object is created. + The readiness of the Component and its resources is not guaranteed at this stage. + - `RuntimeReady`: The Action is triggered after the Component object has been created and all associated + runtime resources (e.g. Pods) are in a ready state. + - `ComponentReady`: The Action is triggered after the Component itself is in a ready state. + This process does not affect the readiness state of the Component or the Cluster. + - `ClusterReady`: The Action is executed after the Cluster is in a ready state. + This execution does not alter the Component or the Cluster's state of readiness. - - `postProvision`: Defines the hook to be executed after the creation of a Component, - with `preCondition` specifying when the action should be fired relative to the Component's lifecycle stages: - `Immediately`, `RuntimeReady`, `ComponentReady`, and `ClusterReady`. - - `preTerminate`: Defines the hook to be executed before terminating a Component. - - `roleProbe`: Defines the procedure which is invoked regularly to assess the role of replicas. - - `switchover`: Defines the procedure for a controlled transition of leadership from the current leader to a new replica. - This approach aims to minimize downtime and maintain availability in systems with a leader-follower topology, - such as before planned maintenance or upgrades on the current leader node. - - `memberJoin`: Defines the procedure to add a new replica to the replication group. - - `memberLeave`: Defines the method to remove a replica from the replication group. - - `readOnly`: Defines the procedure to switch a replica into the read-only state. - - `readWrite`: transition a replica from the read-only state back to the read-write state. - - `dataDump`: Defines the procedure to export the data from a replica. - - `dataLoad`: Defines the procedure to import data into a replica. - - `reconfigure`: Defines the procedure that update a replica with new configuration file. - - `accountProvision`: Defines the procedure to generate a new database account. + This field cannot be updated. + type: string + retryPolicy: + description: |- + Defines the strategy to be taken when retrying the Action after a failure. - This field is immutable. - properties: - accountProvision: - description: |- - Defines the procedure to generate a new database account. + It specifies the conditions under which the Action should be retried and the limits to apply, + such as the maximum number of retries and backoff strategy. - Use Case: - This action is designed to create system accounts that are utilized for replication, monitoring, backup, - and other administrative tasks. + This field cannot be updated. + properties: + maxRetries: + default: 0 + description: |- + Defines the maximum number of retry attempts that should be made for a given Action. + This value is set to 0 by default, indicating that no retries will be made. + type: integer + retryInterval: + default: 0 + description: |- + Indicates the duration of time to wait between each retry attempt. + This value is set to 0 by default, indicating that there will be no delay between retry attempts. + format: int64 + type: integer + type: object + timeoutSeconds: + default: 0 + description: |- + Specifies the maximum duration in seconds that the Action is allowed to run. - The container executing this action has access to following variables: + If the Action does not complete within this time frame, it will be terminated. - - KB_ACCOUNT_NAME: The name of the system account to be created. - - KB_ACCOUNT_PASSWORD: The password for the system account. // TODO: how to pass the password securely? - - KB_ACCOUNT_STATEMENT: The statement used to create the system account. + This field cannot be updated. + format: int32 + type: integer + type: object + availableProbe: + description: |- + Defines the procedure which is invoked regularly to assess the availability of the component. Note: This field is immutable once it has been set. @@ -639,6 +5026,24 @@ spec: - Ordinal type: string type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + initialDelaySeconds: + description: |- + Specifies the number of seconds to wait after the container has started before the RoleProbe + begins to detect the container's role. + format: int32 + type: integer + periodSeconds: + description: |- + Specifies the frequency at which the probe is conducted. This value is expressed in seconds. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -685,6 +5090,12 @@ spec: format: int64 type: integer type: object + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Minimum value is 1. + format: int32 + type: integer timeoutSeconds: default: 0 description: |- diff --git a/controllers/apps/componentdefinition_controller.go b/controllers/apps/componentdefinition_controller.go index aa76acf7a06..508e62d071a 100644 --- a/controllers/apps/componentdefinition_controller.go +++ b/controllers/apps/componentdefinition_controller.go @@ -33,6 +33,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/rand" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -184,17 +185,18 @@ func (r *ComponentDefinitionReconciler) validate(cli client.Client, rctx intctrl cmpd *appsv1.ComponentDefinition) error { for _, validator := range []func(client.Client, intctrlutil.RequestCtx, *appsv1.ComponentDefinition) error{ r.validateServiceVersion, + r.validateLabels, r.validateRuntime, r.validateVars, r.validateVolumes, r.validateHostNetwork, r.validateServices, r.validateConfigs, - r.validatePolicyRules, - r.validateLabels, - r.validateReplicasLimit, r.validateSystemAccounts, + r.validateReplicasLimit, + r.validateAvailable, r.validateReplicaRoles, + r.validatePolicyRules, r.validateLifecycleActions, } { if err := validator(cli, rctx, cmpd); err != nil { @@ -209,6 +211,11 @@ func (r *ComponentDefinitionReconciler) validateServiceVersion(cli client.Client return validateServiceVersion(cmpd.Spec.ServiceVersion) } +func (r *ComponentDefinitionReconciler) validateLabels(cli client.Client, rctx intctrlutil.RequestCtx, + cmpd *appsv1.ComponentDefinition) error { + return nil +} + func (r *ComponentDefinitionReconciler) validateRuntime(cli client.Client, rctx intctrlutil.RequestCtx, cmpd *appsv1.ComponentDefinition) error { return nil @@ -326,22 +333,6 @@ func (r *ComponentDefinitionReconciler) validateConfigs(cli client.Client, rctx return appsconfig.ReconcileConfigSpecsForReferencedCR(cli, rctx, compDef) } -func (r *ComponentDefinitionReconciler) validatePolicyRules(cli client.Client, rctx intctrlutil.RequestCtx, - cmpd *appsv1.ComponentDefinition) error { - // TODO: how to check the acquired rules can be granted? - return nil -} - -func (r *ComponentDefinitionReconciler) validateLabels(cli client.Client, rctx intctrlutil.RequestCtx, - cmpd *appsv1.ComponentDefinition) error { - return nil -} - -func (r *ComponentDefinitionReconciler) validateReplicasLimit(cli client.Client, rctx intctrlutil.RequestCtx, - cmpd *appsv1.ComponentDefinition) error { - return nil -} - func (r *ComponentDefinitionReconciler) validateSystemAccounts(cli client.Client, rctx intctrlutil.RequestCtx, cmpd *appsv1.ComponentDefinition) error { for _, v := range cmpd.Spec.SystemAccounts { @@ -360,6 +351,52 @@ func (r *ComponentDefinitionReconciler) validateSystemAccounts(cli client.Client return nil } +func (r *ComponentDefinitionReconciler) validateReplicasLimit(cli client.Client, rctx intctrlutil.RequestCtx, + cmpd *appsv1.ComponentDefinition) error { + return nil +} + +func (r *ComponentDefinitionReconciler) validateAvailable(cli client.Client, rctx intctrlutil.RequestCtx, + cmpd *appsv1.ComponentDefinition) error { + if cmpd.Spec.Available == nil { + return nil + } + if cmpd.Spec.Available.WithPhases != nil && cmpd.Spec.Available.WithProbe == nil { + return r.validateAvailableWithPhases(cmpd) + } + return r.validateAvailableWithProbe(cmpd) +} + +func (r *ComponentDefinitionReconciler) validateAvailableWithPhases(cmpd *appsv1.ComponentDefinition) error { + phases := sets.New[string](strings.Split(strings.ToLower(*cmpd.Spec.Available.WithPhases), ",")...) + supported := sets.New[string]( + strings.ToLower(string(appsv1.CreatingClusterCompPhase)), + strings.ToLower(string(appsv1.RunningClusterCompPhase)), + strings.ToLower(string(appsv1.UpdatingClusterCompPhase)), + strings.ToLower(string(appsv1.StoppingClusterCompPhase)), + strings.ToLower(string(appsv1.StoppedClusterCompPhase)), + strings.ToLower(string(appsv1.DeletingClusterCompPhase)), + strings.ToLower(string(appsv1.FailedClusterCompPhase)), + strings.ToLower(string(appsv1.AbnormalClusterCompPhase)), + ) + result := phases.Difference(supported) + if result.Len() > 0 { + return fmt.Errorf("unsupported phases are specified: %s", strings.Join(sets.List(result), ",")) + } + return nil +} + +func (r *ComponentDefinitionReconciler) validateAvailableWithProbe(cmpd *appsv1.ComponentDefinition) error { + withProbe := cmpd.Spec.Available.WithProbe + if withProbe == nil { + return nil + } + if cmpd.Spec.LifecycleActions == nil || cmpd.Spec.LifecycleActions.AvailableProbe == nil { + return fmt.Errorf("the available probe is required to be defined when withProbe of available is specified") + } + return nil +} + func (r *ComponentDefinitionReconciler) validateReplicaRoles(cli client.Client, reqCtx intctrlutil.RequestCtx, cmpd *appsv1.ComponentDefinition) error { if !checkUniqueItemWithValue(cmpd.Spec.Roles, "Name", nil) { @@ -368,6 +405,12 @@ func (r *ComponentDefinitionReconciler) validateReplicaRoles(cli client.Client, return nil } +func (r *ComponentDefinitionReconciler) validatePolicyRules(cli client.Client, rctx intctrlutil.RequestCtx, + cmpd *appsv1.ComponentDefinition) error { + // TODO: how to check the acquired rules can be granted? + return nil +} + func (r *ComponentDefinitionReconciler) validateLifecycleActions(cli client.Client, reqCtx intctrlutil.RequestCtx, cmpd *appsv1.ComponentDefinition) error { return nil diff --git a/controllers/apps/componentdefinition_controller_test.go b/controllers/apps/componentdefinition_controller_test.go index a5c3b40b38e..f776a43f7e1 100644 --- a/controllers/apps/componentdefinition_controller_test.go +++ b/controllers/apps/componentdefinition_controller_test.go @@ -28,6 +28,7 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + "k8s.io/utils/pointer" "sigs.k8s.io/controller-runtime/pkg/client" kbappsv1 "github.com/apecloud/kubeblocks/apis/apps/v1" @@ -308,33 +309,6 @@ var _ = Describe("ComponentDefinition Controller", func() { }) }) - Context("replica roles", func() { - It("ok", func() { - By("create a ComponentDefinition obj") - componentDefObj := testapps.NewComponentDefinitionFactory(componentDefName). - SetRuntime(nil). - AddRole("leader", true, true). - AddRole("follower", true, false). - AddRole("learner", false, false). - Create(&testCtx).GetObject() - - checkObjectStatus(componentDefObj, kbappsv1.AvailablePhase) - }) - - It("duplicate roles", func() { - By("create a ComponentDefinition obj") - componentDefObj := testapps.NewComponentDefinitionFactory(componentDefName). - SetRuntime(nil). - AddRole("leader", true, true). - AddRole("follower", true, false). - AddRole("learner", false, false). - AddRole("learner", true, false). - Create(&testCtx).GetObject() - - checkObjectStatus(componentDefObj, kbappsv1.UnavailablePhase) - }) - }) - Context("vars", func() { It("ok", func() { By("create a ComponentDefinition obj") @@ -404,6 +378,91 @@ var _ = Describe("ComponentDefinition Controller", func() { }) }) + Context("available", func() { + It("with phases - ok", func() { + By("create a ComponentDefinition obj") + componentDefObj := testapps.NewComponentDefinitionFactory(componentDefName). + SetRuntime(nil). + SetAvailable(&kbappsv1.ComponentAvailable{ + WithPhases: pointer.String(fmt.Sprintf("%s,%s", + string(kbappsv1.RunningClusterCompPhase), string(kbappsv1.UpdatingClusterCompPhase))), + }). + Create(&testCtx). + GetObject() + + checkObjectStatus(componentDefObj, kbappsv1.AvailablePhase) + }) + + It("with phases - fail", func() { + By("create a ComponentDefinition obj") + componentDefObj := testapps.NewComponentDefinitionFactory(componentDefName). + SetRuntime(nil). + SetAvailable(&kbappsv1.ComponentAvailable{ + // empty phase + WithPhases: pointer.String(fmt.Sprintf("%s,%s", string(kbappsv1.RunningClusterCompPhase), "")), + }). + Create(&testCtx). + GetObject() + + checkObjectStatus(componentDefObj, kbappsv1.UnavailablePhase) + }) + + It("with probe - ok", func() { + By("create a ComponentDefinition obj") + componentDefObj := testapps.NewComponentDefinitionFactory(componentDefName). + SetRuntime(nil). + SetAvailable(&kbappsv1.ComponentAvailable{ + WithProbe: &kbappsv1.ComponentAvailableWithProbe{}, + }). + SetLifecycleAction("availableProbe", &kbappsv1.Probe{}). + Create(&testCtx). + GetObject() + + checkObjectStatus(componentDefObj, kbappsv1.AvailablePhase) + }) + + It("with probe - fail", func() { + By("create a ComponentDefinition obj") + componentDefObj := testapps.NewComponentDefinitionFactory(componentDefName). + SetRuntime(nil). + SetAvailable(&kbappsv1.ComponentAvailable{ + WithProbe: &kbappsv1.ComponentAvailableWithProbe{}, + }). + // without available probe + Create(&testCtx). + GetObject() + + checkObjectStatus(componentDefObj, kbappsv1.UnavailablePhase) + }) + }) + + Context("replica roles", func() { + It("ok", func() { + By("create a ComponentDefinition obj") + componentDefObj := testapps.NewComponentDefinitionFactory(componentDefName). + SetRuntime(nil). + AddRole("leader", true, true). + AddRole("follower", true, false). + AddRole("learner", false, false). + Create(&testCtx).GetObject() + + checkObjectStatus(componentDefObj, kbappsv1.AvailablePhase) + }) + + It("duplicate roles", func() { + By("create a ComponentDefinition obj") + componentDefObj := testapps.NewComponentDefinitionFactory(componentDefName). + SetRuntime(nil). + AddRole("leader", true, true). + AddRole("follower", true, false). + AddRole("learner", false, false). + AddRole("learner", true, false). + Create(&testCtx).GetObject() + + checkObjectStatus(componentDefObj, kbappsv1.UnavailablePhase) + }) + }) + Context("immutable", func() { newCmpdFn := func(processor func(*testapps.MockComponentDefinitionFactory)) *kbappsv1.ComponentDefinition { By("create a ComponentDefinition obj") diff --git a/controllers/apps/transformer_cluster_status.go b/controllers/apps/transformer_cluster_status.go index 5acfabbc469..aa25ad5e201 100644 --- a/controllers/apps/transformer_cluster_status.go +++ b/controllers/apps/transformer_cluster_status.go @@ -85,29 +85,6 @@ func (t *clusterStatusTransformer) reconcileClusterStatus(transCtx *clusterTrans return nil } -// func (t *clusterStatusTransformer) removeDeletedCompNSharding(transCtx *clusterTransformContext, cluster *appsv1.Cluster) { -// func() { -// tmp := map[string]appsv1.ClusterComponentStatus{} -// compsStatus := cluster.Status.Components -// for _, v := range transCtx.components { -// if status, ok := compsStatus[v.Name]; ok { -// tmp[v.Name] = status -// } -// } -// cluster.Status.Components = tmp -// }() -// func() { -// tmp := map[string]appsv1.ClusterComponentStatus{} -// shardingsStatus := cluster.Status.Shardings -// for _, v := range transCtx.shardings { -// if status, ok := shardingsStatus[v.Name]; ok { -// tmp[v.Name] = status -// } -// } -// cluster.Status.Shardings = tmp -// }() -// } - func (t *clusterStatusTransformer) reconcileClusterPhase(cluster *appsv1.Cluster) appsv1.ClusterPhase { statusList := make([]appsv1.ClusterComponentStatus, 0) if cluster.Status.Components != nil { diff --git a/controllers/apps/transformer_component_service.go b/controllers/apps/transformer_component_service.go index b809a2e1a30..40fddeb8327 100644 --- a/controllers/apps/transformer_component_service.go +++ b/controllers/apps/transformer_component_service.go @@ -347,7 +347,7 @@ func skipImmutableCheckForComponentService(svc *corev1.Service) bool { func generatePodNames(synthesizeComp *component.SynthesizedComponent) ([]string, error) { return component.GenerateAllPodNames(synthesizeComp.Replicas, synthesizeComp.Instances, - synthesizeComp.OfflineInstances, synthesizeComp.ClusterName, synthesizeComp.Name) + synthesizeComp.OfflineInstances, synthesizeComp.FullCompName) } func generatePodNamesByITS(its *workloads.InstanceSet) ([]string, error) { diff --git a/controllers/apps/transformer_component_status.go b/controllers/apps/transformer_component_status.go index b58b6f97d78..7e248d0fd08 100644 --- a/controllers/apps/transformer_component_status.go +++ b/controllers/apps/transformer_component_status.go @@ -22,10 +22,12 @@ package apps import ( "fmt" "strconv" + "strings" "time" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" "sigs.k8s.io/controller-runtime/pkg/client" @@ -116,7 +118,7 @@ func (t *componentStatusTransformer) init(transCtx *componentTransformContext, d // reconcileStatus reconciles component status. func (t *componentStatusTransformer) reconcileStatus(transCtx *componentTransformContext) error { if t.runningITS == nil { - return nil + return t.reconcileStatusCondition(transCtx) } // check if the ITS is deleting @@ -191,7 +193,7 @@ func (t *componentStatusTransformer) reconcileStatus(transCtx *componentTransfor t.setComponentStatusPhase(transCtx, appsv1.AbnormalClusterCompPhase, nil, "component is Abnormal") } - return nil + return t.reconcileStatusCondition(transCtx) } func (t *componentStatusTransformer) isWorkloadUpdated() bool { @@ -430,3 +432,42 @@ func (t *componentStatusTransformer) updateComponentStatus(transCtx *componentTr } return nil } + +func (t *componentStatusTransformer) reconcileStatusCondition(transCtx *componentTransformContext) error { + return t.reconcileAvailableCondition(transCtx) +} + +func (t *componentStatusTransformer) reconcileAvailableCondition(transCtx *componentTransformContext) error { + policy := component.GetComponentAvailablePolicy(transCtx.CompDef) + if policy.WithPhases == nil { + return nil + } + + var ( + comp = transCtx.Component + ) + status, reason, message := func() (metav1.ConditionStatus, string, string) { + if comp.Status.Phase == "" { + return metav1.ConditionUnknown, "Unknown", "the component phase is unknown" + } + phases := sets.New[string](strings.Split(strings.ToLower(*policy.WithPhases), ",")...) + if phases.Has(strings.ToLower(string(comp.Status.Phase))) { + return metav1.ConditionTrue, "Available", fmt.Sprintf("the component phase is %s", comp.Status.Phase) + } + return metav1.ConditionFalse, "Unavailable", fmt.Sprintf("the component phase is %s", comp.Status.Phase) + }() + + cond := metav1.Condition{ + Type: appsv1.ConditionTypeAvailable, + Status: status, + ObservedGeneration: comp.Generation, + LastTransitionTime: metav1.Now(), + Reason: reason, + Message: message, + } + if meta.SetStatusCondition(&comp.Status.Conditions, cond) { + transCtx.EventRecorder.Event(comp, corev1.EventTypeNormal, reason, message) + } + + return nil +} diff --git a/controllers/k8score/event_controller.go b/controllers/k8score/event_controller.go index 1a172a4490c..69685848328 100644 --- a/controllers/k8score/event_controller.go +++ b/controllers/k8score/event_controller.go @@ -31,11 +31,16 @@ import ( "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/log" + "github.com/apecloud/kubeblocks/pkg/controller/component" "github.com/apecloud/kubeblocks/pkg/controller/instanceset" "github.com/apecloud/kubeblocks/pkg/controller/multicluster" intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" ) +type eventHandler interface { + Handle(cli client.Client, reqCtx intctrlutil.RequestCtx, recorder record.EventRecorder, event *corev1.Event) error +} + // EventReconciler reconciles an Event object type EventReconciler struct { client.Client @@ -65,9 +70,14 @@ func (r *EventReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl return intctrlutil.CheckedRequeueWithError(err, reqCtx.Log, "getEventError") } - handler := &instanceset.PodRoleEventHandler{} - if err := handler.Handle(r.Client, reqCtx, r.Recorder, event); err != nil && !apierrors.IsNotFound(err) { - return intctrlutil.RequeueWithError(err, reqCtx.Log, "handleEventError") + handlers := []eventHandler{ + &instanceset.PodRoleEventHandler{}, + &component.AvailableEventHandler{}, + } + for _, handler := range handlers { + if err := handler.Handle(r.Client, reqCtx, r.Recorder, event); err != nil && !apierrors.IsNotFound(err) { + return intctrlutil.RequeueWithError(err, reqCtx.Log, "handleEventError") + } } return intctrlutil.Reconciled() } diff --git a/deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml b/deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml index 54164157d4a..d43b2f699de 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_componentdefinitions.yaml @@ -100,335 +100,4722 @@ spec: This field is immutable. type: object - configs: + available: description: |- - Specifies the configuration file templates and volume mount parameters used by the Component. - It also includes descriptions of the parameters in the ConfigMaps, such as value range limitations. + Specifies the strategies for determining the available status of the Component. - This field specifies a list of templates that will be rendered into Component containers' configuration files. - Each template is represented as a ConfigMap and may contain multiple configuration files, - with each file being a key in the ConfigMap. + This field is immutable. + properties: + withPhases: + description: |- + Specifies the phases that the component will go through to be considered available. - The rendered configuration files will be mounted into the Component's containers - according to the specified volume mount parameters. + This field is immutable once set. + type: string + withProbe: + description: |- + Specifies the strategies for determining whether the component is available based on the available probe. - This field is immutable. - items: - properties: - asEnvFrom: - description: |- - Specifies the containers to inject the ConfigMap parameters as environment variables. + This field is immutable once set. + properties: + condition: + description: |- + Specifies the conditions that the component will go through to be considered available. - This is useful when application images accept parameters through environment variables and - generate the final configuration file in the startup script based on these variables. + This field is immutable once set. + properties: + all: + description: |- + All replicas must satisfy the assertion. - This field allows users to specify a list of container names, and KubeBlocks will inject the environment - variables converted from the ConfigMap into these designated containers. This provides a flexible way to - pass the configuration items from the ConfigMap to the container without modifying the image. + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. - Deprecated: `asEnvFrom` has been deprecated since 0.9.0 and will be removed in 0.10.0. - Use `injectEnvTo` instead. - items: - type: string - type: array - x-kubernetes-list-type: set - asSecret: - description: Whether to store the final rendered parameters - as a secret. - type: boolean - constraintRef: - description: Specifies the name of the referenced configuration - constraints object. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - defaultMode: - description: |- - The operator attempts to set default file permissions for scripts (0555) and configurations (0444). - However, certain database engines may require different file permissions. - You can specify the desired file permissions here. + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. - Must be specified as an octal value between 0000 and 0777 (inclusive), - or as a decimal value between 0 and 511 (inclusive). - YAML supports both octal and decimal values for file permissions. + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. - Please note that this setting only affects the permissions of the files themselves. - Directories within the specified path are not impacted by this setting. - It's important to be aware that this setting might conflict with other options - that influence the file mode, such as fsGroup. - In such cases, the resulting file mode may have additional bits set. - Refers to documents of k8s.ConfigMapVolumeSource.defaultMode for more information. - format: int32 - type: integer - injectEnvTo: - description: |- - Specifies the containers to inject the ConfigMap parameters as environment variables. + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. - This is useful when application images accept parameters through environment variables and - generate the final configuration file in the startup script based on these variables. + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. - This field allows users to specify a list of container names, and KubeBlocks will inject the environment - variables converted from the ConfigMap into these designated containers. This provides a flexible way to - pass the configuration items from the ConfigMap to the container without modifying the image. - items: - type: string - type: array - x-kubernetes-list-type: set - keys: - description: |- - Specifies the configuration files within the ConfigMap that support dynamic updates. + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. - A configuration template (provided in the form of a ConfigMap) may contain templates for multiple - configuration files. - Each configuration file corresponds to a key in the ConfigMap. - Some of these configuration files may support dynamic modification and reloading without requiring - a pod restart. + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. - If empty or omitted, all configuration files in the ConfigMap are assumed to support dynamic updates, - and ConfigConstraint applies to all keys. - items: - type: string - type: array - x-kubernetes-list-type: set - legacyRenderedConfigSpec: - description: |- - Specifies the secondary rendered config spec for pod-specific customization. + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. - The template is rendered inside the pod (by the "config-manager" sidecar container) and merged with the main - template's render result to generate the final configuration file. + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. - This field is intended to handle scenarios where different pods within the same Component have - varying configurations. It allows for pod-specific customization of the configuration. + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. - Note: This field will be deprecated in future versions, and the functionality will be moved to - `cluster.spec.componentSpecs[*].instances[*]`. - properties: - namespace: - default: default - description: |- - Specifies the namespace of the referenced configuration template ConfigMap object. - An empty namespace is equivalent to the "default" namespace. - pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ - type: string - policy: - default: none - description: Defines the strategy for merging externally - imported templates into component templates. - enum: - - patch - - replace - - none - type: string - templateRef: - description: Specifies the name of the referenced configuration - template ConfigMap object. - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - required: - - templateRef - type: object - name: - description: Specifies the name of the configuration template. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - namespace: - default: default - description: |- - Specifies the namespace of the referenced configuration template ConfigMap object. - An empty namespace is equivalent to the "default" namespace. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ - type: string - reRenderResourceTypes: - description: |- - Specifies whether the configuration needs to be re-rendered after v-scale or h-scale operations to reflect changes. + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + and: + description: |- + Logical And to combine multiple expressions. + + + This field is immutable once set. + items: + properties: + all: + description: |- + All replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + any: + description: |- + At least one replica must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + majority: + description: |- + Majority replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + none: + description: |- + None of the replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: object + type: array + any: + description: |- + At least one replica must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + majority: + description: |- + Majority replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + none: + description: |- + None of the replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + not: + description: |- + Logical Not to negate the expression. + + + This field is immutable once set. + properties: + all: + description: |- + All replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + any: + description: |- + At least one replica must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + majority: + description: |- + Majority replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + none: + description: |- + None of the replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or failure + of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: object + or: + description: |- + Logical Or to combine multiple expressions. + + + This field is immutable once set. + items: + properties: + all: + description: |- + All replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + any: + description: |- + At least one replica must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + majority: + description: |- + Majority replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + none: + description: |- + None of the replicas must satisfy the assertion. + + + This field is immutable once set. + properties: + and: + description: |- + Logical And to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + not: + description: |- + Logical Not to negate the assertions. + + + This field is immutable once set. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + or: + description: |- + Logical Or to combine multiple assertions. + + + This field is immutable once set. + items: + description: ActionAssertion defines the custom + assertions for evaluating the success or + failure of an action. + properties: + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: array + stderr: + description: |- + Specifies the stderr matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + stdout: + description: |- + Specifies the stdout matcher for the action. + + + This field is immutable once set. + properties: + contains: + description: |- + The output of the action should contain the specified value. + + + This field is immutable once set. + type: string + equalTo: + description: |- + The output of the action should be equal to the specified value. + + + This field is immutable once set. + type: string + type: object + strict: + description: |- + Specifies whether apply the assertions strictly to all replicas. + + + This field is immutable once set. + type: boolean + succeed: + description: |- + Whether the action should succeed or fail. + + + This field is immutable once set. + type: boolean + type: object + type: object + type: array + type: object + description: + description: A brief description for the condition when the + component is available. + type: string + timeWindowSeconds: + description: This field is immutable once set. + format: int32 + type: integer + type: object + type: object + configs: + description: |- + Specifies the configuration file templates and volume mount parameters used by the Component. + It also includes descriptions of the parameters in the ConfigMaps, such as value range limitations. + + + This field specifies a list of templates that will be rendered into Component containers' configuration files. + Each template is represented as a ConfigMap and may contain multiple configuration files, + with each file being a key in the ConfigMap. + + + The rendered configuration files will be mounted into the Component's containers + according to the specified volume mount parameters. + + + This field is immutable. + items: + properties: + asEnvFrom: + description: |- + Specifies the containers to inject the ConfigMap parameters as environment variables. + + + This is useful when application images accept parameters through environment variables and + generate the final configuration file in the startup script based on these variables. + + + This field allows users to specify a list of container names, and KubeBlocks will inject the environment + variables converted from the ConfigMap into these designated containers. This provides a flexible way to + pass the configuration items from the ConfigMap to the container without modifying the image. + + + Deprecated: `asEnvFrom` has been deprecated since 0.9.0 and will be removed in 0.10.0. + Use `injectEnvTo` instead. + items: + type: string + type: array + x-kubernetes-list-type: set + asSecret: + description: Whether to store the final rendered parameters + as a secret. + type: boolean + constraintRef: + description: Specifies the name of the referenced configuration + constraints object. + maxLength: 63 + pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ + type: string + defaultMode: + description: |- + The operator attempts to set default file permissions for scripts (0555) and configurations (0444). + However, certain database engines may require different file permissions. + You can specify the desired file permissions here. + + + Must be specified as an octal value between 0000 and 0777 (inclusive), + or as a decimal value between 0 and 511 (inclusive). + YAML supports both octal and decimal values for file permissions. + + + Please note that this setting only affects the permissions of the files themselves. + Directories within the specified path are not impacted by this setting. + It's important to be aware that this setting might conflict with other options + that influence the file mode, such as fsGroup. + In such cases, the resulting file mode may have additional bits set. + Refers to documents of k8s.ConfigMapVolumeSource.defaultMode for more information. + format: int32 + type: integer + injectEnvTo: + description: |- + Specifies the containers to inject the ConfigMap parameters as environment variables. + + + This is useful when application images accept parameters through environment variables and + generate the final configuration file in the startup script based on these variables. + + + This field allows users to specify a list of container names, and KubeBlocks will inject the environment + variables converted from the ConfigMap into these designated containers. This provides a flexible way to + pass the configuration items from the ConfigMap to the container without modifying the image. + items: + type: string + type: array + x-kubernetes-list-type: set + keys: + description: |- + Specifies the configuration files within the ConfigMap that support dynamic updates. + + + A configuration template (provided in the form of a ConfigMap) may contain templates for multiple + configuration files. + Each configuration file corresponds to a key in the ConfigMap. + Some of these configuration files may support dynamic modification and reloading without requiring + a pod restart. + + + If empty or omitted, all configuration files in the ConfigMap are assumed to support dynamic updates, + and ConfigConstraint applies to all keys. + items: + type: string + type: array + x-kubernetes-list-type: set + legacyRenderedConfigSpec: + description: |- + Specifies the secondary rendered config spec for pod-specific customization. + + + The template is rendered inside the pod (by the "config-manager" sidecar container) and merged with the main + template's render result to generate the final configuration file. + + + This field is intended to handle scenarios where different pods within the same Component have + varying configurations. It allows for pod-specific customization of the configuration. + + + Note: This field will be deprecated in future versions, and the functionality will be moved to + `cluster.spec.componentSpecs[*].instances[*]`. + properties: + namespace: + default: default + description: |- + Specifies the namespace of the referenced configuration template ConfigMap object. + An empty namespace is equivalent to the "default" namespace. + pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ + type: string + policy: + default: none + description: Defines the strategy for merging externally + imported templates into component templates. + enum: + - patch + - replace + - none + type: string + templateRef: + description: Specifies the name of the referenced configuration + template ConfigMap object. + pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ + type: string + required: + - templateRef + type: object + name: + description: Specifies the name of the configuration template. + maxLength: 63 + pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ + type: string + namespace: + default: default + description: |- + Specifies the namespace of the referenced configuration template ConfigMap object. + An empty namespace is equivalent to the "default" namespace. + maxLength: 63 + pattern: ^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$ + type: string + reRenderResourceTypes: + description: |- + Specifies whether the configuration needs to be re-rendered after v-scale or h-scale operations to reflect changes. + + + In some scenarios, the configuration may need to be updated to reflect the changes in resource allocation + or cluster topology. Examples: + + + - Redis: adjust maxmemory after v-scale operation. + - MySQL: increase max connections after v-scale operation. + - Zookeeper: update zoo.cfg with new node addresses after h-scale operation. + items: + description: RerenderResourceType defines the resource requirements + for a component. + enum: + - vscale + - hscale + - tls + type: string + type: array + x-kubernetes-list-type: set + templateRef: + description: Specifies the name of the referenced configuration + template ConfigMap object. + maxLength: 63 + pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ + type: string + volumeName: + description: |- + Refers to the volume name of PodTemplate. The configuration file produced through the configuration + template will be mounted to the corresponding volume. Must be a DNS_LABEL name. + The volume name must be defined in podSpec.containers[*].volumeMounts. + maxLength: 63 + pattern: ^[a-z]([a-z0-9\-]*[a-z0-9])?$ + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + description: + description: |- + Provides a brief and concise explanation of the Component's purpose, functionality, and any relevant details. + It serves as a quick reference for users to understand the Component's role and characteristics. + maxLength: 256 + type: string + exporter: + description: Defines the built-in metrics exporter container. + properties: + containerName: + description: Specifies the name of the built-in metrics exporter + container. + type: string + scrapePath: + description: |- + Specifies the http/https url path to scrape for metrics. + If empty, Prometheus uses the default value (e.g. `/metrics`). + type: string + scrapePort: + description: Specifies the port name to scrape for metrics. + type: string + scrapeScheme: + description: |- + Specifies the schema to use for scraping. + `http` and `https` are the expected values unless you rewrite the `__scheme__` label via relabeling. + If empty, Prometheus uses the default value `http`. + enum: + - http + - https + type: string + type: object + hostNetwork: + description: |- + Specifies the host network configuration for the Component. + + + When `hostNetwork` option is enabled, the Pods share the host's network namespace and can directly access + the host's network interfaces. + This means that if multiple Pods need to use the same port, they cannot run on the same host simultaneously + due to port conflicts. + + + The DNSPolicy field in the Pod spec determines how containers within the Pod perform DNS resolution. + When using hostNetwork, the operator will set the DNSPolicy to 'ClusterFirstWithHostNet'. + With this policy, DNS queries will first go through the K8s cluster's DNS service. + If the query fails, it will fall back to the host's DNS settings. + + + If set, the DNS policy will be automatically set to "ClusterFirstWithHostNet". + + + This field is immutable. + properties: + containerPorts: + description: The list of container ports that are required by + the component. + items: + properties: + container: + description: Container specifies the target container within + the Pod. + type: string + ports: + description: |- + Ports are named container ports within the specified container. + These container ports must be defined in the container for proper port allocation. + items: + type: string + minItems: 1 + type: array + required: + - container + - ports + type: object + type: array + type: object + labels: + additionalProperties: + type: string + description: |- + Specifies static labels that will be patched to all Kubernetes resources created for the Component. + + + Note: If a label key in the `labels` field conflicts with any system labels or user-specified labels, + it will be silently ignored to avoid overriding higher-priority labels. + + + This field is immutable. + type: object + lifecycleActions: + description: |- + Defines a set of hooks and procedures that customize the behavior of a Component throughout its lifecycle. + Actions are triggered at specific lifecycle stages: + + + - `postProvision`: Defines the hook to be executed after the creation of a Component, + with `preCondition` specifying when the action should be fired relative to the Component's lifecycle stages: + `Immediately`, `RuntimeReady`, `ComponentReady`, and `ClusterReady`. + - `preTerminate`: Defines the hook to be executed before terminating a Component. + - `roleProbe`: Defines the procedure which is invoked regularly to assess the role of replicas. + - `switchover`: Defines the procedure for a controlled transition of leadership from the current leader to a new replica. + This approach aims to minimize downtime and maintain availability in systems with a leader-follower topology, + such as before planned maintenance or upgrades on the current leader node. + - `memberJoin`: Defines the procedure to add a new replica to the replication group. + - `memberLeave`: Defines the method to remove a replica from the replication group. + - `readOnly`: Defines the procedure to switch a replica into the read-only state. + - `readWrite`: transition a replica from the read-only state back to the read-write state. + - `dataDump`: Defines the procedure to export the data from a replica. + - `dataLoad`: Defines the procedure to import data into a replica. + - `reconfigure`: Defines the procedure that update a replica with new configuration file. + - `accountProvision`: Defines the procedure to generate a new database account. + + + This field is immutable. + properties: + accountProvision: + description: |- + Defines the procedure to generate a new database account. + + + Use Case: + This action is designed to create system accounts that are utilized for replication, monitoring, backup, + and other administrative tasks. + + + The container executing this action has access to following variables: + + + - KB_ACCOUNT_NAME: The name of the system account to be created. + - KB_ACCOUNT_PASSWORD: The password for the system account. // TODO: how to pass the password securely? + - KB_ACCOUNT_STATEMENT: The statement used to create the system account. + + + Note: This field is immutable once it has been set. + properties: + exec: + description: |- + Defines the command to run. + + + This field cannot be updated. + properties: + args: + description: Args represents the arguments that are passed + to the `command` for execution. + items: + type: string + type: array + command: + description: |- + Specifies the command to be executed inside the container. + The working directory for this command is the container's root directory('/'). + Commands are executed directly without a shell environment, meaning shell-specific syntax ('|', etc.) is not supported. + If the shell is required, it must be explicitly invoked in the command. + + + A successful execution is indicated by an exit status of 0; any non-zero status signifies a failure. + items: + type: string + type: array + container: + description: |- + Specifies the name of the container within the same pod whose resources will be shared with the action. + This allows the action to utilize the specified container's resources without executing within it. + + + The name must match one of the containers defined in `componentDefinition.spec.runtime`. + + + The resources that can be shared are included: + + + - volume mounts + + + This field cannot be updated. + type: string + env: + description: |- + Represents a list of environment variables that will be injected into the container. + These variables enable the container to adapt its behavior based on the environment it's running in. + + + This field cannot be updated. + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid? + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for + volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the + pod's namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid? + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: |- + Specifies the container image to be used for running the Action. - In some scenarios, the configuration may need to be updated to reflect the changes in resource allocation - or cluster topology. Examples: + When specified, a dedicated container will be created using this image to execute the Action. + All actions with same image will share the same container. - - Redis: adjust maxmemory after v-scale operation. - - MySQL: increase max connections after v-scale operation. - - Zookeeper: update zoo.cfg with new node addresses after h-scale operation. - items: - description: RerenderResourceType defines the resource requirements - for a component. - enum: - - vscale - - hscale - - tls - type: string - type: array - x-kubernetes-list-type: set - templateRef: - description: Specifies the name of the referenced configuration - template ConfigMap object. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ - type: string - volumeName: - description: |- - Refers to the volume name of PodTemplate. The configuration file produced through the configuration - template will be mounted to the corresponding volume. Must be a DNS_LABEL name. - The volume name must be defined in podSpec.containers[*].volumeMounts. - maxLength: 63 - pattern: ^[a-z]([a-z0-9\-]*[a-z0-9])?$ - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - description: - description: |- - Provides a brief and concise explanation of the Component's purpose, functionality, and any relevant details. - It serves as a quick reference for users to understand the Component's role and characteristics. - maxLength: 256 - type: string - exporter: - description: Defines the built-in metrics exporter container. - properties: - containerName: - description: Specifies the name of the built-in metrics exporter - container. - type: string - scrapePath: - description: |- - Specifies the http/https url path to scrape for metrics. - If empty, Prometheus uses the default value (e.g. `/metrics`). - type: string - scrapePort: - description: Specifies the port name to scrape for metrics. - type: string - scrapeScheme: - description: |- - Specifies the schema to use for scraping. - `http` and `https` are the expected values unless you rewrite the `__scheme__` label via relabeling. - If empty, Prometheus uses the default value `http`. - enum: - - http - - https - type: string - type: object - hostNetwork: - description: |- - Specifies the host network configuration for the Component. + This field cannot be updated. + type: string + matchingKey: + description: |- + Used in conjunction with the `targetPodSelector` field to refine the selection of target pod(s) for Action execution. + The impact of this field depends on the `targetPodSelector` value: - When `hostNetwork` option is enabled, the Pods share the host's network namespace and can directly access - the host's network interfaces. - This means that if multiple Pods need to use the same port, they cannot run on the same host simultaneously - due to port conflicts. + - When `targetPodSelector` is set to `Any` or `All`, this field will be ignored. + - When `targetPodSelector` is set to `Role`, only those replicas whose role matches the `matchingKey` + will be selected for the Action. - The DNSPolicy field in the Pod spec determines how containers within the Pod perform DNS resolution. - When using hostNetwork, the operator will set the DNSPolicy to 'ClusterFirstWithHostNet'. - With this policy, DNS queries will first go through the K8s cluster's DNS service. - If the query fails, it will fall back to the host's DNS settings. + This field cannot be updated. + type: string + targetPodSelector: + description: |- + Defines the criteria used to select the target Pod(s) for executing the Action. + This is useful when there is no default target replica identified. + It allows for precise control over which Pod(s) the Action should run in. - If set, the DNS policy will be automatically set to "ClusterFirstWithHostNet". + If not specified, the Action will be executed in the pod where the Action is triggered, such as the pod + to be removed or added; or a random pod if the Action is triggered at the component level, such as + post-provision or pre-terminate of the component. - This field is immutable. - properties: - containerPorts: - description: The list of container ports that are required by - the component. - items: - properties: - container: - description: Container specifies the target container within - the Pod. - type: string - ports: - description: |- - Ports are named container ports within the specified container. - These container ports must be defined in the container for proper port allocation. - items: + This field cannot be updated. + enum: + - Any + - All + - Role + - Ordinal type: string - minItems: 1 - type: array - required: - - container - - ports - type: object - type: array - type: object - labels: - additionalProperties: - type: string - description: |- - Specifies static labels that will be patched to all Kubernetes resources created for the Component. + type: object + preCondition: + description: |- + Specifies the state that the cluster must reach before the Action is executed. + Currently, this is only applicable to the `postProvision` action. - Note: If a label key in the `labels` field conflicts with any system labels or user-specified labels, - it will be silently ignored to avoid overriding higher-priority labels. + The conditions are as follows: - This field is immutable. - type: object - lifecycleActions: - description: |- - Defines a set of hooks and procedures that customize the behavior of a Component throughout its lifecycle. - Actions are triggered at specific lifecycle stages: + - `Immediately`: Executed right after the Component object is created. + The readiness of the Component and its resources is not guaranteed at this stage. + - `RuntimeReady`: The Action is triggered after the Component object has been created and all associated + runtime resources (e.g. Pods) are in a ready state. + - `ComponentReady`: The Action is triggered after the Component itself is in a ready state. + This process does not affect the readiness state of the Component or the Cluster. + - `ClusterReady`: The Action is executed after the Cluster is in a ready state. + This execution does not alter the Component or the Cluster's state of readiness. - - `postProvision`: Defines the hook to be executed after the creation of a Component, - with `preCondition` specifying when the action should be fired relative to the Component's lifecycle stages: - `Immediately`, `RuntimeReady`, `ComponentReady`, and `ClusterReady`. - - `preTerminate`: Defines the hook to be executed before terminating a Component. - - `roleProbe`: Defines the procedure which is invoked regularly to assess the role of replicas. - - `switchover`: Defines the procedure for a controlled transition of leadership from the current leader to a new replica. - This approach aims to minimize downtime and maintain availability in systems with a leader-follower topology, - such as before planned maintenance or upgrades on the current leader node. - - `memberJoin`: Defines the procedure to add a new replica to the replication group. - - `memberLeave`: Defines the method to remove a replica from the replication group. - - `readOnly`: Defines the procedure to switch a replica into the read-only state. - - `readWrite`: transition a replica from the read-only state back to the read-write state. - - `dataDump`: Defines the procedure to export the data from a replica. - - `dataLoad`: Defines the procedure to import data into a replica. - - `reconfigure`: Defines the procedure that update a replica with new configuration file. - - `accountProvision`: Defines the procedure to generate a new database account. + This field cannot be updated. + type: string + retryPolicy: + description: |- + Defines the strategy to be taken when retrying the Action after a failure. - This field is immutable. - properties: - accountProvision: - description: |- - Defines the procedure to generate a new database account. + It specifies the conditions under which the Action should be retried and the limits to apply, + such as the maximum number of retries and backoff strategy. - Use Case: - This action is designed to create system accounts that are utilized for replication, monitoring, backup, - and other administrative tasks. + This field cannot be updated. + properties: + maxRetries: + default: 0 + description: |- + Defines the maximum number of retry attempts that should be made for a given Action. + This value is set to 0 by default, indicating that no retries will be made. + type: integer + retryInterval: + default: 0 + description: |- + Indicates the duration of time to wait between each retry attempt. + This value is set to 0 by default, indicating that there will be no delay between retry attempts. + format: int64 + type: integer + type: object + timeoutSeconds: + default: 0 + description: |- + Specifies the maximum duration in seconds that the Action is allowed to run. - The container executing this action has access to following variables: + If the Action does not complete within this time frame, it will be terminated. - - KB_ACCOUNT_NAME: The name of the system account to be created. - - KB_ACCOUNT_PASSWORD: The password for the system account. // TODO: how to pass the password securely? - - KB_ACCOUNT_STATEMENT: The statement used to create the system account. + This field cannot be updated. + format: int32 + type: integer + type: object + availableProbe: + description: |- + Defines the procedure which is invoked regularly to assess the availability of the component. Note: This field is immutable once it has been set. @@ -639,6 +5026,24 @@ spec: - Ordinal type: string type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + initialDelaySeconds: + description: |- + Specifies the number of seconds to wait after the container has started before the RoleProbe + begins to detect the container's role. + format: int32 + type: integer + periodSeconds: + description: |- + Specifies the frequency at which the probe is conducted. This value is expressed in seconds. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer preCondition: description: |- Specifies the state that the cluster must reach before the Action is executed. @@ -685,6 +5090,12 @@ spec: format: int64 type: integer type: object + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Minimum value is 1. + format: int32 + type: integer timeoutSeconds: default: 0 description: |- diff --git a/docs/developer_docs/api-reference/cluster.md b/docs/developer_docs/api-reference/cluster.md index 8c377a6065a..cfda825c147 100644 --- a/docs/developer_docs/api-reference/cluster.md +++ b/docs/developer_docs/api-reference/cluster.md @@ -1329,6 +1329,21 @@ This field allows you to set a limit on the scalability of the Component, preven +available
+ + +ComponentAvailable + + + + +(Optional) +

Specifies the strategies for determining the available status of the Component.

+

This field is immutable.

+ + + + roles
@@ -2089,6 +2104,111 @@ This execution does not alter the Component or the Cluster’s state of read +

ActionAssertion +

+

+(Appears on:ComponentAvailableProbeAssertion) +

+
+

ActionAssertion defines the custom assertions for evaluating the success or failure of an action.

+
+ + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+succeed
+ +bool + +
+(Optional) +

Whether the action should succeed or fail.

+

This field is immutable once set.

+
+stdout
+ + +ActionOutputMatcher + + +
+(Optional) +

Specifies the stdout matcher for the action.

+

This field is immutable once set.

+
+stderr
+ + +ActionOutputMatcher + + +
+(Optional) +

Specifies the stderr matcher for the action.

+

This field is immutable once set.

+
+

ActionOutputMatcher +

+

+(Appears on:ActionAssertion) +

+
+

ActionOutputMatcher defines the matcher for the output of an action.

+
+ + + + + + + + + + + + + + + + + +
FieldDescription
+equalTo
+ +string + +
+(Optional) +

The output of the action should be equal to the specified value.

+

This field is immutable once set.

+
+contains
+ +string + +
+(Optional) +

The output of the action should contain the specified value.

+

This field is immutable once set.

+

ClusterBackup

@@ -4000,6 +4120,352 @@ VarOption +

ComponentAvailable +

+

+(Appears on:ComponentDefinitionSpec) +

+
+

ComponentAvailable defines the strategies for determining whether the component is available.

+
+ + + + + + + + + + + + + + + + + +
FieldDescription
+withPhases
+ +string + +
+(Optional) +

Specifies the phases that the component will go through to be considered available.

+

This field is immutable once set.

+
+withProbe
+ + +ComponentAvailableWithProbe + + +
+(Optional) +

Specifies the strategies for determining whether the component is available based on the available probe.

+

This field is immutable once set.

+
+

ComponentAvailableCondition +

+

+(Appears on:ComponentAvailableWithProbe) +

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+ComponentAvailableExpression
+ + +ComponentAvailableExpression + + +
+

+(Members of ComponentAvailableExpression are embedded into this type.) +

+
+and
+ + +[]ComponentAvailableExpression + + +
+(Optional) +

Logical And to combine multiple expressions.

+

This field is immutable once set.

+
+or
+ + +[]ComponentAvailableExpression + + +
+(Optional) +

Logical Or to combine multiple expressions.

+

This field is immutable once set.

+
+not
+ + +ComponentAvailableExpression + + +
+(Optional) +

Logical Not to negate the expression.

+

This field is immutable once set.

+
+

ComponentAvailableExpression +

+

+(Appears on:ComponentAvailableCondition) +

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+all
+ + +ComponentAvailableProbeAssertion + + +
+(Optional) +

All replicas must satisfy the assertion.

+

This field is immutable once set.

+
+any
+ + +ComponentAvailableProbeAssertion + + +
+(Optional) +

At least one replica must satisfy the assertion.

+

This field is immutable once set.

+
+none
+ + +ComponentAvailableProbeAssertion + + +
+(Optional) +

None of the replicas must satisfy the assertion.

+

This field is immutable once set.

+
+majority
+ + +ComponentAvailableProbeAssertion + + +
+(Optional) +

Majority replicas must satisfy the assertion.

+

This field is immutable once set.

+
+

ComponentAvailableProbeAssertion +

+

+(Appears on:ComponentAvailableExpression) +

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+ActionAssertion
+ + +ActionAssertion + + +
+

+(Members of ActionAssertion are embedded into this type.) +

+
+and
+ + +[]ActionAssertion + + +
+(Optional) +

Logical And to combine multiple assertions.

+

This field is immutable once set.

+
+or
+ + +[]ActionAssertion + + +
+(Optional) +

Logical Or to combine multiple assertions.

+

This field is immutable once set.

+
+not
+ + +ActionAssertion + + +
+(Optional) +

Logical Not to negate the assertions.

+

This field is immutable once set.

+
+strict
+ +bool + +
+(Optional) +

Specifies whether apply the assertions strictly to all replicas.

+

This field is immutable once set.

+
+

ComponentAvailableWithProbe +

+

+(Appears on:ComponentAvailable) +

+
+
+ + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+timeWindowSeconds
+ +int32 + +
+(Optional) +

This field is immutable once set.

+
+condition
+ + +ComponentAvailableCondition + + +
+(Optional) +

Specifies the conditions that the component will go through to be considered available.

+

This field is immutable once set.

+
+description
+ +string + +
+(Optional) +

A brief description for the condition when the component is available.

+

ComponentConfigSpec

@@ -4566,6 +5032,21 @@ This field allows you to set a limit on the scalability of the Component, preven +available
+ + +ComponentAvailable + + + + +(Optional) +

Specifies the strategies for determining the available status of the Component.

+

This field is immutable.

+ + + + roles
@@ -4883,6 +5364,21 @@ Without this, services that rely on roleSelectors might improperly direct traffi +availableProbe
+ +
+Probe + + + + +(Optional) +

Defines the procedure which is invoked regularly to assess the availability of the component.

+

Note: This field is immutable once it has been set.

+ + + + switchover
diff --git a/pkg/controller/component/available.go b/pkg/controller/component/available.go new file mode 100644 index 00000000000..86174d36ed0 --- /dev/null +++ b/pkg/controller/component/available.go @@ -0,0 +1,566 @@ +/* +Copyright (C) 2022-2024 ApeCloud Co., Ltd + +This file is part of KubeBlocks project + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ + +package component + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "reflect" + "strings" + "time" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/client-go/tools/record" + "k8s.io/utils/pointer" + "sigs.k8s.io/controller-runtime/pkg/client" + + appsv1 "github.com/apecloud/kubeblocks/apis/apps/v1" + intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" + "github.com/apecloud/kubeblocks/pkg/kbagent/proto" +) + +const ( + availableProbe = "availableProbe" + availableProbeMessageKey = "Event/available-probe" +) + +type AvailableEventHandler struct{} + +func (h *AvailableEventHandler) Handle(cli client.Client, reqCtx intctrlutil.RequestCtx, recorder record.EventRecorder, event *corev1.Event) error { + if !h.isAvailableEvent(event) { + return nil + } + + ppEvent := &proto.ProbeEvent{} + if err := json.Unmarshal([]byte(event.Message), ppEvent); err != nil { + return err + } + + compKey := types.NamespacedName{ + Namespace: event.InvolvedObject.Namespace, + Name: ppEvent.Instance, + } + comp := &appsv1.Component{} + if err := cli.Get(reqCtx.Ctx, compKey, comp); err != nil { + return err + } + compCopy := comp.DeepCopy() + + compDef, err := h.getNCheckCompDefinition(reqCtx.Ctx, cli, comp.Spec.CompDef) + if err != nil { + return err + } + + available, message, err := h.handleEvent(newProbeEvent(event, ppEvent), comp, compDef) + if err != nil { + return err + } + if available == nil { + return nil // w/o available probe + } + if *available { + return h.available(reqCtx.Ctx, cli, recorder, compCopy, comp, message) + } + return h.unavailable(reqCtx.Ctx, cli, recorder, compCopy, comp, message) +} + +func (h *AvailableEventHandler) isAvailableEvent(event *corev1.Event) bool { + return event.ReportingController == proto.ProbeEventReportingController && + event.Reason == availableProbe && event.InvolvedObject.FieldPath == proto.ProbeEventFieldPath +} + +func (h *AvailableEventHandler) available(ctx context.Context, cli client.Client, + recorder record.EventRecorder, compCopy, comp *appsv1.Component, message string) error { + return h.status(ctx, cli, recorder, compCopy, comp, metav1.ConditionTrue, "Available", message) +} + +func (h *AvailableEventHandler) unavailable(ctx context.Context, cli client.Client, + recorder record.EventRecorder, compCopy, comp *appsv1.Component, message string) error { + return h.status(ctx, cli, recorder, compCopy, comp, metav1.ConditionFalse, "Unavailable", message) +} + +func (h *AvailableEventHandler) status(ctx context.Context, cli client.Client, recorder record.EventRecorder, + compCopy, comp *appsv1.Component, status metav1.ConditionStatus, reason, message string) error { + var ( + cond = metav1.Condition{ + Type: appsv1.ConditionTypeAvailable, + Status: status, + ObservedGeneration: comp.Generation, // TODO: ??? + LastTransitionTime: metav1.Now(), + Reason: reason, + Message: message, + } + ) + changed := meta.SetStatusCondition(&comp.Status.Conditions, cond) + if changed || !reflect.DeepEqual(comp.Status.Message, compCopy.Status.Message) { + if changed { + recorder.Event(comp, corev1.EventTypeNormal, reason, message) + } + return cli.Status().Patch(ctx, comp, client.MergeFrom(compCopy)) + } + return nil +} + +func (h *AvailableEventHandler) handleEvent(event probeEvent, comp *appsv1.Component, compDef *appsv1.ComponentDefinition) (*bool, string, error) { + policy := GetComponentAvailablePolicy(compDef) + if policy.WithProbe == nil || policy.WithProbe.Condition == nil { + if policy.WithPhases != nil { + return nil, "", nil + } + return nil, "", fmt.Errorf("the referenced ComponentDefinition does not have available probe defined, but we got a probe event? %s", compDef.Name) + } + + events, err := h.pickupProbeEvents(event, *policy.WithProbe.TimeWindowSeconds, comp) + if err != nil { + return nil, "", err + } + available, message := h.evalCond(*policy.WithProbe.Condition, comp.Spec.Replicas, events) + if available { + message = "the available conditions are met" + if len(policy.WithProbe.Description) > 0 { + message = policy.WithProbe.Description + } + } + return &available, message, nil +} + +func (h *AvailableEventHandler) getNCheckCompDefinition(ctx context.Context, cli client.Reader, name string) (*appsv1.ComponentDefinition, error) { + compKey := types.NamespacedName{ + Name: name, + } + compDef := &appsv1.ComponentDefinition{} + if err := cli.Get(ctx, compKey, compDef); err != nil { + return nil, err + } + if compDef.Generation != compDef.Status.ObservedGeneration { + return nil, fmt.Errorf("the referenced ComponentDefinition is not up to date: %s", compDef.Name) + } + if compDef.Status.Phase != appsv1.AvailablePhase { + return nil, fmt.Errorf("the referenced ComponentDefinition is unavailable: %s", compDef.Name) + } + return compDef, nil +} + +type probeEvent struct { + PodName string `json:"podName"` + PodUID types.UID `json:"podUID"` + Timestamp time.Time `json:"timestamp"` + Code int32 `json:"code"` + Stdout []byte `json:"stdout,omitempty"` + Stderr []byte `json:"stderr,omitempty"` +} + +func newProbeEvent(event *corev1.Event, ppEvent *proto.ProbeEvent) probeEvent { + return probeEvent{ + PodName: event.InvolvedObject.Name, + PodUID: event.InvolvedObject.UID, + Timestamp: event.LastTimestamp.Time, + Code: ppEvent.Code, + Stdout: ppEvent.Output, + Stderr: []byte(ppEvent.Message), + } +} + +func (h *AvailableEventHandler) pickupProbeEvents(event probeEvent, timeWindow int32, comp *appsv1.Component) ([]probeEvent, error) { + events, err := h.getCachedEvents(comp) + if err != nil { + return nil, err + } + events = append(events, event) + + podNames, err := GenerateAllPodNames(comp.Spec.Replicas, comp.Spec.Instances, comp.Spec.OfflineInstances, comp.Name) + if err != nil { + return nil, err + } + + timestamp := time.Now().Add(time.Duration(timeWindow*-1) * time.Second) + + filterByTimeWindow := func(events []probeEvent) []probeEvent { + result := make([]probeEvent, 0) + for i, evt := range events { + if evt.Timestamp.After(timestamp) { + result = append(result, events[i]) + } + } + return result + } + + filterByPodNames := func(events map[string][]probeEvent) map[string][]probeEvent { + names := sets.New[string](podNames...) + result := make(map[string][]probeEvent) + for name := range events { + if names.Has(name) { + result[name] = events[name] + } + } + return result + } + + groupByPod := func(events []probeEvent) map[string][]probeEvent { + result := make(map[string][]probeEvent) + for i, evt := range events { + podEvents, ok := result[evt.PodName] + if ok { + result[evt.PodName] = append(podEvents, events[i]) + } else { + result[evt.PodName] = []probeEvent{events[i]} + } + } + return result + } + + latest := func(events map[string][]probeEvent) []probeEvent { + result := make([]probeEvent, 0) + for k := range events { + podEvents := events[k] + evt := podEvents[0] + for i := 1; i < len(podEvents); i++ { + if podEvents[i].Timestamp.After(evt.Timestamp) { + evt = podEvents[i] + } + } + result = append(result, evt) + } + return result + } + + pickedEvents := latest(filterByPodNames(groupByPod(filterByTimeWindow(events)))) + if err = h.updateCachedEvents(comp, pickedEvents); err != nil { + return nil, err + } + return pickedEvents, nil +} + +func (h *AvailableEventHandler) getCachedEvents(comp *appsv1.Component) ([]probeEvent, error) { + if comp.Status.Message == nil { + return nil, nil + } + message, ok := comp.Status.Message[availableProbeMessageKey] + if !ok { + return nil, nil + } + events := make([]probeEvent, 0) + err := json.Unmarshal([]byte(message), &events) + if err != nil { + return nil, err + } + return events, nil +} + +func (h *AvailableEventHandler) updateCachedEvents(comp *appsv1.Component, events []probeEvent) error { + if comp.Status.Message == nil && len(events) == 0 { + return nil + } + + out, err := json.Marshal(&events) + if err != nil { + return err + } + + if comp.Status.Message == nil { + comp.Status.Message = make(map[string]string) + } + comp.Status.Message[availableProbeMessageKey] = string(out) + + return nil +} + +func (h *AvailableEventHandler) evalCond(cond appsv1.ComponentAvailableCondition, replicas int32, events []probeEvent) (bool, string) { + if len(cond.And) > 0 { + return h.evalCondAnd(cond.And, replicas, events) + } + if len(cond.Or) > 0 { + return h.evalCondOr(cond.Or, replicas, events) + } + if cond.Not != nil { + return h.evalCondNot(*cond.Not, replicas, events) + } + return h.evalExpr(cond.ComponentAvailableExpression, replicas, events) +} + +func (h *AvailableEventHandler) evalCondAnd(expressions []appsv1.ComponentAvailableExpression, replicas int32, events []probeEvent) (bool, string) { + for _, expr := range expressions { + ok, msg := h.evalExpr(expr, replicas, events) + if !ok { + return false, msg + } + } + return true, "" +} + +func (h *AvailableEventHandler) evalCondOr(expressions []appsv1.ComponentAvailableExpression, replicas int32, events []probeEvent) (bool, string) { + msgs := make([]string, 0) + for _, expr := range expressions { + ok, msg := h.evalExpr(expr, replicas, events) + if ok { + return true, "" + } + if len(msg) > 0 { + msgs = append(msgs, msg) + } + } + return false, strings.Join(h.distinct(msgs), ",") +} + +func (h *AvailableEventHandler) evalCondNot(expr appsv1.ComponentAvailableExpression, replicas int32, events []probeEvent) (bool, string) { + ok, msg := h.evalExpr(expr, replicas, events) + if ok { + return false, msg + } + return true, "" +} + +func (h *AvailableEventHandler) evalExpr(expr appsv1.ComponentAvailableExpression, replicas int32, events []probeEvent) (bool, string) { + if expr.All != nil { + return h.evalAssertionAll(*expr.All, replicas, events) + } + if expr.Any != nil { + return h.evalAssertionAny(*expr.Any, replicas, events) + } + if expr.None != nil { + return h.evalAssertionNone(*expr.None, replicas, events) + } + if expr.Majority != nil { + return h.evalAssertionMajority(*expr.Majority, replicas, events) + } + return true, "" +} + +func (h *AvailableEventHandler) evalAssertionAll(assertion appsv1.ComponentAvailableProbeAssertion, replicas int32, events []probeEvent) (bool, string) { + if !h.strictCheck(assertion, replicas, events) { + return false, fmt.Sprintf("not all replicas are available: %d/%d", len(events), replicas) + } + for _, event := range events { + ok, msg := h.evalAssertion(assertion, []probeEvent{event}) + if !ok { + return false, msg + } + } + return true, "" +} + +func (h *AvailableEventHandler) evalAssertionAny(assertion appsv1.ComponentAvailableProbeAssertion, replicas int32, events []probeEvent) (bool, string) { + if !h.strictCheck(assertion, replicas, events) { + return false, fmt.Sprintf("not all replicas are available: %d/%d", len(events), replicas) + } + msgs := make([]string, 0) + for _, event := range events { + ok, msg := h.evalAssertion(assertion, []probeEvent{event}) + if ok { + return true, "" + } + if len(msg) > 0 { + msgs = append(msgs, msg) + } + } + return false, strings.Join(h.distinct(msgs), ",") +} + +func (h *AvailableEventHandler) evalAssertionNone(assertion appsv1.ComponentAvailableProbeAssertion, replicas int32, events []probeEvent) (bool, string) { + if !h.strictCheck(assertion, replicas, events) { + return false, fmt.Sprintf("not all replicas are available: %d/%d", len(events), replicas) + } + for _, event := range events { + ok, msg := h.evalAssertion(assertion, []probeEvent{event}) + if ok { + return false, msg + } + } + return true, "" +} + +func (h *AvailableEventHandler) evalAssertionMajority(assertion appsv1.ComponentAvailableProbeAssertion, replicas int32, events []probeEvent) (bool, string) { + count := 0 + msgs := make([]string, 0) + for _, event := range events { + ok, msg := h.evalAssertion(assertion, []probeEvent{event}) + if ok { + count++ + } else if len(msg) > 0 { + msgs = append(msgs, msg) + } + } + ok := int32(count) > replicas/2 + if ok { + return true, "" + } + return false, strings.Join(h.distinct(msgs), ",") +} + +func (h *AvailableEventHandler) strictCheck(assertion appsv1.ComponentAvailableProbeAssertion, replicas int32, events []probeEvent) bool { + if assertion.Strict != nil && *assertion.Strict { + if replicas != int32(len(events)) { + return false + } + } + return true +} + +func (h *AvailableEventHandler) evalAssertion(assertion appsv1.ComponentAvailableProbeAssertion, events []probeEvent) (bool, string) { + if assertion.ActionAssertion != (appsv1.ActionAssertion{}) { + return h.evalAction(assertion.ActionAssertion, events) + } + if len(assertion.And) > 0 { + return h.evalActionAnd(assertion.And, events) + } + if assertion.Or != nil { + return h.evalActionOr(assertion.Or, events) + } + if assertion.Not != nil { + return h.evalActionNot(*assertion.Not, events) + } + return true, "" +} + +func (h *AvailableEventHandler) evalActionAnd(assertions []appsv1.ActionAssertion, events []probeEvent) (bool, string) { + for _, assertion := range assertions { + ok, msg := h.evalAction(assertion, events) + if !ok { + return false, msg + } + } + return true, "" +} + +func (h *AvailableEventHandler) evalActionOr(assertions []appsv1.ActionAssertion, events []probeEvent) (bool, string) { + msgs := make([]string, 0) + for _, assertion := range assertions { + ok, msg := h.evalAction(assertion, events) + if ok { + return true, "" + } + if len(msg) > 0 { + msgs = append(msgs, msg) + } + } + return false, strings.Join(h.distinct(msgs), ",") +} + +func (h *AvailableEventHandler) evalActionNot(assertion appsv1.ActionAssertion, events []probeEvent) (bool, string) { + ok, msg := h.evalAction(assertion, events) + return !ok, msg +} + +func (h *AvailableEventHandler) evalAction(assertion appsv1.ActionAssertion, events []probeEvent) (bool, string) { + msgs := make([]string, 0) + for _, event := range events { + ok, msg := h.evalActionEvent(assertion, event) + if ok { + return true, "" + } + if len(msg) > 0 { + msgs = append(msgs, msg) + } + } + return false, strings.Join(h.distinct(msgs), ",") + +} + +func (h *AvailableEventHandler) evalActionEvent(assertion appsv1.ActionAssertion, event probeEvent) (bool, string) { + if assertion.Succeed != nil && *assertion.Succeed != (event.Code == 0) { + return false, fmt.Sprintf("probe code is not 0: %d", event.Code) + } + prefix16 := func(out string) string { + if len(out) <= 16 { + return out + } + return out[:16] + "..." + } + if assertion.Stdout != nil { + if assertion.Stdout.EqualTo != nil && !bytes.Equal(event.Stdout, []byte(*assertion.Stdout.EqualTo)) { + return false, fmt.Sprintf("probe stdout is not match: %s", prefix16(*assertion.Stdout.EqualTo)) + } + if assertion.Stdout.Contains != nil && !bytes.Contains(event.Stdout, []byte(*assertion.Stdout.Contains)) { + return false, fmt.Sprintf("probe stdout does not contain: %s", prefix16(*assertion.Stdout.Contains)) + } + } + if assertion.Stderr != nil { + if assertion.Stderr.EqualTo != nil && !bytes.Equal(event.Stderr, []byte(*assertion.Stderr.EqualTo)) { + return false, fmt.Sprintf("probe stderr is not match: %s", prefix16(*assertion.Stderr.EqualTo)) + } + if assertion.Stderr.Contains != nil && !bytes.Contains(event.Stderr, []byte(*assertion.Stderr.Contains)) { + return false, fmt.Sprintf("probe stderr does not contain: %s", prefix16(*assertion.Stderr.Contains)) + } + } + return true, "" +} + +func (h *AvailableEventHandler) distinct(msgs []string) []string { + seen := make(map[string]bool) + result := make([]string, 0) + for _, msg := range msgs { + if !seen[msg] { + seen[msg] = true + result = append(result, msg) + } + } + return result +} + +func GetComponentAvailablePolicy(compDef *appsv1.ComponentDefinition) appsv1.ComponentAvailable { + timeWindowSeconds := func() *int32 { + periodSeconds := int32(0) + if compDef.Spec.LifecycleActions != nil && compDef.Spec.LifecycleActions.AvailableProbe != nil { + periodSeconds = compDef.Spec.LifecycleActions.AvailableProbe.PeriodSeconds + } + return pointer.Int32(probeReportPeriodSeconds(periodSeconds) * 2) + } + + // has available policy defined + if compDef.Spec.Available != nil { + policy := *compDef.Spec.Available + if policy.WithProbe != nil && policy.WithProbe.TimeWindowSeconds == nil { + policy.WithProbe.TimeWindowSeconds = timeWindowSeconds() + } + return policy + } + + // has available probe defined + if compDef.Spec.LifecycleActions != nil && compDef.Spec.LifecycleActions.AvailableProbe != nil { + return appsv1.ComponentAvailable{ + WithProbe: &appsv1.ComponentAvailableWithProbe{ + TimeWindowSeconds: timeWindowSeconds(), + Condition: &appsv1.ComponentAvailableCondition{ + ComponentAvailableExpression: appsv1.ComponentAvailableExpression{ + All: &appsv1.ComponentAvailableProbeAssertion{ + ActionAssertion: appsv1.ActionAssertion{ + Succeed: pointer.Bool(true), + }, + Strict: pointer.Bool(true), + }, + }, + }, + Description: "all replicas are available", + }, + } + } + + // use phases as default policy + return appsv1.ComponentAvailable{ + // TODO: replicas == 0, stopped, updating, abnormal? + WithPhases: pointer.String(string(appsv1.RunningClusterCompPhase)), + } +} diff --git a/pkg/controller/component/available_test.go b/pkg/controller/component/available_test.go new file mode 100644 index 00000000000..0d170a4dad1 --- /dev/null +++ b/pkg/controller/component/available_test.go @@ -0,0 +1,722 @@ +/* +Copyright (C) 2022-2024 ApeCloud Co., Ltd + +This file is part of KubeBlocks project + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ + +package component + +import ( + "encoding/json" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/pointer" + + appsv1 "github.com/apecloud/kubeblocks/apis/apps/v1" + intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" + "github.com/apecloud/kubeblocks/pkg/kbagent/proto" +) + +var _ = Describe("Available", func() { + cleanEnv := func() { + // must wait till resources deleted and no longer existed before the testcases start, + // otherwise if later it needs to create some new resource objects with the same name, + // in race conditions, it will find the existence of old objects, resulting failure to + // create the new objects. + By("clean resources") + } + + BeforeEach(func() { + cleanEnv() + }) + + AfterEach(func() { + cleanEnv() + }) + + Context("handle event", func() { + var ( + compDef *appsv1.ComponentDefinition + comp *appsv1.Component + availableTimeWindow = int32(10) + ) + + BeforeEach(func() { + compDef = &appsv1.ComponentDefinition{ + Spec: appsv1.ComponentDefinitionSpec{ + Available: &appsv1.ComponentAvailable{ + WithProbe: &appsv1.ComponentAvailableWithProbe{ + TimeWindowSeconds: &availableTimeWindow, + // has the leader, and majority replicas have roles + Condition: &appsv1.ComponentAvailableCondition{ + And: []appsv1.ComponentAvailableExpression{ + { + Majority: &appsv1.ComponentAvailableProbeAssertion{ + Or: []appsv1.ActionAssertion{ + { + Succeed: pointer.Bool(true), + Stdout: &appsv1.ActionOutputMatcher{ + EqualTo: pointer.String("leader"), + }, + }, + { + Succeed: pointer.Bool(true), + Stdout: &appsv1.ActionOutputMatcher{ + EqualTo: pointer.String("follower"), + }, + }, + }, + }, + }, + { + Any: &appsv1.ComponentAvailableProbeAssertion{ + ActionAssertion: appsv1.ActionAssertion{ + Succeed: pointer.Bool(true), + Stdout: &appsv1.ActionOutputMatcher{ + EqualTo: pointer.String("leader"), + }, + }, + }, + }, + }, + }, + }, + }, + LifecycleActions: &appsv1.ComponentLifecycleActions{ + AvailableProbe: &appsv1.Probe{ + Action: appsv1.Action{ + Exec: &appsv1.ExecAction{ + Command: []string{"echo", "available"}, + }, + }, + }, + }, + }, + } + comp = &appsv1.Component{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster-comp", + }, + Spec: appsv1.ComponentSpec{ + Replicas: 3, + }, + Status: appsv1.ComponentStatus{}, + } + }) + + reqCtx := func() intctrlutil.RequestCtx { + return intctrlutil.RequestCtx{ + Ctx: ctx, + Log: logger, + Recorder: recorder, + } + }() + + statusMessageWithProbeEvents := func(events []probeEvent) { + message, ok := json.Marshal(&events) + Expect(ok).Should(BeNil()) + comp.Status.Message = map[string]string{ + availableProbeMessageKey: string(message), + } + } + + It("not probe event", func() { + h := &AvailableEventHandler{} + + event := &corev1.Event{ + InvolvedObject: corev1.ObjectReference{ + FieldPath: proto.ProbeEventFieldPath, + }, + Reason: "roleProbe", + ReportingController: proto.ProbeEventReportingController, + } + err := h.Handle(k8sClient, reqCtx, reqCtx.Recorder, event) + Expect(err).Should(Succeed()) + }) + + It("ok", func() { + h := &AvailableEventHandler{} + + statusMessageWithProbeEvents([]probeEvent{ + { + PodName: "test-cluster-comp-0", + Timestamp: time.Now().Add(-5 * time.Second), + Code: 0, + Stdout: []byte("leader"), + }, + { + PodName: "test-cluster-comp-1", + Timestamp: time.Now().Add(-5 * -time.Second), + Code: 0, + Stdout: []byte(""), // has no role + }, + }) + event := probeEvent{ + PodName: "test-cluster-comp-2", + Timestamp: time.Now().Add(-1 * -time.Second), + Code: 0, + Stdout: []byte("follower"), + } + available, _, err := h.handleEvent(event, comp, compDef) + Expect(err).Should(Succeed()) + Expect(*available).Should(BeTrue()) + }) + + It("has no event", func() { + h := &AvailableEventHandler{} + + event := probeEvent{} + available, _, err := h.handleEvent(event, comp, compDef) + Expect(err).Should(Succeed()) + Expect(*available).Should(BeFalse()) + }) + + It("duplicate events", func() { + h := &AvailableEventHandler{} + + statusMessageWithProbeEvents([]probeEvent{ + { + PodName: "test-cluster-comp-0", + Timestamp: time.Now().Add(-5 * time.Second), + Code: 0, + Stdout: []byte("leader"), + }, + { + PodName: "test-cluster-comp-1", + Timestamp: time.Now().Add(-5 * -time.Second), + Code: 0, + Stdout: []byte("follower"), + }, + { + PodName: "test-cluster-comp-2", + Timestamp: time.Now().Add(-5 * -time.Second), + Code: 0, + Stdout: []byte("follower"), + }, + }) + event := probeEvent{ + PodName: "test-cluster-comp-2", + Timestamp: time.Now().Add(-1 * -time.Second), + Code: 0, + Stdout: []byte("follower"), // duplicate event + } + available, _, err := h.handleEvent(event, comp, compDef) + Expect(err).Should(Succeed()) + Expect(*available).Should(BeTrue()) + }) + + It("event expired", func() { + h := &AvailableEventHandler{} + + statusMessageWithProbeEvents([]probeEvent{ + { + PodName: "test-cluster-comp-0", + Timestamp: time.Now().Add(-15 * time.Second), // expired + Code: 0, + Stdout: []byte("leader"), + }, + { + PodName: "test-cluster-comp-1", + Timestamp: time.Now().Add(-15 * -time.Second), // expired + Code: 0, + Stdout: []byte("follower"), + }, + { + PodName: "test-cluster-comp-2", + Timestamp: time.Now().Add(-15 * -time.Second), // expired + Code: 0, + Stdout: []byte("follower"), + }, + }) + event := probeEvent{ + PodName: "test-cluster-comp-2", + Timestamp: time.Now().Add(-1 * -time.Second), + Code: 0, + Stdout: []byte("follower"), + } + available, _, err := h.handleEvent(event, comp, compDef) + Expect(err).Should(Succeed()) + Expect(*available).Should(BeFalse()) + }) + + It("has new event and keep", func() { + h := &AvailableEventHandler{} + + statusMessageWithProbeEvents([]probeEvent{ + { + PodName: "test-cluster-comp-0", + Timestamp: time.Now().Add(-5 * time.Second), + Code: 0, + Stdout: []byte("leader"), + }, + { + PodName: "test-cluster-comp-1", + Timestamp: time.Now().Add(-5 * -time.Second), + Code: 0, + Stdout: []byte("follower"), + }, + { + PodName: "test-cluster-comp-2", + Timestamp: time.Now().Add(-15 * -time.Second), // expired + Code: 0, + Stdout: []byte("follower"), + }, + }) + event := probeEvent{ + PodName: "test-cluster-comp-2", + Timestamp: time.Now().Add(-1 * -time.Second), + Code: 0, + Stdout: []byte("follower"), // new event + } + available, _, err := h.handleEvent(event, comp, compDef) + Expect(err).Should(Succeed()) + Expect(*available).Should(BeTrue()) + }) + + It("probe event in annotation", func() { + h := &AvailableEventHandler{} + + statusMessageWithProbeEvents([]probeEvent{ + { + PodName: "test-cluster-comp-0", + Timestamp: time.Now().Add(-5 * time.Second), + Code: 0, + Stdout: []byte("leader"), + }, + }) + Expect(comp.Status.Message).ShouldNot(BeNil()) + Expect(comp.Status.Message[availableProbeMessageKey]).ShouldNot(BeEmpty()) + message := comp.Status.Message[availableProbeMessageKey] + + event := probeEvent{ + PodName: "test-cluster-comp-2", + Timestamp: time.Now().Add(-3 * -time.Second), + Code: 0, + Stdout: []byte("follower"), + } + available, _, err := h.handleEvent(event, comp, compDef) + Expect(err).Should(Succeed()) + Expect(*available).Should(BeTrue()) + + Expect(comp.Status.Message[availableProbeMessageKey]).ShouldNot(Equal(message)) + events := make([]probeEvent, 0) + Expect(json.Unmarshal([]byte(comp.Status.Message[availableProbeMessageKey]), &events)).Should(Succeed()) + Expect(events).Should(HaveLen(2)) + Expect(events[0].PodName).Should(Or(Equal("test-cluster-comp-0"), Equal("test-cluster-comp-2"))) + Expect(events[1].PodName).Should(Or(Equal("test-cluster-comp-0"), Equal("test-cluster-comp-2"))) + }) + + It("strict all", func() { + h := &AvailableEventHandler{} + + // all has leader or follower + compDef.Spec.Available.WithProbe.Condition = &appsv1.ComponentAvailableCondition{ + ComponentAvailableExpression: appsv1.ComponentAvailableExpression{ + All: &appsv1.ComponentAvailableProbeAssertion{ + Or: []appsv1.ActionAssertion{ + { + Succeed: pointer.Bool(true), + Stdout: &appsv1.ActionOutputMatcher{ + EqualTo: pointer.String("leader"), + }, + }, + { + Succeed: pointer.Bool(true), + Stdout: &appsv1.ActionOutputMatcher{ + EqualTo: pointer.String("follower"), + }, + }, + }, + Strict: pointer.Bool(true), + }, + }, + } + statusMessageWithProbeEvents([]probeEvent{ + { + PodName: "test-cluster-comp-0", + Timestamp: time.Now().Add(-5 * time.Second), + Code: 0, + Stdout: []byte("leader"), + }, + }) + event := probeEvent{ + PodName: "test-cluster-comp-1", + Timestamp: time.Now().Add(-3 * -time.Second), + Code: 0, + Stdout: []byte("follower"), + } + available, _, err := h.handleEvent(event, comp, compDef) + Expect(err).Should(Succeed()) + Expect(*available).Should(BeFalse()) + + // new event for last replica + event = probeEvent{ + PodName: "test-cluster-comp-2", + Timestamp: time.Now().Add(-1 * -time.Second), + Code: 0, + Stdout: []byte("follower"), + } + available, _, err = h.handleEvent(event, comp, compDef) + Expect(err).Should(Succeed()) + Expect(*available).Should(BeTrue()) + }) + + It("deleted replicas - available", func() { + h := &AvailableEventHandler{} + + statusMessageWithProbeEvents([]probeEvent{ + { + PodName: "test-cluster-comp-0", + Timestamp: time.Now().Add(-5 * time.Second), + Code: 0, + Stdout: []byte("leader"), + }, + { + PodName: "test-cluster-comp-1", + Timestamp: time.Now().Add(-5 * -time.Second), + Code: 0, + Stdout: []byte("follower"), + }, + { + PodName: "test-cluster-comp-3", // replica 3 is deleted + Timestamp: time.Now().Add(-5 * -time.Second), + Code: 0, + Stdout: []byte("follower"), + }, + }) + event := probeEvent{ + PodName: "test-cluster-comp-2", + Timestamp: time.Now().Add(-1 * -time.Second), + Code: 0, + Stdout: []byte("follower"), + } + available, _, err := h.handleEvent(event, comp, compDef) + Expect(err).Should(Succeed()) + Expect(*available).Should(BeTrue()) + }) + + It("deleted replicas - unavailable", func() { + h := &AvailableEventHandler{} + + statusMessageWithProbeEvents([]probeEvent{ + { + PodName: "test-cluster-comp-0", + Timestamp: time.Now().Add(-5 * time.Second), + Code: 0, + Stdout: []byte("leader"), + }, + { + PodName: "test-cluster-comp-3", // replica 3 is deleted + Timestamp: time.Now().Add(-5 * -time.Second), + Code: 0, + Stdout: []byte("follower"), + }, + }) + event := probeEvent{ + PodName: "test-cluster-comp-2", + Timestamp: time.Now().Add(-1 * -time.Second), + Code: 0, + Stdout: []byte(""), // has no role + } + available, _, err := h.handleEvent(event, comp, compDef) + Expect(err).Should(Succeed()) + Expect(*available).Should(BeFalse()) + }) + }) + + Context("eval condition", func() { + It("all succeed - ok", func() { + h := &AvailableEventHandler{} + + cond := appsv1.ComponentAvailableCondition{ + ComponentAvailableExpression: appsv1.ComponentAvailableExpression{ + All: &appsv1.ComponentAvailableProbeAssertion{ + ActionAssertion: appsv1.ActionAssertion{ + Succeed: pointer.Bool(true), + }, + }, + }, + } + events := []probeEvent{ + { + Code: 0, + Stdout: []byte("ok"), + }, + { + Code: 0, + Stdout: []byte("ok"), + }, + { + Code: 0, + Stdout: []byte("ok"), + }, + } + available, _ := h.evalCond(cond, 1, events) + Expect(available).Should(BeTrue()) + }) + + It("all succeed - fail", func() { + h := &AvailableEventHandler{} + + cond := appsv1.ComponentAvailableCondition{ + ComponentAvailableExpression: appsv1.ComponentAvailableExpression{ + All: &appsv1.ComponentAvailableProbeAssertion{ + ActionAssertion: appsv1.ActionAssertion{ + Succeed: pointer.Bool(true), + }, + }, + }, + } + events := []probeEvent{ + { + Code: 0, + Stdout: []byte("ok"), + }, + { + Code: 0, + Stdout: []byte("ok"), + }, + { + Code: -1, + Stderr: []byte("command not found"), + }, + } + available, _ := h.evalCond(cond, 1, events) + Expect(available).Should(BeFalse()) + }) + + It("has leader - ok", func() { + h := &AvailableEventHandler{} + + cond := appsv1.ComponentAvailableCondition{ + ComponentAvailableExpression: appsv1.ComponentAvailableExpression{ + Any: &appsv1.ComponentAvailableProbeAssertion{ + ActionAssertion: appsv1.ActionAssertion{ + Succeed: pointer.Bool(true), + Stdout: &appsv1.ActionOutputMatcher{ + EqualTo: pointer.String("leader"), + }, + }, + }, + }, + } + events := []probeEvent{ + { + Code: 0, + Stdout: []byte("leader"), + }, + { + Code: 0, + Stdout: []byte("follower"), + }, + { + Code: -1, + Stderr: []byte("host is unreachable"), + }, + } + available, _ := h.evalCond(cond, 1, events) + Expect(available).Should(BeTrue()) + }) + + It("has leader - fail", func() { + h := &AvailableEventHandler{} + + cond := appsv1.ComponentAvailableCondition{ + ComponentAvailableExpression: appsv1.ComponentAvailableExpression{ + Any: &appsv1.ComponentAvailableProbeAssertion{ + ActionAssertion: appsv1.ActionAssertion{ + Succeed: pointer.Bool(true), + Stdout: &appsv1.ActionOutputMatcher{ + EqualTo: pointer.String("leader"), + }, + }, + }, + }, + } + events := []probeEvent{ + { + Code: 0, + Stdout: []byte("follower"), + }, + { + Code: 0, + Stdout: []byte("follower"), + }, + { + Code: -1, + Stderr: []byte("operation is timed-out"), + }, + } + available, _ := h.evalCond(cond, 1, events) + Expect(available).Should(BeFalse()) + }) + + It("has leader, majority replicas have roles - ok", func() { + h := &AvailableEventHandler{} + + cond := appsv1.ComponentAvailableCondition{ + And: []appsv1.ComponentAvailableExpression{ + { + Majority: &appsv1.ComponentAvailableProbeAssertion{ + Or: []appsv1.ActionAssertion{ + { + Succeed: pointer.Bool(true), + Stdout: &appsv1.ActionOutputMatcher{ + EqualTo: pointer.String("leader"), + }, + }, + { + Succeed: pointer.Bool(true), + Stdout: &appsv1.ActionOutputMatcher{ + EqualTo: pointer.String("follower"), + }, + }, + }, + }, + }, + { + Any: &appsv1.ComponentAvailableProbeAssertion{ + ActionAssertion: appsv1.ActionAssertion{ + Succeed: pointer.Bool(true), + Stdout: &appsv1.ActionOutputMatcher{ + EqualTo: pointer.String("leader"), + }, + }, + }, + }, + }, + } + events := []probeEvent{ + { + Code: 0, + Stdout: []byte("leader"), + }, + { + Code: 0, + Stdout: []byte("follower"), + }, + { + Code: 0, + Stdout: []byte("follower"), + }, + } + available, _ := h.evalCond(cond, 1, events) + Expect(available).Should(BeTrue()) + }) + + It("has leader, majority replicas have roles - fail", func() { + h := &AvailableEventHandler{} + + cond := appsv1.ComponentAvailableCondition{ + And: []appsv1.ComponentAvailableExpression{ + { + Majority: &appsv1.ComponentAvailableProbeAssertion{ + Or: []appsv1.ActionAssertion{ + { + Succeed: pointer.Bool(true), + Stdout: &appsv1.ActionOutputMatcher{ + EqualTo: pointer.String("leader"), + }, + }, + { + Succeed: pointer.Bool(true), + Stdout: &appsv1.ActionOutputMatcher{ + EqualTo: pointer.String("follower"), + }, + }, + }, + }, + }, + { + Any: &appsv1.ComponentAvailableProbeAssertion{ + ActionAssertion: appsv1.ActionAssertion{ + Succeed: pointer.Bool(true), + Stdout: &appsv1.ActionOutputMatcher{ + EqualTo: pointer.String("leader"), + }, + }, + }, + }, + }, + } + events := []probeEvent{ + { + Code: 0, + Stdout: []byte("follower"), + }, + { + Code: 0, + Stdout: []byte("follower"), + }, + { + Code: 0, + Stdout: []byte("learner"), + }, + } + available, _ := h.evalCond(cond, 1, events) + Expect(available).Should(BeFalse()) + }) + + It("has leader, has no FATAL errors", func() { + h := &AvailableEventHandler{} + + cond := appsv1.ComponentAvailableCondition{ + And: []appsv1.ComponentAvailableExpression{ + { + Any: &appsv1.ComponentAvailableProbeAssertion{ + ActionAssertion: appsv1.ActionAssertion{ + Succeed: pointer.Bool(true), + Stdout: &appsv1.ActionOutputMatcher{ + EqualTo: pointer.String("leader"), + }, + }, + }, + }, + { + None: &appsv1.ComponentAvailableProbeAssertion{ + ActionAssertion: appsv1.ActionAssertion{ + Stderr: &appsv1.ActionOutputMatcher{ + Contains: pointer.String("FATAL"), + }, + }, + }, + }, + }, + } + events := []probeEvent{ + { + Code: 0, + Stdout: []byte("leader"), + }, + { + Code: 0, + Stdout: []byte("follower"), + }, + { + Code: -1, + Stderr: []byte("[xxxx] FATAL: detected data is conrputed at offset 0x1234"), + }, + } + available, _ := h.evalCond(cond, 1, events) + Expect(available).Should(BeFalse()) + }) + }) +}) diff --git a/pkg/controller/component/kbagent.go b/pkg/controller/component/kbagent.go index 0d0d55a215e..98b4d34b71a 100644 --- a/pkg/controller/component/kbagent.go +++ b/pkg/controller/component/kbagent.go @@ -45,6 +45,9 @@ const ( minAvailablePort = 1025 maxAvailablePort = 65535 kbAgentDefaultPort = 3501 + + defaultProbeReportPeriodSeconds = 60 + minProbeReportPeriodSeconds = 15 ) var ( @@ -220,7 +223,13 @@ func buildKBAgentStartupEnvs(synthesizedComp *SynthesizedComponent) ([]corev1.En actions = append(actions, *a) } - if a, p := buildProbe4KBAgent(synthesizedComp.LifecycleActions.RoleProbe, "roleProbe"); a != nil && p != nil { + if a, p := buildProbe4KBAgent(synthesizedComp.LifecycleActions.RoleProbe, "roleProbe", synthesizedComp.FullCompName); a != nil && p != nil { + actions = append(actions, *a) + probes = append(probes, *p) + } + // TODO: how to schedule the execution of probes? + if a, p := buildProbe4KBAgent(synthesizedComp.LifecycleActions.AvailableProbe, availableProbe, synthesizedComp.FullCompName); a != nil && p != nil { + p.ReportPeriodSeconds = probeReportPeriodSeconds(p.PeriodSeconds) actions = append(actions, *a) probes = append(probes, *p) } @@ -228,6 +237,16 @@ func buildKBAgentStartupEnvs(synthesizedComp *SynthesizedComponent) ([]corev1.En return kbagent.BuildStartupEnv(actions, probes) } +func probeReportPeriodSeconds(periodSeconds int32) int32 { + if periodSeconds <= 0 { + return defaultProbeReportPeriodSeconds + } + if periodSeconds < minProbeReportPeriodSeconds { + return minProbeReportPeriodSeconds + } + return periodSeconds +} + func buildAction4KBAgent(action *appsv1.Action, name string) *proto.Action { if action == nil || action.Exec == nil { return nil @@ -249,7 +268,7 @@ func buildAction4KBAgent(action *appsv1.Action, name string) *proto.Action { return a } -func buildProbe4KBAgent(probe *appsv1.Probe, name string) (*proto.Action, *proto.Probe) { +func buildProbe4KBAgent(probe *appsv1.Probe, name, instance string) (*proto.Action, *proto.Probe) { if probe == nil || probe.Exec == nil { return nil, nil } @@ -260,7 +279,7 @@ func buildProbe4KBAgent(probe *appsv1.Probe, name string) (*proto.Action, *proto PeriodSeconds: probe.PeriodSeconds, SuccessThreshold: probe.SuccessThreshold, FailureThreshold: probe.FailureThreshold, - ReportPeriodSeconds: nil, // TODO: impl + Instance: instance, } return a, p } diff --git a/pkg/controller/component/suite_test.go b/pkg/controller/component/suite_test.go index f18af56d10f..98b3b7a2e91 100644 --- a/pkg/controller/component/suite_test.go +++ b/pkg/controller/component/suite_test.go @@ -32,6 +32,7 @@ import ( "go.uber.org/zap/zapcore" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" + "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" @@ -60,6 +61,7 @@ var testEnv *envtest.Environment var ctx context.Context var cancel context.CancelFunc var testCtx testutil.TestContext +var recorder record.EventRecorder var logger logr.Logger func init() { @@ -141,6 +143,7 @@ var _ = BeforeSuite(func() { Expect(err).ToNot(HaveOccurred()) testCtx = testutil.NewDefaultTestContext(ctx, k8sClient, testEnv) + recorder = k8sManager.GetEventRecorderFor("available-event-handler") go func() { defer GinkgoRecover() diff --git a/pkg/controller/component/workload_utils.go b/pkg/controller/component/workload_utils.go index cb72618c6b8..9d3d16d269c 100644 --- a/pkg/controller/component/workload_utils.go +++ b/pkg/controller/component/workload_utils.go @@ -131,9 +131,7 @@ func GenerateAllPodNames( compReplicas int32, instances []appsv1.InstanceTemplate, offlineInstances []string, - clusterName, fullCompName string) ([]string, error) { - workloadName := constant.GenerateWorkloadNamePattern(clusterName, fullCompName) var templates []instanceset.InstanceTemplate for i := range instances { templates = append(templates, &workloads.InstanceTemplate{ @@ -141,7 +139,7 @@ func GenerateAllPodNames( Replicas: instances[i].Replicas, }) } - return instanceset.GenerateAllInstanceNames(workloadName, compReplicas, templates, offlineInstances, workloads.Ordinals{}) + return instanceset.GenerateAllInstanceNames(fullCompName, compReplicas, templates, offlineInstances, workloads.Ordinals{}) } // GenerateAllPodNamesToSet generate all pod names for a component @@ -152,7 +150,8 @@ func GenerateAllPodNamesToSet( offlineInstances []string, clusterName, fullCompName string) (map[string]string, error) { - instanceNames, err := GenerateAllPodNames(compReplicas, instances, offlineInstances, clusterName, fullCompName) + compName := constant.GenerateClusterComponentName(clusterName, fullCompName) + instanceNames, err := GenerateAllPodNames(compReplicas, instances, offlineInstances, compName) if err != nil { return nil, err } diff --git a/pkg/controller/instanceset/pod_role_event_handler.go b/pkg/controller/instanceset/pod_role_event_handler.go index 0359e14ed8c..26eca264bb0 100644 --- a/pkg/controller/instanceset/pod_role_event_handler.go +++ b/pkg/controller/instanceset/pod_role_event_handler.go @@ -102,7 +102,7 @@ func (h *PodRoleEventHandler) Handle(cli client.Client, reqCtx intctrlutil.Reque } func (h *PodRoleEventHandler) transformKBAgentProbeEvent(logger logr.Logger, event *corev1.Event) *corev1.Event { - if event.ReportingController != "kbagent" || event.Reason != "roleProbe" { + if event.ReportingController != proto.ProbeEventReportingController || event.Reason != "roleProbe" { return event } diff --git a/pkg/kbagent/proto/proto.go b/pkg/kbagent/proto/proto.go index e30463f6afd..dee8c8d1b88 100644 --- a/pkg/kbagent/proto/proto.go +++ b/pkg/kbagent/proto/proto.go @@ -55,17 +55,25 @@ type ActionResponse struct { // TODO: define the event spec for probe or async action type Probe struct { + Instance string `json:"instance"` Action string `json:"action"` InitialDelaySeconds int32 `json:"initialDelaySeconds,omitempty"` PeriodSeconds int32 `json:"periodSeconds,omitempty"` SuccessThreshold int32 `json:"successThreshold,omitempty"` FailureThreshold int32 `json:"failureThreshold,omitempty"` - ReportPeriodSeconds *int32 `json:"reportPeriodSeconds,omitempty"` + ReportPeriodSeconds int32 `json:"reportPeriodSeconds,omitempty"` } type ProbeEvent struct { - Probe string `json:"probe,omitempty"` - Code int32 `json:"code,omitempty"` - Output []byte `json:"output,omitempty"` - Message string `json:"message,omitempty"` + Instance string `json:"instance"` + Probe string `json:"probe"` + Code int32 `json:"code"` + Output []byte `json:"output,omitempty"` // output of the probe on success, or latest succeed output on failure + Message string `json:"message,omitempty"` // message of the probe on failure } + +const ( + ProbeEventFieldPath = "spec.containers{kbagent}" + ProbeEventReportingController = "kbagent" + ProbeEventSourceComponent = "kbagent" +) diff --git a/pkg/kbagent/service/probe.go b/pkg/kbagent/service/probe.go index a981ea70ab8..c5a70573374 100644 --- a/pkg/kbagent/service/probe.go +++ b/pkg/kbagent/service/probe.go @@ -78,6 +78,7 @@ func (s *probeService) Start() error { runner := &probeRunner{ logger: s.logger.WithValues("probe", name), actionService: s.actionService, + latestEvent: make(chan proto.ProbeEvent, 1), } go runner.run(s.probes[name]) s.runners[name] = runner @@ -96,6 +97,7 @@ type probeRunner struct { succeedCount int64 failedCount int64 latestOutput []byte + latestEvent chan proto.ProbeEvent } func (r *probeRunner) run(probe *proto.Probe) { @@ -105,6 +107,13 @@ func (r *probeRunner) run(probe *proto.Probe) { time.Sleep(time.Duration(probe.InitialDelaySeconds) * time.Second) } + // launch report loop first + r.launchReportLoop(probe) + + r.launchRunLoop(probe) +} + +func (r *probeRunner) launchRunLoop(probe *proto.Probe) { if probe.PeriodSeconds <= 0 { probe.PeriodSeconds = defaultProbePeriodSeconds } @@ -115,8 +124,12 @@ func (r *probeRunner) run(probe *proto.Probe) { } func (r *probeRunner) runLoop(probe *proto.Probe) { + runOnce := func() ([]byte, error) { + return r.actionService.handleRequest(context.Background(), &proto.ActionRequest{Action: probe.Action}) + } + for range r.ticker.C { - output, err := r.runOnce(probe) + output, err := runOnce() if err == nil { r.succeedCount++ r.failedCount = 0 @@ -133,18 +146,54 @@ func (r *probeRunner) runLoop(probe *proto.Probe) { } } -func (r *probeRunner) runOnce(probe *proto.Probe) ([]byte, error) { - return r.actionService.handleRequest(context.Background(), &proto.ActionRequest{Action: probe.Action}) +func (r *probeRunner) launchReportLoop(probe *proto.Probe) { + if probe.ReportPeriodSeconds <= 0 { + return + } + + if probe.ReportPeriodSeconds < probe.PeriodSeconds { + probe.ReportPeriodSeconds = probe.PeriodSeconds + } + + go func() { + ticker := time.NewTicker(time.Duration(probe.ReportPeriodSeconds) * time.Second) + defer ticker.Stop() + + var latestReportedEvent *proto.ProbeEvent + for range ticker.C { + latestEvent := gather(r.latestEvent) + if latestEvent == nil && latestReportedEvent != nil { + latestEvent = latestReportedEvent + } + if latestEvent != nil { + r.logger.Info("report probe event periodically", + "code", latestEvent.Code, "output", outputPrefix(latestEvent.Output), "message", latestEvent.Message) + r.sendEvent(latestEvent) + } + latestReportedEvent = latestEvent + } + }() } func (r *probeRunner) report(probe *proto.Probe, output []byte, err error) { + var latestEvent *proto.ProbeEvent + succeed, thresholdPoint := r.succeed(probe) if succeed && thresholdPoint || succeed && !thresholdPoint && !reflect.DeepEqual(output, r.latestOutput) { - r.sendEvent(probe.Action, 0, output, "") + latestEvent = r.buildNSendEvent(probe.Instance, probe.Action, 0, output, "") } if r.fail(probe) { - r.sendEvent(probe.Action, -1, r.latestOutput, err.Error()) + latestEvent = r.buildNSendEvent(probe.Instance, probe.Action, -1, r.latestOutput, err.Error()) + } + + if latestEvent != nil { + select { + case r.latestEvent <- *latestEvent: + default: + gather(r.latestEvent) // drain the channel + r.latestEvent <- *latestEvent + } } } @@ -170,20 +219,29 @@ func (r *probeRunner) fail(probe *proto.Probe) bool { return false } -func (r *probeRunner) sendEvent(probe string, code int32, output []byte, message string) { - prefixLen := min(len(output), 32) - r.logger.Info("send probe event", "code", code, "output", string(output[:prefixLen]), "message", message) - - eventMsg := &proto.ProbeEvent{ - Probe: probe, - Code: code, - Message: message, - Output: output, +func (r *probeRunner) buildNSendEvent(instance, probe string, code int32, output []byte, message string) *proto.ProbeEvent { + r.logger.Info("send probe event", "probe", probe, "code", code, "output", outputPrefix(output), "message", message) + event := &proto.ProbeEvent{ + Instance: instance, + Probe: probe, + Code: code, + Output: output, + Message: message, } - msg, err := json.Marshal(&eventMsg) - if err != nil { - r.logger.Error(err, "failed to marshal probe event") - return + r.sendEvent(event) + return event +} + +func (r *probeRunner) sendEvent(event *proto.ProbeEvent) { + msg, err := json.Marshal(&event) + if err == nil { + util.SendEventWithMessage(&r.logger, event.Probe, string(msg)) + } else { + r.logger.Error(err, fmt.Sprintf("failed to marshal probe event, probe: %s", event.Probe)) } - util.SendEventWithMessage(&r.logger, probe, string(msg)) +} + +func outputPrefix(output []byte) string { + prefixLen := min(len(output), 32) + return string(output[:prefixLen]) } diff --git a/pkg/kbagent/service/probe_test.go b/pkg/kbagent/service/probe_test.go index 8cb2119be7a..04784fe9b1d 100644 --- a/pkg/kbagent/service/probe_test.go +++ b/pkg/kbagent/service/probe_test.go @@ -49,7 +49,7 @@ var _ = Describe("probe", func() { PeriodSeconds: 1, SuccessThreshold: 1, FailureThreshold: 1, - ReportPeriodSeconds: nil, + ReportPeriodSeconds: 0, }, } @@ -62,7 +62,6 @@ var _ = Describe("probe", func() { Expect(err).Should(BeNil()) }) - // func newProbeService(logger logr.Logger, actionService *actionService, probes []proto.Probe) (*probeService, error) { It("new", func() { service, err := newProbeService(logr.New(nil), actionSvc, probes) Expect(err).Should(BeNil()) diff --git a/pkg/kbagent/util/event.go b/pkg/kbagent/util/event.go index bfee74b539e..76d5e5127ef 100644 --- a/pkg/kbagent/util/event.go +++ b/pkg/kbagent/util/event.go @@ -32,6 +32,8 @@ import ( "k8s.io/apimachinery/pkg/util/rand" "k8s.io/client-go/kubernetes" ctlruntime "sigs.k8s.io/controller-runtime" + + "github.com/apecloud/kubeblocks/pkg/kbagent/proto" ) const ( @@ -44,7 +46,7 @@ func SendEventWithMessage(logger *logr.Logger, reason string, message string) { event := createEvent(reason, message) err := sendEvent(event) if logger != nil && err != nil { - logger.Error(err, "send event failed") + logger.Error(err, fmt.Sprintf("send event failed, reason: %s, message: %s", reason, message)) } }() } @@ -60,18 +62,18 @@ func createEvent(reason string, message string) *corev1.Event { Namespace: namespace(), Name: podName(), UID: types.UID(podUID()), - FieldPath: "spec.containers{kbagent}", + FieldPath: proto.ProbeEventFieldPath, }, Reason: reason, Message: message, Source: corev1.EventSource{ - Component: "kbagent", + Component: proto.ProbeEventSourceComponent, Host: nodeName(), }, FirstTimestamp: metav1.Now(), LastTimestamp: metav1.Now(), EventTime: metav1.NowMicro(), - ReportingController: "kbagent", + ReportingController: proto.ProbeEventReportingController, ReportingInstance: podName(), Action: reason, Type: "Normal", diff --git a/pkg/testutil/apps/componentdefinition_factory.go b/pkg/testutil/apps/componentdefinition_factory.go index 04346c1e7dc..0d8e586512f 100644 --- a/pkg/testutil/apps/componentdefinition_factory.go +++ b/pkg/testutil/apps/componentdefinition_factory.go @@ -284,6 +284,11 @@ func (f *MockComponentDefinitionFactory) SetPodManagementPolicy(policy *appsv1.P return f } +func (f *MockComponentDefinitionFactory) SetAvailable(available *kbappsv1.ComponentAvailable) *MockComponentDefinitionFactory { + f.Get().Spec.Available = available + return f +} + func (f *MockComponentDefinitionFactory) AddRole(name string, serviceable, writable bool) *MockComponentDefinitionFactory { role := kbappsv1.ReplicaRole{ Name: name,