Skip to content
This repository has been archived by the owner on Dec 16, 2022. It is now read-only.

[vtctld do not merge] Custom build for vtctld development (cherry-picks on top of 9.0) #211

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
31bca6c
Merge pull request #7302 from tinyspeck/am_vtctld_cell_getters
rohit-nayak-ps Jan 15, 2021
2c2c777
Merge pull request #7311 from tinyspeck/am_vtctld_tablet_getters
rohit-nayak-ps Jan 18, 2021
403c0f4
Merge pull request #7321 from tinyspeck/am_vtctldclient_command_pkg
deepthi Jan 20, 2021
5cf1e89
Merge pull request #7334 from tinyspeck/am_vtctld_getsrvvschema
rohit-nayak-ps Jan 21, 2021
6f8384c
Merge pull request #7346 from tinyspeck/am_vtctld_getschema
rohit-nayak-ps Jan 22, 2021
0ac37bf
Merge pull request #7352 from tinyspeck/am_vtctld_listbackups
rohit-nayak-ps Jan 23, 2021
04eb72e
Merge pull request #7360 from tinyspeck/am_vtctld_getvschema
rohit-nayak-ps Jan 24, 2021
e082766
Merge pull request #7395 from tinyspeck/am_vtctld_manage_topo
rohit-nayak-ps Feb 4, 2021
e99a9ab
Merge pull request #7404 from tinyspeck/am_vtctldclient_silence_errors
deepthi Feb 2, 2021
7c11532
Merge pull request #7518 from tinyspeck/am_testtmclient_refactor
deepthi Feb 22, 2021
31d5ee1
Merge pull request #7451 from tinyspeck/am_vtctldclient_errors
rohit-nayak-ps Feb 5, 2021
71b359e
Merge pull request #7575 from tinyspeck/am_vtctld_workflows
rohit-nayak-ps Mar 4, 2021
dbf1b6c
Merge pull request #7680 from tinyspeck/am_vtctld_srvkeyspace
deepthi Mar 15, 2021
feeed80
Merge pull request #7690 from tinyspeck/am_vtctld_shard_replication_p…
deepthi Mar 18, 2021
c7449dd
Merge pull request #7715 from tinyspeck/am_listtablets_timeouts
deepthi Mar 22, 2021
bb95d60
Merge branch 'release-9.0' into am_slack-9-vtctld-wip.rc6
rafael May 18, 2021
5072051
Added ReshardWorkflow vschema validation
makinje16 Apr 28, 2021
4d3e1a5
added ValidateVSchema and ValidateVSchemaKeyspace
makinje16 Apr 30, 2021
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
73 changes: 73 additions & 0 deletions go/cmd/vtctldclient/cli/awk.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
Copyright 2021 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cli

