Files
nomad/command/node_pool_apply.go
James Rasell c80c60965f node pool: Allow specifying node identity ttl in HCL or JSON spec. (#26825)
The node identity TTL defaults to 24hr but can be altered by
setting the node identity TTL parameter. In order to allow setting
and viewing the value, the field is now plumbed through the CLI
and HTTP API.

In order to parse the HCL, a new helper package has been created
which contains generic parsing and decoding functionality for
dealing with HCL that contains time durations. hclsimple can be
used when this functionality is not needed. In order to parse the
JSON, custom marshal and unmarshal functions have been created as
used in many other places.

The node pool init command has been updated to include this new
parameter, although commented out, so reference. The info command
now includes the TTL in its output too.
2025-09-24 14:20:34 +01:00

146 lines
3.3 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package command
import (
"encoding/json"
"fmt"
"io"
"os"
"strings"
"github.com/hashicorp/nomad/api"
"github.com/hashicorp/nomad/helper/hcl"
"github.com/posener/complete"
)
type NodePoolApplyCommand struct {
Meta
}
func (c *NodePoolApplyCommand) Name() string {
return "node pool apply"
}
func (c *NodePoolApplyCommand) Synopsis() string {
return "Create or update a node pool"
}
func (c *NodePoolApplyCommand) Help() string {
helpText := `
Usage: nomad node pool apply [options] <input>
Apply is used to create or update a node pool. The specification file is read
from stdin by specifying "-", otherwise a path to the file is expected.
If ACLs are enabled, this command requires a token with the 'write' capability
in a 'node_pool' policy that matches the node pool being targeted. In
federated clusters, the node pool will be created in the authoritative region
and will be replicated to all federated regions.
General Options:
` + generalOptionsUsage(usageOptsDefault) + `
Apply Options:
-json
Parse the input as a JSON node pool specification.
`
return strings.TrimSpace(helpText)
}
func (c *NodePoolApplyCommand) AutocompleteFlags() complete.Flags {
return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
complete.Flags{
"-json": complete.PredictNothing,
})
}
func (c *NodePoolApplyCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictOr(
complete.PredictFiles("*.hcl"),
complete.PredictFiles("*.json"),
)
}
func (c *NodePoolApplyCommand) Run(args []string) int {
var jsonInput bool
flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
flags.BoolVar(&jsonInput, "json", false, "")
if err := flags.Parse(args); err != nil {
return 1
}
// Check that we only have one argument.
args = flags.Args()
if len(args) != 1 {
c.Ui.Error("This command takes one argument: <input>")
c.Ui.Error(commandErrorText(c))
return 1
}
// Read input content.
path := args[0]
var content []byte
var err error
switch path {
case "-":
content, err = io.ReadAll(os.Stdin)
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to read stdin: %v", err))
return 1
}
// Set .hcl extension so the decoder doesn't fail.
if !jsonInput {
path = "stdin.nomad.hcl"
}
default:
content, err = os.ReadFile(path)
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to read file %q: %v", path, err))
return 1
}
}
// Parse input.
var poolSpec nodePoolSpec
if jsonInput {
err = json.Unmarshal(content, &poolSpec.NodePool)
} else {
hclParser := hcl.NewParser()
if hclDiags := hclParser.Parse(content, &poolSpec, path); hclDiags.HasErrors() {
err = hclDiags
}
}
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to parse input content: %v", err))
return 1
}
// Make API request.
client, err := c.Meta.Client()
if err != nil {
c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
return 1
}
_, err = client.NodePools().Register(poolSpec.NodePool, nil)
if err != nil {
c.Ui.Error(fmt.Sprintf("Error applying node pool: %s", err))
return 1
}
c.Ui.Output(fmt.Sprintf("Successfully applied node pool %q!", poolSpec.NodePool.Name))
return 0
}
type nodePoolSpec struct {
NodePool *api.NodePool `hcl:"node_pool,block"`
}