Ales Komarek | 1b37311 | 2017-08-08 08:48:56 +0200 | [diff] [blame] | 1 | #!/bin/bash |
| 2 | |
| 3 | # Usage: |
| 4 | # ./formula-fetch.sh <Formula URL> <Name> <Branch> |
| 5 | # |
Petr Michalec | 40e909d | 2018-03-26 21:15:50 +0200 | [diff] [blame] | 6 | # Example usage: |
| 7 | # FORMULA_SOURCES=https://github.com/epcim/my-salt-formulas https://github.com/salt-formulas https://github.com/saltstack-formulas |
| 8 | # SALT_ENV_PATH=.vendor/formulas |
Ales Komarek | 1b37311 | 2017-08-08 08:48:56 +0200 | [diff] [blame] | 9 | # -- |
Petr Michalec | 40e909d | 2018-03-26 21:15:50 +0200 | [diff] [blame] | 10 | # ./formula-fetch.sh |
Ales Komarek | 1b37311 | 2017-08-08 08:48:56 +0200 | [diff] [blame] | 11 | # xargs -n1 ./formula-fetch.sh < dependencies.txt |
| 12 | |
| 13 | |
Petr Michalec | 40e909d | 2018-03-26 21:15:50 +0200 | [diff] [blame] | 14 | ## DEFAULTS |
| 15 | # |
| 16 | # default sources |
| 17 | FORMULA_SOURCES="${SALT_FORMULA_SOURCES:-https://github.com/salt-formulas https://github.com/saltstack-formulas}" |
| 18 | FORMULA_VERSION="${SALT_FORMULA_VERSION:-master}" |
Petr Michalec | fbebe99 | 2018-03-29 10:07:48 +0200 | [diff] [blame^] | 19 | # where to fetch formulas |
| 20 | FORMULAS_BASE=${SALT_FORMULAS_BASE:-/srv/salt/formulas} |
| 21 | # For better stability, skip formula repos without recognized CI |
| 22 | FORMULA_WITHOUT_CI=${SALT_FORMULA_WITHOUT_CI:-false} |
Petr Michalec | 40e909d | 2018-03-26 21:15:50 +0200 | [diff] [blame] | 23 | # salt env/root, where formulas are found |
| 24 | SALT_ENV_PATH=${SALT_ENV_PATH:-/srv/salt/env/prd} |
| 25 | #SALT_ENV_PATH=${SALT_ENV_PATH:-.vendor/formulas} |
| 26 | #SALT_ENV_PATH=${SALT_ENV_PATH:/usr/share/salt-formulas/env/_formulas} |
Petr Michalec | 40e909d | 2018-03-26 21:15:50 +0200 | [diff] [blame] | 27 | # reclass related |
| 28 | RECLASS_BASE=${RECLASS_BASE:-/srv/salt/reclass} |
Petr Michalec | fbebe99 | 2018-03-29 10:07:48 +0200 | [diff] [blame^] | 29 | # env |
Petr Michalec | 40e909d | 2018-03-26 21:15:50 +0200 | [diff] [blame] | 30 | LC_ALL=en_US.UTF-8 |
| 31 | LANG=en_US.UTF-8 |
| 32 | |
| 33 | |
Ales Komarek | 1b37311 | 2017-08-08 08:48:56 +0200 | [diff] [blame] | 34 | # Parse git dependencies from metadata.yml |
| 35 | # $1 - path to <formula>/metadata.yml |
| 36 | # sample to output: |
| 37 | # https://github.com/salt-formulas/salt-formula-git git |
| 38 | # https://github.com/salt-formulas/salt-formula-salt salt |
| 39 | function fetchDependencies() { |
| 40 | METADATA="$1"; |
Petr Michalec | 40e909d | 2018-03-26 21:15:50 +0200 | [diff] [blame] | 41 | grep -E "^dependencies:" "$METADATA" &>/dev/null || return 0 |
| 42 | (python3 - "$METADATA" | while read dep; do fetchGitFormula $dep; done) <<-DEPS |
Ales Komarek | 1b37311 | 2017-08-08 08:48:56 +0200 | [diff] [blame] | 43 | import sys,yaml |
Petr Michalec | 40e909d | 2018-03-26 21:15:50 +0200 | [diff] [blame] | 44 | try: |
| 45 | for dep in yaml.load(open(sys.argv[1], "r"))["dependencies"]: |
| 46 | if len(set(('name', 'source')) & set(dep.keys())) == 2: |
| 47 | print("{source} {name}".format(**dep)) |
| 48 | except: |
| 49 | pass |
Ales Komarek | 1b37311 | 2017-08-08 08:48:56 +0200 | [diff] [blame] | 50 | DEPS |
| 51 | } |
| 52 | |
Petr Michalec | 40e909d | 2018-03-26 21:15:50 +0200 | [diff] [blame] | 53 | |
| 54 | # Read formula name from meetadata.yml |
| 55 | # $1 - path to <formula>/metadata.yml |
| 56 | function getFormulaName() { |
| 57 | python3 - "$1" <<-READ_NAME |
| 58 | try: |
| 59 | import sys,yaml;print(yaml.load(open(sys.argv[1], "r"))["name"]); |
| 60 | except: |
| 61 | pass |
| 62 | READ_NAME |
| 63 | } |
| 64 | |
| 65 | |
Ales Komarek | 1b37311 | 2017-08-08 08:48:56 +0200 | [diff] [blame] | 66 | # Fetch formula from git repo |
| 67 | # $1 - formula git repo url |
| 68 | # $2 - formula name (optional) |
| 69 | # $3 - branch (optional) |
| 70 | function fetchGitFormula() { |
| 71 | test -n "${FETCHED}" || declare -a FETCHED=() |
Petr Michalec | 40e909d | 2018-03-26 21:15:50 +0200 | [diff] [blame] | 72 | mkdir -p "$SALT_ENV_PATH" "$FORMULAS_BASE" |
| 73 | |
Ales Komarek | 1b37311 | 2017-08-08 08:48:56 +0200 | [diff] [blame] | 74 | if [ -n "$1" ]; then |
Petr Michalec | 40e909d | 2018-03-26 21:15:50 +0200 | [diff] [blame] | 75 | |
| 76 | # set origin uri |
| 77 | # FIXME, TEMP fix for not yet up to date gh:salt-formulas -> s/tcpcloud/salt-formulas/ |
| 78 | origin="${1/tcpcloud/salt-formulas}" |
| 79 | # set gh repo https://salt-formulas/salt-formula-salt -> $FORMULAS_BASE/salt-formulas/salt-formula-salt |
| 80 | repo=$(echo $origin | awk -F'/' '{ print substr($0, index($0,$4)) }') |
| 81 | # set normula name |
| 82 | test -n "$2" && name=$2 || name="$(echo ${origin//*\/} | sed -e 's/-formula$//' -e 's/^salt-formula-//' -e 's/^formula-//')" |
| 83 | # set branch |
| 84 | test -n "$3" && branch=$3 || branch=${FORMULA_VERSION} |
| 85 | |
| 86 | # DEBUG |
| 87 | #echo '--- ------------------------------' |
| 88 | #echo origin, $origin |
| 89 | #echo repo, $repo |
| 90 | #echo fetched ${FETCHED[@]} |
| 91 | #echo -e name, $name |
| 92 | #echo '---' |
| 93 | #return |
| 94 | |
Ales Komarek | 1b37311 | 2017-08-08 08:48:56 +0200 | [diff] [blame] | 95 | if ! [[ "${FETCHED[*]}" =~ $name ]]; then # dependency not yet fetched |
Petr Michalec | 40e909d | 2018-03-26 21:15:50 +0200 | [diff] [blame] | 96 | echo -e "[I] Fetching: $origin -> $FORMULAS_BASE/$repo" |
| 97 | if [ -e "$FORMULAS_BASE/$repo" ]; then |
| 98 | pushd "$FORMULAS_BASE/$repo" &>/dev/null |
| 99 | git pull -r; git checkout $branch; |
Ales Komarek | 1b37311 | 2017-08-08 08:48:56 +0200 | [diff] [blame] | 100 | popd &>/dev/null |
| 101 | else |
Petr Michalec | 40e909d | 2018-03-26 21:15:50 +0200 | [diff] [blame] | 102 | echo -e "[I] git clone $origin $FORMULAS_BASE/$repo -b $branch" |
| 103 | if ! git ls-remote --exit-code --heads $origin $branch; then |
| 104 | # Fallback to the master branch if the branch doesn't exist for this repository |
| 105 | branch=master |
| 106 | fi |
| 107 | if ! git clone "$origin" "$FORMULAS_BASE/$repo" -b "$branch"; then |
| 108 | echo -e "[E] Fetching formula from $origin failed." |
| 109 | return ${FAIL_ON_ERRORS:-0} |
| 110 | fi |
Ales Komarek | 1b37311 | 2017-08-08 08:48:56 +0200 | [diff] [blame] | 111 | fi |
Petr Michalec | 40e909d | 2018-03-26 21:15:50 +0200 | [diff] [blame] | 112 | |
Petr Michalec | fbebe99 | 2018-03-29 10:07:48 +0200 | [diff] [blame^] | 113 | # Avoid checkout formulas/repos without CI |
| 114 | if ! $FORMULA_WITHOUT_CI; then |
| 115 | CI=false |
| 116 | for p in .circleci .travis.yml .kitchen.yml invoke.yml tasks.py; do |
| 117 | if [ -e "$FORMULAS_BASE/$repo/$p" ]; then |
| 118 | CI=true; break; |
| 119 | fi |
| 120 | done |
| 121 | if ! $CI; then |
| 122 | mv "$FORMULAS_BASE/$repo" "$FORMULAS_BASE/${repo}.deprecated-no-ci"; |
| 123 | return; |
| 124 | fi |
| 125 | fi |
| 126 | |
Petr Michalec | 40e909d | 2018-03-26 21:15:50 +0200 | [diff] [blame] | 127 | # metadata.yml is github.com/salt-formulas specific |
| 128 | if [ ! -n "$2" -a -e "$FORMULAS_BASE/$repo/metadata.yml" ]; then |
| 129 | # try to update name as in formula metadata |
| 130 | name=$(getFormulaName "$FORMULAS_BASE/$repo/metadata.yml") |
| 131 | fi |
| 132 | |
| 133 | # SET FORMULA IN SALT ENV |
| 134 | if [ ! -e "$SALT_ENV_PATH/$name" ]; then |
| 135 | if [ -e $FORMULAS_BASE/$repo/$name ]; then |
| 136 | |
| 137 | # link formula |
| 138 | ln -svf $FORMULAS_BASE/$repo/$name $SALT_ENV_PATH/$name |
| 139 | |
| 140 | # copy custom _states, _modules, _etc ... |
| 141 | for c in $(/bin/ls $FORMULAS_BASE/$repo | grep '^_' | xargs -n1 --no-run-if-empty); do |
| 142 | test -e $SALT_ENV_PATH/$c || mkdir -p $SALT_ENV_PATH/$c |
| 143 | ln -svf $FORMULAS_BASE/$repo/$c/* $SALT_ENV_PATH/$c |
| 144 | done |
| 145 | |
| 146 | # install optional dependencies (python/pip related as of now only) |
| 147 | if [ -e $FORMULAS_BASE/$repo/requirements.txt ]; then |
| 148 | pip install -r $FORMULAS_BASE/$repo/requirements.txt |
| 149 | fi |
| 150 | |
| 151 | # NOTE: github.com/salt-formulas specific steps |
| 152 | # link formula service pillars |
| 153 | if [ ! -n "$RECLASS_BASE" -a -e "$FORMULAS_BASE/$repo/metadata/service" ]; then |
| 154 | test -e $RECLASS_BASE/service || mkdir -p $RECLASS_BASE/service |
| 155 | ln -svf $FORMULAS_BASE/$repo/metadata/service $RECLASS_BASE/service/$name |
| 156 | fi |
| 157 | # install dependencies |
| 158 | FETCHED+=($name) |
| 159 | if [ -e "$FORMULAS_BASE/$repo/metadata.yml" ]; then |
| 160 | fetchDependencies "$FORMULAS_BASE/$repo/metadata.yml" |
| 161 | fi |
| 162 | else |
| 163 | echo -e "[E] The repository $FORMULAS_BASE/$repo was not recognized as formula repository." |
| 164 | return ${FAIL_ON_ERRORS:-0} |
| 165 | fi |
| 166 | else |
| 167 | echo -e "[I] Formula "$name" already fetched." |
| 168 | fi |
Ales Komarek | 1b37311 | 2017-08-08 08:48:56 +0200 | [diff] [blame] | 169 | fi |
| 170 | else |
Petr Michalec | 40e909d | 2018-03-26 21:15:50 +0200 | [diff] [blame] | 171 | echo -e '[I] Usage: fetchGitFormula git_repo_uri [branch] [local formula directory name]' |
Ales Komarek | 1b37311 | 2017-08-08 08:48:56 +0200 | [diff] [blame] | 172 | fi |
| 173 | } |
| 174 | |
Petr Michalec | 40e909d | 2018-03-26 21:15:50 +0200 | [diff] [blame] | 175 | # DEPRECATED, kept for backward compatibility |
| 176 | # for github.com/salt-formulas (linking "service" pillar metadata from formula to reclas classes) |
Ales Komarek | 1b37311 | 2017-08-08 08:48:56 +0200 | [diff] [blame] | 177 | function linkFormulas() { |
| 178 | # OPTIONAL: Link formulas from git/pkg |
| 179 | |
| 180 | SALT_ROOT=$1 |
| 181 | SALT_ENV=${2:-/usr/share/salt-formulas/env} |
| 182 | |
| 183 | # form git, development versions |
| 184 | find "$SALT_ENV"/_formulas -maxdepth 1 -mindepth 1 -type d -print0| xargs -0 -n1 --no-run-if-empty basename | xargs -I{} --no-run-if-empty \ |
| 185 | ln -fs "$SALT_ENV"/_formulas/{}/{} "$SALT_ROOT"/{}; |
| 186 | |
| 187 | # form pkgs |
| 188 | find "$SALT_ENV" -maxdepth 1 -mindepth 1 -path "*_formulas*" -prune -o -name "*" -type d -print0| xargs -0 -n1 --no-run-if-empty basename | xargs -I{} --no-run-if-empty \ |
| 189 | ln -fs "$SALT_ENV"/{} "$SALT_ROOT"/{}; |
Petr Michalec | 40e909d | 2018-03-26 21:15:50 +0200 | [diff] [blame] | 190 | } |
Ales Komarek | 1b37311 | 2017-08-08 08:48:56 +0200 | [diff] [blame] | 191 | |
Petr Michalec | 40e909d | 2018-03-26 21:15:50 +0200 | [diff] [blame] | 192 | |
| 193 | function setupPyEnv() { |
| 194 | MODULES="pygithub pyyaml" |
| 195 | pip3 install --upgrade $MODULES || { |
| 196 | which pipenv || { |
| 197 | pip install --upgrade pipenv |
| 198 | } |
| 199 | pipenv --three |
| 200 | pipenv install $MODULES |
| 201 | } |
| 202 | } |
| 203 | |
| 204 | function listRepos_github_com() { |
| 205 | #export python=$(pipenv --py || (setupPyEnv &>/dev/null; pipenv --py)) |
| 206 | if [ -e Pipfile.lock ]; then python=$(pipenv --py); else python=python3; fi |
| 207 | $python - "$1" <<-LIST_REPOS |
| 208 | import sys |
| 209 | import github |
| 210 | |
| 211 | def make_github_agent(user=None, password=None): |
| 212 | """ Create github agent to auth """ |
| 213 | if not user: |
| 214 | return github.Github() |
| 215 | else: |
| 216 | return github.Github(user, password) |
| 217 | |
| 218 | def get_org_repos(gh, org_name): |
| 219 | org = gh.get_organization(org_name) |
| 220 | for repo in org.get_repos(): |
| 221 | yield repo.name |
| 222 | |
| 223 | print(*get_org_repos(make_github_agent(), str(sys.argv[1])), sep="\n") |
| 224 | LIST_REPOS |
| 225 | } |
| 226 | |
| 227 | function fetchAll() { |
| 228 | for source in $(echo ${FORMULA_SOURCES} | xargs -n1 --no-run-if-empty| xargs -n1 --no-run-if-empty); do |
| 229 | hosting=$(echo ${source//\./_} | awk -F'/' '{print $3}') |
| 230 | orgname=$(echo ${source//\./_} | awk -F'/' '{print $4}') |
| 231 | for repo in $(listRepos_$hosting "$orgname" | xargs -n1 --no-run-if-empty| sort); do |
| 232 | # TODO, avoid a hardcoded pattern to filter formula repos |
| 233 | if [[ $repo =~ ^(.*formula.*)$ ]]; then |
| 234 | fetchGitFormula "$source/$repo"; |
| 235 | fi |
| 236 | done; |
| 237 | done; |
Ales Komarek | 1b37311 | 2017-08-08 08:48:56 +0200 | [diff] [blame] | 238 | } |
| 239 | |
| 240 | # detect if file is being sourced |
| 241 | [[ "$0" != "$BASH_SOURCE" ]] || { |
Petr Michalec | 40e909d | 2018-03-26 21:15:50 +0200 | [diff] [blame] | 242 | # if executed, fetch specific formula |
| 243 | fetchGitFormula ${@} |
Ales Komarek | 1b37311 | 2017-08-08 08:48:56 +0200 | [diff] [blame] | 244 | } |