Chore: Upgrade Jenkins-job-builder to 6.3.0
[releng/global-jjb.git] / shell / jjb-verify-build-nodes.sh
1 #!/bin/bash -l
2 # SPDX-License-Identifier: EPL-1.0
3 ##############################################################################
4 # Copyright (c) 2020 The Linux Foundation and others.
5 #
6 # All rights reserved. This program and the accompanying materials
7 # are made available under the terms of the Eclipse Public License v1.0
8 # which accompanies this distribution, and is available at
9 # http://www.eclipse.org/legal/epl-v10.html
10 ##############################################################################
11 echo "---> jjb-verify-build-nodes.sh"
12
13 # Checks build-node labels used in ci-management templates and projects,
14 # and prints file names with invalid values.
15 #
16 # Uses -l to get $HOME/.local/bin on path, where pip puts yq
17 # Prereqs:
18 # - Bash version 3+
19 # - Python tool yq is installed; e.g., by python-tools-install.sh
20 # - Working directory is a ci-management repo with subdirs named below
21 # Environment variable:
22 # - EXTERNAL_LABELS - a space-separated list of build-node labels
23 #   for nodes not managed in the jenkins-config area (optional)
24
25 set -eu -o pipefail
26
27 # expected suffix on build-node config files
28 suffix=".cfg"
29 # subdir with cloud config files
30 configdir="jenkins-config/clouds/openstack"
31 # subdir with JJB yaml files
32 jjbdir="jjb"
33
34 # function to test if the argument is empty,
35 # is two double quotes, or has unwanted suffix
36 isBadLabel () {
37     local label="$1"
38     [[ -z "$label" ]] || [[ $label = "\"\"" ]] || [[ $label = *"$suffix" ]]
39 }
40
41 # function to search an array for a value
42 # $1 is value
43 # $2 is array, passed via ${array[@]}
44 isValueInArray () {
45     local e match="$1"
46     shift
47     for e; do
48         [[ "$e" == "$match" ]] && return 0
49     done
50     return 1
51 }
52
53 # check prereqs
54 if [ ! -d "$configdir" ] || [ ! -d "$jjbdir" ]; then
55     echo "ERROR: failed to find subdirs $configdir and $jjbdir"
56     exit 1
57 fi
58
59 # find cloud config node names by recursive descent
60 declare -a labels=()
61 while IFS= read -r ; do
62     file="$REPLY"
63     # valid files contain IMAGE_NAME; skip the cloud config file
64     if grep -q "IMAGE_NAME" "$file" && ! grep -q "CLOUD_CREDENTIAL_ID" "$file"; then
65         # file name without prefix or suffix is a valid label
66         name=$(basename -s "$suffix" "$file")
67         echo "INFO: add label $name for $file"
68         labels+=("$name")
69         # add custom labels from file
70         if custom=$(grep "LABELS=" "$file" | cut -d= -f2); then
71             # TODO: confirm separator for multiple labels
72             read -r -a customarray <<< "$custom"
73             for l in "${customarray[@]}"; do
74                 if isBadLabel "$l"; then
75                     echo "WARN: skip custom label $l from $file"
76                 elif isValueInArray "$l" "${labels[@]}"; then
77                     echo "INFO: skip repeat custom label $l from $file"
78                 else
79                     echo "INFO: add custom label $l from $file"
80                     labels+=("$l")
81                 fi
82             done
83         fi
84     fi
85 done < <(find "$configdir" -name \*$suffix)
86
87 # add external build-node labels
88 if [[ -n ${EXTERNAL_LABELS:-} ]]; then
89     read -r -a externals <<< "$EXTERNAL_LABELS"
90     # defend against empty, quotes-only and repeated values
91     for l in "${externals[@]}"; do
92         if isBadLabel "$l"; then
93             echo "WARN: skip external label $l"
94         elif isValueInArray "$l" "${labels[@]}"; then
95             echo "INFO: skip repeat label $l from environment"
96         else
97             echo "INFO: add label $l from environment"
98             labels+=("$l")
99         fi
100     done
101 fi
102
103 # shellcheck disable=SC1090
104 source ~/lf-env.sh
105
106 lf-activate-venv yq
107
108 # show installed versions
109 python -m pip --version
110 python -m pip freeze
111
112 echo "INFO: label list has ${#labels[@]} entries:"
113 echo "INFO:" "${labels[@]}"
114
115 # check build-node label uses
116 count=0
117 errs=0
118 while IFS= read -r ; do
119     file="$REPLY"
120     echo "INFO: checking $file"
121     # includes job-template AND project entries
122     nodes=$(yq 'recurse | ."build-node"? | values' "$file" | sort -u | tr -d '"')
123     # nodes may be a yaml list; e.g., '[ foo, bar, baz ]'
124     for node in $nodes; do
125         node="${node//[\[\],]/}"
126         if [[ -n $node ]] && ! isValueInArray "$node" "${labels[@]}"; then
127             echo "ERROR: unknown build-node $node in $file"
128             errs=$((errs+1))
129         else
130             count=$((count+1))
131         fi
132     done
133 done < <(find "$jjbdir" -name '*.yaml')
134
135 echo "INFO: $count valid label(s), $errs invalid label(s)"
136 echo "---> jjb-verify-build-nodes.sh ends"
137 exit $errs