import (
"fmt"
"sort"
"strings"
"time"

"vitess.io/vitess/go/vt/logutil"
"vitess.io/vitess/go/vt/topo"
"vitess.io/vitess/go/vt/topo/topoproto"

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

// MarshalMapAWK returns a string representation of a string->string map in an
// AWK-friendly format.
func MarshalMapAWK(m map[string]string) string {
pairs := make([]string, len(m))
i := 0

for k, v := range m {
pairs[i] = fmt.Sprintf("%v: %q", k, v)

i++
}

sort.Strings(pairs)

return "[" + strings.Join(pairs, " ") + "]"
}

// MarshalTabletAWK marshals a tablet into an AWK-friendly line.
func MarshalTabletAWK(t *topodatapb.Tablet) string {
ti := topo.TabletInfo{
Tablet: t,
}

keyspace := t.Keyspace
if keyspace == "" {
keyspace = "<null>"
}

shard := t.Shard
if shard == "" {
shard = "<null>"
}

mtst := "<null>"
// special case for old primary that hasn't been updated in the topo
// yet.
if t.MasterTermStartTime != nil && t.MasterTermStartTime.Seconds > 0 {
mtst = logutil.ProtoToTime(t.MasterTermStartTime).Format(time.RFC3339)
}

return fmt.Sprintf("%v %v %v %v %v %v %v %v", topoproto.TabletAliasString(t.Alias), keyspace, shard, topoproto.TabletTypeLString(t.Type), ti.Addr(), ti.MysqlAddr(), MarshalMapAWK(t.Tags), mtst)
}
32 changes: 32 additions & 0 deletions go/cmd/vtctldclient/cli/cobra.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
Copyright 2021 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cli

import "github.com/spf13/cobra"

// FinishedParsing transitions a cobra.Command from treating RunE errors as
// usage errors to treating them just as normal runtime errors that should be
// propagated up to the root command's Execute method without also printing the
// subcommand's usage text on stderr. A subcommand should call this function
// from its RunE function when it has finished processing its flags and is
// moving into the pure "business logic" of its entrypoint.
//
// Package vitess.io/vitess/go/cmd/vtctldclient/internal/command has more
// details on why this exists.
func FinishedParsing(cmd *cobra.Command) {
cmd.SilenceUsage = true
}
61 changes: 61 additions & 0 deletions go/cmd/vtctldclient/cli/json.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
Copyright 2021 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cli

import (
"bytes"
"encoding/json"
"fmt"

"github.com/golang/protobuf/jsonpb"
"github.com/golang/protobuf/proto"
)

// MarshalJSON marshals obj to a JSON string. It uses the jsonpb marshaler for
// proto.Message types, with some sensible defaults, and falls back to the
// standard Go marshaler otherwise. In both cases, the marshaled JSON is
// indented with two spaces for readability.
//
// Unfortunately jsonpb only works for types that implement proto.Message,
// either by being a proto message type or by anonymously embedding one, so for
// other types that may have nested struct fields, we still use the standard Go
// marshaler, which will result in different formattings.
func MarshalJSON(obj interface{}) ([]byte, error) {
switch obj := obj.(type) {
case proto.Message:
b := bytes.NewBuffer(nil)
m := jsonpb.Marshaler{
EnumsAsInts: false,
EmitDefaults: true,
Indent: " ",
OrigName: true,
}

if err := m.Marshal(b, obj); err != nil {
return nil, fmt.Errorf("jsonpb.Marshal = %v", err)
}

return b.Bytes(), nil
default:
data, err := json.MarshalIndent(obj, "", " ")
if err != nil {
return nil, fmt.Errorf("json.Marshal = %v", err)
}

return data, nil
}
}
93 changes: 93 additions & 0 deletions go/cmd/vtctldclient/cli/pflag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
Copyright 2021 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cli

import (
"github.com/spf13/pflag"

"vitess.io/vitess/go/flagutil"
"vitess.io/vitess/go/vt/key"
"vitess.io/vitess/go/vt/topo/topoproto"

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

// StringMapValue augments flagutil.StringMapValue so it can be used as a
// pflag.Value.
type StringMapValue struct {
flagutil.StringMapValue
}

// Type is part of the pflag.Value interface.
func (v *StringMapValue) Type() string {
return "cli.StringMapValue"
}

// KeyspaceIDTypeFlag adds the pflag.Value interface to a
// topodatapb.KeyspaceIdType.
type KeyspaceIDTypeFlag topodatapb.KeyspaceIdType

var _ pflag.Value = (*KeyspaceIDTypeFlag)(nil)

// Set is part of the pflag.Value interface.
func (v *KeyspaceIDTypeFlag) Set(arg string) error {
t, err := key.ParseKeyspaceIDType(arg)
if err != nil {
return err
}

*v = KeyspaceIDTypeFlag(t)

return nil
}

// String is part of the pflag.Value interface.
func (v *KeyspaceIDTypeFlag) String() string {
return key.KeyspaceIDTypeString(topodatapb.KeyspaceIdType(*v))
}

// Type is part of the pflag.Value interface.
func (v *KeyspaceIDTypeFlag) Type() string {
return "cli.KeyspaceIdTypeFlag"
}

// KeyspaceTypeFlag adds the pflag.Value interface to a topodatapb.KeyspaceType.
type KeyspaceTypeFlag topodatapb.KeyspaceType

var _ pflag.Value = (*KeyspaceTypeFlag)(nil)

// Set is part of the pflag.Value interface.
func (v *KeyspaceTypeFlag) Set(arg string) error {
kt, err := topoproto.ParseKeyspaceType(arg)
if err != nil {
return err
}

*v = KeyspaceTypeFlag(kt)

return nil
}

// String is part of the pflag.Value interface.
func (v *KeyspaceTypeFlag) String() string {
return topoproto.KeyspaceTypeString(topodatapb.KeyspaceType(*v))
}

// Type is part of the pflag.Value interface.
func (v *KeyspaceTypeFlag) Type() string {
return "cli.KeyspaceTypeFlag"
}
123 changes: 123 additions & 0 deletions go/cmd/vtctldclient/cli/shards.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
Copyright 2021 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cli

import (
"sort"

"vitess.io/vitess/go/mysql"
"vitess.io/vitess/go/vt/topo/topoproto"

replicationdatapb "vitess.io/vitess/go/vt/proto/replicationdata"
topodatapb "vitess.io/vitess/go/vt/proto/topodata"
vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata"
)

// ParseKeyspaceShards takes a list of positional arguments and converts them to
// vtctldatapb.Shard objects.
func ParseKeyspaceShards(args []string) ([]*vtctldatapb.Shard, error) {
shards := make([]*vtctldatapb.Shard, 0, len(args))

for _, arg := range args {
keyspace, shard, err := topoproto.ParseKeyspaceShard(arg)
if err != nil {
return nil, err
}

shards = append(shards, &vtctldatapb.Shard{
Keyspace: keyspace,
Name: shard,
})
}

return shards, nil
}

// ReplicatingTablet is a struct to group a Tablet together with its replication
// Status.
type ReplicatingTablet struct {
*replicationdatapb.Status
*topodatapb.Tablet
}

type rTablets []*ReplicatingTablet

func (rts rTablets) Len() int { return len(rts) }
func (rts rTablets) Swap(i, j int) { rts[i], rts[j] = rts[j], rts[i] }
func (rts rTablets) Less(i, j int) bool {
l, r := rts[i], rts[j]

// l or r ReplicationStatus would be nil if we failed to get
// the position (put them at the beginning of the list)
if l.Status == nil {
return r.Status != nil
}

if r.Status == nil {
return false
}

// the type proto has MASTER first, so sort by that. Will show
// the MASTER first, then each replica type sorted by
// replication position.
if l.Tablet.Type < r.Tablet.Type {
return true
}

if l.Tablet.Type > r.Tablet.Type {
return false
}

// then compare replication positions
lpos, err := mysql.DecodePosition(l.Status.Position)
if err != nil {
return true
}

rpos, err := mysql.DecodePosition(r.Status.Position)
if err != nil {
return false
}

return !lpos.AtLeast(rpos)
}

// SortedReplicatingTablets returns a sorted list of replicating tablets (which
// is a struct grouping a Tablet together with its replication Status).
//
// The sorting order is:
// 1. Tablets that do not have a replication Status.
// 2. Any tablets of type MASTER.
// 3. Remaining tablets sorted by comparing replication positions.
func SortedReplicatingTablets(tabletMap map[string]*topodatapb.Tablet, replicationStatuses map[string]*replicationdatapb.Status) []*ReplicatingTablet {
rtablets := make([]*ReplicatingTablet, 0, len(tabletMap))

for alias, tablet := range tabletMap {
if status, ok := replicationStatuses[alias]; ok {
rtablets = append(rtablets, &ReplicatingTablet{
Status: status,
Tablet: tablet,
})
} else {
rtablets = append(rtablets, &ReplicatingTablet{Tablet: tablet})
}
}

sort.Sort(rTablets(rtablets))

return rtablets
}
Loading