8be49268b697bb00d8244f7127d8ab80bc21f281 — Evan Tann a month ago 6d6ce31 master
update usage text
1 files changed, 16 insertions(+), 64 deletions(-)

M cmd/up/main.go
M cmd/up/main.go => cmd/up/main.go +16 -64
@@ 258,8 258,8 @@ func substituteVariables(
	cmds []string,
	cmd string,
) ([]string, error) {
	// Arrange variables biggest to smallest, so $abc is substituted before
	// $a.
	// Arrange variables longest to shortest, so the more specific $abc is
	// substituted before $a.
	bigToSmall := make([]string, 0, len(vars))
	for v := range vars {
		bigToSmall = append(bigToSmall, v)

@@ 291,107 291,59 @@ func substituteVariables(
// Stderr by main().
func usage(err error) error {
	up -c <cmd> [options...]
	up -f -     [options...]
	up [options...] <cmd>

	[-c] command to run in upfile
	[-f] path to Upfile, default "Upfile"
	[-h] short-form help with flags
	[-i] path to inventory, default "inventory.json"
	[-n] number of servers to execute in parallel, default 1
	[-p] prompt before moving to next batch, default false
	[-t] comma-separated tags from inventory to execute, default is your command
	[-t] comma-separated target ips, used for $server value
	[-v] verbose output, default false

	Upfiles define the steps to be run for each server using a syntax
	similar to Makefiles.

	There are 4 parts to Upfiles:
	There are 3 parts to Upfiles:

	1. Command name: This is passed into up using "-c"
	2. Conditionals: Before running commands, up will execute
	   space-separated conditionals in order. It will proceed to run
	   commands for the server if and only if any of the conditionals
	   return a non-zero exit code. Conditionals are optional.
	3. Commands: One or more commands to be run if all conditionals pass.
	4. Variables: Variables can be substituted within commands by prefixing
	1. Command name
	2. Commands: One or more commands to be run, separated by newlines.
	3. Variables: Variables can be substituted within commands by prefixing
	   the name with "$". Variable substitution values may be a single
	   value or an entire series of commands.

	These parts are generally arranged as follows:






	The inventory is a JSON file which maps IP addresses to arbitrary tags.
	It has the following format:

		"IP_1": ["TAG_1", "TAG_2"],
		"IP_2": ["TAG_1"]

	Because this is a simple JSON file, your inventory can be dynamically
	generated if you wish based on the state of your architecture at a
	given moment, or you can commit the single into source code alongside
	your Upfile.

	up exits with 0 on success or 1 on any failure.

	In the following example Upfile, "deploy_dashboard" is the command.
	Before running the script indented underneath the command, up will
	first execute any space-separated commands to the right. In this
	example, up will only execute the deploy_dashboard commands if
	check_version returns a non-zero exit code.

	All steps are executed locally, so to run commands on the server we use
	the reserved variable "$server" to get the IP and execute commands
	through ssh.

	$ cat Upfile
	deploy_dashboard check_version
	check_health=curl --max-time 1 $server/version

		rsync -a dashboard $remote:
		ssh $remote 'sudo service dashboard restart'
		sleep 1 && $check_health

		expr $CHECKSUM == "$(curl --max-time 1 $server/version)"


	$ cat inventory.json
		"": ["dashboard", "redis", "openbsd"],
		"": ["dashboard", "openbsd"],
		"": ["dashboard_staging"],
		"": ["postgres", "debian"],
		"": ["reverse_proxy"]

	Good inventory tags generally include the type of services running on
	the box and the operating system (for easily updating groups of
	machines with the same OS).

	In this example, running:

	$ up -c deploy_dashboard -t dashboard
	$ up -t, deploy_dashboard

	would execute deploy_dashboard on and Since we
	didn't pass in "-n 2", up will deploy on the first server before