From 97d92698231614fb9dc4f851344e763b6b1dc42e Mon Sep 17 00:00:00 2001 From: Tim Gross Date: Mon, 16 Dec 2024 09:10:58 -0500 Subject: [PATCH] dynamic host volumes: add -type flag to volume init (#24667) Adds a `-type` flag to the `volume init` command that generates an example volume specification with only those fields relevant to dynamic host volumes. This changeset also moves the string literals into uses of `go:embed` Ref: https://github.com/hashicorp/nomad/pull/24479 --- command/asset/asset.go | 12 +++ command/asset/volume.csi.hcl | 70 +++++++++++++ command/asset/volume.csi.json | 72 +++++++++++++ command/asset/volume.host.hcl | 28 +++++ command/asset/volume.host.json | 24 +++++ command/volume_init.go | 181 +++++---------------------------- 6 files changed, 230 insertions(+), 157 deletions(-) create mode 100644 command/asset/volume.csi.hcl create mode 100644 command/asset/volume.csi.json create mode 100644 command/asset/volume.host.hcl create mode 100644 command/asset/volume.host.json diff --git a/command/asset/asset.go b/command/asset/asset.go index b6c1d9112f6..3570cb78b05 100644 --- a/command/asset/asset.go +++ b/command/asset/asset.go @@ -22,3 +22,15 @@ var NodePoolSpec []byte //go:embed pool.nomad.json var NodePoolSpecJSON []byte + +//go:embed volume.csi.hcl +var CSIVolumeSpecHCL []byte + +//go:embed volume.csi.json +var CSIVolumeSpecJSON []byte + +//go:embed volume.host.hcl +var HostVolumeSpecHCL []byte + +//go:embed volume.host.json +var HostVolumeSpecJSON []byte diff --git a/command/asset/volume.csi.hcl b/command/asset/volume.csi.hcl new file mode 100644 index 00000000000..998edadeff9 --- /dev/null +++ b/command/asset/volume.csi.hcl @@ -0,0 +1,70 @@ +id = "ebs_prod_db1" +namespace = "default" +name = "database" +type = "csi" +plugin_id = "plugin_id" + +# For 'nomad volume register', provide the external ID from the storage +# provider. This field should be omitted when creating a volume with +# 'nomad volume create' +external_id = "vol-23452345" + +# For 'nomad volume create', specify a snapshot ID or volume to clone. You can +# specify only one of these two fields. +snapshot_id = "snap-12345" +# clone_id = "vol-abcdef" + +# Optional: for 'nomad volume create', specify a maximum and minimum capacity. +# Registering an existing volume will record but ignore these fields. +capacity_min = "10GiB" +capacity_max = "20G" + +# Required (at least one): for 'nomad volume create', specify one or more +# capabilities to validate. Registering an existing volume will record but +# ignore these fields. +capability { + access_mode = "single-node-writer" + attachment_mode = "file-system" +} + +capability { + access_mode = "single-node-reader" + attachment_mode = "block-device" +} + +# Optional: for 'nomad volume create', specify mount options to validate for +# 'attachment_mode = "file-system". Registering an existing volume will record +# but ignore these fields. +mount_options { + fs_type = "ext4" + mount_flags = ["ro"] +} + +# Optional: specify one or more locations where the volume must be accessible +# from. Refer to the plugin documentation for what segment values are supported. +topology_request { + preferred { + topology { segments { rack = "R1" } } + } + required { + topology { segments { rack = "R1" } } + topology { segments { rack = "R2", zone = "us-east-1a" } } + } +} + +# Optional: provide any secrets specified by the plugin. +secrets { + example_secret = "xyzzy" +} + +# Optional: provide a map of keys to string values expected by the plugin. +parameters { + skuname = "Premium_LRS" +} + +# Optional: for 'nomad volume register', provide a map of keys to string +# values expected by the plugin. This field will populated automatically by +# 'nomad volume create'. +context { + endpoint = "http://192.168.1.101:9425" +} diff --git a/command/asset/volume.csi.json b/command/asset/volume.csi.json new file mode 100644 index 00000000000..722433ed60e --- /dev/null +++ b/command/asset/volume.csi.json @@ -0,0 +1,72 @@ +{ + "id": "ebs_prod_db1", + "namespace": "default", + "name": "database", + "type": "csi", + "plugin_id": "plugin_id", + "external_id": "vol-23452345", + "snapshot_id": "snap-12345", + "capacity_min": "10GiB", + "capacity_max": "20G", + "capability": [ + { + "access_mode": "single-node-writer", + "attachment_mode": "file-system" + }, + { + "access_mode": "single-node-reader", + "attachment_mode": "block-device" + } + ], + "context": [ + { + "endpoint": "http://192.168.1.101:9425" + } + ], + "mount_options": [ + { + "fs_type": "ext4", + "mount_flags": [ + "ro" + ] + } + ], + "topology_request": { + "preferred": [ + { + "topology": { + "segments": { + "rack": "R1" + } + } + } + ], + "required": [ + { + "topology": { + "segments": { + "rack": "R1" + } + } + }, + { + "topology": { + "segments": { + "rack": "R2", + "zone": "us-east-1a" + } + } + } + ] + }, + "parameters": [ + { + "skuname": "Premium_LRS" + } + ], + "secrets": [ + { + "example_secret": "xyzzy" + } + ] +} diff --git a/command/asset/volume.host.hcl b/command/asset/volume.host.hcl new file mode 100644 index 00000000000..3447eef998f --- /dev/null +++ b/command/asset/volume.host.hcl @@ -0,0 +1,28 @@ +id = "disk_prod_db1" +namespace = "default" +name = "database" +type = "host" +plugin_id = "plugin_id" + +# Optional: for 'nomad volume create', specify a maximum and minimum capacity. +# Registering an existing volume will record but ignore these fields. +capacity_min = "10GiB" +capacity_max = "20G" + +# Required (at least one): for 'nomad volume create', specify one or more +# capabilities to validate. Registering an existing volume will record but +# ignore these fields. +capability { + access_mode = "single-node-writer" + attachment_mode = "file-system" +} + +capability { + access_mode = "single-node-reader" + attachment_mode = "block-device" +} + +# Optional: provide a map of keys to string values expected by the plugin. +parameters { + skuname = "Premium_LRS" +} diff --git a/command/asset/volume.host.json b/command/asset/volume.host.json new file mode 100644 index 00000000000..59a4f4ef0ec --- /dev/null +++ b/command/asset/volume.host.json @@ -0,0 +1,24 @@ +{ + "id": "disk_prod_db1", + "namespace": "default", + "name": "database", + "type": "host", + "plugin_id": "plugin_id", + "capacity_min": "10GiB", + "capacity_max": "20G", + "capability": [ + { + "access_mode": "single-node-writer", + "attachment_mode": "file-system" + }, + { + "access_mode": "single-node-reader", + "attachment_mode": "block-device" + } + ], + "parameters": [ + { + "skuname": "Premium_LRS" + } + ] +} diff --git a/command/volume_init.go b/command/volume_init.go index bd37df8cfa1..93cd9e17321 100644 --- a/command/volume_init.go +++ b/command/volume_init.go @@ -8,17 +8,18 @@ import ( "os" "strings" + "github.com/hashicorp/nomad/command/asset" "github.com/posener/complete" ) const ( - // DefaultHclVolumeInitName is the default name we use when initializing + // defaultHclVolumeInitName is the default name we use when initializing // the example volume file in HCL format - DefaultHclVolumeInitName = "volume.hcl" + defaultHclVolumeInitName = "volume.hcl" // DefaultHclVolumeInitName is the default name we use when initializing // the example volume file in JSON format - DefaultJsonVolumeInitName = "volume.json" + defaultJsonVolumeInitName = "volume.json" ) // VolumeInitCommand generates a new volume spec that you can customize to @@ -39,6 +40,11 @@ Init Options: -json Create an example JSON volume specification. + + -type + Create an example for a specific type of volume (one of "csi" or "host", + defaults to "csi"). + ` return strings.TrimSpace(helpText) } @@ -50,6 +56,7 @@ func (c *VolumeInitCommand) Synopsis() string { func (c *VolumeInitCommand) AutocompleteFlags() complete.Flags { return complete.Flags{ "-json": complete.PredictNothing, + "-type": complete.PredictSet("host", "csi"), } } @@ -61,9 +68,11 @@ func (c *VolumeInitCommand) Name() string { return "volume init" } func (c *VolumeInitCommand) Run(args []string) int { var jsonOutput bool + var volType string flags := c.Meta.FlagSet(c.Name(), FlagSetClient) flags.Usage = func() { c.Ui.Output(c.Help()) } flags.BoolVar(&jsonOutput, "json", false, "") + flags.StringVar(&volType, "type", "csi", "type of volume") if err := flags.Parse(args); err != nil { return 1 @@ -77,11 +86,17 @@ func (c *VolumeInitCommand) Run(args []string) int { return 1 } - fileName := DefaultHclVolumeInitName - fileContent := defaultHclVolumeSpec - if jsonOutput { - fileName = DefaultJsonVolumeInitName - fileContent = defaultJsonVolumeSpec + fileName := defaultHclVolumeInitName + fileContent := asset.CSIVolumeSpecHCL + + if volType == "host" && !jsonOutput { + fileContent = asset.HostVolumeSpecHCL + } else if volType == "host" && jsonOutput { + fileName = defaultJsonVolumeInitName + fileContent = asset.HostVolumeSpecJSON + } else if jsonOutput { + fileName = defaultJsonVolumeInitName + fileContent = asset.CSIVolumeSpecJSON } if len(args) == 1 { fileName = args[0] @@ -99,7 +114,7 @@ func (c *VolumeInitCommand) Run(args []string) int { } // Write out the example - err = os.WriteFile(fileName, []byte(fileContent), 0660) + err = os.WriteFile(fileName, fileContent, 0660) if err != nil { c.Ui.Error(fmt.Sprintf("Failed to write %q: %v", fileName, err)) return 1 @@ -109,151 +124,3 @@ func (c *VolumeInitCommand) Run(args []string) int { c.Ui.Output(fmt.Sprintf("Example volume specification written to %s", fileName)) return 0 } - -var defaultHclVolumeSpec = strings.TrimSpace(` -id = "ebs_prod_db1" -namespace = "default" -name = "database" -type = "csi" -plugin_id = "plugin_id" - -# For 'nomad volume register', provide the external ID from the storage -# provider. This field should be omitted when creating a volume with -# 'nomad volume create' -external_id = "vol-23452345" - -# For 'nomad volume create', specify a snapshot ID or volume to clone. You can -# specify only one of these two fields. -snapshot_id = "snap-12345" -# clone_id = "vol-abcdef" - -# Optional: for 'nomad volume create', specify a maximum and minimum capacity. -# Registering an existing volume will record but ignore these fields. -capacity_min = "10GiB" -capacity_max = "20G" - -# Required (at least one): for 'nomad volume create', specify one or more -# capabilities to validate. Registering an existing volume will record but -# ignore these fields. -capability { - access_mode = "single-node-writer" - attachment_mode = "file-system" -} - -capability { - access_mode = "single-node-reader" - attachment_mode = "block-device" -} - -# Optional: for 'nomad volume create', specify mount options to validate for -# 'attachment_mode = "file-system". Registering an existing volume will record -# but ignore these fields. -mount_options { - fs_type = "ext4" - mount_flags = ["ro"] -} - -# Optional: specify one or more locations where the volume must be accessible -# from. Refer to the plugin documentation for what segment values are supported. -topology_request { - preferred { - topology { segments { rack = "R1" } } - } - required { - topology { segments { rack = "R1" } } - topology { segments { rack = "R2", zone = "us-east-1a" } } - } -} - -# Optional: provide any secrets specified by the plugin. -secrets { - example_secret = "xyzzy" -} - -# Optional: provide a map of keys to string values expected by the plugin. -parameters { - skuname = "Premium_LRS" -} - -# Optional: for 'nomad volume register', provide a map of keys to string -# values expected by the plugin. This field will populated automatically by -# 'nomad volume create'. -context { - endpoint = "http://192.168.1.101:9425" -} -`) - -var defaultJsonVolumeSpec = strings.TrimSpace(` -{ - "id": "ebs_prod_db1", - "namespace": "default", - "name": "database", - "type": "csi", - "plugin_id": "plugin_id", - "external_id": "vol-23452345", - "snapshot_id": "snap-12345", - "capacity_min": "10GiB", - "capacity_max": "20G", - "capability": [ - { - "access_mode": "single-node-writer", - "attachment_mode": "file-system" - }, - { - "access_mode": "single-node-reader", - "attachment_mode": "block-device" - } - ], - "context": [ - { - "endpoint": "http://192.168.1.101:9425" - } - ], - "mount_options": [ - { - "fs_type": "ext4", - "mount_flags": [ - "ro" - ] - } - ], - "topology_request": { - "preferred": [ - { - "topology": { - "segments": { - "rack": "R1" - } - } - } - ], - "required": [ - { - "topology": { - "segments": { - "rack": "R1" - } - } - }, - { - "topology": { - "segments": { - "rack": "R2", - "zone": "us-east-1a" - } - } - } - ] - }, - "parameters": [ - { - "skuname": "Premium_LRS" - } - ], - "secrets": [ - { - "example_secret": "xyzzy" - } - ] -} -`)