This is an automated email from the ASF dual-hosted git repository.
apupier pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 35da3d2b42a9 CAMEL-24290: Fix alt-arch occupier multi-node detection
and add diagnostic logs
35da3d2b42a9 is described below
commit 35da3d2b42a9cf03ebf3c7e8ae796d9f58f22fe3
Author: Aurélien Pupier <[email protected]>
AuthorDate: Thu Nov 12 12:06:59 2026 +0100
CAMEL-24290: Fix alt-arch occupier multi-node detection and add diagnostic
logs
- Remove artificial max_nodes cap which prevented inspecting all registered
cloud nodes
- Replace String.eachLine with split('\n') loop to prevent CPS closure
truncation
- Use pipe delimiter '|' with flush=True to avoid tab escaping ambiguities
- Add structured diagnostic logging to stderr for every evaluated node and
running job
Co-authored-by: IBM Bob 2.2.1
Signed-off-by: Aurélien Pupier <[email protected]>
---
etc/scripts/jenkins-alt-arch-nodes.groovy | 77 ++++++++++++++++++-------------
1 file changed, 46 insertions(+), 31 deletions(-)
diff --git a/etc/scripts/jenkins-alt-arch-nodes.groovy
b/etc/scripts/jenkins-alt-arch-nodes.groovy
index 646bdd26e36e..50787a87f5fb 100644
--- a/etc/scripts/jenkins-alt-arch-nodes.groovy
+++ b/etc/scripts/jenkins-alt-arch-nodes.groovy
@@ -25,10 +25,10 @@
* The helpers below:
* 1. query ${JENKINS_URL}/computer/api/json and parse it via Python 3 in sh
(to avoid Jenkins sandbox
* approval issues with Groovy JSON parsers),
- * 2. find the online agents of a platform that are running a Camel Core job
and still have idle executors,
- * 3. (only while the platform has not reached its maximum number of agents)
build one parallel branch
- * per idle executor that holds the executor with a 10 minutes sleep, so
that Jenkins sees no free
- * capacity for the label and provisions a new agent.
+ * 2. inspect every registered agent, logging its status, active jobs, and
idle executors to stderr,
+ * 3. find the online agents of a platform that are running a Camel Core job
and still have idle executors,
+ * 4. build one parallel branch per idle executor that holds the executor
with a 10 minutes sleep, so that
+ * Jenkins sees no free capacity for the label and provisions a new agent.
*
* Usage: loaded by Jenkinsfile.occupier, which is triggered by the Camel
Jenkinsfiles with wait: false.
* It must NOT be run inside a job using the 'camel' throttle, as the occupier
branches allocate the
@@ -68,55 +68,70 @@ List<Map> fetchAndPlanOccupiers(String jenkinsUrl,
Collection<String> platforms)
curl --fail --silent --show-error --globoff --max-time 30
'${base}computer/api/json?tree=${ALT_ARCH_COMPUTER_TREE}' | python3 -c '
import json, sys
-max_nodes = {"ppc64le": 3, "s390x": 6}
target_platforms = set(p.strip() for p in sys.argv[1].split(",") if p.strip())
try:
data = json.load(sys.stdin)
-except Exception:
+except Exception as e:
+ sys.stderr.write(f"Failed to parse Jenkins /computer/api/json: {e}\\n")
+ sys.stderr.flush()
sys.exit(0)
computers = data.get("computer", [])
if not isinstance(computers, list):
sys.exit(0)
-for platform in target_platforms:
- max_count = max_nodes.get(platform)
- if max_count is None:
- continue
-
- online = [
+for platform in sorted(target_platforms):
+ matching = [
c for c in computers
- if not c.get("offline") and any(lbl.get("name") == platform for lbl in
(c.get("assignedLabels") or []))
+ if any(lbl.get("name") == platform for lbl in (c.get("assignedLabels")
or []))
]
- if len(online) >= max_count:
- continue
+ sys.stderr.write(f"--> [Alt-Arch Inspector] Evaluating platform
\\"{platform}\\": found {len(matching)} registered node(s)\\n")
- for c in online:
+ for c in matching:
+ node_name = c.get("displayName", "unknown")
+ is_offline = c.get("offline", False)
executors = c.get("executors") or []
idle_count = sum(1 for e in executors if e.get("idle"))
+ active_jobs = []
runs_camel_core = False
for e in executors:
- executable = e.get("currentExecutable") or {}
- url = (executable.get("url") or "").lower()
- if "/job/camel/" in url or "/job/camel%20" in url:
- if not any(excl in url for excl in ["occupier", "kamelet",
"quarkus", "spring-boot", "karaf"]):
- runs_camel_core = True
- break
-
- if idle_count > 0 and runs_camel_core:
- node_name = c.get("displayName", "")
- if node_name:
- print(f"{platform}\\t{node_name}\\t{idle_count}")
+ if not e.get("idle"):
+ executable = e.get("currentExecutable") or {}
+ url = executable.get("url") or "unknown"
+ active_jobs.append(url)
+ url_lower = url.lower()
+ if "/job/camel/" in url_lower or "/job/camel%20" in url_lower:
+ if not any(excl in url_lower for excl in ["occupier",
"kamelet", "quarkus", "spring-boot", "karaf"]):
+ runs_camel_core = True
+
+ status_str = "offline" if is_offline else f"online ({len(executors)}
executors: {idle_count} idle, {len(active_jobs)} active)"
+ sys.stderr.write(f" * Node \\"{node_name}\\": {status_str}\\n")
+ for job_url in active_jobs:
+ sys.stderr.write(f" - Running job: {job_url}\\n")
+
+ if not is_offline and idle_count > 0 and runs_camel_core:
+ sys.stderr.write(f" => TARGET FOR OCCUPIER: {idle_count}
idle executor(s) on busy Camel Core node\\n")
+ print(f"{platform}|{node_name}|{idle_count}", flush=True)
+ elif not is_offline and idle_count > 0 and not runs_camel_core:
+ sys.stderr.write(f" => Skipped: has idle executor(s) but
not running a throttled Camel Core job\\n")
+ elif not is_offline and idle_count == 0:
+ sys.stderr.write(f" => Skipped: 0 idle executors (all
busy)\\n")
+
+sys.stderr.flush()
' "${platformsArg}"
"""
String output = sh(returnStdout: true, script: script).trim()
if (output) {
- output.eachLine { line ->
- def parts = line.split('\t')
- if (parts.length == 3) {
- plan << [platform: parts[0], node: parts[1],
idleExecutors: parts[2] as int]
+ String[] lines = output.split('\n')
+ for (String line : lines) {
+ line = line.trim()
+ if (line) {
+ def parts = line.split('\\|')
+ if (parts.size() == 3) {
+ plan << [platform: parts[0], node: parts[1],
idleExecutors: parts[2] as int]
+ }
}
}
}