blob: 4af18a63bd518b4135fa98119c1466179ff3e4a2 [file] [log] [blame]
marco70723542016-06-14 20:25:31 +02001#!/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']")
Dennis Dmitriev75a3cc72017-07-06 21:07:28 +03009FORMULA_META_DIR=${CURDIR}/../${FORMULA_NAME}/meta
marco70723542016-06-14 20:25:31 +020010
11## Overrideable parameters
12PILLARDIR=${PILLARDIR:-${CURDIR}/pillar}
13BUILDDIR=${BUILDDIR:-${CURDIR}/build}
14VENV_DIR=${VENV_DIR:-${BUILDDIR}/virtualenv}
Dennis Dmitriev75a3cc72017-07-06 21:07:28 +030015MOCK_BIN_DIR=${MOCK_BIN_DIR:-${CURDIR}/mock_bin}
marco70723542016-06-14 20:25:31 +020016DEPSDIR=${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
Dennis Dmitriev75a3cc72017-07-06 21:07:28 +030023SALT_OPTS="${SALT_OPTS} --retcode-passthrough --local -c ${SALT_CONFIG_DIR} --log-file=/dev/null"
marco70723542016-06-14 20:25:31 +020024
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"
Othman Madjoudjf4922ba2021-02-03 18:59:56 +010040 dependency_check virtualenv
marco70723542016-06-14 20:25:31 +020041 virtualenv $VENV_DIR
42 source ${VENV_DIR}/bin/activate
Jakub Josef7a3d6512018-02-08 13:22:21 +010043 python -m pip install salt${PIP_SALT_VERSION}
Othman Madjoudjf4922ba2021-02-03 18:59:56 +010044 if [[ -f ${CURDIR}/test-requirements.txt ]]; then
45 python -m pip install -r ${CURDIR}/test-requirements.txt
46 fi
marco70723542016-06-14 20:25:31 +020047}
48
Dennis Dmitriev75a3cc72017-07-06 21:07:28 +030049setup_mock_bin() {
50 # If some state requires a binary, a lightweight replacement for
51 # such binary can be put into MOCK_BIN_DIR for test purposes
52 if [ -d "${MOCK_BIN_DIR}" ]; then
53 PATH="${MOCK_BIN_DIR}:$PATH"
54 export PATH
55 fi
56}
57
marco70723542016-06-14 20:25:31 +020058setup_pillar() {
59 [ ! -d ${SALT_PILLAR_DIR} ] && mkdir -p ${SALT_PILLAR_DIR}
60 echo "base:" > ${SALT_PILLAR_DIR}/top.sls
61 for pillar in ${PILLARDIR}/*; do
Dennis Dmitriev75a3cc72017-07-06 21:07:28 +030062 grep ${FORMULA_NAME}: ${pillar} &>/dev/null || continue
marco70723542016-06-14 20:25:31 +020063 state_name=$(basename ${pillar%.sls})
64 echo -e " ${state_name}:\n - ${state_name}" >> ${SALT_PILLAR_DIR}/top.sls
65 done
66}
67
68setup_salt() {
69 [ ! -d ${SALT_FILE_DIR} ] && mkdir -p ${SALT_FILE_DIR}
70 [ ! -d ${SALT_CONFIG_DIR} ] && mkdir -p ${SALT_CONFIG_DIR}
71 [ ! -d ${SALT_CACHE_DIR} ] && mkdir -p ${SALT_CACHE_DIR}
72
73 echo "base:" > ${SALT_FILE_DIR}/top.sls
74 for pillar in ${PILLARDIR}/*.sls; do
Dennis Dmitriev75a3cc72017-07-06 21:07:28 +030075 grep ${FORMULA_NAME}: ${pillar} &>/dev/null || continue
marco70723542016-06-14 20:25:31 +020076 state_name=$(basename ${pillar%.sls})
77 echo -e " ${state_name}:\n - ${FORMULA_NAME}" >> ${SALT_FILE_DIR}/top.sls
78 done
79
80 cat << EOF > ${SALT_CONFIG_DIR}/minion
81file_client: local
82cachedir: ${SALT_CACHE_DIR}
83verify_env: False
Dennis Dmitriev75a3cc72017-07-06 21:07:28 +030084minion_id_caching: False
marco70723542016-06-14 20:25:31 +020085
86file_roots:
87 base:
88 - ${SALT_FILE_DIR}
89 - ${CURDIR}/..
90 - /usr/share/salt-formulas/env
91
92pillar_roots:
93 base:
94 - ${SALT_PILLAR_DIR}
95 - ${PILLARDIR}
96EOF
97}
98
99fetch_dependency() {
100 dep_name="$(echo $1|cut -d : -f 1)"
101 dep_source="$(echo $1|cut -d : -f 2-)"
102 dep_root="${DEPSDIR}/$(basename $dep_source .git)"
103 dep_metadata="${dep_root}/metadata.yml"
104
105 [ -d /usr/share/salt-formulas/env/${dep_name} ] && log_info "Dependency $dep_name already present in system-wide salt env" && return 0
106 [ -d $dep_root ] && log_info "Dependency $dep_name already fetched" && return 0
107
108 log_info "Fetching dependency $dep_name"
109 [ ! -d ${DEPSDIR} ] && mkdir -p ${DEPSDIR}
110 git clone $dep_source ${DEPSDIR}/$(basename $dep_source .git)
111 ln -s ${dep_root}/${dep_name} ${SALT_FILE_DIR}/${dep_name}
112
113 METADATA="${dep_metadata}" install_dependencies
114}
115
116install_dependencies() {
117 grep -E "^dependencies:" ${METADATA} >/dev/null || return 0
118 (python - | while read dep; do fetch_dependency "$dep"; done) << EOF
119import sys,yaml
120for dep in yaml.load(open('${METADATA}', 'ro'))['dependencies']:
121 print '%s:%s' % (dep["name"], dep["source"])
122EOF
123}
124
125clean() {
126 log_info "Cleaning up ${BUILDDIR}"
127 [ -d ${BUILDDIR} ] && rm -rf ${BUILDDIR} || exit 0
128}
129
130salt_run() {
Jakub Josef6256e592017-12-15 16:58:31 +0100131 [ -e ${VENV_DIR}/bin/activate ] && source ${VENV_DIR}/bin/activate
Jakub Josef7a3d6512018-02-08 13:22:21 +0100132 python $(which salt-call) ${SALT_OPTS} $*
marco70723542016-06-14 20:25:31 +0200133}
134
135prepare() {
136 [ -d ${BUILDDIR} ] && mkdir -p ${BUILDDIR}
137
138 which salt-call || setup_virtualenv
Dennis Dmitriev75a3cc72017-07-06 21:07:28 +0300139 setup_mock_bin
marco70723542016-06-14 20:25:31 +0200140 setup_pillar
141 setup_salt
142 install_dependencies
143}
144
145run() {
146 for pillar in ${PILLARDIR}/*.sls; do
Dennis Dmitriev75a3cc72017-07-06 21:07:28 +0300147 grep ${FORMULA_NAME}: ${pillar} &>/dev/null || continue
marco70723542016-06-14 20:25:31 +0200148 state_name=$(basename ${pillar%.sls})
Dennis Dmitriev75a3cc72017-07-06 21:07:28 +0300149 salt_run grains.set 'noservices' False force=True
150
151 echo "Checking state ${FORMULA_NAME}.${state_name} ..."
marco70723542016-06-14 20:25:31 +0200152 salt_run --id=${state_name} state.show_sls ${FORMULA_NAME} || (log_err "Execution of ${FORMULA_NAME}.${state_name} failed"; exit 1)
Dennis Dmitriev75a3cc72017-07-06 21:07:28 +0300153
154 # Check that all files in 'meta' folder can be rendered using any valid pillar
155 for meta in `find ${FORMULA_META_DIR} -type f`; do
156 meta_name=$(basename ${meta})
157 echo "Checking meta ${meta_name} ..."
158 salt_run --out=quiet --id=${state_name} cp.get_template ${meta} ${SALT_CACHE_DIR}/${meta_name} \
159 || (log_err "Failed to render meta ${meta} using pillar ${FORMULA_NAME}.${state_name}"; exit 1)
160 cat ${SALT_CACHE_DIR}/${meta_name}
161 done
162 done
163}
164
165real_run() {
166 for pillar in ${PILLARDIR}/*.sls; do
167 state_name=$(basename ${pillar%.sls})
168 salt_run --id=${state_name} state.sls ${FORMULA_NAME} || (log_err "Execution of ${FORMULA_NAME}.${state_name} failed"; exit 1)
marco70723542016-06-14 20:25:31 +0200169 done
170}
171
Othman Madjoudjf4922ba2021-02-03 18:59:56 +0100172dependency_check() {
173 local DEPENDENCY_COMMANDS=$*
174 for DEPENDENCY_COMMAND in $DEPENDENCY_COMMANDS; do
175 which $DEPENDENCY_COMMAND > /dev/null || ( log_err "Command \"$DEPENDENCY_COMMAND\" can not be found in default path."; exit 1; )
176 done
177}
178
marco70723542016-06-14 20:25:31 +0200179_atexit() {
180 RETVAL=$?
181 trap true INT TERM EXIT
182
183 if [ $RETVAL -ne 0 ]; then
184 log_err "Execution failed"
185 else
186 log_info "Execution successful"
187 fi
188 return $RETVAL
189}
190
191## Main
192trap _atexit INT TERM EXIT
193
194case $1 in
195 clean)
196 clean
197 ;;
198 prepare)
199 prepare
200 ;;
201 run)
202 run
203 ;;
Dennis Dmitriev75a3cc72017-07-06 21:07:28 +0300204 real-run)
205 real_run
206 ;;
marco70723542016-06-14 20:25:31 +0200207 *)
208 prepare
209 run
210 ;;
211esac