-
Notifications
You must be signed in to change notification settings - Fork 15
product-lifecycle: Add plc_lookup.py CLI, migrate to v2 API #13
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,3 +1,3 @@ | ||
| # Cluster Update skills | ||
|
|
||
| This directory contains skills which are designed to help agents with ClusterVersion activities such as preparing for cluster updates. | ||
| This directory contains skills which are designed to help agents with ClusterVersion activities such as preparing for cluster updates. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,165 +1,90 @@ | ||
| --- | ||
| 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. | ||
| allowed-tools: Bash(python3:*) | ||
| --- | ||
|
|
||
| # 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. | ||
| Query the Red Hat Product Life Cycle API (v2) to check support status, EOL | ||
|
Member
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. nit: this skill doesn't have to care that the tool queries the v2 API, so we can probably drop the change to this line. One less place that will need bumping if we eventually pivot the tool to a v3 API or whatever. |
||
| dates, and OpenShift compatibility for Red Hat products and layered operators. | ||
|
|
||
| ## API Overview | ||
| ## CLI Tool | ||
|
|
||
| - **Base URL**: `https://access.redhat.com/product-life-cycles/api/v1/products` | ||
| - **Authentication**: None required — the API is public. | ||
| - **Query parameter**: `?name=<substring>` — case-insensitive substring match on product name. | ||
| - **Response**: `{ "data": [ { product }, ... ] }` — array of matching products. | ||
|
|
||
| ## Quick Start | ||
| All queries go through `product-lifecycle/scripts/plc_lookup.py` — a standalone Python 3 script | ||
| with no dependencies beyond stdlib. Run with `-h` for full usage: | ||
|
|
||
| ```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" | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| python3 product-lifecycle/scripts/plc_lookup.py -h | ||
|
Member
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. can't we drop |
||
| ``` | ||
|
|
||
| For full field descriptions, type enumerations, and phase name details, see `references/api-details.md`. | ||
| ### Commands | ||
|
|
||
| ## Common Queries | ||
| #### `products` — Query products by name | ||
|
|
||
| ### Check support status for a specific product version | ||
| Maps directly to `GET /v2/products?name=<name>`. | ||
|
Member
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. Internal tool detail, right? I expect dropping this line would save the AI agent a few tokens parsing the skill, and not impact its ability to use the tool at all. And I expect dropping this line will save us the effort of having to remember to bump this line if the tool behavior changes in the future. |
||
|
|
||
| ```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"))")' | ||
| ``` | ||
| # Look up a product | ||
| python3 product-lifecycle/scripts/plc_lookup.py products "logging for Red Hat OpenShift" | ||
|
|
||
| ### Check if a product version is compatible with a target OCP version | ||
| # With OCP compatibility check | ||
| python3 product-lifecycle/scripts/plc_lookup.py products "logging for Red Hat OpenShift" --ocp 4.21 | ||
|
|
||
| ```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)"' | ||
| # Paginate broad queries | ||
| python3 product-lifecycle/scripts/plc_lookup.py products "OpenShift" --limit 5 | ||
| python3 product-lifecycle/scripts/plc_lookup.py products "OpenShift" --limit 5 --offset 5 | ||
| ``` | ||
|
|
||
| ### Get EOL dates for OCP itself | ||
| Returns matching product versions with normalized support status, OCP | ||
| compatibility, and lifecycle phase dates. When `--ocp` is provided, adds | ||
| `ocp_target` and `ocp_compatible` (true/false/null) to each version entry. | ||
|
|
||
| ```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" | ||
| ))"' | ||
| ``` | ||
| Use `--limit` and `--offset` for broad queries that return many results. | ||
| The response includes `total`, `returned`, and `next_offset` (when more | ||
| results are available) so you can paginate through the full result set. | ||
|
|
||
| ### 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 | ||
| #### `olm-check` — Batch check OLM operators | ||
|
|
||
| ```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' | ||
| python3 product-lifecycle/scripts/plc_lookup.py olm-check --ocp 4.21 \ | ||
| --operators '[{"package":"cluster-logging"},{"package":"elasticsearch-operator"}]' | ||
| ``` | ||
|
|
||
| If the `?name=` search doesn't return the operator, try searching by `csv_display_name` | ||
| from the readiness data as a fallback. | ||
| Looks up each operator by its OLM `package` name. First searches the bulk | ||
| "OpenShift" product set, then falls back to individual queries. Reports | ||
| `lifecycle_unavailable` for operators not tracked in the API. | ||
|
|
||
| **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. | ||
| ### Output Format | ||
|
|
||
| ### Batch lookup for multiple OLM operators | ||
| All commands output JSON. Each product version entry includes: | ||
|
|
||
| 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. | ||
| | Field | Description | | ||
| |---|---| | ||
| | `status` | Normalized: `supported`, `maintenance`, `extended`, `end-of-maintenance`, `eol`, or `unknown` | | ||
| | `status_raw` | Original API value (e.g. `"Full Support"`, `"End of life"`) | | ||
| | `ocp_versions` | List of compatible OCP versions (empty for non-layered products) | | ||
| | `ocp_compatible` | `true`/`false`/`null` — only present when `--ocp` is used | | ||
| | `ga_date` | General availability date | | ||
| | `full_support_end` | End of full support phase | | ||
| | `maintenance_end` | End of maintenance support phase | | ||
|
|
||
| ```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)"' | ||
| ``` | ||
| Date fields are objects with `date` (ISO 8601 or descriptive string) and | ||
| `format` (`"date"` or `"string"`). | ||
|
|
||
| ## When to Use | ||
|
|
||
| - **Upgrade readiness**: check if installed operators are compatible with the | ||
| target OCP version before upgrading | ||
| - **EOL planning**: identify products approaching or past end of life | ||
| - **Support status**: determine current support phase for any Red Hat product | ||
| - **Cross-reference with update-advisor**: when `olm_operator_lifecycle` data | ||
| is present in readiness JSON, use `olm-check` to verify lifecycle status | ||
|
|
||
| ## 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. | ||
| - `ocp_versions` is only present on **layered product** versions, not on OCP itself. | ||
| - Not all operators have lifecycle entries — report "lifecycle data unavailable" | ||
| rather than treating missing data as an error. | ||
| - The `package` field in API responses maps to the OLM Subscription's | ||
| `spec.name` — use this for exact matching, not product name. | ||
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our previous discussion ended up deciding
allowed-toolswas too under-specified to be worth including. Doesn't look like the spec has evolved since then.