From e270143c6fa10843df159d41c98c5a9c4ba01f37 Mon Sep 17 00:00:00 2001 From: ajanikow Date: Tue, 4 Feb 2020 09:35:23 +0000 Subject: [PATCH 1/2] Cluster Upgrade for 3.6 --- go.mod | 1 - pkg/deployment/pod/args.go | 40 ++++++ pkg/deployment/pod/pair.go | 46 ++++++ pkg/deployment/pod/upgrade.go | 47 ++++++ pkg/deployment/reconcile/plan_builder_test.go | 88 +++++++----- pkg/deployment/resources/exporter.go | 9 +- pkg/deployment/resources/pod_creator.go | 135 ++++++++---------- .../pod_creator_coordinator_args_test.go | 42 ++++++ 8 files changed, 294 insertions(+), 114 deletions(-) create mode 100644 pkg/deployment/pod/args.go create mode 100644 pkg/deployment/pod/pair.go create mode 100644 pkg/deployment/pod/upgrade.go diff --git a/go.mod b/go.mod index 6672b09ee..ff0047420 100644 --- a/go.mod +++ b/go.mod @@ -67,7 +67,6 @@ require ( github.com/mattn/go-isatty v0.0.7 // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 // indirect - github.com/pborman/uuid v1.2.0 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pkg/errors v0.8.1 github.com/prometheus/client_golang v1.0.0 diff --git a/pkg/deployment/pod/args.go b/pkg/deployment/pod/args.go new file mode 100644 index 000000000..04a0c2ff9 --- /dev/null +++ b/pkg/deployment/pod/args.go @@ -0,0 +1,40 @@ +// +// DISCLAIMER +// +// Copyright 2020 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. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright holder is ArangoDB GmbH, Cologne, Germany +// +// Author Adam Janikowski +// + +package pod + +import ( + "github.com/arangodb/go-driver" + deploymentApi "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1" +) + +type Input struct { + Deployment deploymentApi.DeploymentSpec + GroupSpec deploymentApi.ServerGroupSpec + Group deploymentApi.ServerGroup + Version driver.Version + AutoUpgrade bool +} + +type ArgumentsBuilder interface { + Create(i Input) []OptionPair +} diff --git a/pkg/deployment/pod/pair.go b/pkg/deployment/pod/pair.go new file mode 100644 index 000000000..e1b3bd4da --- /dev/null +++ b/pkg/deployment/pod/pair.go @@ -0,0 +1,46 @@ +// +// DISCLAIMER +// +// Copyright 2020 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. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright holder is ArangoDB GmbH, Cologne, Germany +// +// Author Adam Janikowski +// + +package pod + +import "strings" + +// OptionPair key value pair builder +type OptionPair struct { + Key string + Value string +} + +// CompareTo returns -1 if o < other, 0 if o == other, 1 otherwise +func (o OptionPair) CompareTo(other OptionPair) int { + rc := strings.Compare(o.Key, other.Key) + if rc < 0 { + return -1 + } else if rc > 0 { + return 1 + } + return strings.Compare(o.Value, other.Value) +} + +func NewOptionPair(pairs...OptionPair) []OptionPair { + return pairs +} \ No newline at end of file diff --git a/pkg/deployment/pod/upgrade.go b/pkg/deployment/pod/upgrade.go new file mode 100644 index 000000000..163fb9a6a --- /dev/null +++ b/pkg/deployment/pod/upgrade.go @@ -0,0 +1,47 @@ +// +// DISCLAIMER +// +// Copyright 2020 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. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright holder is ArangoDB GmbH, Cologne, Germany +// +// Author Adam Janikowski +// + +package pod + +import deploymentApi "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1" + +func AutoUpgrade() ArgumentsBuilder { + return autoUpgradeArgs{} +} + +type autoUpgradeArgs struct {} + +func (u autoUpgradeArgs) Create(i Input) []OptionPair { + if !i.AutoUpgrade { + return NewOptionPair() + } + + if i.Version.CompareTo("3.6.0") >= 0 { + switch i.Group { + case deploymentApi.ServerGroupCoordinators: + return NewOptionPair(OptionPair{"--cluster.upgrade", "online"}) + } + } + + return NewOptionPair(OptionPair{"--database.auto-upgrade", "true"}) +} + diff --git a/pkg/deployment/reconcile/plan_builder_test.go b/pkg/deployment/reconcile/plan_builder_test.go index 02fe40865..e97caa4cf 100644 --- a/pkg/deployment/reconcile/plan_builder_test.go +++ b/pkg/deployment/reconcile/plan_builder_test.go @@ -40,18 +40,24 @@ import ( api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1" "github.com/arangodb/kube-arangodb/pkg/util" "github.com/arangodb/kube-arangodb/pkg/util/k8sutil" - v1 "k8s.io/api/core/v1" + core "k8s.io/api/core/v1" ) +var _ PlanBuilderContext = &testContext{} + type testContext struct { - Pods []v1.Pod + Pods []core.Pod ErrPods error ArangoDeployment *api.ArangoDeployment - PVC *v1.PersistentVolumeClaim + PVC *core.PersistentVolumeClaim PVCErr error RecordedEvent *k8sutil.Event } +func (c *testContext) GetAgencyData(ctx context.Context, i interface{}, keyParts ...string) error { + return nil +} + func (c *testContext) GetAPIObject() k8sutil.APIObject { if c.ArangoDeployment == nil { return &api.ArangoDeployment{} @@ -108,13 +114,13 @@ func (c *testContext) RemovePodFinalizers(podName string) error { panic("implement me") } -func (c *testContext) GetOwnedPods() ([]v1.Pod, error) { +func (c *testContext) GetOwnedPods() ([]core.Pod, error) { if c.ErrPods != nil { return nil, c.ErrPods } if c.Pods == nil { - return make([]v1.Pod, 0), c.ErrPods + return make([]core.Pod, 0), c.ErrPods } return c.Pods, c.ErrPods } @@ -158,7 +164,7 @@ func (c *testContext) CreateEvent(evt *k8sutil.Event) { } // GetPvc gets a PVC by the given name, in the samespace of the deployment. -func (c *testContext) GetPvc(pvcName string) (*v1.PersistentVolumeClaim, error) { +func (c *testContext) GetPvc(pvcName string) (*core.PersistentVolumeClaim, error) { return c.PVC, c.PVCErr } @@ -181,6 +187,22 @@ func (c *testContext) GetStatus() (api.DeploymentStatus, int32) { return c.ArangoDeployment.Status, 0 } +func addAgentsToStatus(t *testing.T, status *api.DeploymentStatus, count int) { + for i := 0; i < count; i++ { + require.NoError(t, status.Members.Add(api.MemberStatus{ + ID: fmt.Sprintf("AGNT-%d", i), + PodName: fmt.Sprintf("agnt-depl-xxx-%d", i), + Phase: api.MemberPhaseCreated, + Conditions: []api.Condition{ + { + Type: api.ConditionTypeReady, + Status: core.ConditionTrue, + }, + }, + }, api.ServerGroupAgents)) + } +} + // TestCreatePlanSingleScale creates a `single` deployment to test the creating of scaling plan. func TestCreatePlanSingleScale(t *testing.T) { c := &testContext{} @@ -249,6 +271,8 @@ func TestCreatePlanActiveFailoverScale(t *testing.T) { // Test with empty status var status api.DeploymentStatus + addAgentsToStatus(t, &status, 3) + newPlan, changed := createPlan(log, depl, nil, spec, status, nil, c) assert.True(t, changed) require.Len(t, newPlan, 2) @@ -314,6 +338,8 @@ func TestCreatePlanClusterScale(t *testing.T) { // Test with empty status var status api.DeploymentStatus + addAgentsToStatus(t, &status, 3) + newPlan, changed := createPlan(log, depl, nil, spec, status, nil, c) assert.True(t, changed) 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) { ID: "3", }, } - twoAgents := api.MemberStatusList{ - { - ID: "1", - }, - { - ID: "2", - }, - } threeDBServers := api.MemberStatusList{ { ID: "1", @@ -455,10 +473,10 @@ func TestCreatePlan(t *testing.T) { Members: api.DeploymentStatusMembers{ DBServers: threeDBServers, Coordinators: threeCoordinators, - Agents: twoAgents, }, }, } + addAgentsToStatus(t, &deploymentTemplate.Status, 3) deploymentTemplate.Spec.SetDefaults("createPlanTest") testCases := []struct { @@ -525,8 +543,8 @@ func TestCreatePlan(t *testing.T) { Name: "Change Storage for DBServers", context: &testContext{ ArangoDeployment: deploymentTemplate.DeepCopy(), - PVC: &v1.PersistentVolumeClaim{ - Spec: v1.PersistentVolumeClaimSpec{ + PVC: &core.PersistentVolumeClaim{ + Spec: core.PersistentVolumeClaimSpec{ StorageClassName: util.NewString("oldStorage"), }, }, @@ -534,8 +552,8 @@ func TestCreatePlan(t *testing.T) { Helper: func(ad *api.ArangoDeployment) { ad.Spec.DBServers = api.ServerGroupSpec{ Count: util.NewInt(3), - VolumeClaimTemplate: &v1.PersistentVolumeClaim{ - Spec: v1.PersistentVolumeClaimSpec{ + VolumeClaimTemplate: &core.PersistentVolumeClaim{ + Spec: core.PersistentVolumeClaimSpec{ StorageClassName: util.NewString("newStorage"), }, }, @@ -558,8 +576,8 @@ func TestCreatePlan(t *testing.T) { Name: "Change Storage for Agents with deprecated storage class name", context: &testContext{ ArangoDeployment: deploymentTemplate.DeepCopy(), - PVC: &v1.PersistentVolumeClaim{ - Spec: v1.PersistentVolumeClaimSpec{ + PVC: &core.PersistentVolumeClaim{ + Spec: core.PersistentVolumeClaimSpec{ StorageClassName: util.NewString("oldStorage"), }, }, @@ -584,8 +602,8 @@ func TestCreatePlan(t *testing.T) { Name: "Storage for Coordinators is not possible", context: &testContext{ ArangoDeployment: deploymentTemplate.DeepCopy(), - PVC: &v1.PersistentVolumeClaim{ - Spec: v1.PersistentVolumeClaimSpec{ + PVC: &core.PersistentVolumeClaim{ + Spec: core.PersistentVolumeClaimSpec{ StorageClassName: util.NewString("oldStorage"), }, }, @@ -593,8 +611,8 @@ func TestCreatePlan(t *testing.T) { Helper: func(ad *api.ArangoDeployment) { ad.Spec.Coordinators = api.ServerGroupSpec{ Count: util.NewInt(3), - VolumeClaimTemplate: &v1.PersistentVolumeClaim{ - Spec: v1.PersistentVolumeClaimSpec{ + VolumeClaimTemplate: &core.PersistentVolumeClaim{ + Spec: core.PersistentVolumeClaimSpec{ StorageClassName: util.NewString("newStorage"), }, }, @@ -605,7 +623,7 @@ func TestCreatePlan(t *testing.T) { ExpectedPlan: []api.Action{}, ExpectedLog: "Storage class has changed - pod needs replacement", ExpectedEvent: &k8sutil.Event{ - Type: v1.EventTypeNormal, + Type: core.EventTypeNormal, Reason: "Coordinator Member StorageClass Cannot Change", Message: "Member 1 with role coordinator should use a different StorageClass, but is cannot because: Not supported", }, @@ -614,15 +632,15 @@ func TestCreatePlan(t *testing.T) { Name: "Create rotation plan", context: &testContext{ ArangoDeployment: deploymentTemplate.DeepCopy(), - PVC: &v1.PersistentVolumeClaim{ - Spec: v1.PersistentVolumeClaimSpec{ + PVC: &core.PersistentVolumeClaim{ + Spec: core.PersistentVolumeClaimSpec{ StorageClassName: util.NewString("oldStorage"), }, - Status: v1.PersistentVolumeClaimStatus{ - Conditions: []v1.PersistentVolumeClaimCondition{ + Status: core.PersistentVolumeClaimStatus{ + Conditions: []core.PersistentVolumeClaimCondition{ { - Type: v1.PersistentVolumeClaimFileSystemResizePending, - Status: v1.ConditionTrue, + Type: core.PersistentVolumeClaimFileSystemResizePending, + Status: core.ConditionTrue, }, }, }, @@ -631,8 +649,8 @@ func TestCreatePlan(t *testing.T) { Helper: func(ad *api.ArangoDeployment) { ad.Spec.Agents = api.ServerGroupSpec{ Count: util.NewInt(2), - VolumeClaimTemplate: &v1.PersistentVolumeClaim{ - Spec: v1.PersistentVolumeClaimSpec{ + VolumeClaimTemplate: &core.PersistentVolumeClaim{ + Spec: core.PersistentVolumeClaimSpec{ StorageClassName: util.NewString("oldStorage"), }, }, @@ -676,7 +694,7 @@ func TestCreatePlan(t *testing.T) { ad.Status.Members.DBServers[0].Conditions = api.ConditionList{ { Type: api.ConditionTypeCleanedOut, - Status: v1.ConditionTrue, + Status: core.ConditionTrue, }, } }, diff --git a/pkg/deployment/resources/exporter.go b/pkg/deployment/resources/exporter.go index eb44db660..788a84487 100644 --- a/pkg/deployment/resources/exporter.go +++ b/pkg/deployment/resources/exporter.go @@ -21,6 +21,7 @@ package resources import ( + "github.com/arangodb/kube-arangodb/pkg/deployment/pod" "path/filepath" "sort" "strconv" @@ -59,19 +60,19 @@ func ArangodbExporterContainer(image string, args []string, livenessProbe *k8sut func createExporterArgs(isSecure bool) []string { tokenpath := filepath.Join(k8sutil.ExporterJWTVolumeMountDir, constants.SecretKeyToken) - options := make([]optionPair, 0, 64) + options := make([]pod.OptionPair, 0, 64) scheme := "http" if isSecure { scheme = "https" } options = append(options, - optionPair{"--arangodb.jwt-file", tokenpath}, - optionPair{"--arangodb.endpoint", scheme + "://localhost:" + strconv.Itoa(k8sutil.ArangoPort)}, + pod.OptionPair{"--arangodb.jwt-file", tokenpath}, + pod.OptionPair{"--arangodb.endpoint", scheme + "://localhost:" + strconv.Itoa(k8sutil.ArangoPort)}, ) keyPath := filepath.Join(k8sutil.TLSKeyfileVolumeMountDir, constants.SecretTLSKeyfile) if isSecure { options = append(options, - optionPair{"--ssl.keyfile", keyPath}, + pod.OptionPair{"--ssl.keyfile", keyPath}, ) } args := make([]string, 0, 2+len(options)) diff --git a/pkg/deployment/resources/pod_creator.go b/pkg/deployment/resources/pod_creator.go index ab3d12c9f..54ca41274 100644 --- a/pkg/deployment/resources/pod_creator.go +++ b/pkg/deployment/resources/pod_creator.go @@ -26,12 +26,12 @@ import ( "crypto/sha1" "encoding/json" "fmt" + "github.com/arangodb/kube-arangodb/pkg/deployment/pod" "net" "net/url" "path/filepath" "sort" "strconv" - "strings" "sync" "time" @@ -46,22 +46,6 @@ import ( "k8s.io/client-go/kubernetes" ) -type optionPair struct { - Key string - Value string -} - -// CompareTo returns -1 if o < other, 0 if o == other, 1 otherwise -func (o optionPair) CompareTo(other optionPair) int { - rc := strings.Compare(o.Key, other.Key) - if rc < 0 { - return -1 - } else if rc > 0 { - return 1 - } - return strings.Compare(o.Value, other.Value) -} - func versionHasAdvertisedEndpoint(v driver.Version) bool { return v.CompareTo("3.4.0") >= 0 } @@ -83,57 +67,65 @@ func versionHasJWTSecretKeyfile(v driver.Version) bool { // createArangodArgs creates command line arguments for an arangod server in the given group. func createArangodArgs(apiObject metav1.Object, deplSpec api.DeploymentSpec, group api.ServerGroup, agents api.MemberStatusList, id string, version driver.Version, autoUpgrade bool) []string { - options := make([]optionPair, 0, 64) + options := make([]pod.OptionPair, 0, 64) svrSpec := deplSpec.GetServerGroupSpec(group) + i := pod.Input{ + Deployment: deplSpec, + Group: group, + GroupSpec: svrSpec, + Version: version, + AutoUpgrade: autoUpgrade, + } + //scheme := NewURLSchemes(bsCfg.SslKeyFile != "").Arangod scheme := "tcp" if deplSpec.IsSecure() { scheme = "ssl" } options = append(options, - optionPair{"--server.endpoint", fmt.Sprintf("%s://%s:%d", scheme, deplSpec.GetListenAddr(), k8sutil.ArangoPort)}, + pod.OptionPair{"--server.endpoint", fmt.Sprintf("%s://%s:%d", scheme, deplSpec.GetListenAddr(), k8sutil.ArangoPort)}, ) // Authentication if deplSpec.IsAuthenticated() { // With authentication options = append(options, - optionPair{"--server.authentication", "true"}, + pod.OptionPair{"--server.authentication", "true"}, ) if versionHasJWTSecretKeyfile(version) { keyPath := filepath.Join(k8sutil.ClusterJWTSecretVolumeMountDir, constants.SecretKeyToken) options = append(options, - optionPair{"--server.jwt-secret-keyfile", keyPath}, + pod.OptionPair{"--server.jwt-secret-keyfile", keyPath}, ) } else { options = append(options, - optionPair{"--server.jwt-secret", "$(" + constants.EnvArangodJWTSecret + ")"}, + pod.OptionPair{"--server.jwt-secret", "$(" + constants.EnvArangodJWTSecret + ")"}, ) } } else { // Without authentication options = append(options, - optionPair{"--server.authentication", "false"}, + pod.OptionPair{"--server.authentication", "false"}, ) } // Storage engine options = append(options, - optionPair{"--server.storage-engine", deplSpec.GetStorageEngine().AsArangoArgument()}, + pod.OptionPair{"--server.storage-engine", deplSpec.GetStorageEngine().AsArangoArgument()}, ) // Logging options = append(options, - optionPair{"--log.level", "INFO"}, + pod.OptionPair{"--log.level", "INFO"}, ) // TLS if deplSpec.IsSecure() { keyPath := filepath.Join(k8sutil.TLSKeyfileVolumeMountDir, constants.SecretTLSKeyfile) options = append(options, - optionPair{"--ssl.keyfile", keyPath}, - optionPair{"--ssl.ecdh-curve", ""}, // This way arangod accepts curves other than P256 as well. + pod.OptionPair{"--ssl.keyfile", keyPath}, + pod.OptionPair{"--ssl.ecdh-curve", ""}, // This way arangod accepts curves other than P256 as well. ) /*if bsCfg.SslKeyFile != "" { if bsCfg.SslCAFile != "" { @@ -147,89 +139,84 @@ func createArangodArgs(apiObject metav1.Object, deplSpec api.DeploymentSpec, gro if deplSpec.RocksDB.IsEncrypted() { keyPath := filepath.Join(k8sutil.RocksDBEncryptionVolumeMountDir, constants.SecretEncryptionKey) options = append(options, - optionPair{"--rocksdb.encryption-keyfile", keyPath}, + pod.OptionPair{"--rocksdb.encryption-keyfile", keyPath}, ) } options = append(options, - optionPair{"--database.directory", k8sutil.ArangodVolumeMountDir}, - optionPair{"--log.output", "+"}, + pod.OptionPair{"--database.directory", k8sutil.ArangodVolumeMountDir}, + pod.OptionPair{"--log.output", "+"}, ) - // Auto upgrade? - if autoUpgrade { - options = append(options, - optionPair{"--database.auto-upgrade", "true"}, - ) - } + options = append(options, pod.AutoUpgrade().Create(i)...) versionHasAdvertisedEndpoint := versionHasAdvertisedEndpoint(version) /* if config.ServerThreads != 0 { options = append(options, - optionPair{"--server.threads", strconv.Itoa(config.ServerThreads)}) + pod.OptionPair{"--server.threads", strconv.Itoa(config.ServerThreads)}) }*/ /*if config.DebugCluster { options = append(options, - optionPair{"--log.level", "startup=trace"}) + pod.OptionPair{"--log.level", "startup=trace"}) }*/ myTCPURL := scheme + "://" + net.JoinHostPort(k8sutil.CreatePodDNSName(apiObject, group.AsRole(), id), strconv.Itoa(k8sutil.ArangoPort)) addAgentEndpoints := false switch group { case api.ServerGroupAgents: options = append(options, - optionPair{"--agency.disaster-recovery-id", id}, - optionPair{"--agency.activate", "true"}, - optionPair{"--agency.my-address", myTCPURL}, - optionPair{"--agency.size", strconv.Itoa(deplSpec.Agents.GetCount())}, - optionPair{"--agency.supervision", "true"}, - optionPair{"--foxx.queues", "false"}, - optionPair{"--server.statistics", "false"}, + pod.OptionPair{"--agency.disaster-recovery-id", id}, + pod.OptionPair{"--agency.activate", "true"}, + pod.OptionPair{"--agency.my-address", myTCPURL}, + pod.OptionPair{"--agency.size", strconv.Itoa(deplSpec.Agents.GetCount())}, + pod.OptionPair{"--agency.supervision", "true"}, + pod.OptionPair{"--foxx.queues", "false"}, + pod.OptionPair{"--server.statistics", "false"}, ) for _, p := range agents { if p.ID != id { dnsName := k8sutil.CreatePodDNSName(apiObject, api.ServerGroupAgents.AsRole(), p.ID) options = append(options, - optionPair{"--agency.endpoint", fmt.Sprintf("%s://%s", scheme, net.JoinHostPort(dnsName, strconv.Itoa(k8sutil.ArangoPort)))}, + pod.OptionPair{"--agency.endpoint", fmt.Sprintf("%s://%s", scheme, net.JoinHostPort(dnsName, strconv.Itoa(k8sutil.ArangoPort)))}, ) } } case api.ServerGroupDBServers: addAgentEndpoints = true options = append(options, - optionPair{"--cluster.my-address", myTCPURL}, - optionPair{"--cluster.my-role", "PRIMARY"}, - optionPair{"--foxx.queues", "false"}, - optionPair{"--server.statistics", "true"}, + pod.OptionPair{"--cluster.my-address", myTCPURL}, + pod.OptionPair{"--cluster.my-role", "PRIMARY"}, + pod.OptionPair{"--foxx.queues", "false"}, + pod.OptionPair{"--server.statistics", "true"}, ) case api.ServerGroupCoordinators: addAgentEndpoints = true options = append(options, - optionPair{"--cluster.my-address", myTCPURL}, - optionPair{"--cluster.my-role", "COORDINATOR"}, - optionPair{"--foxx.queues", "true"}, - optionPair{"--server.statistics", "true"}, + pod.OptionPair{"--cluster.my-address", myTCPURL}, + pod.OptionPair{"--cluster.my-role", "COORDINATOR"}, + pod.OptionPair{"--foxx.queues", "true"}, + pod.OptionPair{"--server.statistics", "true"}, ) if deplSpec.ExternalAccess.HasAdvertisedEndpoint() && versionHasAdvertisedEndpoint { options = append(options, - optionPair{"--cluster.my-advertised-endpoint", deplSpec.ExternalAccess.GetAdvertisedEndpoint()}, + pod.OptionPair{"--cluster.my-advertised-endpoint", deplSpec.ExternalAccess.GetAdvertisedEndpoint()}, ) } case api.ServerGroupSingle: options = append(options, - optionPair{"--foxx.queues", "true"}, - optionPair{"--server.statistics", "true"}, + pod.OptionPair{"--foxx.queues", "true"}, + pod.OptionPair{"--server.statistics", "true"}, ) if deplSpec.GetMode() == api.DeploymentModeActiveFailover { addAgentEndpoints = true options = append(options, - optionPair{"--replication.automatic-failover", "true"}, - optionPair{"--cluster.my-address", myTCPURL}, - optionPair{"--cluster.my-role", "SINGLE"}, + pod.OptionPair{"--replication.automatic-failover", "true"}, + pod.OptionPair{"--cluster.my-address", myTCPURL}, + pod.OptionPair{"--cluster.my-role", "SINGLE"}, ) if deplSpec.ExternalAccess.HasAdvertisedEndpoint() && versionHasAdvertisedEndpoint { options = append(options, - optionPair{"--cluster.my-advertised-endpoint", deplSpec.ExternalAccess.GetAdvertisedEndpoint()}, + pod.OptionPair{"--cluster.my-advertised-endpoint", deplSpec.ExternalAccess.GetAdvertisedEndpoint()}, ) } } @@ -238,7 +225,7 @@ func createArangodArgs(apiObject metav1.Object, deplSpec api.DeploymentSpec, gro for _, p := range agents { dnsName := k8sutil.CreatePodDNSName(apiObject, api.ServerGroupAgents.AsRole(), p.ID) options = append(options, - optionPair{"--cluster.agency-endpoint", + pod.OptionPair{"--cluster.agency-endpoint", fmt.Sprintf("%s://%s", scheme, net.JoinHostPort(dnsName, strconv.Itoa(k8sutil.ArangoPort)))}, ) } @@ -259,22 +246,22 @@ func createArangodArgs(apiObject metav1.Object, deplSpec api.DeploymentSpec, gro // createArangoSyncArgs creates command line arguments for an arangosync server in the given group. func createArangoSyncArgs(apiObject metav1.Object, spec api.DeploymentSpec, group api.ServerGroup, groupSpec api.ServerGroupSpec, id string) []string { - options := make([]optionPair, 0, 64) + options := make([]pod.OptionPair, 0, 64) var runCmd string var port int /*if config.DebugCluster { options = append(options, - optionPair{"--log.level", "debug"}) + pod.OptionPair{"--log.level", "debug"}) }*/ if spec.Sync.Monitoring.GetTokenSecretName() != "" { options = append(options, - optionPair{"--monitoring.token", "$(" + constants.EnvArangoSyncMonitoringToken + ")"}, + pod.OptionPair{"--monitoring.token", "$(" + constants.EnvArangoSyncMonitoringToken + ")"}, ) } masterSecretPath := filepath.Join(k8sutil.MasterJWTSecretVolumeMountDir, constants.SecretKeyToken) options = append(options, - optionPair{"--master.jwt-secret", masterSecretPath}, + pod.OptionPair{"--master.jwt-secret", masterSecretPath}, ) var masterEndpoint []string switch group { @@ -285,14 +272,14 @@ func createArangoSyncArgs(apiObject metav1.Object, spec api.DeploymentSpec, grou keyPath := filepath.Join(k8sutil.TLSKeyfileVolumeMountDir, constants.SecretTLSKeyfile) clientCAPath := filepath.Join(k8sutil.ClientAuthCAVolumeMountDir, constants.SecretCACertificate) options = append(options, - optionPair{"--server.keyfile", keyPath}, - optionPair{"--server.client-cafile", clientCAPath}, - optionPair{"--mq.type", "direct"}, + pod.OptionPair{"--server.keyfile", keyPath}, + pod.OptionPair{"--server.client-cafile", clientCAPath}, + pod.OptionPair{"--mq.type", "direct"}, ) if spec.IsAuthenticated() { clusterSecretPath := filepath.Join(k8sutil.ClusterJWTSecretVolumeMountDir, constants.SecretKeyToken) options = append(options, - optionPair{"--cluster.jwt-secret", clusterSecretPath}, + pod.OptionPair{"--cluster.jwt-secret", clusterSecretPath}, ) } dbServiceName := k8sutil.CreateDatabaseClientServiceName(apiObject.GetName()) @@ -301,7 +288,7 @@ func createArangoSyncArgs(apiObject metav1.Object, spec api.DeploymentSpec, grou scheme = "https" } options = append(options, - optionPair{"--cluster.endpoint", fmt.Sprintf("%s://%s:%d", scheme, dbServiceName, k8sutil.ArangoPort)}) + pod.OptionPair{"--cluster.endpoint", fmt.Sprintf("%s://%s:%d", scheme, dbServiceName, k8sutil.ArangoPort)}) case api.ServerGroupSyncWorkers: runCmd = "worker" port = k8sutil.ArangoSyncWorkerPort @@ -310,12 +297,12 @@ func createArangoSyncArgs(apiObject metav1.Object, spec api.DeploymentSpec, grou } for _, ep := range masterEndpoint { options = append(options, - optionPair{"--master.endpoint", ep}) + pod.OptionPair{"--master.endpoint", ep}) } serverEndpoint := "https://" + net.JoinHostPort(k8sutil.CreatePodDNSName(apiObject, group.AsRole(), id), strconv.Itoa(port)) options = append(options, - optionPair{"--server.endpoint", serverEndpoint}, - optionPair{"--server.port", strconv.Itoa(port)}, + pod.OptionPair{"--server.endpoint", serverEndpoint}, + pod.OptionPair{"--server.port", strconv.Itoa(port)}, ) args := make([]string, 0, 2+len(options)+len(groupSpec.Args)) diff --git a/pkg/deployment/resources/pod_creator_coordinator_args_test.go b/pkg/deployment/resources/pod_creator_coordinator_args_test.go index b550c5736..54616b5a2 100644 --- a/pkg/deployment/resources/pod_creator_coordinator_args_test.go +++ b/pkg/deployment/resources/pod_creator_coordinator_args_test.go @@ -117,6 +117,48 @@ func TestCreateArangodArgsCoordinator(t *testing.T) { ) } + // Default+AutoUpgrade deployment for 3.6.0 + { + apiObject := &api.ArangoDeployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: "name", + Namespace: "ns", + }, + Spec: api.DeploymentSpec{ + Mode: api.NewMode(api.DeploymentModeCluster), + }, + } + apiObject.Spec.SetDefaults("test") + agents := api.MemberStatusList{ + api.MemberStatus{ID: "a1"}, + api.MemberStatus{ID: "a2"}, + api.MemberStatus{ID: "a3"}, + } + cmdline := createArangodArgs(apiObject, apiObject.Spec, api.ServerGroupCoordinators, agents, "id1", "3.6.0", true) + assert.Equal(t, + []string{ + "--cluster.agency-endpoint=ssl://name-agent-a1.name-int.ns.svc:8529", + "--cluster.agency-endpoint=ssl://name-agent-a2.name-int.ns.svc:8529", + "--cluster.agency-endpoint=ssl://name-agent-a3.name-int.ns.svc:8529", + "--cluster.my-address=ssl://name-coordinator-id1.name-int.ns.svc:8529", + "--cluster.my-role=COORDINATOR", + "--cluster.upgrade=online", + "--database.directory=/data", + "--foxx.queues=true", + "--log.level=INFO", + "--log.output=+", + "--server.authentication=true", + "--server.endpoint=ssl://[::]:8529", + "--server.jwt-secret-keyfile=/secrets/cluster/jwt/token", + "--server.statistics=true", + "--server.storage-engine=rocksdb", + "--ssl.ecdh-curve=", + "--ssl.keyfile=/secrets/tls/tls.keyfile", + }, + cmdline, + ) + } + // Default+TLS disabled deployment { apiObject := &api.ArangoDeployment{ From 9ef5fe83dbca864f97b1ac0c5ce0fbd0b3dc0da7 Mon Sep 17 00:00:00 2001 From: ajanikow Date: Tue, 4 Feb 2020 09:39:46 +0000 Subject: [PATCH 2/2] Linter fixes --- pkg/deployment/pod/args.go | 8 ++++---- pkg/deployment/pod/pair.go | 4 ++-- pkg/deployment/pod/upgrade.go | 3 +-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/pkg/deployment/pod/args.go b/pkg/deployment/pod/args.go index 04a0c2ff9..458175610 100644 --- a/pkg/deployment/pod/args.go +++ b/pkg/deployment/pod/args.go @@ -28,10 +28,10 @@ import ( ) type Input struct { - Deployment deploymentApi.DeploymentSpec - GroupSpec deploymentApi.ServerGroupSpec - Group deploymentApi.ServerGroup - Version driver.Version + Deployment deploymentApi.DeploymentSpec + GroupSpec deploymentApi.ServerGroupSpec + Group deploymentApi.ServerGroup + Version driver.Version AutoUpgrade bool } diff --git a/pkg/deployment/pod/pair.go b/pkg/deployment/pod/pair.go index e1b3bd4da..3f7de3e98 100644 --- a/pkg/deployment/pod/pair.go +++ b/pkg/deployment/pod/pair.go @@ -41,6 +41,6 @@ func (o OptionPair) CompareTo(other OptionPair) int { return strings.Compare(o.Value, other.Value) } -func NewOptionPair(pairs...OptionPair) []OptionPair { +func NewOptionPair(pairs ...OptionPair) []OptionPair { return pairs -} \ No newline at end of file +} diff --git a/pkg/deployment/pod/upgrade.go b/pkg/deployment/pod/upgrade.go index 163fb9a6a..44bcca740 100644 --- a/pkg/deployment/pod/upgrade.go +++ b/pkg/deployment/pod/upgrade.go @@ -28,7 +28,7 @@ func AutoUpgrade() ArgumentsBuilder { return autoUpgradeArgs{} } -type autoUpgradeArgs struct {} +type autoUpgradeArgs struct{} func (u autoUpgradeArgs) Create(i Input) []OptionPair { if !i.AutoUpgrade { @@ -44,4 +44,3 @@ func (u autoUpgradeArgs) Create(i Input) []OptionPair { return NewOptionPair(OptionPair{"--database.auto-upgrade", "true"}) } -