diff --git a/.gitignore b/.gitignore index 3ad9447e6..ffb5944c4 100644 --- a/.gitignore +++ b/.gitignore @@ -55,7 +55,11 @@ ui/dist/ website/.bundle website/vendor +# init outputs example.nomad +spec.hcl +volume.hcl + nomad_linux_amd64 nomad_darwin_amd64 TODO.md diff --git a/command/commands.go b/command/commands.go index 7d5a4653e..6f55efed7 100644 --- a/command/commands.go +++ b/command/commands.go @@ -796,6 +796,11 @@ func Commands(metaPtr *Meta, agentUi cli.Ui) map[string]cli.CommandFactory { Meta: meta, }, nil }, + "volume init": func() (cli.Command, error) { + return &VolumeInitCommand{ + Meta: meta, + }, nil + }, "volume status": func() (cli.Command, error) { return &VolumeStatusCommand{ Meta: meta, diff --git a/command/volume_init.go b/command/volume_init.go new file mode 100644 index 000000000..19ee1fe14 --- /dev/null +++ b/command/volume_init.go @@ -0,0 +1,154 @@ +package command + +import ( + "fmt" + "io/ioutil" + "os" + "strings" + + "github.com/posener/complete" +) + +const ( + // DefaultHclVolumeInitName is the default name we use when initializing + // the example volume file in HCL format + DefaultHclVolumeInitName = "volume.hcl" + + // DefaultHclVolumeInitName is the default name we use when initializing + // the example volume file in JSON format + DefaultJsonVolumeInitName = "volume.json" +) + +// VolumeInitCommand generates a new volume spec that you can customize to +// your liking, like vagrant init +type VolumeInitCommand struct { + Meta +} + +func (c *VolumeInitCommand) Help() string { + helpText := ` +Usage: nomad volume init + + Creates an example volume specification file that can be used as a starting + point to customize further. + +Init Options: + + -json + Create an example JSON volume specification. +` + return strings.TrimSpace(helpText) +} + +func (c *VolumeInitCommand) Synopsis() string { + return "Create an example volume specification file" +} + +func (c *VolumeInitCommand) AutocompleteFlags() complete.Flags { + return complete.Flags{ + "-json": complete.PredictNothing, + } +} + +func (c *VolumeInitCommand) AutocompleteArgs() complete.Predictor { + return complete.PredictNothing +} + +func (c *VolumeInitCommand) Name() string { return "volume init" } + +func (c *VolumeInitCommand) Run(args []string) int { + var jsonOutput bool + flags := c.Meta.FlagSet(c.Name(), FlagSetClient) + flags.Usage = func() { c.Ui.Output(c.Help()) } + flags.BoolVar(&jsonOutput, "json", false, "") + + if err := flags.Parse(args); err != nil { + return 1 + } + + // Check that we get no arguments + args = flags.Args() + if l := len(args); l != 0 { + c.Ui.Error("This command takes no arguments") + c.Ui.Error(commandErrorText(c)) + return 1 + } + + fileName := DefaultHclVolumeInitName + fileContent := defaultHclVolumeSpec + if jsonOutput { + fileName = DefaultJsonVolumeInitName + fileContent = defaultJsonVolumeSpec + } + + // Check if the file already exists + _, err := os.Stat(fileName) + if err != nil && !os.IsNotExist(err) { + c.Ui.Error(fmt.Sprintf("Failed to stat %q: %v", fileName, err)) + return 1 + } + if !os.IsNotExist(err) { + c.Ui.Error(fmt.Sprintf("Volume specification %q already exists", fileName)) + return 1 + } + + // Write out the example + err = ioutil.WriteFile(fileName, []byte(fileContent), 0660) + if err != nil { + c.Ui.Error(fmt.Sprintf("Failed to write %q: %v", fileName, err)) + return 1 + } + + // Success + c.Ui.Output(fmt.Sprintf("Example volume specification written to %s", fileName)) + return 0 +} + +var defaultHclVolumeSpec = strings.TrimSpace(` +id = "ebs_prod_db1" +name = "database" +type = "csi" +external_id = "vol-23452345" +access_mode = "single-node-writer" +attachment_mode = "file-system" + +mount_options { + fs_type = "ext4" + mount_flags = ["ro"] +} +secrets { + example_secret = "xyzzy" +} +parameters { + skuname = "Premium_LRS" +} +context { + endpoint = "http://192.168.1.101:9425" +} +`) + +var defaultJsonVolumeSpec = strings.TrimSpace(` +{ + "id": "ebs_prod_db1", + "name": "database", + "type": "csi", + "external_id": "vol-23452345", + "access_mode": "single-node-writer", + "attachment_mode": "file-system", + "mount_options": { + "fs_type": "ext4", + "mount_flags": [ + "ro" + ] + }, + "secrets": { + "example_secret": "xyzzy" + }, + "parameters": { + "skuname": "Premium_LRS" + }, + "context": { + "endpoint": "http://192.168.1.101:9425" + } +} +`) diff --git a/website/content/docs/commands/volume/index.mdx b/website/content/docs/commands/volume/index.mdx index 67930c155..71054932d 100644 --- a/website/content/docs/commands/volume/index.mdx +++ b/website/content/docs/commands/volume/index.mdx @@ -19,10 +19,12 @@ subcommands are available: - [`volume deregister`][deregister] - Deregister a volume. - [`volume detach`][detach] - Detach a volume. +- [`volume init`][init] - Create an example volume specification file - [`volume register`][register] - Register a volume. - [`volume status`][status] - Display status information about a volume [deregister]: /docs/commands/volume/deregister 'Deregister a volume' [detach]: /docs/commands/volume/detach 'Detach a volume' +[init]: /docs/commands/volume/init 'Create an example volume specification file' [register]: /docs/commands/volume/register 'Register a volume' [status]: /docs/commands/volume/status 'Display status information about a volume' diff --git a/website/content/docs/commands/volume/init.mdx b/website/content/docs/commands/volume/init.mdx new file mode 100644 index 000000000..e716e7d18 --- /dev/null +++ b/website/content/docs/commands/volume/init.mdx @@ -0,0 +1,31 @@ +--- +layout: docs +page_title: 'Commands: volume init' +sidebar_title: init +description: | + Generate an example volume specification. +--- + +# Command: volume init + +The `volume init` command is used to create an example volume specification +file that can be used as a starting point to customize further. + +## Usage + +```plaintext +nomad volume init +``` + +## Init Options + +- `-json`: Create an example JSON volume specification. + +## Examples + +Create an example volume specification: + +```shell-session +$ nomad volume init +Example volume specification written to volume.hcl +``` diff --git a/website/data/docs-navigation.js b/website/data/docs-navigation.js index 0b2779c36..32987a86f 100644 --- a/website/data/docs-navigation.js +++ b/website/data/docs-navigation.js @@ -177,7 +177,7 @@ export default [ 'version', { category: 'volume', - content: ['deregister', 'detach', 'status', 'register'], + content: ['deregister', 'detach', 'init', 'register', 'status'], }, ], },