Saltstack Official Home Assistant Formula
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

6 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. #!/usr/bin/env bash
  2. ###
  3. # Script requirments:
  4. # apt-get install -y python-yaml virtualenv git
  5. set -e
  6. [ -n "$DEBUG" ] && set -x
  7. CURDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
  8. METADATA=${CURDIR}/../metadata.yml
  9. FORMULA_NAME=$(cat $METADATA | python -c "import sys,yaml; print yaml.load(sys.stdin)['name']")
  10. FORMULA_META_DIR=${CURDIR}/../${FORMULA_NAME}/meta
  11. ## Overrideable parameters
  12. PILLARDIR=${PILLARDIR:-${CURDIR}/pillar}
  13. BUILDDIR=${BUILDDIR:-${CURDIR}/build}
  14. VENV_DIR=${VENV_DIR:-${BUILDDIR}/virtualenv}
  15. MOCK_BIN_DIR=${MOCK_BIN_DIR:-${CURDIR}/mock_bin}
  16. DEPSDIR=${BUILDDIR}/deps
  17. SCHEMARDIR=${SCHEMARDIR:-"${CURDIR}/../${FORMULA_NAME}/schemas/"}
  18. SALT_FILE_DIR=${SALT_FILE_DIR:-${BUILDDIR}/file_root}
  19. SALT_PILLAR_DIR=${SALT_PILLAR_DIR:-${BUILDDIR}/pillar_root}
  20. SALT_CONFIG_DIR=${SALT_CONFIG_DIR:-${BUILDDIR}/salt}
  21. SALT_CACHE_DIR=${SALT_CACHE_DIR:-${SALT_CONFIG_DIR}/cache}
  22. SALT_CACHE_EXTMODS_DIR=${SALT_CACHE_EXTMODS_DIR:-${SALT_CONFIG_DIR}/cache_master_extmods}
  23. SALT_OPTS="${SALT_OPTS} --retcode-passthrough --local -c ${SALT_CONFIG_DIR} --log-file=/dev/null"
  24. if [ "x${SALT_VERSION}" != "x" ]; then
  25. PIP_SALT_VERSION="==${SALT_VERSION}"
  26. fi
  27. ## Functions
  28. log_info() {
  29. echo -e "[INFO] $*"
  30. }
  31. log_err() {
  32. echo -e "[ERROR] $*" >&2
  33. }
  34. setup_virtualenv() {
  35. log_info "Setting up Python virtualenv"
  36. virtualenv $VENV_DIR
  37. source ${VENV_DIR}/bin/activate
  38. pip install salt${PIP_SALT_VERSION}
  39. if [[ -f ${CURDIR}/pip_requirements.txt ]]; then
  40. pip install -r ${CURDIR}/pip_requirements.txt
  41. fi
  42. }
  43. setup_mock_bin() {
  44. # If some state requires a binary, a lightweight replacement for
  45. # such binary can be put into MOCK_BIN_DIR for test purposes
  46. if [ -d "${MOCK_BIN_DIR}" ]; then
  47. PATH="${MOCK_BIN_DIR}:$PATH"
  48. export PATH
  49. fi
  50. }
  51. setup_pillar() {
  52. [ ! -d ${SALT_PILLAR_DIR} ] && mkdir -p ${SALT_PILLAR_DIR}
  53. echo "base:" > ${SALT_PILLAR_DIR}/top.sls
  54. for pillar in ${PILLARDIR}/*; do
  55. grep ${FORMULA_NAME}: ${pillar} &>/dev/null || continue
  56. state_name=$(basename ${pillar%.sls})
  57. echo -e " ${state_name}:\n - ${state_name}" >> ${SALT_PILLAR_DIR}/top.sls
  58. done
  59. }
  60. setup_salt() {
  61. [ ! -d ${SALT_FILE_DIR} ] && mkdir -p ${SALT_FILE_DIR}
  62. [ ! -d ${SALT_CONFIG_DIR} ] && mkdir -p ${SALT_CONFIG_DIR}
  63. [ ! -d ${SALT_CACHE_DIR} ] && mkdir -p ${SALT_CACHE_DIR}
  64. [ ! -d ${SALT_CACHE_EXTMODS_DIR} ] && mkdir -p ${SALT_CACHE_EXTMODS_DIR}
  65. echo "base:" > ${SALT_FILE_DIR}/top.sls
  66. for pillar in ${PILLARDIR}/*.sls; do
  67. grep ${FORMULA_NAME}: ${pillar} &>/dev/null || continue
  68. state_name=$(basename ${pillar%.sls})
  69. echo -e " ${state_name}:\n - ${FORMULA_NAME}" >> ${SALT_FILE_DIR}/top.sls
  70. done
  71. cat << EOF > ${SALT_CONFIG_DIR}/minion
  72. file_client: local
  73. cachedir: ${SALT_CACHE_DIR}
  74. extension_modules: ${SALT_CACHE_EXTMODS_DIR}
  75. verify_env: False
  76. minion_id_caching: False
  77. file_roots:
  78. base:
  79. - ${SALT_FILE_DIR}
  80. - ${CURDIR}/..
  81. pillar_roots:
  82. base:
  83. - ${SALT_PILLAR_DIR}
  84. - ${PILLARDIR}
  85. EOF
  86. }
  87. fetch_dependency() {
  88. # example: fetch_dependency "linux:https://github.com/salt-formulas/salt-formula-linux"
  89. dep_name="$(echo $1|cut -d : -f 1)"
  90. dep_source="$(echo $1|cut -d : -f 2-)"
  91. dep_root="${DEPSDIR}/$(basename $dep_source .git)"
  92. dep_metadata="${dep_root}/metadata.yml"
  93. [ -d $dep_root ] && { log_info "Dependency $dep_name already fetched"; return 0; }
  94. log_info "Fetching dependency $dep_name"
  95. [ ! -d ${DEPSDIR} ] && mkdir -p ${DEPSDIR}
  96. git clone $dep_source ${DEPSDIR}/$(basename $dep_source .git)
  97. ln -s ${dep_root}/${dep_name} ${SALT_FILE_DIR}/${dep_name}
  98. METADATA="${dep_metadata}" install_dependencies
  99. }
  100. link_modules(){
  101. # Link modules *.py files to temporary salt-root
  102. local SALT_ROOT=${1:-$SALT_FILE_DIR}
  103. local SALT_ENV=${2:-$DEPSDIR}
  104. mkdir -p "${SALT_ROOT}/_modules/"
  105. # from git, development versions
  106. find ${SALT_ENV} -maxdepth 3 -mindepth 3 -path '*_modules*' -iname "*.py" -type f -print0 | while read -d $'\0' file; do
  107. ln -fs $(readlink -e ${file}) "$SALT_ROOT"/_modules/$(basename ${file}) ;
  108. done
  109. salt_run saltutil.sync_all
  110. }
  111. install_dependencies() {
  112. grep -E "^dependencies:" ${METADATA} >/dev/null || return 0
  113. (python - | while read dep; do fetch_dependency "$dep"; done) << EOF
  114. import sys,yaml
  115. for dep in yaml.load(open('${METADATA}', 'ro'))['dependencies']:
  116. print '%s:%s' % (dep["name"], dep["source"])
  117. EOF
  118. }
  119. clean() {
  120. log_info "Cleaning up ${BUILDDIR}"
  121. [ -d ${BUILDDIR} ] && rm -rf ${BUILDDIR} || exit 0
  122. }
  123. salt_run() {
  124. [ -e ${VENV_DIR}/bin/activate ] && source ${VENV_DIR}/bin/activate
  125. salt-call ${SALT_OPTS} $*
  126. }
  127. prepare() {
  128. [ -d ${BUILDDIR} ] && mkdir -p ${BUILDDIR}
  129. [[ ! -f "${VENV_DIR}/bin/activate" ]] && setup_virtualenv
  130. setup_mock_bin
  131. setup_pillar
  132. setup_salt
  133. install_dependencies
  134. }
  135. lint_releasenotes() {
  136. [[ ! -f "${VENV_DIR}/bin/activate" ]] && setup_virtualenv
  137. source ${VENV_DIR}/bin/activate
  138. pip install reno
  139. reno lint ${CURDIR}/../
  140. }
  141. lint() {
  142. # lint_releasenotes
  143. log_err "TODO: lint_releasenotes"
  144. }
  145. run() {
  146. for pillar in ${PILLARDIR}/*.sls; do
  147. grep ${FORMULA_NAME}: ${pillar} &>/dev/null || continue
  148. state_name=$(basename ${pillar%.sls})
  149. salt_run grains.set 'noservices' False force=True
  150. echo "Checking state ${FORMULA_NAME}.${state_name} ..."
  151. salt_run --id=${state_name} state.show_sls ${FORMULA_NAME} || (log_err "Execution of ${FORMULA_NAME}.${state_name} failed"; exit 1)
  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. real_run() {
  163. for pillar in ${PILLARDIR}/*.sls; do
  164. state_name=$(basename ${pillar%.sls})
  165. salt_run --id=${state_name} state.sls ${FORMULA_NAME} || { log_err "Execution of ${FORMULA_NAME}.${state_name} failed"; exit 1; }
  166. done
  167. }
  168. run_model_validate(){
  169. [[ -d ${SCHEMARDIR} ]] || { log_err "${SCHEMARDIR} not found!"; return 1; }
  170. # model validator require py modules
  171. fetch_dependency "salt:https://github.com/salt-formulas/salt-formula-salt"
  172. link_modules
  173. # Rendered Example:
  174. # salt-call --local -c /test1/maas/tests/build/salt --id=maas_cluster modelschema.model_validate maas cluster
  175. for role in ${SCHEMARDIR}/*.yaml; do
  176. state_name=$(basename "${role%*.yaml}")
  177. minion_id="${state_name}"
  178. # in case debug-reruns, usefull to make cleanup
  179. [ -n "$DEBUG" ] && { salt_run saltutil.clear_cache; salt_run saltutil.refresh_pillar; salt_run saltutil.sync_all; }
  180. salt_run -m ${DEPSDIR}/salt-formula-salt --id=${minion_id} modelschema.model_validate ${FORMULA_NAME} ${state_name} || { log_err "Execution of ${FORMULA_NAME}.${state_name} failed"; exit 1 ; }
  181. done
  182. }
  183. _atexit() {
  184. RETVAL=$?
  185. trap true INT TERM EXIT
  186. if [ $RETVAL -ne 0 ]; then
  187. log_err "Execution failed"
  188. else
  189. log_info "Execution successful"
  190. fi
  191. return $RETVAL
  192. }
  193. ## Main
  194. trap _atexit INT TERM EXIT
  195. case $1 in
  196. clean)
  197. clean
  198. ;;
  199. prepare)
  200. prepare
  201. ;;
  202. lint)
  203. lint
  204. ;;
  205. run)
  206. run
  207. ;;
  208. real-run)
  209. real_run
  210. ;;
  211. model-validate)
  212. prepare
  213. run_model_validate
  214. ;;
  215. *)
  216. prepare
  217. # lint
  218. run
  219. run_model_validate
  220. ;;
  221. esac