Skip to content

Commit

Permalink
dynamic host volumes: Sentinel improvements for CLI (#24592)
Browse files Browse the repository at this point in the history
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: #24479
  • Loading branch information
tgross committed Dec 3, 2024
1 parent d6fd14f commit 8c3d8fe
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 23 deletions.
32 changes: 22 additions & 10 deletions api/host_volumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
Expand Down
13 changes: 9 additions & 4 deletions command/volume_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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,
})
}

Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
14 changes: 11 additions & 3 deletions command/volume_create_host.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
Expand Down
18 changes: 15 additions & 3 deletions command/volume_register.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
15 changes: 12 additions & 3 deletions command/volume_register_host.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,30 @@ 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))
return 1
}

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))

Expand Down

0 comments on commit 8c3d8fe

Please sign in to comment.