github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/command/var_get.go (about)

     1  package command
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"os"
     7  	"strings"
     8  
     9  	"github.com/hashicorp/nomad/api"
    10  	"github.com/mitchellh/cli"
    11  	"github.com/posener/complete"
    12  )
    13  
    14  type VarGetCommand struct {
    15  	Meta
    16  	outFmt string
    17  	tmpl   string
    18  }
    19  
    20  func (c *VarGetCommand) Help() string {
    21  	helpText := `
    22  Usage: nomad var get [options] <path>
    23  
    24    The 'var get' command is used to get the contents of an existing variable.
    25  
    26    If ACLs are enabled, this command requires a token with the 'variables:read'
    27    capability for the target variable's namespace and path.
    28  
    29  General Options:
    30  
    31    ` + generalOptionsUsage(usageOptsDefault) + `
    32  
    33  Get Options:
    34  
    35    -item <item key>
    36       Print only the value of the given item. Specifying this option will
    37       take precedence over other formatting directives. The result will not
    38       have a trailing newline making it ideal for piping to other processes.
    39  
    40    -out ( go-template | hcl | json | none | table )
    41       Format to render the variable in. When using "go-template", you must
    42       provide the template content with the "-template" option. Defaults
    43       to "table" when stdout is a terminal and to "json" when stdout is
    44       redirected.
    45  
    46    -template
    47       Template to render output with. Required when output is "go-template".
    48  
    49  `
    50  	return strings.TrimSpace(helpText)
    51  }
    52  
    53  func (c *VarGetCommand) AutocompleteFlags() complete.Flags {
    54  	return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
    55  		complete.Flags{
    56  			"-out":      complete.PredictSet("go-template", "hcl", "json", "none", "table"),
    57  			"-template": complete.PredictAnything,
    58  		},
    59  	)
    60  }
    61  
    62  func (c *VarGetCommand) AutocompleteArgs() complete.Predictor {
    63  	return VariablePathPredictor(c.Meta.Client)
    64  }
    65  
    66  func (c *VarGetCommand) Synopsis() string {
    67  	return "Read a variable"
    68  }
    69  
    70  func (c *VarGetCommand) Name() string { return "var get" }
    71  
    72  func (c *VarGetCommand) Run(args []string) int {
    73  	var out, item string
    74  
    75  	flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
    76  	flags.Usage = func() { c.Ui.Output(c.Help()) }
    77  
    78  	flags.StringVar(&item, "item", "", "")
    79  	flags.StringVar(&c.tmpl, "template", "", "")
    80  
    81  	if fileInfo, _ := os.Stdout.Stat(); (fileInfo.Mode() & os.ModeCharDevice) != 0 {
    82  		flags.StringVar(&c.outFmt, "out", "table", "")
    83  	} else {
    84  		flags.StringVar(&c.outFmt, "out", "json", "")
    85  	}
    86  
    87  	if err := flags.Parse(args); err != nil {
    88  		return 1
    89  	}
    90  
    91  	// Check that we got one argument
    92  	args = flags.Args()
    93  	if len(args) != 1 {
    94  		c.Ui.Error("This command takes one argument: <path>")
    95  		c.Ui.Error(commandErrorText(c))
    96  		return 1
    97  	}
    98  
    99  	if err := c.validateOutputFlag(); err != nil {
   100  		c.Ui.Error(err.Error())
   101  		c.Ui.Error(commandErrorText(c))
   102  		return 1
   103  	}
   104  
   105  	if c.Meta.namespace == "*" {
   106  		c.Ui.Error(errWildcardNamespaceNotAllowed)
   107  		return 1
   108  	}
   109  
   110  	path := args[0]
   111  
   112  	// Get the HTTP client
   113  	client, err := c.Meta.Client()
   114  	if err != nil {
   115  		c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
   116  		return 1
   117  	}
   118  
   119  	qo := &api.QueryOptions{
   120  		Namespace: c.Meta.namespace,
   121  	}
   122  
   123  	sv, _, err := client.Variables().Read(path, qo)
   124  	if err != nil {
   125  		if err.Error() == "variable not found" {
   126  			c.Ui.Warn(errVariableNotFound)
   127  			return 1
   128  		}
   129  		c.Ui.Error(fmt.Sprintf("Error retrieving variable: %s", err))
   130  		return 1
   131  	}
   132  	// If the user provided an item key, return that value instead of the whole
   133  	// object
   134  	if item != "" {
   135  		if v, ok := sv.Items[item]; ok {
   136  			fmt.Print(v)
   137  			return 0
   138  		} else {
   139  			c.Ui.Error(fmt.Sprintf("Variable does not contain %q item", args[1]))
   140  			return 1
   141  		}
   142  	}
   143  
   144  	// Output whole object
   145  	switch c.outFmt {
   146  	case "json":
   147  		out = sv.AsPrettyJSON()
   148  	case "hcl":
   149  		out = renderAsHCL(sv)
   150  	case "go-template":
   151  		if out, err = renderWithGoTemplate(sv, c.tmpl); err != nil {
   152  			c.Ui.Error(err.Error())
   153  			return 1
   154  		}
   155  	case "none":
   156  		// exit without more output
   157  		return 0
   158  	default:
   159  		// the renderSVAsUiTable func writes directly to the ui and doesn't error.
   160  		renderSVAsUiTable(sv, c)
   161  		return 0
   162  	}
   163  
   164  	c.Ui.Output(out)
   165  	return 0
   166  }
   167  
   168  func (c *VarGetCommand) validateOutputFlag() error {
   169  	if c.outFmt != "go-template" && c.tmpl != "" {
   170  		return errors.New(errUnexpectedTemplate)
   171  	}
   172  	switch c.outFmt {
   173  	case "hcl", "json", "none", "table":
   174  		return nil
   175  	case "go-template": //noop - needs more validation
   176  		if c.tmpl == "" {
   177  			return errors.New(errMissingTemplate)
   178  		}
   179  		return nil
   180  	default:
   181  		return errors.New(errInvalidOutFormat)
   182  	}
   183  }
   184  
   185  func (c *VarGetCommand) GetConcurrentUI() cli.ConcurrentUi {
   186  	return cli.ConcurrentUi{Ui: c.Ui}
   187  }