diff --git a/api/v1/ytsaurus_types.go b/api/v1/ytsaurus_types.go
index 44b34097..3367ba69 100644
--- a/api/v1/ytsaurus_types.go
+++ b/api/v1/ytsaurus_types.go
@@ -673,7 +673,7 @@ type YtsaurusSpec struct {
EnableFullUpdate bool `json:"enableFullUpdate"`
//+optional
//+optional
- // Deprecated: UpdateSelector is an experimental field. Behaviour may change.
+ // Deprecated: UpdateSelector is going to be removed soon. Please use UpdateSelectors instead.
UpdateSelector UpdateSelector `json:"updateSelector"`
//+optional
@@ -761,6 +761,27 @@ type TabletCellBundleInfo struct {
type UpdateSelector string
+const (
+ // UpdateSelectorUnspecified means that selector is disabled and would be ignored completely.
+ UpdateSelectorUnspecified UpdateSelector = ""
+ // UpdateSelectorNothing means that no component could be updated.
+ UpdateSelectorNothing UpdateSelector = "Nothing"
+ // UpdateSelectorMasterOnly means that only master could be updated.
+ UpdateSelectorMasterOnly UpdateSelector = "MasterOnly"
+ // UpdateSelectorTabletNodesOnly means that only data nodes could be updated
+ UpdateSelectorDataNodesOnly UpdateSelector = "DataNodesOnly"
+ // UpdateSelectorTabletNodesOnly means that only tablet nodes could be updated
+ UpdateSelectorTabletNodesOnly UpdateSelector = "TabletNodesOnly"
+ // UpdateSelectorExecNodesOnly means that only tablet nodes could be updated
+ UpdateSelectorExecNodesOnly UpdateSelector = "ExecNodesOnly"
+ // UpdateSelectorStatelessOnly means that only stateless components (everything but master, data nodes, and tablet nodes)
+ // could be updated.
+ UpdateSelectorStatelessOnly UpdateSelector = "StatelessOnly"
+ // UpdateSelectorEverything means that all components could be updated.
+ // With this setting and if master or tablet nodes need update all the components would be updated.
+ UpdateSelectorEverything UpdateSelector = "Everything"
+)
+
type ComponentUpdateSelector struct {
//+optional
ComponentType consts.ComponentType `json:"componentType,omitempty"`
@@ -774,14 +795,6 @@ type ComponentUpdateSelector struct {
type UpdateFlow string
-const (
- UpdateFlowNone UpdateFlow = ""
- UpdateFlowStateless UpdateFlow = "Stateless"
- UpdateFlowMaster UpdateFlow = "Master"
- UpdateFlowTabletNodes UpdateFlow = "TabletNodes"
- UpdateFlowFull UpdateFlow = "Full"
-)
-
type UpdateStatus struct {
//+kubebuilder:default:=None
State UpdateState `json:"state,omitempty"`
diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go
index 31ab77ac..665c9869 100644
--- a/api/v1/zz_generated.deepcopy.go
+++ b/api/v1/zz_generated.deepcopy.go
@@ -419,6 +419,21 @@ func (in *Component) DeepCopy() *Component {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ComponentUpdateSelector) DeepCopyInto(out *ComponentUpdateSelector) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentUpdateSelector.
+func (in *ComponentUpdateSelector) DeepCopy() *ComponentUpdateSelector {
+ if in == nil {
+ return nil
+ }
+ out := new(ComponentUpdateSelector)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ControllerAgentsSpec) DeepCopyInto(out *ControllerAgentsSpec) {
*out = *in
@@ -1999,6 +2014,11 @@ func (in *YtsaurusSpec) DeepCopyInto(out *YtsaurusSpec) {
*out = new(OauthServiceSpec)
(*in).DeepCopyInto(*out)
}
+ if in.UpdateSelectors != nil {
+ in, out := &in.UpdateSelectors, &out.UpdateSelectors
+ *out = make([]ComponentUpdateSelector, len(*in))
+ copy(*out, *in)
+ }
if in.NodeSelector != nil {
in, out := &in.NodeSelector, &out.NodeSelector
*out = make(map[string]string, len(*in))
diff --git a/config/crd/bases/cluster.ytsaurus.tech_ytsaurus.yaml b/config/crd/bases/cluster.ytsaurus.tech_ytsaurus.yaml
index 74f5ec20..5f6f7d87 100644
--- a/config/crd/bases/cluster.ytsaurus.tech_ytsaurus.yaml
+++ b/config/crd/bases/cluster.ytsaurus.tech_ytsaurus.yaml
@@ -39570,8 +39570,7 @@ spec:
uiImage:
type: string
updateSelector:
- description: 'Deprecated: UpdateSelector is an experimental field.
- Behaviour may change.'
+ description: 'Deprecated: UpdateSelector is going to be removed soon.'
type: string
updateSelectors:
description: Controls the components that should be updated during
diff --git a/controllers/sync.go b/controllers/sync.go
index 579c7d8d..35465b25 100644
--- a/controllers/sync.go
+++ b/controllers/sync.go
@@ -15,59 +15,43 @@ import (
apiProxy "github.com/ytsaurus/ytsaurus-k8s-operator/pkg/apiproxy"
)
-func getFlowFromComponent(component consts.ComponentType) ytv1.UpdateFlow {
- if component == consts.MasterType {
- return ytv1.UpdateFlowMaster
- }
- if component == consts.TabletNodeType {
- return ytv1.UpdateFlowTabletNodes
- }
- if component == consts.DataNodeType || component == consts.ExecNodeType {
- return ytv1.UpdateFlowFull
- }
- return ytv1.UpdateFlowStateless
-}
-
-func canUpdateComponent(selectors []ytv1.ComponentUpdateSelector, component ytv1.Component) (bool, error) {
+func canUpdateComponent(selectors []ytv1.ComponentUpdateSelector, component ytv1.Component) bool {
for _, selector := range selectors {
- if selector.ComponentType != "" {
- if selector.ComponentType == component.Type {
- return true, nil
- }
- } else if selector.ComponentName != "" {
+ if selector.ComponentName != "" {
if selector.ComponentName == component.Name {
- return true, nil
+ return true
+ }
+ } else if selector.ComponentType != "" {
+ if selector.ComponentType == component.Type {
+ return true
}
} else {
switch selector.ComponentGroup {
case consts.ComponentGroupEverything:
- return true, nil
+ return true
case consts.ComponentGroupNothing:
- return false, nil
+ return false
case consts.ComponentGroupStateful:
if component.Type == consts.DataNodeType || component.Type == consts.TabletNodeType {
- return true, nil
+ return true
}
case consts.ComponentGroupStateless:
if component.Type != consts.DataNodeType && component.Type != consts.TabletNodeType && component.Type != consts.MasterType {
- return true, nil
+ return true
}
default:
- return false, fmt.Errorf("unexpected component group %s", selector.ComponentGroup)
+ return false
}
}
}
- return false, nil
+ return false
}
// Considers spec and decides if operator should proceed with update or block.
// Block case is indicated with non-empty blockMsg.
// If update is not blocked, updateMeta containing a chosen flow and the component names to update returned.
func chooseUpdatingComponents(spec ytv1.YtsaurusSpec, needUpdate []components.Component, allComponents []components.Component) (components []ytv1.Component, blockMsg string) {
- configuredSelectors := spec.UpdateSelectors
- if len(configuredSelectors) == 0 && spec.EnableFullUpdate {
- configuredSelectors = []ytv1.ComponentUpdateSelector{{ComponentGroup: consts.ComponentGroupEverything}}
- }
+ configuredSelectors := getEffectiveSelectors(spec)
needFullUpdate := false
var canUpdate []ytv1.Component
@@ -78,16 +62,13 @@ func chooseUpdatingComponents(spec ytv1.YtsaurusSpec, needUpdate []components.Co
Name: comp.GetName(),
Type: comp.GetType(),
}
- upd, err := canUpdateComponent(configuredSelectors, component)
- if err != nil {
- return nil, err.Error()
- }
+ upd := canUpdateComponent(configuredSelectors, component)
if upd {
canUpdate = append(canUpdate, component)
} else {
cannotUpdate = append(cannotUpdate, component)
}
- statelessCheck, err := canUpdateComponent([]ytv1.ComponentUpdateSelector{{ComponentGroup: consts.ComponentGroupStateless}}, component)
+ statelessCheck := canUpdateComponent([]ytv1.ComponentUpdateSelector{{ComponentGroup: consts.ComponentGroupStateless}}, component)
if !statelessCheck && component.Type != consts.DataNodeType {
needFullUpdate = true
}
@@ -110,6 +91,37 @@ func chooseUpdatingComponents(spec ytv1.YtsaurusSpec, needUpdate []components.Co
return canUpdate, ""
}
+func getEffectiveSelectors(spec ytv1.YtsaurusSpec) []ytv1.ComponentUpdateSelector {
+ if len(spec.UpdateSelectors) != 0 {
+ return spec.UpdateSelectors
+ }
+
+ if spec.UpdateSelector != ytv1.UpdateSelectorUnspecified {
+ switch spec.UpdateSelector {
+ case ytv1.UpdateSelectorNothing:
+ return []ytv1.ComponentUpdateSelector{{ComponentGroup: consts.ComponentGroupNothing}}
+ case ytv1.UpdateSelectorMasterOnly:
+ return []ytv1.ComponentUpdateSelector{{ComponentType: consts.MasterType}}
+ case ytv1.UpdateSelectorDataNodesOnly:
+ return []ytv1.ComponentUpdateSelector{{ComponentType: consts.DataNodeType}}
+ case ytv1.UpdateSelectorTabletNodesOnly:
+ return []ytv1.ComponentUpdateSelector{{ComponentType: consts.TabletNodeType}}
+ case ytv1.UpdateSelectorExecNodesOnly:
+ return []ytv1.ComponentUpdateSelector{{ComponentType: consts.ExecNodeType}}
+ case ytv1.UpdateSelectorStatelessOnly:
+ return []ytv1.ComponentUpdateSelector{{ComponentGroup: consts.ComponentGroupStateless}}
+ case ytv1.UpdateSelectorEverything:
+ return []ytv1.ComponentUpdateSelector{{ComponentGroup: consts.ComponentGroupEverything}}
+ }
+ }
+
+ if spec.EnableFullUpdate {
+ return []ytv1.ComponentUpdateSelector{{ComponentGroup: consts.ComponentGroupEverything}}
+ }
+
+ return []ytv1.ComponentUpdateSelector{{ComponentGroup: consts.ComponentGroupStateless}}
+}
+
func convertToComponent(components []components.Component) []ytv1.Component {
var result []ytv1.Component
for _, c := range components {
diff --git a/docs/api.md b/docs/api.md
index 1677ec60..5c537090 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -344,6 +344,24 @@ _Appears in:_
| `type` _[ComponentType](#componenttype)_ | | | |
+#### ComponentUpdateSelector
+
+
+
+
+
+
+
+_Appears in:_
+- [YtsaurusSpec](#ytsaurusspec)
+
+| Field | Description | Default | Validation |
+| --- | --- | --- | --- |
+| `componentType` _[ComponentType](#componenttype)_ | | | |
+| `componentGroup` _[ComponentGroup](#componentgroup)_ | | | |
+| `componentName` _string_ | | | |
+
+
#### ControllerAgentsSpec
@@ -2134,13 +2152,6 @@ _Underlying type:_ _string_
_Appears in:_
- [UpdateStatus](#updatestatus)
-| Field | Description |
-| --- | --- |
-| `` | |
-| `Stateless` | |
-| `Master` | |
-| `TabletNodes` | |
-| `Full` | |
#### UpdateSelector
@@ -2317,7 +2328,8 @@ _Appears in:_
| `oauthService` _[OauthServiceSpec](#oauthservicespec)_ | | | |
| `isManaged` _boolean_ | | true | |
| `enableFullUpdate` _boolean_ | | true | |
-| `updateSelector` _[UpdateSelector](#updateselector)_ | UpdateSelector is an experimental field. Behaviour may change.
If UpdateSelector is not empty EnableFullUpdate is ignored. | | Enum: [ Nothing MasterOnly DataNodesOnly TabletNodesOnly ExecNodesOnly StatelessOnly Everything]
|
+| `updateSelector` _[UpdateSelector](#updateselector)_ | Deprecated: UpdateSelector is going to be removed soon. Please use UpdateSelectors instead. | | |
+| `updateSelectors` _[ComponentUpdateSelector](#componentupdateselector) array_ | Controls the components that should be updated during the update process. | | |
| `nodeSelector` _object (keys:string, values:string)_ | | | |
| `tolerations` _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#toleration-v1-core) array_ | | | |
| `dnsConfig` _[PodDNSConfig](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#poddnsconfig-v1-core)_ | DNSConfig allows customizing the DNS settings for the pods. | | |
diff --git a/ytop-chart/templates/crds/ytsaurus.cluster.ytsaurus.tech.yaml b/ytop-chart/templates/crds/ytsaurus.cluster.ytsaurus.tech.yaml
index 0a27bef5..cd3a35b5 100644
--- a/ytop-chart/templates/crds/ytsaurus.cluster.ytsaurus.tech.yaml
+++ b/ytop-chart/templates/crds/ytsaurus.cluster.ytsaurus.tech.yaml
@@ -39581,8 +39581,7 @@ spec:
uiImage:
type: string
updateSelector:
- description: 'Deprecated: UpdateSelector is an experimental field.
- Behaviour may change.'
+ description: 'Deprecated: UpdateSelector is going to be removed soon.'
type: string
updateSelectors:
description: Controls the components that should be updated during