From 28fb9290d424b253c3bb7ac93b7f9a54bcdd64b1 Mon Sep 17 00:00:00 2001 From: Gene Liverman Date: Thu, 2 Jul 2020 10:39:52 -0400 Subject: [PATCH] Update docs This chane updates docs to reflect that ownership has moved to the DIO team at Puppet. It also includes some formatting changes. --- .github/PULL_REQUEST_TEMPLATE | 1 + CODEOWNERS | 6 ++ README.md | 119 ++++++++++++++++++++++------------ float.jpg | Bin 0 -> 11329 bytes lib/vmfloaty.rb | 2 +- vmfloaty.gemspec | 12 +++- 6 files changed, 94 insertions(+), 46 deletions(-) create mode 100644 CODEOWNERS create mode 100644 float.jpg diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE index b1d9431..0259cfe 100644 --- a/.github/PULL_REQUEST_TEMPLATE +++ b/.github/PULL_REQUEST_TEMPLATE @@ -17,5 +17,6 @@ FIXME ## Reviewers +@puppetlabs/dio @highb @briancain diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..b5b2b0e --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,6 @@ +# Set Puppet's DIO team as the default code owner +* @puppetlabs/dio + +# External code owners +* @briancain +* @highb diff --git a/README.md b/README.md index 3e71791..b9c170d 100644 --- a/README.md +++ b/README.md @@ -1,38 +1,61 @@ -vmfloaty -======== +# vmfloaty -[![Gem Version](https://badge.fury.io/rb/vmfloaty.svg)](https://badge.fury.io/rb/vmfloaty) [![Build Status](https://travis-ci.org/briancain/vmfloaty.svg?branch=master)](https://travis-ci.org/briancain/vmfloaty) +[![Gem Version](https://badge.fury.io/rb/vmfloaty.svg)](https://badge.fury.io/rb/vmfloaty) [![Build Status](https://travis-ci.com/puppetlabs/vmfloaty.svg?branch=master)](https://travis-ci.com/puppetlabs/vmfloaty) -A CLI helper tool for [Puppet Labs vmpooler](https://github.com/puppetlabs/vmpooler) to help you stay afloat. +A CLI helper tool for [Puppet's vmpooler](https://github.com/puppetlabs/vmpooler) to help you stay afloat. - +![float image](float.jpg) + +- [Install](#install) +- [Usage](#usage) + - [Example workflow](#example-workflow) + - [vmfloaty dotfile](#vmfloaty-dotfile) + - [Basic configuration](#basic-configuration) + - [Default to Puppet's ABS instead of vmpooler](#default-to-puppets-abs-instead-of-vmpooler) + - [Configuring multiple services](#configuring-multiple-services) + - [Using a Nonstandard Pooler service](#using-a-nonstandard-pooler-service) + - [Valid config keys](#valid-config-keys) + - [Tab Completion](#tab-completion) +- [vmpooler API](#vmpooler-api) +- [Using the Pooler class](#using-the-pooler-class) + - [Example Projects](#example-projects) +- [Special thanks](#special-thanks) ## Install Grab the latest from ruby gems... -``` -$ gem install vmfloaty -... -... -$ floaty --help +```bash +gem install vmfloaty ``` ## Usage -``` - delete Schedules the deletion of a host or hosts - get Gets a vm or vms based on the os argument - help Display global or [command] help documentation - list Shows a list of available vms from the pooler or vms obtained with a token - modify Modify a vms tags, time to live, and disk space - query Get information about a given vm - revert Reverts a vm to a specified snapshot - snapshot Takes a snapshot of a given vm - ssh Grabs a single vm and sshs into it - status Prints the status of pools in vmpooler - summary Prints a summary of vmpooler - token Retrieves or deletes a token or checks token status +```plain +$ floaty --help + NAME: + + floaty + + DESCRIPTION: + + A CLI helper tool for Puppet's vmpooler to help you stay afloat + + COMMANDS: + + completion Outputs path to completion script + delete Schedules the deletion of a host or hosts + get Gets a vm or vms based on the os argument + help Display global or [command] help documentation + list Shows a list of available vms from the pooler or vms obtained with a token + modify Modify a VM's tags, time to live, disk space, or reservation reason + query Get information about a given vm + revert Reverts a vm to a specified snapshot + snapshot Takes a snapshot of a given vm + ssh Grabs a single vm and sshs into it + status Prints the status of pools in the pooler service + summary Prints a summary of a pooler service + token Retrieves or deletes a token or checks token status GLOBAL OPTIONS: @@ -50,7 +73,7 @@ $ floaty --help Grabbing a token for authenticated pooler requests: -``` +```bash floaty token get --user username --url https://vmpooler.example.net/api/v1 ``` @@ -58,7 +81,7 @@ This command will then ask you to log in. If successful, it will return a token Grabbing vms: -``` +```bash floaty get centos-7-x86_64=2 debian-7-x86_64 windows-10=3 --token mytokenstring --url https://vmpooler.example.net/api/v1 ``` @@ -69,7 +92,7 @@ If you do not wish to continually specify various config options with the cli, y #### Basic configuration ```yaml -# file at /Users/me/.vmfloaty.yml +# file at ~/.vmfloaty.yml url: 'https://vmpooler.example.net/api/v1' user: 'brian' token: 'tokenstring' @@ -77,6 +100,16 @@ token: 'tokenstring' Now vmfloaty will use those config files if no flag was specified. +#### Default to Puppet's ABS instead of vmpooler + +```yaml +# file at ~/.vmfloaty.yml +url: 'https://abs.example.net' +user: 'brian' +token: 'tokenstring' +type: 'abs' +``` + #### Configuring multiple services Most commands allow you to specify a `--service ` option to allow the use of multiple vmpooler instances. This can be useful when you'd rather not specify a `--url` or `--token` by hand for alternate services. @@ -103,14 +136,16 @@ services: Examples using the above configuration: List available vm types from our main vmpooler instance: -```sh + +```bash floaty list --service main # or, since the first configured service is used by default: floaty list ``` List available vm types from our alternate vmpooler instance: -```sh + +```bash floaty list --service alternate ``` @@ -138,7 +173,7 @@ services: With this configuration, you could list available OS types from nspooler like this: -```sh +```bash floaty list --service ns ``` @@ -146,20 +181,16 @@ floaty list --service ns Here are the keys that vmfloaty currently supports: -- verbose - + Boolean -- token - + String -- user - + String -- url - + String -- services - + Map +- verbose (Boolean) +- token (String) +- user (String) +- url (String) +- services (String) +- type (String) ### Tab Completion -There is a basic completion script for Bash (and possibly other shells) included with the gem in the [extras/completions](https://github.com/briancain/vmfloaty/blob/master/extras/completions) folder. To activate, that file simply needs to be sourced somehow in your shell profile. +There is a basic completion script for Bash (and possibly other shells) included with the gem in the [extras/completions](https://github.com/puppetlabs/vmfloaty/blob/master/extras/completions) folder. To activate, that file simply needs to be sourced somehow in your shell profile. For convenience, the path to the completion script for the currently active version of the gem can be found with the `floaty completion` subcommand. This makes it easy to add the completion script to your profile like so: @@ -184,6 +215,10 @@ vmfloaty providers a `Pooler` class that gives users the ability to make request ### Example Projects - [John McCabe: vmpooler-bitbar](https://github.com/johnmccabe/vmpooler-bitbar/) - + vmpooler status and management in your menubar with bitbar + - vmpooler status and management in your menubar with bitbar - [Brian Cain: vagrant-vmpooler](https://github.com/briancain/vagrant-vmpooler) - + Use Vagrant to manage your vmpooler instances + - Use Vagrant to manage your vmpooler instances + +## Special thanks + +Special thanks to [Brian Cain](https://github.com/briancain) as he is the original author of vmfloaty! Vast amounts of this code exist thanks to his efforts. diff --git a/float.jpg b/float.jpg new file mode 100644 index 0000000000000000000000000000000000000000..87b06f47f2ed7e1e07c0504c8f1fe7e4d4ca76f3 GIT binary patch literal 11329 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