diff --git a/cluster-update/product-lifecycle/SKILL.md b/cluster-update/product-lifecycle/SKILL.md new file mode 100644 index 0000000..e41e6f2 --- /dev/null +++ b/cluster-update/product-lifecycle/SKILL.md @@ -0,0 +1,165 @@ +--- +name: product-lifecycle +description: Query Red Hat Product Life Cycle data for support phases, end-of-life dates, and OpenShift version compatibility. Use when evaluating whether installed operators or layered products are supported on a given OCP version, approaching end of life, or need upgrading before a cluster upgrade. Also use when the user asks about product support status, EOL dates, or lifecycle phases for any Red Hat product. +--- + +# Red Hat Product Life Cycle + +Query the Red Hat Product Life Cycle API to check support status, EOL dates, and OpenShift compatibility for Red Hat products and layered operators. + +## API Overview + +- **Base URL**: `https://access.redhat.com/product-life-cycles/api/v1/products` +- **Authentication**: None required — the API is public. +- **Query parameter**: `?name=` — case-insensitive substring match on product name. +- **Response**: `{ "data": [ { product }, ... ] }` — array of matching products. + +## Quick Start + +```bash +# Search for a product by name (substring match) +curl -s "https://access.redhat.com/product-life-cycles/api/v1/products?name=logging+for+Red+Hat+OpenShift" | jq . + +# List all products with "OpenShift" in the name +curl -s "https://access.redhat.com/product-life-cycles/api/v1/products?name=OpenShift" | jq -r '.data[].name' +``` + +## Response Structure + +Each product in `data[]` has: + +```json +{ + "name": "logging for Red Hat OpenShift", + "former_names": ["Red Hat OpenShift Logging"], + "all_phases": [{"name": "General availability", ...}, ...], + "versions": [ + { + "name": "6.5", + "type": "Full Support", + "openshift_compatibility": "4.19, 4.20, 4.21", + "phases": [ + { + "name": "General availability", + "end_date": "2026-04-01T00:00:00.000Z", + "date_format": "date" + }, + { + "name": "Full support", + "end_date": "Release of Logging 6.6 + 1 month", + "date_format": "string" + }, + { + "name": "Maintenance support", + "end_date": "Release of Logging 6.7", + "date_format": "string" + } + ] + } + ] +} +``` + +For full field descriptions, type enumerations, and phase name details, see `references/api-details.md`. + +## Common Queries + +### Check support status for a specific product version + +```bash +curl -s "https://access.redhat.com/product-life-cycles/api/v1/products?name=logging+for+Red+Hat+OpenShift" \ + | jq -r '.data[] | "\(.name)", (.versions[] | " \(.name) - \(.type) (OCP: \(.openshift_compatibility // "N/A"))")' +``` + +### Check if a product version is compatible with a target OCP version + +```bash +TARGET_OCP="4.21" +PRODUCT="logging+for+Red+Hat+OpenShift" + +curl -s "https://access.redhat.com/product-life-cycles/api/v1/products?name=$PRODUCT" \ + | jq -r --arg target "$TARGET_OCP" ' + .data[] | .name as $prod | + .versions[] | + .name as $ver | .type as $type | + (.openshift_compatibility // "" | split(", ")) as $compat | + (if ($compat | index($target)) then "COMPATIBLE" else "NOT COMPATIBLE" end) as $status | + "\($prod) \($ver) (\($type)) - \($status) with OCP \($target)"' +``` + +### Get EOL dates for OCP itself + +```bash +curl -s "https://access.redhat.com/product-life-cycles/api/v1/products?name=OpenShift+Container+Platform" \ + | jq -r '.data[0].versions[] | + "OCP \(.name) - \(.type) (maintenance ends: \( + [.phases[] | select(.name == "Maintenance support") | .end_date] | first // "N/A" + ))"' +``` + +### Cross-reference OLM operators with Product Life Cycle data + +Products that are OLM operators have a `package` field that maps directly to the +OLM Subscription's `spec.name`. This is an **exact match key** — more reliable than name +matching. The `is_operator` field confirms the product is OLM-managed. + +When the upgrade advisor readiness JSON includes `olm_operator_lifecycle` data: + +1. Extract the `package` name from each operator in readiness data +2. Search the Product Life Cycle API using that package name +3. Match by comparing `product.package` == operator's `package` +4. Check if the installed version's `openshift_compatibility` includes the target OCP version +5. Check the `type` field for support status + +```bash +# Look up Product Life Cycle data for an OLM operator by its package name +OLM_PACKAGE="cluster-logging" +TARGET_OCP="4.21" + +curl -s "https://access.redhat.com/product-life-cycles/api/v1/products?name=logging" \ + | jq -r --arg pkg "$OLM_PACKAGE" --arg target "$TARGET_OCP" ' + [.data[] | select(.package == $pkg)] | + if length == 0 then "No Product Life Cycle entry with package=\($pkg)" + else .[0] | + "\(.name) (package: \(.package))", + (.versions[] | + .name as $ver | .type as $type | + (.openshift_compatibility // "" | split(", ")) as $compat | + (if ($compat | index($target)) then "YES" else "NO" end) as $ok | + " \($ver) - \($type) - OCP \($target) compatible: \($ok)") + end' +``` + +If the `?name=` search doesn't return the operator, try searching by `csv_display_name` +from the readiness data as a fallback. + +**Not all operators have Product Life Cycle entries.** If a search returns no results, that's expected — +it means the product isn't tracked in the Product Life Cycle API. Report this as "lifecycle data unavailable" +rather than an error. + +### Batch lookup for multiple OLM operators + +When cross-referencing several operators, avoid N+1 API calls. Fetch `?name=OpenShift` +once (~14 products covering most Red Hat layered operators), then make individual calls +only for operators not found in that initial batch. + +```bash +TARGET_OCP="4.21" + +# Single call covers most Red Hat operator products +curl -s "https://access.redhat.com/product-life-cycles/api/v1/products?name=OpenShift" \ + | jq -r --arg target "$TARGET_OCP" ' + .data[] | select(.is_operator) | + (.package // "") as $pkg | .name as $prod | + .versions[] | + .name as $ver | .type as $type | + (.openshift_compatibility // "" | split(", ")) as $compat | + (if ($compat | index($target)) then "YES" else "NO" end) as $ok | + "\($pkg): \($prod) \($ver) (\($type)) - OCP \($target): \($ok)"' +``` + +## Important + +- **Always use `?name=`** to filter — never fetch the unfiltered `/products` endpoint. +- `openshift_compatibility` is only present on **layered product** versions, not on OCP itself. +- When cross-referencing with OLM data, a missing Product Life Cycle entry is normal — report "lifecycle data unavailable" and move on. diff --git a/cluster-update/product-lifecycle/references/api-details.md b/cluster-update/product-lifecycle/references/api-details.md new file mode 100644 index 0000000..eb98f8c --- /dev/null +++ b/cluster-update/product-lifecycle/references/api-details.md @@ -0,0 +1,82 @@ +# Product Life Cycle API Reference + +## Endpoint + +``` +GET https://access.redhat.com/product-life-cycles/api/v1/products?name= +``` + +No authentication required. The `name` parameter is a case-insensitive substring match. + +## Product Object + +| Field | Type | Description | +|---|---|---| +| `name` | string | Current product name | +| `former_names` | string[] | Previous product names (useful for search fallback) | +| `is_operator` | bool | Whether this product is an OLM-managed operator | +| `is_layered_product` | bool | Whether this product is layered on OpenShift | +| `is_retired` | bool | Whether the entire product has been retired | +| `package` | string\|null | **OLM package name** — maps to Subscription `spec.name` | +| `versions` | object[] | Per-version lifecycle data | + +### The `package` field + +The `package` field is the OLM package name and provides an **exact match key** to correlate +Product Life Cycle products with OLM Subscriptions. This is more reliable than name matching. + +Mapping: `product.package` == `subscription.spec.name` + +## Version Object + +| Field | Type | Description | +|---|---|---| +| `name` | string | Version number (e.g., `"6.5"`, `"4.21"`) | +| `type` | string | **Current support status** — see table below | +| `openshift_compatibility` | string\|null | Comma-separated OCP versions (e.g., `"4.19, 4.20, 4.21"`) — only on layered products | +| `phases` | object[] | Lifecycle phase details with dates | + +### Support status (`type`) + +| Value | Meaning | +|---|---| +| `"Full Support"` | Active development, bug fixes, security patches | +| `"Maintenance Support"` | Critical/security fixes only, no new features | +| `"End of Maintenance"` | Maintenance support has ended; no EUS/ELS applies to this version | +| `"Extended Support"` | Past maintenance, currently in a paid Extended Life Cycle Support (ELS) phase | +| `"End of life"` | No fixes, no support — must upgrade | +| `""` (empty) | Status not yet determined (e.g., version has incomplete lifecycle data) | + +## Phase Object + +| Field | Type | Description | +|---|---|---| +| `name` | string | Phase name (e.g., `"General availability"`, `"Full support"`, `"Maintenance support"`) | +| `start_date` | string | Phase start — ISO 8601 date or descriptive string | +| `end_date` | string | Phase end — ISO 8601 date or descriptive string | +| `date_format` | string | `"date"` (ISO 8601) or `"string"` (relative/TBD) | + +Phase names vary by product. Common categories: + +| Category | Phase names | Meaning | +|---|---|---| +| Release | `General availability` | When the version was first released | +| Active support | `Full support` | Active development, bug fixes, security patches | +| Reduced support | `Maintenance support`, `Maintenance Support 1`, `Maintenance support 2` | Critical/security fixes only | +| Extended support | `Extended update support`, `Extended update support Term 2`, `Extended update support Term 3` | EUS — available for select versions, may require add-on purchase | +| Extended lifecycle | `Extended life phase`, `Extended life cycle support (ELS) 1`/`2`, `Extended life cycle support (ELS) add-on`/`Term 2 add-on`/`Term 3 add-on` | Paid extended support beyond normal EOL | +| End | `End of Life`, `Retired` | No further updates or support | +| Other | `Migration support`, `Third-party certification period` | Product-specific transitional phases | + +Phase names are not standardized across products. Use the `start_date` and `end_date` fields +to determine whether a phase is current, rather than relying on the phase name alone. + +For detailed lifecycle policy definitions, see the [Red Hat product lifecycle policies](https://access.redhat.com/support/policy/updates/openshift#dates). + +## Search Tips + +1. **Be specific with `?name=`** — `"logging+for+Red+Hat+OpenShift"` is better than `"logging"` +2. **Check `former_names`** — products may appear under a previous name in the `former_names` field +3. **Use `is_operator: true`** to filter for OLM operators in results +4. **Use `package` for OLM correlation** — more reliable than name matching +5. **Never omit `?name=`** — the unfiltered response is very large diff --git a/cluster-update/update-advisor/SKILL.md b/cluster-update/update-advisor/SKILL.md index 7e82c3c..2c8a382 100644 --- a/cluster-update/update-advisor/SKILL.md +++ b/cluster-update/update-advisor/SKILL.md @@ -1,6 +1,162 @@ --- -name: openshift-cluster-update-advisor -description: Assess OpenShift cluster update readiness and risk. Use when evaluating whether a cluster is safe to update, when an update is available, or when the user asks about update risks, prerequisites, blockers, or best practices. +name: cluster-update-advisor +description: Assess OpenShift cluster update (upgrade) readiness and risk. Use when evaluating whether a cluster is safe to update, when an update is available, or when the user asks about update risks, prerequisites, blockers, or best practices. --- -FIXME: just a draft at the moment, fill in with an actual skill later. +# Cluster Update Advisor + +## 1. Purpose + +Assess cluster update readiness and produce a structured risk report with +actionable prerequisites, blockers, and recommendations. + +The proposal request includes pre-collected cluster readiness data (JSON) +gathered by the Cluster Version Operator. Analyze this data, classify findings, +and produce a decision with evidence. Do not re-collect cluster data — it is +already in the request. + +## 2. Inputs + +The proposal request contains: +- Current and target version metadata +- Channel and update path information +- **Cluster readiness JSON** — cluster health checks with context relevant to preparing for the update + +The readiness JSON is embedded in the request between ` ```json ` markers under +the "Cluster Readiness Data" heading. Parse it to begin analysis. + +**Readiness JSON structure:** + +```json +{ + "current_version": "4.21.5", + "target_version": "4.21.8", + "checks": { + "cluster_conditions": { "_status": "ok", "summary": {...}, ... }, + "operator_health": { "_status": "ok", "summary": {...}, ... }, + "api_deprecations": { "_status": "ok", "summary": {...}, ... }, + "node_capacity": { "_status": "ok", "summary": {...}, ... }, + "pdb_drain": { "_status": "ok", "summary": {...}, ... }, + "etcd_health": { "_status": "ok", "summary": {...}, ... }, + "network": { "_status": "ok", "summary": {...}, ... }, + "crd_compat": { "_status": "ok", "summary": {...}, ... }, + "olm_operator_lifecycle": { "_status": "ok", "summary": {...}, ... } + } +} +``` + +Each check contains `_status` (`ok` or `error`) and check-specific data +with a `summary` section for quick parsing. + +## 3. Decision Policy + +### 3.1 Workflow + +``` +Step 1: Parse readiness data + Extract the JSON from the proposal request. Count checks + with _status "ok" vs "error" for completeness. + │ +Step 2: Verify data completeness + Any check with _status "error" represents a gap in + visibility. Note incomplete areas — they reduce confidence. + │ +Step 3: Evaluate findings + If the system prompt includes organization-specific policy + (thresholds, scheduling preferences, risk tolerance), apply + those constraints. Otherwise use sensible defaults. + Walk through each check's summary and detail data: + - Compare numeric thresholds (node headroom, etcd backup age) + - Evaluate conditional update risks against cluster state + - Identify compounding risks (e.g., paused MCP + cert expiry) + - Estimate update duration (~10 min/node) + │ +Step 4: Classify and decide + Assign each finding a severity per the classification table + in section 4.2. Then determine the overall assessment: + recommend — all checks pass within acceptable thresholds + caution — findings exist but manageable with prerequisites + block — findings must be resolved before update + escalate — insufficient data for confident assessment + │ +Step 5: Investigate (as needed) + Use prometheus, platform-docs, redhat-support, or + product-lifecycle skills for deeper analysis. + │ + ▼ + Produce structured risk report +``` + +### 3.2 Blocker Classification + +| Severity | Criteria | Action | +|---|---|---| +| **Blocker** | Update will fail or cause data loss | `decision: block` | +| **Warning** | Update may cause disruption | `decision: caution` | +| **Info** | Noteworthy but non-blocking | Include for awareness | + +Classification rules: + +| Check | Blocker if... | Warning if... | +|---|---|---| +| Cluster conditions | Upgradeable=False (non-z-stream) | Update already in progress | +| API deprecations | Workloads use APIs **removed** in target | Workloads use **deprecated** APIs | +| Operator health | Any operator has Upgradeable=False | Any operator is Degraded=True | +| MachineConfigPool | Any MCP paused or degraded | MCP updating or not all machines ready | +| Node capacity | Headroom < 20% | Headroom < 40% | +| PDB config | PDB blocks ALL replicas from draining | PDB has maxUnavailable: 0 | +| etcd health | Any member unhealthy | No recent backup (within 24h) | +| Network plugin | SDN in use and target requires OVN (4.17+) | Using deprecated SDN (< 4.17) | +| CRD compatibility | Stored version not served; operator maxOpenShiftVersion < target | Deprecated versions still served | +| OLM operator lifecycle | Installed operator incompatible with target OCP; operator product EOL | Operator has pending update; operator product in Maintenance Support | + +### 3.3 Decision Matrix + +| Blockers | Warnings | Decision | +|---|---|---| +| 0 | 0 | `recommend` | +| 0 | 1+ | `caution` | +| 1+ | any | `block` | +| Unable to assess | any | `escalate` | + +### 3.4 Output + +The output schema is enforced by the OlsAgent CR's `outputSchema` field — +the operator handles structured output compliance via the LLM API. + +## 4. Failure Modes — What NOT to Do + +1. **Never recommend updating without analyzing the readiness data.** The JSON + in the request is the source of truth. + +2. **Never dismiss conditional update risks.** If the update path is conditional, + evaluate each risk against the cluster. + +3. **Never skip the API deprecation check.** Workloads using removed APIs will + break after the update. + +4. **Never assume etcd is healthy.** Always check member health in the readiness data. + +5. **Never fabricate Jira issue keys, KB article IDs, or CVE numbers.** Use the + `redhat-support` skill to get real data. + +6. **Never recommend skipping an update version** unless the readiness data shows + that path exists. + +7. **Never recommend force-updating.** If the standard path is blocked, report it. + +## 5. Using Other Skills + +- **`openshift-docs`** — Read official OpenShift update docs for version-specific + procedures and breaking changes. + +- **`prometheus`** — Query cluster metrics for trend analysis (etcd latency, + CPU headroom, firing alerts). + +- **`jira`** — Search Red Hat Jira for bugs and known issues affecting the target version. + +- **`product-lifecycle`** — Query Red Hat Product Life Cycle API to check + support status and OCP compatibility for installed operators. Use the operator's + `package` name from OLM readiness data to look up entries via the `package` + field (exact match). Flag operators whose product version is End of life or whose + `openshift_compatibility` does not include the target OCP version.