Update Bash Library
[releng/global-jjb.git] / jenkins-init-scripts / lf-env.sh
1 #!/usr/bin/no-execute
2
3 # SPDX-License-Identifier: EPL-1.0
4 ##############################################################################
5 # Copyright (c) 2019 The Linux Foundation and others.
6 #
7 # All rights reserved. This program and the accompanying materials
8 # are made available under the terms of the Eclipse Public License v1.0
9 # which accompanies this distribution, and is available at
10 # http://www.eclipse.org/legal/epl-v10.html
11 ##############################################################################
12
13 # A library of functions for LF/Jenkins bash scripts. In the general case, these
14 # functions should only use 'local' variables, and should NOT set
15 # shell/environment variables. If you want to make a
16 # variable available, provide a function that sets the variable: 'function
17 # lf_set_foo() {foo=asdf;}'. Any scripts that need access to the variable can
18 # call the 'set' function. This keeps the name-space pollution to a minimum.
19
20 # Shell variables that are shared between functions
21
22 _lf_done_file=".lf-done"
23
24 ################################################################################
25 #
26 # Name:    lf-echo-stderr
27 #
28 # SYNOPSIS
29 #       source ~/lf-env.sh
30 #
31 #       lf-echo-stderr "this entire" "string will be sent to stderr"
32 #
33 # DESCRIPTION
34 #       This function will echo all command line aruments to 'stderr'
35 #
36 # RETURN VALUE
37 #       None
38 #
39 ################################################################################
40
41 function lf-echo-stderr() { echo "$@" 1>&2; }
42
43 ################################################################################
44 #
45 # NAME
46 #       lf-boolean()
47 #
48 # SYNOPSIS
49 #       # shellcheck disable=SC1090
50 #       source ~/lf-env.sh
51 #
52 #       if lf-boolean $VAR; then
53 #           echo "VAR is true"
54 #       fi
55 #
56 # DESCRIPTION
57 #       This function will return a BOOLEAN (true or false) based upon the value
58 #       of VAR. The value of VAR will be mapped to lower case. If VAR maps to
59 #       "true", return true(0). If VAR maps to "false", return false(1).  Any
60 #       other values will return false(2) and an error message.
61 #
62 # RETURN VALUES
63 #       true(0), false(1) or false(2)
64 #
65 ################################################################################
66
67 function lf-boolean()
68 {
69     if (( $# != 1 )); then
70         echo "ERROR: ${FUNCNAME[0]}() line: ${BASH_LINENO[0]} : Missing required argument"
71         return 1
72     fi
73     local bool
74     bool=$(echo "$1" | tr '[:upper:]' '[:lower:]')
75     case $bool in
76         true)  return 0 ;;
77         false) return 1 ;;
78         '')
79            lf-echo-stderr "ERROR: ${FUNCNAME[0]}() line:{BASH_LINENO[0]} : A boolean cannot be a empty string" >&2
80            return 2
81            ;;
82         *)
83             lf-echo-stderr "ERROR: ${FUNCNAME[0]}() line: ${BASH_LINENO[0]} : Invalid value for a boolean: '$bool'"
84             return 2
85             ;;
86     esac
87 }
88
89 ################################################################################
90 #
91 # NAME
92 #       lf-venv-activate()
93 #
94 # SYNOPSIS
95 #       # shellcheck disable=SC1090
96 #       source ~/lf-env.sh
97 #
98 #       lf-venv-activate python3
99 #
100 # DESCRIPTION
101 #       This function will validate existance of 'python' venv. If it exists
102 #       'path-to-venv/bin' will be prepended to the PATH.
103 #
104 # RETURN VALUES
105 #       None
106 #
107 ################################################################################
108
109 function lf-venv-activate()
110 {
111     if (( $# != 1 )); then
112         echo "${FUNCNAME[0]}(): Missing path operand"
113         return 1
114     fi
115     local arg=$1
116     local venv
117     if [[ $arg =~ ^python ]] && type $arg > /dev/null ; then
118         venv=~/.venv${arg#python}
119     else
120         venv=$arg
121     fi
122     # Validate the path to a VENV
123     if [[ ! -f $venv/$_lf_done_file ]]; then
124         lf-echo-stderr "ERROR: Is '$venv' a Python Environment ?"
125         return 1
126     fi
127     echo "${FUNCNAME[0]}(): Adding $venv/bin to PATH"
128     PATH=$venv/bin:$PATH
129
130 }  # ENd lf-venv-activate()
131
132 ################################################################################
133 #
134 # NAME
135 #       lf-venv-create()
136 #
137 # SYNOPSIS
138 #       # shellcheck disable=SC1090
139 #       source ~/lf-env.sh
140 #
141 #       lf-venv-create python2
142 #       or
143 #       lf-venv-create python3.6
144 #
145 # DESCRIPTION
146 #       This function will create a Python Virtual Environment based on the
147 #       python specified. The 'python' argument must be in the PATH. The venv
148 #       will be located in ~/.venv## where ## comes from the 'python' argument.
149 #       I.E. python3 -> ~/.venv3. The resulting venv will be left 'read-only' to
150 #       discourage the installation of any other packages (except by
151 #       lf-venv-add()).
152 #
153 # RETURN VALUES
154 #       None
155 #
156 ################################################################################
157
158 function lf-venv-create()
159 {
160     if (( $# != 1 )); then
161         lf-echo-stderr "${FUNCNAME[0]}(): ERROR: Missing Python argument"
162         return 1
163     fi
164     python=$1
165     if ! type $python > /dev/null; then
166         lf-echo-stderr "${FUNCNAME[0]}(): ERROR: Unknown Python: $python"
167         return 1
168     fi
169     local venv=~/.venv${python#python}
170     local suffix=$python-$$
171     local pip_log=/tmp/pip_log.$suffix
172     if [[ -f $venv/$_lf_done_file ]]; then
173         echo "Venv Already Exists: '$venv'"
174         return
175     fi
176     # Make sure noting is left over
177     if [[ -d $venv ]]; then
178         chmod -R +w $venv
179         rm -rf $venv
180     fi
181
182     echo "Creating '$python' venv ($venv)"
183
184     case $python in
185     python2*)
186         # For Python2, just create venv and install pip
187         virtualenv -p $python $venv > $pip_log || return 1
188         $venv/bin/pip install --upgrade pip > $pip_log || return 1
189         ;;
190     python3*)
191         local pkg_list="git-review jenkins-job-builder lftools[openstack] "
192         pkg_list+="python-heatclient python-openstackclient "
193         pkg_list+="setuptools testresources tox yq"
194         $python -m venv $venv > $pip_log
195         $venv/bin/pip install --upgrade pip > $pip_log || return 1
196         # Redirect errors for now
197         $venv/bin/pip install --upgrade $pkg_list >> $pip_log 2> /dev/null || return 1
198         # Generate list of packages
199         pkg_list=$($venv/bin/pip freeze | awk -F '=' '{print $1}') || return 1
200         # Update all packages, usuaally need to run twice to get all versions
201         # correct.
202         local upgrade_cmd="$venv/bin/pip install --upgrade $pkg_list"
203         if $upgrade_cmd >> $pip_log 2>&1 > /dev/null ; then
204             echo -n "Running 'pip --upgrade' to validate..."
205             $upgrade_cmd >> $pip_log || return 1
206             echo "..OK"
207         fi
208         ;;
209     *)
210         lf-echo-stderr "${FUNCNAME[0]}(): ERROR: No support for: $python"
211         return 1
212         ;;
213     esac
214
215     touch $venv/$_lf_done_file
216     # Once this venv is created, make it read-only
217     chmod -R -w $venv
218     # Archive output of 'pip freeze'
219     mkdir -p $WORKSPACE/archives
220     $venv/bin/pip freeze > $WORKSPACE/archives/freeze-log-$python || return 1
221     rm -rf $pip_log
222
223 }   # End lf-venv-create()
224
225 ################################################################################
226 #
227 # NAME
228 #       lf-venv-add()
229 #
230 # SYNOPSIS
231 #       # shellcheck disable=SC1090
232 #       source ~/lf-env.sh
233 #
234 #       lf-venv-add python3 pkg
235 #       or
236 #       lf-venv-add python2 pkg1 pkg2 pkg3
237 #
238 # DESCRIPTION
239 #       This function will add one or more python packages to an existing venv.
240 #       Attempts to add packages directly (pip) will result in errors because
241 #       the venv does not have 'write' permission.
242 #
243 # RETURN VALUES
244 #       None
245 #
246 ################################################################################
247
248 function lf-venv-add()
249 {
250     if (( $# < 2 )); then
251         lf-echo-stderr "${FUNCNAME[0]}(): ERROR: Missing Package argument"
252         return 1
253     fi
254     python=$1
255     if ! type $python > /dev/null ; then
256         lf-echo-stderr "${FUNCNAME[0]}(): ERROR: Unknown Python: $python"
257         return 1
258     fi
259     shift
260     local venv=~/.venv${python#python}
261     if [[ ! -f $venv/$_lf_done_file ]]; then
262         lf-echo-stderr "${FUNCNAME[0]}(): ERROR: '$venv' is not a valid venv"
263         return 1
264     fi
265     local pkg_list=$*
266     local pip_log=/tmp/pip_log-$$
267
268     echo "Installing '$pkg_list' into $venv"
269     chmod -R +w $venv
270     rm $venv/$_lf_done_file
271     $venv/bin/pip install --upgrade $pkg_list > $pip_log || return 1
272     pkg_list=$($venv/bin/pip freeze | awk -F '=' '{print $1}') || return 1
273     $venv/bin/pip install --upgrade $pkg_list > $pip_log || return 1
274     touch $venv/$_lf_done_file
275     chmod -R -w $venv
276     # Archive output of 'pip freeze'
277     $venv/bin/pip freeze > $WORKSPACE/archives/freeze-log-$python || return 1
278
279 } # End lf-venv-add()
280
281 ################################################################################
282 # Functions that assign Variables
283 ################################################################################
284
285 # These variables are shell (local) variables and need to be lower-case so
286 # Shellcheck knows they are shell variables and will check for
287 # 'used-before-set'.
288
289 function lf-set-maven-options()
290 {
291     # Disable 'unused-variable' check
292     # shellcheck disable=SC2034
293     maven_options="--show-version --batch-mode -Djenkins \
294         -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn \
295         -Dmaven.repo.local=/tmp/r -Dorg.ops4j.pax.url.mvn.localRepository=/tmp/r"
296 }