-
Notifications
You must be signed in to change notification settings - Fork 453
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[coordinator] Validate placement on set placement endpoint unless force set #2922
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,6 +29,7 @@ import ( | |
"github.com/m3db/m3/src/cluster/shard" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestPlacement(t *testing.T) { | ||
|
@@ -139,7 +140,7 @@ func TestMismatchShards(t *testing.T) { | |
|
||
// mismatch shards | ||
p := NewPlacement().SetInstances([]Instance{i1, i2}).SetShards([]uint32{1, 2, 3}).SetReplicaFactor(1) | ||
assert.Error(t, Validate(p)) | ||
require.Error(t, Validate(p)) | ||
} | ||
|
||
func TestNonSharded(t *testing.T) { | ||
|
@@ -155,8 +156,8 @@ func TestNonSharded(t *testing.T) { | |
func TestValidateMirrorButNotSharded(t *testing.T) { | ||
p := NewPlacement().SetIsMirrored(true) | ||
err := Validate(p) | ||
assert.Error(t, err) | ||
assert.Equal(t, errMirrorNotSharded, err) | ||
require.Error(t, err) | ||
assert.Equal(t, errMirrorNotSharded.Error(), err.Error()) | ||
} | ||
|
||
func TestValidateMissingShard(t *testing.T) { | ||
|
@@ -170,7 +171,7 @@ func TestValidateMissingShard(t *testing.T) { | |
ids := []uint32{1, 2} | ||
p := NewPlacement().SetInstances([]Instance{i1, i2}).SetShards(ids).SetReplicaFactor(2).SetIsSharded(true) | ||
err := Validate(p) | ||
assert.Error(t, err) | ||
require.Error(t, err) | ||
assert.Equal(t, "invalid placement, the total available shards in the placement is 3, expecting 4", err.Error()) | ||
} | ||
|
||
|
@@ -189,8 +190,9 @@ func TestValidateUnexpectedShard(t *testing.T) { | |
SetReplicaFactor(2). | ||
SetIsSharded(true) | ||
|
||
assert.Error(t, Validate(p)) | ||
assert.Equal(t, errUnexpectedShards, Validate(p)) | ||
err := Validate(p) | ||
require.Error(t, err) | ||
assert.Equal(t, errUnexpectedShards.Error(), err.Error()) | ||
} | ||
|
||
func TestValidateDuplicatedShards(t *testing.T) { | ||
|
@@ -208,8 +210,9 @@ func TestValidateDuplicatedShards(t *testing.T) { | |
SetInstances([]Instance{i1, i2}). | ||
SetShards([]uint32{2, 3, 4, 4, 5, 6}). | ||
SetReplicaFactor(1) | ||
assert.Error(t, Validate(p)) | ||
assert.Equal(t, errDuplicatedShards, Validate(p)) | ||
err := Validate(p) | ||
require.Error(t, err) | ||
assert.Equal(t, errDuplicatedShards.Error(), err.Error()) | ||
} | ||
|
||
func TestValidateWrongReplicaForSomeShards(t *testing.T) { | ||
|
@@ -276,6 +279,87 @@ func TestValidateLeavingNotMatchInitializingWithSourceID(t *testing.T) { | |
assert.Equal(t, err.Error(), "invalid placement, 2 shards in Leaving state, not equal 1 in Initializing state with source id") | ||
} | ||
|
||
func TestValidateLeavingAndInitializingWithSourceIDMissing(t *testing.T) { | ||
i1 := NewEmptyInstance("i1", "r1", "z1", "endpoint", 1) | ||
i1.Shards().Add(shard.NewShard(1).SetState(shard.Leaving)) | ||
i1.Shards().Add(shard.NewShard(2).SetState(shard.Leaving)) | ||
i1.Shards().Add(shard.NewShard(3).SetState(shard.Available)) | ||
|
||
i2 := NewEmptyInstance("i2", "r2", "z1", "endpoint", 1) | ||
i2.Shards().Add(shard.NewShard(1).SetState(shard.Initializing).SetSourceID("unknown")) | ||
i2.Shards().Add(shard.NewShard(2).SetState(shard.Initializing).SetSourceID("i1")) | ||
|
||
p := NewPlacement(). | ||
SetInstances([]Instance{i1, i2}). | ||
SetShards([]uint32{1, 2, 3}). | ||
SetReplicaFactor(1). | ||
SetIsSharded(true) | ||
err := Validate(p) | ||
require.Error(t, err) | ||
assert.Equal(t, err.Error(), "instance i2 has initializing shard 1 with source ID unknown but no such instance in placement") | ||
} | ||
|
||
func TestValidateLeavingAndInitializingWithSourceIDNoSuchShard(t *testing.T) { | ||
i1 := NewEmptyInstance("i1", "r1", "z1", "endpoint", 1) | ||
i1.Shards().Add(shard.NewShard(1).SetState(shard.Available)) | ||
i1.Shards().Add(shard.NewShard(2).SetState(shard.Leaving)) | ||
|
||
i2 := NewEmptyInstance("i2", "r2", "z1", "endpoint", 1) | ||
i2.Shards().Add(shard.NewShard(2).SetState(shard.Initializing).SetSourceID("i1")) | ||
i2.Shards().Add(shard.NewShard(3).SetState(shard.Initializing).SetSourceID("i1")) | ||
|
||
p := NewPlacement(). | ||
SetInstances([]Instance{i1, i2}). | ||
SetShards([]uint32{1, 2, 3}). | ||
SetReplicaFactor(1). | ||
SetIsSharded(true) | ||
err := Validate(p) | ||
require.Error(t, err) | ||
assert.Equal(t, err.Error(), "instance i2 has initializing shard 3 with source ID i1 but leaving instance has no such shard") | ||
} | ||
|
||
func TestValidateLeavingAndInitializingWithSourceIDShardNotLeaving(t *testing.T) { | ||
i1 := NewEmptyInstance("i1", "r1", "z1", "endpoint", 1) | ||
i1.Shards().Add(shard.NewShard(1).SetState(shard.Available)) | ||
i1.Shards().Add(shard.NewShard(2).SetState(shard.Leaving)) | ||
i1.Shards().Add(shard.NewShard(3).SetState(shard.Available)) | ||
|
||
i2 := NewEmptyInstance("i2", "r2", "z1", "endpoint", 1) | ||
i2.Shards().Add(shard.NewShard(1).SetState(shard.Initializing).SetSourceID("i1")) | ||
i2.Shards().Add(shard.NewShard(2).SetState(shard.Initializing).SetSourceID("i1")) | ||
|
||
p := NewPlacement(). | ||
SetInstances([]Instance{i1, i2}). | ||
SetShards([]uint32{1, 2, 3}). | ||
SetReplicaFactor(1). | ||
SetIsSharded(true) | ||
err := Validate(p) | ||
require.Error(t, err) | ||
assert.Equal(t, err.Error(), "instance i2 has initializing shard 1 with source ID i1 but leaving instance has shard with state Available") | ||
} | ||
|
||
func TestValidateLeavingAndInitializingWithSourceIDDoubleMatched(t *testing.T) { | ||
i1 := NewEmptyInstance("i1", "r1", "z1", "endpoint", 1) | ||
i1.Shards().Add(shard.NewShard(1).SetState(shard.Available)) | ||
i1.Shards().Add(shard.NewShard(2).SetState(shard.Leaving)) | ||
i1.Shards().Add(shard.NewShard(3).SetState(shard.Available)) | ||
|
||
i2 := NewEmptyInstance("i2", "r2", "z1", "endpoint", 1) | ||
i2.Shards().Add(shard.NewShard(2).SetState(shard.Initializing).SetSourceID("i1")) | ||
|
||
i3 := NewEmptyInstance("i3", "r2", "z1", "endpoint", 1) | ||
Comment on lines
+342
to
+350
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: repeated code may tick off the linter unfortunately, can we just add stuff to the placement options and attempt validation in one function? Validates 1 test per function/path, but probably easier to maintain and see what's going on |
||
i3.Shards().Add(shard.NewShard(2).SetState(shard.Initializing).SetSourceID("i1")) | ||
|
||
p := NewPlacement(). | ||
SetInstances([]Instance{i1, i2, i3}). | ||
SetShards([]uint32{1, 2, 3}). | ||
SetReplicaFactor(1). | ||
SetIsSharded(true) | ||
err := Validate(p) | ||
require.Error(t, err) | ||
assert.Equal(t, err.Error(), "instance i3 has initializing shard 2 with source ID i1 but leaving instance has shard already matched by i2") | ||
} | ||
|
||
func TestValidateNoEndpoint(t *testing.T) { | ||
i1 := NewEmptyInstance("i1", "r1", "z1", "", 1) | ||
i1.Shards().Add(shard.NewShard(1).SetState(shard.Available)) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit; never uses the string value, maybe this should be a
make(map[string]map[uint32]struct{})
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah believe we do to print out the error of which host previously had claimed that leaving shard to match it's own initializing shard: