@installdoc/ansible-gas-station
Version:
An Ansible playbook that provisions your network with software from GitHub Awesome lists, developed with disaster recovery in mind ⛽🔥🤤
253 lines (227 loc) • 10.2 kB
YAML
---
version: '3'
tasks:
docs:
deps:
- :install:npm:leasot
summary: |
```shell
# @description Processes leasot data and returns .variables.json data including charts written in @appnest/readme format
#
# @arg $1 The file that the leasot JSON was written to
# @arg $2 The tag being processed
function populateChartVar() {
...
}
```
vars:
DOC_IDS: '@binary,@brew,@cask,@chrome,@firefox,@gem,@helm,@npm,@pypi,@vscode'
log:
error: Failed to acquire package information from comments via `leasot`
start: Scanning and acquiring package information in comments via `leasot`
success: Acquired package information from comments
cmds:
- |
function populateChartVar() {
CHART='[["Package", "Description"]'
jq --arg tag "$(echo $2 | tr '[a-z]' '[A-Z]')" -r '.[] | select(.tag == $tag) | .
| del(. ["file", "ref", "line", "tag"]) | .text' "$1" | while read COMMENT; do
if [ "$CHART" != '[' ]; then
CHART="${CHART},"
fi
LINK="$(echo $COMMENT | sed 's/ - .*//')"
DESCRIPTION="$(echo $COMMENT | sed 's/.* - //' | sed 's/\"/\\\"/g')"
CHART="${CHART}[\"**$LINK**\",\"$DESCRIPTION\"]"
done
CHART="${CHART}]"
TMP_CHART="$(mktemp)"
KEY="$(echo $2 | sed 's/^@//')"
jq --arg chart "$CHART" --arg key "${KEY}_var_chart" '.[$key] = ($chart | fromjson)' .variables.json > "$TMP_CHART"
mv "$TMP_CHART" .variables.json
}
TMP="$(mktemp)"
leasot --tags '{{.DOC_IDS}}' --reporter json './environments/prod/group_vars/**/*.yml' > "$TMP" || true
VARIABLES_JSON="$(jq '.' .variables.json)"
for ID in {{replace "," " " .DOC_IDS}}; do
populateChartVar "$TMP" "$ID"
done
environment:
desc: Prompts for which environment to use and then symlinks to it
hide: '{{ne (print .REPOSITORY_TYPE "-" .REPOSITORY_SUBTYPE) "ansible-playbook"}}'
summary: |
# Switch environments using an interactive dialogue
Ansible does not really provide any great ways to switch between environments (or sets of
`host_vars/`, `group_vars/` etc.). If you place all the files and folders you wish to constitute
as an environment inside a folder named as the name of the environment then you can use
this task to handle the symlinking and switching between environments.
**Example of opening the interactive prompt:**
`task ansible:environment`
**You can directly switch enironments to `environments/prod/` by running:**
`task ansible:environment -- prod`
cmds:
- task: environment:{{if .CLI_ARGS}}cli{{else}}prompt{{end}}
environment:cli:
log:
error: Encountered an error while switching environments to `{{.CLI_ARGS}}`
start: Switching environment to `{{.CLI_ARGS}}`
success: Successfully switched environment to `{{.CLI_ARGS}}`
cmds:
- |
{{if .CLI_ARGS}}
for ITEM in environments/{{.CLI_ARGS}}/*; do
ITEM="$(echo $ITEM | sed 's/.*\///')"
if test -L "$ITEM" || ! test -e "$ITEM"; then
rm -f "$ITEM"
ln -s "./environments/{{.CLI_ARGS}}/$ITEM" "$ITEM"
.config/log success "Successfully symlinked `$ITEM` from ./environments/{{.CLI_ARGS}}/$ITEM"
else
.config/log warn "$ITEM exists in the root and was not a symlink so it was skipped to prevent possible data loss"
fi
done
{{else}}
exit 69
{{end}}
environment:prompt:
vars:
MARKDOWN: |
# Symlink Environment
Answer the prompt below to switch between environments. Each environment
should be a folder with folders and files you wish to link to from the root
of the project. They should normally consist of a host_vars, group_vars,
inventory, and files folder (but can contain any files/folders you wish to link).
Each environment should have its own folder in the `environments/` folder titled
as the name of the environment. After you select an answer, the script will
symlink all of the items in the environments folder to the root as long as there
is not anything except a symlink to the target location (i.e. it will overwrite
symlinks but not files).
cmds:
- task: :log:markdown
vars:
MARKDOWN: '{{.MARKDOWN}}'
- task: environment:prompt:continue
environment:prompt:continue:
interactive: true
deps:
- :install:software:jq
vars:
ENVIRONMENT_OPTIONS:
sh: find ./environments -maxdepth 1 -mindepth 1 | sed 's/\.\/environments\///' | jq -R '[.]' | jq -s -c 'add'
prompt:
type: select
message: Which environment would you like to use?
options: '{{.ENVIRONMENT_OPTIONS}}'
answer:
cmds:
- task: environment:cli
vars:
CLI_ARGS: '{{.ANSWER}}'
find-missing:
desc: Find roles that are missing files
hide: '{{ne (print .REPOSITORY_TYPE "-" .REPOSITORY_SUBTYPE) "ansible-playbook"}}'
summary: |
# Find roles that are missing any given file
This task scans through all the folders in the roles/ directory and checks
for the presence of a file that you pass in through the CLI.
**Example usage:**
`task find-missing -- logo.png`
The example above will look through all the folders two levels deep (e.g. `./roles/tools/nmap`,
`./roles/system/snapd`) in the roles folder and display any roles that are missing the file.
log:
error: Failed to scan the `/roles/*` folders for roles missing `{{.CLI_ARGS}}`
start: Determining which roles in the `/roles/*` folders are missing `{{.CLI_ARGS}}`
success: Finished scanning for roles missing `{{.CLI_ARGS}}` (if there are any then they should be listed above)
cmds:
- |
FILES=$(find ./roles -mindepth 2 -maxdepth 2 -type d '!' -exec test -e "{}/{{.CLI_ARGS}}" ';' -print)
.config/log info 'Found '"$(echo "$FILES" | wc -l | xargs)"' roles missing {{.CLI_ARGS}}'
echo "$FILES"
preconditions:
- sh: test -d roles
msg: The `roles/` folder is missing. Is the project set up right?
remotes:
deps:
- :install:software:git
- :install:software:jq
- :install:software:subrepo
summary: |
# Ensures each role is added as a remote
This task cycles through all the roles in the `/roles` folder and ensures
they are added as remotes. This helps with managing the git trees used
for combining the many role repositories into the playbook mono-repository.
It also adds a remote for a private submodule that is intended to store
files that are not meant to be shared. The remote is named `private`.
run: once
log:
error: Failed to set remotes for one or more of the roles in the `/roles/*` folders
start: Adding git remotes for all of the roles in the `/roles/*` folders
success: Successfully added git remotes for all of the roles in the `/roles/*` folders
cmds:
- git init -q
- |
for ROLE_RELATIVE_PATH in roles/*/*; do
if [ -f "${ROLE_RELATIVE_PATH}/package.json" ]; then
ROLE_FOLDER="$(basename $ROLE_RELATIVE_PATH)"
ROLE_HTTPS_REPO="$(jq -r '.blueprint.repository.gitlab' $ROLE_RELATIVE_PATH/package.json)"
ROLE_SSH_REPO="$(echo $ROLE_HTTPS_REPO | sed 's/https:\/\/gitlab.com\//git@gitlab.com:/' | sed 's/$/.git/')"
if git config "remote.${ROLE_FOLDER}.url" > /dev/null; then
git remote set-url "$ROLE_FOLDER" "$ROLE_SSH_REPO"
else
git remote add "$ROLE_FOLDER" "$ROLE_SSH_REPO"
fi
else
.config/log warn "${ROLE_RELATIVE_PATH}/package.json is missing!"
fi
done
run:
cmds:
- task: run:{{if .CLI_ARGS}}cli{{else}}prompt{{end}}
run:cli:
deps:
- task: :install:python:requirements
env:
INSTALL_OPTIONS: --no-dev
- :symlink:playbook
log:
error: Error encounted while running `ansible-playbook -i inventories/{{.CLI_ARGS}} --ask-vault-pass main.yml`
start: Running `ansible-playbook -i inventories/{{.CLI_ARGS}} --ask-vault-pass main.yml`
success: Successfully ran `ansible-playbook -i inventories/{{.CLI_ARGS}} --ask-vault-pass main.yml`
cmds:
- ansible-playbook -i inventories/{{.CLI_ARGS}} --ask-vault-pass main.yml
run:prompt:
vars:
MARKDOWN: |
# Run the Playbook
These set of prompts will run the `main.yml` playbook after you specify:
1. The "environment"
The environment is a collection of folders that should, at the very minimum,
include "files", "group_vars", "host_vars", and "inventories". Each folder in
the "environments" folder constitutes a different environment. By using
environments, you can seperate different sets of variables/files or even seperate
your private variables out into a sub-module.
2. An inventory file
The Ansible inventory stored in the "inventories" folder. This will generally be
a YML file with host connection information that also correlates the inventory with
the proper host_vars and group_vars. It is assumed that your sudo username and
password are encrypted inside the inventory (via "ansible-vault").
cmds:
- task: environment
- task: :log:markdown
vars:
MARKDOWN: '{{.MARKDOWN}}'
- task: run:prompt:continue
run:prompt:continue:
interactive: true
deps:
- :install:software:jq
vars:
INVENTORY_OPTIONS:
sh: find ./inventories/ -mindepth 1 -maxdepth 1 | sed 's/\.\/inventories\///' | jq -R '[.]' | jq -s -c 'add'
prompt:
type: select
message: Which inventory would you like to use?
options: '{{.INVENTORY_OPTIONS}}'
answer:
cmds:
- task: run:cli
vars:
CLI_ARGS: '{{.ANSWER}}'