Skip to content

Commit c8a5d79

Browse files
authored
Feature: cluster upgrade for 3.6 (#518)
1 parent ac329f5 commit c8a5d79

File tree

8 files changed

+293
-114
lines changed

8 files changed

+293
-114
lines changed

go.mod

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ require (
6767
github.com/mattn/go-isatty v0.0.7 // indirect
6868
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
6969
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 // indirect
70-
github.com/pborman/uuid v1.2.0 // indirect
7170
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
7271
github.com/pkg/errors v0.8.1
7372
github.com/prometheus/client_golang v1.0.0

pkg/deployment/pod/args.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2020 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
// Author Adam Janikowski
21+
//
22+
23+
package pod
24+
25+
import (
26+
"github.com/arangodb/go-driver"
27+
deploymentApi "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
28+
)
29+
30+
type Input struct {
31+
Deployment deploymentApi.DeploymentSpec
32+
GroupSpec deploymentApi.ServerGroupSpec
33+
Group deploymentApi.ServerGroup
34+
Version driver.Version
35+
AutoUpgrade bool
36+
}
37+
38+
type ArgumentsBuilder interface {
39+
Create(i Input) []OptionPair
40+
}

pkg/deployment/pod/pair.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2020 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
// Author Adam Janikowski
21+
//
22+
23+
package pod
24+
25+
import "strings"
26+
27+
// OptionPair key value pair builder
28+
type OptionPair struct {
29+
Key string
30+
Value string
31+
}
32+
33+
// CompareTo returns -1 if o < other, 0 if o == other, 1 otherwise
34+
func (o OptionPair) CompareTo(other OptionPair) int {
35+
rc := strings.Compare(o.Key, other.Key)
36+
if rc < 0 {
37+
return -1
38+
} else if rc > 0 {
39+
return 1
40+
}
41+
return strings.Compare(o.Value, other.Value)
42+
}
43+
44+
func NewOptionPair(pairs ...OptionPair) []OptionPair {
45+
return pairs
46+
}

pkg/deployment/pod/upgrade.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2020 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
// Author Adam Janikowski
21+
//
22+
23+
package pod
24+
25+
import deploymentApi "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
26+
27+
func AutoUpgrade() ArgumentsBuilder {
28+
return autoUpgradeArgs{}
29+
}
30+
31+
type autoUpgradeArgs struct{}
32+
33+
func (u autoUpgradeArgs) Create(i Input) []OptionPair {
34+
if !i.AutoUpgrade {
35+
return NewOptionPair()
36+
}
37+
38+
if i.Version.CompareTo("3.6.0") >= 0 {
39+
switch i.Group {
40+
case deploymentApi.ServerGroupCoordinators:
41+
return NewOptionPair(OptionPair{"--cluster.upgrade", "online"})
42+
}
43+
}
44+
45+
return NewOptionPair(OptionPair{"--database.auto-upgrade", "true"})
46+
}

pkg/deployment/reconcile/plan_builder_test.go

Lines changed: 53 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,24 @@ import (
4040
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
4141
"github.com/arangodb/kube-arangodb/pkg/util"
4242
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
43-
v1 "k8s.io/api/core/v1"
43+
core "k8s.io/api/core/v1"
4444
)
4545

46+
var _ PlanBuilderContext = &testContext{}
47+
4648
type testContext struct {
47-
Pods []v1.Pod
49+
Pods []core.Pod
4850
ErrPods error
4951
ArangoDeployment *api.ArangoDeployment
50-
PVC *v1.PersistentVolumeClaim
52+
PVC *core.PersistentVolumeClaim
5153
PVCErr error
5254
RecordedEvent *k8sutil.Event
5355
}
5456

57+
func (c *testContext) GetAgencyData(ctx context.Context, i interface{}, keyParts ...string) error {
58+
return nil
59+
}
60+
5561
func (c *testContext) GetAPIObject() k8sutil.APIObject {
5662
if c.ArangoDeployment == nil {
5763
return &api.ArangoDeployment{}
@@ -108,13 +114,13 @@ func (c *testContext) RemovePodFinalizers(podName string) error {
108114
panic("implement me")
109115
}
110116

111-
func (c *testContext) GetOwnedPods() ([]v1.Pod, error) {
117+
func (c *testContext) GetOwnedPods() ([]core.Pod, error) {
112118
if c.ErrPods != nil {
113119
return nil, c.ErrPods
114120
}
115121

116122
if c.Pods == nil {
117-
return make([]v1.Pod, 0), c.ErrPods
123+
return make([]core.Pod, 0), c.ErrPods
118124
}
119125
return c.Pods, c.ErrPods
120126
}
@@ -158,7 +164,7 @@ func (c *testContext) CreateEvent(evt *k8sutil.Event) {
158164
}
159165

160166
// GetPvc gets a PVC by the given name, in the samespace of the deployment.
161-
func (c *testContext) GetPvc(pvcName string) (*v1.PersistentVolumeClaim, error) {
167+
func (c *testContext) GetPvc(pvcName string) (*core.PersistentVolumeClaim, error) {
162168
return c.PVC, c.PVCErr
163169
}
164170

@@ -181,6 +187,22 @@ func (c *testContext) GetStatus() (api.DeploymentStatus, int32) {
181187
return c.ArangoDeployment.Status, 0
182188
}
183189

190+
func addAgentsToStatus(t *testing.T, status *api.DeploymentStatus, count int) {
191+
for i := 0; i < count; i++ {
192+
require.NoError(t, status.Members.Add(api.MemberStatus{
193+
ID: fmt.Sprintf("AGNT-%d", i),
194+
PodName: fmt.Sprintf("agnt-depl-xxx-%d", i),
195+
Phase: api.MemberPhaseCreated,
196+
Conditions: []api.Condition{
197+
{
198+
Type: api.ConditionTypeReady,
199+
Status: core.ConditionTrue,
200+
},
201+
},
202+
}, api.ServerGroupAgents))
203+
}
204+
}
205+
184206
// TestCreatePlanSingleScale creates a `single` deployment to test the creating of scaling plan.
185207
func TestCreatePlanSingleScale(t *testing.T) {
186208
c := &testContext{}
@@ -249,6 +271,8 @@ func TestCreatePlanActiveFailoverScale(t *testing.T) {
249271

250272
// Test with empty status
251273
var status api.DeploymentStatus
274+
addAgentsToStatus(t, &status, 3)
275+
252276
newPlan, changed := createPlan(log, depl, nil, spec, status, nil, c)
253277
assert.True(t, changed)
254278
require.Len(t, newPlan, 2)
@@ -314,6 +338,8 @@ func TestCreatePlanClusterScale(t *testing.T) {
314338

315339
// Test with empty status
316340
var status api.DeploymentStatus
341+
addAgentsToStatus(t, &status, 3)
342+
317343
newPlan, changed := createPlan(log, depl, nil, spec, status, nil, c)
318344
assert.True(t, changed)
319345
require.Len(t, newPlan, 6) // Adding 3 dbservers & 3 coordinators (note: agents do not scale now)
@@ -420,14 +446,6 @@ func TestCreatePlan(t *testing.T) {
420446
ID: "3",
421447
},
422448
}
423-
twoAgents := api.MemberStatusList{
424-
{
425-
ID: "1",
426-
},
427-
{
428-
ID: "2",
429-
},
430-
}
431449
threeDBServers := api.MemberStatusList{
432450
{
433451
ID: "1",
@@ -455,10 +473,10 @@ func TestCreatePlan(t *testing.T) {
455473
Members: api.DeploymentStatusMembers{
456474
DBServers: threeDBServers,
457475
Coordinators: threeCoordinators,
458-
Agents: twoAgents,
459476
},
460477
},
461478
}
479+
addAgentsToStatus(t, &deploymentTemplate.Status, 3)
462480
deploymentTemplate.Spec.SetDefaults("createPlanTest")
463481

464482
testCases := []struct {
@@ -525,17 +543,17 @@ func TestCreatePlan(t *testing.T) {
525543
Name: "Change Storage for DBServers",
526544
context: &testContext{
527545
ArangoDeployment: deploymentTemplate.DeepCopy(),
528-
PVC: &v1.PersistentVolumeClaim{
529-
Spec: v1.PersistentVolumeClaimSpec{
546+
PVC: &core.PersistentVolumeClaim{
547+
Spec: core.PersistentVolumeClaimSpec{
530548
StorageClassName: util.NewString("oldStorage"),
531549
},
532550
},
533551
},
534552
Helper: func(ad *api.ArangoDeployment) {
535553
ad.Spec.DBServers = api.ServerGroupSpec{
536554
Count: util.NewInt(3),
537-
VolumeClaimTemplate: &v1.PersistentVolumeClaim{
538-
Spec: v1.PersistentVolumeClaimSpec{
555+
VolumeClaimTemplate: &core.PersistentVolumeClaim{
556+
Spec: core.PersistentVolumeClaimSpec{
539557
StorageClassName: util.NewString("newStorage"),
540558
},
541559
},
@@ -558,8 +576,8 @@ func TestCreatePlan(t *testing.T) {
558576
Name: "Change Storage for Agents with deprecated storage class name",
559577
context: &testContext{
560578
ArangoDeployment: deploymentTemplate.DeepCopy(),
561-
PVC: &v1.PersistentVolumeClaim{
562-
Spec: v1.PersistentVolumeClaimSpec{
579+
PVC: &core.PersistentVolumeClaim{
580+
Spec: core.PersistentVolumeClaimSpec{
563581
StorageClassName: util.NewString("oldStorage"),
564582
},
565583
},
@@ -584,17 +602,17 @@ func TestCreatePlan(t *testing.T) {
584602
Name: "Storage for Coordinators is not possible",
585603
context: &testContext{
586604
ArangoDeployment: deploymentTemplate.DeepCopy(),
587-
PVC: &v1.PersistentVolumeClaim{
588-
Spec: v1.PersistentVolumeClaimSpec{
605+
PVC: &core.PersistentVolumeClaim{
606+
Spec: core.PersistentVolumeClaimSpec{
589607
StorageClassName: util.NewString("oldStorage"),
590608
},
591609
},
592610
},
593611
Helper: func(ad *api.ArangoDeployment) {
594612
ad.Spec.Coordinators = api.ServerGroupSpec{
595613
Count: util.NewInt(3),
596-
VolumeClaimTemplate: &v1.PersistentVolumeClaim{
597-
Spec: v1.PersistentVolumeClaimSpec{
614+
VolumeClaimTemplate: &core.PersistentVolumeClaim{
615+
Spec: core.PersistentVolumeClaimSpec{
598616
StorageClassName: util.NewString("newStorage"),
599617
},
600618
},
@@ -605,7 +623,7 @@ func TestCreatePlan(t *testing.T) {
605623
ExpectedPlan: []api.Action{},
606624
ExpectedLog: "Storage class has changed - pod needs replacement",
607625
ExpectedEvent: &k8sutil.Event{
608-
Type: v1.EventTypeNormal,
626+
Type: core.EventTypeNormal,
609627
Reason: "Coordinator Member StorageClass Cannot Change",
610628
Message: "Member 1 with role coordinator should use a different StorageClass, but is cannot because: Not supported",
611629
},
@@ -614,15 +632,15 @@ func TestCreatePlan(t *testing.T) {
614632
Name: "Create rotation plan",
615633
context: &testContext{
616634
ArangoDeployment: deploymentTemplate.DeepCopy(),
617-
PVC: &v1.PersistentVolumeClaim{
618-
Spec: v1.PersistentVolumeClaimSpec{
635+
PVC: &core.PersistentVolumeClaim{
636+
Spec: core.PersistentVolumeClaimSpec{
619637
StorageClassName: util.NewString("oldStorage"),
620638
},
621-
Status: v1.PersistentVolumeClaimStatus{
622-
Conditions: []v1.PersistentVolumeClaimCondition{
639+
Status: core.PersistentVolumeClaimStatus{
640+
Conditions: []core.PersistentVolumeClaimCondition{
623641
{
624-
Type: v1.PersistentVolumeClaimFileSystemResizePending,
625-
Status: v1.ConditionTrue,
642+
Type: core.PersistentVolumeClaimFileSystemResizePending,
643+
Status: core.ConditionTrue,
626644
},
627645
},
628646
},
@@ -631,8 +649,8 @@ func TestCreatePlan(t *testing.T) {
631649
Helper: func(ad *api.ArangoDeployment) {
632650
ad.Spec.Agents = api.ServerGroupSpec{
633651
Count: util.NewInt(2),
634-
VolumeClaimTemplate: &v1.PersistentVolumeClaim{
635-
Spec: v1.PersistentVolumeClaimSpec{
652+
VolumeClaimTemplate: &core.PersistentVolumeClaim{
653+
Spec: core.PersistentVolumeClaimSpec{
636654
StorageClassName: util.NewString("oldStorage"),
637655
},
638656
},
@@ -676,7 +694,7 @@ func TestCreatePlan(t *testing.T) {
676694
ad.Status.Members.DBServers[0].Conditions = api.ConditionList{
677695
{
678696
Type: api.ConditionTypeCleanedOut,
679-
Status: v1.ConditionTrue,
697+
Status: core.ConditionTrue,
680698
},
681699
}
682700
},

0 commit comments

Comments
 (0)