Skip to content

Commit

Permalink
Sync from server repo (c9992e7be4e)
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt Spilchen committed May 10, 2024
1 parent 8b4c82a commit 520dab9
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 11 deletions.
3 changes: 3 additions & 0 deletions commands/cluster_command_launcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ const (
connFlag = "conn"
connKey = "conn"
stopNodeFlag = "stop-hosts"
// VER-90436: restart -> start
startNodeFlag = "restart"
startHostFlag = "start-hosts"
)

// Flag and key for database replication
Expand Down
74 changes: 64 additions & 10 deletions commands/cmd_restart_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package commands

import (
"fmt"

"github.com/spf13/cobra"
"github.com/vertica/vcluster/vclusterops"
"github.com/vertica/vcluster/vclusterops/util"
Expand All @@ -30,8 +32,11 @@ type CmdRestartNodes struct {
CmdBase
restartNodesOptions *vclusterops.VStartNodesOptions

// Comma-separated list of vnode=host
vnodeListStr map[string]string
// comma-separated list of vnode=host
vnodeHostMap map[string]string

// comma-separated list of hosts
rawStartHostList []string
}

func makeCmdRestartNodes() *cobra.Command {
Expand Down Expand Up @@ -76,26 +81,36 @@ Examples:
// local flags
newCmd.setLocalFlags(cmd)

// require nodes to restart
markFlagsRequired(cmd, []string{"restart"})
// require nodes or hosts to restart
cmd.MarkFlagsOneRequired([]string{startNodeFlag, startHostFlag}...)

return cmd
}

// setLocalFlags will set the local flags the command has
func (c *CmdRestartNodes) setLocalFlags(cmd *cobra.Command) {
cmd.Flags().StringToStringVar(
&c.vnodeListStr,
"restart",
&c.vnodeHostMap,
startNodeFlag,
map[string]string{},
"Comma-separated list of <node_name=re_ip_host> pairs part of the database nodes that need to be restarted",
)
cmd.Flags().StringSliceVar(
&c.rawStartHostList,
startHostFlag,
[]string{},
"Comma-separated list of hosts that need to be started",
)
cmd.Flags().IntVar(
&c.restartNodesOptions.StatePollingTimeout,
"timeout",
util.DefaultTimeoutSeconds,
"The timeout (in seconds) to wait for polling node state operation",
)

// VER-90436: restart -> start
// users only input --restart or --start-hosts
cmd.MarkFlagsMutuallyExclusive([]string{startNodeFlag, startHostFlag}...)
}

func (c *CmdRestartNodes) Parse(inputArgv []string, logger vlog.Printer) error {
Expand All @@ -112,12 +127,23 @@ func (c *CmdRestartNodes) Parse(inputArgv []string, logger vlog.Printer) error {

func (c *CmdRestartNodes) validateParse(logger vlog.Printer) error {
logger.Info("Called validateParse()")
err := c.restartNodesOptions.ParseNodesList(c.vnodeListStr)
if err != nil {
return err

// VER-90436: restart -> start
// the node-host map can be loaded from the value of
// either --restart or --start-hosts
if len(c.rawStartHostList) > 0 {
err := c.buildRestartNodeHostMap()
if err != nil {
return err
}
} else {
err := c.restartNodesOptions.ParseNodesList(c.vnodeHostMap)
if err != nil {
return err
}
}

err = c.getCertFilesFromCertPaths(&c.restartNodesOptions.DatabaseOptions)
err := c.getCertFilesFromCertPaths(&c.restartNodesOptions.DatabaseOptions)
if err != nil {
return err
}
Expand Down Expand Up @@ -153,3 +179,31 @@ func (c *CmdRestartNodes) Run(vcc vclusterops.ClusterCommands) error {
func (c *CmdRestartNodes) SetDatabaseOptions(opt *vclusterops.DatabaseOptions) {
c.restartNodesOptions.DatabaseOptions = *opt
}

func (c *CmdRestartNodes) buildRestartNodeHostMap() error {
dbConfig, err := readConfig()
if err != nil {
return fmt.Errorf("--start-hosts can only be used when "+
"the config file is available, detail: %w", err)
}

hostNodeMap := make(map[string]string)
for _, n := range dbConfig.Nodes {
hostNodeMap[n.Address] = n.Name
}

for _, rawHost := range c.rawStartHostList {
ip, err := util.ResolveToOneIP(rawHost, c.restartNodesOptions.IPv6)
if err != nil {
return err
}
nodeName, ok := hostNodeMap[ip]
if !ok {
return fmt.Errorf("cannot find the address %s (of host %s) from the config file",
ip, rawHost)
}
c.restartNodesOptions.Nodes[nodeName] = ip
}

return nil
}
19 changes: 19 additions & 0 deletions commands/user_input_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,22 @@ func TestCreateConnection(t *testing.T) {
assert.Equal(t, dbName, dbConn.TargetDBName)
assert.Equal(t, hosts, dbConn.TargetHosts[0])
}

// VER-90436: restart -> start
func TestStartNode(t *testing.T) {
// either --restart or --start-hosts must be specified
err := simulateVClusterCli("vcluster restart_node")
assert.ErrorContains(t, err, "at least one of the flags in the group [restart start-hosts] is required")

// --restart should be followed with the key1=value1,key2=value2 format
err = simulateVClusterCli("vcluster restart_node --restart host1")
assert.ErrorContains(t, err, `"--restart" flag: host1 must be formatted as key=value`)

// --start-hosts should be used with the config file
err = simulateVClusterCli("vcluster restart_node --start-hosts host1")
assert.ErrorContains(t, err, "--start-hosts can only be used when the config file is available")

// --restart or --start-hosts cannot be both specified
err = simulateVClusterCli("vcluster restart_node --restart node1=host1 --start-hosts host1")
assert.ErrorContains(t, err, "[restart start-hosts] were all set")
}
2 changes: 1 addition & 1 deletion vclusterops/start_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ func VStartNodesOptionsFactory() VStartNodesOptions {

func (options *VStartNodesOptions) setDefaultValues() {
options.DatabaseOptions.setDefaultValues()
options.Nodes = make(map[string]string)
}

func (options *VStartNodesOptions) validateParseOptions(logger vlog.Printer) error {
Expand All @@ -90,7 +91,6 @@ func (options *VStartNodesOptions) analyzeOptions() (err error) {
// For example, map[string]string{vnodeName1: host1, vnodeName2: host2} is converted to
// map[string]string{vnodeName1: 192.168.1.101, vnodeName2: 192.168.1.102}
func (options *VStartNodesOptions) ParseNodesList(rawNodeMap map[string]string) error {
options.Nodes = make(map[string]string)
for k, v := range rawNodeMap {
ip, err := util.ResolveToOneIP(v, options.IPv6)
if err != nil {
Expand Down

0 comments on commit 520dab9

Please sign in to comment.