Skip to content

Commit

Permalink
Sync from server repo (9fd701fd630)
Browse files Browse the repository at this point in the history
  • Loading branch information
ctran committed May 31, 2024
1 parent 804280c commit 61fab78
Show file tree
Hide file tree
Showing 60 changed files with 1,335 additions and 182 deletions.
29 changes: 27 additions & 2 deletions commands/cluster_command_launcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ const (
eonModeKey = "eonMode"
configParamFlag = "config-param"
configParamKey = "configParam"
configParamFileFlag = "config-param-file"
configParamFileKey = "configParamFile"
logPathFlag = "log-path"
logPathKey = "logPath"
keyFileFlag = "key-file"
Expand All @@ -80,10 +82,15 @@ const (
subclusterFlag = "subcluster"
addNodeFlag = "new-hosts"
sandboxFlag = "sandbox"
saveRpFlag = "save-restore-point"
isolateMetadataFlag = "isolate-metadata"
createStorageLocationsFlag = "create-storage-locations"
sandboxKey = "sandbox"
connFlag = "conn"
connKey = "conn"
stopNodeFlag = "stop-hosts"
reIPFileFlag = "re-ip-file"
removeNodeFlag = "remove"
// VER-90436: restart -> start
startNodeFlag = "restart"
startHostFlag = "start-hosts"
Expand Down Expand Up @@ -542,13 +549,31 @@ func hideLocalFlags(cmd *cobra.Command, flags []string) {
}
}

// markFlagsRequired will mark local flags as required
func markFlagsRequired(cmd *cobra.Command, flags []string) {
// markFlagsRequired marks given flags as required
func markFlagsRequired(cmd *cobra.Command, flags ...string) {
for _, flag := range flags {
err := cmd.MarkFlagRequired(flag)
if err != nil {
fmt.Printf("Warning: fail to mark flag %q required, details: %v\n", flag, err)
}

// emphasize [Required] in the help message
f := cmd.Flags().Lookup(flag)
if f != nil { // empty flag means not found
f.Usage = "[Required] " + f.Usage
}
}
}

// markFlagsOneRequired marks one of the given flags as required
func markFlagsOneRequired(cmd *cobra.Command, flags []string) {
cmd.MarkFlagsOneRequired(flags...)
for _, flag := range flags {
f := cmd.Flags().Lookup(flag)
if f != nil { // empty flag means not found
oneRequiredGroup := f.Annotations["cobra_annotation_one_required"]
f.Usage = fmt.Sprintf("(One of %v is required) ", oneRequiredGroup) + f.Usage
}
}
}

Expand Down
8 changes: 4 additions & 4 deletions commands/cmd_add_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func makeCmdAddNode() *cobra.Command {
newCmd,
addNodeSubCmd,
"Add host(s) to an existing database",
`This subcommand adds one or more hosts to an existing database.
`This command adds one or more hosts to an existing database.
You must provide the --new-hosts option followed by one or more hosts to add as
a comma-separated list.
Expand All @@ -57,7 +57,7 @@ You cannot add hosts to a sandbox subcluster in an Eon Mode database.
Use the --node-names option to address issues resulting from a failed node
addition attempt. It's crucial to include all expected nodes in the catalog
when using this option. This subcommand removes any surplus nodes from the
when using this option. This command removes any surplus nodes from the
catalog, provided they are down, before commencing the node addition process.
Omitting the option will skip this node trimming process.
Expand All @@ -79,7 +79,7 @@ Examples:
newCmd.setLocalFlags(cmd)

// require hosts to add
markFlagsRequired(cmd, []string{addNodeFlag})
markFlagsRequired(cmd, addNodeFlag)

return cmd
}
Expand Down Expand Up @@ -199,7 +199,7 @@ func (c *CmdAddNode) Run(vcc vclusterops.ClusterCommands) error {
}

// write db info to vcluster config file
err := writeConfig(&vdb)
err := writeConfig(&vdb, true /*forceOverwrite*/)
if err != nil {
vcc.PrintWarning("fail to write config file, details: %s", err)
}
Expand Down
6 changes: 3 additions & 3 deletions commands/cmd_add_subcluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func makeCmdAddSubcluster() *cobra.Command {
newCmd,
addSCSubCmd,
"Add a subcluster",
`This subcommand adds a new subcluster to an existing Eon Mode database.
`This command adds a new subcluster to an existing Eon Mode database.
You must provide a subcluster name with the --subcluster option.
Expand Down Expand Up @@ -89,7 +89,7 @@ Examples:
newCmd.setHiddenFlags(cmd)

// require name of subcluster to add
markFlagsRequired(cmd, []string{subclusterFlag})
markFlagsRequired(cmd, subclusterFlag)

// hide eon mode flag since we expect it to come from config file, not from user input
hideLocalFlags(cmd, []string{eonModeFlag})
Expand Down Expand Up @@ -222,7 +222,7 @@ func (c *CmdAddSubcluster) Run(vcc vclusterops.ClusterCommands) error {
return err
}
// update db info in the config file
err = writeConfig(&vdb)
err = writeConfig(&vdb, true /*forceOverwrite*/)
if err != nil {
vcc.PrintWarning("fail to write config file, details: %s", err)
}
Expand Down
128 changes: 124 additions & 4 deletions commands/cmd_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
package commands

import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/spf13/cobra"
Expand All @@ -28,7 +30,9 @@ import (
)

const (
outputFilePerm = 0644
filePerm = 0644
configDirPerm = 0755
defConfigParamFileName = "config_param.json"
)

/* CmdBase
Expand All @@ -43,6 +47,7 @@ type CmdBase struct {
// to a file instead of being displayed in stdout. This is the file the output will
// be written to
output string
configParamFile string
passwordFile string
readPasswordFromPrompt bool
}
Expand Down Expand Up @@ -70,7 +75,7 @@ func (c *CmdBase) setCommonFlags(cmd *cobra.Command, flags []string) {
if len(flags) == 0 {
return
}
setConfigFlags(cmd, flags)
c.setConfigFlags(cmd, flags)
if util.StringInArray(passwordFlag, flags) {
c.setPasswordFlags(cmd)
}
Expand Down Expand Up @@ -132,7 +137,7 @@ func (c *CmdBase) setCommonFlags(cmd *cobra.Command, flags []string) {

// setConfigFlags sets the config flag as well as all the common flags that
// can also be set with values from the config file
func setConfigFlags(cmd *cobra.Command, flags []string) {
func (c *CmdBase) setConfigFlags(cmd *cobra.Command, flags []string) {
if util.StringInArray(dbNameFlag, flags) {
cmd.Flags().StringVarP(
&dbOptions.DBName,
Expand Down Expand Up @@ -209,7 +214,122 @@ func setConfigFlags(cmd *cobra.Command, flags []string) {
configParamFlag,
map[string]string{},
"Comma-separated list of NAME=VALUE pairs of existing configuration parameters")
cmd.Flags().StringVar(
&c.configParamFile,
configParamFileFlag,
"",
"Path to config parameter file")
}
}

func (c *CmdBase) initConfigParam() error {
// We need to find the path to the config param. The order of precedence is as follows:
// 1. Option
// 2. Default locations
// a. /opt/vertica/config/config_param.json if running vcluster in /opt/vertica/bin
// b. $HOME/.config/vcluster/config_param.json otherwise
//
// If none of these things are true, then we run the cli without a config param file.

if c.configParamFile != "" {
return nil
}

// Pick a default config param file

// If we are running vcluster from /opt/vertica/bin, we'll assume we
// have installed the vertica package on this machine and so can assume
// /opt/vertica/config exists too.
vclusterExePath, err := os.Executable()
if err != nil {
return err
}
if vclusterExePath == defaultExecutablePath {
if util.CheckPathExist(rpmConfDir) {
c.configParamFile = fmt.Sprintf("%s/%s", rpmConfDir, defConfigParamFileName)
return nil
}
}
// Finally default to the .config directory in the users home. This is used
// by many CLI applications.
cfgDir, err := os.UserConfigDir()
if err != nil {
return err
}
// Ensure the config directory exists.
path := filepath.Join(cfgDir, "vcluster")
err = os.MkdirAll(path, configDirPerm)
if err != nil {
// Just abort if we don't have write access to the config path
return err
}
c.configParamFile = fmt.Sprintf("%s/%s", path, defConfigParamFileName)
return nil
}

// setConfigParam sets the configuration parameters from config param file
func (c *CmdBase) setConfigParam(opt *vclusterops.DatabaseOptions) error {
err := c.initConfigParam()
if err != nil {
return err
}

if c.configParamFile == "" {
return nil
}
configParam, err := c.getConfigParamFromFile(c.configParamFile)
if err != nil {
return err
}
for name, val := range configParam {
// allow users to overwrite params in file with --config-param
if _, ok := opt.ConfigurationParameters[name]; ok {
continue
}
opt.ConfigurationParameters[name] = val
}
return nil
}

func (c *CmdBase) writeConfigParam(configParam map[string]string, forceOverwrite bool) error {
if !c.parser.Changed(configParamFlag) {
// no new config param specified, no need to write
return nil
}
if c.configParamFile == "" {
return fmt.Errorf("config param file path is empty")
}
if util.CheckPathExist(c.configParamFile) && !forceOverwrite {
return fmt.Errorf("file %s exist, consider using --force-overwrite-file to overwrite the file", c.configParamFile)
}
configParamBytes, err := json.Marshal(&configParam)
if err != nil {
return fmt.Errorf("fail to marshal configuration parameters, details: %w", err)
}
err = os.WriteFile(c.configParamFile, configParamBytes, filePerm)
if err != nil {
return fmt.Errorf("fail to write configuration parameters file, details: %w", err)
}
return nil
}

func (c *CmdBase) getConfigParamFromFile(configParamFile string) (map[string]string, error) {
if !util.CheckPathExist(configParamFile) {
return nil, nil
}
// Read config param from file
configParamBytes, err := os.ReadFile(configParamFile)
if err != nil {
return nil, fmt.Errorf("error reading config param from file %q: %w", configParamFile, err)
}

var configParam map[string]string
err = json.Unmarshal(configParamBytes, &configParam)
if err != nil {
return nil, fmt.Errorf("error reading config param from file %q: %w", configParamFile, err)
}

return configParam, nil
}

// setPasswordFlags sets all the password flags
Expand Down Expand Up @@ -334,7 +454,7 @@ func (c *CmdBase) initCmdOutputFile() (*os.File, error) {
if c.output == "" {
return nil, fmt.Errorf("output-file cannot be empty")
}
return os.OpenFile(c.output, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, outputFilePerm)
return os.OpenFile(c.output, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, filePerm)
}

// getCertFilesFromPaths will update cert and key file from cert path options
Expand Down
4 changes: 2 additions & 2 deletions commands/cmd_config_recover.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ Examples:
)

// require db-name, hosts, catalog-path, and data-path
markFlagsRequired(cmd, []string{dbNameFlag, hostsFlag, catalogPathFlag})
markFlagsRequired(cmd, dbNameFlag, hostsFlag, catalogPathFlag)

// local flags
newCmd.setLocalFlags(cmd)
Expand Down Expand Up @@ -120,7 +120,7 @@ func (c *CmdConfigRecover) Run(vcc vclusterops.ClusterCommands) error {
}
// write db info to vcluster config file
vdb.FirstStartAfterRevive = c.recoverConfigOptions.AfterRevive
err = writeConfig(&vdb)
err = writeConfig(&vdb, true /*forceOverwrite*/)
if err != nil {
return fmt.Errorf("fail to write config file, details: %s", err)
}
Expand Down
4 changes: 2 additions & 2 deletions commands/cmd_create_connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func makeCmdCreateConnection() *cobra.Command {
newCmd,
createConnectionSubCmd,
"create the content of the connection file",
`This subcommand is used to create the content of the connection file.
`This command is used to create the content of the connection file.
You must specify the database name and host list. If the database has a
password, you need to provide password. If the database uses
Expand All @@ -59,7 +59,7 @@ Examples:
// local flags
newCmd.setLocalFlags(cmd)

markFlagsRequired(cmd, []string{dbNameFlag, hostsFlag, connFlag})
markFlagsRequired(cmd, dbNameFlag, hostsFlag, connFlag)
return cmd
}

Expand Down
Loading

0 comments on commit 61fab78

Please sign in to comment.