diff --git a/api/host_volumes.go b/api/host_volumes.go index 985695fa7..e417177d2 100644 --- a/api/host_volumes.go +++ b/api/host_volumes.go @@ -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 diff --git a/command/volume_create.go b/command/volume_create.go index 1e3dcbad0..5a4254e52 100644 --- a/command/volume_create.go +++ b/command/volume_create.go @@ -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 diff --git a/command/volume_create_host.go b/command/volume_create_host.go index 54cd31efb..dc0d1e1ae 100644 --- a/command/volume_create_host.go +++ b/command/volume_create_host.go @@ -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 diff --git a/command/volume_register.go b/command/volume_register.go index 19527cf6b..d47c93b22 100644 --- a/command/volume_register.go +++ b/command/volume_register.go @@ -34,13 +34,23 @@ Usage: nomad volume register [options] 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 diff --git a/command/volume_register_host.go b/command/volume_register_host.go index 4e3ce6ccd..b6cb213ca 100644 --- a/command/volume_register_host.go +++ b/command/volume_register_host.go @@ -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))