Skip to content

Commit a097829

Browse files
committed
Merge branch 'master' into store-accepted-spec
2 parents 61aaf55 + da9e477 commit a097829

File tree

4 files changed

+267
-1
lines changed

4 files changed

+267
-1
lines changed

pkg/deployment/cluster_informer.go

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2018 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 Ewout Prangsma
21+
//
22+
23+
package deployment
24+
25+
import (
26+
"context"
27+
"time"
28+
29+
"github.com/arangodb/kube-arangodb/pkg/util/arangod"
30+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
31+
)
32+
33+
// listenForClusterEvents keep listening for changes entered in the UI of the cluster.
34+
func (d *Deployment) listenForClusterEvents(stopCh <-chan struct{}) {
35+
for {
36+
delay := time.Second * 2
37+
38+
// Inspect once
39+
ctx := context.Background()
40+
if err := d.inspectCluster(ctx); err != nil {
41+
d.deps.Log.Debug().Err(err).Msg("Cluster inspection failed")
42+
}
43+
44+
select {
45+
case <-time.After(delay):
46+
// Continue
47+
case <-stopCh:
48+
// We're done
49+
return
50+
}
51+
}
52+
}
53+
54+
// Perform a single inspection of the cluster
55+
func (d *Deployment) inspectCluster(ctx context.Context) error {
56+
log := d.deps.Log
57+
c, err := d.clientCache.GetDatabase(ctx)
58+
if err != nil {
59+
return maskAny(err)
60+
}
61+
req, err := arangod.GetNumberOfServers(ctx, c.Connection())
62+
if err != nil {
63+
log.Debug().Err(err).Msg("Failed to get number of servers")
64+
return maskAny(err)
65+
}
66+
if req.Coordinators == nil && req.DBServers == nil {
67+
// Nothing to check
68+
return nil
69+
}
70+
coordinatorsChanged := false
71+
dbserversChanged := false
72+
d.lastNumberOfServers.mutex.Lock()
73+
defer d.lastNumberOfServers.mutex.Unlock()
74+
desired := d.lastNumberOfServers.NumberOfServers
75+
if req.Coordinators != nil && desired.Coordinators != nil && req.GetCoordinators() != desired.GetCoordinators() {
76+
// #Coordinator has changed
77+
coordinatorsChanged = true
78+
}
79+
if req.DBServers != nil && desired.DBServers != nil && req.GetDBServers() != desired.GetDBServers() {
80+
// #DBServers has changed
81+
dbserversChanged = true
82+
}
83+
if !coordinatorsChanged && !dbserversChanged {
84+
// Nothing has changed
85+
return nil
86+
}
87+
// Let's update the spec
88+
current, err := d.deps.DatabaseCRCli.DatabaseV1alpha().ArangoDeployments(d.apiObject.Namespace).Get(d.apiObject.Name, metav1.GetOptions{})
89+
if err != nil {
90+
log.Debug().Err(err).Msg("Failed to get current deployment")
91+
return maskAny(err)
92+
}
93+
if coordinatorsChanged {
94+
current.Spec.Coordinators.Count = req.GetCoordinators()
95+
}
96+
if dbserversChanged {
97+
current.Spec.DBServers.Count = req.GetDBServers()
98+
}
99+
if err := d.updateCRSpec(current.Spec); err != nil {
100+
log.Warn().Err(err).Msg("Failed to update current deployment")
101+
return maskAny(err)
102+
}
103+
return nil
104+
}

pkg/deployment/cluster_updater.go

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2018 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 Ewout Prangsma
21+
//
22+
23+
package deployment
24+
25+
import (
26+
"context"
27+
28+
"github.com/arangodb/kube-arangodb/pkg/util/arangod"
29+
)
30+
31+
// updateClusterServerCount updates the intended number of servers of the cluster.
32+
func (d *Deployment) updateClusterServerCount(ctx context.Context) error {
33+
log := d.deps.Log
34+
c, err := d.clientCache.GetDatabase(ctx)
35+
if err != nil {
36+
return maskAny(err)
37+
}
38+
spec := d.apiObject.Spec
39+
coordinatorCount := spec.Coordinators.Count
40+
dbserverCount := spec.DBServers.Count
41+
if err := arangod.SetNumberOfServers(ctx, c.Connection(), coordinatorCount, dbserverCount); err != nil {
42+
log.Debug().Err(err).Msg("Failed to set number of servers")
43+
return maskAny(err)
44+
}
45+
d.lastNumberOfServers.mutex.Lock()
46+
defer d.lastNumberOfServers.mutex.Unlock()
47+
d.lastNumberOfServers.Coordinators = &coordinatorCount
48+
d.lastNumberOfServers.DBServers = &dbserverCount
49+
return nil
50+
}

pkg/deployment/deployment.go

+19-1
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
package deployment
2424

