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  }