Skip to content

Commit 4254057

Browse files
authored
[Feature] Topology Support (#804)
1 parent b60b48e commit 4254057

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1741
-129
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
- Add "Short Names" feature
66
- Switch ArangoDB Image Discovery process from Headless Service to Pod IP
77
- Fix PVC Resize for Single servers
8+
- Add Topology support
89

910
## [1.2.3](https://github.com/arangodb/kube-arangodb/tree/1.2.3) (2021-09-24)
1011
- Update UBI Image to 8.4

go.mod

+3-3
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ require (
2929
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.2.1+incompatible
32-
github.com/coreos/go-semver v0.3.0
32+
github.com/coreos/go-semver v0.3.0 // indirect
3333
github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9
3434
github.com/evanphx/json-patch v4.9.0+incompatible
3535
github.com/ghodss/yaml v1.0.0
@@ -43,7 +43,7 @@ require (
4343
github.com/jessevdk/go-assets v0.0.0-20160921144138-4f4301a06e15
4444
github.com/jessevdk/go-assets-builder v0.0.0-20130903091706-b8483521738f // indirect
4545
github.com/jessevdk/go-flags v1.4.0 // indirect
46-
github.com/json-iterator/go v1.1.11
46+
github.com/json-iterator/go v1.1.11 // indirect
4747
github.com/julienschmidt/httprouter v1.3.0
4848
github.com/kevinburke/rest v0.0.0-20210222204520-f7a2e216372f // indirect
4949
github.com/magiconair/properties v1.8.0
@@ -62,7 +62,7 @@ require (
6262
github.com/ugorji/go/codec v1.2.6 // indirect
6363
github.com/voxelbrain/goptions v0.0.0-20180630082107-58cddc247ea2 // indirect
6464
github.com/zenazn/goji v0.9.0 // indirect
65-
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4
65+
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect
6666
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c
6767
golang.org/x/tools v0.1.1-0.20210504181558-0bb7e5c47b1a // indirect
6868
google.golang.org/protobuf v1.27.1 // indirect

pkg/apis/deployment/v1/conditions.go

+2
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ const (
8383
ConditionTypeUpdating ConditionType = "Updating"
8484
// ConditionTypeUpdateFailed indicates that runtime update failed
8585
ConditionTypeUpdateFailed ConditionType = "UpdateFailed"
86+
// ConditionTypeTopologyAware indicates that the member is deployed with TopologyAwareness.
87+
ConditionTypeTopologyAware ConditionType = "TopologyAware"
8688
)
8789

8890
// Condition represents one current condition of a deployment or deployment member.

pkg/apis/deployment/v1/deployment_spec.go

+3
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ type DeploymentSpec struct {
163163

164164
// CommunicationMethod define communication method used in deployment
165165
CommunicationMethod *DeploymentCommunicationMethod `json:"communicationMethod,omitempty"`
166+
167+
// Topology define topology adjustment details, Enterprise only
168+
Topology *TopologySpec `json:"topology,omitempty"`
166169
}
167170

168171
// GetAllowMemberRecreation returns member recreation policy based on group and settings

pkg/apis/deployment/v1/deployment_status.go

+2
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ type DeploymentStatus struct {
8181

8282
// Agency keeps information about agency
8383
Agency *DeploymentStatusAgencyInfo `json:"agency,omitempty"`
84+
85+
Topology *TopologyStatus `json:"topology,omitempty"`
8486
}
8587

8688
// Equal checks for equality

pkg/apis/deployment/v1/list.go

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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+
21+
package v1
22+
23+
import "sort"
24+
25+
type List []string
26+
27+
func (l List) Contains(v string) bool {
28+
for _, z := range l {
29+
if z == v {
30+
return true
31+
}
32+
}
33+
34+
return false
35+
}
36+
37+
func (l List) Sort() {
38+
sort.Strings(l)
39+
}
40+
41+
func (l List) Remove(values ...string) List {
42+
var m List
43+
44+
toRemove := List(values)
45+
46+
for _, v := range l {
47+
if toRemove.Contains(v) {
48+
continue
49+
}
50+
51+
m = append(m, v)
52+
}
53+
54+
return m
55+
}

pkg/apis/deployment/v1/member_status.go

+6
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ type MemberStatus struct {
4141
// ID holds the unique ID of the member.
4242
// This id is also used within the ArangoDB cluster to identify this server.
4343
ID string `json:"id"`
44+
// UID holds the unique UID of the member.
45+
// UID is created once member run in AddMember action.
46+
UID types.UID `json:"uid,omitempty"`
4447
// RID holds the ID of the member run.
4548
// Value is updated in Pending Phase.
4649
RID types.UID `json:"rid,omitempty"`
@@ -80,11 +83,14 @@ type MemberStatus struct {
8083
Upgrade bool `json:"upgrade,omitempty"`
8184
// Endpoint definition how member should be reachable
8285
Endpoint *string `json:"endpoint,omitempty"`
86+
// Topology define topology member status assignment
87+
Topology *TopologyMemberStatus `json:"topology,omitempty"`
8388
}
8489

8590
// Equal checks for equality
8691
func (s MemberStatus) Equal(other MemberStatus) bool {
8792
return s.ID == other.ID &&
93+
s.UID == other.UID &&
8894
s.RID == other.RID &&
8995
s.Phase == other.Phase &&
9096
util.TimeCompareEqual(s.CreatedAt, other.CreatedAt) &&

pkg/apis/deployment/v1/member_status_list.go

+17-1
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,12 @@ func (l *MemberStatusList) removeByID(id string) error {
138138
return errors.WithStack(errors.Wrapf(NotFoundError, "Member '%s' is not a member", id))
139139
}
140140

141+
type MemberToRemoveSelector func(m MemberStatusList) (string, error)
142+
141143
// SelectMemberToRemove selects a member from the given list that should
142144
// be removed in a scale down action.
143145
// Returns an error if the list is empty.
144-
func (l MemberStatusList) SelectMemberToRemove() (MemberStatus, error) {
146+
func (l MemberStatusList) SelectMemberToRemove(selectors ...MemberToRemoveSelector) (MemberStatus, error) {
145147
if len(l) > 0 {
146148
// Try to find member with phase to be removed
147149
for _, m := range l {
@@ -165,6 +167,20 @@ func (l MemberStatusList) SelectMemberToRemove() (MemberStatus, error) {
165167
return m, nil
166168
}
167169
}
170+
171+
// Run conditional picker
172+
for _, selector := range selectors {
173+
if m, err := selector(l); err != nil {
174+
return MemberStatus{}, err
175+
} else if m != "" {
176+
if member, ok := l.ElementByID(m); ok {
177+
return member, nil
178+
} else {
179+
return MemberStatus{}, errors.Newf("Unable to find member with id %s", m)
180+
}
181+
}
182+
}
183+
168184
// Pick a random member that is in created state
169185
perm := rand.Perm(len(l))
170186
for _, idx := range perm {

pkg/apis/deployment/v1/plan.go

+47
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,11 @@ const (
171171
ActionTypeRuntimeContainerImageUpdate ActionType = "RuntimeContainerImageUpdate"
172172
// ActionTypeRuntimeContainerArgsLogLevelUpdate updates the container's executor arguments.
173173
ActionTypeRuntimeContainerArgsLogLevelUpdate ActionType = "RuntimeContainerArgsLogLevelUpdate"
174+
175+
// Topology
176+
ActionTypeTopologyEnable ActionType = "TopologyEnable"
177+
ActionTypeTopologyDisable ActionType = "TopologyDisable"
178+
ActionTypeTopologyMemberAssignment ActionType = "TopologyMemberAssignment"
174179
)
175180

176181
const (
@@ -346,3 +351,45 @@ func (p Plan) Wrap(before, after Action) Plan {
346351

347352
return n
348353
}
354+
355+
// AfterFirst adds actions when condition will return false
356+
func (p Plan) AfterFirst(condition func(a Action) bool, actions ...Action) Plan {
357+
var r Plan
358+
c := p
359+
for {
360+
if len(c) == 0 {
361+
break
362+
}
363+
364+
if !condition(c[0]) {
365+
r = append(r, actions...)
366+
367+
r = append(r, c...)
368+
369+
break
370+
}
371+
372+
r = append(r, c[0])
373+
374+
if len(c) == 1 {
375+
break
376+
}
377+
378+
c = c[1:]
379+
}
380+
381+
return r
382+
}
383+
384+
// Filter filter list of the actions
385+
func (p Plan) Filter(condition func(a Action) bool) Plan {
386+
var r Plan
387+
388+
for _, a := range p {
389+
if condition(a) {
390+
r = append(r, a)
391+
}
392+
}
393+
394+
return r
395+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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+
21+
package v1
22+
23+
import "k8s.io/apimachinery/pkg/types"
24+
25+
type TopologyMemberStatus struct {
26+
ID types.UID `json:"id"`
27+
Zone int `json:"rack"`
28+
}
+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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+
21+
package v1
22+
23+
const DefaultTopologySpecLabel = "topology.kubernetes.io/zone"
24+
25+
type TopologySpec struct {
26+
Enabled bool `json:"enabled,omitempty"`
27+
Zones int `json:"zones,omitempty"`
28+
Label *string `json:"label,omitempty"`
29+
}
30+
31+
func (t *TopologySpec) IsEnabled() bool {
32+
if t == nil {
33+
return false
34+
}
35+
36+
return t.Enabled && t.Zones > 0
37+
}
38+
39+
func (t *TopologySpec) GetZones() int {
40+
if t == nil {
41+
return 0
42+
}
43+
44+
return t.Zones
45+
}
46+
47+
func (t *TopologySpec) GetLabel() string {
48+
if t == nil || t.Label == nil {
49+
return DefaultTopologySpecLabel
50+
}
51+
52+
return *t.Label
53+
}

0 commit comments

Comments
 (0)