2525
import (
26+
"context"
2627
"fmt"
2728
"reflect"
29+
"sync"
2830
"time"
2931

3032
"github.com/rs/zerolog"
@@ -36,6 +38,7 @@ import (
3638

3739
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha"
3840
"github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned"
41+
"github.com/arangodb/kube-arangodb/pkg/util/arangod"
3942
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
4043
"github.com/arangodb/kube-arangodb/pkg/util/retry"
4144
"github.com/arangodb/kube-arangodb/pkg/util/trigger"
@@ -89,8 +92,12 @@ type Deployment struct {
8992
eventsCli corev1.EventInterface
9093

9194
inspectTrigger trigger.Trigger
92-
recentInspectionErrors int
9395
clientCache *clientCache
96+
recentInspectionErrors int
97+
lastNumberOfServers struct {
98+
arangod.NumberOfServers
99+
mutex sync.Mutex
100+
}
94101
}
95102

96103
// New creates a new Deployment from the given API object.
@@ -115,6 +122,9 @@ func New(config Config, deps Dependencies, apiObject *api.ArangoDeployment) (*De
115122

116123
go d.run()
117124
go d.listenForPodEvents()
125+
if apiObject.Spec.Mode == api.DeploymentModeCluster {
126+
go d.listenForClusterEvents(d.stopCh)
127+
}
118128

119129
return d, nil
120130
}
@@ -282,6 +292,14 @@ func (d *Deployment) handleArangoDeploymentUpdatedEvent(event *deploymentEvent)
282292
return maskAny(fmt.Errorf("failed to update ArangoDeployment status: %v", err))
283293
}
284294

295+
// Notify cluster of desired server count
296+
if d.apiObject.Spec.Mode == api.DeploymentModeCluster {
297+
ctx := context.Background()
298+
if err := d.updateClusterServerCount(ctx); err != nil {
299+
log.Error().Err(err).Msg("Failed to update desired server count in cluster")
300+
}
301+
}
302+
285303
// Trigger inspect
286304
d.inspectTrigger.Trigger()
287305

pkg/util/arangod/cluster.go

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2018 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 Ewout Prangsma
21+
//
22+
23+
package arangod
24+
25+
import (
26+
"context"
27+
28+
driver "github.com/arangodb/go-driver"
29+
)
30+
31+
// NumberOfServers is the JSON structure return for the numberOfServers API call.
32+
type NumberOfServers struct {
33+
Coordinators *int `json:"numberOfCoordinators,omitempty"`
34+
DBServers *int `json:"numberOfDBServers,omitempty"`
35+
}
36+
37+
// GetCoordinators returns Coordinators if not nil, otherwise 0.
38+
func (n NumberOfServers) GetCoordinators() int {
39+
if n.Coordinators != nil {
40+
return *n.Coordinators
41+
}
42+
return 0
43+
}
44+
45+
// GetDBServers returns DBServers if not nil, otherwise 0.
46+
func (n NumberOfServers) GetDBServers() int {
47+
if n.DBServers != nil {
48+
return *n.DBServers
49+
}
50+
return 0
51+
}
52+
53+
// GetNumberOfServers fetches the number of servers the cluster wants to have.
54+
func GetNumberOfServers(ctx context.Context, conn driver.Connection) (NumberOfServers, error) {
55+
req, err := conn.NewRequest("GET", "_admin/cluster/numberOfServers")
56+
if err != nil {
57+
return NumberOfServers{}, maskAny(err)
58+
}
59+
resp, err := conn.Do(ctx, req)
60+
if err != nil {
61+
return NumberOfServers{}, maskAny(err)
62+
}
63+
if err := resp.CheckStatus(200); err != nil {
64+
return NumberOfServers{}, maskAny(err)
65+
}
66+
var result NumberOfServers
67+
if err := resp.ParseBody("", &result); err != nil {
68+
return NumberOfServers{}, maskAny(err)
69+
}
70+
return result, nil
71+
}
72+
73+
// SetNumberOfServers updates the number of servers the cluster has.
74+
func SetNumberOfServers(ctx context.Context, conn driver.Connection, noCoordinators, noDBServers int) error {
75+
req, err := conn.NewRequest("PUT", "_admin/cluster/numberOfServers")
76+
if err != nil {
77+
return maskAny(err)
78+
}
79+
input := NumberOfServers{
80+
Coordinators: &noCoordinators,
81+
DBServers: &noDBServers,
82+
}
83+
if _, err := req.SetBody(input); err != nil {
84+
return maskAny(err)
85+
}
86+
resp, err := conn.Do(ctx, req)
87+
if err != nil {
88+
return maskAny(err)
89+
}
90+
if err := resp.CheckStatus(200); err != nil {
91+
return maskAny(err)
92+
}
93+
return nil
94+
}

0 commit comments

Comments
 (0)