diff --git a/CHANGELOG.md b/CHANGELOG.md index d737e28de..0ce5ee673 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - (Feature) (Platform) Service Handler - (Feature) (Platform) Service Handler Implementation - (Feature) (Platform) Packer +- (Feature) Manual Upgrade Mode ## [1.2.49](https://github.com/arangodb/kube-arangodb/tree/1.2.49) (2025-06-17) - (Maintenance) Optimize go.mod diff --git a/docs/api/ArangoDeployment.V1.md b/docs/api/ArangoDeployment.V1.md index 65bedc960..39c31db5d 100644 --- a/docs/api/ArangoDeployment.V1.md +++ b/docs/api/ArangoDeployment.V1.md @@ -230,6 +230,18 @@ LabelsMode Define labels mode which should be use while overriding labels *** +### .spec.agents.manualUpgradeMode + +Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L224) + +UpgradeMode Defines the manually triggered upgrade mode for the Member + +Possible Values: +* `"inplace"` (default) - Inplace Upgrade procedure (with Upgrade initContainer) +* `"replace"` - Replaces server instead of upgrading. Takes an effect only on DBServer + +*** + ### .spec.agents.maxCount Type: `integer` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L50) @@ -611,7 +623,7 @@ Links: ### .spec.agents.restartPolicy -Type: `core.RestartPolicy` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L224) +Type: `core.RestartPolicy` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L231) RestartPolicy for all pods within the group. @@ -852,13 +864,14 @@ Links: ### .spec.agents.upgradeMode -Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L217) +Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L218) UpgradeMode Defines the upgrade mode for the Member Possible Values: * `"inplace"` (default) - Inplace Upgrade procedure (with Upgrade initContainer) * `"replace"` - Replaces server instead of upgrading. Takes an effect only on DBServer +* `"manual"` - Waits for the manual upgrade. Requires replacement or the annotation on the member *** @@ -1327,6 +1340,18 @@ LabelsMode Define labels mode which should be use while overriding labels *** +### .spec.coordinators.manualUpgradeMode + +Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L224) + +UpgradeMode Defines the manually triggered upgrade mode for the Member + +Possible Values: +* `"inplace"` (default) - Inplace Upgrade procedure (with Upgrade initContainer) +* `"replace"` - Replaces server instead of upgrading. Takes an effect only on DBServer + +*** + ### .spec.coordinators.maxCount Type: `integer` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L50) @@ -1708,7 +1733,7 @@ Links: ### .spec.coordinators.restartPolicy -Type: `core.RestartPolicy` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L224) +Type: `core.RestartPolicy` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L231) RestartPolicy for all pods within the group. @@ -1949,13 +1974,14 @@ Links: ### .spec.coordinators.upgradeMode -Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L217) +Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L218) UpgradeMode Defines the upgrade mode for the Member Possible Values: * `"inplace"` (default) - Inplace Upgrade procedure (with Upgrade initContainer) * `"replace"` - Replaces server instead of upgrading. Takes an effect only on DBServer +* `"manual"` - Waits for the manual upgrade. Requires replacement or the annotation on the member *** @@ -2292,6 +2318,18 @@ LabelsMode Define labels mode which should be use while overriding labels *** +### .spec.dbservers.manualUpgradeMode + +Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L224) + +UpgradeMode Defines the manually triggered upgrade mode for the Member + +Possible Values: +* `"inplace"` (default) - Inplace Upgrade procedure (with Upgrade initContainer) +* `"replace"` - Replaces server instead of upgrading. Takes an effect only on DBServer + +*** + ### .spec.dbservers.maxCount Type: `integer` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L50) @@ -2673,7 +2711,7 @@ Links: ### .spec.dbservers.restartPolicy -Type: `core.RestartPolicy` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L224) +Type: `core.RestartPolicy` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L231) RestartPolicy for all pods within the group. @@ -2914,13 +2952,14 @@ Links: ### .spec.dbservers.upgradeMode -Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L217) +Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L218) UpgradeMode Defines the upgrade mode for the Member Possible Values: * `"inplace"` (default) - Inplace Upgrade procedure (with Upgrade initContainer) * `"replace"` - Replaces server instead of upgrading. Takes an effect only on DBServer +* `"manual"` - Waits for the manual upgrade. Requires replacement or the annotation on the member *** @@ -3478,6 +3517,18 @@ LabelsMode Define labels mode which should be use while overriding labels *** +### .spec.gateways.manualUpgradeMode + +Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L224) + +UpgradeMode Defines the manually triggered upgrade mode for the Member + +Possible Values: +* `"inplace"` (default) - Inplace Upgrade procedure (with Upgrade initContainer) +* `"replace"` - Replaces server instead of upgrading. Takes an effect only on DBServer + +*** + ### .spec.gateways.maxCount Type: `integer` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L50) @@ -3859,7 +3910,7 @@ Links: ### .spec.gateways.restartPolicy -Type: `core.RestartPolicy` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L224) +Type: `core.RestartPolicy` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L231) RestartPolicy for all pods within the group. @@ -4100,13 +4151,14 @@ Links: ### .spec.gateways.upgradeMode -Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L217) +Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L218) UpgradeMode Defines the upgrade mode for the Member Possible Values: * `"inplace"` (default) - Inplace Upgrade procedure (with Upgrade initContainer) * `"replace"` - Replaces server instead of upgrading. Takes an effect only on DBServer +* `"manual"` - Waits for the manual upgrade. Requires replacement or the annotation on the member *** @@ -5208,6 +5260,18 @@ LabelsMode Define labels mode which should be use while overriding labels *** +### .spec.single.manualUpgradeMode + +Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L224) + +UpgradeMode Defines the manually triggered upgrade mode for the Member + +Possible Values: +* `"inplace"` (default) - Inplace Upgrade procedure (with Upgrade initContainer) +* `"replace"` - Replaces server instead of upgrading. Takes an effect only on DBServer + +*** + ### .spec.single.maxCount Type: `integer` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L50) @@ -5589,7 +5653,7 @@ Links: ### .spec.single.restartPolicy -Type: `core.RestartPolicy` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L224) +Type: `core.RestartPolicy` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L231) RestartPolicy for all pods within the group. @@ -5830,13 +5894,14 @@ Links: ### .spec.single.upgradeMode -Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L217) +Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L218) UpgradeMode Defines the upgrade mode for the Member Possible Values: * `"inplace"` (default) - Inplace Upgrade procedure (with Upgrade initContainer) * `"replace"` - Replaces server instead of upgrading. Takes an effect only on DBServer +* `"manual"` - Waits for the manual upgrade. Requires replacement or the annotation on the member *** @@ -6387,6 +6452,18 @@ LabelsMode Define labels mode which should be use while overriding labels *** +### .spec.syncmasters.manualUpgradeMode + +Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L224) + +UpgradeMode Defines the manually triggered upgrade mode for the Member + +Possible Values: +* `"inplace"` (default) - Inplace Upgrade procedure (with Upgrade initContainer) +* `"replace"` - Replaces server instead of upgrading. Takes an effect only on DBServer + +*** + ### .spec.syncmasters.maxCount Type: `integer` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L50) @@ -6768,7 +6845,7 @@ Links: ### .spec.syncmasters.restartPolicy -Type: `core.RestartPolicy` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L224) +Type: `core.RestartPolicy` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L231) RestartPolicy for all pods within the group. @@ -7009,13 +7086,14 @@ Links: ### .spec.syncmasters.upgradeMode -Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L217) +Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L218) UpgradeMode Defines the upgrade mode for the Member Possible Values: * `"inplace"` (default) - Inplace Upgrade procedure (with Upgrade initContainer) * `"replace"` - Replaces server instead of upgrading. Takes an effect only on DBServer +* `"manual"` - Waits for the manual upgrade. Requires replacement or the annotation on the member *** @@ -7344,6 +7422,18 @@ LabelsMode Define labels mode which should be use while overriding labels *** +### .spec.syncworkers.manualUpgradeMode + +Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L224) + +UpgradeMode Defines the manually triggered upgrade mode for the Member + +Possible Values: +* `"inplace"` (default) - Inplace Upgrade procedure (with Upgrade initContainer) +* `"replace"` - Replaces server instead of upgrading. Takes an effect only on DBServer + +*** + ### .spec.syncworkers.maxCount Type: `integer` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L50) @@ -7725,7 +7815,7 @@ Links: ### .spec.syncworkers.restartPolicy -Type: `core.RestartPolicy` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L224) +Type: `core.RestartPolicy` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L231) RestartPolicy for all pods within the group. @@ -7966,13 +8056,14 @@ Links: ### .spec.syncworkers.upgradeMode -Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L217) +Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.49/pkg/apis/deployment/v1/server_group_spec.go#L218) UpgradeMode Defines the upgrade mode for the Member Possible Values: * `"inplace"` (default) - Inplace Upgrade procedure (with Upgrade initContainer) * `"replace"` - Replaces server instead of upgrading. Takes an effect only on DBServer +* `"manual"` - Waits for the manual upgrade. Requires replacement or the annotation on the member *** diff --git a/pkg/apis/deployment/annotations.go b/pkg/apis/deployment/annotations.go index a6316c754..68ca1eb7e 100644 --- a/pkg/apis/deployment/annotations.go +++ b/pkg/apis/deployment/annotations.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2016-2023 ArangoDB GmbH, Cologne, Germany +// Copyright 2016-2025 ArangoDB GmbH, Cologne, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,11 +21,12 @@ package deployment const ( - ArangoDeploymentAnnotationPrefix = "deployment.arangodb.com" - ArangoDeploymentPodMaintenanceAnnotation = ArangoDeploymentAnnotationPrefix + "/maintenance" - ArangoDeploymentPodChangeArchAnnotation = ArangoDeploymentAnnotationPrefix + "/arch" - ArangoDeploymentPodRotateAnnotation = ArangoDeploymentAnnotationPrefix + "/rotate" - ArangoDeploymentPodReplaceAnnotation = ArangoDeploymentAnnotationPrefix + "/replace" - ArangoDeploymentPodDeleteNow = ArangoDeploymentAnnotationPrefix + "/delete_now" - ArangoDeploymentPlanCleanAnnotation = "plan." + ArangoDeploymentAnnotationPrefix + "/clean" + ArangoDeploymentAnnotationPrefix = "deployment.arangodb.com" + ArangoDeploymentPodMaintenanceAnnotation = ArangoDeploymentAnnotationPrefix + "/maintenance" + ArangoDeploymentPodChangeArchAnnotation = ArangoDeploymentAnnotationPrefix + "/arch" + ArangoDeploymentPodRotateAnnotation = ArangoDeploymentAnnotationPrefix + "/rotate" + ArangoDeploymentPodReplaceAnnotation = ArangoDeploymentAnnotationPrefix + "/replace" + ArangoDeploymentPodAllowUpgradeAnnotation = "upgrade." + ArangoDeploymentAnnotationPrefix + "/allow" + ArangoDeploymentPodDeleteNow = ArangoDeploymentAnnotationPrefix + "/delete_now" + ArangoDeploymentPlanCleanAnnotation = "plan." + ArangoDeploymentAnnotationPrefix + "/clean" ) diff --git a/pkg/apis/deployment/v1/conditions.go b/pkg/apis/deployment/v1/conditions.go index 9e0cd5ae1..9f83bd997 100644 --- a/pkg/apis/deployment/v1/conditions.go +++ b/pkg/apis/deployment/v1/conditions.go @@ -53,6 +53,8 @@ const ( ConditionTypeTerminated ConditionType = "Terminated" // ConditionTypeAutoUpgrade indicates that the member has to be started with `--database.auto-upgrade` once. ConditionTypeAutoUpgrade ConditionType = "AutoUpgrade" + // ConditionTypeUpgradeAllowed indicates that the member upgrade is allowed in the manual procedure. + ConditionTypeUpgradeAllowed ConditionType = "UpgradeAllowed" // ConditionTypeCleanedOut indicates that the member (dbserver) has been cleaned out. // Always check in combination with ConditionTypeTerminated. diff --git a/pkg/apis/deployment/v1/server_group_spec.go b/pkg/apis/deployment/v1/server_group_spec.go index 4a0e1315f..e89da32ba 100644 --- a/pkg/apis/deployment/v1/server_group_spec.go +++ b/pkg/apis/deployment/v1/server_group_spec.go @@ -213,9 +213,16 @@ type ServerGroupSpec struct { // UpgradeMode Defines the upgrade mode for the Member // +doc/enum: inplace|Inplace Upgrade procedure (with Upgrade initContainer) // +doc/enum: replace|Replaces server instead of upgrading. Takes an effect only on DBServer + // +doc/enum: manual| Waits for the manual upgrade. Requires replacement or the annotation on the member // +doc/default: inplace UpgradeMode *ServerGroupUpgradeMode `json:"upgradeMode,omitempty"` + // UpgradeMode Defines the manually triggered upgrade mode for the Member + // +doc/enum: inplace|Inplace Upgrade procedure (with Upgrade initContainer) + // +doc/enum: replace|Replaces server instead of upgrading. Takes an effect only on DBServer + // +doc/default: inplace + ManualUpgradeMode *ServerGroupUpgradeMode `json:"manualUpgradeMode,omitempty"` + // RestartPolicy for all pods within the group. // +doc/type: core.RestartPolicy // +doc/enum: Always|Means that containers within the pod are always restarted. @@ -479,7 +486,9 @@ func (s *ServerGroupSpec) validate() error { shared.PrefixResourceError("volumes", s.Volumes.Validate()), shared.PrefixResourceError("volumeMounts", s.VolumeMounts.Validate()), shared.PrefixResourceError("initContainers", s.InitContainers.Validate()), - shared.PrefixResourceError("IndexMethod", s.IndexMethod.Validate()), + shared.PrefixResourceError("indexMethod", s.IndexMethod.Validate()), + shared.PrefixResourceError("upgradeMode", s.UpgradeMode.Validate()), + shared.PrefixResourceError("manualUpgradeMode", s.ManualUpgradeMode.Validate()), s.validateVolumes(), ) } diff --git a/pkg/apis/deployment/v1/server_group_spec_upgrade_mode.go b/pkg/apis/deployment/v1/server_group_spec_upgrade_mode.go index fbae43202..47aea1f61 100644 --- a/pkg/apis/deployment/v1/server_group_spec_upgrade_mode.go +++ b/pkg/apis/deployment/v1/server_group_spec_upgrade_mode.go @@ -32,13 +32,17 @@ const ( // ServerGroupUpgradeModeReplace Replaces server instead of upgrading. Takes an effect only on DBServer ServerGroupUpgradeModeReplace ServerGroupUpgradeMode = "replace" + // ServerGroupUpgradeModeManual Waits for the manual upgrade. Requires replacement or the annotation on the member. + // Requires annotation `upgrade.deployment.arangodb.com/allow` on a Pod + ServerGroupUpgradeModeManual ServerGroupUpgradeMode = "manual" + // DefaultServerGroupUpgradeMode defaults to ServerGroupUpgradeModeInplace DefaultServerGroupUpgradeMode = ServerGroupUpgradeModeInplace ) func (n *ServerGroupUpgradeMode) Validate() error { switch v := n.Get(); v { - case ServerGroupUpgradeModeInplace, ServerGroupUpgradeModeReplace: + case ServerGroupUpgradeModeInplace, ServerGroupUpgradeModeReplace, ServerGroupUpgradeModeManual: return nil default: return errors.WithStack(errors.Wrapf(ValidationError, "Unknown UpgradeMode %s", v.String())) @@ -46,8 +50,12 @@ func (n *ServerGroupUpgradeMode) Validate() error { } func (n *ServerGroupUpgradeMode) Get() ServerGroupUpgradeMode { + return n.Default(ServerGroupUpgradeModeInplace) +} + +func (n *ServerGroupUpgradeMode) Default(d ServerGroupUpgradeMode) ServerGroupUpgradeMode { if n == nil { - return DefaultServerGroupUpgradeMode + return d } return *n diff --git a/pkg/apis/deployment/v1/zz_generated.deepcopy.go b/pkg/apis/deployment/v1/zz_generated.deepcopy.go index eec0385dc..25dc588f3 100644 --- a/pkg/apis/deployment/v1/zz_generated.deepcopy.go +++ b/pkg/apis/deployment/v1/zz_generated.deepcopy.go @@ -2741,6 +2741,11 @@ func (in *ServerGroupSpec) DeepCopyInto(out *ServerGroupSpec) { *out = new(ServerGroupUpgradeMode) **out = **in } + if in.ManualUpgradeMode != nil { + in, out := &in.ManualUpgradeMode, &out.ManualUpgradeMode + *out = new(ServerGroupUpgradeMode) + **out = **in + } if in.RestartPolicy != nil { in, out := &in.RestartPolicy, &out.RestartPolicy *out = new(corev1.RestartPolicy) diff --git a/pkg/apis/deployment/v2alpha1/conditions.go b/pkg/apis/deployment/v2alpha1/conditions.go index 7f116d8b8..2343e97b0 100644 --- a/pkg/apis/deployment/v2alpha1/conditions.go +++ b/pkg/apis/deployment/v2alpha1/conditions.go @@ -53,6 +53,8 @@ const ( ConditionTypeTerminated ConditionType = "Terminated" // ConditionTypeAutoUpgrade indicates that the member has to be started with `--database.auto-upgrade` once. ConditionTypeAutoUpgrade ConditionType = "AutoUpgrade" + // ConditionTypeUpgradeAllowed indicates that the member upgrade is allowed in the manual procedure. + ConditionTypeUpgradeAllowed ConditionType = "UpgradeAllowed" // ConditionTypeCleanedOut indicates that the member (dbserver) has been cleaned out. // Always check in combination with ConditionTypeTerminated. diff --git a/pkg/apis/deployment/v2alpha1/server_group_spec.go b/pkg/apis/deployment/v2alpha1/server_group_spec.go index d5847652a..2a32e2f13 100644 --- a/pkg/apis/deployment/v2alpha1/server_group_spec.go +++ b/pkg/apis/deployment/v2alpha1/server_group_spec.go @@ -213,9 +213,16 @@ type ServerGroupSpec struct { // UpgradeMode Defines the upgrade mode for the Member // +doc/enum: inplace|Inplace Upgrade procedure (with Upgrade initContainer) // +doc/enum: replace|Replaces server instead of upgrading. Takes an effect only on DBServer + // +doc/enum: manual| Waits for the manual upgrade. Requires replacement or the annotation on the member // +doc/default: inplace UpgradeMode *ServerGroupUpgradeMode `json:"upgradeMode,omitempty"` + // UpgradeMode Defines the manually triggered upgrade mode for the Member + // +doc/enum: inplace|Inplace Upgrade procedure (with Upgrade initContainer) + // +doc/enum: replace|Replaces server instead of upgrading. Takes an effect only on DBServer + // +doc/default: inplace + ManualUpgradeMode *ServerGroupUpgradeMode `json:"manualUpgradeMode,omitempty"` + // RestartPolicy for all pods within the group. // +doc/type: core.RestartPolicy // +doc/enum: Always|Means that containers within the pod are always restarted. @@ -479,7 +486,9 @@ func (s *ServerGroupSpec) validate() error { shared.PrefixResourceError("volumes", s.Volumes.Validate()), shared.PrefixResourceError("volumeMounts", s.VolumeMounts.Validate()), shared.PrefixResourceError("initContainers", s.InitContainers.Validate()), - shared.PrefixResourceError("IndexMethod", s.IndexMethod.Validate()), + shared.PrefixResourceError("indexMethod", s.IndexMethod.Validate()), + shared.PrefixResourceError("upgradeMode", s.UpgradeMode.Validate()), + shared.PrefixResourceError("manualUpgradeMode", s.ManualUpgradeMode.Validate()), s.validateVolumes(), ) } diff --git a/pkg/apis/deployment/v2alpha1/server_group_spec_upgrade_mode.go b/pkg/apis/deployment/v2alpha1/server_group_spec_upgrade_mode.go index 58bb4f678..a9666f63a 100644 --- a/pkg/apis/deployment/v2alpha1/server_group_spec_upgrade_mode.go +++ b/pkg/apis/deployment/v2alpha1/server_group_spec_upgrade_mode.go @@ -32,13 +32,17 @@ const ( // ServerGroupUpgradeModeReplace Replaces server instead of upgrading. Takes an effect only on DBServer ServerGroupUpgradeModeReplace ServerGroupUpgradeMode = "replace" + // ServerGroupUpgradeModeManual Waits for the manual upgrade. Requires replacement or the annotation on the member. + // Requires annotation `upgrade.deployment.arangodb.com/allow` on a Pod + ServerGroupUpgradeModeManual ServerGroupUpgradeMode = "manual" + // DefaultServerGroupUpgradeMode defaults to ServerGroupUpgradeModeInplace DefaultServerGroupUpgradeMode = ServerGroupUpgradeModeInplace ) func (n *ServerGroupUpgradeMode) Validate() error { switch v := n.Get(); v { - case ServerGroupUpgradeModeInplace, ServerGroupUpgradeModeReplace: + case ServerGroupUpgradeModeInplace, ServerGroupUpgradeModeReplace, ServerGroupUpgradeModeManual: return nil default: return errors.WithStack(errors.Wrapf(ValidationError, "Unknown UpgradeMode %s", v.String())) @@ -46,8 +50,12 @@ func (n *ServerGroupUpgradeMode) Validate() error { } func (n *ServerGroupUpgradeMode) Get() ServerGroupUpgradeMode { + return n.Default(ServerGroupUpgradeModeInplace) +} + +func (n *ServerGroupUpgradeMode) Default(d ServerGroupUpgradeMode) ServerGroupUpgradeMode { if n == nil { - return DefaultServerGroupUpgradeMode + return d } return *n diff --git a/pkg/apis/deployment/v2alpha1/zz_generated.deepcopy.go b/pkg/apis/deployment/v2alpha1/zz_generated.deepcopy.go index c2ef4e715..8d19f2365 100644 --- a/pkg/apis/deployment/v2alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/deployment/v2alpha1/zz_generated.deepcopy.go @@ -2741,6 +2741,11 @@ func (in *ServerGroupSpec) DeepCopyInto(out *ServerGroupSpec) { *out = new(ServerGroupUpgradeMode) **out = **in } + if in.ManualUpgradeMode != nil { + in, out := &in.ManualUpgradeMode, &out.ManualUpgradeMode + *out = new(ServerGroupUpgradeMode) + **out = **in + } if in.RestartPolicy != nil { in, out := &in.RestartPolicy, &out.RestartPolicy *out = new(v1.RestartPolicy) diff --git a/pkg/crd/crds/database-deployment.schema.generated.yaml b/pkg/crd/crds/database-deployment.schema.generated.yaml index 853f3e8d1..9197a4289 100644 --- a/pkg/crd/crds/database-deployment.schema.generated.yaml +++ b/pkg/crd/crds/database-deployment.schema.generated.yaml @@ -915,6 +915,12 @@ v1: labelsMode: description: LabelsMode Define labels mode which should be use while overriding labels type: string + manualUpgradeMode: + description: UpgradeMode Defines the manually triggered upgrade mode for the Member + enum: + - inplace + - replace + type: string maxCount: description: MaxCount specifies a maximum for the count of servers. If set, a specification is invalid if `count > maxCount`. format: int32 @@ -1880,6 +1886,7 @@ v1: enum: - inplace - replace + - manual type: string volumeAllowShrink: description: VolumeAllowShrink allows shrinking of the volume @@ -3210,6 +3217,12 @@ v1: labelsMode: description: LabelsMode Define labels mode which should be use while overriding labels type: string + manualUpgradeMode: + description: UpgradeMode Defines the manually triggered upgrade mode for the Member + enum: + - inplace + - replace + type: string maxCount: description: MaxCount specifies a maximum for the count of servers. If set, a specification is invalid if `count > maxCount`. format: int32 @@ -4175,6 +4188,7 @@ v1: enum: - inplace - replace + - manual type: string volumeAllowShrink: description: VolumeAllowShrink allows shrinking of the volume @@ -5423,6 +5437,12 @@ v1: labelsMode: description: LabelsMode Define labels mode which should be use while overriding labels type: string + manualUpgradeMode: + description: UpgradeMode Defines the manually triggered upgrade mode for the Member + enum: + - inplace + - replace + type: string maxCount: description: MaxCount specifies a maximum for the count of servers. If set, a specification is invalid if `count > maxCount`. format: int32 @@ -6388,6 +6408,7 @@ v1: enum: - inplace - replace + - manual type: string volumeAllowShrink: description: VolumeAllowShrink allows shrinking of the volume @@ -7756,6 +7777,12 @@ v1: labelsMode: description: LabelsMode Define labels mode which should be use while overriding labels type: string + manualUpgradeMode: + description: UpgradeMode Defines the manually triggered upgrade mode for the Member + enum: + - inplace + - replace + type: string maxCount: description: MaxCount specifies a maximum for the count of servers. If set, a specification is invalid if `count > maxCount`. format: int32 @@ -8721,6 +8748,7 @@ v1: enum: - inplace - replace + - manual type: string volumeAllowShrink: description: VolumeAllowShrink allows shrinking of the volume @@ -11184,6 +11212,12 @@ v1: labelsMode: description: LabelsMode Define labels mode which should be use while overriding labels type: string + manualUpgradeMode: + description: UpgradeMode Defines the manually triggered upgrade mode for the Member + enum: + - inplace + - replace + type: string maxCount: description: MaxCount specifies a maximum for the count of servers. If set, a specification is invalid if `count > maxCount`. format: int32 @@ -12149,6 +12183,7 @@ v1: enum: - inplace - replace + - manual type: string volumeAllowShrink: description: VolumeAllowShrink allows shrinking of the volume @@ -13542,6 +13577,12 @@ v1: labelsMode: description: LabelsMode Define labels mode which should be use while overriding labels type: string + manualUpgradeMode: + description: UpgradeMode Defines the manually triggered upgrade mode for the Member + enum: + - inplace + - replace + type: string maxCount: description: MaxCount specifies a maximum for the count of servers. If set, a specification is invalid if `count > maxCount`. format: int32 @@ -14507,6 +14548,7 @@ v1: enum: - inplace - replace + - manual type: string volumeAllowShrink: description: VolumeAllowShrink allows shrinking of the volume @@ -15748,6 +15790,12 @@ v1: labelsMode: description: LabelsMode Define labels mode which should be use while overriding labels type: string + manualUpgradeMode: + description: UpgradeMode Defines the manually triggered upgrade mode for the Member + enum: + - inplace + - replace + type: string maxCount: description: MaxCount specifies a maximum for the count of servers. If set, a specification is invalid if `count > maxCount`. format: int32 @@ -16713,6 +16761,7 @@ v1: enum: - inplace - replace + - manual type: string volumeAllowShrink: description: VolumeAllowShrink allows shrinking of the volume @@ -18061,6 +18110,12 @@ v2alpha1: labelsMode: description: LabelsMode Define labels mode which should be use while overriding labels type: string + manualUpgradeMode: + description: UpgradeMode Defines the manually triggered upgrade mode for the Member + enum: + - inplace + - replace + type: string maxCount: description: MaxCount specifies a maximum for the count of servers. If set, a specification is invalid if `count > maxCount`. format: int32 @@ -19026,6 +19081,7 @@ v2alpha1: enum: - inplace - replace + - manual type: string volumeAllowShrink: description: VolumeAllowShrink allows shrinking of the volume @@ -20356,6 +20412,12 @@ v2alpha1: labelsMode: description: LabelsMode Define labels mode which should be use while overriding labels type: string + manualUpgradeMode: + description: UpgradeMode Defines the manually triggered upgrade mode for the Member + enum: + - inplace + - replace + type: string maxCount: description: MaxCount specifies a maximum for the count of servers. If set, a specification is invalid if `count > maxCount`. format: int32 @@ -21321,6 +21383,7 @@ v2alpha1: enum: - inplace - replace + - manual type: string volumeAllowShrink: description: VolumeAllowShrink allows shrinking of the volume @@ -22569,6 +22632,12 @@ v2alpha1: labelsMode: description: LabelsMode Define labels mode which should be use while overriding labels type: string + manualUpgradeMode: + description: UpgradeMode Defines the manually triggered upgrade mode for the Member + enum: + - inplace + - replace + type: string maxCount: description: MaxCount specifies a maximum for the count of servers. If set, a specification is invalid if `count > maxCount`. format: int32 @@ -23534,6 +23603,7 @@ v2alpha1: enum: - inplace - replace + - manual type: string volumeAllowShrink: description: VolumeAllowShrink allows shrinking of the volume @@ -24902,6 +24972,12 @@ v2alpha1: labelsMode: description: LabelsMode Define labels mode which should be use while overriding labels type: string + manualUpgradeMode: + description: UpgradeMode Defines the manually triggered upgrade mode for the Member + enum: + - inplace + - replace + type: string maxCount: description: MaxCount specifies a maximum for the count of servers. If set, a specification is invalid if `count > maxCount`. format: int32 @@ -25867,6 +25943,7 @@ v2alpha1: enum: - inplace - replace + - manual type: string volumeAllowShrink: description: VolumeAllowShrink allows shrinking of the volume @@ -28330,6 +28407,12 @@ v2alpha1: labelsMode: description: LabelsMode Define labels mode which should be use while overriding labels type: string + manualUpgradeMode: + description: UpgradeMode Defines the manually triggered upgrade mode for the Member + enum: + - inplace + - replace + type: string maxCount: description: MaxCount specifies a maximum for the count of servers. If set, a specification is invalid if `count > maxCount`. format: int32 @@ -29295,6 +29378,7 @@ v2alpha1: enum: - inplace - replace + - manual type: string volumeAllowShrink: description: VolumeAllowShrink allows shrinking of the volume @@ -30688,6 +30772,12 @@ v2alpha1: labelsMode: description: LabelsMode Define labels mode which should be use while overriding labels type: string + manualUpgradeMode: + description: UpgradeMode Defines the manually triggered upgrade mode for the Member + enum: + - inplace + - replace + type: string maxCount: description: MaxCount specifies a maximum for the count of servers. If set, a specification is invalid if `count > maxCount`. format: int32 @@ -31653,6 +31743,7 @@ v2alpha1: enum: - inplace - replace + - manual type: string volumeAllowShrink: description: VolumeAllowShrink allows shrinking of the volume @@ -32894,6 +32985,12 @@ v2alpha1: labelsMode: description: LabelsMode Define labels mode which should be use while overriding labels type: string + manualUpgradeMode: + description: UpgradeMode Defines the manually triggered upgrade mode for the Member + enum: + - inplace + - replace + type: string maxCount: description: MaxCount specifies a maximum for the count of servers. If set, a specification is invalid if `count > maxCount`. format: int32 @@ -33859,6 +33956,7 @@ v2alpha1: enum: - inplace - replace + - manual type: string volumeAllowShrink: description: VolumeAllowShrink allows shrinking of the volume diff --git a/pkg/deployment/reconcile/plan_builder_high.go b/pkg/deployment/reconcile/plan_builder_high.go index 478001e9c..1341ee775 100644 --- a/pkg/deployment/reconcile/plan_builder_high.go +++ b/pkg/deployment/reconcile/plan_builder_high.go @@ -54,6 +54,7 @@ func (r *Reconciler) createHighPlan(ctx context.Context, apiObject k8sutil.APIOb ApplyIfEmpty(r.createSyncPlan). ApplyIfEmpty(r.updateMemberUpdateConditionsPlan). ApplyIfEmpty(r.updateMemberRotationConditionsPlan). + ApplyIfEmpty(r.createMemberAllowUpgradeConditionPlan). ApplyIfEmpty(r.createMemberRecreationConditionsPlan). ApplyIfEmpty(r.createMemberPodSchedulingFailurePlan). ApplyIfEmpty(r.createRotateServerStoragePVCPendingResizeConditionPlan). diff --git a/pkg/deployment/reconcile/plan_builder_rotate_upgrade.go b/pkg/deployment/reconcile/plan_builder_rotate_upgrade.go index 4177379c8..8b77ebfca 100644 --- a/pkg/deployment/reconcile/plan_builder_rotate_upgrade.go +++ b/pkg/deployment/reconcile/plan_builder_rotate_upgrade.go @@ -292,16 +292,27 @@ func (r *Reconciler) createUpgradePlanInternal(apiObject k8sutil.APIObject, spec return nil, false } - um := spec.GetServerGroupSpec(group).UpgradeMode + dum := util.BoolSwitch(features.IsUpgradeIndexOrderIssueEnabled(group, d.upgradeDecision.FromVersion, d.upgradeDecision.ToVersion), api.ServerGroupUpgradeModeReplace, api.ServerGroupUpgradeModeInplace) - if features.IsUpgradeIndexOrderIssueEnabled(group, d.upgradeDecision.FromVersion, d.upgradeDecision.ToVersion) && um == nil { - um = util.NewType(api.ServerGroupUpgradeModeReplace) + um := spec.GetServerGroupSpec(group).UpgradeMode.Default(dum) + + mum := spec.GetServerGroupSpec(group).ManualUpgradeMode.Default(dum) + + switch um.Get() { + case api.ServerGroupUpgradeModeManual: + if !m.Member.Conditions.IsTrue(api.ConditionTypeUpgradeAllowed) { + continue + } + + // Once we pick manual mode, ensure that we still follow planned scenario + um = mum } - switch group { - case api.ServerGroupDBServers: - if um.Get() == api.ServerGroupUpgradeModeReplace { - // Members are suppose to be replaced + switch um.Get() { + case api.ServerGroupUpgradeModeReplace: + switch group { + case api.ServerGroupDBServers: + // Members are supposed to be replaced if !m.Member.Conditions.IsTrue(api.ConditionTypeMarkedToRemove) { return api.Plan{actions.NewAction(api.ActionTypeMarkToRemoveMember, m.Group, m.Member, "Replace by Upgrade")}, false } @@ -549,6 +560,39 @@ func groupReadyForRestart(context PlanBuilderContext, status api.DeploymentStatu return true, "Restart allowed" } +func (r *Reconciler) createMemberAllowUpgradeConditionPlan(ctx context.Context, + apiObject k8sutil.APIObject, + spec api.DeploymentSpec, status api.DeploymentStatus, + context PlanBuilderContext) api.Plan { + var p api.Plan + + for _, m := range status.Members.AsList() { + if m.Member.Conditions.IsTrue(api.ConditionTypeUpgradeAllowed) { + continue + } + + cache, ok := context.ACS().ClusterCache(m.Member.ClusterID) + if !ok { + continue + } + + if pod, ok := cache.Pod().V1().GetSimple(m.Member.Pod.GetName()); ok { + if _, ok := pod.GetAnnotations()[deployment.ArangoDeploymentPodAllowUpgradeAnnotation]; ok { + r.log. + Str("pod-name", m.Member.Pod.GetName()). + Str("server-group", m.Group.AsRole()). + Info("Upgrade Allowed by annotation") + + return api.Plan{ + sharedReconcile.UpdateMemberConditionActionV2("Upgrade allowed by Annotation", api.ConditionTypeUpgradeAllowed, m.Group, m.Member.ID, true, "Upgrade allowed by Annotation", "", ""), + } + } + } + } + + return p +} + // createUpgradeMemberPlan creates a plan to upgrade (stop-recreateWithAutoUpgrade-stop-start) an existing // member. func (r *Reconciler) createUpgradeMemberPlan(member api.MemberStatus,