-
Notifications
You must be signed in to change notification settings - Fork 14
USHIFT-7381: feat(microshift-ci): add --local mode to PCP dashboard generator #233
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,15 @@ | ||
| #!/usr/bin/bash | ||
| # Generate an interactive PCP performance dashboard from a Prow job URL. | ||
| # Generate an interactive PCP performance dashboard. | ||
| # | ||
| # Downloads artifacts from GCS, extracts per-VM PCP archives, and produces | ||
| # an interactive HTML dashboard. | ||
| # Two modes: | ||
| # --url <prow-url> Download artifacts from GCS (default) | ||
| # --local <path> Use a local scenario-info/ directory | ||
| # | ||
| # Usage: generate-dashboard.sh --url <prow-url> [--parallel N] [--timezone TZ] | ||
| # Usage: | ||
| # generate-dashboard.sh --url <prow-url> [--parallel N] [--timezone TZ] | ||
| # generate-dashboard.sh --local <path> [--build-id ID] [--output FILE] [--title TITLE] [--timezone TZ] | ||
| # | ||
| # Prerequisites: gsutil, python3, and one of: | ||
| # Prerequisites: python3, and one of: | ||
| # - pcp-export-pcp2json (native) | ||
| # - podman (container fallback) | ||
|
|
||
|
|
@@ -16,15 +19,26 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |
| SHARED_SCRIPTS="$(cd "${SCRIPT_DIR}/../../../shared/scripts" && pwd)" | ||
|
|
||
| URL="" | ||
| LOCAL_PATH="" | ||
| BUILD_ID="" | ||
| OUTPUT="" | ||
| TITLE="" | ||
| PARALLEL=6 | ||
| TIMEZONE="UTC" | ||
| PCP2JSON_MODE="" # "native" or "container" | ||
| CONTAINER_RT="" # "podman" | ||
| CONTAINER_IMAGE="pcp2json-tool" | ||
|
|
||
| usage() { | ||
| echo "Usage: ${0} --url <prow-url> [--parallel N] [--timezone TZ]" >&2 | ||
| echo " --url URL : Prow job URL (required)" >&2 | ||
| echo "Usage:" >&2 | ||
| echo " ${0} --url <prow-url> [--parallel N] [--timezone TZ]" >&2 | ||
| echo " ${0} --local <path> [--build-id ID] [--output FILE] [--title TITLE] [--timezone TZ]" >&2 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's make the usage of the two modes as consistent as possible. |
||
| echo "" >&2 | ||
| echo " --url URL : Prow job URL" >&2 | ||
| echo " --local PATH : path to scenario-info/ directory" >&2 | ||
| echo " --build-id ID : build label (default: local)" >&2 | ||
| echo " --output FILE : output HTML file path" >&2 | ||
| echo " --title TITLE : HTML <title> for the dashboard" >&2 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If possible, let's remove |
||
| echo " --parallel N : number of parallel extraction jobs (default: 6)" >&2 | ||
| echo " --timezone TZ : IANA timezone for timestamps (default: UTC)" >&2 | ||
| exit 1 | ||
|
|
@@ -35,6 +49,19 @@ while [[ $# -gt 0 ]]; do | |
| --url) | ||
| [[ $# -lt 2 ]] && { echo "Error: --url requires a URL" >&2; usage; } | ||
| URL="$2"; shift 2 ;; | ||
| --local) | ||
| [[ $# -lt 2 ]] && { echo "Error: --local requires a path" >&2; usage; } | ||
| LOCAL_PATH="$2"; shift 2 ;; | ||
| --build-id) | ||
| [[ $# -lt 2 ]] && { echo "Error: --build-id requires a value" >&2; usage; } | ||
| [[ "$2" =~ ^[a-zA-Z0-9._-]+$ ]] || { echo "Error: --build-id contains invalid characters" >&2; usage; } | ||
| BUILD_ID="$2"; shift 2 ;; | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| --output) | ||
| [[ $# -lt 2 ]] && { echo "Error: --output requires a file path" >&2; usage; } | ||
| OUTPUT="$2"; shift 2 ;; | ||
| --title) | ||
| [[ $# -lt 2 ]] && { echo "Error: --title requires a value" >&2; usage; } | ||
| TITLE="$2"; shift 2 ;; | ||
| --parallel) | ||
| [[ $# -lt 2 ]] && { echo "Error: --parallel requires a number" >&2; usage; } | ||
| [[ "$2" =~ ^[1-9][0-9]*$ ]] || { echo "Error: --parallel must be a positive integer" >&2; usage; } | ||
|
|
@@ -47,20 +74,34 @@ while [[ $# -gt 0 ]]; do | |
| esac | ||
| done | ||
|
|
||
| if [[ -z "${URL}" ]]; then | ||
| echo "Error: --url is required" >&2 | ||
| if [[ -n "${URL}" && -n "${LOCAL_PATH}" ]]; then | ||
| echo "Error: --url and --local are mutually exclusive" >&2 | ||
| usage | ||
| fi | ||
|
|
||
| if [[ -z "${URL}" && -z "${LOCAL_PATH}" ]]; then | ||
| echo "Error: --url or --local is required" >&2 | ||
| usage | ||
| fi | ||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # URL parsing and artifact download (delegates to shared download-jobs.sh) | ||
| # Set up WORKDIR depending on mode | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
| # Extract build ID (last path segment of the URL) to compute workdir | ||
| BUILD_ID=$(basename "${URL%/}") | ||
| WORKDIR="/tmp/microshift-job-pcp-dashboard.${BUILD_ID}" | ||
|
|
||
| bash "${SHARED_SCRIPTS}/download-jobs.sh" --workdir "${WORKDIR}" --url "${URL}" | ||
| if [[ -n "${LOCAL_PATH}" ]]; then | ||
| # Local mode: symlink the local scenario-info into a temp workdir | ||
| LOCAL_PATH="$(cd "${LOCAL_PATH}" && pwd)" | ||
| BUILD_ID="${BUILD_ID:-local}" | ||
| WORKDIR=$(mktemp -d "/tmp/microshift-pcp-local.XXXXXX") | ||
| mkdir -p "${WORKDIR}/artifacts/${BUILD_ID}" | ||
| ln -s "${LOCAL_PATH}" "${WORKDIR}/artifacts/${BUILD_ID}/scenario-info" | ||
| echo "Local mode: ${LOCAL_PATH} -> ${WORKDIR}/artifacts/${BUILD_ID}/scenario-info" >&2 | ||
| else | ||
| # URL mode: download artifacts via shared script | ||
| BUILD_ID=$(basename "${URL%/}") | ||
| WORKDIR="/tmp/microshift-job-pcp-dashboard.${BUILD_ID}" | ||
| bash "${SHARED_SCRIPTS}/download-jobs.sh" --workdir "${WORKDIR}" --url "${URL}" | ||
| fi | ||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # pcp2json detection: native or container fallback | ||
|
|
@@ -121,7 +162,7 @@ run_pcp2json() { | |
| # --------------------------------------------------------------------------- | ||
|
|
||
| find_pcp_tarballs() { | ||
| find "${WORKDIR}/artifacts" -name "pcp-archives.tar" -path "*/vms/*/pcp/*" \ | ||
| find -L "${WORKDIR}/artifacts" -name "pcp-archives.tar" -path "*/vms/*/pcp/*" \ | ||
| 2>/dev/null | sort | ||
| } | ||
|
|
||
|
|
@@ -223,7 +264,7 @@ process_tarball() { | |
| # --------------------------------------------------------------------------- | ||
|
|
||
| find_hypervisor_pcp_dirs() { | ||
| find "${WORKDIR}/artifacts" -name "Latest" -path "*pmlogs*" \ | ||
| find -L "${WORKDIR}/artifacts" -name "Latest" -path "*pmlogs*" \ | ||
| -exec dirname {} \; 2>/dev/null | sort | ||
| } | ||
|
|
||
|
|
@@ -327,10 +368,13 @@ python3 "${SCRIPT_DIR}/extract_scenarios.py" --workdir "${WORKDIR}" | |
|
|
||
| # Generate the HTML dashboard | ||
| echo "Generating HTML dashboard..." >&2 | ||
| python3 "${SCRIPT_DIR}/create-pcp-dashboard.py" \ | ||
| --workdir "${WORKDIR}" --timezone "${TIMEZONE}" | ||
| dashboard_args=(--workdir "${WORKDIR}" --timezone "${TIMEZONE}") | ||
| [[ -n "${OUTPUT}" ]] && dashboard_args+=(--output "${OUTPUT}") | ||
| [[ -n "${TITLE}" ]] && dashboard_args+=(--title "${TITLE}") | ||
|
|
||
| python3 "${SCRIPT_DIR}/create-pcp-dashboard.py" "${dashboard_args[@]}" | ||
|
|
||
| output="${WORKDIR}/pcp-dashboard.html" | ||
| output="${OUTPUT:-${WORKDIR}/pcp-dashboard.html}" | ||
| if [[ -f "${output}" ]]; then | ||
| echo "Dashboard: ${output}" >&2 | ||
| else | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.