Skip to content

Commit 5a15002

Browse files
authored
[Feature] Maintenance mode improvements (#757)
1 parent 78b989c commit 5a15002

28 files changed

+464
-117
lines changed

go.mod

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/arangodb/kube-arangodb
33
go 1.16
44

55
replace (
6-
github.com/arangodb/go-driver => github.com/arangodb/go-driver v0.0.0-20210518064911-4985e8be3d90
6+
github.com/arangodb/go-driver => github.com/arangodb/go-driver v0.0.0-20210621075908-e7a6fa0cbd18
77
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring => github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.46.0
88
github.com/prometheus-operator/prometheus-operator/pkg/client => github.com/prometheus-operator/prometheus-operator/pkg/client v0.46.0
99
github.com/stretchr/testify => github.com/stretchr/testify v1.5.1
@@ -26,7 +26,7 @@ require (
2626
github.com/aktau/github-release v0.10.0 // indirect
2727
github.com/arangodb-helper/go-certificates v0.0.0-20180821055445-9fca24fc2680
2828
github.com/arangodb/arangosync-client v0.6.3
29-
github.com/arangodb/go-driver v0.0.0-20191002124627-11b6bfc64f67
29+
github.com/arangodb/go-driver v0.0.0-20210621075908-e7a6fa0cbd18
3030
github.com/arangodb/go-upgrade-rules v0.0.0-20180809110947-031b4774ff21
3131
github.com/cenkalti/backoff v2.1.1+incompatible
3232
github.com/coreos/go-semver v0.3.0

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ github.com/arangodb/go-driver v0.0.0-20210517114204-8cc084268066 h1:NneOFWxfa7rh
5656
github.com/arangodb/go-driver v0.0.0-20210517114204-8cc084268066/go.mod h1:3NUekcRLpgheFIGEwcOvxilEW73MV1queNKW58k7sdc=
5757
github.com/arangodb/go-driver v0.0.0-20210518064911-4985e8be3d90 h1:NMnMsS32jOF+e0v+MLXlgRJM7ejSAXxHg1UDv1q417I=
5858
github.com/arangodb/go-driver v0.0.0-20210518064911-4985e8be3d90/go.mod h1:3NUekcRLpgheFIGEwcOvxilEW73MV1queNKW58k7sdc=
59+
github.com/arangodb/go-driver v0.0.0-20210621075908-e7a6fa0cbd18 h1:3J0tqp5eQ8ptGOeeu7vo92RKf24bOA7MFy0z3uPiTWg=
60+
github.com/arangodb/go-driver v0.0.0-20210621075908-e7a6fa0cbd18/go.mod h1:3NUekcRLpgheFIGEwcOvxilEW73MV1queNKW58k7sdc=
5961
github.com/arangodb/go-upgrade-rules v0.0.0-20180809110947-031b4774ff21 h1:+W7D5ttxi/Ygh/39vialtypE23p9KI7P0J2qtoqUV4w=
6062
github.com/arangodb/go-upgrade-rules v0.0.0-20180809110947-031b4774ff21/go.mod h1:RkPIG6JJ2pcJUoymc18NxAJGraZd+iAEVnOTDjZey/w=
6163
github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e h1:Xg+hGrY2LcQBbxd0ZFdbGSyRKTYMZCfBbw/pMJFOk1g=

pkg/apis/deployment/v1/conditions.go

+16-1
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,10 @@ const (
6363
ConditionTypeUpToDate ConditionType = "UpToDate"
6464
// ConditionTypeMarkedToRemove indicates that the member is marked to be removed.
6565
ConditionTypeMarkedToRemove ConditionType = "MarkedToRemove"
66-
// ConditionTypeUpgradeFailed indicates that mem
66+
// ConditionTypeUpgradeFailed indicates that upgrade failed
6767
ConditionTypeUpgradeFailed ConditionType = "UpgradeFailed"
68+
// ConditionTypeMaintenanceMode indicates that Maintenance is enabled
69+
ConditionTypeMaintenanceMode ConditionType = "MaintenanceMode"
6870
)
6971

7072
// Condition represents one current condition of a deployment or deployment member.
@@ -146,6 +148,19 @@ func (list ConditionList) Get(conditionType ConditionType) (Condition, bool) {
146148
return Condition{}, false
147149
}
148150

151+
// Touch update condition LastUpdateTime if condition exists
152+
func (list *ConditionList) Touch(conditionType ConditionType) bool {
153+
src := *list
154+
for i, x := range src {
155+
if x.Type == conditionType {
156+
src[i].LastUpdateTime = metav1.Now()
157+
return true
158+
}
159+
}
160+
161+
return false
162+
}
163+
149164
// Update the condition, replacing an old condition with same type (if any)
150165
// Returns true when changes were made, false otherwise.
151166
func (list *ConditionList) Update(conditionType ConditionType, status bool, reason, message string) bool {

pkg/apis/deployment/v1/plan.go

+42
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ const (
129129
ActionTypeEnableMaintenance ActionType = "EnableMaintenance"
130130
// ActionTypeEnableMaintenance disables maintenance on cluster.
131131
ActionTypeDisableMaintenance ActionType = "DisableMaintenance"
132+
// ActionTypeSetMaintenanceCondition sets maintenance condition.
133+
ActionTypeSetMaintenanceCondition ActionType = "SetMaintenanceCondition"
132134
// ActionTypeBootstrapUpdate update bootstrap status to true
133135
ActionTypeBootstrapUpdate ActionType = "BootstrapUpdate"
134136
// ActionTypeBootstrapSetPassword set password to the bootstrapped user
@@ -220,6 +222,11 @@ func (a Action) SetImage(image string) Action {
220222
return a
221223
}
222224

225+
// AsPlan parse action list into plan
226+
func AsPlan(a []Action) Plan {
227+
return a
228+
}
229+
223230
// Plan is a list of actions that will be taken to update a deployment.
224231
// Only 1 action is in progress at a time. The operator will wait for that
225232
// action to be completely and then remove the action.
@@ -245,3 +252,38 @@ func (p Plan) Equal(other Plan) bool {
245252
func (p Plan) IsEmpty() bool {
246253
return len(p) == 0
247254
}
255+
256+
// Add add action at the end of plan
257+
func (p Plan) After(action ...Action) Plan {
258+
n := Plan{}
259+
260+
n = append(n, p...)
261+
262+
n = append(n, action...)
263+
264+
return n
265+
}
266+
267+
// Prefix add action at the beginning of plan
268+
func (p Plan) Before(action ...Action) Plan {
269+
n := Plan{}
270+
271+
n = append(n, action...)
272+
273+
n = append(n, p...)
274+
275+
return n
276+
}
277+
278+
// Prefix add action at the beginning of plan
279+
func (p Plan) Wrap(before, after Action) Plan {
280+
n := Plan{}
281+
282+
n = append(n, before)
283+
284+
n = append(n, p...)
285+
286+
n = append(n, after)
287+
288+
return n
289+
}

pkg/apis/deployment/v1/timeouts.go

+14
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,22 @@ import (
2828
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
2929
)
3030

31+
const (
32+
DefaultMaintenanceGracePeriod = 30 * time.Minute
33+
)
34+
3135
type Timeouts struct {
3236
AddMember *Timeout `json:"addMember,omitempty"`
37+
38+
MaintenanceGracePeriod *Timeout `json:"maintenanceGracePeriod,omitempty"`
39+
}
40+
41+
func (t *Timeouts) GetMaintenanceGracePeriod() time.Duration {
42+
if t == nil {
43+
return DefaultMaintenanceGracePeriod
44+
}
45+
46+
return t.MaintenanceGracePeriod.Get(DefaultMaintenanceGracePeriod)
3347
}
3448

3549
func (t *Timeouts) Get() Timeouts {

pkg/apis/deployment/v1/zz_generated.deepcopy.go

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/apis/deployment/v2alpha1/conditions.go

+16-1
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,10 @@ const (
6363
ConditionTypeUpToDate ConditionType = "UpToDate"
6464
// ConditionTypeMarkedToRemove indicates that the member is marked to be removed.
6565
ConditionTypeMarkedToRemove ConditionType = "MarkedToRemove"
66-
// ConditionTypeUpgradeFailed indicates that mem
66+
// ConditionTypeUpgradeFailed indicates that upgrade failed
6767
ConditionTypeUpgradeFailed ConditionType = "UpgradeFailed"
68+
// ConditionTypeMaintenanceMode indicates that Maintenance is enabled
69+
ConditionTypeMaintenanceMode ConditionType = "MaintenanceMode"
6870
)
6971

7072
// Condition represents one current condition of a deployment or deployment member.
@@ -146,6 +148,19 @@ func (list ConditionList) Get(conditionType ConditionType) (Condition, bool) {
146148
return Condition{}, false
147149
}
148150

151+
// Touch update condition LastUpdateTime if condition exists
152+
func (list *ConditionList) Touch(conditionType ConditionType) bool {
153+
src := *list
154+
for i, x := range src {
155+
if x.Type == conditionType {
156+
src[i].LastUpdateTime = metav1.Now()
157+
return true
158+
}
159+
}
160+
161+
return false
162+
}
163+
149164
// Update the condition, replacing an old condition with same type (if any)
150165
// Returns true when changes were made, false otherwise.
151166
func (list *ConditionList) Update(conditionType ConditionType, status bool, reason, message string) bool {

pkg/apis/deployment/v2alpha1/plan.go

+42
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ const (
129129
ActionTypeEnableMaintenance ActionType = "EnableMaintenance"
130130
// ActionTypeEnableMaintenance disables maintenance on cluster.
131131
ActionTypeDisableMaintenance ActionType = "DisableMaintenance"
132+
// ActionTypeSetMaintenanceCondition sets maintenance condition.
133+
ActionTypeSetMaintenanceCondition ActionType = "SetMaintenanceCondition"
132134
// ActionTypeBootstrapUpdate update bootstrap status to true
133135
ActionTypeBootstrapUpdate ActionType = "BootstrapUpdate"
134136
// ActionTypeBootstrapSetPassword set password to the bootstrapped user
@@ -220,6 +222,11 @@ func (a Action) SetImage(image string) Action {
220222
return a
221223
}
222224

225+
// AsPlan parse action list into plan
226+
func AsPlan(a []Action) Plan {
227+
return a
228+
}
229+
223230
// Plan is a list of actions that will be taken to update a deployment.
224231
// Only 1 action is in progress at a time. The operator will wait for that
225232
// action to be completely and then remove the action.
@@ -245,3 +252,38 @@ func (p Plan) Equal(other Plan) bool {
245252
func (p Plan) IsEmpty() bool {
246253
return len(p) == 0
247254
}
255+
256+
// Add add action at the end of plan
257+
func (p Plan) After(action ...Action) Plan {
258+
n := Plan{}
259+
260+
n = append(n, p...)
261+
262+
n = append(n, action...)
263+
264+
return n
265+
}
266+
267+
// Prefix add action at the beginning of plan
268+
func (p Plan) Before(action ...Action) Plan {
269+
n := Plan{}
270+
271+
n = append(n, action...)
272+
273+
n = append(n, p...)
274+
275+
return n
276+
}
277+
278+
// Prefix add action at the beginning of plan
279+
func (p Plan) Wrap(before, after Action) Plan {
280+
n := Plan{}
281+
282+
n = append(n, before)
283+
284+
n = append(n, p...)
285+
286+
n = append(n, after)
287+
288+
return n
289+
}

pkg/apis/deployment/v2alpha1/timeouts.go

+14
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,22 @@ import (
2828
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
2929
)
3030

31+
const (
32+
DefaultMaintenanceGracePeriod = 30 * time.Minute
33+
)
34+
3135
type Timeouts struct {
3236
AddMember *Timeout `json:"addMember,omitempty"`
37+
38+
MaintenanceGracePeriod *Timeout `json:"maintenanceGracePeriod,omitempty"`
39+
}
40+
41+
func (t *Timeouts) GetMaintenanceGracePeriod() time.Duration {
42+
if t == nil {
43+
return DefaultMaintenanceGracePeriod
44+
}
45+
46+
return t.MaintenanceGracePeriod.Get(DefaultMaintenanceGracePeriod)
3347
}
3448

3549
func (t *Timeouts) Get() Timeouts {

pkg/apis/deployment/v2alpha1/zz_generated.deepcopy.go

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/deployment/agency/maintenance.go

+11-26
Original file line numberDiff line numberDiff line change
@@ -26,40 +26,25 @@ import (
2626
"context"
2727
"net/http"
2828

29+
"github.com/arangodb/go-driver/agency"
30+
2931
"github.com/arangodb/go-driver"
3032
)
3133

32-
type Maintenance struct {
33-
Result string `json:"result"`
34-
}
35-
36-
func (m Maintenance) Enabled() bool {
37-
return m.Result == "Maintenance"
38-
}
39-
40-
func GetMaintenanceMode(ctx context.Context, client driver.Client) (Maintenance, error) {
41-
conn := client.Connection()
42-
r, err := conn.NewRequest(http.MethodGet, "/_admin/cluster/maintenance")
43-
if err != nil {
44-
return Maintenance{}, err
45-
}
46-
47-
resp, err := conn.Do(ctx, r)
48-
if err != nil {
49-
return Maintenance{}, err
50-
}
34+
func GetMaintenanceMode(ctx context.Context, client agency.Agency) (bool, error) {
35+
var data interface{}
36+
err := client.ReadKey(ctx, []string{"arango", "Supervision", "Maintenance"}, &data)
5137

52-
if err := resp.CheckStatus(http.StatusOK); err != nil {
53-
return Maintenance{}, err
38+
if err == nil {
39+
// We got 200
40+
return true, nil
5441
}
5542

56-
var m Maintenance
57-
58-
if err := resp.ParseBody("", &m); err != nil {
59-
return Maintenance{}, err
43+
if agency.IsKeyNotFound(err) {
44+
return false, nil
6045
}
6146

62-
return m, nil
47+
return false, err
6348
}
6449

6550
func SetMaintenanceMode(ctx context.Context, client driver.Client, enabled bool) error {

pkg/deployment/context_impl.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ func (d *Deployment) GetArangoImage() string {
593593
return d.config.ArangoImage
594594
}
595595

596-
func (d *Deployment) WithStatusUpdate(ctx context.Context, action func(s *api.DeploymentStatus) bool, force ...bool) error {
596+
func (d *Deployment) WithStatusUpdate(ctx context.Context, action resources.DeploymentStatusUpdateFunc, force ...bool) error {
597597
d.status.mutex.Lock()
598598
defer d.status.mutex.Unlock()
599599

pkg/deployment/deployment.go

+37
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import (
2929
"sync/atomic"
3030
"time"
3131

32+
"github.com/arangodb/kube-arangodb/pkg/deployment/agency"
33+
3234
inspectorInterface "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector"
3335

3436
deploymentClient "github.com/arangodb/kube-arangodb/pkg/deployment/client"
@@ -138,6 +140,41 @@ type Deployment struct {
138140
haveServiceMonitorCRD bool
139141
}
140142

143+
func (d *Deployment) GetAgencyMaintenanceMode(ctx context.Context) (bool, error) {
144+
if !d.Mode().HasAgents() {
145+
return false, nil
146+
}
147+
148+
ctxChild, cancel := context.WithTimeout(ctx, arangod.GetRequestTimeout())
149+
defer cancel()
150+
151+
client, err := d.GetAgency(ctxChild)
152+
if err != nil {
153+
return false, err
154+
}
155+
156+
if enabled, err := agency.GetMaintenanceMode(ctxChild, client); err != nil {
157+
return false, err
158+
} else {
159+
return enabled, nil
160+
}
161+
}
162+
163+
func (d *Deployment) SetAgencyMaintenanceMode(ctx context.Context, enabled bool) error {
164+
if !d.Mode().HasAgents() {
165+
return nil
166+
}
167+
168+
ctxChild, cancel := context.WithTimeout(ctx, arangod.GetRequestTimeout())
169+
defer cancel()
170+
client, err := d.GetDatabaseClient(ctxChild)
171+
if err != nil {
172+
return err
173+
}
174+
175+
return agency.SetMaintenanceMode(ctxChild, client, enabled)
176+
}
177+
141178
// New creates a new Deployment from the given API object.
142179
func New(config Config, deps Dependencies, apiObject *api.ArangoDeployment) (*Deployment, error) {
143180
if err := apiObject.Spec.Validate(); err != nil {

0 commit comments

Comments
 (0)