Add doc for jjb-verify build-node label check 21/63621/1
authorLott, Christopher (cl778h) <cl778h@att.com>
Tue, 7 Apr 2020 13:11:26 +0000 (09:11 -0400)
committerLott, Christopher (cl778h) <cl778h@att.com>
Tue, 7 Apr 2020 13:43:57 +0000 (09:43 -0400)
Document the jjb-verify feature that checks build-node labels named
in JJB YAML files against nodes in cloud config files.
Change the feature's JJB configuration variables to share a prefix.
Improve the shell script to be robust to errors such as a suffix of
".cfg" or an external label of "" (just two double quotes).

Change-Id: I8beb5669531fe2b7f59a9bcf3706b27ede3965b9
Issue-ID: RELENG-2828
Signed-off-by: Lott, Christopher (cl778h) <cl778h@att.com>
docs/jjb/lf-ci-jobs.rst
jjb/lf-ci-jobs.yaml
releasenotes/notes/jjb-verify-build-nodes-doc-cdb47bfa721775923.yaml [new file with mode: 0644]
shell/jjb-verify-build-nodes.sh

index 65568e2..0323bd2 100644 (file)
@@ -443,7 +443,8 @@ Runs `jenkins-jobs update` to update production job configuration
 JJB Verify
 ----------
 
-Runs `jenkins-jobs test` to validate JJB syntax
+Runs `jenkins-jobs test` to validate JJB syntax. Optionally validates
+build-node labels used in templates and job definitions.
 
 :Template Names:
     - {project-name}-jjb-verify
@@ -464,6 +465,10 @@ Runs `jenkins-jobs test` to validate JJB syntax
     :build-concurrent: Whether or not to allow this job to run multiple jobs
         simultaneously. (default: true)
     :build-days-to-keep: Days to keep build logs in Jenkins. (default: 7)
+    :build-node-label-check: Whether to check build-node labels in jobs
+        against node names in cloud config files (default: false)
+    :build-node-label-list: Space-separated list of external build-node
+        labels not present in cloud config files (default: "")
     :build-timeout: Timeout in minutes before aborting build. (default: 10)
     :git-url: URL clone project from. (default: $GIT_URL/$PROJECT)
     :jjb-cache: JJB cache location. (default: $HOME/.cache/jenkins_jobs)
index 9ecd38f..635bc67 100644 (file)
     ######################
 
     build-concurrent: true
-    check-build-node-labels: false
-    external-build-node-labels: ""
+    build-node-label-check: false
+    build-node-label-list: ""
 
     gerrit_verify_triggers:
       - patchset-created-event:
           - ../shell/jjb-verify-job.sh
       - conditional-step:
           condition-kind: boolean-expression
-          condition-expression: "{check-build-node-labels}"
+          condition-expression: "{build-node-label-check}"
           on-evaluation-failure: dont-run
           steps:
             - inject:
-                properties-content: EXTERNAL_LABELS="{external-build-node-labels}"
+                properties-content: EXTERNAL_LABELS="{build-node-label-list}"
             - shell: !include-raw-escape:
                 - ../shell/jjb-verify-build-nodes.sh
       - lf-infra-gpg-verify-git-signature
diff --git a/releasenotes/notes/jjb-verify-build-nodes-doc-cdb47bfa721775923.yaml b/releasenotes/notes/jjb-verify-build-nodes-doc-cdb47bfa721775923.yaml
new file mode 100644 (file)
index 0000000..69d13ec
--- /dev/null
@@ -0,0 +1,8 @@
+---
+fixes:
+  - |
+    Document the jjb-verify feature that checks build-node labels named
+    in JJB YAML files against nodes in cloud config files.
+    Change the feature's JJB configuration variables to share a prefix.
+    Improve the shell script to be robust to errors such as a suffix of
+    ".cfg" or an external label of "" (just two double quotes).
index 9483118..b4457e4 100644 (file)
@@ -17,14 +17,27 @@ echo "---> jjb-verify-build-nodes.sh"
 # Prereqs:
 # - Bash version 3+
 # - Python tool yq is installed; e.g., by python-tools-install.sh
-# - Working directory is a ci-management repo with subdirs
-#   jenkins-config/clouds/openstack and jjb
+# - Working directory is a ci-management repo with subdirs named below
 # Environment variable:
 # - EXTERNAL_LABELS - a space-separated list of build-node labels
 #   for nodes not managed in the jenkins-config area (optional)
 
 set -eu -o pipefail
 
