@@ 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 {
fmt.Println(`USAGE
- up -c <cmd> [options...]
- up -f - [options...]
+ up [options...] <cmd>
OPTIONS
- [-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
UPFILE
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:
- CMD_NAME_1 CONDITIONAL_1 CONDITIONAL_2
+ VARIABLE_1=SUBSTITUTION_VALUE
+
+ CMD_NAME_1:
CMD_1
CMD_2
-
- CMD_NAME_2
- CMD_3
$VARIABLE_1
- CONDITIONAL_1
- CMD_4
-
- VARIABLE_1
- SUBSTITUTION_VALUE
-
-INVENTORY
- 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.
-
EXIT STATUS
up exits with 0 on success or 1 on any failure.
EXAMPLES
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
+ remote=$UP_USER@$server
+ check_health=curl --max-time 1 $server/version
+
+ deploy_dashboard:
rsync -a dashboard $remote:
ssh $remote 'sudo service dashboard restart'
sleep 1 && $check_health
- check_version
- expr $CHECKSUM == "$(curl --max-time 1 $server/version)"
-
- remote
- $UP_USER@$server
-
- $ cat inventory.json
- {
- "10.0.0.1": ["dashboard", "redis", "openbsd"],
- "10.0.0.2": ["dashboard", "openbsd"],
- "10.0.0.3": ["dashboard_staging"],
- "10.0.0.4": ["postgres", "debian"],
- "10.0.0.5": ["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 10.0.0.1,10.0.0.2 deploy_dashboard
would execute deploy_dashboard on 10.0.0.1 and 10.0.0.2. Since we
didn't pass in "-n 2", up will deploy on the first server before