blob: 3155e5da0acbcbf615c896f3a09085d35c6e89c7 [file] [log] [blame]
Ales Komarekc3976c52016-01-25 23:15:20 +01001#!/usr/bin/env bash
2
3set -e
Botond Zoltán4c1125f2017-08-31 08:44:51 +02004if [[ $DEBUG =~ ^(True|true|1|yes)$ ]]; then
5 set -x
6fi
Ales Komarekc3976c52016-01-25 23:15:20 +01007
8CURDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
9METADATA=${CURDIR}/../metadata.yml
10FORMULA_NAME=$(cat $METADATA | python -c "import sys,yaml; print yaml.load(sys.stdin)['name']")
Dennis Dmitriev30b51612017-07-06 21:07:27 +030011FORMULA_META_DIR=${CURDIR}/../${FORMULA_NAME}/meta
Ales Komarekc3976c52016-01-25 23:15:20 +010012
13## Overrideable parameters
14PILLARDIR=${PILLARDIR:-${CURDIR}/pillar}
15BUILDDIR=${BUILDDIR:-${CURDIR}/build}
16VENV_DIR=${VENV_DIR:-${BUILDDIR}/virtualenv}
Dennis Dmitriev30b51612017-07-06 21:07:27 +030017MOCK_BIN_DIR=${MOCK_BIN_DIR:-${CURDIR}/mock_bin}
Ales Komarekc3976c52016-01-25 23:15:20 +010018DEPSDIR=${BUILDDIR}/deps
19
20SALT_FILE_DIR=${SALT_FILE_DIR:-${BUILDDIR}/file_root}
21SALT_PILLAR_DIR=${SALT_PILLAR_DIR:-${BUILDDIR}/pillar_root}
22SALT_CONFIG_DIR=${SALT_CONFIG_DIR:-${BUILDDIR}/salt}
23SALT_CACHE_DIR=${SALT_CACHE_DIR:-${SALT_CONFIG_DIR}/cache}
24
Dennis Dmitriev30b51612017-07-06 21:07:27 +030025SALT_OPTS="${SALT_OPTS} --retcode-passthrough --local -c ${SALT_CONFIG_DIR} --log-file=/dev/null"
Ales Komarekc3976c52016-01-25 23:15:20 +010026
Botond Zoltán4c1125f2017-08-31 08:44:51 +020027if [ -n "${SALT_VERSION}" ]; then
Ales Komarekc3976c52016-01-25 23:15:20 +010028 PIP_SALT_VERSION="==${SALT_VERSION}"
29fi
30
31## Functions
32log_info() {
33 echo "[INFO] $*"
34}
35
36log_err() {
37 echo "[ERROR] $*" >&2
38}
39
40setup_virtualenv() {
41 log_info "Setting up Python virtualenv"
42 virtualenv $VENV_DIR
43 source ${VENV_DIR}/bin/activate
Jakub Josef9e8a45d2018-02-08 13:22:15 +010044 python -m pip install salt${PIP_SALT_VERSION}
Ales Komarekc3976c52016-01-25 23:15:20 +010045}
46
Dennis Dmitriev30b51612017-07-06 21:07:27 +030047setup_mock_bin() {
48 # If some state requires a binary, a lightweight replacement for
49 # such binary can be put into MOCK_BIN_DIR for test purposes
50 if [ -d "${MOCK_BIN_DIR}" ]; then
51 PATH="${MOCK_BIN_DIR}:$PATH"
52 export PATH
53 fi
54}
55
Ales Komarekc3976c52016-01-25 23:15:20 +010056setup_pillar() {
57 [ ! -d ${SALT_PILLAR_DIR} ] && mkdir -p ${SALT_PILLAR_DIR}
58 echo "base:" > ${SALT_PILLAR_DIR}/top.sls
59 for pillar in ${PILLARDIR}/*; do
Dennis Dmitriev30b51612017-07-06 21:07:27 +030060 grep ${FORMULA_NAME}: ${pillar} &>/dev/null || continue
Ales Komarekc3976c52016-01-25 23:15:20 +010061 state_name=$(basename ${pillar%.sls})
62 echo -e " ${state_name}:\n - ${state_name}" >> ${SALT_PILLAR_DIR}/top.sls
63 done
64}
65
66setup_salt() {
67 [ ! -d ${SALT_FILE_DIR} ] && mkdir -p ${SALT_FILE_DIR}
68 [ ! -d ${SALT_CONFIG_DIR} ] && mkdir -p ${SALT_CONFIG_DIR}
69 [ ! -d ${SALT_CACHE_DIR} ] && mkdir -p ${SALT_CACHE_DIR}
70
71 echo "base:" > ${SALT_FILE_DIR}/top.sls
72 for pillar in ${PILLARDIR}/*.sls; do
Dennis Dmitriev30b51612017-07-06 21:07:27 +030073 grep ${FORMULA_NAME}: ${pillar} &>/dev/null || continue
Ales Komarekc3976c52016-01-25 23:15:20 +010074 state_name=$(basename ${pillar%.sls})
75 echo -e " ${state_name}:\n - ${FORMULA_NAME}" >> ${SALT_FILE_DIR}/top.sls
76 done
77
78 cat << EOF > ${SALT_CONFIG_DIR}/minion
79file_client: local
80cachedir: ${SALT_CACHE_DIR}
81verify_env: False
Dennis Dmitriev30b51612017-07-06 21:07:27 +030082minion_id_caching: False
Ales Komarekc3976c52016-01-25 23:15:20 +010083
84file_roots:
85 base:
86 - ${SALT_FILE_DIR}
87 - ${CURDIR}/..
Filip Pytloun0a6f3ba2016-04-14 11:51:09 +020088 - /usr/share/salt-formulas/env
Ales Komarekc3976c52016-01-25 23:15:20 +010089
90pillar_roots:
91 base:
92 - ${SALT_PILLAR_DIR}
93 - ${PILLARDIR}
94EOF
95}
96
97fetch_dependency() {
Filip Pytloun0a6f3ba2016-04-14 11:51:09 +020098 dep_name="$(echo $1|cut -d : -f 1)"
Filip Pytloun9f823e22016-04-14 16:38:53 +020099 dep_source="$(echo $1|cut -d : -f 2-)"
Filip Pytloun0a6f3ba2016-04-14 11:51:09 +0200100 dep_root="${DEPSDIR}/$(basename $dep_source .git)"
Ales Komarekc3976c52016-01-25 23:15:20 +0100101 dep_metadata="${dep_root}/metadata.yml"
102
Filip Pytloun0a6f3ba2016-04-14 11:51:09 +0200103 [ -d /usr/share/salt-formulas/env/${dep_name} ] && log_info "Dependency $dep_name already present in system-wide salt env" && return 0
104 [ -d $dep_root ] && log_info "Dependency $dep_name already fetched" && return 0
Ales Komarekc3976c52016-01-25 23:15:20 +0100105
Filip Pytloun0a6f3ba2016-04-14 11:51:09 +0200106 log_info "Fetching dependency $dep_name"
Ales Komarekc3976c52016-01-25 23:15:20 +0100107 [ ! -d ${DEPSDIR} ] && mkdir -p ${DEPSDIR}
Filip Pytloun56c63ef2016-04-14 12:46:30 +0200108 git clone $dep_source ${DEPSDIR}/$(basename $dep_source .git)
Ales Komarekc3976c52016-01-25 23:15:20 +0100109 ln -s ${dep_root}/${dep_name} ${SALT_FILE_DIR}/${dep_name}
110
111 METADATA="${dep_metadata}" install_dependencies
112}
113
114install_dependencies() {
115 grep -E "^dependencies:" ${METADATA} >/dev/null || return 0
116 (python - | while read dep; do fetch_dependency "$dep"; done) << EOF
117import sys,yaml
118for dep in yaml.load(open('${METADATA}', 'ro'))['dependencies']:
Filip Pytloun0a6f3ba2016-04-14 11:51:09 +0200119 print '%s:%s' % (dep["name"], dep["source"])
Ales Komarekc3976c52016-01-25 23:15:20 +0100120EOF
121}
122
123clean() {
124 log_info "Cleaning up ${BUILDDIR}"
125 [ -d ${BUILDDIR} ] && rm -rf ${BUILDDIR} || exit 0
126}
127
128salt_run() {
Jakub Josefb0ab09b2017-12-15 16:58:29 +0100129 [ -e ${VENV_DIR}/bin/activate ] && source ${VENV_DIR}/bin/activate
Jakub Josef9e8a45d2018-02-08 13:22:15 +0100130 python $(which salt-call) ${SALT_OPTS} $*
Ales Komarekc3976c52016-01-25 23:15:20 +0100131}
132
133prepare() {
134 [ -d ${BUILDDIR} ] && mkdir -p ${BUILDDIR}
135
Filip Pytloun0a6f3ba2016-04-14 11:51:09 +0200136 which salt-call || setup_virtualenv
Dennis Dmitriev30b51612017-07-06 21:07:27 +0300137 setup_mock_bin
Ales Komarekc3976c52016-01-25 23:15:20 +0100138 setup_pillar
139 setup_salt
140 install_dependencies
141}
142
143run() {
144 for pillar in ${PILLARDIR}/*.sls; do
Dennis Dmitriev30b51612017-07-06 21:07:27 +0300145 grep ${FORMULA_NAME}: ${pillar} &>/dev/null || continue
Ales Komarekc3976c52016-01-25 23:15:20 +0100146 state_name=$(basename ${pillar%.sls})
Dennis Dmitriev30b51612017-07-06 21:07:27 +0300147 salt_run grains.set 'noservices' False force=True
148
149 echo "Checking state ${FORMULA_NAME}.${state_name} ..."
Ales Komarekc3976c52016-01-25 23:15:20 +0100150 salt_run --id=${state_name} state.show_sls ${FORMULA_NAME} || (log_err "Execution of ${FORMULA_NAME}.${state_name} failed"; exit 1)
Dennis Dmitriev30b51612017-07-06 21:07:27 +0300151
152 # Check that all files in 'meta' folder can be rendered using any valid pillar
153 for meta in `find ${FORMULA_META_DIR} -type f`; do
154 meta_name=$(basename ${meta})
155 echo "Checking meta ${meta_name} ..."
156 salt_run --out=quiet --id=${state_name} cp.get_template ${meta} ${SALT_CACHE_DIR}/${meta_name} \
157 || (log_err "Failed to render meta ${meta} using pillar ${FORMULA_NAME}.${state_name}"; exit 1)
158 cat ${SALT_CACHE_DIR}/${meta_name}
159 done
160 done
161}
162
163real_run() {
164 for pillar in ${PILLARDIR}/*.sls; do
165 state_name=$(basename ${pillar%.sls})
166 salt_run --id=${state_name} state.sls ${FORMULA_NAME} || (log_err "Execution of ${FORMULA_NAME}.${state_name} failed"; exit 1)
Ales Komarekc3976c52016-01-25 23:15:20 +0100167 done
168}
169
170_atexit() {
171 RETVAL=$?
172 trap true INT TERM EXIT
173
174 if [ $RETVAL -ne 0 ]; then
175 log_err "Execution failed"
176 else
177 log_info "Execution successful"
178 fi
179 return $RETVAL
180}
181
182## Main
183trap _atexit INT TERM EXIT
184
185case $1 in
186 clean)
187 clean
188 ;;
189 prepare)
190 prepare
191 ;;
192 run)
193 run
194 ;;
Dennis Dmitriev30b51612017-07-06 21:07:27 +0300195 real-run)
196 real_run
197 ;;
Ales Komarekc3976c52016-01-25 23:15:20 +0100198 *)
199 prepare
200 run
201 ;;
202esac