Skip to content

Commit b74beb5

Browse files
authored
[Bugfix] Add unreachable condition (#902)
1 parent 58b2ff9 commit b74beb5

File tree

15 files changed

+208
-12
lines changed

15 files changed

+208
-12
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
- Remove pod immediately when annotation is turned on
88
- (ARM64) Add support for ARM64 enablement
99
- (Cleanup) Reorganize main reconciliation context
10+
- (Bugfix) Unreachable condition
1011

1112
## [1.2.7](https://github.com/arangodb/kube-arangodb/tree/1.2.7) (2022-01-17)
1213
- Add Plan BackOff functionality

cmd/main.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ var (
131131
operatorTimeouts struct {
132132
k8s time.Duration
133133
arangoD time.Duration
134+
arangoDCheck time.Duration
134135
reconciliation time.Duration
135136
}
136137
chaosOptions struct {
@@ -170,6 +171,7 @@ func init() {
170171
f.StringVar(&operatorOptions.scope, "scope", scope.DefaultScope.String(), "Define scope on which Operator works. Legacy - pre 1.1.0 scope with limited cluster access")
171172
f.DurationVar(&operatorTimeouts.k8s, "timeout.k8s", globals.DefaultKubernetesTimeout, "The request timeout to the kubernetes")
172173
f.DurationVar(&operatorTimeouts.arangoD, "timeout.arangod", globals.DefaultArangoDTimeout, "The request timeout to the ArangoDB")
174+
f.DurationVar(&operatorTimeouts.arangoDCheck, "timeout.arangod-check", globals.DefaultArangoDCheckTimeout, "The version check request timeout to the ArangoDB")
173175
f.DurationVar(&operatorTimeouts.reconciliation, "timeout.reconciliation", globals.DefaultReconciliationTimeout, "The reconciliation timeout to the ArangoDB CR")
174176
f.BoolVar(&operatorOptions.scalingIntegrationEnabled, "internal.scaling-integration", true, "Enable Scaling Integration")
175177
f.Int64Var(&operatorKubernetesOptions.maxBatchSize, "kubernetes.max-batch-size", globals.DefaultKubernetesRequestBatchSize, "Size of batch during objects read")
@@ -206,6 +208,7 @@ func executeMain(cmd *cobra.Command, args []string) {
206208

207209
globals.GetGlobalTimeouts().Kubernetes().Set(operatorTimeouts.k8s)
208210
globals.GetGlobalTimeouts().ArangoD().Set(operatorTimeouts.arangoD)
211+
globals.GetGlobalTimeouts().ArangoDCheck().Set(operatorTimeouts.arangoDCheck)
209212
globals.GetGlobalTimeouts().Reconciliation().Set(operatorTimeouts.reconciliation)
210213
globals.GetGlobals().Kubernetes().RequestBatchSize().Set(operatorKubernetesOptions.maxBatchSize)
211214
globals.GetGlobals().Backup().ConcurrentUploads().Set(operatorBackup.concurrentUploads)

pkg/apis/deployment/v1/conditions.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ const (
3838
ConditionTypeReady ConditionType = "Ready"
3939
// ConditionTypeStarted indicates that the member was ready at least once.
4040
ConditionTypeStarted ConditionType = "Started"
41+
// ConditionTypeReachable indicates that the member is reachable.
42+
ConditionTypeReachable ConditionType = "Reachable"
4143
// ConditionTypeServing indicates that the member core services are running.
4244
ConditionTypeServing ConditionType = "Serving"
4345
// ConditionTypeTerminated indicates that the member has terminated and will not restart.
@@ -158,6 +160,15 @@ func (list ConditionList) IsTrue(conditionType ConditionType) bool {
158160
return found && c.IsTrue()
159161
}
160162

163+
// GetValue returns *bool value in case if condition exists, nil otherwise
164+
func (list ConditionList) GetValue(conditionType ConditionType) *bool {
165+
c, found := list.Get(conditionType)
166+
if found {
167+
return util.NewBool(c.IsTrue())
168+
}
169+
return nil
170+
}
171+
161172
// Get a condition by type.
162173
// Returns true if found, false if not found.
163174
func (list ConditionList) Get(conditionType ConditionType) (Condition, bool) {

pkg/apis/deployment/v1/deployment_member_status_element.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,36 @@
2020

2121
package v1
2222

23-
import "sort"
23+
import (
24+
"sort"
25+
"sync"
26+
)
2427

2528
type DeploymentStatusMemberElementsSortFunc func(a, b DeploymentStatusMemberElement) bool
2629
type DeploymentStatusMemberElementsCondFunc func(a DeploymentStatusMemberElement) bool
2730

2831
type DeploymentStatusMemberElements []DeploymentStatusMemberElement
2932

33+
func (d DeploymentStatusMemberElements) ForEach(f func(id int)) {
34+
if f == nil {
35+
return
36+
}
37+
38+
var wg sync.WaitGroup
39+
40+
wg.Add(len(d))
41+
42+
for id := range d {
43+
go func(i int) {
44+
defer wg.Done()
45+
46+
f(i)
47+
}(id)
48+
}
49+
50+
wg.Wait()
51+
}
52+
3053
func (d DeploymentStatusMemberElements) Filter(f DeploymentStatusMemberElementsCondFunc) DeploymentStatusMemberElements {
3154
var l DeploymentStatusMemberElements
3255

pkg/apis/deployment/v2alpha1/conditions.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ const (
3838
ConditionTypeReady ConditionType = "Ready"
3939
// ConditionTypeStarted indicates that the member was ready at least once.
4040
ConditionTypeStarted ConditionType = "Started"
41+
// ConditionTypeReachable indicates that the member is reachable.
42+
ConditionTypeReachable ConditionType = "Reachable"
4143
// ConditionTypeServing indicates that the member core services are running.
4244
ConditionTypeServing ConditionType = "Serving"
4345
// ConditionTypeTerminated indicates that the member has terminated and will not restart.
@@ -158,6 +160,15 @@ func (list ConditionList) IsTrue(conditionType ConditionType) bool {
158160
return found && c.IsTrue()
159161
}
160162

163+
// GetValue returns *bool value in case if condition exists, nil otherwise
164+
func (list ConditionList) GetValue(conditionType ConditionType) *bool {
165+
c, found := list.Get(conditionType)
166+
if found {
167+
return util.NewBool(c.IsTrue())
168+
}
169+
return nil
170+
}
171+
161172
// Get a condition by type.
162173
// Returns true if found, false if not found.
163174
func (list ConditionList) Get(conditionType ConditionType) (Condition, bool) {

pkg/apis/deployment/v2alpha1/deployment_member_status_element.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,36 @@
2020

2121
package v2alpha1
2222

23-
import "sort"
23+
import (
24+
"sort"
25+
"sync"
26+
)
2427

2528
type DeploymentStatusMemberElementsSortFunc func(a, b DeploymentStatusMemberElement) bool
2629
type DeploymentStatusMemberElementsCondFunc func(a DeploymentStatusMemberElement) bool
2730

2831
type DeploymentStatusMemberElements []DeploymentStatusMemberElement
2932

33+
func (d DeploymentStatusMemberElements) ForEach(f func(id int)) {
34+
if f == nil {
35+
return
36+
}
37+
38+
var wg sync.WaitGroup
39+
40+
wg.Add(len(d))
41+
42+
for id := range d {
43+
go func(i int) {
44+
defer wg.Done()
45+
46+
f(i)
47+
}(id)
48+
}
49+
50+
wg.Wait()
51+
}
52+
3053
func (d DeploymentStatusMemberElements) Filter(f DeploymentStatusMemberElementsCondFunc) DeploymentStatusMemberElements {
3154
var l DeploymentStatusMemberElements
3255

pkg/deployment/deployment.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ import (
5858

5959
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
6060
"github.com/arangodb/kube-arangodb/pkg/deployment/chaos"
61+
memberState "github.com/arangodb/kube-arangodb/pkg/deployment/member"
6162
"github.com/arangodb/kube-arangodb/pkg/deployment/reconcile"
6263
"github.com/arangodb/kube-arangodb/pkg/deployment/resilience"
6364
"github.com/arangodb/kube-arangodb/pkg/deployment/resources"
@@ -142,6 +143,8 @@ type Deployment struct {
142143
chaosMonkey *chaos.Monkey
143144
syncClientCache client.ClientCache
144145
haveServiceMonitorCRD bool
146+
147+
memberState.StateInspector
145148
}
146149

147150
func (d *Deployment) GetAgencyCache() (agency.State, bool) {
@@ -219,6 +222,8 @@ func New(config Config, deps Dependencies, apiObject *api.ArangoDeployment) (*De
219222
agencyCache: agency.NewCache(apiObject.Spec.Mode),
220223
}
221224

225+
d.StateInspector = memberState.NewStateInspector(d)
226+
222227
d.clientCache = deploymentClient.NewClientCache(d, conn.NewFactory(d.getAuth, d.getConnConfig))
223228

224229
d.status.last = *(apiObject.Status.DeepCopy())

pkg/deployment/deployment_inspector.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ func (d *Deployment) inspectDeployment(lastInterval util.Interval) util.Interval
115115

116116
d.apiObject = updated
117117

118+
d.RefreshState(ctxReconciliation, updated.Status.Members.AsList())
119+
118120
inspectNextInterval, err := d.inspectDeploymentWithError(ctxReconciliation, nextInterval, cachedStatus)
119121
if err != nil {
120122
if !operatorErrors.IsReconcile(err) {

pkg/deployment/member/phase_updates.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ func removeMemberConditionsMapFunc(m *api.MemberStatus) {
7171
// Clean conditions
7272
m.Conditions.Remove(api.ConditionTypeReady)
7373
m.Conditions.Remove(api.ConditionTypeStarted)
74+
m.Conditions.Remove(api.ConditionTypeReachable)
7475
m.Conditions.Remove(api.ConditionTypeServing)
7576
m.Conditions.Remove(api.ConditionTypeTerminated)
7677
m.Conditions.Remove(api.ConditionTypeTerminating)

pkg/deployment/member/state.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2016-2022 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+
21+
package member
22+
23+
import (
24+
"context"
25+
"sync"
26+
27+
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
28+
"github.com/arangodb/kube-arangodb/pkg/deployment/reconciler"
29+
"github.com/arangodb/kube-arangodb/pkg/util/globals"
30+
)
31+
32+
type StateInspector interface {
33+
RefreshState(ctx context.Context, members api.DeploymentStatusMemberElements)
34+
MemberState(id string) (State, bool)
35+
}
36+
37+
func NewStateInspector(client reconciler.DeploymentMemberClient) StateInspector {
38+
return &stateInspector{
39+
client: client,
40+
}
41+
}
42+
43+
type stateInspector struct {
44+
lock sync.Mutex
45+
46+
members map[string]State
47+
48+
client reconciler.DeploymentMemberClient
49+
}
50+
51+
func (s *stateInspector) RefreshState(ctx context.Context, members api.DeploymentStatusMemberElements) {
52+
s.lock.Lock()
53+
defer s.lock.Unlock()
54+
55+
results := make([]State, len(members))
56+
57+
nctx, cancel := globals.GetGlobalTimeouts().ArangoDCheck().WithTimeout(ctx)
58+
defer cancel()
59+
60+
members.ForEach(func(id int) {
61+
c, err := s.client.GetServerClient(nctx, members[id].Group, members[id].Member.ID)
62+
if err != nil {
63+
results[id].Reachable = false
64+
return
65+
}
66+
67+
if _, err := c.Version(nctx); err != nil {
68+
results[id].Reachable = false
69+
return
70+
}
71+
72+
results[id].Reachable = true
73+
})
74+
75+
current := map[string]State{}
76+
77+
for id := range members {
78+
current[members[id].Member.ID] = results[id]
79+
}
80+
81+
s.members = current
82+
}
83+
84+
func (s *stateInspector) MemberState(id string) (State, bool) {
85+
s.lock.Lock()
86+
defer s.lock.Unlock()
87+
88+
if s.members == nil {
89+
return State{}, false
90+
}
91+
92+
v, ok := s.members[id]
93+
94+
return v, ok
95+
}
96+
97+
type State struct {
98+
Reachable bool
99+
}

0 commit comments

Comments
 (0)