+# expected suffix on build-node config files
+suffix=".cfg"
+# subdir with cloud config files
+configdir="jenkins-config/clouds/openstack"
+# subdir with JJB yaml files
+jjbdir="jjb"
+
+# function to test if the argument is empty,
+# is two double quotes, or has unwanted suffix
+isBadLabel () {
+  local label="$1"
+  [[ -z "$label" ]] || [[ $label = "\"\"" ]] || [[ $label = *"$suffix" ]]
+}
+
 # function to search an array for a value
 # $1 is value
 # $2 is array, passed via ${array[@]}
@@ -35,54 +48,79 @@ isValueInArray () {
   return 1
 }
 
-# discover build node labels
+# check prereqs
+if [ ! -d "$configdir" ] || [ ! -d "$jjbdir" ]; then
+    echo "ERROR: failed to find subdirs $configdir and $jjbdir"
+    exit 1
+fi
+
+# find cloud config node names by recursive descent
 declare -a labels=()
-suffix=".cfg"
 while IFS= read -r ; do
     file="$REPLY"
     # valid files contain IMAGE_NAME; skip the cloud config file
     if grep -q "IMAGE_NAME" "$file" && ! grep -q "CLOUD_CREDENTIAL_ID" "$file"; then
-        # file name is a valid label, without path prefix and suffix
+        # file name without prefix or suffix is a valid label
         name=$(basename -s "$suffix" "$file")
+        echo "INFO: add label $name for $file"
         labels+=("$name")
-        # a file can define custom labels
+        # add custom labels from file
         if custom=$(grep "LABELS=" "$file" | cut -d= -f2); then
             # TODO: confirm separator for multiple labels
             read -r -a customarray <<< "$custom"
-            for c in "${customarray[@]}"; do
-                if ! isValueInArray "$c" "${labels[@]}"; then
-                    labels+=("$c")
+            for l in "${customarray[@]}"; do
+                if isBadLabel "$l"; then
+                    echo "WARN: skip custom label $l from $file"
+                elif isValueInArray "$l" "${labels[@]}"; then
+                    echo "INFO: skip repeat custom label $l from $file"
+                else
+                    echo "INFO: add custom label $l from $file"
+                    labels+=("$l")
                 fi
             done
         fi
     fi
-done < <(find "jenkins-config/clouds/openstack" -name \*$suffix)
-echo "Found ${#labels[@]} configured label(s):"
-echo "${labels[@]}"
-declare -a externals=()
+done < <(find "$configdir" -name \*$suffix)
+
+# add external build-node labels
 if [[ -n ${EXTERNAL_LABELS:-} ]]; then
     read -r -a externals <<< "$EXTERNAL_LABELS"
-    echo "Received ${#externals[@]} external label(s):"
-    echo "${externals[@]}"
-    labels=("${externals[@]}" "${labels[@]}")
+    # defend against empty, quotes-only and repeated values
+    for l in "${externals[@]}"; do
+        if isBadLabel "$l"; then
+            echo "WARN: skip external label $l"
+        elif isValueInArray "$l" "${labels[@]}"; then
+            echo "INFO: skip repeat label $l from environment"
+        else
+            echo "INFO: add label $l from environment"
+            labels+=("$l")
+        fi
+    done
 fi
 
-# check build node label uses
+echo "INFO: label list has ${#labels[@]} entries:"
+echo "INFO:" "${labels[@]}"
+
+# check build-node label uses
+count=0
 errs=0
 while IFS= read -r ; do
     file="$REPLY"
-    echo "Checking $file"
-    # this includes job-templates which may be annoying
+    echo "INFO: checking $file"
+    # includes job-template AND project entries
     nodes=$(yq 'recurse | ."build-node"? | values' "$file" | sort -u | tr -d '"')
+    # nodes may be a yaml list; e.g., '[ foo, bar, baz ]'
     for node in $nodes; do
-        # may be a yaml list; e.g., '[ foo, bar, baz ]'
         node="${node//[\[\],]/}"
         if [[ -n $node ]] && ! isValueInArray "$node" "${labels[@]}"; then
-            echo "ERROR: file $file uses unknown build-node $node"
+            echo "ERROR: unknown build-node $node in $file"
             errs=$((errs+1))
+        else
+            count=$((count+1))
         fi
     done
-done < <(find "jjb" -name '*.yaml')
+done < <(find "$jjbdir" -name '*.yaml')
 
+echo "INFO: $count valid label(s), $errs invalid label(s)"
 echo "---> jjb-verify-build-nodes.sh ends"
 exit $errs