vitess.io/vitess@v0.16.2/go/cmd/vtctldclient/command/vschemas.go (about) 1 /* 2 Copyright 2021 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package command 18 19 import ( 20 "fmt" 21 "os" 22 23 "github.com/spf13/cobra" 24 25 "vitess.io/vitess/go/cmd/vtctldclient/cli" 26 "vitess.io/vitess/go/json2" 27 28 vschemapb "vitess.io/vitess/go/vt/proto/vschema" 29 vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" 30 ) 31 32 var ( 33 // GetVSchema makes a GetVSchema gRPC call to a vtctld. 34 GetVSchema = &cobra.Command{ 35 Use: "GetVSchema <keyspace>", 36 Short: "Prints a JSON representation of a keyspace's topo record.", 37 DisableFlagsInUseLine: true, 38 Args: cobra.ExactArgs(1), 39 RunE: commandGetVSchema, 40 } 41 // ApplyVSchema makes an ApplyVSchema gRPC call to a vtctld. 42 ApplyVSchema = &cobra.Command{ 43 Use: "ApplyVSchema {--vschema=<vschema> || --vschema-file=<vschema file> || --sql=<sql> || --sql-file=<sql file>} [--cells=c1,c2,...] [--skip-rebuild] [--dry-run] <keyspace>", 44 Short: "Applies the VTGate routing schema to the provided keyspace. Shows the result after application.", 45 DisableFlagsInUseLine: true, 46 Args: cobra.ExactArgs(1), 47 RunE: commandApplyVSchema, 48 } 49 ) 50 51 var applyVSchemaOptions = struct { 52 VSchema string 53 VSchemaFile string 54 SQL string 55 SQLFile string 56 DryRun bool 57 SkipRebuild bool 58 Cells []string 59 }{} 60 61 func commandApplyVSchema(cmd *cobra.Command, args []string) error { 62 sqlMode := (applyVSchemaOptions.SQL != "") != (applyVSchemaOptions.SQLFile != "") 63 jsonMode := (applyVSchemaOptions.VSchema != "") != (applyVSchemaOptions.VSchemaFile != "") 64 65 if sqlMode && jsonMode { 66 return fmt.Errorf("only one of the sql, sql-file, vschema, or vschema-file flags may be specified when calling the ApplyVSchema command") 67 } 68 69 if !sqlMode && !jsonMode { 70 return fmt.Errorf("one of the sql, sql-file, vschema, or vschema-file flags must be specified when calling the ApplyVSchema command") 71 } 72 73 req := &vtctldatapb.ApplyVSchemaRequest{ 74 Keyspace: cmd.Flags().Arg(0), 75 SkipRebuild: applyVSchemaOptions.SkipRebuild, 76 Cells: applyVSchemaOptions.Cells, 77 DryRun: applyVSchemaOptions.DryRun, 78 } 79 80 var err error 81 if sqlMode { 82 if applyVSchemaOptions.SQLFile != "" { 83 sqlBytes, err := os.ReadFile(applyVSchemaOptions.SQLFile) 84 if err != nil { 85 return err 86 } 87 req.Sql = string(sqlBytes) 88 } else { 89 req.Sql = applyVSchemaOptions.SQL 90 } 91 } else { // jsonMode 92 var schema []byte 93 if applyVSchemaOptions.VSchemaFile != "" { 94 schema, err = os.ReadFile(applyVSchemaOptions.VSchemaFile) 95 if err != nil { 96 return err 97 } 98 } else { 99 schema = []byte(applyVSchemaOptions.VSchema) 100 } 101 102 var vs vschemapb.Keyspace 103 err = json2.Unmarshal(schema, &vs) 104 if err != nil { 105 return err 106 } 107 req.VSchema = &vs 108 } 109 110 cli.FinishedParsing(cmd) 111 112 res, err := client.ApplyVSchema(commandCtx, req) 113 if err != nil { 114 return err 115 } 116 data, err := cli.MarshalJSON(res.VSchema) 117 if err != nil { 118 return err 119 } 120 fmt.Printf("New VSchema object:\n%s\nIf this is not what you expected, check the input data (as JSON parsing will skip unexpected fields).\n", data) 121 return nil 122 } 123 124 func commandGetVSchema(cmd *cobra.Command, args []string) error { 125 cli.FinishedParsing(cmd) 126 127 keyspace := cmd.Flags().Arg(0) 128 129 resp, err := client.GetVSchema(commandCtx, &vtctldatapb.GetVSchemaRequest{ 130 Keyspace: keyspace, 131 }) 132 if err != nil { 133 return err 134 } 135 136 data, err := cli.MarshalJSON(resp.VSchema) 137 if err != nil { 138 return err 139 } 140 141 fmt.Printf("%s\n", data) 142 143 return nil 144 } 145 146 func init() { 147 ApplyVSchema.Flags().StringVar(&applyVSchemaOptions.VSchema, "vschema", "", "VSchema to apply, in JSON form.") 148 ApplyVSchema.Flags().StringVar(&applyVSchemaOptions.VSchemaFile, "vschema-file", "", "Path to a file containing the vschema to apply, in JSON form.") 149 ApplyVSchema.Flags().StringVar(&applyVSchemaOptions.SQL, "sql", "", "A VSchema DDL SQL statement, e.g. `alter table t add vindex hash(id)`.") 150 ApplyVSchema.Flags().StringVar(&applyVSchemaOptions.SQLFile, "sql-file", "", "Path to a file containing a VSchema DDL SQL.") 151 ApplyVSchema.Flags().BoolVar(&applyVSchemaOptions.DryRun, "dry-run", false, "If set, do not save the altered vschema, simply echo to console.") 152 ApplyVSchema.Flags().BoolVar(&applyVSchemaOptions.SkipRebuild, "skip-rebuild", false, "Skip rebuilding the SrvSchema objects.") 153 ApplyVSchema.Flags().StringSliceVar(&applyVSchemaOptions.Cells, "cells", nil, "Limits the rebuild to the specified cells, after application. Ignored if --skip-rebuild is set.") 154 Root.AddCommand(ApplyVSchema) 155 156 Root.AddCommand(GetVSchema) 157 }