vitess.io/vitess@v0.16.2/go/cmd/vtctldclient/command/keyspaces.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 "errors" 21 "fmt" 22 "time" 23 24 "github.com/spf13/cobra" 25 26 "vitess.io/vitess/go/cmd/vtctldclient/cli" 27 "vitess.io/vitess/go/vt/logutil" 28 "vitess.io/vitess/go/vt/topo" 29 30 topodatapb "vitess.io/vitess/go/vt/proto/topodata" 31 vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" 32 "vitess.io/vitess/go/vt/proto/vttime" 33 ) 34 35 var ( 36 // CreateKeyspace makes a CreateKeyspace gRPC call to a vtctld. 37 CreateKeyspace = &cobra.Command{ 38 Use: "CreateKeyspace <keyspace> [--force|-f] [--type KEYSPACE_TYPE] [--base-keyspace KEYSPACE --snapshot-timestamp TIME] [--served-from DB_TYPE:KEYSPACE ...] [--durability-policy <policy_name>]", 39 Short: "Creates the specified keyspace in the topology.", 40 Long: `Creates the specified keyspace in the topology. 41 42 For a SNAPSHOT keyspace, the request must specify the name of a base keyspace, 43 as well as a snapshot time.`, 44 DisableFlagsInUseLine: true, 45 Args: cobra.ExactArgs(1), 46 RunE: commandCreateKeyspace, 47 } 48 // DeleteKeyspace makes a DeleteKeyspace gRPC call to a vtctld. 49 DeleteKeyspace = &cobra.Command{ 50 Use: "DeleteKeyspace [--recursive|-r] [--force|-f] <keyspace>", 51 Short: "Deletes the specified keyspace from the topology.", 52 Long: `Deletes the specified keyspace from the topology. 53 54 In recursive mode, it also recursively deletes all shards in the keyspace. 55 Otherwise, the keyspace must be empty (have no shards), or returns an error.`, 56 DisableFlagsInUseLine: true, 57 Args: cobra.ExactArgs(1), 58 RunE: commandDeleteKeyspace, 59 } 60 // FindAllShardsInKeyspace makes a FindAllShardsInKeyspace gRPC call to a vtctld. 61 FindAllShardsInKeyspace = &cobra.Command{ 62 Use: "FindAllShardsInKeyspace <keyspace>", 63 Short: "Returns a map of shard names to shard references for a given keyspace.", 64 DisableFlagsInUseLine: true, 65 Aliases: []string{"findallshardsinkeyspace"}, 66 Args: cobra.ExactArgs(1), 67 RunE: commandFindAllShardsInKeyspace, 68 } 69 // GetKeyspace makes a GetKeyspace gRPC call to a vtctld. 70 GetKeyspace = &cobra.Command{ 71 Use: "GetKeyspace <keyspace>", 72 Short: "Returns information about the given keyspace from the topology.", 73 DisableFlagsInUseLine: true, 74 Aliases: []string{"getkeyspace"}, 75 Args: cobra.ExactArgs(1), 76 RunE: commandGetKeyspace, 77 } 78 // GetKeyspaces makes a GetKeyspaces gRPC call to a vtctld. 79 GetKeyspaces = &cobra.Command{ 80 Use: "GetKeyspaces", 81 Short: "Returns information about every keyspace in the topology.", 82 DisableFlagsInUseLine: true, 83 Aliases: []string{"getkeyspaces"}, 84 Args: cobra.NoArgs, 85 RunE: commandGetKeyspaces, 86 } 87 // RemoveKeyspaceCell makes a RemoveKeyspaceCell gRPC call to a vtctld. 88 RemoveKeyspaceCell = &cobra.Command{ 89 Use: "RemoveKeyspaceCell [--force|-f] [--recursive|-r] <keyspace> <cell>", 90 Short: "Removes the specified cell from the Cells list for all shards in the specified keyspace (by calling RemoveShardCell on every shard). It also removes the SrvKeyspace for that keyspace in that cell.", 91 DisableFlagsInUseLine: true, 92 Args: cobra.ExactArgs(2), 93 RunE: commandRemoveKeyspaceCell, 94 } 95 // SetKeyspaceDurabilityPolicy makes a SetKeyspaceDurabilityPolicy gRPC call to a vtcltd. 96 SetKeyspaceDurabilityPolicy = &cobra.Command{ 97 Use: "SetKeyspaceDurabilityPolicy [--durability-policy=policy_name] <keyspace name>", 98 Short: "Sets the durability-policy used by the specified keyspace.", 99 Long: `Sets the durability-policy used by the specified keyspace. 100 Durability policy governs the durability of the keyspace by describing which tablets should be sending semi-sync acknowledgements to the primary. 101 Possible values include 'semi_sync', 'none' and others as dictated by registered plugins. 102 103 To set the durability policy of customer keyspace to semi_sync, you would use the following command: 104 SetKeyspaceDurabilityPolicy --durability-policy='semi_sync' customer`, 105 DisableFlagsInUseLine: true, 106 Args: cobra.ExactArgs(1), 107 RunE: commandSetKeyspaceDurabilityPolicy, 108 } 109 // ValidateSchemaKeyspace makes a ValidateSchemaKeyspace gRPC call to a vtctld. 110 ValidateSchemaKeyspace = &cobra.Command{ 111 Use: "ValidateSchemaKeyspace [--exclude-tables=<exclude_tables>] [--include-views] [--skip-no-primary] [--include-vschema] <keyspace>", 112 Short: "Validates that the schema on the primary tablet for shard 0 matches the schema on all other tablets in the keyspace.", 113 DisableFlagsInUseLine: true, 114 Aliases: []string{"validateschemakeyspace"}, 115 Args: cobra.ExactArgs(1), 116 RunE: commandValidateSchemaKeyspace, 117 } 118 // ValidateVersionKeyspace makes a ValidateVersionKeyspace gRPC call to a vtctld. 119 ValidateVersionKeyspace = &cobra.Command{ 120 Use: "ValidateVersionKeyspace <keyspace>", 121 Short: "Validates that the version on the primary tablet of shard 0 matches all of the other tablets in the keyspace.", 122 DisableFlagsInUseLine: true, 123 Aliases: []string{"validateversionkeyspace"}, 124 Args: cobra.ExactArgs(1), 125 RunE: commandValidateVersionKeyspace, 126 } 127 ) 128 129 var createKeyspaceOptions = struct { 130 Force bool 131 AllowEmptyVSchema bool 132 133 ServedFromsMap cli.StringMapValue 134 135 KeyspaceType cli.KeyspaceTypeFlag 136 BaseKeyspace string 137 SnapshotTimestamp string 138 DurabilityPolicy string 139 }{ 140 KeyspaceType: cli.KeyspaceTypeFlag(topodatapb.KeyspaceType_NORMAL), 141 } 142 143 func commandCreateKeyspace(cmd *cobra.Command, args []string) error { 144 name := cmd.Flags().Arg(0) 145 146 switch topodatapb.KeyspaceType(createKeyspaceOptions.KeyspaceType) { 147 case topodatapb.KeyspaceType_NORMAL, topodatapb.KeyspaceType_SNAPSHOT: 148 default: 149 return fmt.Errorf("invalid keyspace type passed to --type: %v", createKeyspaceOptions.KeyspaceType) 150 } 151 152 var snapshotTime *vttime.Time 153 if topodatapb.KeyspaceType(createKeyspaceOptions.KeyspaceType) == topodatapb.KeyspaceType_SNAPSHOT { 154 if createKeyspaceOptions.DurabilityPolicy != "none" { 155 return errors.New("--durability-policy cannot be specified while creating a snapshot keyspace") 156 } 157 158 if createKeyspaceOptions.BaseKeyspace == "" { 159 return errors.New("--base-keyspace is required for a snapshot keyspace") 160 } 161 162 if createKeyspaceOptions.SnapshotTimestamp == "" { 163 return errors.New("--snapshot-timestamp is required for a snapshot keyspace") 164 } 165 166 t, err := time.Parse(time.RFC3339, createKeyspaceOptions.SnapshotTimestamp) 167 if err != nil { 168 return fmt.Errorf("cannot parse --snapshot-timestamp as RFC3339: %w", err) 169 } 170 171 if now := time.Now(); t.After(now) { 172 return fmt.Errorf("--snapshot-time cannot be in the future; snapshot = %v, now = %v", t, now) 173 } 174 175 snapshotTime = logutil.TimeToProto(t) 176 } 177 178 cli.FinishedParsing(cmd) 179 180 req := &vtctldatapb.CreateKeyspaceRequest{ 181 Name: name, 182 Force: createKeyspaceOptions.Force, 183 AllowEmptyVSchema: createKeyspaceOptions.AllowEmptyVSchema, 184 Type: topodatapb.KeyspaceType(createKeyspaceOptions.KeyspaceType), 185 BaseKeyspace: createKeyspaceOptions.BaseKeyspace, 186 SnapshotTime: snapshotTime, 187 DurabilityPolicy: createKeyspaceOptions.DurabilityPolicy, 188 } 189 190 for n, v := range createKeyspaceOptions.ServedFromsMap.StringMapValue { 191 tt, err := topo.ParseServingTabletType(n) 192 if err != nil { 193 return err 194 } 195 196 req.ServedFroms = append(req.ServedFroms, &topodatapb.Keyspace_ServedFrom{ 197 TabletType: tt, 198 Keyspace: v, 199 }) 200 } 201 202 resp, err := client.CreateKeyspace(commandCtx, req) 203 if err != nil { 204 return err 205 } 206 207 data, err := cli.MarshalJSON(resp.Keyspace) 208 if err != nil { 209 return err 210 } 211 212 fmt.Printf("Successfully created keyspace %s. Result:\n%s\n", name, data) 213 214 return nil 215 } 216 217 var deleteKeyspaceOptions = struct { 218 Recursive bool 219 Force bool 220 }{} 221 222 func commandDeleteKeyspace(cmd *cobra.Command, args []string) error { 223 cli.FinishedParsing(cmd) 224 225 ks := cmd.Flags().Arg(0) 226 _, err := client.DeleteKeyspace(commandCtx, &vtctldatapb.DeleteKeyspaceRequest{ 227 Keyspace: ks, 228 Recursive: deleteKeyspaceOptions.Recursive, 229 Force: deleteKeyspaceOptions.Force, 230 }) 231 232 if err != nil { 233 return fmt.Errorf("DeleteKeyspace(%v) error: %w; please check the topo", ks, err) 234 } 235 236 fmt.Printf("Successfully deleted keyspace %v.\n", ks) 237 238 return nil 239 } 240 241 func commandFindAllShardsInKeyspace(cmd *cobra.Command, args []string) error { 242 cli.FinishedParsing(cmd) 243 244 ks := cmd.Flags().Arg(0) 245 resp, err := client.FindAllShardsInKeyspace(commandCtx, &vtctldatapb.FindAllShardsInKeyspaceRequest{ 246 Keyspace: ks, 247 }) 248 249 if err != nil { 250 return err 251 } 252 253 data, err := cli.MarshalJSON(resp) 254 if err != nil { 255 return err 256 } 257 258 fmt.Printf("%s\n", data) 259 return nil 260 } 261 262 func commandGetKeyspace(cmd *cobra.Command, args []string) error { 263 cli.FinishedParsing(cmd) 264 265 ks := cmd.Flags().Arg(0) 266 resp, err := client.GetKeyspace(commandCtx, &vtctldatapb.GetKeyspaceRequest{ 267 Keyspace: ks, 268 }) 269 if err != nil { 270 return err 271 } 272 273 data, err := cli.MarshalJSON(resp.Keyspace) 274 if err != nil { 275 return err 276 } 277 278 fmt.Printf("%s\n", data) 279 280 return nil 281 } 282 283 func commandGetKeyspaces(cmd *cobra.Command, args []string) error { 284 cli.FinishedParsing(cmd) 285 286 resp, err := client.GetKeyspaces(commandCtx, &vtctldatapb.GetKeyspacesRequest{}) 287 if err != nil { 288 return err 289 } 290 291 data, err := cli.MarshalJSON(resp.Keyspaces) 292 if err != nil { 293 return err 294 } 295 296 fmt.Printf("%s\n", data) 297 298 return nil 299 } 300 301 var removeKeyspaceCellOptions = struct { 302 Force bool 303 Recursive bool 304 }{} 305 306 func commandRemoveKeyspaceCell(cmd *cobra.Command, args []string) error { 307 cli.FinishedParsing(cmd) 308 309 keyspace := cmd.Flags().Arg(0) 310 cell := cmd.Flags().Arg(1) 311 312 _, err := client.RemoveKeyspaceCell(commandCtx, &vtctldatapb.RemoveKeyspaceCellRequest{ 313 Keyspace: keyspace, 314 Cell: cell, 315 Force: removeKeyspaceCellOptions.Force, 316 Recursive: removeKeyspaceCellOptions.Recursive, 317 }) 318 319 if err != nil { 320 return err 321 } 322 323 fmt.Printf("Successfully removed keyspace %s from cell %s\n", keyspace, cell) 324 325 return nil 326 } 327 328 var setKeyspaceDurabilityPolicyOptions = struct { 329 DurabilityPolicy string 330 }{} 331 332 func commandSetKeyspaceDurabilityPolicy(cmd *cobra.Command, args []string) error { 333 keyspace := cmd.Flags().Arg(0) 334 cli.FinishedParsing(cmd) 335 336 resp, err := client.SetKeyspaceDurabilityPolicy(commandCtx, &vtctldatapb.SetKeyspaceDurabilityPolicyRequest{ 337 Keyspace: keyspace, 338 DurabilityPolicy: setKeyspaceDurabilityPolicyOptions.DurabilityPolicy, 339 }) 340 if err != nil { 341 return err 342 } 343 344 data, err := cli.MarshalJSON(resp) 345 if err != nil { 346 return err 347 } 348 349 fmt.Printf("%s\n", data) 350 return nil 351 } 352 353 var validateSchemaKeyspaceOptions = struct { 354 ExcludeTables []string 355 IncludeViews bool 356 SkipNoPrimary bool 357 IncludeVSchema bool 358 }{} 359 360 func commandValidateSchemaKeyspace(cmd *cobra.Command, args []string) error { 361 cli.FinishedParsing(cmd) 362 363 ks := cmd.Flags().Arg(0) 364 resp, err := client.ValidateSchemaKeyspace(commandCtx, &vtctldatapb.ValidateSchemaKeyspaceRequest{ 365 Keyspace: ks, 366 ExcludeTables: validateSchemaKeyspaceOptions.ExcludeTables, 367 IncludeVschema: validateSchemaKeyspaceOptions.IncludeVSchema, 368 SkipNoPrimary: validateSchemaKeyspaceOptions.SkipNoPrimary, 369 IncludeViews: validateSchemaKeyspaceOptions.IncludeViews, 370 }) 371 372 if err != nil { 373 return err 374 } 375 376 data, err := cli.MarshalJSON(resp) 377 if err != nil { 378 return err 379 } 380 381 fmt.Printf("%s\n", data) 382 return nil 383 } 384 385 func commandValidateVersionKeyspace(cmd *cobra.Command, args []string) error { 386 cli.FinishedParsing(cmd) 387 388 ks := cmd.Flags().Arg(0) 389 resp, err := client.ValidateVersionKeyspace(commandCtx, &vtctldatapb.ValidateVersionKeyspaceRequest{ 390 Keyspace: ks, 391 }) 392 393 if err != nil { 394 return err 395 } 396 397 data, err := cli.MarshalJSON(resp) 398 if err != nil { 399 return err 400 } 401 402 fmt.Printf("%s\n", data) 403 return nil 404 } 405 406 func init() { 407 CreateKeyspace.Flags().BoolVarP(&createKeyspaceOptions.Force, "force", "f", false, "Proceeds even if the keyspace already exists. Does not overwrite the existing keyspace record.") 408 CreateKeyspace.Flags().BoolVarP(&createKeyspaceOptions.AllowEmptyVSchema, "allow-empty-vschema", "e", false, "Allows a new keyspace to have no vschema.") 409 CreateKeyspace.Flags().Var(&createKeyspaceOptions.ServedFromsMap, "served-from", "Specifies a set of db_type:keyspace pairs used to serve traffic for the keyspace.") 410 CreateKeyspace.Flags().Var(&createKeyspaceOptions.KeyspaceType, "type", "The type of the keyspace.") 411 CreateKeyspace.Flags().StringVar(&createKeyspaceOptions.BaseKeyspace, "base-keyspace", "", "The base keyspace for a snapshot keyspace.") 412 CreateKeyspace.Flags().StringVar(&createKeyspaceOptions.SnapshotTimestamp, "snapshot-timestamp", "", "The snapshot time for a snapshot keyspace, as a timestamp in RFC3339 format.") 413 CreateKeyspace.Flags().StringVar(&createKeyspaceOptions.DurabilityPolicy, "durability-policy", "none", "Type of durability to enforce for this keyspace. Default is none. Possible values include 'semi_sync' and others as dictated by registered plugins.") 414 Root.AddCommand(CreateKeyspace) 415 416 DeleteKeyspace.Flags().BoolVarP(&deleteKeyspaceOptions.Recursive, "recursive", "r", false, "Recursively delete all shards in the keyspace, and all tablets in those shards.") 417 DeleteKeyspace.Flags().BoolVarP(&deleteKeyspaceOptions.Force, "force", "f", false, "Delete the keyspace even if it cannot be locked; this should only be used for cleanup operations.") 418 Root.AddCommand(DeleteKeyspace) 419 420 Root.AddCommand(FindAllShardsInKeyspace) 421 Root.AddCommand(GetKeyspace) 422 Root.AddCommand(GetKeyspaces) 423 424 RemoveKeyspaceCell.Flags().BoolVarP(&removeKeyspaceCellOptions.Force, "force", "f", false, "Proceed even if the cell's topology server cannot be reached. The assumption is that you turned down the entire cell, and just need to update the global topo data.") 425 RemoveKeyspaceCell.Flags().BoolVarP(&removeKeyspaceCellOptions.Recursive, "recursive", "r", false, "Also delete all tablets in that cell beloning to the specified keyspace.") 426 Root.AddCommand(RemoveKeyspaceCell) 427 428 SetKeyspaceDurabilityPolicy.Flags().StringVar(&setKeyspaceDurabilityPolicyOptions.DurabilityPolicy, "durability-policy", "none", "Type of durability to enforce for this keyspace. Default is none. Other values include 'semi_sync' and others as dictated by registered plugins.") 429 Root.AddCommand(SetKeyspaceDurabilityPolicy) 430 431 ValidateSchemaKeyspace.Flags().BoolVar(&validateSchemaKeyspaceOptions.IncludeViews, "include-views", false, "Includes views in compared schemas.") 432 ValidateSchemaKeyspace.Flags().BoolVar(&validateSchemaKeyspaceOptions.IncludeVSchema, "include-vschema", false, "Includes VSchema validation in validation results.") 433 ValidateSchemaKeyspace.Flags().BoolVar(&validateSchemaKeyspaceOptions.SkipNoPrimary, "skip-no-primary", false, "Skips validation on whether or not a primary exists in shards.") 434 ValidateSchemaKeyspace.Flags().StringSliceVar(&validateSchemaKeyspaceOptions.ExcludeTables, "exclude-tables", []string{}, "Tables to exclude during schema comparison.") 435 Root.AddCommand(ValidateSchemaKeyspace) 436 437 Root.AddCommand(ValidateVersionKeyspace) 438 }