dynamic host volumes: Sentinel improvements for CLI (#24592)

The create/register volume RPCs support a policy override flag for
soft-mandatory Sentinel policies, but the CLI and Go API were missing support
for it.

Also add support for Sentinel warnings to the Go API and CLI.

Ref: https://github.com/hashicorp/nomad/pull/24479
This commit is contained in:
Tim Gross
2024-12-03 09:48:36 -05:00
parent 46a39560bb
commit d700538921
5 changed files with 69 additions and 23 deletions

View File

@@ -148,10 +148,26 @@ func (c *Client) HostVolumes() *HostVolumes {
type HostVolumeCreateRequest struct {
Volume *HostVolume
// PolicyOverride overrides Sentinel soft-mandatory policy enforcement
PolicyOverride bool
}
type HostVolumeRegisterRequest struct {
Volume *HostVolume
// PolicyOverride overrides Sentinel soft-mandatory policy enforcement
PolicyOverride bool
}
type HostVolumeCreateResponse struct {
Volume *HostVolume
Warnings string
}
type HostVolumeRegisterResponse struct {
Volume *HostVolume
Warnings string
}
type HostVolumeListRequest struct {
@@ -165,28 +181,24 @@ type HostVolumeDeleteRequest struct {
// Create forwards to client agents so a host volume can be created on those
// hosts, and registers the volume with Nomad servers.
func (hv *HostVolumes) Create(req *HostVolumeCreateRequest, opts *WriteOptions) (*HostVolume, *WriteMeta, error) {
var out struct {
Volume *HostVolume
}
func (hv *HostVolumes) Create(req *HostVolumeCreateRequest, opts *WriteOptions) (*HostVolumeCreateResponse, *WriteMeta, error) {
var out *HostVolumeCreateResponse
wm, err := hv.client.put("/v1/volume/host/create", req, &out, opts)
if err != nil {
return nil, wm, err
}
return out.Volume, wm, nil
return out, wm, nil
}
// Register registers a host volume that was created out-of-band with the Nomad
// servers.
func (hv *HostVolumes) Register(req *HostVolumeRegisterRequest, opts *WriteOptions) (*HostVolume, *WriteMeta, error) {
var out struct {
Volume *HostVolume
}
func (hv *HostVolumes) Register(req *HostVolumeRegisterRequest, opts *WriteOptions) (*HostVolumeRegisterResponse, *WriteMeta, error) {
var out *HostVolumeRegisterResponse
wm, err := hv.client.put("/v1/volume/host/register", req, &out, opts)
if err != nil {
return nil, wm, err
}
return out.Volume, wm, nil
return out, wm, nil
}
// Get queries for a single host volume, by ID

View File

@@ -46,6 +46,9 @@ Create Options:
Display full information when monitoring volume state. Used for dynamic host
volumes only.
-policy-override
Sets the flag to force override any soft mandatory Sentinel policies. Used
for dynamic host volumes only.
`
return strings.TrimSpace(helpText)
@@ -54,8 +57,9 @@ Create Options:
func (c *VolumeCreateCommand) AutocompleteFlags() complete.Flags {
return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
complete.Flags{
"-detach": complete.PredictNothing,
"-verbose": complete.PredictNothing,
"-detach": complete.PredictNothing,
"-verbose": complete.PredictNothing,
"-policy-override": complete.PredictNothing,
})
}
@@ -70,10 +74,11 @@ func (c *VolumeCreateCommand) Synopsis() string {
func (c *VolumeCreateCommand) Name() string { return "volume create" }
func (c *VolumeCreateCommand) Run(args []string) int {
var detach, verbose bool
var detach, verbose, override bool
flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
flags.BoolVar(&detach, "detach", false, "detach from monitor")
flags.BoolVar(&verbose, "verbose", false, "display full volume IDs")
flags.BoolVar(&override, "policy-override", false, "override soft mandatory Sentinel policies")
flags.Usage = func() { c.Ui.Output(c.Help()) }
if err := flags.Parse(args); err != nil {
@@ -124,7 +129,7 @@ func (c *VolumeCreateCommand) Run(args []string) int {
case "csi":
return c.csiCreate(client, ast)
case "host":
return c.hostVolumeCreate(client, ast, detach, verbose)
return c.hostVolumeCreate(client, ast, detach, verbose, override)
default:
c.Ui.Error(fmt.Sprintf("Error unknown volume type: %s", volType))
return 1

View File

@@ -19,7 +19,7 @@ import (
)
func (c *VolumeCreateCommand) hostVolumeCreate(
client *api.Client, ast *ast.File, detach, verbose bool) int {
client *api.Client, ast *ast.File, detach, verbose, override bool) int {
vol, err := decodeHostVolume(ast)
if err != nil {
@@ -28,13 +28,21 @@ func (c *VolumeCreateCommand) hostVolumeCreate(
}
req := &api.HostVolumeCreateRequest{
Volume: vol,
Volume: vol,
PolicyOverride: override,
}
vol, _, err = client.HostVolumes().Create(req, nil)
resp, _, err := client.HostVolumes().Create(req, nil)
if err != nil {
c.Ui.Error(fmt.Sprintf("Error creating volume: %s", err))
return 1
}
vol = resp.Volume
if resp.Warnings != "" {
c.Ui.Output(
c.Colorize().Color(
fmt.Sprintf("[bold][yellow]Volume Warnings:\n%s[reset]\n", resp.Warnings)))
}
var volID string
var lastIndex uint64

View File

@@ -34,13 +34,23 @@ Usage: nomad volume register [options] <input>
General Options:
` + generalOptionsUsage(usageOptsDefault)
` + generalOptionsUsage(usageOptsDefault) + `
Register Options:
-policy-override
Sets the flag to force override any soft mandatory Sentinel policies. Used
for dynamic host volumes only.
`
return strings.TrimSpace(helpText)
}
func (c *VolumeRegisterCommand) AutocompleteFlags() complete.Flags {
return c.Meta.AutocompleteFlags(FlagSetClient)
return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
complete.Flags{
"-policy-override": complete.PredictNothing,
})
}
func (c *VolumeRegisterCommand) AutocompleteArgs() complete.Predictor {
@@ -54,7 +64,9 @@ func (c *VolumeRegisterCommand) Synopsis() string {
func (c *VolumeRegisterCommand) Name() string { return "volume register" }
func (c *VolumeRegisterCommand) Run(args []string) int {
var override bool
flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
flags.BoolVar(&override, "policy-override", false, "override soft mandatory Sentinel policies")
flags.Usage = func() { c.Ui.Output(c.Help()) }
if err := flags.Parse(args); err != nil {
@@ -106,7 +118,7 @@ func (c *VolumeRegisterCommand) Run(args []string) int {
case "csi":
return c.csiRegister(client, ast)
case "host":
return c.hostVolumeRegister(client, ast)
return c.hostVolumeRegister(client, ast, override)
default:
c.Ui.Error(fmt.Sprintf("Error unknown volume type: %s", volType))
return 1

View File

@@ -10,7 +10,7 @@ import (
"github.com/hashicorp/nomad/api"
)
func (c *VolumeRegisterCommand) hostVolumeRegister(client *api.Client, ast *ast.File) int {
func (c *VolumeRegisterCommand) hostVolumeRegister(client *api.Client, ast *ast.File, override bool) int {
vol, err := decodeHostVolume(ast)
if err != nil {
c.Ui.Error(fmt.Sprintf("Error decoding the volume definition: %s", err))
@@ -18,13 +18,22 @@ func (c *VolumeRegisterCommand) hostVolumeRegister(client *api.Client, ast *ast.
}
req := &api.HostVolumeRegisterRequest{
Volume: vol,
Volume: vol,
PolicyOverride: override,
}
vol, _, err = client.HostVolumes().Register(req, nil)
resp, _, err := client.HostVolumes().Register(req, nil)
if err != nil {
c.Ui.Error(fmt.Sprintf("Error registering volume: %s", err))
return 1
}
vol = resp.Volume
if resp.Warnings != "" {
c.Ui.Output(
c.Colorize().Color(
fmt.Sprintf("[bold][yellow]Volume Warnings:\n%s[reset]\n", resp.Warnings)))
}
c.Ui.Output(fmt.Sprintf(
"Registered host volume %s with ID %s", vol.Name, vol.ID))