blob: 1f05f1c21e3d6f4401934b953b83dc4c3592ef30 [file] [log] [blame]
Jakub Pavlikfe0960c2016-01-25 21:35:39 +01001#!/usr/bin/env bash
2
3set -e
4[ -n "$DEBUG" ] && set -x
5
6CURDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
7METADATA=${CURDIR}/../metadata.yml
8FORMULA_NAME=$(cat $METADATA | python -c "import sys,yaml; print yaml.load(sys.stdin)['name']")
Oleksandr Shyshko87005682018-07-31 18:31:57 +03009FORMULA_META_DIR=${CURDIR}/../${FORMULA_NAME}/meta
Jakub Pavlikfe0960c2016-01-25 21:35:39 +010010
11## Overrideable parameters
12PILLARDIR=${PILLARDIR:-${CURDIR}/pillar}
13BUILDDIR=${BUILDDIR:-${CURDIR}/build}
14VENV_DIR=${VENV_DIR:-${BUILDDIR}/virtualenv}
Oleksandr Shyshko87005682018-07-31 18:31:57 +030015MOCK_BIN_DIR=${MOCK_BIN_DIR:-${CURDIR}/mock_bin}
Jakub Pavlikfe0960c2016-01-25 21:35:39 +010016DEPSDIR=${BUILDDIR}/deps
17
18SALT_FILE_DIR=${SALT_FILE_DIR:-${BUILDDIR}/file_root}
19SALT_PILLAR_DIR=${SALT_PILLAR_DIR:-${BUILDDIR}/pillar_root}
20SALT_CONFIG_DIR=${SALT_CONFIG_DIR:-${BUILDDIR}/salt}
21SALT_CACHE_DIR=${SALT_CACHE_DIR:-${SALT_CONFIG_DIR}/cache}
22
Jakub Pavlik882f8482017-04-06 16:38:35 +020023SALT_OPTS="${SALT_OPTS} --retcode-passthrough --local -c ${SALT_CONFIG_DIR} --log-file=/dev/null"
Jakub Pavlikfe0960c2016-01-25 21:35:39 +010024
25if [ "x${SALT_VERSION}" != "x" ]; then
26 PIP_SALT_VERSION="==${SALT_VERSION}"
27fi
28
29## Functions
30log_info() {
31 echo "[INFO] $*"
32}
33
34log_err() {
35 echo "[ERROR] $*" >&2
36}
37
38setup_virtualenv() {
39 log_info "Setting up Python virtualenv"
40 virtualenv $VENV_DIR
41 source ${VENV_DIR}/bin/activate
Jakub Josef9eb6a032018-02-08 13:22:15 +010042 python -m pip install salt${PIP_SALT_VERSION}
Oleksii Molchanov74048b62020-05-25 16:59:07 +030043 if [[ -f ${CURDIR}/test-requirements.txt ]]; then
44 python -m pip install -r ${CURDIR}/test-requirements.txt
45 fi
Jakub Pavlikfe0960c2016-01-25 21:35:39 +010046}
47
Oleksandr Shyshko87005682018-07-31 18:31:57 +030048setup_mock_bin() {
49 # If some state requires a binary, a lightweight replacement for
50 # such binary can be put into MOCK_BIN_DIR for test purposes
51 if [ -d "${MOCK_BIN_DIR}" ]; then
52 PATH="${MOCK_BIN_DIR}:$PATH"
53 export PATH
54 fi
55}
56
Jakub Pavlikfe0960c2016-01-25 21:35:39 +010057setup_pillar() {
58 [ ! -d ${SALT_PILLAR_DIR} ] && mkdir -p ${SALT_PILLAR_DIR}
59 echo "base:" > ${SALT_PILLAR_DIR}/top.sls
60 for pillar in ${PILLARDIR}/*; do
Jakub Pavlik882f8482017-04-06 16:38:35 +020061 grep ${FORMULA_NAME}: ${pillar} &>/dev/null || continue
Jakub Pavlikfe0960c2016-01-25 21:35:39 +010062 state_name=$(basename ${pillar%.sls})
63 echo -e " ${state_name}:\n - ${state_name}" >> ${SALT_PILLAR_DIR}/top.sls
64 done
65}
66
67setup_salt() {
68 [ ! -d ${SALT_FILE_DIR} ] && mkdir -p ${SALT_FILE_DIR}
69 [ ! -d ${SALT_CONFIG_DIR} ] && mkdir -p ${SALT_CONFIG_DIR}
70 [ ! -d ${SALT_CACHE_DIR} ] && mkdir -p ${SALT_CACHE_DIR}
71
72 echo "base:" > ${SALT_FILE_DIR}/top.sls
73 for pillar in ${PILLARDIR}/*.sls; do
Jakub Pavlik882f8482017-04-06 16:38:35 +020074 grep ${FORMULA_NAME}: ${pillar} &>/dev/null || continue
Jakub Pavlikfe0960c2016-01-25 21:35:39 +010075 state_name=$(basename ${pillar%.sls})
76 echo -e " ${state_name}:\n - ${FORMULA_NAME}" >> ${SALT_FILE_DIR}/top.sls
77 done
78
79 cat << EOF > ${SALT_CONFIG_DIR}/minion
80file_client: local
81cachedir: ${SALT_CACHE_DIR}
82verify_env: False
Ondřej Novýad6274d2016-04-23 17:11:01 +020083minion_id_caching: False
Jakub Pavlikfe0960c2016-01-25 21:35:39 +010084
85file_roots:
86 base:
87 - ${SALT_FILE_DIR}
88 - ${CURDIR}/..
Filip Pytloun9e404cf2016-04-14 11:51:09 +020089 - /usr/share/salt-formulas/env
Jakub Pavlikfe0960c2016-01-25 21:35:39 +010090
91pillar_roots:
92 base:
93 - ${SALT_PILLAR_DIR}
94 - ${PILLARDIR}
95EOF
96}
97
98fetch_dependency() {
Filip Pytloun9e404cf2016-04-14 11:51:09 +020099 dep_name="$(echo $1|cut -d : -f 1)"
100 dep_source="$(echo $1|cut -d : -f 2-)"
101 dep_root="${DEPSDIR}/$(basename $dep_source .git)"
Jakub Pavlikfe0960c2016-01-25 21:35:39 +0100102 dep_metadata="${dep_root}/metadata.yml"
103
Filip Pytloun9e404cf2016-04-14 11:51:09 +0200104 [ -d /usr/share/salt-formulas/env/${dep_name} ] && log_info "Dependency $dep_name already present in system-wide salt env" && return 0
105 [ -d $dep_root ] && log_info "Dependency $dep_name already fetched" && return 0
Jakub Pavlikfe0960c2016-01-25 21:35:39 +0100106
Filip Pytloun9e404cf2016-04-14 11:51:09 +0200107 log_info "Fetching dependency $dep_name"
Jakub Pavlikfe0960c2016-01-25 21:35:39 +0100108 [ ! -d ${DEPSDIR} ] && mkdir -p ${DEPSDIR}
Filip Pytloun9e404cf2016-04-14 11:51:09 +0200109 git clone $dep_source ${DEPSDIR}/$(basename $dep_source .git)
Jakub Pavlikfe0960c2016-01-25 21:35:39 +0100110 ln -s ${dep_root}/${dep_name} ${SALT_FILE_DIR}/${dep_name}
111
112 METADATA="${dep_metadata}" install_dependencies
113}
114
115install_dependencies() {
116 grep -E "^dependencies:" ${METADATA} >/dev/null || return 0
117 (python - | while read dep; do fetch_dependency "$dep"; done) << EOF
118import sys,yaml
119for dep in yaml.load(open('${METADATA}', 'ro'))['dependencies']:
Filip Pytloun9e404cf2016-04-14 11:51:09 +0200120 print '%s:%s' % (dep["name"], dep["source"])
Jakub Pavlikfe0960c2016-01-25 21:35:39 +0100121EOF
122}
123
124clean() {
125 log_info "Cleaning up ${BUILDDIR}"
126 [ -d ${BUILDDIR} ] && rm -rf ${BUILDDIR} || exit 0
127}
128
129salt_run() {
Jakub Josefdbe0bf22017-12-15 16:58:29 +0100130 [ -e ${VENV_DIR}/bin/activate ] && source ${VENV_DIR}/bin/activate
Jakub Josef9eb6a032018-02-08 13:22:15 +0100131 python $(which salt-call) ${SALT_OPTS} $*
Jakub Pavlikfe0960c2016-01-25 21:35:39 +0100132}
133
134prepare() {
135 [ -d ${BUILDDIR} ] && mkdir -p ${BUILDDIR}
136
Filip Pytloun9e404cf2016-04-14 11:51:09 +0200137 which salt-call || setup_virtualenv
Oleksandr Shyshko87005682018-07-31 18:31:57 +0300138 setup_mock_bin
Jakub Pavlikfe0960c2016-01-25 21:35:39 +0100139 setup_pillar
140 setup_salt
141 install_dependencies
142}
143
144run() {
145 for pillar in ${PILLARDIR}/*.sls; do
Jakub Pavlik882f8482017-04-06 16:38:35 +0200146 grep ${FORMULA_NAME}: ${pillar} &>/dev/null || continue
Jakub Pavlikfe0960c2016-01-25 21:35:39 +0100147 state_name=$(basename ${pillar%.sls})
Oleksandr Shyshko87005682018-07-31 18:31:57 +0300148 salt_run grains.set 'noservices' False force=True
149
150 echo "Checking state ${FORMULA_NAME}.${state_name} ..."
Jakub Pavlikfe0960c2016-01-25 21:35:39 +0100151 salt_run --id=${state_name} state.show_sls ${FORMULA_NAME} || (log_err "Execution of ${FORMULA_NAME}.${state_name} failed"; exit 1)
Oleksandr Shyshko87005682018-07-31 18:31:57 +0300152
153 # Check that all files in 'meta' folder can be rendered using any valid pillar
154 for meta in `find ${FORMULA_META_DIR} -type f`; do
155 meta_name=$(basename ${meta})
156 echo "Checking meta ${meta_name} ..."
157 salt_run --out=quiet --id=${state_name} cp.get_template ${meta} ${SALT_CACHE_DIR}/${meta_name} \
158 || (log_err "Failed to render meta ${meta} using pillar ${FORMULA_NAME}.${state_name}"; exit 1)
159 cat ${SALT_CACHE_DIR}/${meta_name}
160 done
161 done
162}
163
164real_run() {
165 for pillar in ${PILLARDIR}/*.sls; do
166 state_name=$(basename ${pillar%.sls})
167 salt_run --id=${state_name} state.sls ${FORMULA_NAME} || (log_err "Execution of ${FORMULA_NAME}.${state_name} failed"; exit 1)
Jakub Pavlikfe0960c2016-01-25 21:35:39 +0100168 done
169}
170
171_atexit() {
172 RETVAL=$?
173 trap true INT TERM EXIT
174
175 if [ $RETVAL -ne 0 ]; then
176 log_err "Execution failed"
177 else
178 log_info "Execution successful"
179 fi
180 return $RETVAL
181}
182
183## Main
184trap _atexit INT TERM EXIT
185
186case $1 in
187 clean)
188 clean
189 ;;
190 prepare)
191 prepare
192 ;;
193 run)
194 run
195 ;;
Oleksandr Shyshko87005682018-07-31 18:31:57 +0300196 real-run)
197 real_run
198 ;;
Jakub Pavlikfe0960c2016-01-25 21:35:39 +0100199 *)
200 prepare
201 run
202 ;;
203esac