Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions changelog/17.0/17.0.0/summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- **[Breaking Changes](#breaking-changes)**
- [Dedicated stats for VTGate Prepare operations](#dedicated-vtgate-prepare-stats)
- [Keyspace name validation in TopoServer](#keyspace-name-validation)
- [Shard name validation in TopoServer](#shard-name-validation)
- **[New command line flags and behavior](#new-flag)**
- [Builtin backup: read buffering flags](#builtin-backup-read-buffering-flags)
- **[New stats](#new-stats)**
Expand Down Expand Up @@ -58,6 +59,12 @@ Prior to v17, it was possible to create a keyspace with invalid characters, whic

Keyspace names may no longer contain the forward slash ("/") character, and TopoServer's `GetKeyspace` and `CreateKeyspace` methods return an error if given such a name.

#### <a id="shard-name-validation"> Shard name validation in TopoServer

Prior to v17, it was possible to create a shard name with invalid characters, which would then be inaccessible to various cluster management operations.

Shard names may no longer contain the forward slash ("/") character, and TopoServer's `CreateShard` method returns an error if given such a name.

### <a id="new-flag"/> New command line flags and behavior

#### <a id="builtin-backup-read-buffering-flags" /> Backup --builtinbackup-file-read-buffer-size and --builtinbackup-file-write-buffer-size
Expand Down
4 changes: 4 additions & 0 deletions go/vt/topo/shard.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ func IsShardUsingRangeBasedSharding(shard string) bool {
// ValidateShardName takes a shard name and sanitizes it, and also returns
// the KeyRange.
func ValidateShardName(shard string) (string, *topodatapb.KeyRange, error) {
if strings.Contains(shard, "/") {
return "", nil, vterrors.Errorf(vtrpc.Code_INVALID_ARGUMENT, "invalid shardId, may not contain '/': %v", shard)
}

if !IsShardUsingRangeBasedSharding(shard) {
return shard, nil, nil
}
Expand Down
60 changes: 58 additions & 2 deletions go/vt/topo/shard_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ limitations under the License.
package topo

import (
"context"
"reflect"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"context"

"vitess.io/vitess/go/test/utils"
topodatapb "vitess.io/vitess/go/vt/proto/topodata"
)

Expand Down Expand Up @@ -222,3 +223,58 @@ func TestUpdateSourceDeniedTables(t *testing.T) {
t.Fatalf("one cell removal from all failed: %v", si)
}
}

func TestValidateShardName(t *testing.T) {
t.Parallel()

cases := []struct {
name string
expectedRange *topodatapb.KeyRange
valid bool
}{
{
name: "0",
valid: true,
},
{
name: "-80",
expectedRange: &topodatapb.KeyRange{
Start: nil,
End: []byte{0x80},
},
valid: true,
},
{
name: "40-80",
expectedRange: &topodatapb.KeyRange{
Start: []byte{0x40},
End: []byte{0x80},
},
valid: true,
},
{
name: "foo-bar",
valid: false,
},
{
name: "a/b",
valid: false,
},
}

for _, tcase := range cases {
tcase := tcase
t.Run(tcase.name, func(t *testing.T) {
t.Parallel()

_, kr, err := ValidateShardName(tcase.name)
if !tcase.valid {
assert.Error(t, err, "expected %q to be an invalid shard name", tcase.name)
return
}

require.NoError(t, err, "expected %q to be a valid shard name, got error: %v", tcase.name, err)
utils.MustMatch(t, tcase.expectedRange, kr)
})
}
}