mirror of
https://github.com/hackacad/bastille.git
synced 2025-12-20 17:20:12 +01:00
Add support for template args
Closes 211.
This commit is contained in:
53
README.md
53
README.md
@@ -631,8 +631,8 @@ Templates](https://gitlab.com/BastilleBSD-Templates)?
|
||||
Bastille supports a templating system allowing you to apply files, pkgs and
|
||||
execute commands inside the container automatically.
|
||||
|
||||
Currently supported template hooks are: `LIMITS`, `INCLUDE`, `PRE`, `FSTAB`,
|
||||
`PKG`, `OVERLAY`, `SYSRC`, `SERVICE`, `CMD`.
|
||||
Currently supported template hooks are: `ARG`, `LIMITS`, `INCLUDE`, `PRE`,
|
||||
`FSTAB`, `PKG`, `OVERLAY`, `SYSRC`, `SERVICE`, `CMD`, `RENDER`.
|
||||
Planned template hooks include: `PF`, `LOG`
|
||||
|
||||
Templates are created in `${bastille_prefix}/templates` and can leverage any of
|
||||
@@ -655,17 +655,19 @@ echo "usr" > /usr/local/bastille/templates/username/base-template/OVERLAY
|
||||
Template hooks are executed in specific order and require specific syntax to
|
||||
work as expected. This table outlines that order and those requirements:
|
||||
|
||||
| SUPPORTED | format | example |
|
||||
|-----------|---------------------|------------------------------------------------|
|
||||
| LIMITS | resource value | memoryuse 1G |
|
||||
| INCLUDE | template path/URL | http?://TEMPLATE_URL or username/base-template |
|
||||
| PRE | /bin/sh command | mkdir -p /usr/local/path |
|
||||
| FSTAB | fstab syntax | /host/path container/path nullfs ro 0 0 |
|
||||
| PKG | port/pkg name(s) | vim-console zsh git-lite tree htop |
|
||||
| OVERLAY | paths (one/line) | etc usr |
|
||||
| SYSRC | sysrc command(s) | nginx_enable=YES |
|
||||
| SERVICE | service command(s) | nginx restart |
|
||||
| CMD | /bin/sh command | /usr/bin/chsh -s /usr/local/bin/zsh |
|
||||
| SUPPORTED | format | example |
|
||||
|-----------|-----------------------|------------------------------------------------|
|
||||
| ARG | name=value (one/line) | domain=example.com (omit value for no default) |
|
||||
| LIMITS | resource value | memoryuse 1G |
|
||||
| INCLUDE | template path/URL | http?://TEMPLATE_URL or username/base-template |
|
||||
| PRE | /bin/sh command | mkdir -p /usr/local/path |
|
||||
| FSTAB | fstab syntax | /host/path container/path nullfs ro 0 0 |
|
||||
| PKG | port/pkg name(s) | vim-console zsh git-lite tree htop |
|
||||
| OVERLAY | paths (one/line) | etc usr |
|
||||
| SYSRC | sysrc command(s) | nginx_enable=YES |
|
||||
| SERVICE | service command(s) | nginx restart |
|
||||
| CMD | /bin/sh command | /usr/bin/chsh -s /usr/local/bin/zsh |
|
||||
| RENDER | paths (one/line) | /usr/local/etc/nginx |
|
||||
|
||||
| PLANNED | format | example |
|
||||
|---------|------------------|----------------------------------------------------------------|
|
||||
@@ -674,6 +676,12 @@ work as expected. This table outlines that order and those requirements:
|
||||
|
||||
Note: SYSRC requires NO quotes or that quotes (`"`) be escaped. ie; `\"`)
|
||||
|
||||
Any name provided in the ARG file can be used as a variable in the other hooks.
|
||||
For example, `name=value` in the ARG file will cause instances of `${name}`
|
||||
to be replaced with `value`. The `RENDER` hook can be used to specify files or
|
||||
directories whose contents should have the variables replaced. Values can be specified
|
||||
either through the command line when applying the template or as a default in the ARG file.
|
||||
|
||||
In addition to supporting template hooks, Bastille supports overlaying files
|
||||
into the container. This is done by placing the files in their full path, using the
|
||||
template directory as "/".
|
||||
@@ -705,12 +713,22 @@ create a `Bastillefile` inside the base template directory. Each line in
|
||||
the file should begin with an uppercase reference to a Bastille command
|
||||
followed by its arguments (omitting the target, which is deduced from the
|
||||
`template` arguments). Lines beginning with `#` are treated as comments.
|
||||
Variables can also be defined using `ARG` with one `name=value` pair per
|
||||
line. Subsequent references to `${name}` would be replaced by `value`.
|
||||
Note that argument values are not available for use until after the point
|
||||
at which they are defined in the file.
|
||||
|
||||
Bastillefile example:
|
||||
|
||||
```shell
|
||||
LIMITS memoryuse 1G
|
||||
|
||||
# This value can be overridden when the template is applied.
|
||||
ARG domain=example.com
|
||||
|
||||
# Replace all argument variables inside the nginx config.
|
||||
RENDER /usr/local/etc/nginx
|
||||
|
||||
# Install and start nginx.
|
||||
PKG nginx
|
||||
SYSRC nginx_enable=YES
|
||||
@@ -719,6 +737,9 @@ SERVICE nginx restart
|
||||
# Copy files to nginx.
|
||||
CP www/ usr/local/www/nginx-dist/
|
||||
|
||||
# Use the "domain" arg to create a file on the server containing the domain.
|
||||
CMD echo "${domain}" > /usr/local/www/nginx-dist/domain.txt
|
||||
|
||||
# Create a file on the server containing the jail's hostname.
|
||||
CMD hostname > /usr/local/www/nginx-dist/hostname.txt
|
||||
|
||||
@@ -735,8 +756,12 @@ Bastille includes a `template` sub-command. This sub-command requires a target
|
||||
and a template name. As covered in the previous section, template names
|
||||
correspond to directory names in the `bastille/templates` directory.
|
||||
|
||||
To provide values for arguments defined by `ARG` in the template, pass the
|
||||
optional `--arg` parameter as many times as needed. Alternatively, use
|
||||
`--arg-file <fileName>` with one `name=value` pair per line.
|
||||
|
||||
```shell
|
||||
ishmael ~ # bastille template folsom username/base
|
||||
ishmael ~ # bastille template folsom username/base --arg domain=example.com
|
||||
[folsom]:
|
||||
Copying files...
|
||||
Copy complete.
|
||||
|
||||
@@ -49,6 +49,62 @@ post_command_hook() {
|
||||
esac
|
||||
}
|
||||
|
||||
get_arg_name() {
|
||||
echo "${1}" | sed -E 's/=.*//'
|
||||
}
|
||||
|
||||
parse_arg_value() {
|
||||
# Parses the value after = and then escapes back/forward slashes and single quotes in it. -- cwells
|
||||
echo "${1}" | sed -E 's/[^=]+=?//' | sed -e 's/\\/\\\\/g' -e 's/\//\\\//g' -e 's/'\''/'\''\\'\'\''/g'
|
||||
}
|
||||
|
||||
get_arg_value() {
|
||||
_name_value_pair="${1}"
|
||||
shift
|
||||
_arg_name="$(get_arg_name "${_name_value_pair}")"
|
||||
|
||||
# Remaining arguments in $@ are the script arguments, which take precedence. -- cwells
|
||||
for _script_arg in "$@"; do
|
||||
case ${_script_arg} in
|
||||
--arg)
|
||||
# Parse whatever is next. -- cwells
|
||||
_next_arg='true' ;;
|
||||
*)
|
||||
if [ "${_next_arg}" = 'true' ]; then # This is the parameter after --arg. -- cwells
|
||||
_next_arg=''
|
||||
if [ "$(get_arg_name "${_script_arg}")" = "${_arg_name}" ]; then
|
||||
parse_arg_value "${_script_arg}"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Check the ARG_FILE if one was provided. --cwells
|
||||
if [ -n "${ARG_FILE}" ]; then
|
||||
# To prevent a false empty value, only parse the value if this argument exists in the file. -- cwells
|
||||
if grep "^${_arg_name}=" "${ARG_FILE}" > /dev/null 2>&1; then
|
||||
parse_arg_value "$(grep "^${_arg_name}=" "${ARG_FILE}")"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
# Return the default value, which may be empty, from the name=value pair. -- cwells
|
||||
parse_arg_value "${_name_value_pair}"
|
||||
}
|
||||
|
||||
render() {
|
||||
_file_path="${1}/${2}"
|
||||
if [ -d "${_file_path}" ]; then # Recursively render every file in this directory. -- cwells
|
||||
find "${_file_path}" \( -type d -name .git -prune \) -o -type f -print0 | $(eval "xargs -0 sed -i '' ${ARG_REPLACEMENTS}")
|
||||
elif [ -f "${_file_path}" ]; then
|
||||
eval "sed -i '' ${ARG_REPLACEMENTS} '${_file_path}'"
|
||||
else
|
||||
echo -e "${COLOR_YELLOW}Path not found for render: ${2}${COLOR_RESET}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Handle special-case commands first.
|
||||
case "$1" in
|
||||
help|-h|--help)
|
||||
@@ -56,7 +112,7 @@ help|-h|--help)
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ $# -ne 1 ]; then
|
||||
if [ $# -lt 1 ]; then
|
||||
bastille_usage
|
||||
fi
|
||||
|
||||
@@ -87,7 +143,27 @@ if [ -z "${JAILS}" ]; then
|
||||
fi
|
||||
|
||||
if [ -z "${HOOKS}" ]; then
|
||||
HOOKS='LIMITS INCLUDE PRE FSTAB PF PKG OVERLAY CONFIG SYSRC SERVICE CMD'
|
||||
HOOKS='LIMITS INCLUDE PRE FSTAB PF PKG OVERLAY CONFIG SYSRC SERVICE CMD RENDER'
|
||||
fi
|
||||
|
||||
# Check for an --arg-file parameter. -- cwells
|
||||
for _script_arg in "$@"; do
|
||||
case ${_script_arg} in
|
||||
--arg-file)
|
||||
# Parse whatever is next. -- cwells
|
||||
_next_arg='true' ;;
|
||||
*)
|
||||
if [ "${_next_arg}" = 'true' ]; then # This is the parameter after --arg-file. -- cwells
|
||||
_next_arg=''
|
||||
ARG_FILE="${_script_arg}"
|
||||
break
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -n "${ARG_FILE}" ] && [ ! -f "${ARG_FILE}" ]; then
|
||||
error_exit "File not found: ${ARG_FILE}"
|
||||
fi
|
||||
|
||||
## global variables
|
||||
@@ -113,6 +189,23 @@ for _jail in ${JAILS}; do
|
||||
fi
|
||||
fi
|
||||
|
||||
# This is parsed outside the HOOKS loop so an ARG file can be used with a Bastillefile. -- cwells
|
||||
ARG_REPLACEMENTS=''
|
||||
if [ -s "${bastille_template}/ARG" ]; then
|
||||
while read _line; do
|
||||
if [ -z "${_line}" ]; then
|
||||
continue
|
||||
fi
|
||||
_arg_name=$(get_arg_name "${_line}")
|
||||
_arg_value=$(get_arg_value "${_line}" "$@")
|
||||
if [ -z "${_arg_value}" ]; then
|
||||
echo -e "${COLOR_YELLOW}No value provided for arg: ${_arg_name}${COLOR_RESET}"
|
||||
fi
|
||||
# Build a list of sed commands like this: -e 's/${username}/root/g' -e 's/${domain}/example.com/g'
|
||||
ARG_REPLACEMENTS="${ARG_REPLACEMENTS} -e 's/\${${_arg_name}}/${_arg_value}/g'"
|
||||
done < "${bastille_template}/ARG"
|
||||
fi
|
||||
|
||||
if [ -s "${bastille_template}/Bastillefile" ]; then
|
||||
# Ignore blank lines and comments. -- cwells
|
||||
SCRIPT=$(grep -v '^\s*$' "${bastille_template}/Bastillefile" | grep -v '^\s*#')
|
||||
@@ -121,19 +214,27 @@ for _jail in ${JAILS}; do
|
||||
'
|
||||
set -f
|
||||
for _line in ${SCRIPT}; do
|
||||
# First word converted to lowercase is the Bastille command. -- cwells
|
||||
_cmd=$(echo "${_line}" | awk '{print tolower($1);}')
|
||||
_args=$(echo "${_line}" | awk '{$1=""; sub(/^ */, ""); print;}')
|
||||
# Rest of the line with "arg" variables replaced will be the arguments. -- cwells
|
||||
_args=$(echo "${_line}" | awk '{$1=""; sub(/^ */, ""); print;}' | eval "sed ${ARG_REPLACEMENTS}")
|
||||
|
||||
# Apply overrides for commands/aliases and arguments. -- cwells
|
||||
case $_cmd in
|
||||
arg) # This is a template argument definition. -- cwells
|
||||
_arg_name=$(get_arg_name "${_args}")
|
||||
_arg_value=$(get_arg_value "${_args}" "$@")
|
||||
if [ -z "${_arg_value}" ]; then
|
||||
echo -e "${COLOR_YELLOW}No value provided for arg: ${_arg_name}${COLOR_RESET}"
|
||||
fi
|
||||
# Build a list of sed commands like this: -e 's/${username}/root/g' -e 's/${domain}/example.com/g'
|
||||
ARG_REPLACEMENTS="${ARG_REPLACEMENTS} -e 's/\${${_arg_name}}/${_arg_value}/g'"
|
||||
continue
|
||||
;;
|
||||
cmd)
|
||||
# Allow redirection within the jail. -- cwells
|
||||
_args="sh -c '${_args}'"
|
||||
;;
|
||||
overlay)
|
||||
_cmd='cp'
|
||||
_args="${bastille_template}/${_args} /"
|
||||
;;
|
||||
cp|copy)
|
||||
_cmd='cp'
|
||||
# Convert relative "from" path into absolute path inside the template directory. -- cwells
|
||||
@@ -145,8 +246,16 @@ for _jail in ${JAILS}; do
|
||||
_cmd='mount' ;;
|
||||
include)
|
||||
_cmd='template' ;;
|
||||
overlay)
|
||||
_cmd='cp'
|
||||
_args="${bastille_template}/${_args} /"
|
||||
;;
|
||||
pkg)
|
||||
_args="install -y ${_args}" ;;
|
||||
render) # This is a path to one or more files needing arguments replaced by values. -- cwells
|
||||
render "${bastille_jail_path}" "${_args}"
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
|
||||
if ! eval "bastille ${_cmd} ${_jail} ${_args}"; then
|
||||
@@ -185,6 +294,10 @@ for _jail in ${JAILS}; do
|
||||
continue ;;
|
||||
PRE)
|
||||
_cmd='cmd' ;;
|
||||
RENDER) # This is a path to one or more files needing arguments replaced by values. -- cwells
|
||||
render "${bastille_jail_path}" "${_line}"
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
|
||||
echo -e "${COLOR_GREEN}[${_jail}]:${_hook} -- START${COLOR_RESET}"
|
||||
@@ -198,6 +311,8 @@ for _jail in ${JAILS}; do
|
||||
if [ -z "${_line}" ]; then
|
||||
continue
|
||||
fi
|
||||
# Replace "arg" variables in this line with the provided values. -- cwells
|
||||
_line=$(echo "${_line}" | eval "sed ${ARG_REPLACEMENTS}")
|
||||
eval "_args=\"${_args_template}\""
|
||||
bastille "${_cmd}" "${_jail}" ${_args} || exit 1
|
||||
done < "${bastille_template}/${_hook}"
|
||||
|
||||
Reference in New Issue
Block a user