Skip to content

Commit 72e02e4

Browse files
author
Lars Maier
authored
bug-fix/bad-remove-member (#345)
* Updated go-driver. * Introduced condition Terminating for a pod marked for deletion. * Remove Terminating when pod is recreated. * Removed dead code. * Wait for shards to be in sync. Rotate members on upgrade when possible. * Updated changelog.
1 parent 782503c commit 72e02e4

21 files changed

+662
-43
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
## [0.3.8](https://github.com/arangodb/kube-arangodb/tree/0.3.8) (2019-02-19)
44
[Full Changelog](https://github.com/arangodb/kube-arangodb/compare/0.3.6...0.3.7)
55

6+
- Wait for shards to be in sync before continuing upgrade process.
7+
- Rotate members when patch-level upgrade.
8+
- Don't trigger cleanout server during upgrade.
9+
- More robust remove-server actions.
10+
11+
## [0.3.8](https://github.com/arangodb/kube-arangodb/tree/0.3.8) (2019-02-19)
12+
[Full Changelog](https://github.com/arangodb/kube-arangodb/compare/0.3.6...0.3.7)
13+
614
- Added scaling limits to spec and enforce in operator.
715
- npm update for dashboard to alleviate security problems.
816
- Added bare metal walk through to documentation.

deps/github.com/arangodb/go-driver/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ __test_go_test:
325325
-e TEST_CVERSION=$(TEST_CVERSION) \
326326
-e TEST_CONTENT_TYPE=$(TEST_CONTENT_TYPE) \
327327
-e TEST_PPROF=$(TEST_PPROF) \
328+
-e TEST_MODE=$(TEST_MODE) \
328329
-w /usr/code/ \
329330
golang:$(GOVERSION) \
330331
go test $(TAGS) $(TESTOPTIONS) $(TESTVERBOSEOPTIONS) $(TESTS)
@@ -337,7 +338,7 @@ ifdef JWTSECRET
337338
echo "$JWTSECRET" > "${JWTSECRETFILE}"
338339
endif
339340
@-docker rm -f -v $(TESTCONTAINER) &> /dev/null
340-
@TESTCONTAINER=$(TESTCONTAINER) ARANGODB=$(ARANGODB) STARTER=$(STARTER) STARTERMODE=$(TEST_MODE) TMPDIR=${GOBUILDDIR} $(CLUSTERENV) $(ROOTDIR)/test/cluster.sh start
341+
@TESTCONTAINER=$(TESTCONTAINER) ARANGODB=$(ARANGODB) ARANGO_LICENSE_KEY=$(ARANGO_LICENSE_KEY) STARTER=$(STARTER) STARTERMODE=$(TEST_MODE) TMPDIR=${GOBUILDDIR} $(CLUSTERENV) $(ROOTDIR)/test/cluster.sh start
341342
endif
342343

343344
__test_cleanup:

deps/github.com/arangodb/go-driver/client.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ type VersionInfo struct {
100100
Details map[string]interface{} `json:"details,omitempty"`
101101
}
102102

103+
func (v *VersionInfo) IsEnterprise() bool {
104+
return v.License == "enterprise"
105+
}
106+
103107
// String creates a string representation of the given VersionInfo.
104108
func (v VersionInfo) String() string {
105109
result := fmt.Sprintf("%s, version %s, license %s", v.Server, v.Version, v.License)

deps/github.com/arangodb/go-driver/cluster.go

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,40 @@ type ClusterHealth struct {
6464
Health map[ServerID]ServerHealth `json:"Health"`
6565
}
6666

67+
// ServerSyncStatus describes the servers sync status
68+
type ServerSyncStatus string
69+
70+
const (
71+
ServerSyncStatusUnknown ServerSyncStatus = "UNKNOWN"
72+
ServerSyncStatusUndefined ServerSyncStatus = "UNDEFINED"
73+
ServerSyncStatusStartup ServerSyncStatus = "STARTUP"
74+
ServerSyncStatusStopping ServerSyncStatus = "STOPPING"
75+
ServerSyncStatusStopped ServerSyncStatus = "STOPPED"
76+
ServerSyncStatusServing ServerSyncStatus = "SERVING"
77+
ServerSyncStatusShutdown ServerSyncStatus = "SHUTDOWN"
78+
)
79+
6780
// ServerHealth contains health information of a single server in a cluster.
6881
type ServerHealth struct {
69-
Endpoint string `json:"Endpoint"`
70-
LastHeartbeatAcked time.Time `json:"LastHeartbeatAcked"`
71-
LastHeartbeatSent time.Time `json:"LastHeartbeatSent"`
72-
LastHeartbeatStatus string `json:"LastHeartbeatStatus"`
73-
Role ServerRole `json:"Role"`
74-
ShortName string `json:"ShortName"`
75-
Status ServerStatus `json:"Status"`
76-
CanBeDeleted bool `json:"CanBeDeleted"`
77-
HostID string `json:"Host,omitempty"`
78-
Version Version `json:"Version,omitempty"`
79-
Engine EngineType `json:"Engine,omitempty"`
82+
Endpoint string `json:"Endpoint"`
83+
LastHeartbeatAcked time.Time `json:"LastHeartbeatAcked"`
84+
LastHeartbeatSent time.Time `json:"LastHeartbeatSent"`
85+
LastHeartbeatStatus string `json:"LastHeartbeatStatus"`
86+
Role ServerRole `json:"Role"`
87+
ShortName string `json:"ShortName"`
88+
Status ServerStatus `json:"Status"`
89+
CanBeDeleted bool `json:"CanBeDeleted"`
90+
HostID string `json:"Host,omitempty"`
91+
Version Version `json:"Version,omitempty"`
92+
Engine EngineType `json:"Engine,omitempty"`
93+
SyncStatus ServerSyncStatus `json:"SyncStatus,omitempty"`
94+
95+
// Only for Coordinators
96+
AdvertisedEndpoint *string `json:"AdvertisedEndpoint,omitempty"`
97+
98+
// Only for Agents
99+
Leader *string `json:"Leader,omitempty"`
100+
Leading *bool `json:"Leading,omitempty"`
80101
}
81102

82103
// ServerStatus describes the health status of a server
@@ -146,6 +167,7 @@ type InventoryCollection struct {
146167
Indexes []InventoryIndex `json:"indexes,omitempty"`
147168
PlanVersion int64 `json:"planVersion,omitempty"`
148169
IsReady bool `json:"isReady,omitempty"`
170+
AllInSync bool `json:"allInSync,omitempty"`
149171
}
150172

151173
// IndexByFieldsAndType returns the InventoryIndex with given fields & type.
@@ -189,6 +211,11 @@ type InventoryCollectionParameters struct {
189211
DistributeShardsLike string `json:"distributeShardsLike,omitempty"`
190212
}
191213

214+
// IsSatellite returns true if the collection is a satellite collection
215+
func (icp *InventoryCollectionParameters) IsSatellite() bool {
216+
return icp.ReplicationFactor == ReplicationFactorSatellite
217+
}
218+
192219
// ShardID is an internal identifier of a specific shard
193220
type ShardID string
194221

deps/github.com/arangodb/go-driver/cluster_impl.go

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ package driver
2424

2525
import (
2626
"context"
27+
"encoding/json"
2728
"path"
29+
"reflect"
2830
)
2931

3032
// newCluster creates a new Cluster implementation.
@@ -221,3 +223,151 @@ func (c *cluster) RemoveServer(ctx context.Context, serverID ServerID) error {
221223
}
222224
return nil
223225
}
226+
227+
// replicationFactor represents the replication factor of a collection
228+
// Has special value ReplicationFactorSatellite for satellite collections
229+
type replicationFactor int
230+
231+
type inventoryCollectionParametersInternal struct {
232+
Deleted bool `json:"deleted,omitempty"`
233+
DoCompact bool `json:"doCompact,omitempty"`
234+
ID string `json:"id,omitempty"`
235+
IndexBuckets int `json:"indexBuckets,omitempty"`
236+
Indexes []InventoryIndex `json:"indexes,omitempty"`
237+
IsSmart bool `json:"isSmart,omitempty"`
238+
SmartGraphAttribute string `json:"smartGraphAttribute,omitempty"`
239+
IsSystem bool `json:"isSystem,omitempty"`
240+
IsVolatile bool `json:"isVolatile,omitempty"`
241+
JournalSize int64 `json:"journalSize,omitempty"`
242+
KeyOptions struct {
243+
Type string `json:"type,omitempty"`
244+
AllowUserKeys bool `json:"allowUserKeys,omitempty"`
245+
LastValue int64 `json:"lastValue,omitempty"`
246+
} `json:"keyOptions"`
247+
Name string `json:"name,omitempty"`
248+
NumberOfShards int `json:"numberOfShards,omitempty"`
249+
Path string `json:"path,omitempty"`
250+
PlanID string `json:"planId,omitempty"`
251+
ReplicationFactor replicationFactor `json:"replicationFactor,omitempty"`
252+
ShardKeys []string `json:"shardKeys,omitempty"`
253+
Shards map[ShardID][]ServerID `json:"shards,omitempty"`
254+
Status CollectionStatus `json:"status,omitempty"`
255+
Type CollectionType `json:"type,omitempty"`
256+
WaitForSync bool `json:"waitForSync,omitempty"`
257+
DistributeShardsLike string `json:"distributeShardsLike,omitempty"`
258+
}
259+
260+
func (p *InventoryCollectionParameters) asInternal() inventoryCollectionParametersInternal {
261+
return inventoryCollectionParametersInternal{
262+
Deleted: p.Deleted,
263+
DoCompact: p.DoCompact,
264+
ID: p.ID,
265+
IndexBuckets: p.IndexBuckets,
266+
Indexes: p.Indexes,
267+
IsSmart: p.IsSmart,
268+
SmartGraphAttribute: p.SmartGraphAttribute,
269+
IsSystem: p.IsSystem,
270+
IsVolatile: p.IsVolatile,
271+
JournalSize: p.JournalSize,
272+
KeyOptions: p.KeyOptions,
273+
Name: p.Name,
274+
NumberOfShards: p.NumberOfShards,
275+
Path: p.Path,
276+
PlanID: p.PlanID,
277+
ReplicationFactor: replicationFactor(p.ReplicationFactor),
278+
ShardKeys: p.ShardKeys,
279+
Shards: p.Shards,
280+
Status: p.Status,
281+
Type: p.Type,
282+
WaitForSync: p.WaitForSync,
283+
DistributeShardsLike: p.DistributeShardsLike,
284+
}
285+
}
286+
287+
func (p *InventoryCollectionParameters) fromInternal(i inventoryCollectionParametersInternal) {
288+
*p = i.asExternal()
289+
}
290+
291+
func (p *inventoryCollectionParametersInternal) asExternal() InventoryCollectionParameters {
292+
return InventoryCollectionParameters{
293+
Deleted: p.Deleted,
294+
DoCompact: p.DoCompact,
295+
ID: p.ID,
296+
IndexBuckets: p.IndexBuckets,
297+
Indexes: p.Indexes,
298+
IsSmart: p.IsSmart,
299+
SmartGraphAttribute: p.SmartGraphAttribute,
300+
IsSystem: p.IsSystem,
301+
IsVolatile: p.IsVolatile,
302+
JournalSize: p.JournalSize,
303+
KeyOptions: p.KeyOptions,
304+
Name: p.Name,
305+
NumberOfShards: p.NumberOfShards,
306+
Path: p.Path,
307+
PlanID: p.PlanID,
308+
ReplicationFactor: int(p.ReplicationFactor),
309+
ShardKeys: p.ShardKeys,
310+
Shards: p.Shards,
311+
Status: p.Status,
312+
Type: p.Type,
313+
WaitForSync: p.WaitForSync,
314+
DistributeShardsLike: p.DistributeShardsLike,
315+
}
316+
}
317+
318+
// MarshalJSON converts InventoryCollectionParameters into json
319+
func (p *InventoryCollectionParameters) MarshalJSON() ([]byte, error) {
320+
return json.Marshal(p.asInternal())
321+
}
322+
323+
// UnmarshalJSON loads InventoryCollectionParameters from json
324+
func (p *InventoryCollectionParameters) UnmarshalJSON(d []byte) error {
325+
var internal inventoryCollectionParametersInternal
326+
if err := json.Unmarshal(d, &internal); err != nil {
327+
return err
328+
}
329+
330+
p.fromInternal(internal)
331+
return nil
332+
}
333+
334+
const (
335+
replicationFactorSatelliteString string = "satellite"
336+
)
337+
338+
// MarshalJSON marshals InventoryCollectionParameters to arangodb json representation
339+
func (r replicationFactor) MarshalJSON() ([]byte, error) {
340+
var replicationFactor interface{}
341+
342+
if int(r) == ReplicationFactorSatellite {
343+
replicationFactor = replicationFactorSatelliteString
344+
} else {
345+
replicationFactor = int(r)
346+
}
347+
348+
return json.Marshal(replicationFactor)
349+
}
350+
351+
// UnmarshalJSON marshals InventoryCollectionParameters to arangodb json representation
352+
func (r *replicationFactor) UnmarshalJSON(d []byte) error {
353+
var internal interface{}
354+
355+
if err := json.Unmarshal(d, &internal); err != nil {
356+
return err
357+
}
358+
359+
if i, ok := internal.(float64); ok {
360+
*r = replicationFactor(i)
361+
return nil
362+
} else if str, ok := internal.(string); ok {
363+
if ok && str == replicationFactorSatelliteString {
364+
*r = replicationFactor(ReplicationFactorSatellite)
365+
return nil
366+
}
367+
}
368+
369+
return &json.UnmarshalTypeError{
370+
Value: string(d),
371+
Type: reflect.TypeOf(r).Elem(),
372+
}
373+
}

deps/github.com/arangodb/go-driver/collection.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,16 @@ type CollectionProperties struct {
118118
ReplicationFactor int `json:"replicationFactor,omitempty"`
119119
}
120120

121+
const (
122+
// ReplicationFactorSatellite represents a satellite collection's replication factor
123+
ReplicationFactorSatellite int = -1
124+
)
125+
126+
// IsSatellite returns true if the collection is a satellite collection
127+
func (p *CollectionProperties) IsSatellite() bool {
128+
return p.ReplicationFactor == ReplicationFactorSatellite
129+
}
130+
121131
// SetCollectionPropertiesOptions contains data for Collection.SetProperties.
122132
type SetCollectionPropertiesOptions struct {
123133
// If true then creating or changing a document will wait until the data has been synchronized to disk.

0 commit comments

Comments
 (0)