diff --git a/go/cmd/vtctldclient/internal/command/workflows.go b/go/cmd/vtctldclient/internal/command/workflows.go new file mode 100644 index 00000000000..760139a9be9 --- /dev/null +++ b/go/cmd/vtctldclient/internal/command/workflows.go @@ -0,0 +1,69 @@ +/* +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 command + +import ( + "fmt" + + "github.com/spf13/cobra" + + "vitess.io/vitess/go/cmd/vtctldclient/cli" + + vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" +) + +var ( + // GetWorkflows makes a GetWorkflows gRPC call to a vtctld. + GetWorkflows = &cobra.Command{ + Use: "GetWorkflows ", + Args: cobra.ExactArgs(1), + RunE: commandGetWorkflows, + } +) + +var getWorkflowsOptions = struct { + ShowAll bool +}{} + +func commandGetWorkflows(cmd *cobra.Command, args []string) error { + cli.FinishedParsing(cmd) + + ks := cmd.Flags().Arg(0) + + resp, err := client.GetWorkflows(commandCtx, &vtctldatapb.GetWorkflowsRequest{ + Keyspace: ks, + ActiveOnly: !getWorkflowsOptions.ShowAll, + }) + + if err != nil { + return err + } + + data, err := cli.MarshalJSON(resp) + if err != nil { + return err + } + + fmt.Printf("%s\n", data) + + return nil +} + +func init() { + GetWorkflows.Flags().BoolVarP(&getWorkflowsOptions.ShowAll, "show-all", "a", false, "Show all workflows instead of just active workflows") + Root.AddCommand(GetWorkflows) +} diff --git a/go/vt/proto/vtctldata/vtctldata.pb.go b/go/vt/proto/vtctldata/vtctldata.pb.go index 67d02fa0a8e..298cb95633f 100644 --- a/go/vt/proto/vtctldata/vtctldata.pb.go +++ b/go/vt/proto/vtctldata/vtctldata.pb.go @@ -9,6 +9,7 @@ import ( proto "github.com/golang/protobuf/proto" + binlogdata "vitess.io/vitess/go/vt/proto/binlogdata" logutil "vitess.io/vitess/go/vt/proto/logutil" mysqlctl "vitess.io/vitess/go/vt/proto/mysqlctl" tabletmanagerdata "vitess.io/vitess/go/vt/proto/tabletmanagerdata" @@ -117,6 +118,617 @@ func (m *ExecuteVtctlCommandResponse) GetEvent() *logutil.Event { return nil } +// TableMaterializeSttings contains the settings for one table. +type TableMaterializeSettings struct { + TargetTable string `protobuf:"bytes,1,opt,name=target_table,json=targetTable,proto3" json:"target_table,omitempty"` + // source_expression is a select statement. + SourceExpression string `protobuf:"bytes,2,opt,name=source_expression,json=sourceExpression,proto3" json:"source_expression,omitempty"` + // create_ddl contains the DDL to create the target table. + // If empty, the target table must already exist. + // if "copy", the target table DDL is the same as the source table. + CreateDdl string `protobuf:"bytes,3,opt,name=create_ddl,json=createDdl,proto3" json:"create_ddl,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *TableMaterializeSettings) Reset() { *m = TableMaterializeSettings{} } +func (m *TableMaterializeSettings) String() string { return proto.CompactTextString(m) } +func (*TableMaterializeSettings) ProtoMessage() {} +func (*TableMaterializeSettings) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{2} +} + +func (m *TableMaterializeSettings) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_TableMaterializeSettings.Unmarshal(m, b) +} +func (m *TableMaterializeSettings) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_TableMaterializeSettings.Marshal(b, m, deterministic) +} +func (m *TableMaterializeSettings) XXX_Merge(src proto.Message) { + xxx_messageInfo_TableMaterializeSettings.Merge(m, src) +} +func (m *TableMaterializeSettings) XXX_Size() int { + return xxx_messageInfo_TableMaterializeSettings.Size(m) +} +func (m *TableMaterializeSettings) XXX_DiscardUnknown() { + xxx_messageInfo_TableMaterializeSettings.DiscardUnknown(m) +} + +var xxx_messageInfo_TableMaterializeSettings proto.InternalMessageInfo + +func (m *TableMaterializeSettings) GetTargetTable() string { + if m != nil { + return m.TargetTable + } + return "" +} + +func (m *TableMaterializeSettings) GetSourceExpression() string { + if m != nil { + return m.SourceExpression + } + return "" +} + +func (m *TableMaterializeSettings) GetCreateDdl() string { + if m != nil { + return m.CreateDdl + } + return "" +} + +// MaterializeSettings contains the settings for the Materialize command. +type MaterializeSettings struct { + // workflow is the name of the workflow. + Workflow string `protobuf:"bytes,1,opt,name=workflow,proto3" json:"workflow,omitempty"` + SourceKeyspace string `protobuf:"bytes,2,opt,name=source_keyspace,json=sourceKeyspace,proto3" json:"source_keyspace,omitempty"` + TargetKeyspace string `protobuf:"bytes,3,opt,name=target_keyspace,json=targetKeyspace,proto3" json:"target_keyspace,omitempty"` + // stop_after_copy specifies if vreplication should be stopped after copying. + StopAfterCopy bool `protobuf:"varint,4,opt,name=stop_after_copy,json=stopAfterCopy,proto3" json:"stop_after_copy,omitempty"` + TableSettings []*TableMaterializeSettings `protobuf:"bytes,5,rep,name=table_settings,json=tableSettings,proto3" json:"table_settings,omitempty"` + // optional parameters. + Cell string `protobuf:"bytes,6,opt,name=cell,proto3" json:"cell,omitempty"` + TabletTypes string `protobuf:"bytes,7,opt,name=tablet_types,json=tabletTypes,proto3" json:"tablet_types,omitempty"` + // ExternalCluster is the name of the mounted cluster which has the source keyspace/db for this workflow + // it is of the type + ExternalCluster string `protobuf:"bytes,8,opt,name=external_cluster,json=externalCluster,proto3" json:"external_cluster,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MaterializeSettings) Reset() { *m = MaterializeSettings{} } +func (m *MaterializeSettings) String() string { return proto.CompactTextString(m) } +func (*MaterializeSettings) ProtoMessage() {} +func (*MaterializeSettings) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{3} +} + +func (m *MaterializeSettings) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MaterializeSettings.Unmarshal(m, b) +} +func (m *MaterializeSettings) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MaterializeSettings.Marshal(b, m, deterministic) +} +func (m *MaterializeSettings) XXX_Merge(src proto.Message) { + xxx_messageInfo_MaterializeSettings.Merge(m, src) +} +func (m *MaterializeSettings) XXX_Size() int { + return xxx_messageInfo_MaterializeSettings.Size(m) +} +func (m *MaterializeSettings) XXX_DiscardUnknown() { + xxx_messageInfo_MaterializeSettings.DiscardUnknown(m) +} + +var xxx_messageInfo_MaterializeSettings proto.InternalMessageInfo + +func (m *MaterializeSettings) GetWorkflow() string { + if m != nil { + return m.Workflow + } + return "" +} + +func (m *MaterializeSettings) GetSourceKeyspace() string { + if m != nil { + return m.SourceKeyspace + } + return "" +} + +func (m *MaterializeSettings) GetTargetKeyspace() string { + if m != nil { + return m.TargetKeyspace + } + return "" +} + +func (m *MaterializeSettings) GetStopAfterCopy() bool { + if m != nil { + return m.StopAfterCopy + } + return false +} + +func (m *MaterializeSettings) GetTableSettings() []*TableMaterializeSettings { + if m != nil { + return m.TableSettings + } + return nil +} + +func (m *MaterializeSettings) GetCell() string { + if m != nil { + return m.Cell + } + return "" +} + +func (m *MaterializeSettings) GetTabletTypes() string { + if m != nil { + return m.TabletTypes + } + return "" +} + +func (m *MaterializeSettings) GetExternalCluster() string { + if m != nil { + return m.ExternalCluster + } + return "" +} + +type Keyspace struct { + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Keyspace *topodata.Keyspace `protobuf:"bytes,2,opt,name=keyspace,proto3" json:"keyspace,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Keyspace) Reset() { *m = Keyspace{} } +func (m *Keyspace) String() string { return proto.CompactTextString(m) } +func (*Keyspace) ProtoMessage() {} +func (*Keyspace) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{4} +} + +func (m *Keyspace) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Keyspace.Unmarshal(m, b) +} +func (m *Keyspace) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Keyspace.Marshal(b, m, deterministic) +} +func (m *Keyspace) XXX_Merge(src proto.Message) { + xxx_messageInfo_Keyspace.Merge(m, src) +} +func (m *Keyspace) XXX_Size() int { + return xxx_messageInfo_Keyspace.Size(m) +} +func (m *Keyspace) XXX_DiscardUnknown() { + xxx_messageInfo_Keyspace.DiscardUnknown(m) +} + +var xxx_messageInfo_Keyspace proto.InternalMessageInfo + +func (m *Keyspace) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *Keyspace) GetKeyspace() *topodata.Keyspace { + if m != nil { + return m.Keyspace + } + return nil +} + +type Shard struct { + Keyspace string `protobuf:"bytes,1,opt,name=keyspace,proto3" json:"keyspace,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Shard *topodata.Shard `protobuf:"bytes,3,opt,name=shard,proto3" json:"shard,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Shard) Reset() { *m = Shard{} } +func (m *Shard) String() string { return proto.CompactTextString(m) } +func (*Shard) ProtoMessage() {} +func (*Shard) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{5} +} + +func (m *Shard) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Shard.Unmarshal(m, b) +} +func (m *Shard) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Shard.Marshal(b, m, deterministic) +} +func (m *Shard) XXX_Merge(src proto.Message) { + xxx_messageInfo_Shard.Merge(m, src) +} +func (m *Shard) XXX_Size() int { + return xxx_messageInfo_Shard.Size(m) +} +func (m *Shard) XXX_DiscardUnknown() { + xxx_messageInfo_Shard.DiscardUnknown(m) +} + +var xxx_messageInfo_Shard proto.InternalMessageInfo + +func (m *Shard) GetKeyspace() string { + if m != nil { + return m.Keyspace + } + return "" +} + +func (m *Shard) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *Shard) GetShard() *topodata.Shard { + if m != nil { + return m.Shard + } + return nil +} + +// TODO: comment the hell out of this. +type Workflow struct { + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Source *Workflow_ReplicationLocation `protobuf:"bytes,2,opt,name=source,proto3" json:"source,omitempty"` + Target *Workflow_ReplicationLocation `protobuf:"bytes,3,opt,name=target,proto3" json:"target,omitempty"` + MaxVReplicationLag int64 `protobuf:"varint,4,opt,name=max_v_replication_lag,json=maxVReplicationLag,proto3" json:"max_v_replication_lag,omitempty"` + ShardStreams map[string]*Workflow_ShardStream `protobuf:"bytes,5,rep,name=shard_streams,json=shardStreams,proto3" json:"shard_streams,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Workflow) Reset() { *m = Workflow{} } +func (m *Workflow) String() string { return proto.CompactTextString(m) } +func (*Workflow) ProtoMessage() {} +func (*Workflow) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{6} +} + +func (m *Workflow) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Workflow.Unmarshal(m, b) +} +func (m *Workflow) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Workflow.Marshal(b, m, deterministic) +} +func (m *Workflow) XXX_Merge(src proto.Message) { + xxx_messageInfo_Workflow.Merge(m, src) +} +func (m *Workflow) XXX_Size() int { + return xxx_messageInfo_Workflow.Size(m) +} +func (m *Workflow) XXX_DiscardUnknown() { + xxx_messageInfo_Workflow.DiscardUnknown(m) +} + +var xxx_messageInfo_Workflow proto.InternalMessageInfo + +func (m *Workflow) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *Workflow) GetSource() *Workflow_ReplicationLocation { + if m != nil { + return m.Source + } + return nil +} + +func (m *Workflow) GetTarget() *Workflow_ReplicationLocation { + if m != nil { + return m.Target + } + return nil +} + +func (m *Workflow) GetMaxVReplicationLag() int64 { + if m != nil { + return m.MaxVReplicationLag + } + return 0 +} + +func (m *Workflow) GetShardStreams() map[string]*Workflow_ShardStream { + if m != nil { + return m.ShardStreams + } + return nil +} + +type Workflow_ReplicationLocation struct { + Keyspace string `protobuf:"bytes,1,opt,name=keyspace,proto3" json:"keyspace,omitempty"` + Shards []string `protobuf:"bytes,2,rep,name=shards,proto3" json:"shards,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Workflow_ReplicationLocation) Reset() { *m = Workflow_ReplicationLocation{} } +func (m *Workflow_ReplicationLocation) String() string { return proto.CompactTextString(m) } +func (*Workflow_ReplicationLocation) ProtoMessage() {} +func (*Workflow_ReplicationLocation) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{6, 1} +} + +func (m *Workflow_ReplicationLocation) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Workflow_ReplicationLocation.Unmarshal(m, b) +} +func (m *Workflow_ReplicationLocation) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Workflow_ReplicationLocation.Marshal(b, m, deterministic) +} +func (m *Workflow_ReplicationLocation) XXX_Merge(src proto.Message) { + xxx_messageInfo_Workflow_ReplicationLocation.Merge(m, src) +} +func (m *Workflow_ReplicationLocation) XXX_Size() int { + return xxx_messageInfo_Workflow_ReplicationLocation.Size(m) +} +func (m *Workflow_ReplicationLocation) XXX_DiscardUnknown() { + xxx_messageInfo_Workflow_ReplicationLocation.DiscardUnknown(m) +} + +var xxx_messageInfo_Workflow_ReplicationLocation proto.InternalMessageInfo + +func (m *Workflow_ReplicationLocation) GetKeyspace() string { + if m != nil { + return m.Keyspace + } + return "" +} + +func (m *Workflow_ReplicationLocation) GetShards() []string { + if m != nil { + return m.Shards + } + return nil +} + +type Workflow_ShardStream struct { + Streams []*Workflow_Stream `protobuf:"bytes,1,rep,name=streams,proto3" json:"streams,omitempty"` + TabletControls []*topodata.Shard_TabletControl `protobuf:"bytes,2,rep,name=tablet_controls,json=tabletControls,proto3" json:"tablet_controls,omitempty"` + IsPrimaryServing bool `protobuf:"varint,3,opt,name=is_primary_serving,json=isPrimaryServing,proto3" json:"is_primary_serving,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Workflow_ShardStream) Reset() { *m = Workflow_ShardStream{} } +func (m *Workflow_ShardStream) String() string { return proto.CompactTextString(m) } +func (*Workflow_ShardStream) ProtoMessage() {} +func (*Workflow_ShardStream) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{6, 2} +} + +func (m *Workflow_ShardStream) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Workflow_ShardStream.Unmarshal(m, b) +} +func (m *Workflow_ShardStream) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Workflow_ShardStream.Marshal(b, m, deterministic) +} +func (m *Workflow_ShardStream) XXX_Merge(src proto.Message) { + xxx_messageInfo_Workflow_ShardStream.Merge(m, src) +} +func (m *Workflow_ShardStream) XXX_Size() int { + return xxx_messageInfo_Workflow_ShardStream.Size(m) +} +func (m *Workflow_ShardStream) XXX_DiscardUnknown() { + xxx_messageInfo_Workflow_ShardStream.DiscardUnknown(m) +} + +var xxx_messageInfo_Workflow_ShardStream proto.InternalMessageInfo + +func (m *Workflow_ShardStream) GetStreams() []*Workflow_Stream { + if m != nil { + return m.Streams + } + return nil +} + +func (m *Workflow_ShardStream) GetTabletControls() []*topodata.Shard_TabletControl { + if m != nil { + return m.TabletControls + } + return nil +} + +func (m *Workflow_ShardStream) GetIsPrimaryServing() bool { + if m != nil { + return m.IsPrimaryServing + } + return false +} + +type Workflow_Stream struct { + Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Shard string `protobuf:"bytes,2,opt,name=shard,proto3" json:"shard,omitempty"` + Tablet *topodata.TabletAlias `protobuf:"bytes,3,opt,name=tablet,proto3" json:"tablet,omitempty"` + BinlogSource *binlogdata.BinlogSource `protobuf:"bytes,4,opt,name=binlog_source,json=binlogSource,proto3" json:"binlog_source,omitempty"` + Position string `protobuf:"bytes,5,opt,name=position,proto3" json:"position,omitempty"` + StopPosition string `protobuf:"bytes,6,opt,name=stop_position,json=stopPosition,proto3" json:"stop_position,omitempty"` + State string `protobuf:"bytes,7,opt,name=state,proto3" json:"state,omitempty"` + DbName string `protobuf:"bytes,8,opt,name=db_name,json=dbName,proto3" json:"db_name,omitempty"` + TransactionTimestamp *vttime.Time `protobuf:"bytes,9,opt,name=transaction_timestamp,json=transactionTimestamp,proto3" json:"transaction_timestamp,omitempty"` + TimeUpdated *vttime.Time `protobuf:"bytes,10,opt,name=time_updated,json=timeUpdated,proto3" json:"time_updated,omitempty"` + Message string `protobuf:"bytes,11,opt,name=message,proto3" json:"message,omitempty"` + CopyStates []*Workflow_Stream_CopyState `protobuf:"bytes,12,rep,name=copy_states,json=copyStates,proto3" json:"copy_states,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Workflow_Stream) Reset() { *m = Workflow_Stream{} } +func (m *Workflow_Stream) String() string { return proto.CompactTextString(m) } +func (*Workflow_Stream) ProtoMessage() {} +func (*Workflow_Stream) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{6, 3} +} + +func (m *Workflow_Stream) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Workflow_Stream.Unmarshal(m, b) +} +func (m *Workflow_Stream) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Workflow_Stream.Marshal(b, m, deterministic) +} +func (m *Workflow_Stream) XXX_Merge(src proto.Message) { + xxx_messageInfo_Workflow_Stream.Merge(m, src) +} +func (m *Workflow_Stream) XXX_Size() int { + return xxx_messageInfo_Workflow_Stream.Size(m) +} +func (m *Workflow_Stream) XXX_DiscardUnknown() { + xxx_messageInfo_Workflow_Stream.DiscardUnknown(m) +} + +var xxx_messageInfo_Workflow_Stream proto.InternalMessageInfo + +func (m *Workflow_Stream) GetId() int64 { + if m != nil { + return m.Id + } + return 0 +} + +func (m *Workflow_Stream) GetShard() string { + if m != nil { + return m.Shard + } + return "" +} + +func (m *Workflow_Stream) GetTablet() *topodata.TabletAlias { + if m != nil { + return m.Tablet + } + return nil +} + +func (m *Workflow_Stream) GetBinlogSource() *binlogdata.BinlogSource { + if m != nil { + return m.BinlogSource + } + return nil +} + +func (m *Workflow_Stream) GetPosition() string { + if m != nil { + return m.Position + } + return "" +} + +func (m *Workflow_Stream) GetStopPosition() string { + if m != nil { + return m.StopPosition + } + return "" +} + +func (m *Workflow_Stream) GetState() string { + if m != nil { + return m.State + } + return "" +} + +func (m *Workflow_Stream) GetDbName() string { + if m != nil { + return m.DbName + } + return "" +} + +func (m *Workflow_Stream) GetTransactionTimestamp() *vttime.Time { + if m != nil { + return m.TransactionTimestamp + } + return nil +} + +func (m *Workflow_Stream) GetTimeUpdated() *vttime.Time { + if m != nil { + return m.TimeUpdated + } + return nil +} + +func (m *Workflow_Stream) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + +func (m *Workflow_Stream) GetCopyStates() []*Workflow_Stream_CopyState { + if m != nil { + return m.CopyStates + } + return nil +} + +type Workflow_Stream_CopyState struct { + Table string `protobuf:"bytes,1,opt,name=table,proto3" json:"table,omitempty"` + LastPk string `protobuf:"bytes,2,opt,name=last_pk,json=lastPk,proto3" json:"last_pk,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Workflow_Stream_CopyState) Reset() { *m = Workflow_Stream_CopyState{} } +func (m *Workflow_Stream_CopyState) String() string { return proto.CompactTextString(m) } +func (*Workflow_Stream_CopyState) ProtoMessage() {} +func (*Workflow_Stream_CopyState) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{6, 3, 0} +} + +func (m *Workflow_Stream_CopyState) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Workflow_Stream_CopyState.Unmarshal(m, b) +} +func (m *Workflow_Stream_CopyState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Workflow_Stream_CopyState.Marshal(b, m, deterministic) +} +func (m *Workflow_Stream_CopyState) XXX_Merge(src proto.Message) { + xxx_messageInfo_Workflow_Stream_CopyState.Merge(m, src) +} +func (m *Workflow_Stream_CopyState) XXX_Size() int { + return xxx_messageInfo_Workflow_Stream_CopyState.Size(m) +} +func (m *Workflow_Stream_CopyState) XXX_DiscardUnknown() { + xxx_messageInfo_Workflow_Stream_CopyState.DiscardUnknown(m) +} + +var xxx_messageInfo_Workflow_Stream_CopyState proto.InternalMessageInfo + +func (m *Workflow_Stream_CopyState) GetTable() string { + if m != nil { + return m.Table + } + return "" +} + +func (m *Workflow_Stream_CopyState) GetLastPk() string { + if m != nil { + return m.LastPk + } + return "" +} + type ChangeTabletTypeRequest struct { TabletAlias *topodata.TabletAlias `protobuf:"bytes,1,opt,name=tablet_alias,json=tabletAlias,proto3" json:"tablet_alias,omitempty"` DbType topodata.TabletType `protobuf:"varint,2,opt,name=db_type,json=dbType,proto3,enum=topodata.TabletType" json:"db_type,omitempty"` @@ -130,7 +742,7 @@ func (m *ChangeTabletTypeRequest) Reset() { *m = ChangeTabletTypeRequest func (m *ChangeTabletTypeRequest) String() string { return proto.CompactTextString(m) } func (*ChangeTabletTypeRequest) ProtoMessage() {} func (*ChangeTabletTypeRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{2} + return fileDescriptor_f41247b323a1ab2e, []int{7} } func (m *ChangeTabletTypeRequest) XXX_Unmarshal(b []byte) error { @@ -185,7 +797,7 @@ func (m *ChangeTabletTypeResponse) Reset() { *m = ChangeTabletTypeRespon func (m *ChangeTabletTypeResponse) String() string { return proto.CompactTextString(m) } func (*ChangeTabletTypeResponse) ProtoMessage() {} func (*ChangeTabletTypeResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{3} + return fileDescriptor_f41247b323a1ab2e, []int{8} } func (m *ChangeTabletTypeResponse) XXX_Unmarshal(b []byte) error { @@ -259,7 +871,7 @@ func (m *CreateKeyspaceRequest) Reset() { *m = CreateKeyspaceRequest{} } func (m *CreateKeyspaceRequest) String() string { return proto.CompactTextString(m) } func (*CreateKeyspaceRequest) ProtoMessage() {} func (*CreateKeyspaceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{4} + return fileDescriptor_f41247b323a1ab2e, []int{9} } func (m *CreateKeyspaceRequest) XXX_Unmarshal(b []byte) error { @@ -355,7 +967,7 @@ func (m *CreateKeyspaceResponse) Reset() { *m = CreateKeyspaceResponse{} func (m *CreateKeyspaceResponse) String() string { return proto.CompactTextString(m) } func (*CreateKeyspaceResponse) ProtoMessage() {} func (*CreateKeyspaceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{5} + return fileDescriptor_f41247b323a1ab2e, []int{10} } func (m *CreateKeyspaceResponse) XXX_Unmarshal(b []byte) error { @@ -403,7 +1015,7 @@ func (m *CreateShardRequest) Reset() { *m = CreateShardRequest{} } func (m *CreateShardRequest) String() string { return proto.CompactTextString(m) } func (*CreateShardRequest) ProtoMessage() {} func (*CreateShardRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{6} + return fileDescriptor_f41247b323a1ab2e, []int{11} } func (m *CreateShardRequest) XXX_Unmarshal(b []byte) error { @@ -470,7 +1082,7 @@ func (m *CreateShardResponse) Reset() { *m = CreateShardResponse{} } func (m *CreateShardResponse) String() string { return proto.CompactTextString(m) } func (*CreateShardResponse) ProtoMessage() {} func (*CreateShardResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{7} + return fileDescriptor_f41247b323a1ab2e, []int{12} } func (m *CreateShardResponse) XXX_Unmarshal(b []byte) error { @@ -528,7 +1140,7 @@ func (m *DeleteKeyspaceRequest) Reset() { *m = DeleteKeyspaceRequest{} } func (m *DeleteKeyspaceRequest) String() string { return proto.CompactTextString(m) } func (*DeleteKeyspaceRequest) ProtoMessage() {} func (*DeleteKeyspaceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{8} + return fileDescriptor_f41247b323a1ab2e, []int{13} } func (m *DeleteKeyspaceRequest) XXX_Unmarshal(b []byte) error { @@ -573,7 +1185,7 @@ func (m *DeleteKeyspaceResponse) Reset() { *m = DeleteKeyspaceResponse{} func (m *DeleteKeyspaceResponse) String() string { return proto.CompactTextString(m) } func (*DeleteKeyspaceResponse) ProtoMessage() {} func (*DeleteKeyspaceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{9} + return fileDescriptor_f41247b323a1ab2e, []int{14} } func (m *DeleteKeyspaceResponse) XXX_Unmarshal(b []byte) error { @@ -614,7 +1226,7 @@ func (m *DeleteShardsRequest) Reset() { *m = DeleteShardsRequest{} } func (m *DeleteShardsRequest) String() string { return proto.CompactTextString(m) } func (*DeleteShardsRequest) ProtoMessage() {} func (*DeleteShardsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{10} + return fileDescriptor_f41247b323a1ab2e, []int{15} } func (m *DeleteShardsRequest) XXX_Unmarshal(b []byte) error { @@ -666,7 +1278,7 @@ func (m *DeleteShardsResponse) Reset() { *m = DeleteShardsResponse{} } func (m *DeleteShardsResponse) String() string { return proto.CompactTextString(m) } func (*DeleteShardsResponse) ProtoMessage() {} func (*DeleteShardsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{11} + return fileDescriptor_f41247b323a1ab2e, []int{16} } func (m *DeleteShardsResponse) XXX_Unmarshal(b []byte) error { @@ -702,7 +1314,7 @@ func (m *DeleteTabletsRequest) Reset() { *m = DeleteTabletsRequest{} } func (m *DeleteTabletsRequest) String() string { return proto.CompactTextString(m) } func (*DeleteTabletsRequest) ProtoMessage() {} func (*DeleteTabletsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{12} + return fileDescriptor_f41247b323a1ab2e, []int{17} } func (m *DeleteTabletsRequest) XXX_Unmarshal(b []byte) error { @@ -717,56 +1329,284 @@ func (m *DeleteTabletsRequest) XXX_Merge(src proto.Message) { func (m *DeleteTabletsRequest) XXX_Size() int { return xxx_messageInfo_DeleteTabletsRequest.Size(m) } -func (m *DeleteTabletsRequest) XXX_DiscardUnknown() { - xxx_messageInfo_DeleteTabletsRequest.DiscardUnknown(m) +func (m *DeleteTabletsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_DeleteTabletsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_DeleteTabletsRequest proto.InternalMessageInfo + +func (m *DeleteTabletsRequest) GetTabletAliases() []*topodata.TabletAlias { + if m != nil { + return m.TabletAliases + } + return nil +} + +func (m *DeleteTabletsRequest) GetAllowPrimary() bool { + if m != nil { + return m.AllowPrimary + } + return false +} + +type DeleteTabletsResponse struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DeleteTabletsResponse) Reset() { *m = DeleteTabletsResponse{} } +func (m *DeleteTabletsResponse) String() string { return proto.CompactTextString(m) } +func (*DeleteTabletsResponse) ProtoMessage() {} +func (*DeleteTabletsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{18} +} + +func (m *DeleteTabletsResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DeleteTabletsResponse.Unmarshal(m, b) +} +func (m *DeleteTabletsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DeleteTabletsResponse.Marshal(b, m, deterministic) +} +func (m *DeleteTabletsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_DeleteTabletsResponse.Merge(m, src) +} +func (m *DeleteTabletsResponse) XXX_Size() int { + return xxx_messageInfo_DeleteTabletsResponse.Size(m) +} +func (m *DeleteTabletsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_DeleteTabletsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_DeleteTabletsResponse proto.InternalMessageInfo + +type EmergencyReparentShardRequest struct { + // Keyspace is the name of the keyspace to perform the Emergency Reparent in. + Keyspace string `protobuf:"bytes,1,opt,name=keyspace,proto3" json:"keyspace,omitempty"` + // Shard is the name of the shard to perform the Emergency Reparent in. + Shard string `protobuf:"bytes,2,opt,name=shard,proto3" json:"shard,omitempty"` + // Optional alias of a tablet that should become the new shard primary. If not + // not specified, the vtctld will select the most up-to-date canditate to + // promote. + NewPrimary *topodata.TabletAlias `protobuf:"bytes,3,opt,name=new_primary,json=newPrimary,proto3" json:"new_primary,omitempty"` + // List of replica aliases to ignore during the Emergency Reparent. The vtctld + // will not attempt to stop replication on these tablets, nor attempt to + // demote any that may think they are the shard primary. + IgnoreReplicas []*topodata.TabletAlias `protobuf:"bytes,4,rep,name=ignore_replicas,json=ignoreReplicas,proto3" json:"ignore_replicas,omitempty"` + // WaitReplicasTimeout is the duration of time to wait for replicas to catch + // up in reparenting. + WaitReplicasTimeout *vttime.Duration `protobuf:"bytes,5,opt,name=wait_replicas_timeout,json=waitReplicasTimeout,proto3" json:"wait_replicas_timeout,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EmergencyReparentShardRequest) Reset() { *m = EmergencyReparentShardRequest{} } +func (m *EmergencyReparentShardRequest) String() string { return proto.CompactTextString(m) } +func (*EmergencyReparentShardRequest) ProtoMessage() {} +func (*EmergencyReparentShardRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{19} +} + +func (m *EmergencyReparentShardRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EmergencyReparentShardRequest.Unmarshal(m, b) +} +func (m *EmergencyReparentShardRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EmergencyReparentShardRequest.Marshal(b, m, deterministic) +} +func (m *EmergencyReparentShardRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_EmergencyReparentShardRequest.Merge(m, src) +} +func (m *EmergencyReparentShardRequest) XXX_Size() int { + return xxx_messageInfo_EmergencyReparentShardRequest.Size(m) +} +func (m *EmergencyReparentShardRequest) XXX_DiscardUnknown() { + xxx_messageInfo_EmergencyReparentShardRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_EmergencyReparentShardRequest proto.InternalMessageInfo + +func (m *EmergencyReparentShardRequest) GetKeyspace() string { + if m != nil { + return m.Keyspace + } + return "" +} + +func (m *EmergencyReparentShardRequest) GetShard() string { + if m != nil { + return m.Shard + } + return "" +} + +func (m *EmergencyReparentShardRequest) GetNewPrimary() *topodata.TabletAlias { + if m != nil { + return m.NewPrimary + } + return nil +} + +func (m *EmergencyReparentShardRequest) GetIgnoreReplicas() []*topodata.TabletAlias { + if m != nil { + return m.IgnoreReplicas + } + return nil +} + +func (m *EmergencyReparentShardRequest) GetWaitReplicasTimeout() *vttime.Duration { + if m != nil { + return m.WaitReplicasTimeout + } + return nil +} + +type EmergencyReparentShardResponse struct { + // Keyspace is the name of the keyspace the Emergency Reparent took place in. + Keyspace string `protobuf:"bytes,1,opt,name=keyspace,proto3" json:"keyspace,omitempty"` + // Shard is the name of the shard the Emergency Reparent took place in. + Shard string `protobuf:"bytes,2,opt,name=shard,proto3" json:"shard,omitempty"` + // PromotedPrimary is the alias of the tablet that was promoted to shard + // primary. If NewPrimary was set in the request, then this will be the same + // alias. Otherwise, it will be the alias of the tablet found to be most + // up-to-date. + PromotedPrimary *topodata.TabletAlias `protobuf:"bytes,3,opt,name=promoted_primary,json=promotedPrimary,proto3" json:"promoted_primary,omitempty"` + Events []*logutil.Event `protobuf:"bytes,4,rep,name=events,proto3" json:"events,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *EmergencyReparentShardResponse) Reset() { *m = EmergencyReparentShardResponse{} } +func (m *EmergencyReparentShardResponse) String() string { return proto.CompactTextString(m) } +func (*EmergencyReparentShardResponse) ProtoMessage() {} +func (*EmergencyReparentShardResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{20} +} + +func (m *EmergencyReparentShardResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_EmergencyReparentShardResponse.Unmarshal(m, b) +} +func (m *EmergencyReparentShardResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_EmergencyReparentShardResponse.Marshal(b, m, deterministic) +} +func (m *EmergencyReparentShardResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_EmergencyReparentShardResponse.Merge(m, src) +} +func (m *EmergencyReparentShardResponse) XXX_Size() int { + return xxx_messageInfo_EmergencyReparentShardResponse.Size(m) +} +func (m *EmergencyReparentShardResponse) XXX_DiscardUnknown() { + xxx_messageInfo_EmergencyReparentShardResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_EmergencyReparentShardResponse proto.InternalMessageInfo + +func (m *EmergencyReparentShardResponse) GetKeyspace() string { + if m != nil { + return m.Keyspace + } + return "" +} + +func (m *EmergencyReparentShardResponse) GetShard() string { + if m != nil { + return m.Shard + } + return "" +} + +func (m *EmergencyReparentShardResponse) GetPromotedPrimary() *topodata.TabletAlias { + if m != nil { + return m.PromotedPrimary + } + return nil +} + +func (m *EmergencyReparentShardResponse) GetEvents() []*logutil.Event { + if m != nil { + return m.Events + } + return nil +} + +type FindAllShardsInKeyspaceRequest struct { + Keyspace string `protobuf:"bytes,1,opt,name=keyspace,proto3" json:"keyspace,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *FindAllShardsInKeyspaceRequest) Reset() { *m = FindAllShardsInKeyspaceRequest{} } +func (m *FindAllShardsInKeyspaceRequest) String() string { return proto.CompactTextString(m) } +func (*FindAllShardsInKeyspaceRequest) ProtoMessage() {} +func (*FindAllShardsInKeyspaceRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{21} +} + +func (m *FindAllShardsInKeyspaceRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FindAllShardsInKeyspaceRequest.Unmarshal(m, b) +} +func (m *FindAllShardsInKeyspaceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FindAllShardsInKeyspaceRequest.Marshal(b, m, deterministic) +} +func (m *FindAllShardsInKeyspaceRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_FindAllShardsInKeyspaceRequest.Merge(m, src) +} +func (m *FindAllShardsInKeyspaceRequest) XXX_Size() int { + return xxx_messageInfo_FindAllShardsInKeyspaceRequest.Size(m) +} +func (m *FindAllShardsInKeyspaceRequest) XXX_DiscardUnknown() { + xxx_messageInfo_FindAllShardsInKeyspaceRequest.DiscardUnknown(m) } -var xxx_messageInfo_DeleteTabletsRequest proto.InternalMessageInfo - -func (m *DeleteTabletsRequest) GetTabletAliases() []*topodata.TabletAlias { - if m != nil { - return m.TabletAliases - } - return nil -} +var xxx_messageInfo_FindAllShardsInKeyspaceRequest proto.InternalMessageInfo -func (m *DeleteTabletsRequest) GetAllowPrimary() bool { +func (m *FindAllShardsInKeyspaceRequest) GetKeyspace() string { if m != nil { - return m.AllowPrimary + return m.Keyspace } - return false + return "" } -type DeleteTabletsResponse struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +type FindAllShardsInKeyspaceResponse struct { + Shards map[string]*Shard `protobuf:"bytes,1,rep,name=shards,proto3" json:"shards,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *DeleteTabletsResponse) Reset() { *m = DeleteTabletsResponse{} } -func (m *DeleteTabletsResponse) String() string { return proto.CompactTextString(m) } -func (*DeleteTabletsResponse) ProtoMessage() {} -func (*DeleteTabletsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{13} +func (m *FindAllShardsInKeyspaceResponse) Reset() { *m = FindAllShardsInKeyspaceResponse{} } +func (m *FindAllShardsInKeyspaceResponse) String() string { return proto.CompactTextString(m) } +func (*FindAllShardsInKeyspaceResponse) ProtoMessage() {} +func (*FindAllShardsInKeyspaceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{22} } -func (m *DeleteTabletsResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_DeleteTabletsResponse.Unmarshal(m, b) +func (m *FindAllShardsInKeyspaceResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_FindAllShardsInKeyspaceResponse.Unmarshal(m, b) } -func (m *DeleteTabletsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_DeleteTabletsResponse.Marshal(b, m, deterministic) +func (m *FindAllShardsInKeyspaceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_FindAllShardsInKeyspaceResponse.Marshal(b, m, deterministic) } -func (m *DeleteTabletsResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_DeleteTabletsResponse.Merge(m, src) +func (m *FindAllShardsInKeyspaceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_FindAllShardsInKeyspaceResponse.Merge(m, src) } -func (m *DeleteTabletsResponse) XXX_Size() int { - return xxx_messageInfo_DeleteTabletsResponse.Size(m) +func (m *FindAllShardsInKeyspaceResponse) XXX_Size() int { + return xxx_messageInfo_FindAllShardsInKeyspaceResponse.Size(m) } -func (m *DeleteTabletsResponse) XXX_DiscardUnknown() { - xxx_messageInfo_DeleteTabletsResponse.DiscardUnknown(m) +func (m *FindAllShardsInKeyspaceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_FindAllShardsInKeyspaceResponse.DiscardUnknown(m) } -var xxx_messageInfo_DeleteTabletsResponse proto.InternalMessageInfo +var xxx_messageInfo_FindAllShardsInKeyspaceResponse proto.InternalMessageInfo + +func (m *FindAllShardsInKeyspaceResponse) GetShards() map[string]*Shard { + if m != nil { + return m.Shards + } + return nil +} type GetBackupsRequest struct { Keyspace string `protobuf:"bytes,1,opt,name=keyspace,proto3" json:"keyspace,omitempty"` @@ -780,7 +1620,7 @@ func (m *GetBackupsRequest) Reset() { *m = GetBackupsRequest{} } func (m *GetBackupsRequest) String() string { return proto.CompactTextString(m) } func (*GetBackupsRequest) ProtoMessage() {} func (*GetBackupsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{14} + return fileDescriptor_f41247b323a1ab2e, []int{23} } func (m *GetBackupsRequest) XXX_Unmarshal(b []byte) error { @@ -826,7 +1666,7 @@ func (m *GetBackupsResponse) Reset() { *m = GetBackupsResponse{} } func (m *GetBackupsResponse) String() string { return proto.CompactTextString(m) } func (*GetBackupsResponse) ProtoMessage() {} func (*GetBackupsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{15} + return fileDescriptor_f41247b323a1ab2e, []int{24} } func (m *GetBackupsResponse) XXX_Unmarshal(b []byte) error { @@ -864,7 +1704,7 @@ func (m *GetCellInfoNamesRequest) Reset() { *m = GetCellInfoNamesRequest func (m *GetCellInfoNamesRequest) String() string { return proto.CompactTextString(m) } func (*GetCellInfoNamesRequest) ProtoMessage() {} func (*GetCellInfoNamesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{16} + return fileDescriptor_f41247b323a1ab2e, []int{25} } func (m *GetCellInfoNamesRequest) XXX_Unmarshal(b []byte) error { @@ -896,7 +1736,7 @@ func (m *GetCellInfoNamesResponse) Reset() { *m = GetCellInfoNamesRespon func (m *GetCellInfoNamesResponse) String() string { return proto.CompactTextString(m) } func (*GetCellInfoNamesResponse) ProtoMessage() {} func (*GetCellInfoNamesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{17} + return fileDescriptor_f41247b323a1ab2e, []int{26} } func (m *GetCellInfoNamesResponse) XXX_Unmarshal(b []byte) error { @@ -935,7 +1775,7 @@ func (m *GetCellInfoRequest) Reset() { *m = GetCellInfoRequest{} } func (m *GetCellInfoRequest) String() string { return proto.CompactTextString(m) } func (*GetCellInfoRequest) ProtoMessage() {} func (*GetCellInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{18} + return fileDescriptor_f41247b323a1ab2e, []int{27} } func (m *GetCellInfoRequest) XXX_Unmarshal(b []byte) error { @@ -974,7 +1814,7 @@ func (m *GetCellInfoResponse) Reset() { *m = GetCellInfoResponse{} } func (m *GetCellInfoResponse) String() string { return proto.CompactTextString(m) } func (*GetCellInfoResponse) ProtoMessage() {} func (*GetCellInfoResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{19} + return fileDescriptor_f41247b323a1ab2e, []int{28} } func (m *GetCellInfoResponse) XXX_Unmarshal(b []byte) error { @@ -1012,7 +1852,7 @@ func (m *GetCellsAliasesRequest) Reset() { *m = GetCellsAliasesRequest{} func (m *GetCellsAliasesRequest) String() string { return proto.CompactTextString(m) } func (*GetCellsAliasesRequest) ProtoMessage() {} func (*GetCellsAliasesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{20} + return fileDescriptor_f41247b323a1ab2e, []int{29} } func (m *GetCellsAliasesRequest) XXX_Unmarshal(b []byte) error { @@ -1044,7 +1884,7 @@ func (m *GetCellsAliasesResponse) Reset() { *m = GetCellsAliasesResponse func (m *GetCellsAliasesResponse) String() string { return proto.CompactTextString(m) } func (*GetCellsAliasesResponse) ProtoMessage() {} func (*GetCellsAliasesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{21} + return fileDescriptor_f41247b323a1ab2e, []int{30} } func (m *GetCellsAliasesResponse) XXX_Unmarshal(b []byte) error { @@ -1082,7 +1922,7 @@ func (m *GetKeyspacesRequest) Reset() { *m = GetKeyspacesRequest{} } func (m *GetKeyspacesRequest) String() string { return proto.CompactTextString(m) } func (*GetKeyspacesRequest) ProtoMessage() {} func (*GetKeyspacesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{22} + return fileDescriptor_f41247b323a1ab2e, []int{31} } func (m *GetKeyspacesRequest) XXX_Unmarshal(b []byte) error { @@ -1114,7 +1954,7 @@ func (m *GetKeyspacesResponse) Reset() { *m = GetKeyspacesResponse{} } func (m *GetKeyspacesResponse) String() string { return proto.CompactTextString(m) } func (*GetKeyspacesResponse) ProtoMessage() {} func (*GetKeyspacesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{23} + return fileDescriptor_f41247b323a1ab2e, []int{32} } func (m *GetKeyspacesResponse) XXX_Unmarshal(b []byte) error { @@ -1153,7 +1993,7 @@ func (m *GetKeyspaceRequest) Reset() { *m = GetKeyspaceRequest{} } func (m *GetKeyspaceRequest) String() string { return proto.CompactTextString(m) } func (*GetKeyspaceRequest) ProtoMessage() {} func (*GetKeyspaceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{24} + return fileDescriptor_f41247b323a1ab2e, []int{33} } func (m *GetKeyspaceRequest) XXX_Unmarshal(b []byte) error { @@ -1192,7 +2032,7 @@ func (m *GetKeyspaceResponse) Reset() { *m = GetKeyspaceResponse{} } func (m *GetKeyspaceResponse) String() string { return proto.CompactTextString(m) } func (*GetKeyspaceResponse) ProtoMessage() {} func (*GetKeyspaceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{25} + return fileDescriptor_f41247b323a1ab2e, []int{34} } func (m *GetKeyspaceResponse) XXX_Unmarshal(b []byte) error { @@ -1246,7 +2086,7 @@ func (m *GetSchemaRequest) Reset() { *m = GetSchemaRequest{} } func (m *GetSchemaRequest) String() string { return proto.CompactTextString(m) } func (*GetSchemaRequest) ProtoMessage() {} func (*GetSchemaRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{26} + return fileDescriptor_f41247b323a1ab2e, []int{35} } func (m *GetSchemaRequest) XXX_Unmarshal(b []byte) error { @@ -1320,7 +2160,7 @@ func (m *GetSchemaResponse) Reset() { *m = GetSchemaResponse{} } func (m *GetSchemaResponse) String() string { return proto.CompactTextString(m) } func (*GetSchemaResponse) ProtoMessage() {} func (*GetSchemaResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{27} + return fileDescriptor_f41247b323a1ab2e, []int{36} } func (m *GetSchemaResponse) XXX_Unmarshal(b []byte) error { @@ -1360,7 +2200,7 @@ func (m *GetShardRequest) Reset() { *m = GetShardRequest{} } func (m *GetShardRequest) String() string { return proto.CompactTextString(m) } func (*GetShardRequest) ProtoMessage() {} func (*GetShardRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{28} + return fileDescriptor_f41247b323a1ab2e, []int{37} } func (m *GetShardRequest) XXX_Unmarshal(b []byte) error { @@ -1406,7 +2246,7 @@ func (m *GetShardResponse) Reset() { *m = GetShardResponse{} } func (m *GetShardResponse) String() string { return proto.CompactTextString(m) } func (*GetShardResponse) ProtoMessage() {} func (*GetShardResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{29} + return fileDescriptor_f41247b323a1ab2e, []int{38} } func (m *GetShardResponse) XXX_Unmarshal(b []byte) error { @@ -1445,7 +2285,7 @@ func (m *GetSrvVSchemaRequest) Reset() { *m = GetSrvVSchemaRequest{} } func (m *GetSrvVSchemaRequest) String() string { return proto.CompactTextString(m) } func (*GetSrvVSchemaRequest) ProtoMessage() {} func (*GetSrvVSchemaRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{30} + return fileDescriptor_f41247b323a1ab2e, []int{39} } func (m *GetSrvVSchemaRequest) XXX_Unmarshal(b []byte) error { @@ -1484,7 +2324,7 @@ func (m *GetSrvVSchemaResponse) Reset() { *m = GetSrvVSchemaResponse{} } func (m *GetSrvVSchemaResponse) String() string { return proto.CompactTextString(m) } func (*GetSrvVSchemaResponse) ProtoMessage() {} func (*GetSrvVSchemaResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{31} + return fileDescriptor_f41247b323a1ab2e, []int{40} } func (m *GetSrvVSchemaResponse) XXX_Unmarshal(b []byte) error { @@ -1523,7 +2363,7 @@ func (m *GetTabletRequest) Reset() { *m = GetTabletRequest{} } func (m *GetTabletRequest) String() string { return proto.CompactTextString(m) } func (*GetTabletRequest) ProtoMessage() {} func (*GetTabletRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{32} + return fileDescriptor_f41247b323a1ab2e, []int{41} } func (m *GetTabletRequest) XXX_Unmarshal(b []byte) error { @@ -1562,7 +2402,7 @@ func (m *GetTabletResponse) Reset() { *m = GetTabletResponse{} } func (m *GetTabletResponse) String() string { return proto.CompactTextString(m) } func (*GetTabletResponse) ProtoMessage() {} func (*GetTabletResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{33} + return fileDescriptor_f41247b323a1ab2e, []int{42} } func (m *GetTabletResponse) XXX_Unmarshal(b []byte) error { @@ -1608,7 +2448,7 @@ func (m *GetTabletsRequest) Reset() { *m = GetTabletsRequest{} } func (m *GetTabletsRequest) String() string { return proto.CompactTextString(m) } func (*GetTabletsRequest) ProtoMessage() {} func (*GetTabletsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{34} + return fileDescriptor_f41247b323a1ab2e, []int{43} } func (m *GetTabletsRequest) XXX_Unmarshal(b []byte) error { @@ -1661,7 +2501,7 @@ func (m *GetTabletsResponse) Reset() { *m = GetTabletsResponse{} } func (m *GetTabletsResponse) String() string { return proto.CompactTextString(m) } func (*GetTabletsResponse) ProtoMessage() {} func (*GetTabletsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{35} + return fileDescriptor_f41247b323a1ab2e, []int{44} } func (m *GetTabletsResponse) XXX_Unmarshal(b []byte) error { @@ -1700,7 +2540,7 @@ func (m *GetVSchemaRequest) Reset() { *m = GetVSchemaRequest{} } func (m *GetVSchemaRequest) String() string { return proto.CompactTextString(m) } func (*GetVSchemaRequest) ProtoMessage() {} func (*GetVSchemaRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{36} + return fileDescriptor_f41247b323a1ab2e, []int{45} } func (m *GetVSchemaRequest) XXX_Unmarshal(b []byte) error { @@ -1739,7 +2579,7 @@ func (m *GetVSchemaResponse) Reset() { *m = GetVSchemaResponse{} } func (m *GetVSchemaResponse) String() string { return proto.CompactTextString(m) } func (*GetVSchemaResponse) ProtoMessage() {} func (*GetVSchemaResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{37} + return fileDescriptor_f41247b323a1ab2e, []int{46} } func (m *GetVSchemaResponse) XXX_Unmarshal(b []byte) error { @@ -1767,6 +2607,92 @@ func (m *GetVSchemaResponse) GetVSchema() *vschema.Keyspace { return nil } +type GetWorkflowsRequest struct { + Keyspace string `protobuf:"bytes,1,opt,name=keyspace,proto3" json:"keyspace,omitempty"` + ActiveOnly bool `protobuf:"varint,2,opt,name=active_only,json=activeOnly,proto3" json:"active_only,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GetWorkflowsRequest) Reset() { *m = GetWorkflowsRequest{} } +func (m *GetWorkflowsRequest) String() string { return proto.CompactTextString(m) } +func (*GetWorkflowsRequest) ProtoMessage() {} +func (*GetWorkflowsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{47} +} + +func (m *GetWorkflowsRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetWorkflowsRequest.Unmarshal(m, b) +} +func (m *GetWorkflowsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetWorkflowsRequest.Marshal(b, m, deterministic) +} +func (m *GetWorkflowsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetWorkflowsRequest.Merge(m, src) +} +func (m *GetWorkflowsRequest) XXX_Size() int { + return xxx_messageInfo_GetWorkflowsRequest.Size(m) +} +func (m *GetWorkflowsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetWorkflowsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetWorkflowsRequest proto.InternalMessageInfo + +func (m *GetWorkflowsRequest) GetKeyspace() string { + if m != nil { + return m.Keyspace + } + return "" +} + +func (m *GetWorkflowsRequest) GetActiveOnly() bool { + if m != nil { + return m.ActiveOnly + } + return false +} + +type GetWorkflowsResponse struct { + Workflows []*Workflow `protobuf:"bytes,1,rep,name=workflows,proto3" json:"workflows,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GetWorkflowsResponse) Reset() { *m = GetWorkflowsResponse{} } +func (m *GetWorkflowsResponse) String() string { return proto.CompactTextString(m) } +func (*GetWorkflowsResponse) ProtoMessage() {} +func (*GetWorkflowsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{48} +} + +func (m *GetWorkflowsResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetWorkflowsResponse.Unmarshal(m, b) +} +func (m *GetWorkflowsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetWorkflowsResponse.Marshal(b, m, deterministic) +} +func (m *GetWorkflowsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetWorkflowsResponse.Merge(m, src) +} +func (m *GetWorkflowsResponse) XXX_Size() int { + return xxx_messageInfo_GetWorkflowsResponse.Size(m) +} +func (m *GetWorkflowsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetWorkflowsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetWorkflowsResponse proto.InternalMessageInfo + +func (m *GetWorkflowsResponse) GetWorkflows() []*Workflow { + if m != nil { + return m.Workflows + } + return nil +} + type RemoveKeyspaceCellRequest struct { Keyspace string `protobuf:"bytes,1,opt,name=keyspace,proto3" json:"keyspace,omitempty"` Cell string `protobuf:"bytes,2,opt,name=cell,proto3" json:"cell,omitempty"` @@ -1786,7 +2712,7 @@ func (m *RemoveKeyspaceCellRequest) Reset() { *m = RemoveKeyspaceCellReq func (m *RemoveKeyspaceCellRequest) String() string { return proto.CompactTextString(m) } func (*RemoveKeyspaceCellRequest) ProtoMessage() {} func (*RemoveKeyspaceCellRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{38} + return fileDescriptor_f41247b323a1ab2e, []int{49} } func (m *RemoveKeyspaceCellRequest) XXX_Unmarshal(b []byte) error { @@ -1845,7 +2771,7 @@ func (m *RemoveKeyspaceCellResponse) Reset() { *m = RemoveKeyspaceCellRe func (m *RemoveKeyspaceCellResponse) String() string { return proto.CompactTextString(m) } func (*RemoveKeyspaceCellResponse) ProtoMessage() {} func (*RemoveKeyspaceCellResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{39} + return fileDescriptor_f41247b323a1ab2e, []int{50} } func (m *RemoveKeyspaceCellResponse) XXX_Unmarshal(b []byte) error { @@ -1886,7 +2812,7 @@ func (m *RemoveShardCellRequest) Reset() { *m = RemoveShardCellRequest{} func (m *RemoveShardCellRequest) String() string { return proto.CompactTextString(m) } func (*RemoveShardCellRequest) ProtoMessage() {} func (*RemoveShardCellRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{40} + return fileDescriptor_f41247b323a1ab2e, []int{51} } func (m *RemoveShardCellRequest) XXX_Unmarshal(b []byte) error { @@ -1911,402 +2837,284 @@ func (m *RemoveShardCellRequest) GetKeyspace() string { if m != nil { return m.Keyspace } - return "" -} - -func (m *RemoveShardCellRequest) GetShardName() string { - if m != nil { - return m.ShardName - } - return "" -} - -func (m *RemoveShardCellRequest) GetCell() string { - if m != nil { - return m.Cell - } - return "" -} - -func (m *RemoveShardCellRequest) GetForce() bool { - if m != nil { - return m.Force - } - return false -} - -func (m *RemoveShardCellRequest) GetRecursive() bool { - if m != nil { - return m.Recursive - } - return false -} - -type RemoveShardCellResponse struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *RemoveShardCellResponse) Reset() { *m = RemoveShardCellResponse{} } -func (m *RemoveShardCellResponse) String() string { return proto.CompactTextString(m) } -func (*RemoveShardCellResponse) ProtoMessage() {} -func (*RemoveShardCellResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{41} -} - -func (m *RemoveShardCellResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_RemoveShardCellResponse.Unmarshal(m, b) -} -func (m *RemoveShardCellResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_RemoveShardCellResponse.Marshal(b, m, deterministic) -} -func (m *RemoveShardCellResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_RemoveShardCellResponse.Merge(m, src) -} -func (m *RemoveShardCellResponse) XXX_Size() int { - return xxx_messageInfo_RemoveShardCellResponse.Size(m) -} -func (m *RemoveShardCellResponse) XXX_DiscardUnknown() { - xxx_messageInfo_RemoveShardCellResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_RemoveShardCellResponse proto.InternalMessageInfo - -type Keyspace struct { - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Keyspace *topodata.Keyspace `protobuf:"bytes,2,opt,name=keyspace,proto3" json:"keyspace,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Keyspace) Reset() { *m = Keyspace{} } -func (m *Keyspace) String() string { return proto.CompactTextString(m) } -func (*Keyspace) ProtoMessage() {} -func (*Keyspace) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{42} -} - -func (m *Keyspace) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Keyspace.Unmarshal(m, b) -} -func (m *Keyspace) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Keyspace.Marshal(b, m, deterministic) -} -func (m *Keyspace) XXX_Merge(src proto.Message) { - xxx_messageInfo_Keyspace.Merge(m, src) -} -func (m *Keyspace) XXX_Size() int { - return xxx_messageInfo_Keyspace.Size(m) -} -func (m *Keyspace) XXX_DiscardUnknown() { - xxx_messageInfo_Keyspace.DiscardUnknown(m) + return "" } -var xxx_messageInfo_Keyspace proto.InternalMessageInfo +func (m *RemoveShardCellRequest) GetShardName() string { + if m != nil { + return m.ShardName + } + return "" +} -func (m *Keyspace) GetName() string { +func (m *RemoveShardCellRequest) GetCell() string { if m != nil { - return m.Name + return m.Cell } return "" } -func (m *Keyspace) GetKeyspace() *topodata.Keyspace { +func (m *RemoveShardCellRequest) GetForce() bool { if m != nil { - return m.Keyspace + return m.Force } - return nil + return false } -type FindAllShardsInKeyspaceRequest struct { - Keyspace string `protobuf:"bytes,1,opt,name=keyspace,proto3" json:"keyspace,omitempty"` +func (m *RemoveShardCellRequest) GetRecursive() bool { + if m != nil { + return m.Recursive + } + return false +} + +type RemoveShardCellResponse struct { XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` } -func (m *FindAllShardsInKeyspaceRequest) Reset() { *m = FindAllShardsInKeyspaceRequest{} } -func (m *FindAllShardsInKeyspaceRequest) String() string { return proto.CompactTextString(m) } -func (*FindAllShardsInKeyspaceRequest) ProtoMessage() {} -func (*FindAllShardsInKeyspaceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{43} +func (m *RemoveShardCellResponse) Reset() { *m = RemoveShardCellResponse{} } +func (m *RemoveShardCellResponse) String() string { return proto.CompactTextString(m) } +func (*RemoveShardCellResponse) ProtoMessage() {} +func (*RemoveShardCellResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{52} } -func (m *FindAllShardsInKeyspaceRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_FindAllShardsInKeyspaceRequest.Unmarshal(m, b) +func (m *RemoveShardCellResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_RemoveShardCellResponse.Unmarshal(m, b) } -func (m *FindAllShardsInKeyspaceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_FindAllShardsInKeyspaceRequest.Marshal(b, m, deterministic) +func (m *RemoveShardCellResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_RemoveShardCellResponse.Marshal(b, m, deterministic) } -func (m *FindAllShardsInKeyspaceRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_FindAllShardsInKeyspaceRequest.Merge(m, src) +func (m *RemoveShardCellResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_RemoveShardCellResponse.Merge(m, src) } -func (m *FindAllShardsInKeyspaceRequest) XXX_Size() int { - return xxx_messageInfo_FindAllShardsInKeyspaceRequest.Size(m) +func (m *RemoveShardCellResponse) XXX_Size() int { + return xxx_messageInfo_RemoveShardCellResponse.Size(m) } -func (m *FindAllShardsInKeyspaceRequest) XXX_DiscardUnknown() { - xxx_messageInfo_FindAllShardsInKeyspaceRequest.DiscardUnknown(m) +func (m *RemoveShardCellResponse) XXX_DiscardUnknown() { + xxx_messageInfo_RemoveShardCellResponse.DiscardUnknown(m) } -var xxx_messageInfo_FindAllShardsInKeyspaceRequest proto.InternalMessageInfo - -func (m *FindAllShardsInKeyspaceRequest) GetKeyspace() string { - if m != nil { - return m.Keyspace - } - return "" -} +var xxx_messageInfo_RemoveShardCellResponse proto.InternalMessageInfo -type FindAllShardsInKeyspaceResponse struct { - Shards map[string]*Shard `protobuf:"bytes,1,rep,name=shards,proto3" json:"shards,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +type ReparentTabletRequest struct { + // Tablet is the alias of the tablet that should be reparented under the + // current shard primary. + Tablet *topodata.TabletAlias `protobuf:"bytes,1,opt,name=tablet,proto3" json:"tablet,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *FindAllShardsInKeyspaceResponse) Reset() { *m = FindAllShardsInKeyspaceResponse{} } -func (m *FindAllShardsInKeyspaceResponse) String() string { return proto.CompactTextString(m) } -func (*FindAllShardsInKeyspaceResponse) ProtoMessage() {} -func (*FindAllShardsInKeyspaceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{44} +func (m *ReparentTabletRequest) Reset() { *m = ReparentTabletRequest{} } +func (m *ReparentTabletRequest) String() string { return proto.CompactTextString(m) } +func (*ReparentTabletRequest) ProtoMessage() {} +func (*ReparentTabletRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{53} } -func (m *FindAllShardsInKeyspaceResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_FindAllShardsInKeyspaceResponse.Unmarshal(m, b) +func (m *ReparentTabletRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ReparentTabletRequest.Unmarshal(m, b) } -func (m *FindAllShardsInKeyspaceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_FindAllShardsInKeyspaceResponse.Marshal(b, m, deterministic) +func (m *ReparentTabletRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ReparentTabletRequest.Marshal(b, m, deterministic) } -func (m *FindAllShardsInKeyspaceResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_FindAllShardsInKeyspaceResponse.Merge(m, src) +func (m *ReparentTabletRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ReparentTabletRequest.Merge(m, src) } -func (m *FindAllShardsInKeyspaceResponse) XXX_Size() int { - return xxx_messageInfo_FindAllShardsInKeyspaceResponse.Size(m) +func (m *ReparentTabletRequest) XXX_Size() int { + return xxx_messageInfo_ReparentTabletRequest.Size(m) } -func (m *FindAllShardsInKeyspaceResponse) XXX_DiscardUnknown() { - xxx_messageInfo_FindAllShardsInKeyspaceResponse.DiscardUnknown(m) +func (m *ReparentTabletRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ReparentTabletRequest.DiscardUnknown(m) } -var xxx_messageInfo_FindAllShardsInKeyspaceResponse proto.InternalMessageInfo +var xxx_messageInfo_ReparentTabletRequest proto.InternalMessageInfo -func (m *FindAllShardsInKeyspaceResponse) GetShards() map[string]*Shard { +func (m *ReparentTabletRequest) GetTablet() *topodata.TabletAlias { if m != nil { - return m.Shards + return m.Tablet } return nil } -type Shard struct { - Keyspace string `protobuf:"bytes,1,opt,name=keyspace,proto3" json:"keyspace,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - Shard *topodata.Shard `protobuf:"bytes,3,opt,name=shard,proto3" json:"shard,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +type ReparentTabletResponse struct { + // Keyspace is the name of the keyspace the tablet was reparented in. + Keyspace string `protobuf:"bytes,1,opt,name=keyspace,proto3" json:"keyspace,omitempty"` + // Shard is the name of the shard the tablet was reparented in. + Shard string `protobuf:"bytes,2,opt,name=shard,proto3" json:"shard,omitempty"` + // Primary is the alias of the tablet that the tablet was reparented under. + Primary *topodata.TabletAlias `protobuf:"bytes,3,opt,name=primary,proto3" json:"primary,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *Shard) Reset() { *m = Shard{} } -func (m *Shard) String() string { return proto.CompactTextString(m) } -func (*Shard) ProtoMessage() {} -func (*Shard) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{45} +func (m *ReparentTabletResponse) Reset() { *m = ReparentTabletResponse{} } +func (m *ReparentTabletResponse) String() string { return proto.CompactTextString(m) } +func (*ReparentTabletResponse) ProtoMessage() {} +func (*ReparentTabletResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{54} } -func (m *Shard) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Shard.Unmarshal(m, b) +func (m *ReparentTabletResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ReparentTabletResponse.Unmarshal(m, b) } -func (m *Shard) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Shard.Marshal(b, m, deterministic) +func (m *ReparentTabletResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ReparentTabletResponse.Marshal(b, m, deterministic) } -func (m *Shard) XXX_Merge(src proto.Message) { - xxx_messageInfo_Shard.Merge(m, src) +func (m *ReparentTabletResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ReparentTabletResponse.Merge(m, src) } -func (m *Shard) XXX_Size() int { - return xxx_messageInfo_Shard.Size(m) +func (m *ReparentTabletResponse) XXX_Size() int { + return xxx_messageInfo_ReparentTabletResponse.Size(m) } -func (m *Shard) XXX_DiscardUnknown() { - xxx_messageInfo_Shard.DiscardUnknown(m) +func (m *ReparentTabletResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ReparentTabletResponse.DiscardUnknown(m) } -var xxx_messageInfo_Shard proto.InternalMessageInfo +var xxx_messageInfo_ReparentTabletResponse proto.InternalMessageInfo -func (m *Shard) GetKeyspace() string { +func (m *ReparentTabletResponse) GetKeyspace() string { if m != nil { return m.Keyspace } return "" } -func (m *Shard) GetName() string { +func (m *ReparentTabletResponse) GetShard() string { if m != nil { - return m.Name + return m.Shard } return "" } -func (m *Shard) GetShard() *topodata.Shard { +func (m *ReparentTabletResponse) GetPrimary() *topodata.TabletAlias { if m != nil { - return m.Shard + return m.Primary } return nil } -// TableMaterializeSttings contains the settings for one table. -type TableMaterializeSettings struct { - TargetTable string `protobuf:"bytes,1,opt,name=target_table,json=targetTable,proto3" json:"target_table,omitempty"` - // source_expression is a select statement. - SourceExpression string `protobuf:"bytes,2,opt,name=source_expression,json=sourceExpression,proto3" json:"source_expression,omitempty"` - // create_ddl contains the DDL to create the target table. - // If empty, the target table must already exist. - // if "copy", the target table DDL is the same as the source table. - CreateDdl string `protobuf:"bytes,3,opt,name=create_ddl,json=createDdl,proto3" json:"create_ddl,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +type TabletExternallyReparentedRequest struct { + // Tablet is the alias of the tablet that was promoted externally and should + // be updated to the shard primary in the topo. + Tablet *topodata.TabletAlias `protobuf:"bytes,1,opt,name=tablet,proto3" json:"tablet,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *TableMaterializeSettings) Reset() { *m = TableMaterializeSettings{} } -func (m *TableMaterializeSettings) String() string { return proto.CompactTextString(m) } -func (*TableMaterializeSettings) ProtoMessage() {} -func (*TableMaterializeSettings) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{46} +func (m *TabletExternallyReparentedRequest) Reset() { *m = TabletExternallyReparentedRequest{} } +func (m *TabletExternallyReparentedRequest) String() string { return proto.CompactTextString(m) } +func (*TabletExternallyReparentedRequest) ProtoMessage() {} +func (*TabletExternallyReparentedRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{55} } -func (m *TableMaterializeSettings) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_TableMaterializeSettings.Unmarshal(m, b) -} -func (m *TableMaterializeSettings) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_TableMaterializeSettings.Marshal(b, m, deterministic) +func (m *TabletExternallyReparentedRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_TabletExternallyReparentedRequest.Unmarshal(m, b) } -func (m *TableMaterializeSettings) XXX_Merge(src proto.Message) { - xxx_messageInfo_TableMaterializeSettings.Merge(m, src) +func (m *TabletExternallyReparentedRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_TabletExternallyReparentedRequest.Marshal(b, m, deterministic) } -func (m *TableMaterializeSettings) XXX_Size() int { - return xxx_messageInfo_TableMaterializeSettings.Size(m) +func (m *TabletExternallyReparentedRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_TabletExternallyReparentedRequest.Merge(m, src) } -func (m *TableMaterializeSettings) XXX_DiscardUnknown() { - xxx_messageInfo_TableMaterializeSettings.DiscardUnknown(m) +func (m *TabletExternallyReparentedRequest) XXX_Size() int { + return xxx_messageInfo_TabletExternallyReparentedRequest.Size(m) } - -var xxx_messageInfo_TableMaterializeSettings proto.InternalMessageInfo - -func (m *TableMaterializeSettings) GetTargetTable() string { - if m != nil { - return m.TargetTable - } - return "" +func (m *TabletExternallyReparentedRequest) XXX_DiscardUnknown() { + xxx_messageInfo_TabletExternallyReparentedRequest.DiscardUnknown(m) } -func (m *TableMaterializeSettings) GetSourceExpression() string { - if m != nil { - return m.SourceExpression - } - return "" -} +var xxx_messageInfo_TabletExternallyReparentedRequest proto.InternalMessageInfo -func (m *TableMaterializeSettings) GetCreateDdl() string { +func (m *TabletExternallyReparentedRequest) GetTablet() *topodata.TabletAlias { if m != nil { - return m.CreateDdl + return m.Tablet } - return "" + return nil } -// MaterializeSettings contains the settings for the Materialize command. -type MaterializeSettings struct { - // workflow is the name of the workflow. - Workflow string `protobuf:"bytes,1,opt,name=workflow,proto3" json:"workflow,omitempty"` - SourceKeyspace string `protobuf:"bytes,2,opt,name=source_keyspace,json=sourceKeyspace,proto3" json:"source_keyspace,omitempty"` - TargetKeyspace string `protobuf:"bytes,3,opt,name=target_keyspace,json=targetKeyspace,proto3" json:"target_keyspace,omitempty"` - // stop_after_copy specifies if vreplication should be stopped after copying. - StopAfterCopy bool `protobuf:"varint,4,opt,name=stop_after_copy,json=stopAfterCopy,proto3" json:"stop_after_copy,omitempty"` - TableSettings []*TableMaterializeSettings `protobuf:"bytes,5,rep,name=table_settings,json=tableSettings,proto3" json:"table_settings,omitempty"` - // optional parameters. - Cell string `protobuf:"bytes,6,opt,name=cell,proto3" json:"cell,omitempty"` - TabletTypes string `protobuf:"bytes,7,opt,name=tablet_types,json=tabletTypes,proto3" json:"tablet_types,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +type TabletExternallyReparentedResponse struct { + Keyspace string `protobuf:"bytes,1,opt,name=keyspace,proto3" json:"keyspace,omitempty"` + Shard string `protobuf:"bytes,2,opt,name=shard,proto3" json:"shard,omitempty"` + NewPrimary *topodata.TabletAlias `protobuf:"bytes,3,opt,name=new_primary,json=newPrimary,proto3" json:"new_primary,omitempty"` + OldPrimary *topodata.TabletAlias `protobuf:"bytes,4,opt,name=old_primary,json=oldPrimary,proto3" json:"old_primary,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *MaterializeSettings) Reset() { *m = MaterializeSettings{} } -func (m *MaterializeSettings) String() string { return proto.CompactTextString(m) } -func (*MaterializeSettings) ProtoMessage() {} -func (*MaterializeSettings) Descriptor() ([]byte, []int) { - return fileDescriptor_f41247b323a1ab2e, []int{47} +func (m *TabletExternallyReparentedResponse) Reset() { *m = TabletExternallyReparentedResponse{} } +func (m *TabletExternallyReparentedResponse) String() string { return proto.CompactTextString(m) } +func (*TabletExternallyReparentedResponse) ProtoMessage() {} +func (*TabletExternallyReparentedResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f41247b323a1ab2e, []int{56} } -func (m *MaterializeSettings) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_MaterializeSettings.Unmarshal(m, b) +func (m *TabletExternallyReparentedResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_TabletExternallyReparentedResponse.Unmarshal(m, b) } -func (m *MaterializeSettings) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_MaterializeSettings.Marshal(b, m, deterministic) +func (m *TabletExternallyReparentedResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_TabletExternallyReparentedResponse.Marshal(b, m, deterministic) } -func (m *MaterializeSettings) XXX_Merge(src proto.Message) { - xxx_messageInfo_MaterializeSettings.Merge(m, src) +func (m *TabletExternallyReparentedResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_TabletExternallyReparentedResponse.Merge(m, src) } -func (m *MaterializeSettings) XXX_Size() int { - return xxx_messageInfo_MaterializeSettings.Size(m) +func (m *TabletExternallyReparentedResponse) XXX_Size() int { + return xxx_messageInfo_TabletExternallyReparentedResponse.Size(m) } -func (m *MaterializeSettings) XXX_DiscardUnknown() { - xxx_messageInfo_MaterializeSettings.DiscardUnknown(m) +func (m *TabletExternallyReparentedResponse) XXX_DiscardUnknown() { + xxx_messageInfo_TabletExternallyReparentedResponse.DiscardUnknown(m) } -var xxx_messageInfo_MaterializeSettings proto.InternalMessageInfo - -func (m *MaterializeSettings) GetWorkflow() string { - if m != nil { - return m.Workflow - } - return "" -} +var xxx_messageInfo_TabletExternallyReparentedResponse proto.InternalMessageInfo -func (m *MaterializeSettings) GetSourceKeyspace() string { +func (m *TabletExternallyReparentedResponse) GetKeyspace() string { if m != nil { - return m.SourceKeyspace + return m.Keyspace } return "" } -func (m *MaterializeSettings) GetTargetKeyspace() string { +func (m *TabletExternallyReparentedResponse) GetShard() string { if m != nil { - return m.TargetKeyspace + return m.Shard } return "" } -func (m *MaterializeSettings) GetStopAfterCopy() bool { - if m != nil { - return m.StopAfterCopy - } - return false -} - -func (m *MaterializeSettings) GetTableSettings() []*TableMaterializeSettings { +func (m *TabletExternallyReparentedResponse) GetNewPrimary() *topodata.TabletAlias { if m != nil { - return m.TableSettings + return m.NewPrimary } return nil } -func (m *MaterializeSettings) GetCell() string { - if m != nil { - return m.Cell - } - return "" -} - -func (m *MaterializeSettings) GetTabletTypes() string { +func (m *TabletExternallyReparentedResponse) GetOldPrimary() *topodata.TabletAlias { if m != nil { - return m.TabletTypes + return m.OldPrimary } - return "" + return nil } func init() { proto.RegisterType((*ExecuteVtctlCommandRequest)(nil), "vtctldata.ExecuteVtctlCommandRequest") proto.RegisterType((*ExecuteVtctlCommandResponse)(nil), "vtctldata.ExecuteVtctlCommandResponse") + proto.RegisterType((*TableMaterializeSettings)(nil), "vtctldata.TableMaterializeSettings") + proto.RegisterType((*MaterializeSettings)(nil), "vtctldata.MaterializeSettings") + proto.RegisterType((*Keyspace)(nil), "vtctldata.Keyspace") + proto.RegisterType((*Shard)(nil), "vtctldata.Shard") + proto.RegisterType((*Workflow)(nil), "vtctldata.Workflow") + proto.RegisterMapType((map[string]*Workflow_ShardStream)(nil), "vtctldata.Workflow.ShardStreamsEntry") + proto.RegisterType((*Workflow_ReplicationLocation)(nil), "vtctldata.Workflow.ReplicationLocation") + proto.RegisterType((*Workflow_ShardStream)(nil), "vtctldata.Workflow.ShardStream") + proto.RegisterType((*Workflow_Stream)(nil), "vtctldata.Workflow.Stream") + proto.RegisterType((*Workflow_Stream_CopyState)(nil), "vtctldata.Workflow.Stream.CopyState") proto.RegisterType((*ChangeTabletTypeRequest)(nil), "vtctldata.ChangeTabletTypeRequest") proto.RegisterType((*ChangeTabletTypeResponse)(nil), "vtctldata.ChangeTabletTypeResponse") proto.RegisterType((*CreateKeyspaceRequest)(nil), "vtctldata.CreateKeyspaceRequest") @@ -2319,6 +3127,11 @@ func init() { proto.RegisterType((*DeleteShardsResponse)(nil), "vtctldata.DeleteShardsResponse") proto.RegisterType((*DeleteTabletsRequest)(nil), "vtctldata.DeleteTabletsRequest") proto.RegisterType((*DeleteTabletsResponse)(nil), "vtctldata.DeleteTabletsResponse") + proto.RegisterType((*EmergencyReparentShardRequest)(nil), "vtctldata.EmergencyReparentShardRequest") + proto.RegisterType((*EmergencyReparentShardResponse)(nil), "vtctldata.EmergencyReparentShardResponse") + proto.RegisterType((*FindAllShardsInKeyspaceRequest)(nil), "vtctldata.FindAllShardsInKeyspaceRequest") + proto.RegisterType((*FindAllShardsInKeyspaceResponse)(nil), "vtctldata.FindAllShardsInKeyspaceResponse") + proto.RegisterMapType((map[string]*Shard)(nil), "vtctldata.FindAllShardsInKeyspaceResponse.ShardsEntry") proto.RegisterType((*GetBackupsRequest)(nil), "vtctldata.GetBackupsRequest") proto.RegisterType((*GetBackupsResponse)(nil), "vtctldata.GetBackupsResponse") proto.RegisterType((*GetCellInfoNamesRequest)(nil), "vtctldata.GetCellInfoNamesRequest") @@ -2344,128 +3157,171 @@ func init() { proto.RegisterType((*GetTabletsResponse)(nil), "vtctldata.GetTabletsResponse") proto.RegisterType((*GetVSchemaRequest)(nil), "vtctldata.GetVSchemaRequest") proto.RegisterType((*GetVSchemaResponse)(nil), "vtctldata.GetVSchemaResponse") + proto.RegisterType((*GetWorkflowsRequest)(nil), "vtctldata.GetWorkflowsRequest") + proto.RegisterType((*GetWorkflowsResponse)(nil), "vtctldata.GetWorkflowsResponse") proto.RegisterType((*RemoveKeyspaceCellRequest)(nil), "vtctldata.RemoveKeyspaceCellRequest") proto.RegisterType((*RemoveKeyspaceCellResponse)(nil), "vtctldata.RemoveKeyspaceCellResponse") proto.RegisterType((*RemoveShardCellRequest)(nil), "vtctldata.RemoveShardCellRequest") proto.RegisterType((*RemoveShardCellResponse)(nil), "vtctldata.RemoveShardCellResponse") - proto.RegisterType((*Keyspace)(nil), "vtctldata.Keyspace") - proto.RegisterType((*FindAllShardsInKeyspaceRequest)(nil), "vtctldata.FindAllShardsInKeyspaceRequest") - proto.RegisterType((*FindAllShardsInKeyspaceResponse)(nil), "vtctldata.FindAllShardsInKeyspaceResponse") - proto.RegisterMapType((map[string]*Shard)(nil), "vtctldata.FindAllShardsInKeyspaceResponse.ShardsEntry") - proto.RegisterType((*Shard)(nil), "vtctldata.Shard") - proto.RegisterType((*TableMaterializeSettings)(nil), "vtctldata.TableMaterializeSettings") - proto.RegisterType((*MaterializeSettings)(nil), "vtctldata.MaterializeSettings") + proto.RegisterType((*ReparentTabletRequest)(nil), "vtctldata.ReparentTabletRequest") + proto.RegisterType((*ReparentTabletResponse)(nil), "vtctldata.ReparentTabletResponse") + proto.RegisterType((*TabletExternallyReparentedRequest)(nil), "vtctldata.TabletExternallyReparentedRequest") + proto.RegisterType((*TabletExternallyReparentedResponse)(nil), "vtctldata.TabletExternallyReparentedResponse") } func init() { proto.RegisterFile("vtctldata.proto", fileDescriptor_f41247b323a1ab2e) } var fileDescriptor_f41247b323a1ab2e = []byte{ - // 1708 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0x4b, 0x6f, 0xdb, 0x56, - 0x16, 0x06, 0x25, 0x4b, 0x96, 0x8e, 0x1e, 0xb6, 0x69, 0xd9, 0x56, 0x34, 0x49, 0xc6, 0xa1, 0x27, - 0x8e, 0xe0, 0x99, 0x91, 0xf2, 0xc0, 0x0c, 0x82, 0x4c, 0x06, 0x88, 0x63, 0x3b, 0x81, 0xe3, 0x8c, - 0xc7, 0xa5, 0x0d, 0x17, 0x68, 0x81, 0x12, 0x34, 0x75, 0x25, 0x13, 0xa6, 0x48, 0x86, 0xf7, 0x8a, - 0x36, 0xb3, 0xe9, 0xa6, 0x5d, 0x14, 0xe8, 0x3f, 0xc8, 0xa6, 0xab, 0x2e, 0xbb, 0xcc, 0xb2, 0xbf, - 0xad, 0xb8, 0x2f, 0x92, 0xa2, 0x24, 0xe7, 0xd5, 0x95, 0x79, 0xcf, 0xe3, 0x9e, 0xef, 0xdc, 0xf3, - 0x94, 0x61, 0x21, 0x24, 0x16, 0x71, 0x7a, 0x26, 0x31, 0x3b, 0x7e, 0xe0, 0x11, 0x4f, 0x2d, 0xc7, - 0x84, 0x56, 0xcd, 0xf1, 0x06, 0x23, 0x62, 0x3b, 0x9c, 0xd3, 0xaa, 0x0f, 0x23, 0xfc, 0xc6, 0xb1, - 0x88, 0x3c, 0xaf, 0x11, 0xf3, 0xcc, 0x41, 0x64, 0x68, 0xba, 0xe6, 0x00, 0x05, 0xc9, 0x15, 0xad, - 0x3a, 0xf1, 0x7c, 0x2f, 0x75, 0xae, 0x85, 0xd8, 0x3a, 0x47, 0x43, 0x79, 0xac, 0x86, 0x84, 0xd8, - 0x43, 0xc4, 0x4f, 0xda, 0xd7, 0xd0, 0xda, 0xbb, 0x42, 0xd6, 0x88, 0xa0, 0x53, 0x6a, 0x78, 0xc7, - 0x1b, 0x0e, 0x4d, 0xb7, 0xa7, 0xa3, 0x37, 0x23, 0x84, 0x89, 0xaa, 0xc2, 0x9c, 0x19, 0x0c, 0x70, - 0x53, 0x59, 0xcf, 0xb7, 0xcb, 0x3a, 0xfb, 0x56, 0xef, 0x42, 0xdd, 0xb4, 0x88, 0xed, 0xb9, 0x06, - 0xbd, 0xc6, 0x1b, 0x91, 0x66, 0x6e, 0x5d, 0x69, 0xe7, 0xf5, 0x1a, 0xa7, 0x9e, 0x70, 0xa2, 0xb6, - 0x03, 0x7f, 0x99, 0x7a, 0x31, 0xf6, 0x3d, 0x17, 0x23, 0xf5, 0x6f, 0x50, 0x40, 0x21, 0x72, 0x49, - 0x53, 0x59, 0x57, 0xda, 0x95, 0x87, 0xf5, 0x8e, 0x74, 0x76, 0x8f, 0x52, 0x75, 0xce, 0xd4, 0xde, - 0x29, 0xb0, 0xb6, 0x73, 0x6e, 0xba, 0x03, 0x74, 0xc2, 0x9c, 0x3d, 0x89, 0x7c, 0x24, 0xb1, 0x3d, - 0x86, 0x2a, 0x7f, 0x01, 0xc3, 0x74, 0x6c, 0x13, 0x8b, 0x8b, 0x56, 0x3a, 0xb1, 0xf7, 0x5c, 0x65, - 0x9b, 0x32, 0xf5, 0x0a, 0x49, 0x0e, 0xea, 0x3f, 0x61, 0xbe, 0x77, 0x66, 0x90, 0xc8, 0x47, 0x0c, - 0x7a, 0xfd, 0x61, 0x23, 0xab, 0xc4, 0xec, 0x14, 0x7b, 0x67, 0xf4, 0xaf, 0xba, 0x06, 0xf3, 0xbd, - 0x20, 0x32, 0x82, 0x91, 0xdb, 0xcc, 0xaf, 0x2b, 0xed, 0x92, 0x5e, 0xec, 0x05, 0x91, 0x3e, 0x72, - 0xb5, 0x5f, 0x15, 0x68, 0x4e, 0xa2, 0x13, 0x0e, 0xfe, 0x0b, 0x6a, 0x67, 0xa8, 0xef, 0x05, 0xc8, - 0xe0, 0xa6, 0x05, 0xbe, 0xc5, 0xac, 0x29, 0xbd, 0xca, 0xc5, 0xf8, 0x49, 0x7d, 0x04, 0x55, 0xb3, - 0x4f, 0x50, 0x20, 0xb5, 0x72, 0x33, 0xb4, 0x2a, 0x4c, 0x4a, 0x28, 0xdd, 0x86, 0xca, 0xa5, 0x89, - 0x8d, 0x71, 0x94, 0xe5, 0x4b, 0x13, 0xef, 0x72, 0xa0, 0xef, 0xf3, 0xb0, 0xb2, 0x13, 0x20, 0x93, - 0xa0, 0x03, 0x14, 0x61, 0xdf, 0xb4, 0x50, 0x2a, 0xc0, 0xae, 0x39, 0x44, 0x0c, 0x5c, 0x59, 0x67, - 0xdf, 0x6a, 0x03, 0x0a, 0x7d, 0x2f, 0xb0, 0xf8, 0xe3, 0x94, 0x74, 0x7e, 0x50, 0xbb, 0xd0, 0x30, - 0x1d, 0xc7, 0xbb, 0x34, 0xd0, 0xd0, 0x27, 0x91, 0x11, 0x1a, 0x3c, 0xa9, 0x84, 0xb1, 0x25, 0xc6, - 0xdb, 0xa3, 0xac, 0xd3, 0x63, 0xc6, 0x50, 0xef, 0x43, 0x03, 0x9f, 0x9b, 0x41, 0xcf, 0x76, 0x07, - 0x86, 0xe5, 0x39, 0xa3, 0xa1, 0x6b, 0x30, 0x53, 0x73, 0xcc, 0x94, 0x2a, 0x79, 0x3b, 0x8c, 0x75, - 0x48, 0x0d, 0xbf, 0x9a, 0xd4, 0x60, 0x41, 0x2a, 0xb0, 0x20, 0x35, 0x93, 0x37, 0x90, 0x5e, 0xec, - 0xf7, 0xd8, 0x93, 0x67, 0xee, 0x62, 0x41, 0x7b, 0x06, 0x55, 0x8c, 0x82, 0x10, 0xf5, 0x8c, 0x7e, - 0xe0, 0x0d, 0x71, 0xb3, 0xb8, 0x9e, 0x6f, 0x57, 0x1e, 0xde, 0x9a, 0xbc, 0xa3, 0x73, 0xcc, 0xc4, - 0x5e, 0x04, 0xde, 0x50, 0xaf, 0xe0, 0xf8, 0x1b, 0xab, 0x5b, 0x30, 0xc7, 0xac, 0xcf, 0x33, 0xeb, - 0xab, 0x93, 0x9a, 0xcc, 0x36, 0x93, 0x51, 0x37, 0xa0, 0x76, 0x66, 0x62, 0x64, 0x5c, 0x08, 0x56, - 0xb3, 0xc4, 0x9c, 0xac, 0x52, 0xa2, 0x14, 0x57, 0x1f, 0x40, 0x0d, 0xbb, 0xa6, 0x8f, 0xcf, 0x3d, - 0xc2, 0x4a, 0xa7, 0x59, 0x66, 0xb1, 0xad, 0x76, 0x44, 0x41, 0xd2, 0xca, 0xd1, 0xab, 0x52, 0x84, - 0x9e, 0xb4, 0x7d, 0x58, 0xcd, 0xc6, 0x4d, 0xa4, 0x57, 0x17, 0x4a, 0xb1, 0x31, 0x9e, 0x59, 0xcb, - 0x9d, 0xa4, 0x97, 0xc4, 0xe2, 0xb1, 0x90, 0xf6, 0xb3, 0x02, 0x2a, 0xbf, 0xeb, 0x98, 0xbe, 0x96, - 0x4c, 0x80, 0x56, 0xe6, 0x9e, 0x72, 0xa2, 0xa2, 0xde, 0x02, 0x60, 0x2f, 0xcb, 0xe3, 0x96, 0x63, - 0xdc, 0x32, 0xa3, 0x1c, 0x8e, 0xe5, 0x49, 0x3e, 0x9d, 0x27, 0x77, 0xa1, 0x6e, 0xbb, 0x96, 0x33, - 0xea, 0x21, 0xc3, 0x37, 0x03, 0x5a, 0xe1, 0x73, 0x8c, 0x5d, 0x13, 0xd4, 0x23, 0x46, 0xd4, 0x7e, - 0x51, 0x60, 0x79, 0x0c, 0xce, 0x67, 0xfa, 0xa5, 0x6e, 0x42, 0x81, 0x41, 0x8a, 0x2b, 0x25, 0x91, - 0xe6, 0x37, 0x73, 0x76, 0x9c, 0x8e, 0x86, 0xe9, 0x04, 0xc8, 0xec, 0x45, 0x06, 0xba, 0xb2, 0x31, - 0xc1, 0x02, 0x3c, 0x4f, 0xa1, 0x6d, 0xce, 0xda, 0x63, 0x1c, 0xed, 0x2b, 0x58, 0xd9, 0x45, 0x0e, - 0x9a, 0x2c, 0x9a, 0xeb, 0xde, 0xec, 0x26, 0x94, 0x03, 0x64, 0x8d, 0x02, 0x6c, 0x87, 0xb2, 0x80, - 0x12, 0x82, 0xd6, 0x84, 0xd5, 0xec, 0x95, 0xdc, 0x6f, 0xed, 0x47, 0x05, 0x96, 0x39, 0x8b, 0xa1, - 0xc6, 0xd2, 0x56, 0x1b, 0x8a, 0x0c, 0x1a, 0xef, 0xc1, 0xd3, 0xfc, 0x13, 0xfc, 0xeb, 0x2d, 0xab, - 0x9b, 0xb0, 0x40, 0x5b, 0xaa, 0x61, 0xf7, 0x0d, 0x9a, 0xe4, 0xb6, 0x3b, 0x90, 0x71, 0xa1, 0xe4, - 0xfd, 0xfe, 0x31, 0x27, 0x6a, 0xab, 0xd0, 0x18, 0x87, 0x21, 0xf0, 0x45, 0x92, 0xce, 0x5b, 0x4e, - 0x8c, 0xef, 0x29, 0xd4, 0xd3, 0x5d, 0x18, 0x49, 0x9c, 0x33, 0xfa, 0x70, 0x2d, 0xd5, 0x87, 0x11, - 0xa6, 0x75, 0xc3, 0x9b, 0x8a, 0x1f, 0xd8, 0x43, 0x33, 0x88, 0x04, 0xee, 0x2a, 0x23, 0x1e, 0x71, - 0x9a, 0xb6, 0x26, 0xe3, 0x10, 0x9b, 0x16, 0x98, 0xf6, 0x60, 0xe9, 0x25, 0x22, 0xcf, 0x4d, 0xeb, - 0x62, 0xe4, 0xe3, 0x8f, 0x09, 0x4e, 0x23, 0x9d, 0x2b, 0x65, 0x91, 0x19, 0xda, 0x2e, 0xa8, 0xe9, - 0x6b, 0x44, 0x22, 0x76, 0x60, 0xfe, 0x8c, 0x93, 0x84, 0x47, 0x8d, 0x4e, 0x3c, 0x80, 0xb9, 0xec, - 0xbe, 0xdb, 0xf7, 0x74, 0x29, 0xa4, 0xdd, 0x80, 0xb5, 0x97, 0x88, 0xec, 0x20, 0xc7, 0xa1, 0x74, - 0x5a, 0x20, 0x12, 0x92, 0x76, 0x1f, 0x9a, 0x93, 0x2c, 0x61, 0xa6, 0x01, 0x05, 0x5a, 0x5d, 0x72, - 0xc4, 0xf2, 0x83, 0xd6, 0x66, 0x90, 0xa4, 0x46, 0xaa, 0x59, 0x5b, 0xc8, 0x71, 0x64, 0xb3, 0xa6, - 0xdf, 0xda, 0x0b, 0x58, 0x1e, 0x93, 0x8c, 0xcb, 0xa8, 0x4c, 0xd9, 0x86, 0xed, 0xf6, 0x3d, 0x51, - 0x47, 0x6a, 0x12, 0x91, 0x58, 0xbc, 0x64, 0x89, 0x2f, 0x9a, 0x99, 0xe2, 0x1e, 0x2c, 0x82, 0x23, - 0xd1, 0xbf, 0x57, 0x62, 0xcf, 0x12, 0x96, 0x30, 0xb3, 0x0f, 0xf3, 0xe3, 0x61, 0xef, 0xa6, 0xd2, - 0x73, 0x86, 0x52, 0x47, 0x9c, 0xf7, 0x5c, 0x12, 0x44, 0xba, 0xd4, 0x6f, 0x1d, 0x41, 0x35, 0xcd, - 0x50, 0x17, 0x21, 0x7f, 0x81, 0x22, 0xe1, 0x2b, 0xfd, 0x54, 0xb7, 0xa0, 0x10, 0x9a, 0xce, 0x08, - 0x89, 0x4a, 0x6f, 0x8c, 0xfb, 0xc3, 0xcd, 0xe8, 0x5c, 0xe4, 0x49, 0xee, 0xb1, 0xa2, 0xad, 0xb0, - 0xa7, 0x91, 0x95, 0x16, 0xfb, 0xb3, 0x0f, 0x8d, 0x71, 0xb2, 0xf0, 0xe5, 0x01, 0x94, 0x65, 0xa2, - 0x48, 0x6f, 0xa6, 0xb6, 0x9e, 0x44, 0x4a, 0xbb, 0xcf, 0xc2, 0xf4, 0x09, 0xed, 0x41, 0x84, 0xeb, - 0xcb, 0xbb, 0xf9, 0x0f, 0x39, 0x58, 0x7c, 0x89, 0x08, 0x1f, 0xb5, 0x5f, 0xbe, 0x11, 0xad, 0x42, - 0x91, 0x1d, 0x71, 0x33, 0xc7, 0xd2, 0x50, 0x9c, 0x68, 0x33, 0x47, 0x57, 0xbc, 0x99, 0x0b, 0x7e, - 0x9e, 0xf1, 0x6b, 0x82, 0x7a, 0xc2, 0xc5, 0x36, 0x40, 0x76, 0x77, 0x23, 0xb4, 0xd1, 0x25, 0x16, - 0xad, 0xa5, 0x2a, 0x88, 0xa7, 0x94, 0xa6, 0xb6, 0x61, 0x91, 0xdd, 0xc1, 0xa6, 0x09, 0x36, 0x3c, - 0xd7, 0x89, 0xd8, 0x64, 0x2f, 0xe9, 0xbc, 0x83, 0xb0, 0xba, 0xf8, 0xbf, 0xeb, 0x44, 0x89, 0x24, - 0xb6, 0xdf, 0x4a, 0xc9, 0x62, 0x4a, 0xf2, 0x98, 0x92, 0xa9, 0xa4, 0x76, 0xc4, 0x3a, 0x80, 0x7c, - 0x05, 0xf1, 0x98, 0xff, 0x81, 0xa2, 0xd8, 0x4d, 0xf8, 0x03, 0x6c, 0x74, 0x26, 0x37, 0x65, 0xae, - 0xb2, 0x8b, 0xfa, 0xb6, 0x6b, 0xd3, 0xad, 0x55, 0x17, 0x2a, 0xda, 0x6b, 0x58, 0xa0, 0x37, 0xfe, - 0x39, 0x23, 0x52, 0x7b, 0xc2, 0xa3, 0x34, 0x36, 0xe1, 0xe2, 0x81, 0xa5, 0x5c, 0x3b, 0xb0, 0xb4, - 0x2d, 0x96, 0xa7, 0xc7, 0x41, 0x78, 0x3a, 0x1e, 0xe5, 0x69, 0x5d, 0xe0, 0x10, 0x56, 0x32, 0xb2, - 0xf1, 0x16, 0x5a, 0xc5, 0x41, 0x98, 0x6c, 0x6b, 0x71, 0x72, 0x89, 0x9f, 0x04, 0x29, 0x15, 0xc0, - 0xf1, 0xb7, 0xf6, 0x9a, 0xe1, 0x16, 0xab, 0xe6, 0x97, 0x66, 0x97, 0xf6, 0x5f, 0x16, 0x25, 0x79, - 0x9b, 0x40, 0xd6, 0x16, 0x29, 0x37, 0x7b, 0x31, 0x16, 0x7c, 0xed, 0xdb, 0x94, 0xfa, 0xe7, 0xb7, - 0x79, 0x4a, 0xa5, 0x6f, 0x25, 0x53, 0x98, 0x1f, 0xb4, 0x67, 0xac, 0x84, 0x33, 0x93, 0x45, 0xdd, - 0x82, 0x79, 0x6e, 0x3c, 0x19, 0xbb, 0x59, 0x74, 0x52, 0x40, 0xeb, 0x32, 0x78, 0x99, 0x20, 0x5d, - 0xd7, 0x03, 0x9e, 0x33, 0x93, 0xd9, 0x48, 0xfd, 0x03, 0x4a, 0x99, 0x28, 0x2d, 0xc5, 0x51, 0x8a, - 0x1b, 0xc0, 0x7c, 0x28, 0x02, 0xf4, 0x3d, 0xdc, 0xd0, 0xd1, 0xd0, 0x0b, 0xe3, 0x45, 0x82, 0xb6, - 0xc0, 0x8f, 0x79, 0x1b, 0x99, 0x3d, 0xb9, 0x24, 0x7b, 0x66, 0x2c, 0x72, 0x63, 0xfb, 0xc4, 0x5c, - 0x76, 0x93, 0xb9, 0x09, 0xad, 0x69, 0x00, 0xc4, 0x64, 0x7e, 0xa7, 0xc0, 0x2a, 0x67, 0xb3, 0x94, - 0xfe, 0x58, 0x70, 0x1f, 0x58, 0x38, 0x25, 0xf6, 0xfc, 0x34, 0xec, 0x73, 0x33, 0xb1, 0x17, 0xb2, - 0xd8, 0x6f, 0xc0, 0xda, 0x04, 0x38, 0x01, 0xfc, 0x10, 0x4a, 0x07, 0xa9, 0xa7, 0x9a, 0xf8, 0x6d, - 0xd4, 0x49, 0xa1, 0xcf, 0x65, 0xc7, 0xea, 0x94, 0x3e, 0xfd, 0x14, 0x6e, 0xbf, 0xb0, 0xdd, 0xde, - 0xb6, 0xe3, 0xf0, 0x7d, 0x6a, 0xdf, 0xfd, 0x94, 0x69, 0xf1, 0xbb, 0x02, 0x7f, 0x9d, 0xa9, 0x2e, - 0xf2, 0xe6, 0x30, 0xb3, 0x20, 0xfe, 0x3b, 0xd5, 0x4f, 0x3e, 0xa0, 0xcb, 0xfb, 0x8d, 0x18, 0xc4, - 0xe2, 0x96, 0xd6, 0x01, 0x54, 0x52, 0xe4, 0x29, 0x63, 0x78, 0x73, 0x7c, 0x0c, 0x4f, 0xe9, 0x5f, - 0xc9, 0x08, 0xfe, 0x0e, 0x0a, 0x8c, 0xf6, 0xa1, 0x94, 0x4c, 0xc5, 0x9b, 0xbf, 0xf3, 0x5d, 0x59, - 0xc2, 0x79, 0x66, 0x64, 0x21, 0x79, 0xe4, 0xb1, 0x1e, 0xf9, 0x93, 0x02, 0x4d, 0x56, 0x8f, 0xff, - 0x33, 0x09, 0x0a, 0x6c, 0xd3, 0xb1, 0xdf, 0xa2, 0x63, 0x44, 0x88, 0xed, 0x0e, 0xb0, 0x7a, 0x87, - 0x36, 0xac, 0x60, 0x80, 0x08, 0x9f, 0x5d, 0xc2, 0x6e, 0x85, 0xd3, 0x98, 0x96, 0xfa, 0x77, 0x58, - 0xc2, 0xde, 0x28, 0xb0, 0x90, 0x81, 0xae, 0xfc, 0x00, 0x61, 0x6c, 0x7b, 0xae, 0xc0, 0xb1, 0xc8, - 0x19, 0x7b, 0x31, 0x9d, 0x66, 0xa7, 0xc5, 0x7e, 0xb1, 0x18, 0xbd, 0x9e, 0x4c, 0xc2, 0x32, 0xa7, - 0xec, 0xf6, 0x1c, 0xed, 0xb7, 0x1c, 0x2c, 0x4f, 0x83, 0xd1, 0x82, 0xd2, 0xa5, 0x17, 0x5c, 0xf4, - 0x1d, 0xef, 0x52, 0xba, 0x2e, 0xcf, 0xea, 0x3d, 0x58, 0x10, 0xf6, 0xc7, 0xb2, 0xaa, 0xac, 0xd7, - 0x39, 0x39, 0xce, 0xc5, 0x7b, 0xb0, 0x20, 0x7c, 0x89, 0x05, 0x39, 0x80, 0x3a, 0x27, 0x1f, 0x24, - 0x3f, 0x87, 0x16, 0x30, 0xf1, 0x7c, 0x83, 0xff, 0x13, 0xc1, 0xf2, 0xfc, 0x48, 0xee, 0xf9, 0x94, - 0xbc, 0x4d, 0xa9, 0x3b, 0x9e, 0x1f, 0xa9, 0xaf, 0xc4, 0xde, 0x6e, 0x60, 0x81, 0xb3, 0x59, 0x60, - 0xe9, 0xb3, 0x91, 0x0a, 0xe7, 0xac, 0x97, 0x15, 0x5b, 0x7c, 0xec, 0xa1, 0xac, 0xcb, 0x62, 0xaa, - 0x2e, 0xef, 0xc4, 0xd3, 0x82, 0xfe, 0x40, 0xc6, 0xec, 0x57, 0x74, 0x59, 0x8e, 0x05, 0xfa, 0xcb, - 0x19, 0x3f, 0x6f, 0x7f, 0xb3, 0x19, 0xda, 0x04, 0x61, 0xdc, 0xb1, 0xbd, 0x2e, 0xff, 0xea, 0x0e, - 0xbc, 0x6e, 0x48, 0xba, 0xec, 0x5f, 0x53, 0xdd, 0x18, 0xc8, 0x59, 0x91, 0x11, 0x1e, 0xfd, 0x11, - 0x00, 0x00, 0xff, 0xff, 0xc0, 0xb3, 0xd6, 0x9d, 0x2e, 0x13, 0x00, 0x00, + // 2404 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x59, 0x5b, 0x6f, 0x1b, 0xc7, + 0xf5, 0xc7, 0xf2, 0x26, 0xf2, 0x90, 0xa2, 0xe4, 0x11, 0x25, 0x6d, 0xf8, 0x8f, 0x2f, 0x59, 0xc7, + 0x8e, 0xfe, 0x6e, 0x4c, 0xda, 0x4a, 0x63, 0x04, 0x6e, 0xd2, 0xda, 0xd6, 0xc5, 0x90, 0xe3, 0xba, + 0xea, 0x4a, 0x75, 0x80, 0x16, 0xe8, 0x76, 0xb4, 0x3b, 0xa2, 0x17, 0x5a, 0xee, 0x32, 0x3b, 0x43, + 0x4a, 0x4c, 0x1f, 0xfa, 0xd2, 0x3e, 0x14, 0x28, 0xd0, 0x0f, 0x10, 0x14, 0xe8, 0x53, 0xd1, 0x4f, + 0x10, 0xa0, 0x40, 0xd1, 0xc7, 0x7e, 0x87, 0x7e, 0x9b, 0x62, 0xae, 0x5c, 0x5e, 0x2d, 0x2b, 0x7d, + 0xe2, 0xce, 0x99, 0x73, 0xe6, 0xfc, 0xe6, 0xdc, 0xe6, 0xcc, 0x10, 0x56, 0x06, 0xcc, 0x67, 0x51, + 0x80, 0x19, 0x6e, 0xf5, 0xd2, 0x84, 0x25, 0xa8, 0x62, 0x08, 0xcd, 0xd5, 0x93, 0x30, 0x8e, 0x92, + 0xce, 0x68, 0xb2, 0xb9, 0x1c, 0x25, 0x9d, 0x3e, 0x0b, 0x23, 0x35, 0xac, 0x77, 0x87, 0xf4, 0xeb, + 0xc8, 0x67, 0x7a, 0xbc, 0xc9, 0xf0, 0x49, 0x44, 0x58, 0x17, 0xc7, 0xb8, 0x43, 0xd2, 0x8c, 0x5c, + 0x9d, 0x25, 0xbd, 0x24, 0xbb, 0xce, 0x80, 0xfa, 0x6f, 0x48, 0x57, 0x0f, 0x6b, 0x03, 0xc6, 0xc2, + 0x2e, 0x91, 0x23, 0xe7, 0x2b, 0x68, 0xee, 0x5d, 0x10, 0xbf, 0xcf, 0xc8, 0x6b, 0x0e, 0x65, 0x27, + 0xe9, 0x76, 0x71, 0x1c, 0xb8, 0xe4, 0xeb, 0x3e, 0xa1, 0x0c, 0x21, 0x28, 0xe0, 0xb4, 0x43, 0x6d, + 0xeb, 0x56, 0x7e, 0xab, 0xe2, 0x8a, 0x6f, 0x74, 0x07, 0xea, 0xd8, 0x67, 0x61, 0x12, 0x7b, 0x7c, + 0x99, 0xa4, 0xcf, 0xec, 0xdc, 0x2d, 0x6b, 0x2b, 0xef, 0x2e, 0x4b, 0xea, 0xb1, 0x24, 0x3a, 0x3b, + 0xf0, 0x7f, 0x33, 0x17, 0xa6, 0xbd, 0x24, 0xa6, 0x04, 0x7d, 0x08, 0x45, 0x32, 0x20, 0x31, 0xb3, + 0xad, 0x5b, 0xd6, 0x56, 0x75, 0xbb, 0xde, 0xd2, 0x9b, 0xdd, 0xe3, 0x54, 0x57, 0x4e, 0x3a, 0x7f, + 0xb4, 0xc0, 0x3e, 0xe6, 0xdb, 0xfc, 0x29, 0x66, 0x24, 0x0d, 0x71, 0x14, 0x7e, 0x43, 0x8e, 0x08, + 0x63, 0x61, 0xdc, 0xa1, 0xe8, 0x03, 0xa8, 0x31, 0x9c, 0x76, 0x08, 0xf3, 0x84, 0x25, 0xc4, 0x4a, + 0x15, 0xb7, 0x2a, 0x69, 0x42, 0x0a, 0xfd, 0x00, 0xae, 0xd1, 0xa4, 0x9f, 0xfa, 0xc4, 0x23, 0x17, + 0xbd, 0x94, 0x50, 0x1a, 0x26, 0xb1, 0x80, 0x5b, 0x71, 0x57, 0xe5, 0xc4, 0x9e, 0xa1, 0xa3, 0xeb, + 0x00, 0x7e, 0x4a, 0x30, 0x23, 0x5e, 0x10, 0x44, 0x76, 0x5e, 0x70, 0x55, 0x24, 0x65, 0x37, 0x88, + 0x9c, 0xff, 0xe4, 0x60, 0x6d, 0x16, 0x8c, 0x26, 0x94, 0xcf, 0x93, 0xf4, 0xec, 0x34, 0x4a, 0xce, + 0x15, 0x04, 0x33, 0x46, 0x1f, 0xc1, 0x8a, 0xd2, 0x7f, 0x46, 0x86, 0xb4, 0x87, 0x7d, 0xa2, 0xb4, + 0xd7, 0x25, 0xf9, 0x4b, 0x45, 0xe5, 0x8c, 0x6a, 0x2f, 0x86, 0x51, 0x02, 0xa8, 0x4b, 0xb2, 0x61, + 0xbc, 0x0b, 0x2b, 0x94, 0x25, 0x3d, 0x0f, 0x9f, 0x32, 0x92, 0x7a, 0x7e, 0xd2, 0x1b, 0xda, 0x85, + 0x5b, 0xd6, 0x56, 0xd9, 0x5d, 0xe6, 0xe4, 0xa7, 0x9c, 0xba, 0x93, 0xf4, 0x86, 0xe8, 0x05, 0xd4, + 0x85, 0x55, 0x3c, 0xaa, 0x70, 0xda, 0xc5, 0x5b, 0xf9, 0xad, 0xea, 0xf6, 0xed, 0xd6, 0x28, 0x06, + 0xe7, 0x59, 0xd6, 0x5d, 0x16, 0xa2, 0x66, 0x87, 0x08, 0x0a, 0x3e, 0x89, 0x22, 0xbb, 0x24, 0x10, + 0x89, 0x6f, 0x69, 0x7c, 0x1e, 0x7f, 0x1e, 0x1b, 0xf6, 0x08, 0xb5, 0x97, 0xb4, 0xf1, 0x39, 0xed, + 0x98, 0x93, 0xd0, 0xff, 0xc3, 0x2a, 0xb9, 0x60, 0x24, 0x8d, 0x71, 0xe4, 0xf9, 0x51, 0x9f, 0x32, + 0x92, 0xda, 0x65, 0xc1, 0xb6, 0xa2, 0xe9, 0x3b, 0x92, 0xec, 0xbc, 0x82, 0xb2, 0xd9, 0x21, 0x82, + 0x42, 0x8c, 0xbb, 0xda, 0x9d, 0xe2, 0x1b, 0xb5, 0xa0, 0x3c, 0x66, 0xc0, 0xea, 0x36, 0x6a, 0x99, + 0x28, 0xd7, 0x92, 0xae, 0xe1, 0x71, 0x7e, 0x0d, 0xc5, 0xa3, 0x37, 0x38, 0x0d, 0xb8, 0x73, 0x8c, + 0xa0, 0x72, 0xce, 0xd9, 0xa4, 0xa2, 0x5c, 0x46, 0xd1, 0x1d, 0x28, 0x52, 0x2e, 0x28, 0xac, 0x5f, + 0xdd, 0x5e, 0x19, 0x69, 0x11, 0xeb, 0xb9, 0x72, 0xd6, 0xf9, 0x7b, 0x05, 0xca, 0x5f, 0x69, 0x27, + 0xcf, 0x02, 0xfc, 0x13, 0x28, 0x49, 0x0f, 0x2b, 0xb8, 0x1f, 0x65, 0xcc, 0xae, 0x05, 0x5b, 0x2e, + 0xe9, 0x45, 0xa1, 0x8f, 0x79, 0xd6, 0xbc, 0x4c, 0xe4, 0xaf, 0xab, 0xc4, 0xf8, 0x02, 0xd2, 0xf3, + 0x0a, 0xc9, 0xe5, 0x17, 0x90, 0x62, 0xe8, 0x21, 0xac, 0x77, 0xf1, 0x85, 0x37, 0xf0, 0xd2, 0x11, + 0x93, 0x17, 0xe1, 0x8e, 0x08, 0x97, 0xbc, 0x8b, 0xba, 0xf8, 0xe2, 0x75, 0x56, 0x1e, 0x77, 0xd0, + 0x0b, 0x58, 0x16, 0xdb, 0xf3, 0x28, 0x4b, 0x09, 0xee, 0xea, 0x90, 0xb9, 0x33, 0x4b, 0xb5, 0x30, + 0xc7, 0x91, 0xe4, 0xdb, 0x8b, 0x59, 0x3a, 0x74, 0x6b, 0x34, 0x43, 0x6a, 0xfe, 0x06, 0xae, 0x4d, + 0xb1, 0xa0, 0x55, 0xc8, 0x9f, 0x91, 0xa1, 0x32, 0x14, 0xff, 0x44, 0x9f, 0x42, 0x71, 0x80, 0xa3, + 0xbe, 0x36, 0xd3, 0xcd, 0xb7, 0xa8, 0x72, 0x25, 0xf7, 0xe3, 0xdc, 0x67, 0x56, 0xf3, 0x00, 0xd6, + 0x66, 0xec, 0x7f, 0xa1, 0xc7, 0x37, 0xa0, 0x24, 0x40, 0x52, 0x3b, 0x27, 0x0a, 0x9a, 0x1a, 0x35, + 0xff, 0x61, 0x41, 0x35, 0xa3, 0x05, 0xfd, 0x10, 0x96, 0xb4, 0x09, 0x2c, 0x61, 0x82, 0xe6, 0x4c, + 0x5c, 0x12, 0x92, 0x66, 0x45, 0xfb, 0x3c, 0x87, 0x45, 0x4a, 0xf8, 0x49, 0xcc, 0xd2, 0x24, 0x92, + 0x6a, 0xaa, 0xdb, 0xd7, 0x27, 0xa2, 0x48, 0x26, 0x1e, 0xdb, 0x91, 0x5c, 0xae, 0x4c, 0x54, 0x3d, + 0xa4, 0xe8, 0x63, 0x40, 0x21, 0xf5, 0x7a, 0x69, 0xd8, 0xc5, 0xe9, 0xd0, 0xa3, 0x24, 0x1d, 0x84, + 0x71, 0x47, 0x84, 0x41, 0xd9, 0x5d, 0x0d, 0xe9, 0xa1, 0x9c, 0x38, 0x92, 0xf4, 0xe6, 0x5f, 0x0a, + 0x50, 0x52, 0xb0, 0xeb, 0x90, 0x0b, 0x03, 0xb1, 0xe9, 0xbc, 0x9b, 0x0b, 0x03, 0xd4, 0xd0, 0xc1, + 0x2c, 0x23, 0x5c, 0x0e, 0xd0, 0x7d, 0x1e, 0x59, 0x5c, 0xa1, 0x8a, 0xac, 0xf5, 0x11, 0x3a, 0x89, + 0xeb, 0x69, 0x14, 0x62, 0xea, 0x2a, 0x26, 0xf4, 0x05, 0x2c, 0xcb, 0x93, 0xc9, 0x53, 0x01, 0x5d, + 0x10, 0x52, 0x76, 0x2b, 0x73, 0x5e, 0x3d, 0x13, 0x9f, 0x47, 0x62, 0xde, 0xad, 0x9d, 0x64, 0x46, + 0xdc, 0x1d, 0xbd, 0x84, 0x86, 0xdc, 0x35, 0x76, 0x51, 0xba, 0x43, 0x8f, 0xd1, 0x6d, 0x10, 0x45, + 0xcb, 0x33, 0x0c, 0xb2, 0xc0, 0xd4, 0x38, 0xf1, 0x50, 0x33, 0xf1, 0x4d, 0x30, 0xcc, 0x88, 0xaa, + 0x30, 0x72, 0x80, 0x36, 0x61, 0x29, 0x38, 0xf1, 0x44, 0xda, 0xc9, 0x92, 0x52, 0x0a, 0x4e, 0x5e, + 0xf1, 0xc4, 0x7b, 0x0a, 0xeb, 0x2c, 0xc5, 0x31, 0xcd, 0x1c, 0x51, 0x94, 0xe1, 0x6e, 0xcf, 0xae, + 0x08, 0xd8, 0xb5, 0x96, 0x3a, 0xfd, 0xf8, 0x31, 0xe5, 0x36, 0x32, 0xac, 0xc7, 0x9a, 0x13, 0xb5, + 0xa1, 0xc6, 0x59, 0xbc, 0x7e, 0x2f, 0xc0, 0x8c, 0x04, 0x36, 0xcc, 0x90, 0xac, 0xf2, 0xcf, 0x5f, + 0x48, 0x06, 0x64, 0xc3, 0x52, 0x97, 0x50, 0x8a, 0x3b, 0xc4, 0xae, 0x0a, 0x30, 0x7a, 0x88, 0xf6, + 0xa0, 0xca, 0x4b, 0xb4, 0x27, 0x40, 0x53, 0xbb, 0x26, 0xc2, 0xe1, 0xc3, 0xf9, 0xc1, 0xd4, 0xe2, + 0xb5, 0xfb, 0x88, 0x33, 0xbb, 0xe0, 0xeb, 0x4f, 0xda, 0x7c, 0x0c, 0x15, 0x33, 0xc1, 0x0d, 0x92, + 0x3d, 0xef, 0xe4, 0x80, 0x1b, 0x24, 0xc2, 0x94, 0x79, 0xbd, 0x33, 0xe5, 0xed, 0x12, 0x1f, 0x1e, + 0x9e, 0x39, 0xdf, 0x5a, 0xb0, 0xb9, 0xf3, 0x06, 0xc7, 0x1d, 0x72, 0x6c, 0x6a, 0xb3, 0x3e, 0xde, + 0x3f, 0x33, 0x45, 0x1c, 0x73, 0x9f, 0xab, 0xb3, 0x78, 0x4e, 0x40, 0xa8, 0xda, 0x2e, 0x06, 0xe8, + 0xbe, 0xb0, 0x3f, 0x2f, 0xfd, 0x42, 0x5d, 0x7d, 0xbb, 0x31, 0x29, 0x24, 0xf4, 0x94, 0x82, 0x13, + 0xfe, 0x2b, 0xdc, 0x95, 0x0e, 0xbd, 0xb4, 0x1f, 0xab, 0x38, 0x2e, 0x05, 0xe9, 0xd0, 0xed, 0xc7, + 0xce, 0xdf, 0x2c, 0xb0, 0xa7, 0xd1, 0xa9, 0x1e, 0xe1, 0x53, 0x58, 0x3e, 0x21, 0xa7, 0x49, 0x4a, + 0x3c, 0x15, 0xb0, 0x12, 0xdf, 0xea, 0xa4, 0x2a, 0xb7, 0x26, 0xd9, 0xe4, 0x08, 0x7d, 0x02, 0x35, + 0x79, 0x3a, 0x2a, 0xa9, 0xdc, 0x1c, 0xa9, 0xaa, 0xe0, 0x52, 0x42, 0x37, 0xa0, 0x7a, 0x8e, 0xa9, + 0x37, 0x8e, 0xb2, 0x72, 0x8e, 0xe9, 0xae, 0x04, 0xfa, 0x5d, 0x1e, 0xd6, 0x77, 0x44, 0x2f, 0x60, + 0x8e, 0x9b, 0x51, 0x8f, 0x34, 0x55, 0xfe, 0x1b, 0x50, 0x3c, 0x4d, 0x74, 0xf5, 0x2f, 0xbb, 0x72, + 0x80, 0xda, 0xd0, 0xc0, 0x51, 0x94, 0x9c, 0x7b, 0xa4, 0xdb, 0x63, 0x43, 0x6f, 0xe0, 0xc9, 0xbe, + 0x4c, 0x29, 0xbb, 0x26, 0xe6, 0xf6, 0xf8, 0xd4, 0xeb, 0x23, 0x31, 0x81, 0x1e, 0x40, 0x43, 0xe4, + 0x6c, 0x18, 0x77, 0x3c, 0x3f, 0x89, 0xfa, 0xdd, 0x58, 0x86, 0x7c, 0x41, 0xa8, 0x42, 0x7a, 0x6e, + 0x47, 0x4c, 0x89, 0xf0, 0x7f, 0x31, 0x2d, 0x21, 0x9c, 0x54, 0x14, 0x4e, 0xb2, 0xa7, 0x0f, 0xcd, + 0x83, 0x40, 0x98, 0x7c, 0x62, 0x2d, 0xe1, 0xb4, 0x27, 0x50, 0xe3, 0xc5, 0x87, 0x04, 0xde, 0x69, + 0x9a, 0x74, 0xa9, 0x5d, 0x9a, 0x2c, 0x66, 0x7a, 0x8d, 0xd6, 0x91, 0x60, 0xdb, 0x4f, 0x93, 0xae, + 0x5b, 0xa5, 0xe6, 0x9b, 0xa2, 0x7b, 0x50, 0x10, 0xda, 0x97, 0x84, 0xf6, 0x8d, 0x69, 0x49, 0xa1, + 0x5b, 0xf0, 0xf0, 0x62, 0x70, 0x82, 0x69, 0xa6, 0x51, 0x92, 0x79, 0x5d, 0xe3, 0x44, 0xd3, 0x1b, + 0x3c, 0x84, 0x65, 0x1a, 0xe3, 0x1e, 0x7d, 0x93, 0x30, 0x91, 0xda, 0x33, 0xb3, 0xba, 0xa6, 0x59, + 0xf8, 0xc8, 0x39, 0x80, 0x8d, 0x49, 0xbf, 0xa9, 0xf0, 0x6a, 0x4f, 0x9c, 0x14, 0xd5, 0xed, 0xb5, + 0x4c, 0x66, 0xce, 0xe8, 0x2a, 0xfe, 0x64, 0x01, 0x92, 0x6b, 0xc9, 0x66, 0x40, 0x05, 0xc0, 0xa2, + 0x13, 0xe7, 0x3a, 0x80, 0x3c, 0x52, 0x33, 0x9d, 0x46, 0x45, 0x50, 0x5e, 0x8d, 0xc5, 0x49, 0x3e, + 0x1b, 0x27, 0x77, 0xa0, 0x1e, 0xc6, 0x7e, 0xd4, 0x0f, 0x88, 0xd7, 0xc3, 0x29, 0x6f, 0x92, 0x55, + 0x8b, 0xa7, 0xa8, 0x87, 0x82, 0xe8, 0xfc, 0xd5, 0x82, 0xb5, 0x31, 0x38, 0x57, 0xdc, 0x17, 0xba, + 0x9b, 0x3d, 0x27, 0x78, 0xa6, 0x8c, 0xb8, 0xb3, 0x5d, 0x8f, 0x09, 0x47, 0x0f, 0x47, 0x29, 0xc1, + 0xc1, 0xd0, 0x23, 0x17, 0x21, 0x65, 0x54, 0x81, 0x97, 0x21, 0xf4, 0x54, 0x4e, 0xed, 0x89, 0x19, + 0xe7, 0xe7, 0xb0, 0xbe, 0x4b, 0x22, 0x32, 0x9d, 0x34, 0x8b, 0x6c, 0xf6, 0x3e, 0x54, 0x52, 0xe2, + 0xf7, 0x53, 0x1a, 0x0e, 0x74, 0x02, 0x8d, 0x08, 0x8e, 0x0d, 0x1b, 0x93, 0x4b, 0xca, 0x7d, 0x3b, + 0x7f, 0xb0, 0x60, 0x4d, 0x4e, 0x09, 0xd4, 0x54, 0xeb, 0xda, 0x32, 0xa7, 0xbe, 0x3c, 0xcc, 0xa7, + 0xf7, 0xa7, 0xe6, 0x17, 0x6b, 0xe6, 0xad, 0x37, 0xbf, 0x95, 0x78, 0xe1, 0xa9, 0x39, 0x94, 0x95, + 0x5f, 0x38, 0xf9, 0xe0, 0x54, 0x9d, 0xc8, 0xce, 0x06, 0x34, 0xc6, 0x61, 0x28, 0x7c, 0x43, 0x4d, + 0x97, 0x25, 0xc7, 0xe0, 0xfb, 0x5c, 0xb5, 0xea, 0xaa, 0x0a, 0x13, 0x8d, 0x73, 0x4e, 0x1d, 0x5e, + 0xce, 0xd4, 0x61, 0x42, 0x79, 0xde, 0xc8, 0xa2, 0xa2, 0x1a, 0x06, 0x85, 0xbb, 0x26, 0x88, 0xaa, + 0x57, 0x70, 0x36, 0xb5, 0x1f, 0x8c, 0x6a, 0x85, 0xe9, 0xcf, 0x39, 0xb8, 0xbe, 0xd7, 0x25, 0x69, + 0x87, 0xc4, 0xfe, 0xd0, 0x25, 0x32, 0xdc, 0x2e, 0x1d, 0xdd, 0xb3, 0x1b, 0x8c, 0x47, 0x50, 0x8d, + 0xc9, 0x08, 0xcf, 0xc2, 0x2e, 0x03, 0x62, 0xa2, 0x41, 0xa2, 0x1f, 0xc3, 0x4a, 0xd8, 0x89, 0x79, + 0xb9, 0x57, 0x2d, 0x2b, 0xb5, 0x0b, 0x8b, 0x0c, 0x51, 0x97, 0xdc, 0xaa, 0x09, 0xa4, 0x68, 0x17, + 0xd6, 0xcf, 0x71, 0xc8, 0x8c, 0xb4, 0xb9, 0x9f, 0x16, 0x4d, 0x58, 0x8b, 0x22, 0xb1, 0xdb, 0x4f, + 0x65, 0xab, 0xbc, 0xc6, 0xd9, 0xb5, 0xb8, 0xbe, 0xb7, 0xfe, 0xd3, 0x82, 0x1b, 0xf3, 0x2c, 0xa2, + 0x12, 0xec, 0xdd, 0x4d, 0xf2, 0x04, 0x56, 0x7b, 0x69, 0xd2, 0x4d, 0x18, 0x09, 0x2e, 0x67, 0x97, + 0x15, 0xcd, 0xae, 0x8d, 0x73, 0x17, 0x4a, 0xe2, 0x4a, 0xac, 0x6d, 0x32, 0x79, 0x61, 0x56, 0xb3, + 0xce, 0xe7, 0x70, 0x63, 0x3f, 0x8c, 0x83, 0xa7, 0x51, 0x24, 0xa3, 0xef, 0x20, 0x7e, 0x87, 0xd4, + 0x73, 0xfe, 0x65, 0xc1, 0xcd, 0xb9, 0xe2, 0x6a, 0xf7, 0xaf, 0x26, 0xd2, 0xe9, 0x51, 0x26, 0x9d, + 0xde, 0x22, 0x2b, 0xd3, 0x4d, 0xdd, 0x17, 0x74, 0xf3, 0xfd, 0xa5, 0xea, 0xbd, 0xe7, 0xde, 0x11, + 0xee, 0x8e, 0xdf, 0x11, 0x66, 0x94, 0x27, 0x73, 0x29, 0x70, 0xf6, 0xe0, 0xda, 0x73, 0xc2, 0x9e, + 0x61, 0xff, 0xac, 0xdf, 0xa3, 0x57, 0x0e, 0x61, 0x67, 0x17, 0x50, 0x76, 0x19, 0xb5, 0xf3, 0x16, + 0x2c, 0x9d, 0x48, 0x92, 0xda, 0x7a, 0xa3, 0x65, 0xde, 0x64, 0x24, 0xef, 0x41, 0x7c, 0x9a, 0xb8, + 0x9a, 0xc9, 0x79, 0x0f, 0x36, 0x9f, 0x13, 0xb6, 0x43, 0xa2, 0x88, 0xd3, 0x79, 0xc1, 0xd7, 0x90, + 0x9c, 0x07, 0x60, 0x4f, 0x4f, 0x29, 0x35, 0x0d, 0x28, 0xf2, 0xd3, 0x42, 0xbf, 0xba, 0xc8, 0x81, + 0xb3, 0x25, 0x20, 0x69, 0x89, 0x4c, 0xf3, 0x21, 0xae, 0xe6, 0xd6, 0xe8, 0x6a, 0xee, 0xec, 0xc3, + 0xda, 0x18, 0xa7, 0x39, 0x16, 0x2a, 0x7c, 0xda, 0x0b, 0xe3, 0xd3, 0x44, 0x9d, 0x0b, 0x99, 0x4b, + 0xb4, 0x61, 0x2f, 0xfb, 0xea, 0x8b, 0x57, 0x5a, 0xb5, 0x0e, 0x55, 0xc5, 0x46, 0xa3, 0xff, 0xce, + 0x32, 0x3b, 0x1b, 0x4d, 0x29, 0x35, 0x07, 0xb0, 0x34, 0x5e, 0xc6, 0xda, 0x19, 0x7f, 0xcd, 0x11, + 0x6a, 0xa9, 0xb1, 0x0c, 0x0c, 0x2d, 0xdf, 0x3c, 0x84, 0x5a, 0x76, 0x62, 0x46, 0x68, 0xdc, 0x1b, + 0x0f, 0x8d, 0xc6, 0xf8, 0x7e, 0xa4, 0x9a, 0x6c, 0x78, 0xac, 0x0b, 0xd3, 0xe8, 0xb0, 0x34, 0xfb, + 0x39, 0x80, 0xc6, 0x38, 0x59, 0xed, 0xe5, 0x21, 0x54, 0x74, 0xa0, 0xe8, 0xdd, 0xcc, 0x3c, 0x4a, + 0x47, 0x5c, 0xce, 0x03, 0xe1, 0xa6, 0x77, 0xc9, 0xb9, 0xfd, 0x31, 0x4c, 0x57, 0xef, 0x4e, 0x7e, + 0x9f, 0x83, 0xd5, 0xe7, 0x84, 0xc9, 0xd6, 0xf1, 0xfb, 0x77, 0xf8, 0x1b, 0xea, 0x9a, 0x68, 0xee, + 0xca, 0x72, 0xc4, 0x9b, 0x13, 0x72, 0x21, 0x9b, 0x13, 0x35, 0x9f, 0x17, 0xf3, 0xcb, 0x8a, 0x7a, + 0x2c, 0xd9, 0x6e, 0x83, 0xee, 0x56, 0xbc, 0x41, 0x48, 0xce, 0xa9, 0x3a, 0x2a, 0x6b, 0x8a, 0xf8, + 0x9a, 0xd3, 0xd0, 0x16, 0xac, 0xca, 0x47, 0x2a, 0x11, 0xe2, 0x5e, 0x12, 0x47, 0x43, 0x51, 0xac, + 0xcb, 0xea, 0x4e, 0x2c, 0xf2, 0xe2, 0x67, 0x71, 0x34, 0x1c, 0x71, 0xd2, 0xf0, 0x1b, 0xcd, 0x59, + 0xca, 0x70, 0x1e, 0x71, 0x32, 0xe7, 0x74, 0x0e, 0x45, 0x05, 0xd0, 0x56, 0x50, 0xc6, 0xfc, 0x11, + 0x94, 0x54, 0xaf, 0x2d, 0x0d, 0x70, 0xbb, 0x35, 0xfd, 0x78, 0x2a, 0x45, 0x76, 0xc9, 0x69, 0x18, + 0x87, 0xea, 0x29, 0x46, 0x50, 0x9c, 0x97, 0xb0, 0xc2, 0x57, 0xfc, 0xdf, 0xb4, 0x7c, 0xce, 0x63, + 0xe9, 0xa5, 0xb1, 0x03, 0xc5, 0x34, 0x60, 0xd6, 0xc2, 0x06, 0xcc, 0xb9, 0x27, 0xe2, 0xf4, 0x28, + 0x1d, 0xbc, 0x1e, 0xf7, 0xf2, 0xac, 0x2a, 0xf0, 0x0a, 0xd6, 0x27, 0x78, 0xcd, 0xad, 0xaa, 0x46, + 0xd3, 0xc1, 0xe8, 0xf6, 0x61, 0x82, 0x4b, 0xbd, 0x12, 0x67, 0x44, 0x80, 0x9a, 0x6f, 0xe7, 0xa5, + 0xc0, 0xad, 0xae, 0x4e, 0xdf, 0x37, 0xba, 0x9c, 0x2f, 0x84, 0x97, 0xf4, 0x6a, 0x0a, 0xd9, 0x96, + 0x79, 0x99, 0x98, 0x77, 0xd1, 0x53, 0xf3, 0xce, 0xaf, 0x32, 0xe2, 0x57, 0x2f, 0xf3, 0x9c, 0xca, + 0x6d, 0xa5, 0x43, 0x58, 0x0e, 0x9c, 0x27, 0x22, 0x85, 0x27, 0x3a, 0x25, 0x74, 0x0f, 0x96, 0xa4, + 0xf2, 0x51, 0x1b, 0x39, 0x89, 0x4e, 0x33, 0x38, 0x6d, 0x01, 0x6f, 0xc2, 0x49, 0x8b, 0x6a, 0xc0, + 0x33, 0xa1, 0x72, 0xd2, 0x53, 0x1f, 0x43, 0x79, 0xc2, 0x4b, 0xd7, 0x8c, 0x97, 0x4c, 0x01, 0x58, + 0x1a, 0x28, 0x07, 0xb9, 0xa2, 0x8e, 0xe8, 0x07, 0x85, 0x4b, 0x59, 0xe5, 0x26, 0x54, 0xb1, 0xcf, + 0xc2, 0x01, 0x91, 0x09, 0x25, 0x3b, 0x47, 0x90, 0x24, 0x91, 0x4c, 0xb2, 0x30, 0x66, 0xd6, 0x1c, + 0x15, 0x46, 0xfd, 0xc6, 0x3d, 0xab, 0x30, 0x6a, 0x01, 0x77, 0xc4, 0xe5, 0xfc, 0x0e, 0xde, 0x73, + 0x49, 0x37, 0x19, 0x98, 0xbe, 0x9d, 0x57, 0xe8, 0xcb, 0x80, 0xd4, 0xc1, 0x9d, 0xcb, 0xbc, 0x3e, + 0xcf, 0xbe, 0x37, 0x8d, 0xb5, 0xef, 0x85, 0xc9, 0x8b, 0xc3, 0xfb, 0xd0, 0x9c, 0x05, 0x40, 0x35, + 0xc2, 0xdf, 0x5a, 0xb0, 0x21, 0xa7, 0x45, 0xc6, 0x5d, 0x16, 0xdc, 0x5b, 0xee, 0x77, 0x1a, 0x7b, + 0x7e, 0x16, 0xf6, 0xc2, 0x5c, 0xec, 0xc5, 0x49, 0xec, 0xef, 0xc1, 0xe6, 0x14, 0x38, 0x05, 0x7c, + 0x1f, 0xd6, 0x75, 0x97, 0x3a, 0x9e, 0x9c, 0xf7, 0x27, 0xb2, 0x69, 0xf1, 0x3b, 0x9f, 0xf3, 0x5b, + 0xbe, 0xff, 0xf1, 0x75, 0xae, 0xdc, 0xee, 0xb6, 0x61, 0xe9, 0x52, 0x5d, 0xae, 0xe6, 0x72, 0x5c, + 0xf8, 0x40, 0xd2, 0xf7, 0xd4, 0x1f, 0x03, 0x91, 0x69, 0xbd, 0x49, 0x70, 0xc5, 0x0d, 0xfd, 0xdb, + 0x02, 0x67, 0xd1, 0xa2, 0x57, 0xde, 0xdd, 0x55, 0xef, 0x37, 0x8f, 0xa0, 0x9a, 0x44, 0xa3, 0xfe, + 0xbf, 0xb0, 0x50, 0x2e, 0x89, 0x74, 0xeb, 0xff, 0x6c, 0xeb, 0x97, 0x77, 0x07, 0x21, 0x23, 0x94, + 0xb6, 0xc2, 0xa4, 0x2d, 0xbf, 0xda, 0x9d, 0xa4, 0x3d, 0x60, 0x6d, 0xf1, 0x17, 0x5e, 0xdb, 0xe4, + 0xdd, 0x49, 0x49, 0x10, 0x3e, 0xf9, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb5, 0xf1, 0xb1, 0x1f, + 0x68, 0x1c, 0x00, 0x00, } diff --git a/go/vt/proto/vtctlservice/vtctlservice.pb.go b/go/vt/proto/vtctlservice/vtctlservice.pb.go index 1c40e8b0415..6ec0b007ca7 100644 --- a/go/vt/proto/vtctlservice/vtctlservice.pb.go +++ b/go/vt/proto/vtctlservice/vtctlservice.pb.go @@ -30,42 +30,43 @@ const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package func init() { proto.RegisterFile("vtctlservice.proto", fileDescriptor_27055cdbb1148d2b) } var fileDescriptor_27055cdbb1148d2b = []byte{ - // 553 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x95, 0x6d, 0x4f, 0x13, 0x41, - 0x10, 0xc7, 0xf5, 0x85, 0x44, 0x57, 0x04, 0x32, 0xbe, 0x30, 0x29, 0xb4, 0xd2, 0x2a, 0x26, 0x68, - 0xd2, 0x33, 0xf8, 0x09, 0xa0, 0x62, 0x25, 0x24, 0x24, 0x42, 0x83, 0x09, 0x09, 0x2f, 0x96, 0xbb, - 0x91, 0x5e, 0xbc, 0x27, 0x6e, 0xb7, 0x17, 0xf9, 0x10, 0x7e, 0x67, 0xd3, 0xdd, 0xee, 0x76, 0x6f, - 0x1f, 0x5a, 0xdf, 0xb5, 0xf3, 0xfb, 0xcf, 0x7f, 0x76, 0xee, 0x66, 0xf6, 0x08, 0x34, 0x3c, 0xe6, - 0x19, 0xc3, 0xba, 0x49, 0x63, 0x1c, 0x56, 0x75, 0xc9, 0x4b, 0xd8, 0x34, 0x63, 0x9d, 0x6d, 0xf1, - 0x2f, 0xa1, 0x9c, 0x4a, 0x7c, 0xf4, 0x40, 0x9e, 0x5d, 0xcf, 0x43, 0x30, 0x25, 0xaf, 0x4f, 0xff, - 0x60, 0x3c, 0xe3, 0x28, 0xfe, 0x8f, 0xca, 0x3c, 0xa7, 0x45, 0x02, 0x07, 0xc3, 0x65, 0x86, 0x87, - 0x5f, 0xe2, 0xc3, 0x0c, 0x19, 0xef, 0x7c, 0x58, 0x27, 0x63, 0x55, 0x59, 0x30, 0x1c, 0x3c, 0xf9, - 0xfc, 0xf4, 0xe8, 0xef, 0x16, 0xd9, 0x10, 0x30, 0x81, 0x5b, 0xb2, 0x33, 0x9a, 0xd2, 0xe2, 0x1e, - 0x27, 0xf4, 0x2e, 0x43, 0x3e, 0x79, 0xac, 0x10, 0x06, 0x86, 0x95, 0x0d, 0x55, 0xb9, 0x77, 0x2b, - 0x35, 0xaa, 0x16, 0xfc, 0x24, 0x5b, 0xa3, 0x1a, 0x29, 0xc7, 0x73, 0x7c, 0x64, 0x15, 0x8d, 0x11, - 0xf6, 0xcd, 0xc4, 0x16, 0x52, 0xd6, 0xfd, 0x15, 0x0a, 0x6d, 0x7c, 0x41, 0x5e, 0x4a, 0x76, 0x35, - 0xa5, 0x75, 0x02, 0x5d, 0x27, 0x47, 0xc4, 0x95, 0x65, 0x2f, 0x84, 0xcd, 0x83, 0x7e, 0xc5, 0x0c, - 0x03, 0x07, 0x6d, 0x23, 0xdf, 0x41, 0x6d, 0x85, 0x36, 0xfe, 0x41, 0x36, 0x25, 0x13, 0x15, 0x19, - 0xf4, 0x9c, 0x24, 0x09, 0x94, 0xe9, 0xdb, 0x20, 0xd7, 0x96, 0x13, 0xf2, 0x4a, 0x12, 0xf9, 0xc8, - 0x19, 0xb8, 0x39, 0x0b, 0xa2, 0x4c, 0xf7, 0xc3, 0x02, 0xed, 0x5a, 0x93, 0x37, 0xdf, 0xd2, 0x22, - 0x39, 0xce, 0x32, 0x59, 0xf0, 0xac, 0xd0, 0x8f, 0xe2, 0xd0, 0x48, 0x0f, 0x68, 0x54, 0xa5, 0x8f, - 0xff, 0x23, 0xd5, 0x35, 0xcf, 0x09, 0x19, 0x23, 0x3f, 0xa1, 0xf1, 0xef, 0x59, 0xc5, 0x60, 0xcf, - 0xc8, 0x5d, 0x86, 0x95, 0x73, 0x37, 0x40, 0xb5, 0xd9, 0x2d, 0xd9, 0x19, 0x23, 0x1f, 0x61, 0x96, - 0x9d, 0x15, 0xbf, 0xca, 0x0b, 0x9a, 0x23, 0x6b, 0x8d, 0xb2, 0x0d, 0x7d, 0xa3, 0xec, 0x6a, 0xcc, - 0x89, 0x33, 0x28, 0x74, 0xfd, 0x59, 0xbe, 0x89, 0x6b, 0x61, 0xed, 0x77, 0x43, 0xb6, 0x17, 0x80, - 0x1d, 0x67, 0x29, 0x65, 0xc8, 0xa0, 0xef, 0x26, 0x29, 0xa6, 0x7c, 0x07, 0xab, 0x24, 0xd6, 0x59, - 0xf5, 0xfb, 0xb3, 0xce, 0x6a, 0xbf, 0xb3, 0x5e, 0x08, 0x9b, 0x43, 0x6c, 0x80, 0xf6, 0x10, 0x9b, - 0xc0, 0x37, 0xc4, 0x6d, 0xae, 0x2d, 0xbf, 0x93, 0x17, 0x63, 0xe4, 0x57, 0xf1, 0x14, 0x73, 0x0a, - 0xbb, 0x6d, 0xbd, 0x8c, 0x2a, 0xb3, 0x3d, 0x3f, 0xd4, 0x4e, 0xa7, 0xe4, 0xf9, 0x3c, 0x2c, 0xee, - 0x81, 0x8e, 0xa5, 0x35, 0x2f, 0x81, 0x5d, 0x2f, 0x33, 0xb7, 0x6a, 0x1e, 0xad, 0x9b, 0xeb, 0xc5, - 0xa1, 0xac, 0x26, 0x96, 0xc4, 0xb7, 0x55, 0x96, 0xc0, 0x6a, 0x53, 0x6e, 0x9b, 0xdd, 0xa6, 0x8c, - 0x06, 0xda, 0x54, 0xd0, 0xda, 0x15, 0xb5, 0xf2, 0x5e, 0x75, 0x68, 0x57, 0xdc, 0x65, 0x97, 0x66, - 0xaa, 0x53, 0xcb, 0xcc, 0x6a, 0xb3, 0x1b, 0xa0, 0xda, 0x2c, 0x26, 0x70, 0x89, 0x79, 0xd9, 0xe8, - 0xeb, 0x6f, 0x3e, 0x95, 0xf0, 0xde, 0x48, 0x73, 0xb1, 0x32, 0x3f, 0x58, 0xa3, 0x32, 0xd7, 0x45, - 0x72, 0xf1, 0xde, 0x44, 0x85, 0xbe, 0x93, 0xab, 0x99, 0x6f, 0x5d, 0x1c, 0x89, 0xf2, 0x3e, 0xf9, - 0x74, 0x73, 0xd8, 0xa4, 0x1c, 0x19, 0x1b, 0xa6, 0x65, 0x24, 0x7f, 0x45, 0xf7, 0x65, 0xd4, 0xf0, - 0x48, 0x7c, 0xa2, 0x23, 0xf3, 0x03, 0x7e, 0xb7, 0x21, 0x62, 0x5f, 0xfe, 0x05, 0x00, 0x00, 0xff, - 0xff, 0x73, 0x69, 0xff, 0x16, 0xeb, 0x07, 0x00, 0x00, + // 570 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x96, 0x6f, 0x4f, 0xdb, 0x30, + 0x10, 0xc6, 0xb7, 0x17, 0x43, 0x9b, 0xc7, 0x00, 0x79, 0x2f, 0x26, 0x01, 0xed, 0x68, 0x37, 0x26, + 0xb1, 0x49, 0xcd, 0xc4, 0x3e, 0x01, 0x74, 0xac, 0x43, 0x48, 0x48, 0x83, 0x0a, 0x24, 0x24, 0x5e, + 0x98, 0xe4, 0xa0, 0x11, 0x4e, 0x1c, 0x62, 0x37, 0x1b, 0xdf, 0x76, 0x1f, 0x65, 0xaa, 0x5d, 0xbb, + 0x8e, 0xff, 0x94, 0xbd, 0x23, 0xf7, 0x7b, 0xee, 0x39, 0x5f, 0x72, 0x67, 0x8a, 0x70, 0x23, 0x52, + 0x41, 0x39, 0xd4, 0x4d, 0x9e, 0xc2, 0xa0, 0xaa, 0x99, 0x60, 0x78, 0xd5, 0x8e, 0x6d, 0xae, 0xcb, + 0xa7, 0x8c, 0x08, 0xa2, 0xf0, 0xfe, 0x03, 0x7a, 0x71, 0x31, 0x0b, 0xe1, 0x09, 0x7a, 0x7b, 0xf4, + 0x07, 0xd2, 0xa9, 0x00, 0xf9, 0x3c, 0x64, 0x45, 0x41, 0xca, 0x0c, 0xef, 0x0e, 0x16, 0x19, 0x01, + 0x7e, 0x06, 0x0f, 0x53, 0xe0, 0x62, 0xf3, 0xd3, 0x53, 0x32, 0x5e, 0xb1, 0x92, 0x43, 0xff, 0xd9, + 0xd7, 0xe7, 0xfb, 0x7f, 0xd7, 0xd0, 0x8a, 0x84, 0x19, 0xbe, 0x46, 0x1b, 0xc3, 0x09, 0x29, 0xef, + 0x60, 0x4c, 0x6e, 0x28, 0x88, 0xf1, 0x63, 0x05, 0xb8, 0x6f, 0x59, 0xb9, 0x50, 0x97, 0xfb, 0xb0, + 0x54, 0xa3, 0x6b, 0xe1, 0x4b, 0xb4, 0x36, 0xac, 0x81, 0x08, 0x38, 0x81, 0x47, 0x5e, 0x91, 0x14, + 0xf0, 0x8e, 0x9d, 0xd8, 0x42, 0xda, 0xba, 0xb7, 0x44, 0x61, 0x8c, 0x4f, 0xd1, 0x6b, 0xc5, 0xce, + 0x27, 0xa4, 0xce, 0x70, 0xc7, 0xcb, 0x91, 0x71, 0x6d, 0xd9, 0x8d, 0x61, 0xfb, 0xa0, 0xdf, 0x81, + 0x42, 0xe4, 0xa0, 0x6d, 0x14, 0x3a, 0xa8, 0xab, 0x30, 0xc6, 0xbf, 0xd0, 0xaa, 0x62, 0xb2, 0x22, + 0xc7, 0x5d, 0x2f, 0x49, 0x01, 0x6d, 0xfa, 0x3e, 0xca, 0x8d, 0xe5, 0x18, 0xbd, 0x51, 0x44, 0xbd, + 0x72, 0x8e, 0xfd, 0x9c, 0x39, 0xd1, 0xa6, 0x3b, 0x71, 0x81, 0x71, 0xad, 0xd1, 0xbb, 0x1f, 0x79, + 0x99, 0x1d, 0x50, 0xaa, 0x0a, 0x1e, 0x97, 0xe6, 0x55, 0xec, 0x59, 0xe9, 0x11, 0x8d, 0xae, 0xf4, + 0xf9, 0x7f, 0xa4, 0xa6, 0xe6, 0x09, 0x42, 0x23, 0x10, 0x87, 0x24, 0xbd, 0x9f, 0x56, 0x1c, 0x6f, + 0x5b, 0xb9, 0x8b, 0xb0, 0x76, 0xee, 0x44, 0xa8, 0x31, 0xbb, 0x46, 0x1b, 0x23, 0x10, 0x43, 0xa0, + 0xf4, 0xb8, 0xbc, 0x65, 0xa7, 0xa4, 0x00, 0xde, 0x1a, 0x65, 0x17, 0x86, 0x46, 0xd9, 0xd7, 0xd8, + 0x13, 0x67, 0x51, 0xdc, 0x09, 0x67, 0x85, 0x26, 0xae, 0x85, 0x8d, 0xdf, 0x15, 0x5a, 0x9f, 0x03, + 0x7e, 0x40, 0x73, 0xc2, 0x81, 0xe3, 0x9e, 0x9f, 0xa4, 0x99, 0xf6, 0xed, 0x2f, 0x93, 0x38, 0x67, + 0x35, 0xdf, 0xcf, 0x39, 0xab, 0xfb, 0xcd, 0xba, 0x31, 0x6c, 0x0f, 0xb1, 0x05, 0xda, 0x43, 0x6c, + 0x83, 0xd0, 0x10, 0xb7, 0xb9, 0xb1, 0xfc, 0x89, 0x5e, 0x8d, 0x40, 0x9c, 0xa7, 0x13, 0x28, 0x08, + 0xde, 0x6a, 0xeb, 0x55, 0x54, 0x9b, 0x6d, 0x87, 0xa1, 0x71, 0x3a, 0x42, 0x2f, 0x67, 0x61, 0x79, + 0x0f, 0x6c, 0x3a, 0x5a, 0xfb, 0x12, 0xd8, 0x0a, 0x32, 0x7b, 0xab, 0x66, 0xd1, 0xba, 0xb9, 0x98, + 0x1f, 0xca, 0x69, 0x62, 0x41, 0x42, 0x5b, 0xe5, 0x08, 0x9c, 0x36, 0xd5, 0xb6, 0xb9, 0x6d, 0xaa, + 0x68, 0xa4, 0x4d, 0x0d, 0x9d, 0x5d, 0xd1, 0x2b, 0x1f, 0x54, 0xc7, 0x76, 0xc5, 0x5f, 0x76, 0x65, + 0xa6, 0x3b, 0x75, 0xcc, 0x9c, 0x36, 0x3b, 0x11, 0xea, 0x4c, 0xc7, 0x25, 0xab, 0xef, 0x6f, 0x29, + 0xfb, 0xed, 0x4d, 0x87, 0x01, 0x91, 0xe9, 0xb0, 0xb8, 0xb1, 0x4c, 0x11, 0x3e, 0x83, 0x82, 0x35, + 0xe6, 0x46, 0x9d, 0x0d, 0x3a, 0xfe, 0x68, 0x25, 0xfa, 0x58, 0xdb, 0xef, 0x3e, 0xa1, 0xb2, 0x37, + 0x50, 0x71, 0x39, 0x0a, 0xb2, 0x42, 0xcf, 0xcb, 0x35, 0x2c, 0xb4, 0x81, 0x9e, 0x44, 0x7b, 0x1f, + 0x7e, 0xb9, 0xda, 0x6b, 0x72, 0x01, 0x9c, 0x0f, 0x72, 0x96, 0xa8, 0xbf, 0x92, 0x3b, 0x96, 0x34, + 0x22, 0x91, 0xff, 0xf5, 0x13, 0xfb, 0x37, 0xc1, 0xcd, 0x8a, 0x8c, 0x7d, 0xfb, 0x17, 0x00, 0x00, + 0xff, 0xff, 0xb0, 0xcb, 0xe1, 0x8e, 0x3e, 0x08, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -233,9 +234,8 @@ type VtctldClient interface { GetTablets(ctx context.Context, in *vtctldata.GetTabletsRequest, opts ...grpc.CallOption) (*vtctldata.GetTabletsResponse, error) // GetVSchema returns the vschema for a keyspace. GetVSchema(ctx context.Context, in *vtctldata.GetVSchemaRequest, opts ...grpc.CallOption) (*vtctldata.GetVSchemaResponse, error) - // RemoveKeyspaceCell removes the specified cell from the Cells list for all - // shards in the specified keyspace, as well as from the SrvKeyspace for that - // keyspace in that cell. + // GetWorkflows returns a list of workflows for the given keyspace. + GetWorkflows(ctx context.Context, in *vtctldata.GetWorkflowsRequest, opts ...grpc.CallOption) (*vtctldata.GetWorkflowsResponse, error) RemoveKeyspaceCell(ctx context.Context, in *vtctldata.RemoveKeyspaceCellRequest, opts ...grpc.CallOption) (*vtctldata.RemoveKeyspaceCellResponse, error) // RemoveShardCell removes the specified cell from the specified shard's Cells // list. @@ -421,6 +421,15 @@ func (c *vtctldClient) GetVSchema(ctx context.Context, in *vtctldata.GetVSchemaR return out, nil } +func (c *vtctldClient) GetWorkflows(ctx context.Context, in *vtctldata.GetWorkflowsRequest, opts ...grpc.CallOption) (*vtctldata.GetWorkflowsResponse, error) { + out := new(vtctldata.GetWorkflowsResponse) + err := c.cc.Invoke(ctx, "/vtctlservice.Vtctld/GetWorkflows", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *vtctldClient) RemoveKeyspaceCell(ctx context.Context, in *vtctldata.RemoveKeyspaceCellRequest, opts ...grpc.CallOption) (*vtctldata.RemoveKeyspaceCellResponse, error) { out := new(vtctldata.RemoveKeyspaceCellResponse) err := c.cc.Invoke(ctx, "/vtctlservice.Vtctld/RemoveKeyspaceCell", in, out, opts...) @@ -495,9 +504,8 @@ type VtctldServer interface { GetTablets(context.Context, *vtctldata.GetTabletsRequest) (*vtctldata.GetTabletsResponse, error) // GetVSchema returns the vschema for a keyspace. GetVSchema(context.Context, *vtctldata.GetVSchemaRequest) (*vtctldata.GetVSchemaResponse, error) - // RemoveKeyspaceCell removes the specified cell from the Cells list for all - // shards in the specified keyspace, as well as from the SrvKeyspace for that - // keyspace in that cell. + // GetWorkflows returns a list of workflows for the given keyspace. + GetWorkflows(context.Context, *vtctldata.GetWorkflowsRequest) (*vtctldata.GetWorkflowsResponse, error) RemoveKeyspaceCell(context.Context, *vtctldata.RemoveKeyspaceCellRequest) (*vtctldata.RemoveKeyspaceCellResponse, error) // RemoveShardCell removes the specified cell from the specified shard's Cells // list. @@ -565,6 +573,9 @@ func (*UnimplementedVtctldServer) GetTablets(ctx context.Context, req *vtctldata func (*UnimplementedVtctldServer) GetVSchema(ctx context.Context, req *vtctldata.GetVSchemaRequest) (*vtctldata.GetVSchemaResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetVSchema not implemented") } +func (*UnimplementedVtctldServer) GetWorkflows(ctx context.Context, req *vtctldata.GetWorkflowsRequest) (*vtctldata.GetWorkflowsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetWorkflows not implemented") +} func (*UnimplementedVtctldServer) RemoveKeyspaceCell(ctx context.Context, req *vtctldata.RemoveKeyspaceCellRequest) (*vtctldata.RemoveKeyspaceCellResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RemoveKeyspaceCell not implemented") } @@ -918,6 +929,24 @@ func _Vtctld_GetVSchema_Handler(srv interface{}, ctx context.Context, dec func(i return interceptor(ctx, in, info, handler) } +func _Vtctld_GetWorkflows_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(vtctldata.GetWorkflowsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(VtctldServer).GetWorkflows(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/vtctlservice.Vtctld/GetWorkflows", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(VtctldServer).GetWorkflows(ctx, req.(*vtctldata.GetWorkflowsRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Vtctld_RemoveKeyspaceCell_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(vtctldata.RemoveKeyspaceCellRequest) if err := dec(in); err != nil { @@ -1034,6 +1063,10 @@ var _Vtctld_serviceDesc = grpc.ServiceDesc{ MethodName: "GetVSchema", Handler: _Vtctld_GetVSchema_Handler, }, + { + MethodName: "GetWorkflows", + Handler: _Vtctld_GetWorkflows_Handler, + }, { MethodName: "RemoveKeyspaceCell", Handler: _Vtctld_RemoveKeyspaceCell_Handler, diff --git a/go/vt/proto/vttime/vttime.pb.go b/go/vt/proto/vttime/vttime.pb.go index 95c6f63de33..d3b4f7fb522 100644 --- a/go/vt/proto/vttime/vttime.pb.go +++ b/go/vt/proto/vttime/vttime.pb.go @@ -70,20 +70,69 @@ func (m *Time) GetNanoseconds() int32 { return 0 } +type Duration struct { + Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"` + Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Duration) Reset() { *m = Duration{} } +func (m *Duration) String() string { return proto.CompactTextString(m) } +func (*Duration) ProtoMessage() {} +func (*Duration) Descriptor() ([]byte, []int) { + return fileDescriptor_bbeb0d3434911dee, []int{1} +} + +func (m *Duration) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Duration.Unmarshal(m, b) +} +func (m *Duration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Duration.Marshal(b, m, deterministic) +} +func (m *Duration) XXX_Merge(src proto.Message) { + xxx_messageInfo_Duration.Merge(m, src) +} +func (m *Duration) XXX_Size() int { + return xxx_messageInfo_Duration.Size(m) +} +func (m *Duration) XXX_DiscardUnknown() { + xxx_messageInfo_Duration.DiscardUnknown(m) +} + +var xxx_messageInfo_Duration proto.InternalMessageInfo + +func (m *Duration) GetSeconds() int64 { + if m != nil { + return m.Seconds + } + return 0 +} + +func (m *Duration) GetNanos() int32 { + if m != nil { + return m.Nanos + } + return 0 +} + func init() { proto.RegisterType((*Time)(nil), "vttime.Time") + proto.RegisterType((*Duration)(nil), "vttime.Duration") } func init() { proto.RegisterFile("vttime.proto", fileDescriptor_bbeb0d3434911dee) } var fileDescriptor_bbeb0d3434911dee = []byte{ - // 120 bytes of a gzipped FileDescriptorProto + // 144 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0x2b, 0x29, 0xc9, 0xcc, 0x4d, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0xf0, 0x94, 0x9c, 0xb8, 0x58, 0x42, 0x32, 0x73, 0x53, 0x85, 0x24, 0xb8, 0xd8, 0x8b, 0x53, 0x93, 0xf3, 0xf3, 0x52, 0x8a, 0x25, 0x18, 0x15, 0x18, 0x35, 0x98, 0x83, 0x60, 0x5c, 0x21, 0x05, 0x2e, 0xee, 0xbc, 0xc4, 0xbc, 0x7c, - 0x98, 0x2c, 0x93, 0x02, 0xa3, 0x06, 0x6b, 0x10, 0xb2, 0x90, 0x93, 0x6a, 0x94, 0x72, 0x59, 0x66, - 0x49, 0x6a, 0x71, 0xb1, 0x5e, 0x66, 0xbe, 0x3e, 0x84, 0xa5, 0x9f, 0x9e, 0xaf, 0x5f, 0x56, 0xa2, - 0x0f, 0xb6, 0x4b, 0x1f, 0x62, 0x55, 0x12, 0x1b, 0x98, 0x67, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, - 0x35, 0x46, 0xf4, 0x16, 0x89, 0x00, 0x00, 0x00, + 0x98, 0x2c, 0x93, 0x02, 0xa3, 0x06, 0x6b, 0x10, 0xb2, 0x90, 0x92, 0x15, 0x17, 0x87, 0x4b, 0x69, + 0x51, 0x62, 0x49, 0x66, 0x7e, 0x1e, 0x1e, 0x73, 0x44, 0xb8, 0x58, 0xc1, 0x9a, 0xa0, 0x26, 0x40, + 0x38, 0x4e, 0xaa, 0x51, 0xca, 0x65, 0x99, 0x25, 0xa9, 0xc5, 0xc5, 0x7a, 0x99, 0xf9, 0xfa, 0x10, + 0x96, 0x7e, 0x7a, 0xbe, 0x7e, 0x59, 0x89, 0x3e, 0xd8, 0x9d, 0xfa, 0x10, 0x67, 0x26, 0xb1, 0x81, + 0x79, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0x24, 0xeb, 0xdd, 0xc5, 0x00, 0x00, 0x00, } diff --git a/go/vt/vtctl/grpcvtctldclient/client_gen.go b/go/vt/vtctl/grpcvtctldclient/client_gen.go index db3a1390f32..a36b5c13797 100644 --- a/go/vt/vtctl/grpcvtctldclient/client_gen.go +++ b/go/vt/vtctl/grpcvtctldclient/client_gen.go @@ -199,6 +199,15 @@ func (client *gRPCVtctldClient) GetVSchema(ctx context.Context, in *vtctldatapb. return client.c.GetVSchema(ctx, in, opts...) } +// GetWorkflows is part of the vtctlservicepb.VtctldClient interface. +func (client *gRPCVtctldClient) GetWorkflows(ctx context.Context, in *vtctldatapb.GetWorkflowsRequest, opts ...grpc.CallOption) (*vtctldatapb.GetWorkflowsResponse, error) { + if client.c == nil { + return nil, status.Error(codes.Unavailable, connClosedMsg) + } + + return client.c.GetWorkflows(ctx, in, opts...) +} + // RemoveKeyspaceCell is part of the vtctlservicepb.VtctldClient interface. func (client *gRPCVtctldClient) RemoveKeyspaceCell(ctx context.Context, in *vtctldatapb.RemoveKeyspaceCellRequest, opts ...grpc.CallOption) (*vtctldatapb.RemoveKeyspaceCellResponse, error) { if client.c == nil { diff --git a/go/vt/vtctl/grpcvtctldclient/client_test.go b/go/vt/vtctl/grpcvtctldclient/client_test.go deleted file mode 100644 index d0b9c374e48..00000000000 --- a/go/vt/vtctl/grpcvtctldclient/client_test.go +++ /dev/null @@ -1,169 +0,0 @@ -/* -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 grpcvtctldclient_test - -import ( - "context" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "golang.org/x/net/nettest" - "google.golang.org/grpc" - - "vitess.io/vitess/go/vt/topo" - "vitess.io/vitess/go/vt/topo/memorytopo" - "vitess.io/vitess/go/vt/vtctl/grpcvtctldserver" - "vitess.io/vitess/go/vt/vtctl/grpcvtctldserver/testutil" - "vitess.io/vitess/go/vt/vtctl/vtctldclient" - "vitess.io/vitess/go/vt/vttablet/tmclient" - - topodatapb "vitess.io/vitess/go/vt/proto/topodata" - vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" - vtctlservicepb "vitess.io/vitess/go/vt/proto/vtctlservice" -) - -func init() { - *tmclient.TabletManagerProtocol = testutil.TabletManagerClientProtocol -} - -// annoyingly, this is duplicated with theu tests in package grpcvtctldserver. -// fine for now, I suppose. -func addKeyspace(ctx context.Context, t *testing.T, ts *topo.Server, ks *vtctldatapb.Keyspace) { - in := *ks.Keyspace // take a copy to avoid the XXX_ fields changing - - err := ts.CreateKeyspace(ctx, ks.Name, &in) - require.NoError(t, err) -} - -func withTestServer( - t *testing.T, - server vtctlservicepb.VtctldServer, - test func(t *testing.T, client vtctldclient.VtctldClient), -) { - lis, err := nettest.NewLocalListener("tcp") - require.NoError(t, err, "cannot create nettest listener") - - defer lis.Close() - - s := grpc.NewServer() - vtctlservicepb.RegisterVtctldServer(s, server) - - go s.Serve(lis) - defer s.Stop() - - client, err := vtctldclient.New("grpc", lis.Addr().String()) - require.NoError(t, err, "cannot create vtctld client") - - test(t, client) -} - -func TestFindAllShardsInKeyspace(t *testing.T) { - ctx := context.Background() - ts := memorytopo.NewServer("cell1") - vtctld := grpcvtctldserver.NewVtctldServer(ts) - - withTestServer(t, vtctld, func(t *testing.T, client vtctldclient.VtctldClient) { - ks := &vtctldatapb.Keyspace{ - Name: "testkeyspace", - Keyspace: &topodatapb.Keyspace{}, - } - addKeyspace(ctx, t, ts, ks) - - si1, err := ts.GetOrCreateShard(ctx, ks.Name, "-80") - require.NoError(t, err) - si2, err := ts.GetOrCreateShard(ctx, ks.Name, "80-") - require.NoError(t, err) - - resp, err := client.FindAllShardsInKeyspace(ctx, &vtctldatapb.FindAllShardsInKeyspaceRequest{Keyspace: ks.Name}) - assert.NoError(t, err) - assert.NotNil(t, resp) - - expected := map[string]*vtctldatapb.Shard{ - "-80": { - Keyspace: ks.Name, - Name: "-80", - Shard: si1.Shard, - }, - "80-": { - Keyspace: ks.Name, - Name: "80-", - Shard: si2.Shard, - }, - } - - assert.Equal(t, expected, resp.Shards) - - client.Close() - _, err = client.FindAllShardsInKeyspace(ctx, &vtctldatapb.FindAllShardsInKeyspaceRequest{Keyspace: ks.Name}) - assert.Error(t, err) - }) -} - -func TestGetKeyspace(t *testing.T) { - ctx := context.Background() - - ts := memorytopo.NewServer("cell1") - vtctld := grpcvtctldserver.NewVtctldServer(ts) - - withTestServer(t, vtctld, func(t *testing.T, client vtctldclient.VtctldClient) { - expected := &vtctldatapb.GetKeyspaceResponse{ - Keyspace: &vtctldatapb.Keyspace{ - Name: "testkeyspace", - Keyspace: &topodatapb.Keyspace{ - ShardingColumnName: "col1", - }, - }, - } - addKeyspace(ctx, t, ts, expected.Keyspace) - - resp, err := client.GetKeyspace(ctx, &vtctldatapb.GetKeyspaceRequest{Keyspace: expected.Keyspace.Name}) - assert.NoError(t, err) - assert.Equal(t, expected, resp) - - client.Close() - _, err = client.GetKeyspace(ctx, &vtctldatapb.GetKeyspaceRequest{}) - assert.Error(t, err) - }) -} - -func TestGetKeyspaces(t *testing.T) { - ctx := context.Background() - - ts := memorytopo.NewServer("cell1") - vtctld := grpcvtctldserver.NewVtctldServer(ts) - - withTestServer(t, vtctld, func(t *testing.T, client vtctldclient.VtctldClient) { - resp, err := client.GetKeyspaces(ctx, &vtctldatapb.GetKeyspacesRequest{}) - assert.NoError(t, err) - assert.Empty(t, resp.Keyspaces) - - expected := &vtctldatapb.Keyspace{ - Name: "testkeyspace", - Keyspace: &topodatapb.Keyspace{}, - } - addKeyspace(ctx, t, ts, expected) - - resp, err = client.GetKeyspaces(ctx, &vtctldatapb.GetKeyspacesRequest{}) - assert.NoError(t, err) - assert.Equal(t, []*vtctldatapb.Keyspace{expected}, resp.Keyspaces) - - client.Close() - _, err = client.GetKeyspaces(ctx, &vtctldatapb.GetKeyspacesRequest{}) - assert.Error(t, err) - }) -} diff --git a/go/vt/vtctl/grpcvtctldserver/server.go b/go/vt/vtctl/grpcvtctldserver/server.go index 39f09fd66c5..8bfa475fade 100644 --- a/go/vt/vtctl/grpcvtctldserver/server.go +++ b/go/vt/vtctl/grpcvtctldserver/server.go @@ -30,6 +30,7 @@ import ( "vitess.io/vitess/go/vt/mysqlctl/mysqlctlproto" "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/topotools" + "vitess.io/vitess/go/vt/vtctl/workflow" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vttablet/tmclient" @@ -46,11 +47,18 @@ import ( type VtctldServer struct { ts *topo.Server tmc tmclient.TabletManagerClient + ws *workflow.Server } // NewVtctldServer returns a new VtctldServer for the given topo server. func NewVtctldServer(ts *topo.Server) *VtctldServer { - return &VtctldServer{ts: ts, tmc: tmclient.NewTabletManagerClient()} + tmc := tmclient.NewTabletManagerClient() + + return &VtctldServer{ + ts: ts, + tmc: tmc, + ws: workflow.NewServer(ts, tmc), + } } // ChangeTabletType is part of the vtctlservicepb.VtctldServer interface. @@ -610,6 +618,11 @@ func (s *VtctldServer) GetVSchema(ctx context.Context, req *vtctldatapb.GetVSche }, nil } +// GetWorkflows is part of the vtctlservicepb.VtctldServer interface. +func (s *VtctldServer) GetWorkflows(ctx context.Context, req *vtctldatapb.GetWorkflowsRequest) (*vtctldatapb.GetWorkflowsResponse, error) { + return s.ws.GetWorkflows(ctx, req) +} + // RemoveKeyspaceCell is part of the vtctlservicepb.VtctldServer interface. func (s *VtctldServer) RemoveKeyspaceCell(ctx context.Context, req *vtctldatapb.RemoveKeyspaceCellRequest) (*vtctldatapb.RemoveKeyspaceCellResponse, error) { shards, err := s.ts.GetShardNames(ctx, req.Keyspace) diff --git a/go/vt/vtctl/grpcvtctldserver/testutil/test_tmclient.go b/go/vt/vtctl/grpcvtctldserver/testutil/test_tmclient.go index 0fd14bd75ae..20aa3959e75 100644 --- a/go/vt/vtctl/grpcvtctldserver/testutil/test_tmclient.go +++ b/go/vt/vtctl/grpcvtctldserver/testutil/test_tmclient.go @@ -25,11 +25,13 @@ import ( "github.com/stretchr/testify/assert" + "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/topo/topoproto" "vitess.io/vitess/go/vt/topotools" "vitess.io/vitess/go/vt/vttablet/tmclient" + querypb "vitess.io/vitess/go/vt/proto/query" replicationdatapb "vitess.io/vitess/go/vt/proto/replicationdata" tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" topodatapb "vitess.io/vitess/go/vt/proto/topodata" @@ -181,6 +183,17 @@ type TabletManagerClient struct { Error error } // keyed by tablet alias. + UndoDemoteMasterDelays map[string]time.Duration + // keyed by tablet alias + UndoDemoteMasterResults map[string]error + // tablet alias => duration + VReplicationExecDelays map[string]time.Duration + // tablet alias => query string => result + VReplicationExecResults map[string]map[string]struct { + Result *querypb.QueryResult + Error error + } + // keyed by tablet alias. WaitForPositionDelays map[string]time.Duration // keyed by tablet alias. injects a sleep to the end of the function // regardless of parent context timeout or error result. @@ -188,10 +201,6 @@ type TabletManagerClient struct { // WaitForPosition(tablet *topodatapb.Tablet, position string) error, so we // key by tablet alias and then by position. WaitForPositionResults map[string]map[string]error - // keyed by tablet alias. - UndoDemoteMasterDelays map[string]time.Duration - // keyed by tablet alias - UndoDemoteMasterResults map[string]error } // ChangeType is part of the tmclient.TabletManagerClient interface. @@ -529,3 +538,48 @@ func (fake *TabletManagerClient) UndoDemoteMaster(ctx context.Context, tablet *t return assert.AnError } + +// VReplicationExec is part of the tmclient.TabletManagerCLient interface. +func (fake *TabletManagerClient) VReplicationExec(ctx context.Context, tablet *topodatapb.Tablet, query string) (*querypb.QueryResult, error) { + if fake.VReplicationExecResults == nil { + return nil, assert.AnError + } + + if tablet.Alias == nil { + return nil, assert.AnError + } + + key := topoproto.TabletAliasString(tablet.Alias) + + if fake.VReplicationExecDelays != nil { + if delay, ok := fake.VReplicationExecDelays[key]; ok { + select { + case <-ctx.Done(): + return nil, ctx.Err() + case <-time.After(delay): + // proceed to results + } + } + } + + if resultsForTablet, ok := fake.VReplicationExecResults[key]; ok { + // Round trip the expected query both to ensure it's valid and to + // standardize on capitalization and formatting. + stmt, err := sqlparser.Parse(query) + if err != nil { + return nil, err + } + + buf := sqlparser.NewTrackedBuffer(nil) + buf.Myprintf("%v", stmt) + + parsedQuery := buf.ParsedQuery().Query + + // Now do the map lookup. + if result, ok := resultsForTablet[parsedQuery]; ok { + return result.Result, result.Error + } + } + + return nil, assert.AnError +} diff --git a/go/vt/vtctl/workflow/doc.go b/go/vt/vtctl/workflow/doc.go new file mode 100644 index 00000000000..c334470320f --- /dev/null +++ b/go/vt/vtctl/workflow/doc.go @@ -0,0 +1,45 @@ +/* +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 workflow defines types and functions for working with Vitess workflows. + +This is still a very rough sketch, far from a final API, but I want to document +some things here as I go: + +(1) The lines between package workflow and package workflow/vexec are, uh, + blurry at best, and definitely need serious thinking and refinement. Maybe + there shouldn't even be two separate packages at all. The reason I have the + two packages right now is because I'm operating under the assumption that + there are workflows that are vexec, and then there are other workflows. If + it's true that all workflows are vexec workflows, then probably one single + package could make more sense. For now, two packages seems the way to go, + but like I said, the boundaries are blurry, and things that belong in one + package are in the other, because I haven't gone back and moved things + around. +(2) I'm aiming for this to be a drop-in replacement (more or less) for the + function calls in go/vt/wrangler. However, I'd rather define a better + abstraction if it means having to rewrite even significant portions of the + existing wrangler code to adapt to it, than make a subpar API in the name of + backwards compatibility. I'm not sure if that's a tradeoff I'll even need to + consider in the future, but I'm putting a stake in the ground on which side + of that tradeoff I intend to fall, should it come to it. +(3) Eventually we'll need to consider how the online schema migration workflows + fit into this. I'm trying to at least be somewhat abstract in the + vexec / queryplanner APIs to fit with the QueryParams thing that wrangler + uses, which _should_ work, but who knows?? Time will tell. +*/ +package workflow diff --git a/go/vt/vtctl/workflow/server.go b/go/vt/vtctl/workflow/server.go new file mode 100644 index 00000000000..86c02718d4f --- /dev/null +++ b/go/vt/vtctl/workflow/server.go @@ -0,0 +1,341 @@ +/* +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 workflow + +import ( + "context" + "errors" + "fmt" + "strings" + "time" + + "github.com/golang/protobuf/proto" + "k8s.io/apimachinery/pkg/util/sets" + + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/vt/topo" + "vitess.io/vitess/go/vt/vtctl/workflow/vexec" + "vitess.io/vitess/go/vt/vtgate/evalengine" + "vitess.io/vitess/go/vt/vttablet/tmclient" + + binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" + vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" + "vitess.io/vitess/go/vt/proto/vttime" +) + +var ( + // ErrInvalidWorkflow is a catchall error type for conditions that should be + // impossible when operating on a workflow. + ErrInvalidWorkflow = errors.New("invalid workflow") + // ErrMultipleSourceKeyspaces occurs when a workflow somehow has multiple + // source keyspaces across different shard primaries. This should be + // impossible. + ErrMultipleSourceKeyspaces = errors.New("multiple source keyspaces for a single workflow") + // ErrMultipleTargetKeyspaces occurs when a workflow somehow has multiple + // target keyspaces across different shard primaries. This should be + // impossible. + ErrMultipleTargetKeyspaces = errors.New("multiple target keyspaces for a single workflow") +) + +// Server provides an API to work with Vitess workflows, like vreplication +// workflows (MoveTables, Reshard, etc) and schema migration workflows. +// +// NB: This is in alpha, and you probably don't want to depend on it (yet!). +// Currently, it provides only a read-only API to vreplication workflows. Write +// actions on vreplication workflows, and schema migration workflows entirely, +// are not yet supported, but planned. +type Server struct { + ts *topo.Server + tmc tmclient.TabletManagerClient +} + +// NewServer returns a new server instance with the given topo.Server and +// TabletManagerClient. +func NewServer(ts *topo.Server, tmc tmclient.TabletManagerClient) *Server { + return &Server{ + ts: ts, + tmc: tmc, + } +} + +// GetWorkflows returns a list of all workflows that exist in a given keyspace, +// with some additional filtering depending on the request parameters (for +// example, ActiveOnly=true restricts the search to only workflows that are +// currently running). +// +// It has the same signature as the vtctlservicepb.VtctldServer's GetWorkflows +// rpc, and grpcvtctldserver delegates to this function. +func (s *Server) GetWorkflows(ctx context.Context, req *vtctldatapb.GetWorkflowsRequest) (*vtctldatapb.GetWorkflowsResponse, error) { + where := "" + if req.ActiveOnly { + where = "WHERE state <> 'Stopped'" + } + + query := fmt.Sprintf(` + SELECT + id, + workflow, + source, + pos, + stop_pos, + max_replication_lag, + state, + db_name, + time_updated, + transaction_timestamp, + message + FROM + _vt.vreplication + %s`, + where, + ) + + vx := vexec.NewVExec(req.Keyspace, "", s.ts, s.tmc) + results, err := vx.QueryContext(ctx, query) + if err != nil { + return nil, err + } + + workflowsMap := make(map[string]*vtctldatapb.Workflow, len(results)) + sourceKeyspaceByWorkflow := make(map[string]string, len(results)) + sourceShardsByWorkflow := make(map[string]sets.String, len(results)) + targetKeyspaceByWorkflow := make(map[string]string, len(results)) + targetShardsByWorkflow := make(map[string]sets.String, len(results)) + maxVReplicationLagByWorkflow := make(map[string]float64, len(results)) + + // We guarantee the following invariants when this function is called for a + // given workflow: + // - workflow.Name != "" (more precisely, ".Name is set 'properly'") + // - workflowsMap[workflow.Name] == workflow + // - sourceShardsByWorkflow[workflow.Name] != nil + // - targetShardsByWorkflow[workflow.Name] != nil + // - workflow.ShardStatuses != nil + scanWorkflow := func(ctx context.Context, workflow *vtctldatapb.Workflow, row []sqltypes.Value, tablet *topo.TabletInfo) error { + id, err := evalengine.ToInt64(row[0]) + if err != nil { + return err + } + + var bls binlogdatapb.BinlogSource + if err := proto.UnmarshalText(row[2].ToString(), &bls); err != nil { + return err + } + + pos := row[3].ToString() + stopPos := row[4].ToString() + state := row[6].ToString() + dbName := row[7].ToString() + + timeUpdatedSeconds, err := evalengine.ToInt64(row[8]) + if err != nil { + return err + } + + transactionTimeSeconds, err := evalengine.ToInt64(row[9]) + if err != nil { + return err + } + + message := row[10].ToString() + + stream := &vtctldatapb.Workflow_Stream{ + Id: id, + Shard: tablet.Shard, + Tablet: tablet.Alias, + BinlogSource: &bls, + Position: pos, + StopPosition: stopPos, + State: state, + DbName: dbName, + TransactionTimestamp: &vttime.Time{ + Seconds: transactionTimeSeconds, + }, + TimeUpdated: &vttime.Time{ + Seconds: timeUpdatedSeconds, + }, + Message: message, + } + + stream.CopyStates, err = s.getWorkflowCopyStates(ctx, tablet, id) + if err != nil { + return err + } + + switch { + case strings.Contains(strings.ToLower(stream.Message), "error"): + stream.State = "Error" + case stream.State == "Running" && len(stream.CopyStates) > 0: + stream.State = "Copying" + case stream.State == "Running" && int64(time.Now().Second())-timeUpdatedSeconds > 10: + stream.State = "Lagging" + } + + shardStreamKey := fmt.Sprintf("%s/%s", tablet.Shard, tablet.AliasString()) + shardStream, ok := workflow.ShardStreams[shardStreamKey] + if !ok { + ctx, cancel := context.WithTimeout(ctx, *topo.RemoteOperationTimeout) + defer cancel() + + si, err := s.ts.GetShard(ctx, req.Keyspace, tablet.Shard) + if err != nil { + return err + } + + shardStream = &vtctldatapb.Workflow_ShardStream{ + Streams: nil, + TabletControls: si.TabletControls, + IsPrimaryServing: si.IsMasterServing, + } + + workflow.ShardStreams[shardStreamKey] = shardStream + } + + shardStream.Streams = append(shardStream.Streams, stream) + sourceShardsByWorkflow[workflow.Name].Insert(stream.BinlogSource.Shard) + targetShardsByWorkflow[workflow.Name].Insert(tablet.Shard) + + if ks, ok := sourceKeyspaceByWorkflow[workflow.Name]; ok && ks != stream.BinlogSource.Keyspace { + return fmt.Errorf("%w: workflow = %v, ks1 = %v, ks2 = %v", ErrMultipleSourceKeyspaces, workflow.Name, ks, stream.BinlogSource.Keyspace) + } + + sourceKeyspaceByWorkflow[workflow.Name] = stream.BinlogSource.Keyspace + + if ks, ok := targetKeyspaceByWorkflow[workflow.Name]; ok && ks != tablet.Keyspace { + return fmt.Errorf("%w: workflow = %v, ks1 = %v, ks2 = %v", ErrMultipleTargetKeyspaces, workflow.Name, ks, tablet.Keyspace) + } + + targetKeyspaceByWorkflow[workflow.Name] = tablet.Keyspace + + timeUpdated := time.Unix(timeUpdatedSeconds, 0) + vreplicationLag := time.Since(timeUpdated) + + if currentMaxLag, ok := maxVReplicationLagByWorkflow[workflow.Name]; ok { + if vreplicationLag.Seconds() > currentMaxLag { + maxVReplicationLagByWorkflow[workflow.Name] = vreplicationLag.Seconds() + } + } else { + maxVReplicationLagByWorkflow[workflow.Name] = vreplicationLag.Seconds() + } + + return nil + } + + for tablet, result := range results { + qr := sqltypes.Proto3ToResult(result) + + // In the old implementation, we knew we had at most one (0 <= N <= 1) + // workflow for each shard primary we queried. There might be multiple + // rows (streams) comprising that workflow, so we would aggregate the + // rows for a given primary into a single value ("the workflow", + // ReplicationStatusResult in the old types). + // + // In this version, we have many (N >= 0) workflows for each shard + // primary we queried, so we need to determine if each row corresponds + // to a workflow we're already aggregating, or if it's a workflow we + // haven't seen yet for that shard primary. We use the workflow name to + // dedupe for this. + for _, row := range qr.Rows { + workflowName := row[1].ToString() + workflow, ok := workflowsMap[workflowName] + if !ok { + workflow = &vtctldatapb.Workflow{ + Name: workflowName, + ShardStreams: map[string]*vtctldatapb.Workflow_ShardStream{}, + } + + workflowsMap[workflowName] = workflow + sourceShardsByWorkflow[workflowName] = sets.NewString() + targetShardsByWorkflow[workflowName] = sets.NewString() + } + + if err := scanWorkflow(ctx, workflow, row, tablet); err != nil { + return nil, err + } + } + } + + workflows := make([]*vtctldatapb.Workflow, 0, len(workflowsMap)) + + for name, workflow := range workflowsMap { + sourceShards, ok := sourceShardsByWorkflow[name] + if !ok { + return nil, fmt.Errorf("%w: %s has no source shards", ErrInvalidWorkflow, name) + } + + sourceKeyspace, ok := sourceKeyspaceByWorkflow[name] + if !ok { + return nil, fmt.Errorf("%w: %s has no source keyspace", ErrInvalidWorkflow, name) + } + + targetShards, ok := targetShardsByWorkflow[name] + if !ok { + return nil, fmt.Errorf("%w: %s has no target shards", ErrInvalidWorkflow, name) + } + + targetKeyspace, ok := targetKeyspaceByWorkflow[name] + if !ok { + return nil, fmt.Errorf("%w: %s has no target keyspace", ErrInvalidWorkflow, name) + } + + maxVReplicationLag, ok := maxVReplicationLagByWorkflow[name] + if !ok { + return nil, fmt.Errorf("%w: %s has no tracked vreplication lag", ErrInvalidWorkflow, name) + } + + workflow.Source = &vtctldatapb.Workflow_ReplicationLocation{ + Keyspace: sourceKeyspace, + Shards: sourceShards.List(), + } + + workflow.Target = &vtctldatapb.Workflow_ReplicationLocation{ + Keyspace: targetKeyspace, + Shards: targetShards.List(), + } + + workflow.MaxVReplicationLag = int64(maxVReplicationLag) + + workflows = append(workflows, workflow) + } + + return &vtctldatapb.GetWorkflowsResponse{ + Workflows: workflows, + }, nil +} + +func (s *Server) getWorkflowCopyStates(ctx context.Context, tablet *topo.TabletInfo, id int64) ([]*vtctldatapb.Workflow_Stream_CopyState, error) { + query := fmt.Sprintf("select table_name, lastpk from _vt.copy_state where vrepl_id = %d", id) + qr, err := s.tmc.VReplicationExec(ctx, tablet.Tablet, query) + if err != nil { + return nil, err + } + + result := sqltypes.Proto3ToResult(qr) + if result == nil { + return nil, nil + } + + copyStates := make([]*vtctldatapb.Workflow_Stream_CopyState, len(result.Rows)) + for i, row := range result.Rows { + // These fields are technically varbinary, but this is close enough. + copyStates[i] = &vtctldatapb.Workflow_Stream_CopyState{ + Table: row[0].ToString(), + LastPk: row[1].ToString(), + } + } + + return copyStates, nil +} diff --git a/go/vt/vtctl/workflow/vexec/query_plan.go b/go/vt/vtctl/workflow/vexec/query_plan.go new file mode 100644 index 00000000000..f71e124b786 --- /dev/null +++ b/go/vt/vtctl/workflow/vexec/query_plan.go @@ -0,0 +1,116 @@ +/* +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 vexec + +import ( + "context" + "fmt" + "sync" + + "vitess.io/vitess/go/vt/concurrency" + "vitess.io/vitess/go/vt/log" + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/topo" + "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/vt/vttablet/tmclient" + + querypb "vitess.io/vitess/go/vt/proto/query" +) + +// QueryPlan wraps a planned query produced by a QueryPlanner. It is safe to +// execute a QueryPlan repeatedly and in multiple goroutines. +type QueryPlan struct { + ParsedQuery *sqlparser.ParsedQuery + + workflow string + tmc tmclient.TabletManagerClient +} + +// Execute executes a QueryPlan on a single target. +func (qp *QueryPlan) Execute(ctx context.Context, target *topo.TabletInfo) (qr *querypb.QueryResult, err error) { + if qp.ParsedQuery == nil { + return nil, fmt.Errorf("%w: call PlanQuery on a query planner first", ErrUnpreparedQuery) + } + + targetAliasStr := target.AliasString() + + log.Infof("Running %v on %v", qp.ParsedQuery.Query, targetAliasStr) + defer func() { + if err != nil { + log.Warningf("Result on %v: %v", targetAliasStr, err) + + return + } + + log.Infof("Result on %v: %v", targetAliasStr, qr) + }() + + qr, err = qp.tmc.VReplicationExec(ctx, target.Tablet, qp.ParsedQuery.Query) + if err != nil { + return nil, err + } + + if qr.RowsAffected == 0 { + log.Infof("no matching streams found for workflows %s, tablet %s, query %s", qp.workflow, targetAliasStr, qp.ParsedQuery.Query) + } + + return qr, nil +} + +// ExecuteScatter executes a QueryPlan on multiple targets concurrently, +// returning a mapping of target tablet to querypb.QueryResult. Errors from +// individual targets are aggregated into a singular error. +func (qp *QueryPlan) ExecuteScatter(ctx context.Context, targets ...*topo.TabletInfo) (map[*topo.TabletInfo]*querypb.QueryResult, error) { + if qp.ParsedQuery == nil { + // This check is an "optimization" on error handling. We check here, + // even though we will check this during the individual Execute calls, + // so that we return one error, rather than the same error aggregated + // len(targets) times. + return nil, fmt.Errorf("%w: call PlanQuery on a query planner first", ErrUnpreparedQuery) + } + + var ( + m sync.Mutex + wg sync.WaitGroup + rec concurrency.AllErrorRecorder + results = make(map[*topo.TabletInfo]*querypb.QueryResult, len(targets)) + ) + + for _, target := range targets { + wg.Add(1) + + go func(ctx context.Context, target *topo.TabletInfo) { + defer wg.Done() + + qr, err := qp.Execute(ctx, target) + if err != nil { + rec.RecordError(err) + + return + } + + m.Lock() + defer m.Unlock() + + results[target] = qr + }(ctx, target) + } + + wg.Wait() + + return results, rec.AggrError(vterrors.Aggregate) +} diff --git a/go/vt/vtctl/workflow/vexec/query_plan_test.go b/go/vt/vtctl/workflow/vexec/query_plan_test.go new file mode 100644 index 00000000000..ec4f6fab95d --- /dev/null +++ b/go/vt/vtctl/workflow/vexec/query_plan_test.go @@ -0,0 +1,332 @@ +/* +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 vexec + +import ( + "context" + "errors" + "testing" + + "github.com/stretchr/testify/assert" + + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/topo" + "vitess.io/vitess/go/vt/vtctl/grpcvtctldserver/testutil" + + querypb "vitess.io/vitess/go/vt/proto/query" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" +) + +func TestQueryPlanExecute(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + plan QueryPlan + target *topo.TabletInfo + expected *querypb.QueryResult + shouldErr bool + errKind error + }{ + { + name: "success", + plan: QueryPlan{ + ParsedQuery: &sqlparser.ParsedQuery{ + Query: "SELECT id FROM _vt.vreplication", + }, + tmc: &testutil.TabletManagerClient{ + VReplicationExecResults: map[string]map[string]struct { + Result *querypb.QueryResult + Error error + }{ + "zone1-0000000100": { + "select id from _vt.vreplication": { + Result: &querypb.QueryResult{ + RowsAffected: 1, + }, + }, + }, + }, + }, + }, + target: &topo.TabletInfo{ + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, + }, + }, + expected: &querypb.QueryResult{ + RowsAffected: 1, + }, + shouldErr: false, + }, + { + name: "no rows affected", + plan: QueryPlan{ + ParsedQuery: &sqlparser.ParsedQuery{ + Query: "SELECT id FROM _vt.vreplication", + }, + tmc: &testutil.TabletManagerClient{ + VReplicationExecResults: map[string]map[string]struct { + Result *querypb.QueryResult + Error error + }{ + "zone1-0000000100": { + "select id from _vt.vreplication": { + Result: &querypb.QueryResult{ + RowsAffected: 0, + }, + }, + }, + }, + }, + }, + target: &topo.TabletInfo{ + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, + }, + }, + expected: &querypb.QueryResult{ + RowsAffected: 0, + }, + shouldErr: false, + }, + { + name: "error", + plan: QueryPlan{ + ParsedQuery: &sqlparser.ParsedQuery{ + Query: "SELECT id FROM _vt.vreplication", + }, + tmc: &testutil.TabletManagerClient{ + VReplicationExecResults: map[string]map[string]struct { + Result *querypb.QueryResult + Error error + }{ + "zone1-0000000100": { + "select id from _vt.vreplication": { + Error: assert.AnError, + }, + }, + }, + }, + }, + target: &topo.TabletInfo{ + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, + }, + }, + expected: nil, + shouldErr: true, + }, + { + name: "unprepared query", + plan: QueryPlan{ + ParsedQuery: nil, + }, + shouldErr: true, + errKind: ErrUnpreparedQuery, + }, + } + + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + ctx := context.Background() + + qr, err := tt.plan.Execute(ctx, tt.target) + if tt.shouldErr { + assert.Error(t, err) + + if tt.errKind != nil { + assert.True(t, errors.Is(err, tt.errKind), "expected error kind (= %v), got = %v", tt.errKind, err) + } + + return + } + + assert.NoError(t, err) + assert.Equal(t, tt.expected, qr) + }) + } +} + +func TestQueryPlanExecuteScatter(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + plan QueryPlan + targets []*topo.TabletInfo + // This is different from our actual return type because guaranteeing + // exact pointers in this table-driven style is a bit tough. + expected map[string]*querypb.QueryResult + shouldErr bool + errKind error + }{ + { + name: "success", + plan: QueryPlan{ + ParsedQuery: &sqlparser.ParsedQuery{ + Query: "SELECT id FROM _vt.vreplication", + }, + tmc: &testutil.TabletManagerClient{ + VReplicationExecResults: map[string]map[string]struct { + Result *querypb.QueryResult + Error error + }{ + "zone1-0000000100": { + "select id from _vt.vreplication": { + Result: &querypb.QueryResult{ + RowsAffected: 10, + }, + }, + }, + "zone1-0000000101": { + "select id from _vt.vreplication": { + Result: &querypb.QueryResult{ + RowsAffected: 5, + }, + }, + }, + }, + }, + }, + targets: []*topo.TabletInfo{ + { + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, + }, + }, + { + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 101, + }, + }, + }, + }, + expected: map[string]*querypb.QueryResult{ + "zone1-0000000100": { + RowsAffected: 10, + }, + "zone1-0000000101": { + RowsAffected: 5, + }, + }, + shouldErr: false, + }, + { + name: "some targets fail", + plan: QueryPlan{ + ParsedQuery: &sqlparser.ParsedQuery{ + Query: "SELECT id FROM _vt.vreplication", + }, + tmc: &testutil.TabletManagerClient{ + VReplicationExecResults: map[string]map[string]struct { + Result *querypb.QueryResult + Error error + }{ + "zone1-0000000100": { + "select id from _vt.vreplication": { + Error: assert.AnError, + }, + }, + "zone1-0000000101": { + "select id from _vt.vreplication": { + Result: &querypb.QueryResult{ + RowsAffected: 5, + }, + }, + }, + }, + }, + }, + targets: []*topo.TabletInfo{ + { + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, + }, + }, + { + Tablet: &topodatapb.Tablet{ + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 101, + }, + }, + }, + }, + shouldErr: true, + }, + { + name: "unprepared query", + plan: QueryPlan{ + ParsedQuery: nil, + }, + shouldErr: true, + errKind: ErrUnpreparedQuery, + }, + } + + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + ctx := context.Background() + + results, err := tt.plan.ExecuteScatter(ctx, tt.targets...) + if tt.shouldErr { + assert.Error(t, err) + + if tt.errKind != nil { + assert.True(t, errors.Is(err, tt.errKind), "expected error kind (= %v), got = %v", tt.errKind, err) + } + + return + } + + assert.NoError(t, err) + + resultsByAlias := make(map[string]*querypb.QueryResult, len(results)) + for tablet, qr := range results { + resultsByAlias[tablet.AliasString()] = qr + } + + assert.Equal(t, tt.expected, resultsByAlias) + }) + } +} diff --git a/go/vt/vtctl/workflow/vexec/query_planner.go b/go/vt/vtctl/workflow/vexec/query_planner.go new file mode 100644 index 00000000000..a850cc9816a --- /dev/null +++ b/go/vt/vtctl/workflow/vexec/query_planner.go @@ -0,0 +1,326 @@ +/* +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 vexec + +import ( + "errors" + "fmt" + + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/vttablet/tmclient" +) + +var ( // Query planning errors. + // ErrCannotUpdateImmutableColumn is returned when attempting to plan a + // query that updates a column that should be treated as immutable. + ErrCannotUpdateImmutableColumn = errors.New("cannot update immutable column") + // ErrUnsupportedQueryConstruct is returned when a particular query + // construct is unsupported by a QueryPlanner, despite the more general kind + // of query being supported. + // + // For example, VReplication supports DELETEs, but does not support DELETEs + // with LIMIT clauses, so planning a "DELETE ... LIMIT" will return + // ErrUnsupportedQueryConstruct rather than a "CREATE TABLE", which would + // return an ErrUnsupportedQuery. + ErrUnsupportedQueryConstruct = errors.New("unsupported query construct") +) + +var ( // Query execution errors. + // ErrUnpreparedQuery is returned when attempting to execute an unprepared + // QueryPlan. + ErrUnpreparedQuery = errors.New("attempted to execute unprepared query") +) + +// QueryPlanner defines the interface that VExec uses to build QueryPlans for +// various vexec workflows. A given vexec table, which is to say a table in the +// "_vt" database, will have at most one QueryPlanner implementation, which is +// responsible for defining both what queries are supported for that table, as +// well as how to build plans for those queries. +// +// VReplicationQueryPlanner is a good example implementation to refer to. +type QueryPlanner interface { + // (NOTE:@ajm188) I don't think this method fits on the query planner. To + // me, especially given that it's only implemented by the vrep query planner + // in the old implementation (the schema migration query planner no-ops this + // method), this fits better on our workflow.Manager struct, probably as a + // method called something like "VReplicationExec(ctx, query, Options{DryRun: true})" + // DryRun(ctx context.Context) error + + // PlanQuery constructs and returns a QueryPlan for a given statement. The + // resulting QueryPlan is suitable for repeated, concurrent use. + PlanQuery(stmt sqlparser.Statement) (*QueryPlan, error) + // QueryParams returns a struct of column parameters the QueryPlanner uses. + // It is used primarily to abstract the adding of default WHERE clauses to + // queries by a private function of this package, and may be removed from + // the interface later. + QueryParams() QueryParams +} + +// QueryParams is a struct that QueryPlanner implementations can provide to +// control the addition of default WHERE clauses to their queries. +type QueryParams struct { + // DBName is the value that the column referred to by DBNameColumn should + // equal in a WHERE clause, if set. + DBName string + // DBNameColumn is the name of the column that DBName should equal in a + // WHERE clause, if set. + DBNameColumn string + // Workflow is the value that the column referred to by WorkflowColumn + // should equal in a WHERE clause, if set. + Workflow string + // WorkflowColumn is the name of the column that Workflow should equal in a + // WHERE clause, if set. + WorkflowColumn string +} + +// VReplicationQueryPlanner implements the QueryPlanner interface for queries on +// the _vt.vreplication table. +type VReplicationQueryPlanner struct { + tmc tmclient.TabletManagerClient + + dbname string + workflow string +} + +// NewVReplicationQueryPlanner returns a new VReplicationQueryPlanner. It is +// valid to pass empty strings for both the dbname and workflow parameters. +func NewVReplicationQueryPlanner(tmc tmclient.TabletManagerClient, workflow string, dbname string) *VReplicationQueryPlanner { + return &VReplicationQueryPlanner{ + tmc: tmc, + dbname: dbname, + workflow: workflow, + } +} + +// PlanQuery is part of the QueryPlanner interface. +// +// For vreplication query planners, only SELECT, UPDATE, and DELETE queries are +// supported. +// +// For UPDATE queries, ORDER BY and LIMIT clauses are not supported. Attempting +// to update vreplication.id is an error. +// +// For DELETE queries, USING, PARTITION, ORDER BY, and LIMIT clauses are not +// supported. +func (planner *VReplicationQueryPlanner) PlanQuery(stmt sqlparser.Statement) (plan *QueryPlan, err error) { + switch stmt := stmt.(type) { + case *sqlparser.Select: + plan, err = planner.planSelect(stmt) + case *sqlparser.Insert: + err = ErrUnsupportedQuery + case *sqlparser.Update: + plan, err = planner.planUpdate(stmt) + case *sqlparser.Delete: + plan, err = planner.planDelete(stmt) + default: + err = ErrUnsupportedQuery + } + + if err != nil { + return nil, fmt.Errorf("%w: %s", err, sqlparser.String(stmt)) + } + + return plan, nil +} + +// QueryParams is part of the QueryPlanner interface. A VReplicationQueryPlanner +// will attach the following WHERE clauses iff (a) DBName, Workflow are set, +// respectively, and (b) db_name and workflow do not appear in the original +// query's WHERE clause: +// +// WHERE (db_name = {{ .DBName }} AND)? (workflow = {{ .Workflow }} AND)? {{ .OriginalWhere }} +func (planner *VReplicationQueryPlanner) QueryParams() QueryParams { + return QueryParams{ + DBName: planner.dbname, + DBNameColumn: "db_name", + Workflow: planner.workflow, + WorkflowColumn: "workflow", + } +} + +func (planner *VReplicationQueryPlanner) planDelete(del *sqlparser.Delete) (*QueryPlan, error) { + if del.Targets != nil { + return nil, fmt.Errorf( + "%w: DELETE must not have USING clause (have: %v): %v", + ErrUnsupportedQueryConstruct, + del.Targets, + sqlparser.String(del), + ) + } + + if del.Partitions != nil { + return nil, fmt.Errorf( + "%w: DELETE must not have explicit partitions (have: %v): %v", + ErrUnsupportedQueryConstruct, + del.Partitions, + sqlparser.String(del), + ) + } + + if del.OrderBy != nil || del.Limit != nil { + return nil, fmt.Errorf( + "%w: DELETE must not have explicit ordering (have: %v) or limit clauses (have: %v): %v", + ErrUnsupportedQueryConstruct, + del.OrderBy, + del.Limit, + sqlparser.String(del), + ) + } + + del.Where = addDefaultWheres(planner, del.Where) + + buf := sqlparser.NewTrackedBuffer(nil) + buf.Myprintf("%v", del) + + return &QueryPlan{ + ParsedQuery: buf.ParsedQuery(), + workflow: planner.workflow, + tmc: planner.tmc, + }, nil +} + +func (planner *VReplicationQueryPlanner) planSelect(sel *sqlparser.Select) (*QueryPlan, error) { + sel.Where = addDefaultWheres(planner, sel.Where) + + buf := sqlparser.NewTrackedBuffer(nil) + buf.Myprintf("%v", sel) + + return &QueryPlan{ + ParsedQuery: buf.ParsedQuery(), + workflow: planner.workflow, + tmc: planner.tmc, + }, nil +} + +func (planner *VReplicationQueryPlanner) planUpdate(upd *sqlparser.Update) (*QueryPlan, error) { + if upd.OrderBy != nil || upd.Limit != nil { + return nil, fmt.Errorf( + "%w: UPDATE must not have explicit ordering (have: %v) or limit clauses (have: %v): %v", + ErrUnsupportedQueryConstruct, + upd.OrderBy, + upd.Limit, + sqlparser.String(upd), + ) + } + + // For updates on the _vt.vreplication table, we ban updates to the `id` + // column, and allow updates to all other columns. + for _, expr := range upd.Exprs { + if expr.Name.Name.EqualString("id") { + return nil, fmt.Errorf( + "%w %+v: %v", + ErrCannotUpdateImmutableColumn, + expr.Name.Name, + sqlparser.String(expr), + ) + } + } + + upd.Where = addDefaultWheres(planner, upd.Where) + + buf := sqlparser.NewTrackedBuffer(nil) + buf.Myprintf("%v", upd) + + return &QueryPlan{ + ParsedQuery: buf.ParsedQuery(), + workflow: planner.workflow, + tmc: planner.tmc, + }, nil +} + +func addDefaultWheres(planner QueryPlanner, where *sqlparser.Where) *sqlparser.Where { + cols := extractWhereComparisonColumns(where) + + params := planner.QueryParams() + hasDBNameCol := false + hasWorkflowCol := false + + for _, col := range cols { + switch col { + case params.DBNameColumn: + hasDBNameCol = true + case params.WorkflowColumn: + hasWorkflowCol = true + } + } + + newWhere := where + + if !hasDBNameCol { + expr := &sqlparser.ComparisonExpr{ + Left: &sqlparser.ColName{ + Name: sqlparser.NewColIdent(params.DBNameColumn), + }, + Operator: sqlparser.EqualOp, + Right: sqlparser.NewStrLiteral([]byte(params.DBName)), + } + + switch newWhere { + case nil: + newWhere = &sqlparser.Where{ + Type: sqlparser.WhereClause, + Expr: expr, + } + default: + newWhere.Expr = &sqlparser.AndExpr{ + Left: newWhere.Expr, + Right: expr, + } + } + } + + if !hasWorkflowCol && params.Workflow != "" { + expr := &sqlparser.ComparisonExpr{ + Left: &sqlparser.ColName{ + Name: sqlparser.NewColIdent(params.WorkflowColumn), + }, + Operator: sqlparser.EqualOp, + Right: sqlparser.NewStrLiteral([]byte(params.Workflow)), + } + + newWhere.Expr = &sqlparser.AndExpr{ + Left: newWhere.Expr, + Right: expr, + } + } + + return newWhere +} + +// extractWhereComparisonColumns extracts the column names used in AND-ed +// comparison expressions in a where clause, given the following assumptions: +// - (1) The column name is always the left-hand side of the comparison. +// - (2) There are no compound expressions within the where clause involving OR. +func extractWhereComparisonColumns(where *sqlparser.Where) []string { + if where == nil { + return nil + } + + exprs := sqlparser.SplitAndExpression(nil, where.Expr) + cols := make([]string, 0, len(exprs)) + + for _, expr := range exprs { + switch expr := expr.(type) { + case *sqlparser.ComparisonExpr: + if qualifiedName, ok := expr.Left.(*sqlparser.ColName); ok { + cols = append(cols, qualifiedName.Name.String()) + } + } + } + + return cols +} diff --git a/go/vt/vtctl/workflow/vexec/query_planner_test.go b/go/vt/vtctl/workflow/vexec/query_planner_test.go new file mode 100644 index 00000000000..a63fbb96a65 --- /dev/null +++ b/go/vt/vtctl/workflow/vexec/query_planner_test.go @@ -0,0 +1,244 @@ +/* +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 vexec + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + + "vitess.io/vitess/go/vt/vtctl/workflow/vexec/testutil" +) + +func TestVReplicationQueryPlanner_PlanQuery(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + query string + err error + }{ + { + name: "basic select", + query: "SELECT id FROM _vt.vreplication", + err: nil, + }, + { + name: "insert not supported", + query: "INSERT INTO _vt.vreplication (id) VALUES (1)", + err: ErrUnsupportedQuery, + }, + { + name: "basic update", + query: "UPDATE _vt.vreplication SET workflow = 'my workflow'", + err: nil, + }, + { + name: "basic delete", + query: "DELETE FROM _vt.vreplication", + err: nil, + }, + { + name: "other query", + query: "CREATE TABLE foo (id INT(11) PRIMARY KEY NOT NULL) ENGINE=InnoDB", + err: ErrUnsupportedQuery, + }, + } + + planner := NewVReplicationQueryPlanner(nil, "", "") + + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + stmt := testutil.StatementFromString(t, tt.query) + + _, err := planner.PlanQuery(stmt) + if tt.err != nil { + assert.True(t, errors.Is(err, tt.err), "expected err of type %v, got %v", tt.err, err) + + return + } + + assert.NoError(t, err) + }) + } +} + +func TestVReplicationQueryPlanner_planSelect(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + query string + expectedPlannedQuery string + }{ + { + name: "simple select", + query: "SELECT id FROM _vt.vreplication WHERE id > 10", + expectedPlannedQuery: "SELECT id FROM _vt.vreplication WHERE id > 10 AND db_name = 'vt_testkeyspace' AND workflow = 'testworkflow'", + }, + { + name: "select with workflow and dbname columns already in WHERE", + query: "SELECT id FROM _vt.vreplication WHERE id > 10 AND db_name = 'vt_testkeyspace' AND workflow = 'testworkflow'", + expectedPlannedQuery: "SELECT id FROM _vt.vreplication WHERE id > 10 AND db_name = 'vt_testkeyspace' AND workflow = 'testworkflow'", + }, + { + // In this case, the QueryParams for the planner (which have + // workflow = "testworkflow"; db_name = "vt_testkeyspace") are + // ignored because the WHERE clause was explicit. + name: "select with workflow and dbname columns with different values", + query: "SELECT id FROM _vt.vreplication WHERE id > 10 AND db_name = 'different_keyspace' AND workflow = 'otherworkflow'", + expectedPlannedQuery: "SELECT id FROM _vt.vreplication WHERE id > 10 AND db_name = 'different_keyspace' AND workflow = 'otherworkflow'", + }, + } + + planner := NewVReplicationQueryPlanner(nil, "testworkflow", "vt_testkeyspace") + + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + stmt := testutil.StatementFromString(t, tt.query) + qp, err := planner.PlanQuery(stmt) + + assert.NoError(t, err) + assert.Equal(t, testutil.ParsedQueryFromString(t, tt.expectedPlannedQuery), qp.ParsedQuery) + }) + } +} + +func TestVReplicationQueryPlanner_planUpdate(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + planner *VReplicationQueryPlanner + query string + expectedPlannedQuery string + expectedErr error + }{ + { + name: "simple update", + planner: NewVReplicationQueryPlanner(nil, "testworkflow", "vt_testkeyspace"), + query: "UPDATE _vt.vreplication SET state = 'Running'", + expectedPlannedQuery: "UPDATE _vt.vreplication SET state = 'Running' WHERE db_name = 'vt_testkeyspace' AND workflow = 'testworkflow'", + expectedErr: nil, + }, + { + name: "including an ORDER BY is an error", + planner: NewVReplicationQueryPlanner(nil, "", ""), + query: "UPDATE _vt.vreplication SET state = 'Running' ORDER BY id DESC", + expectedErr: ErrUnsupportedQueryConstruct, + }, + { + name: "including a LIMIT is an error", + planner: NewVReplicationQueryPlanner(nil, "", ""), + query: "UPDATE _vt.vreplication SET state = 'Running' LIMIT 5", + expectedErr: ErrUnsupportedQueryConstruct, + }, + { + name: "cannot update id column", + planner: NewVReplicationQueryPlanner(nil, "", "vt_testkeyspace"), + query: "UPDATE _vt.vreplication SET id = 5", + expectedErr: ErrCannotUpdateImmutableColumn, + }, + } + + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + stmt := testutil.StatementFromString(t, tt.query) + + qp, err := tt.planner.PlanQuery(stmt) + if tt.expectedErr != nil { + assert.True(t, errors.Is(err, tt.expectedErr), "expected err of type %q, got %q", tt.expectedErr, err) + + return + } + + assert.Equal(t, testutil.ParsedQueryFromString(t, tt.expectedPlannedQuery), qp.ParsedQuery) + }) + } +} + +func TestVReplicationQueryPlanner_planDelete(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + query string + expectedPlannedQuery string + expectedErr error + }{ + { + name: "simple delete", + query: "DELETE FROM _vt.vreplication WHERE id = 1", + expectedPlannedQuery: "DELETE FROM _vt.vreplication WHERE id = 1 AND db_name = 'vt_testkeyspace'", + expectedErr: nil, + }, + { + name: "DELETE with USING clause is not supported", + query: "DELETE FROM _vt.vreplication, _vt.schema_migrations USING _vt.vreplication INNER JOIN _vt.schema_migrations", + expectedErr: ErrUnsupportedQueryConstruct, + }, + { + name: "DELETE with a PARTITION clause is not supported", + query: "DELETE FROM _vt.vreplication PARTITION (p1)", + expectedErr: ErrUnsupportedQueryConstruct, + }, + { + name: "DELETE with ORDER BY is not supported", + query: "DELETE FROM _vt.vreplication ORDER BY id DESC", + expectedErr: ErrUnsupportedQueryConstruct, + }, + { + name: "DELETE with LIMIT is not supported", + query: "DELETE FROM _vt.vreplication LIMIT 5", + expectedErr: ErrUnsupportedQueryConstruct, + }, + } + + planner := NewVReplicationQueryPlanner(nil, "", "vt_testkeyspace") + + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + stmt := testutil.StatementFromString(t, tt.query) + + qp, err := planner.PlanQuery(stmt) + if tt.expectedErr != nil { + assert.True(t, errors.Is(err, tt.expectedErr), "expected err of type %q, got %q", tt.expectedErr, err) + + return + } + + assert.Equal(t, testutil.ParsedQueryFromString(t, tt.expectedPlannedQuery), qp.ParsedQuery) + }) + } +} diff --git a/go/vt/vtctl/workflow/vexec/testutil/query.go b/go/vt/vtctl/workflow/vexec/testutil/query.go new file mode 100644 index 00000000000..3988f7a112f --- /dev/null +++ b/go/vt/vtctl/workflow/vexec/testutil/query.go @@ -0,0 +1,48 @@ +/* +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 testutil + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/vt/sqlparser" +) + +// ParsedQueryFromString is a test helper that returns a *sqlparser.ParsedQuery +// from a plain string. It marks the test as a failure if the query cannot be +// parsed. +func ParsedQueryFromString(t *testing.T, query string) *sqlparser.ParsedQuery { + t.Helper() + + buf := sqlparser.NewTrackedBuffer(nil) + buf.Myprintf("%v", StatementFromString(t, query)) + + return buf.ParsedQuery() +} + +// StatementFromString is a test helper that returns a sqlparser.Statement from +// a plain string. It marks the test as a failure if the query cannot be parsed. +func StatementFromString(t *testing.T, query string) sqlparser.Statement { + t.Helper() + + stmt, err := sqlparser.Parse(query) + require.NoError(t, err, "could not parse query %v", query) + + return stmt +} diff --git a/go/vt/vtctl/workflow/vexec/vexec.go b/go/vt/vtctl/workflow/vexec/vexec.go new file mode 100644 index 00000000000..d61bd16ab31 --- /dev/null +++ b/go/vt/vtctl/workflow/vexec/vexec.go @@ -0,0 +1,235 @@ +/* +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 vexec + +import ( + "context" + "errors" + "fmt" + + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/topo" + "vitess.io/vitess/go/vt/topo/topoproto" + "vitess.io/vitess/go/vt/vttablet/tmclient" + + querypb "vitess.io/vitess/go/vt/proto/query" +) + +const ( + // VExecTableQualifier is the qualifier that all tables supported by vexec + // are prefixed by. + VExecTableQualifier = "_vt" + + // SchemaMigrationsTableName is the unqualified name of the schema + // migrations table supported by vexec. + SchemaMigrationsTableName = "schema_migrations" + // VReplicationTableName is the unqualified name of the vreplication table + // supported by vexec. + VReplicationTableName = "vreplication" +) + +var ( // Topo lookup errors. + // ErrNoShardPrimary occurs when a shard is found with no serving + // primary. + ErrNoShardPrimary = errors.New("no primary found for shard") + // ErrNoShardsForKeyspace occurs when attempting to run a vexec on an empty + // keyspace. + ErrNoShardsForKeyspace = errors.New("no shards found in keyspace") +) + +var ( // Query parsing and planning errors. + // ErrUnsupportedQuery occurs when attempting to run an unsupported query + // through vexec. + ErrUnsupportedQuery = errors.New("query not supported by vexec") + // ErrUnsupportedTable occurs when attempting to run vexec on an unsupported + // table. At the time of writing, this occurs when attempting to query any + // table other than _vt.vreplication. + ErrUnsupportedTable = errors.New("table not supported by vexec") +) + +// VExec provides the main interface to planning and executing vexec queries +// (normally, queries on tables in the `_vt` database). It currently supports +// some limited vreplication queries; this set of supported behavior will expand +// over time. It may be extended to support schema_migrations queries as well. +type VExec struct { + ts *topo.Server + tmc tmclient.TabletManagerClient + + keyspace string + workflow string + + // (TODO:@ajm188) Consider renaming this field to "targets", and then + // support different Strategy functions for loading target tablets from a + // topo.Server. + // + // For this, I'm currently thinking: + // type TargetStrategy func(ts *topo.Server) ([]*topo.TabletInfo, error) + // + // We _may_ want this if we ever want a vexec query to target anything other + // than "all of the shard primaries in a given keyspace", and I'm not sure + // about potential future usages yet. + primaries []*topo.TabletInfo + // (TODO:@ajm188) Similar to supporting a TargetStrategy for controlling how + // a VExec picks which tablets to query, we may also want an + // ExecutionStrategy (I'm far less sure about whether we would want this at + // all, or what its type definition might look like, than TargetStrategy), + // to support running in modes like: + // - Execute serially rather than concurrently. + // - Only return error if greater than some percentage of the targets fail. +} + +// NewVExec returns a new instance suitable for making vexec queries to a given +// keyspace (required) and workflow (optional, omit by providing the empty +// string). The provided topo server is used to look up target tablets for +// queries. A given instance will discover targets exactly once for its +// lifetime, so to force a refresh, create another instance. +func NewVExec(keyspace string, workflow string, ts *topo.Server, tmc tmclient.TabletManagerClient) *VExec { + return &VExec{ + ts: ts, + tmc: tmc, + keyspace: keyspace, + workflow: workflow, + } +} + +// QueryContext executes the given vexec query, returning a mapping of tablet +// to querypb.QueryResult. +// +// On first use, QueryContext will also cause the VExec instance to discover +// target tablets from the topo; that target list will be reused for all future +// queries made by this instance. +// +// For details on query parsing and planning, see GetPlanner and the +// QueryPlanner interface. +func (vx *VExec) QueryContext(ctx context.Context, query string) (map[*topo.TabletInfo]*querypb.QueryResult, error) { + if vx.primaries == nil { + if err := vx.initialize(ctx); err != nil { + return nil, err + } + } + + stmt, err := sqlparser.Parse(query) + if err != nil { + return nil, err + } + + table, err := extractTableName(stmt) + if err != nil { + return nil, err + } + + planner, err := vx.GetPlanner(ctx, table) + if err != nil { + return nil, err + } + + qp, err := planner.PlanQuery(stmt) + if err != nil { + return nil, err + } + + return qp.ExecuteScatter(ctx, vx.primaries...) +} + +func (vx *VExec) initialize(ctx context.Context) error { + vx.primaries = nil + + getShardsCtx, getShardsCancel := context.WithTimeout(ctx, *topo.RemoteOperationTimeout) + defer getShardsCancel() + + shards, err := vx.ts.GetShardNames(getShardsCtx, vx.keyspace) + if err != nil { + return err + } + + if len(shards) == 0 { + return fmt.Errorf("%w %s", ErrNoShardsForKeyspace, vx.keyspace) + } + + primaries := make([]*topo.TabletInfo, 0, len(shards)) + + for _, shard := range shards { + ctx, cancel := context.WithTimeout(ctx, *topo.RemoteOperationTimeout) + defer cancel() + + si, err := vx.ts.GetShard(ctx, vx.keyspace, shard) + if err != nil { + return err + } + + if si.MasterAlias == nil { + return fmt.Errorf("%w %s/%s", ErrNoShardPrimary, vx.keyspace, shard) + } + + primary, err := vx.ts.GetTablet(ctx, si.MasterAlias) + if err != nil { + return err + } + + if primary == nil { + return fmt.Errorf("%w %s/%s: tablet %v not found", ErrNoShardPrimary, vx.keyspace, shard, topoproto.TabletAliasString(si.MasterAlias)) + } + + primaries = append(primaries, primary) + } + + vx.primaries = primaries + + return nil +} + +// GetPlanner returns an appropriate implementation of a QueryPlanner, depending +// on the table being queried. +// +// On first use, GetPlanner will also cause the VExec instance to discover +// target tablets from the topo; that target list will be reused for all future +// queries made by this instance. +func (vx *VExec) GetPlanner(ctx context.Context, table string) (QueryPlanner, error) { // TODO: private? + if vx.primaries == nil { + if err := vx.initialize(ctx); err != nil { + return nil, fmt.Errorf("error while initializing target list: %w", err) + } + } + + switch table { + case qualifiedTableName(VReplicationTableName): + return NewVReplicationQueryPlanner(vx.tmc, vx.workflow, vx.primaries[0].DbName()), nil + case qualifiedTableName(SchemaMigrationsTableName): + return nil, errors.New("Schema Migrations not yet supported in new workflow package") + default: + return nil, fmt.Errorf("%w: %v", ErrUnsupportedTable, table) + } +} + +func extractTableName(stmt sqlparser.Statement) (string, error) { + switch stmt := stmt.(type) { + case *sqlparser.Update: + return sqlparser.String(stmt.TableExprs), nil + case *sqlparser.Delete: + return sqlparser.String(stmt.TableExprs), nil + case *sqlparser.Insert: + return sqlparser.String(stmt.Table), nil + case *sqlparser.Select: + return sqlparser.String(stmt.From), nil + } + + return "", fmt.Errorf("%w: %+v", ErrUnsupportedQuery, sqlparser.String(stmt)) +} + +func qualifiedTableName(name string) string { + return fmt.Sprintf("%s.%s", VExecTableQualifier, name) +} diff --git a/go/vt/wrangler/vexec.go b/go/vt/wrangler/vexec.go index 5b7259800a5..2aafefc3331 100644 --- a/go/vt/wrangler/vexec.go +++ b/go/vt/wrangler/vexec.go @@ -30,13 +30,15 @@ import ( "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/concurrency" "vitess.io/vitess/go/vt/log" - binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" - querypb "vitess.io/vitess/go/vt/proto/query" - topodatapb "vitess.io/vitess/go/vt/proto/topodata" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/topo" + vtctldvexec "vitess.io/vitess/go/vt/vtctl/workflow/vexec" // renamed to avoid a collision with the vexec struct in this package "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/evalengine" + + binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" + querypb "vitess.io/vitess/go/vt/proto/query" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" ) const ( @@ -511,7 +513,8 @@ func (wr *Wrangler) ListAllWorkflows(ctx context.Context, keyspace string, activ where = " where state <> 'Stopped'" } query := "select distinct workflow from _vt.vreplication" + where - results, err := wr.runVexec(ctx, "", keyspace, query, false) + vx := vtctldvexec.NewVExec(keyspace, "", wr.ts, wr.tmc) + results, err := vx.QueryContext(ctx, query) if err != nil { return nil, err } diff --git a/proto/vtctldata.proto b/proto/vtctldata.proto index 361bd4a2083..41a0cc13d7c 100644 --- a/proto/vtctldata.proto +++ b/proto/vtctldata.proto @@ -22,6 +22,7 @@ option go_package = "vitess.io/vitess/go/vt/proto/vtctldata"; package vtctldata; +import "binlogdata.proto"; import "logutil.proto"; import "mysqlctl.proto"; import "tabletmanagerdata.proto"; @@ -41,6 +42,90 @@ message ExecuteVtctlCommandResponse { logutil.Event event = 1; } +// TableMaterializeSttings contains the settings for one table. +message TableMaterializeSettings { + string target_table = 1; + // source_expression is a select statement. + string source_expression = 2; + // create_ddl contains the DDL to create the target table. + // If empty, the target table must already exist. + // if "copy", the target table DDL is the same as the source table. + string create_ddl = 3; +} + +// MaterializeSettings contains the settings for the Materialize command. +message MaterializeSettings { + // workflow is the name of the workflow. + string workflow = 1; + string source_keyspace = 2; + string target_keyspace = 3; + // stop_after_copy specifies if vreplication should be stopped after copying. + bool stop_after_copy = 4; + repeated TableMaterializeSettings table_settings = 5; + // optional parameters. + string cell = 6; + string tablet_types = 7; + // ExternalCluster is the name of the mounted cluster which has the source keyspace/db for this workflow + // it is of the type + string external_cluster = 8; + +} + +/* Data types for VtctldServer */ + +message Keyspace { + string name = 1; + topodata.Keyspace keyspace = 2; +} + +message Shard { + string keyspace = 1; + string name = 2; + topodata.Shard shard = 3; +} + +// TODO: comment the hell out of this. +message Workflow { + string name = 1; + ReplicationLocation source = 2; + ReplicationLocation target = 3; + int64 max_v_replication_lag = 4; + map shard_streams = 5; + + message ReplicationLocation { + string keyspace = 1; + repeated string shards = 2; + } + + message ShardStream { + repeated Stream streams = 1; + repeated topodata.Shard.TabletControl tablet_controls = 2; + bool is_primary_serving = 3; + } + + message Stream { + int64 id = 1; + string shard = 2; + topodata.TabletAlias tablet = 3; + binlogdata.BinlogSource binlog_source = 4; + string position = 5; + string stop_position = 6; + string state = 7; + string db_name = 8; + vttime.Time transaction_timestamp = 9; + vttime.Time time_updated = 10; + string message = 11; + repeated CopyState copy_states = 12; + + message CopyState { + string table = 1; + string last_pk = 2; + } + } +} + +/* Request/response types for VtctldServer */ + message ChangeTabletTypeRequest { topodata.TabletAlias tablet_alias = 1; topodata.TabletType db_type = 2; @@ -149,6 +234,45 @@ message DeleteTabletsRequest { message DeleteTabletsResponse { } +message EmergencyReparentShardRequest { + // Keyspace is the name of the keyspace to perform the Emergency Reparent in. + string keyspace = 1; + // Shard is the name of the shard to perform the Emergency Reparent in. + string shard = 2; + // Optional alias of a tablet that should become the new shard primary. If not + // not specified, the vtctld will select the most up-to-date canditate to + // promote. + topodata.TabletAlias new_primary = 3; + // List of replica aliases to ignore during the Emergency Reparent. The vtctld + // will not attempt to stop replication on these tablets, nor attempt to + // demote any that may think they are the shard primary. + repeated topodata.TabletAlias ignore_replicas = 4; + // WaitReplicasTimeout is the duration of time to wait for replicas to catch + // up in reparenting. + vttime.Duration wait_replicas_timeout = 5; +} + +message EmergencyReparentShardResponse { + // Keyspace is the name of the keyspace the Emergency Reparent took place in. + string keyspace = 1; + // Shard is the name of the shard the Emergency Reparent took place in. + string shard = 2; + // PromotedPrimary is the alias of the tablet that was promoted to shard + // primary. If NewPrimary was set in the request, then this will be the same + // alias. Otherwise, it will be the alias of the tablet found to be most + // up-to-date. + topodata.TabletAlias promoted_primary = 3; + repeated logutil.Event events = 4; +} + +message FindAllShardsInKeyspaceRequest { + string keyspace = 1; +} + +message FindAllShardsInKeyspaceResponse { + map shards = 1; +} + message GetBackupsRequest { string keyspace = 1; string shard = 2; @@ -266,6 +390,15 @@ message GetVSchemaResponse { vschema.Keyspace v_schema = 1; } +message GetWorkflowsRequest { + string keyspace = 1; + bool active_only = 2; +} + +message GetWorkflowsResponse { + repeated Workflow workflows = 1; +} + message RemoveKeyspaceCellRequest { string keyspace = 1; string cell = 2; @@ -301,46 +434,30 @@ message RemoveShardCellResponse { // and any deleted Tablet objects here. } -message Keyspace { - string name = 1; - topodata.Keyspace keyspace = 2; +message ReparentTabletRequest { + // Tablet is the alias of the tablet that should be reparented under the + // current shard primary. + topodata.TabletAlias tablet = 1; } -message FindAllShardsInKeyspaceRequest { +message ReparentTabletResponse { + // Keyspace is the name of the keyspace the tablet was reparented in. string keyspace = 1; + // Shard is the name of the shard the tablet was reparented in. + string shard = 2; + // Primary is the alias of the tablet that the tablet was reparented under. + topodata.TabletAlias primary = 3; } -message FindAllShardsInKeyspaceResponse { - map shards = 1; +message TabletExternallyReparentedRequest { + // Tablet is the alias of the tablet that was promoted externally and should + // be updated to the shard primary in the topo. + topodata.TabletAlias tablet = 1; } -message Shard { +message TabletExternallyReparentedResponse { string keyspace = 1; - string name = 2; - topodata.Shard shard = 3; -} - -// TableMaterializeSttings contains the settings for one table. -message TableMaterializeSettings { - string target_table = 1; - // source_expression is a select statement. - string source_expression = 2; - // create_ddl contains the DDL to create the target table. - // If empty, the target table must already exist. - // if "copy", the target table DDL is the same as the source table. - string create_ddl = 3; -} - -// MaterializeSettings contains the settings for the Materialize command. -message MaterializeSettings { - // workflow is the name of the workflow. - string workflow = 1; - string source_keyspace = 2; - string target_keyspace = 3; - // stop_after_copy specifies if vreplication should be stopped after copying. - bool stop_after_copy = 4; - repeated TableMaterializeSettings table_settings = 5; - // optional parameters. - string cell = 6; - string tablet_types = 7; + string shard = 2; + topodata.TabletAlias new_primary = 3; + topodata.TabletAlias old_primary = 4; } diff --git a/proto/vtctlservice.proto b/proto/vtctlservice.proto index 15b0d6729c9..ed0cf1b177f 100644 --- a/proto/vtctlservice.proto +++ b/proto/vtctlservice.proto @@ -85,9 +85,8 @@ service Vtctld { rpc GetTablets(vtctldata.GetTabletsRequest) returns (vtctldata.GetTabletsResponse) {}; // GetVSchema returns the vschema for a keyspace. rpc GetVSchema(vtctldata.GetVSchemaRequest) returns (vtctldata.GetVSchemaResponse) {}; - // RemoveKeyspaceCell removes the specified cell from the Cells list for all - // shards in the specified keyspace, as well as from the SrvKeyspace for that - // keyspace in that cell. + // GetWorkflows returns a list of workflows for the given keyspace. + rpc GetWorkflows(vtctldata.GetWorkflowsRequest) returns (vtctldata.GetWorkflowsResponse) {}; rpc RemoveKeyspaceCell(vtctldata.RemoveKeyspaceCellRequest) returns (vtctldata.RemoveKeyspaceCellResponse) {}; // RemoveShardCell removes the specified cell from the specified shard's Cells // list. diff --git a/proto/vttime.proto b/proto/vttime.proto index 5224fcb9d12..9533771cb6e 100644 --- a/proto/vttime.proto +++ b/proto/vttime.proto @@ -28,3 +28,8 @@ message Time { int32 nanoseconds = 2; } +message Duration { + int64 seconds = 1; + int32 nanos = 2; +} +