b07bf8188c9b4da506c1f19e639db79e082662b0
[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 python [package]...
136 #
137 # SYNOPSIS
138 #   # shellcheck disable=SC1090
139 #   source ~/lf-env.sh
140 #
141 #   lf-venv-create python3 tox tox-pyenv virtualenv
142 #   lf-venv-create python3.6
143 #
144 # DESCRIPTION
145 #   This function will create/update a Python Virtual Environment (venv) based
146 #   on the python specified. The 'python' argument must be in the PATH. The venv
147 #   will be located in ~/.venv## where ## comes from the 'python' argument.
148 #   I.E. python3 -> ~/.venv3. The resulting venv will be left 'read-only' to
149 #   discourage the installation of any other packages (except by
150 #   lf-venv-create()). By default, only versioned packages will be installed, so
151 #   any required packages need to be specified.  By default the 'pip install
152 #   --upgrade' will be run multiple times. Sometimes pip needs that to get the
153 #   versioning correct.
154 #
155 # RETURN VALUES
156 #       None
157 #
158 ################################################################################
159
160 function lf-venv-create()
161 {
162     if (( $# < 1 )); then
163         lf-echo-stderr "${FUNCNAME[0]}(): ERROR: Missing Required Arguments"
164         return 1
165     fi
166     python=$1
167     shift
168     if ! type $python > /dev/null; then
169         lf-echo-stderr "${FUNCNAME[0]}(): ERROR: Unknown Python: $python"
170         return 1
171     fi
172     local pkg_list="$* "
173     local venv=~/.venv${python#python}
174     local suffix=$python-$$
175     local pip_log=/tmp/pip_log.$suffix
176     if [[ -f $venv/$_lf_done_file ]]; then
177         echo "Venv Already Exists: '$venv'"
178         return
179     fi
180     # Make sure noting is left over
181     if [[ -d $venv ]]; then
182         chmod -R +w $venv
183         rm -rf $venv
184     fi
185
186     echo "Creating '$python' venv ($venv)"
187
188     case $python in
189     python2*)
190         # For Python2, just create venv and install pip
191         virtualenv -p $python $venv > $pip_log || return 1
192         $venv/bin/pip install --upgrade pip > $pip_log || return 1
193         $venv/bin/pip install --upgrade $pkg_list > $pip_log || return 1
194         ;;
195     python3*)
196         # Include any packages that are tied to a specific version
197         pkg_list+="jenkins-job-builder==2.8.0 "
198         $python -m venv $venv > $pip_log
199         $venv/bin/pip install --upgrade pip > $pip_log || return 1
200         # Redirect errors for now
201         $venv/bin/pip install --upgrade $pkg_list >> $pip_log 2> /dev/null || return 1
202         # Generate list of packages
203         pkg_list=$($venv/bin/pip freeze | awk -F '=' '{print $1}') || return 1
204         # Update all packages, may need to run twice to get all versions
205         # synced up. Ignore exit status on first try
206         $venv/bin/pip install --upgrade $pkg_list >> $pip_log || true
207         echo "Running 'pip --upgrade' to validate..."
208         $venv/bin/pip install --upgrade $pkg_list >> $pip_log || return 1
209         ;;
210     *)
211         lf-echo-stderr "${FUNCNAME[0]}(): ERROR: No support for: $python"
212         return 1
213         ;;
214     esac
215
216     touch $venv/$_lf_done_file
217     # Once this venv is created, make it read-only
218     chmod -R -w $venv
219     # Archive output of 'pip freeze'
220     mkdir -p $WORKSPACE/archives
221     $venv/bin/pip freeze > $WORKSPACE/archives/freeze-log-$python || return 1
222     rm -rf $pip_log
223
224 }   # End lf-venv-create()
225
226 ################################################################################
227 #
228 # NAME
229 #   lf-venv-add()
230 #
231 # SYNOPSIS
232 #   # shellcheck disable=SC1090
233 #   source ~/lf-env.sh
234 #
235 #   lf-venv-add python3 pkg
236 #   or
237 #   lf-venv-add python2 pkg1 pkg2 pkg3
238 #
239 # DESCRIPTION
240 #   This function will add one or more python packages to an existing venv.
241 #   Attempts to add packages directly (pip) will result in errors because
242 #   the venv does not have 'write' permission.
243 #
244 # RETURN VALUES
245 #   None
246 #
247 ################################################################################
248
249 function lf-venv-add()
250 {
251     if (( $# < 2 )); then
252         lf-echo-stderr "${FUNCNAME[0]}(): ERROR: Missing Package argument"
253         return 1
254     fi
255     python=$1
256     if ! type $python > /dev/null ; then
257         lf-echo-stderr "${FUNCNAME[0]}(): ERROR: Unknown Python: $python"
258         return 1
259     fi
260     shift
261     local venv=~/.venv${python#python}
262     if [[ ! -f $venv/$_lf_done_file ]]; then
263         lf-echo-stderr "${FUNCNAME[0]}(): ERROR: '$venv' is not a valid venv"
264         return 1
265     fi
266     local pkg_list=$*
267     local pip_log=/tmp/pip_log-$$
268
269     echo "Installing '$pkg_list' into $venv"
270     chmod -R +w $venv
271     rm $venv/$_lf_done_file
272     $venv/bin/pip install --upgrade $pkg_list > $pip_log || return 1
273     pkg_list=$($venv/bin/pip freeze | awk -F '=' '{print $1}') || return 1
274     $venv/bin/pip install --upgrade $pkg_list > $pip_log || return 1
275     touch $venv/$_lf_done_file
276     chmod -R -w $venv
277     # Archive output of 'pip freeze'
278     $venv/bin/pip freeze > $WORKSPACE/archives/freeze-log-$python || return 1
279
280 } # End lf-venv-add()
281
282 ################################################################################
283 # Functions that assign Variables
284 ################################################################################
285
286 # These variables are shell (local) variables and need to be lower-case so
287 # Shellcheck knows they are shell variables and will check for
288 # 'used-before-set'.
289
290 function lf-set-maven-options()
291 {
292     # Disable 'unused-variable' check
293     # shellcheck disable=SC2034
294     maven_options="--show-version --batch-mode -Djenkins \
295         -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn \
296         -Dmaven.repo.local=/tmp/r -Dorg.ops4j.pax.url.mvn.localRepository=/tmp/r"
297 }