vitess.io/vitess@v0.16.2/go/cmd/vtctldclient/command/routing_rules.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 "os" 23 "strings" 24 25 "github.com/spf13/cobra" 26 27 "vitess.io/vitess/go/cmd/vtctldclient/cli" 28 "vitess.io/vitess/go/json2" 29 30 vschemapb "vitess.io/vitess/go/vt/proto/vschema" 31 vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" 32 ) 33 34 var ( 35 // ApplyRoutingRules makes an ApplyRoutingRules gRPC call to a vtctld. 36 ApplyRoutingRules = &cobra.Command{ 37 Use: "ApplyRoutingRules {--rules RULES | --rules-file RULES_FILE} [--cells=c1,c2,...] [--skip-rebuild] [--dry-run]", 38 Short: "Applies the VSchema routing rules.", 39 DisableFlagsInUseLine: true, 40 Args: cobra.NoArgs, 41 RunE: commandApplyRoutingRules, 42 } 43 // GetRoutingRules makes a GetRoutingRules gRPC call to a vtctld. 44 GetRoutingRules = &cobra.Command{ 45 Use: "GetRoutingRules", 46 Short: "Displays the VSchema routing rules.", 47 DisableFlagsInUseLine: true, 48 Args: cobra.NoArgs, 49 RunE: commandGetRoutingRules, 50 } 51 ) 52 53 var applyRoutingRulesOptions = struct { 54 Rules string 55 RulesFilePath string 56 Cells []string 57 SkipRebuild bool 58 DryRun bool 59 }{} 60 61 func commandApplyRoutingRules(cmd *cobra.Command, args []string) error { 62 if applyRoutingRulesOptions.Rules != "" && applyRoutingRulesOptions.RulesFilePath != "" { 63 return fmt.Errorf("cannot pass both --rules (=%s) and --rules-file (=%s)", applyRoutingRulesOptions.Rules, applyRoutingRulesOptions.RulesFilePath) 64 } 65 66 if applyRoutingRulesOptions.Rules == "" && applyRoutingRulesOptions.RulesFilePath == "" { 67 return errors.New("must pass exactly one of --rules or --rules-file") 68 } 69 70 cli.FinishedParsing(cmd) 71 72 var rulesBytes []byte 73 if applyRoutingRulesOptions.RulesFilePath != "" { 74 data, err := os.ReadFile(applyRoutingRulesOptions.RulesFilePath) 75 if err != nil { 76 return err 77 } 78 79 rulesBytes = data 80 } else { 81 rulesBytes = []byte(applyRoutingRulesOptions.Rules) 82 } 83 84 rr := &vschemapb.RoutingRules{} 85 if err := json2.Unmarshal(rulesBytes, &rr); err != nil { 86 return err 87 } 88 89 // Round-trip so when we display the result it's readable. 90 data, err := cli.MarshalJSON(rr) 91 if err != nil { 92 return err 93 } 94 95 if applyRoutingRulesOptions.DryRun { 96 fmt.Printf("[DRY RUN] Would have saved new RoutingRules object:\n%s\n", data) 97 98 if applyRoutingRulesOptions.SkipRebuild { 99 fmt.Println("[DRY RUN] Would not have rebuilt VSchema graph, would have required operator to run RebuildVSchemaGraph for changes to take effect") 100 } else { 101 fmt.Print("[DRY RUN] Would have rebuilt the VSchema graph") 102 if len(applyRoutingRulesOptions.Cells) == 0 { 103 fmt.Print(" in all cells\n") 104 } else { 105 fmt.Printf(" in the following cells: %s.\n", strings.Join(applyRoutingRulesOptions.Cells, ", ")) 106 } 107 } 108 109 return nil 110 } 111 112 _, err = client.ApplyRoutingRules(commandCtx, &vtctldatapb.ApplyRoutingRulesRequest{ 113 RoutingRules: rr, 114 SkipRebuild: applyRoutingRulesOptions.SkipRebuild, 115 RebuildCells: applyRoutingRulesOptions.Cells, 116 }) 117 if err != nil { 118 return err 119 } 120 121 fmt.Printf("New RoutingRules object:\n%s\nIf this is not what you expected, check the input data (as JSON parsing will skip unexpected fields).\n", data) 122 123 if applyRoutingRulesOptions.SkipRebuild { 124 fmt.Println("Skipping rebuild of VSchema graph, will need to run RebuildVSchemaGraph for changes to take effect.") 125 } 126 127 return nil 128 } 129 130 func commandGetRoutingRules(cmd *cobra.Command, args []string) error { 131 cli.FinishedParsing(cmd) 132 133 resp, err := client.GetRoutingRules(commandCtx, &vtctldatapb.GetRoutingRulesRequest{}) 134 if err != nil { 135 return err 136 } 137 138 data, err := cli.MarshalJSON(resp.RoutingRules) 139 if err != nil { 140 return err 141 } 142 143 fmt.Printf("%s\n", data) 144 145 return nil 146 } 147 148 func init() { 149 ApplyRoutingRules.Flags().StringVarP(&applyRoutingRulesOptions.Rules, "rules", "r", "", "Routing rules, specified as a string.") 150 ApplyRoutingRules.Flags().StringVarP(&applyRoutingRulesOptions.RulesFilePath, "rules-file", "f", "", "Path to a file containing routing rules specified as JSON.") 151 ApplyRoutingRules.Flags().StringSliceVarP(&applyRoutingRulesOptions.Cells, "cells", "c", nil, "Limit the VSchema graph rebuildingg to the specified cells. Ignored if --skip-rebuild is specified.") 152 ApplyRoutingRules.Flags().BoolVar(&applyRoutingRulesOptions.SkipRebuild, "skip-rebuild", false, "Skip rebuilding the SrvVSchema objects.") 153 ApplyRoutingRules.Flags().BoolVarP(&applyRoutingRulesOptions.DryRun, "dry-run", "d", false, "Load the specified routing rules as a validation step, but do not actually apply the rules to the topo.") 154 Root.AddCommand(ApplyRoutingRules) 155 156 Root.AddCommand(GetRoutingRules) 157 }