diff --git a/PLUGINS.md b/PLUGINS.md index 479778c..ae29d04 100644 --- a/PLUGINS.md +++ b/PLUGINS.md @@ -97,16 +97,19 @@ See [plugins/must-gather/README.md](plugins/must-gather/README.md) for detailed OLM (Operator Lifecycle Manager) plugin for operator management and debugging **Commands:** -- **`/olm:approve` ` [namespace] [--all]`** - Approve pending InstallPlans for operator installations and upgrades -- **`/olm:catalog` ` [arguments]`** - Manage catalog sources for discovering and installing operators +- **`/olm:approve` ` [namespace] [--all]`** - Approve pending InstallPlans for operator installations and upgrades (OLM v0 only) +- **`/olm:catalog` ` [args] [--version v0|v1]`** - Manage catalog sources (v0) or ClusterCatalogs (v1) - **`/olm:debug` ` [olm-version]`** - Debug OLM issues using must-gather logs and source code analysis -- **`/olm:diagnose` `[operator-name] [namespace] [--fix] [--cluster]`** - Diagnose and optionally fix common OLM and operator issues -- **`/olm:install` ` [namespace] [channel] [source] [--approval=Automatic|Manual]`** - Install a day-2 operator using Operator Lifecycle Manager -- **`/olm:list` `[namespace] [--all-namespaces]`** - List installed operators in the cluster -- **`/olm:search` `[query] [--catalog ]`** - Search for available operators in catalog sources -- **`/olm:status` ` [namespace]`** - Get detailed status and health information for an operator -- **`/olm:uninstall` ` [namespace] [--remove-crds] [--remove-namespace]`** - Uninstall a day-2 operator and optionally remove its resources -- **`/olm:upgrade` ` [namespace] [--channel=] [--approve]`** - Update an operator to the latest version or switch channels +- **`/olm:detect-version`** - Auto-detect which OLM version(s) are installed in the cluster +- **`/olm:diagnose` `[operator-name] [namespace] [--fix] [--cluster]`** - Diagnose and optionally fix common OLM and operator issues (OLM v0 only) +- **`/olm:fix-rbac` ``** - Fix RBAC permission issues for a ClusterExtension (OLM v1 only) +- **`/olm:install` ` [options] [--version v0|v1]`** - Install an operator (v0) or extension (v1) using OLM +- **`/olm:list` `[namespace] [--all-namespaces] [--version v0|v1]`** - List installed operators (v0) or extensions (v1) in the cluster +- **`/olm:search` `[query] [--catalog ] [--version v0|v1]`** - Search for available operators (v0) or extensions (v1) in catalogs +- **`/olm:status` ` [namespace] [--version v0|v1]`** - Get detailed status of an operator (v0) or extension (v1) +- **`/olm:uninstall` ` [namespace] [--remove-crds] [--remove-namespace] [--version v0|v1]`** - Uninstall an operator (v0) or extension (v1) from the cluster +- **`/olm:upgrade` ` [namespace] [--channel ] [--approve] [--version v0|v1]`** - Upgrade an operator (v0) or extension (v1) to a new version +- **`/olm:use-version` `[v0|v1|clear]`** - Set or view the OLM version context for this session See [plugins/olm/README.md](plugins/olm/README.md) for detailed documentation. diff --git a/docs/data.json b/docs/data.json index 35f818d..20cac95 100644 --- a/docs/data.json +++ b/docs/data.json @@ -263,15 +263,15 @@ "commands": [ { "name": "approve", - "description": "Approve pending InstallPlans for operator installations and upgrades", + "description": "Approve pending InstallPlans for operator installations and upgrades (OLM v0 only)", "synopsis": "/olm:approve [namespace] [--all]", "argument_hint": " [namespace] [--all]" }, { "name": "catalog", - "description": "Manage catalog sources for discovering and installing operators", - "synopsis": "/olm:catalog list", - "argument_hint": " [arguments]" + "description": "Manage catalog sources (v0) or ClusterCatalogs (v1)", + "synopsis": "/olm:catalog [args] [--version v0|v1]", + "argument_hint": " [args] [--version v0|v1]" }, { "name": "debug", @@ -279,50 +279,74 @@ "synopsis": "/olm:debug [olm-version]", "argument_hint": " [olm-version]" }, + { + "name": "detect-version", + "description": "Auto-detect which OLM version(s) are installed in the cluster", + "synopsis": "/olm:detect-version", + "argument_hint": "" + }, { "name": "diagnose", - "description": "Diagnose and optionally fix common OLM and operator issues", + "description": "Diagnose and optionally fix common OLM and operator issues (OLM v0 only)", "synopsis": "/olm:diagnose [operator-name] [namespace] [--fix] [--cluster]", "argument_hint": "[operator-name] [namespace] [--fix] [--cluster]" }, + { + "name": "fix-rbac", + "description": "Fix RBAC permission issues for a ClusterExtension (OLM v1 only)", + "synopsis": "/olm:fix-rbac ", + "argument_hint": "" + }, { "name": "install", - "description": "Install a day-2 operator using Operator Lifecycle Manager", - "synopsis": "/olm:install [namespace] [channel] [source] [--approval=Automatic|Manual]", - "argument_hint": " [namespace] [channel] [source] [--approval=Automatic|Manual]" + "description": "Install an operator (v0) or extension (v1) using OLM", + "synopsis": "/olm:install [options] [--version v0|v1]", + "argument_hint": " [options] [--version v0|v1]" }, { "name": "list", - "description": "List installed operators in the cluster", - "synopsis": "/olm:list [namespace] [--all-namespaces]", - "argument_hint": "[namespace] [--all-namespaces]" + "description": "List installed operators (v0) or extensions (v1) in the cluster", + "synopsis": "/olm:list [namespace] [--all-namespaces] [--version v0|v1]", + "argument_hint": "[namespace] [--all-namespaces] [--version v0|v1]" }, { "name": "search", - "description": "Search for available operators in catalog sources", - "synopsis": "/olm:search [query] [--catalog ]", - "argument_hint": "[query] [--catalog ]" + "description": "Search for available operators (v0) or extensions (v1) in catalogs", + "synopsis": "/olm:search [query] [--catalog ] [--version v0|v1]", + "argument_hint": "[query] [--catalog ] [--version v0|v1]" }, { "name": "status", - "description": "Get detailed status and health information for an operator", - "synopsis": "/olm:status [namespace]", - "argument_hint": " [namespace]" + "description": "Get detailed status of an operator (v0) or extension (v1)", + "synopsis": "/olm:status [namespace] [--version v0|v1]", + "argument_hint": " [namespace] [--version v0|v1]" }, { "name": "uninstall", - "description": "Uninstall a day-2 operator and optionally remove its resources", - "synopsis": "/olm:uninstall [namespace] [--remove-crds] [--remove-namespace]", - "argument_hint": " [namespace] [--remove-crds] [--remove-namespace]" + "description": "Uninstall an operator (v0) or extension (v1) from the cluster", + "synopsis": "/olm:uninstall [namespace] [--remove-crds] [--remove-namespace] [--version v0|v1]", + "argument_hint": " [namespace] [--remove-crds] [--remove-namespace] [--version v0|v1]" }, { "name": "upgrade", - "description": "Update an operator to the latest version or switch channels", - "synopsis": "/olm:upgrade [namespace] [--channel=] [--approve]", - "argument_hint": " [namespace] [--channel=] [--approve]" + "description": "Upgrade an operator (v0) or extension (v1) to a new version", + "synopsis": "/olm:upgrade [namespace] [--channel ] [--approve] [--version v0|v1]", + "argument_hint": " [namespace] [--channel ] [--approve] [--version v0|v1]" + }, + { + "name": "use-version", + "description": "Set or view the OLM version context for this session", + "synopsis": "/olm:use-version [v0|v1|clear]", + "argument_hint": "[v0|v1|clear]" + } + ], + "skills": [ + { + "name": "OLM Version Detection", + "id": "version-detection", + "description": "Determine which OLM version to use based on context and flags" } ], - "skills": [], "has_readme": true }, { diff --git a/plugins/olm/README.md b/plugins/olm/README.md index e48fc6b..de4543f 100644 --- a/plugins/olm/README.md +++ b/plugins/olm/README.md @@ -1,33 +1,124 @@ # OLM Plugin -A comprehensive plugin for managing and debugging Operator Lifecycle Manager (OLM) in OpenShift clusters. +A comprehensive unified plugin for managing and debugging Operator Lifecycle Manager (OLM) in Kubernetes and OpenShift clusters. ## Overview -This plugin provides comprehensive OLM capabilities: +This plugin provides comprehensive OLM capabilities for both **OLM v0** (traditional) and **OLM v1** (next-generation): -- **Operator Discovery**: Search and discover operators across all catalog sources -- **Lifecycle Management**: Install, upgrade, and uninstall operators with intelligent defaults -- **Health Monitoring**: List and check detailed operator health status -- **Update Management**: Check for and install operator updates with approval workflows -- **Troubleshooting**: Diagnose and fix common OLM issues automatically -- **Catalog Management**: Add, remove, and manage custom catalog sources -- **Advanced Debugging**: Troubleshoot OLM issues by correlating must-gather logs with source code and known bugs in Jira -- **Safety Features**: Orphaned resource cleanup, stuck namespace detection, and confirmation prompts -- **Context-Aware**: Automatic channel discovery, namespace auto-detection, and smart recommendations +- **Unified Interface**: Single plugin supporting both OLM versions +- **Operator/Extension Discovery**: Search and discover packages across catalogs +- **Lifecycle Management**: Install, upgrade, and uninstall with version-aware commands +- **Health Monitoring**: List and check detailed status +- **Update Management**: Handle upgrades with version-specific strategies +- **Troubleshooting**: Diagnose and fix issues (v0: orphaned resources, v1: RBAC permissions) +- **Catalog Management**: Manage catalog sources (v0) or ClusterCatalogs (v1) +- **Advanced Debugging**: Troubleshoot using must-gather logs with source code correlation +- **RBAC Management**: Automatic RBAC setup and fixing for OLM v1 -The plugin supports both OLMv0 (traditional OLM) and OLMv1 (next-generation) architectures. +## πŸ”‘ Version Management (Important!) + +**This plugin requires explicit OLM version selection.** You must specify which OLM version to use via: + +### Option 1: Set Context (Recommended) +```bash +# Detect what's installed in your cluster +/olm:detect-version + +# Set version context for your session +/olm:use-version v0 # For traditional OLM +/olm:use-version v1 # For next-generation OLM + +# Now use commands without repeating --version +/olm:install cert-manager +/olm:list +/olm:status cert-manager +``` + +### Option 2: Per-Command Flag +```bash +# Use --version flag on each command +/olm:install cert-manager --version v0 +/olm:list --version v1 +/olm:status postgres-operator --version v0 +``` + +### Version Detection +```bash +# Auto-detect which OLM version(s) are installed +/olm:detect-version +``` + +### Key Differences + +| Aspect | OLM v0 (Traditional) | OLM v1 (Next-Generation) | +| ------------- | --------------------------------- | ------------------------------------------- | +| **Resources** | Subscription, CSV, InstallPlan | ClusterExtension, ClusterCatalog | +| **Catalogs** | CatalogSource (namespace-scoped) | ClusterCatalog (cluster-scoped) | +| **CLI** | `oc` (OpenShift CLI) | `kubectl` | +| **RBAC** | Managed by OLM (cluster-admin) | User-managed (ServiceAccount + ClusterRole) | +| **Upgrades** | Automatic or manual approval | Version constraints or channel tracking | +| **Scope** | Primarily operators | Any Kubernetes extension | +| **Best For** | OpenShift, existing installations | New projects, GitOps, flexible versioning | ## Prerequisites +### Common - Claude Code installed +- Access to a Kubernetes/OpenShift cluster with sufficient RBAC permissions + +### OLM v0 Specific - OpenShift CLI (`oc`) installed and configured -- Access to an OpenShift cluster with cluster-admin or sufficient RBAC permissions +- OLM v0 installed (pre-installed on OpenShift) + +### OLM v1 Specific +- `kubectl` installed and configured +- OLM v1 (operator-controller) installed +- cert-manager installed (optional, for webhook support) + +### Optional - `git` (required for debug command) - Network access to GitHub and Jira (for debug command) ## Commands +### Version Management Commands + +#### `/olm:use-version` - Set OLM Version Context + +Set the OLM version context for your session to avoid repeating `--version` on every command. + +**Usage:** +```bash +/olm:use-version v0 # Set to OLM v0 +/olm:use-version v1 # Set to OLM v1 +/olm:use-version # View current context +/olm:use-version clear # Clear context +``` + +See [commands/use-version.md](commands/use-version.md) for full documentation. + +--- + +#### `/olm:detect-version` - Auto-Detect OLM Version + +Automatically detect which OLM version(s) are installed in your cluster. + +**Usage:** +```bash +/olm:detect-version +``` + +**What it does:** +- Checks for OLM v0 installation (openshift-operator-lifecycle-manager namespace) +- Checks for OLM v1 installation (olmv1-system namespace) +- Shows component status and versions +- Provides recommendations for version selection + +See [commands/detect-version.md](commands/detect-version.md) for full documentation. + +--- + ### Operator Management Commands #### `/olm:search` - Search for Operators @@ -166,10 +257,12 @@ See [commands/upgrade.md](commands/upgrade.md) for full documentation. --- -#### `/olm:approve` - Approve InstallPlans +#### `/olm:approve` - Approve InstallPlans (v0 only) Approve pending InstallPlans for operators with manual approval mode. +**⚠️ OLM v0 ONLY**: This command only works with OLM v0. + **Usage:** ```bash /olm:approve openshift-cert-manager-operator # Approve pending plan @@ -193,6 +286,38 @@ See [commands/approve.md](commands/approve.md) for full documentation. --- +#### `/olm:fix-rbac` - Fix RBAC Permissions (v1 only) + +Diagnose and fix RBAC permission issues for ClusterExtensions. + +**⚠️ OLM v1 ONLY**: This command only works with OLM v1. + +**Usage:** +```bash +/olm:fix-rbac postgres-operator # Fix RBAC for failed extension +``` + +**What it does:** +- Detects pre-authorization failures in ClusterExtension status +- Parses missing RBAC permissions from error messages +- Identifies current ServiceAccount and ClusterRole +- Offers to automatically update ClusterRole with missing permissions +- Or displays required RBAC YAML for manual application + +**When to use:** +- Extension installation is stuck in "Progressing" state +- Status shows "pre-authorization failed" errors +- You see RBAC-related error messages + +**Arguments:** +- `extension-name` (required): Name of the ClusterExtension to fix + +**Note:** Requires the `PreflightPermissions` feature gate to be enabled in operator-controller for detailed permission analysis. + +See [commands/fix-rbac.md](commands/fix-rbac.md) for full documentation. + +--- + #### `/olm:uninstall` - Uninstall Operators Safely uninstall operators with optional resource cleanup. diff --git a/plugins/olm/commands/approve.md b/plugins/olm/commands/approve.md index 3aa5437..739e4a0 100644 --- a/plugins/olm/commands/approve.md +++ b/plugins/olm/commands/approve.md @@ -1,5 +1,5 @@ --- -description: Approve pending InstallPlans for operator installations and upgrades +description: Approve pending InstallPlans for operator installations and upgrades (OLM v0 only) argument-hint: [namespace] [--all] --- @@ -14,6 +14,8 @@ olm:approve ## Description The `olm:approve` command approves pending InstallPlans for operators with manual approval mode. This is required for operators that have `installPlanApproval: Manual` in their Subscription to proceed with installation or upgrades. +**⚠️ OLM v0 ONLY**: This command only works with OLM v0. OLM v1 does not use InstallPlans. + This command helps you: - Approve operator installations that are waiting for manual approval - Approve operator upgrades @@ -24,7 +26,28 @@ This command helps you: The command performs the following steps: -1. **Parse Arguments**: +1. **Check OLM Version** (v0 ONLY): + ```bash + # Check if version context is set + if [ -f .work/olm/context.txt ]; then + OLM_VERSION=$(cat .work/olm/context.txt) + if [ "$OLM_VERSION" == "v1" ]; then + echo "❌ Command not available for OLM v1" + echo "" + echo "The /olm:approve command is only available for OLM v0." + echo "Current context: v1" + echo "" + echo "OLM v1 does not use InstallPlans. Installations proceed automatically" + echo "once RBAC permissions are satisfied." + echo "" + echo "To use this command, switch to v0:" + echo " /olm:use-version v0" + exit 1 + fi + fi + ``` + +2. **Parse Arguments**: - `$1`: Operator name (required) - Name of the operator - `$2`: Namespace (optional) - Namespace where operator is installed - If not provided, searches for the operator across all namespaces diff --git a/plugins/olm/commands/catalog.md b/plugins/olm/commands/catalog.md index cd43964..89ba977 100644 --- a/plugins/olm/commands/catalog.md +++ b/plugins/olm/commands/catalog.md @@ -1,6 +1,6 @@ --- -description: Manage catalog sources for discovering and installing operators -argument-hint: [arguments] +description: Manage catalog sources (v0) or ClusterCatalogs (v1) +argument-hint: [args] [--version v0|v1] --- ## Name @@ -8,426 +8,171 @@ olm:catalog ## Synopsis ``` -/olm:catalog list -/olm:catalog add [--namespace=openshift-marketplace] -/olm:catalog remove [--namespace=openshift-marketplace] -/olm:catalog refresh [--namespace=openshift-marketplace] -/olm:catalog status [--namespace=openshift-marketplace] +/olm:catalog [args] [--version v0|v1] ``` ## Description -The `olm:catalog` command manages catalog sources for operator discovery and installation. Catalog sources provide the list of operators available for installation in the cluster. +Manage catalog sources (OLM v0 CatalogSource) or ClusterCatalogs (OLM v1) for discovering available operators/extensions. -This command helps you: -- List all available catalog sources and their health status -- Add custom or private catalog sources -- Remove catalog sources -- Refresh catalog sources to get latest operator updates +**You must explicitly specify which OLM version to use** via `--version` flag or context. ## Implementation -### Subcommand: list - -1. **Get All CatalogSources**: - ```bash - oc get catalogsource -n openshift-marketplace -o json - ``` - -2. **Parse CatalogSource Data**: - For each catalog, extract: - - Name: `.metadata.name` - - Display Name: `.spec.displayName` - - Publisher: `.spec.publisher` - - Source Type: `.spec.sourceType` (grpc, configmap, etc.) - - Image: `.spec.image` (for grpc type) - - Connection State: `.status.connectionState.lastObservedState` - - Last Updated: `.status.connectionState.lastUpdatedTime` - - Number of Operators: Count from PackageManifests with this catalog - -3. **Get Catalog Pod Status**: - ```bash - oc get pods -n openshift-marketplace -l olm.catalogSource={catalog-name} - ``` - -4. **Format Output**: - ``` - ═══════════════════════════════════════════════════════════ - CATALOG SOURCES - ═══════════════════════════════════════════════════════════ - - NAME STATUS OPERATORS LAST UPDATED SOURCE TYPE - redhat-operators READY 150 2h ago grpc - certified-operators READY 45 3h ago grpc - community-operators READY 200 1h ago grpc - redhat-marketplace READY 30 4h ago grpc - custom-catalog FAILED 0 - grpc - - ═══════════════════════════════════════════════════════════ - DETAILS - ═══════════════════════════════════════════════════════════ - - redhat-operators: - Display Name: Red Hat Operators - Publisher: Red Hat - Image: registry.redhat.io/redhat/redhat-operator-index:v4.20 - Pod: redhat-operators-abc123 (Running) - - custom-catalog (FAILED): - Display Name: Custom Catalog - Publisher: My Company - Image: registry.example.com/custom-catalog:latest - Pod: custom-catalog-xyz789 (CrashLoopBackOff) - Error: ImagePullBackOff - - To troubleshoot: - /olm:catalog status custom-catalog - ``` - -### Subcommand: add - -1. **Parse Arguments**: - - `name`: Catalog source name (required) - - `image`: Catalog image (required) - - `--namespace`: Target namespace (default: openshift-marketplace) - - `--display-name`: Display name (optional) - - `--publisher`: Publisher name (optional) - -2. **Validate Image**: - - Check if image format is valid - - Optionally test image accessibility (if possible) - -3. **Create CatalogSource Manifest**: - ```yaml - apiVersion: operators.coreos.com/v1alpha1 - kind: CatalogSource - metadata: - name: {name} - namespace: {namespace} - spec: - sourceType: grpc - image: {image} - displayName: {display-name} - publisher: {publisher} - updateStrategy: - registryPoll: - interval: 30m - ``` - -4. **Apply CatalogSource**: - ```bash - oc apply -f /tmp/catalogsource-{name}.yaml - ``` - -5. **Wait for CatalogSource to be Ready**: - ```bash - oc wait --for=condition=READY catalogsource/{name} -n {namespace} --timeout=300s - ``` - -6. **Verify Pod is Running**: - ```bash - oc get pods -n {namespace} -l olm.catalogSource={name} - ``` - -7. **Display Result**: - ``` - βœ“ Catalog source added: {name} - - Name: {name} - Namespace: {namespace} - Image: {image} - Status: READY - Pod: {pod-name} (Running) - - To search operators: /olm:search --catalog {name} - ``` - -### Subcommand: remove - -1. **Parse Arguments**: - - `name`: Catalog source name (required) - - `--namespace`: Namespace (default: openshift-marketplace) - -2. **Check if CatalogSource Exists**: - ```bash - oc get catalogsource {name} -n {namespace} --ignore-not-found - ``` - -3. **Check for Operators Using This Catalog**: - ```bash - oc get subscription --all-namespaces -o json | \ - jq -r '.items[] | select(.spec.source=="{name}") | "\(.metadata.namespace)/\(.metadata.name)"' - ``` - -4. **Display Warning** (if operators found): - ``` - WARNING: The following operators are using this catalog: - - namespace-1/operator-1 - - namespace-2/operator-2 - - Removing this catalog will prevent these operators from receiving updates. - - Do you want to continue? (yes/no) - ``` - -5. **Delete CatalogSource**: - ```bash - oc delete catalogsource {name} -n {namespace} - ``` - -6. **Wait for Pod to be Deleted**: - ```bash - oc wait --for=delete pod -l olm.catalogSource={name} -n {namespace} --timeout=60s - ``` - -7. **Display Result**: - ``` - βœ“ Catalog source removed: {name} - ``` - -### Subcommand: refresh - -1. **Parse Arguments**: - - `name`: Catalog source name (required) - - `--namespace`: Namespace (default: openshift-marketplace) - -2. **Get Current CatalogSource**: - ```bash - oc get catalogsource {name} -n {namespace} -o json - ``` - -3. **Trigger Refresh by Deleting Pod**: - ```bash - oc delete pod -n {namespace} -l olm.catalogSource={name} - ``` - - This forces OLM to recreate the pod and re-fetch catalog data - -4. **Wait for New Pod to be Ready**: - ```bash - oc wait --for=condition=Ready pod -l olm.catalogSource={name} -n {namespace} --timeout=300s - ``` - -5. **Verify Catalog is Updated**: - ```bash - oc get catalogsource {name} -n {namespace} -o json | \ - jq -r '.status.connectionState.lastUpdatedTime' - ``` - -6. **Display Result**: - ``` - βœ“ Catalog source refreshed: {name} - - Last Updated: {timestamp} - Status: READY - Pod: {pod-name} (Running) - - New operators may now be available: /olm:search --catalog {name} - ``` - -### Subcommand: status - -1. **Parse Arguments**: - - `name`: Catalog source name (required) - - `--namespace`: Namespace (default: openshift-marketplace) - -2. **Get CatalogSource Details**: - ```bash - oc get catalogsource {name} -n {namespace} -o json - ``` - -3. **Get Pod Details**: - ```bash - oc get pods -n {namespace} -l olm.catalogSource={name} -o json - ``` - -4. **Get Recent Events**: - ```bash - oc get events -n {namespace} --field-selector involvedObject.name={name} --sort-by='.lastTimestamp' - ``` - -5. **Count Available Operators**: - ```bash - oc get packagemanifests -n openshift-marketplace -o json | \ - jq -r '.items[] | select(.status.catalogSource=="{name}") | .metadata.name' | wc -l - ``` - -6. **Verify Catalog Connectivity**: - - Check if catalog is serving content by verifying PackageManifest count > 0 - - If count is 0 but pod is Running, indicates connectivity or catalog index issues - - Review catalog pod logs for gRPC errors, image pull issues, or index corruption: - ```bash - oc logs -n {namespace} {catalog-pod-name} - ``` - -7. **Format Comprehensive Status Report**: - ``` - ═══════════════════════════════════════════════════════════ - CATALOG SOURCE STATUS: {name} - ═══════════════════════════════════════════════════════════ - - General Information: - Name: {name} - Namespace: {namespace} - Display Name: {display-name} - Publisher: {publisher} - Source Type: {source-type} - Image: {image} - - Connection Status: - State: {state} (READY | CONNECTING | CONNECTION_FAILED) - Last Updated: {timestamp} - Last Successful: {timestamp} - - Pod Status: - Name: {pod-name} - Status: {status} (Running | CrashLoopBackOff | ImagePullBackOff) - Ready: {ready-containers}/{total-containers} - Restarts: {restart-count} - Age: {age} - - Catalog Content: - Operators Available: {count} - - [If issues detected:] - ⚠️ Issues Detected: - - Pod in CrashLoopBackOff - - Last update: 24h ago (stale) - - Connection state: CONNECTION_FAILED - - Recent Events: - {timestamp} Warning: Failed to pull image - {timestamp} Warning: Back-off restarting failed container - - Troubleshooting Steps: - 1. Check pod logs: oc logs -n {namespace} {pod-name} - 2. Check image accessibility - 3. Refresh catalog: /olm:catalog refresh {name} - 4. Verify network connectivity (for disconnected environments) - - Related Commands: - - Refresh: /olm:catalog refresh {name} - - List operators: /olm:search --catalog {name} - ``` +### 1. Determine OLM Version +**See [skills/version-detection/SKILL.md](../../skills/version-detection/SKILL.md)** + +### 2. Parse Action +- `list`: List all catalogs +- `add [--poll-interval ]`: Add new catalog +- `remove `: Remove catalog +- `refresh `: Force catalog refresh +- `status `: Check catalog health + +--- + +## OLM v0 Implementation + +### Actions + +#### list +```bash +oc get catalogsources -n openshift-marketplace -o json | \ + jq -r '.items[] | [.metadata.name, .spec.sourceType, .status.connectionState.lastObservedState] | @tsv' | \ + while IFS=$'\t' read -r name type state; do + echo "Name: $name" + echo " Type: $type" + echo " State: $state" + echo "" + done +``` + +#### add +```bash +cat <**: Poll interval for catalog updates (default: 15m) +- **--version v0|v1**: OLM version + +## Notes +- **v0**: Manages CatalogSource in `openshift-marketplace` namespace +- **v1**: Manages cluster-scoped ClusterCatalog resources +- Catalog refresh may take a few minutes +- After adding catalog, use `/olm:search` to discover packages diff --git a/plugins/olm/commands/detect-version.md b/plugins/olm/commands/detect-version.md new file mode 100644 index 0000000..b9e4d60 --- /dev/null +++ b/plugins/olm/commands/detect-version.md @@ -0,0 +1,369 @@ +--- +description: Auto-detect which OLM version(s) are installed in the cluster +--- + +## Name +olm:detect-version + +## Synopsis +``` +/olm:detect-version +``` + +## Description +The `olm:detect-version` command automatically detects which OLM version(s) are installed in your Kubernetes cluster by checking for characteristic namespaces, deployments, and resources. This helps you determine which version to use with OLM commands. + +**Use this command when:** +- You're unsure which OLM version is installed in your cluster +- You want to verify OLM installation before running other commands +- You're working with a new cluster and need to understand its OLM setup +- Both OLM versions are installed and you want to know which to use + +The command checks for both OLM v0 (traditional) and OLM v1 (next-generation) installations and provides detailed information about what was found. + +## Implementation + +1. **Check prerequisites**: + ```bash + # Check for oc CLI (used by OLM v0) + if ! command -v oc &> /dev/null; then + echo "⚠️ 'oc' command not found - OLM v0 detection may be limited" + echo " Install from: https://docs.openshift.com/container-platform/latest/cli_reference/openshift_cli/getting-started-cli.html" + echo "" + fi + + # Check for kubectl CLI (used by OLM v1) + if ! command -v kubectl &> /dev/null; then + echo "⚠️ 'kubectl' command not found - OLM v1 detection may be limited" + echo " Install from: https://kubernetes.io/docs/tasks/tools/" + echo "" + fi + + # Check cluster access + if ! oc whoami &> /dev/null && ! kubectl auth can-i get nodes &> /dev/null; then + echo "❌ Cannot access cluster" + echo " Please ensure you are logged in to a Kubernetes/OpenShift cluster" + exit 1 + fi + ``` + +2. **Detect OLM v0**: + ```bash + echo "Checking for OLM v0 (traditional OLM)..." + echo "" + + V0_DETECTED=false + + # Check for OLM v0 namespace + if oc get namespace openshift-operator-lifecycle-manager --ignore-not-found &> /dev/null; then + echo "βœ“ OLM v0 namespace found: openshift-operator-lifecycle-manager" + V0_DETECTED=true + + # Check for OLM operator + if oc get deployment olm-operator -n openshift-operator-lifecycle-manager --ignore-not-found &> /dev/null; then + OLM_STATUS=$(oc get deployment olm-operator -n openshift-operator-lifecycle-manager -o jsonpath='{.status.conditions[?(@.type=="Available")].status}') + if [ "$OLM_STATUS" == "True" ]; then + echo " βœ“ olm-operator: Running" + else + echo " ⚠️ olm-operator: Not ready" + fi + else + echo " βœ— olm-operator: Not found" + fi + + # Check for Catalog operator + if oc get deployment catalog-operator -n openshift-operator-lifecycle-manager --ignore-not-found &> /dev/null; then + CATALOG_STATUS=$(oc get deployment catalog-operator -n openshift-operator-lifecycle-manager -o jsonpath='{.status.conditions[?(@.type=="Available")].status}') + if [ "$CATALOG_STATUS" == "True" ]; then + echo " βœ“ catalog-operator: Running" + else + echo " ⚠️ catalog-operator: Not ready" + fi + else + echo " βœ— catalog-operator: Not found" + fi + + # Get PackageServer version + PACKAGESERVER_CSV=$(oc get csv -A -l olm.clusteroperator.name=packageserver --ignore-not-found -o jsonpath='{.items[0].metadata.name}' 2>/dev/null) + if [ -n "$PACKAGESERVER_CSV" ]; then + echo " βœ“ PackageServer CSV: $PACKAGESERVER_CSV" + fi + + # Count catalog sources + CATALOG_COUNT=$(oc get catalogsources -n openshift-marketplace --ignore-not-found 2>/dev/null | grep -v NAME | wc -l) + if [ "$CATALOG_COUNT" -gt 0 ]; then + echo " βœ“ CatalogSources: $CATALOG_COUNT available" + else + echo " ⚠️ CatalogSources: None found" + fi + + # Count installed operators + CSV_COUNT=$(oc get csv --all-namespaces --ignore-not-found 2>/dev/null | grep -v NAME | wc -l) + if [ "$CSV_COUNT" -gt 0 ]; then + echo " βœ“ Installed operators: $CSV_COUNT" + fi + + else + echo "βœ— OLM v0 not detected" + echo " Namespace 'openshift-operator-lifecycle-manager' not found" + fi + + echo "" + ``` + +3. **Detect OLM v1**: + ```bash + echo "Checking for OLM v1 (next-generation OLM)..." + echo "" + + V1_DETECTED=false + + # Check for OLM v1 namespace + if kubectl get namespace olmv1-system --ignore-not-found &> /dev/null; then + echo "βœ“ OLM v1 namespace found: olmv1-system" + V1_DETECTED=true + + # Check for operator-controller + if kubectl get deployment operator-controller-controller-manager -n olmv1-system --ignore-not-found &> /dev/null; then + CONTROLLER_STATUS=$(kubectl get deployment operator-controller-controller-manager -n olmv1-system -o jsonpath='{.status.conditions[?(@.type=="Available")].status}') + if [ "$CONTROLLER_STATUS" == "True" ]; then + echo " βœ“ operator-controller: Running" + else + echo " ⚠️ operator-controller: Not ready" + fi + + # Get controller image/version + CONTROLLER_IMAGE=$(kubectl get deployment operator-controller-controller-manager -n olmv1-system -o jsonpath='{.spec.template.spec.containers[0].image}') + if [ -n "$CONTROLLER_IMAGE" ]; then + CONTROLLER_VERSION=$(echo "$CONTROLLER_IMAGE" | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' | head -1) + if [ -n "$CONTROLLER_VERSION" ]; then + echo " βœ“ Version: $CONTROLLER_VERSION" + else + echo " βœ“ Image: $CONTROLLER_IMAGE" + fi + fi + + # Check feature gates + FEATURE_GATES=$(kubectl get deployment operator-controller-controller-manager -n olmv1-system -o jsonpath='{.spec.template.spec.containers[0].args}' | grep -o 'feature-gates=[^"]*' | head -1) + if [ -n "$FEATURE_GATES" ]; then + echo " βœ“ Feature gates: $FEATURE_GATES" + fi + else + echo " βœ— operator-controller: Not found" + fi + + # Check for catalogd service + if kubectl get service catalogd-service -n olmv1-system --ignore-not-found &> /dev/null; then + echo " βœ“ catalogd-service: Available" + fi + + # Count cluster catalogs + CATALOG_COUNT=$(kubectl get clustercatalogs --ignore-not-found 2>/dev/null | grep -v NAME | wc -l) + if [ "$CATALOG_COUNT" -gt 0 ]; then + echo " βœ“ ClusterCatalogs: $CATALOG_COUNT available" + # List them + kubectl get clustercatalogs --no-headers 2>/dev/null | awk '{print " - " $1}' + else + echo " ⚠️ ClusterCatalogs: None found" + fi + + # Count installed extensions + EXTENSION_COUNT=$(kubectl get clusterextensions --ignore-not-found 2>/dev/null | grep -v NAME | wc -l) + if [ "$EXTENSION_COUNT" -gt 0 ]; then + echo " βœ“ Installed extensions: $EXTENSION_COUNT" + fi + + else + echo "βœ— OLM v1 not detected" + echo " Namespace 'olmv1-system' not found" + fi + + echo "" + ``` + +4. **Provide summary and recommendations**: + ```bash + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "" + + if [ "$V0_DETECTED" = true ] && [ "$V1_DETECTED" = true ]; then + echo "πŸ“Š Summary: Both OLM v0 and v1 are installed" + echo "" + echo "You can use either version with this plugin:" + echo "" + echo "OLM v0 (Traditional):" + echo " - Best for: OpenShift operators, existing installations" + echo " - Resources: Subscription, CSV, InstallPlan" + echo " - Catalogs: CatalogSource" + echo " - Set context: /olm:use-version v0" + echo "" + echo "OLM v1 (Next-Generation):" + echo " - Best for: New installations, GitOps, flexible versioning" + echo " - Resources: ClusterExtension" + echo " - Catalogs: ClusterCatalog" + echo " - RBAC: User-managed (more control, more setup)" + echo " - Set context: /olm:use-version v1" + echo "" + echo "πŸ’‘ Recommendation: Use v0 for OpenShift, v1 for new projects" + + elif [ "$V0_DETECTED" = true ]; then + echo "πŸ“Š Summary: Only OLM v0 detected" + echo "" + echo "Your cluster has traditional OLM installed." + echo "" + echo "To use OLM commands with v0:" + echo " /olm:use-version v0" + echo "" + echo "Or use --version flag on each command:" + echo " /olm:install --version v0 [options]" + + elif [ "$V1_DETECTED" = true ]; then + echo "πŸ“Š Summary: Only OLM v1 detected" + echo "" + echo "Your cluster has next-generation OLM installed." + echo "" + echo "To use OLM commands with v1:" + echo " /olm:use-version v1" + echo "" + echo "Or use --version flag on each command:" + echo " /olm:install --version v1 [options]" + echo "" + echo "⚠️ Note: OLM v1 requires user-managed RBAC (ServiceAccount + ClusterRole)" + + else + echo "πŸ“Š Summary: No OLM installation detected" + echo "" + echo "Neither OLM v0 nor OLM v1 were found in this cluster." + echo "" + echo "To install OLM:" + echo "" + echo "For OLM v0 (traditional):" + echo " - OpenShift clusters have this pre-installed" + echo " - For vanilla Kubernetes: https://olm.operatorframework.io/" + echo "" + echo "For OLM v1 (next-generation):" + echo " - Installation guide: https://operator-framework.github.io/operator-controller/" + echo " - GitHub: https://github.com/operator-framework/operator-controller" + fi + + echo "" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + ``` + +## Return Value +- **Success**: Detection report showing which OLM version(s) are installed with component status +- **Format**: Multi-section report with: + - OLM v0 detection results + - OLM v1 detection results + - Summary and recommendations + - Next steps for setting context + +## Examples + +1. **Both versions installed**: + ``` + /olm:detect-version + ``` + + Output: + ``` + Checking for OLM v0 (traditional OLM)... + + βœ“ OLM v0 namespace found: openshift-operator-lifecycle-manager + βœ“ olm-operator: Running + βœ“ catalog-operator: Running + βœ“ PackageServer CSV: packageserver.v0.28.0 + βœ“ CatalogSources: 4 available + βœ“ Installed operators: 12 + + Checking for OLM v1 (next-generation OLM)... + + βœ“ OLM v1 namespace found: olmv1-system + βœ“ operator-controller: Running + βœ“ Version: v0.5.0 + βœ“ Feature gates: feature-gates=WebhookProviderCertManager=true + βœ“ catalogd-service: Available + βœ“ ClusterCatalogs: 2 available + - operatorhubio + - certified-operators + βœ“ Installed extensions: 3 + + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + πŸ“Š Summary: Both OLM v0 and v1 are installed + + You can use either version with this plugin: + + OLM v0 (Traditional): + - Best for: OpenShift operators, existing installations + - Set context: /olm:use-version v0 + + OLM v1 (Next-Generation): + - Best for: New installations, GitOps, flexible versioning + - Set context: /olm:use-version v1 + ``` + +2. **Only v0 installed**: + ``` + /olm:detect-version + ``` + + Output: + ``` + Checking for OLM v0 (traditional OLM)... + + βœ“ OLM v0 namespace found: openshift-operator-lifecycle-manager + βœ“ olm-operator: Running + βœ“ catalog-operator: Running + βœ“ CatalogSources: 4 available + + Checking for OLM v1 (next-generation OLM)... + + βœ— OLM v1 not detected + Namespace 'olmv1-system' not found + + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + πŸ“Š Summary: Only OLM v0 detected + + To use OLM commands with v0: + /olm:use-version v0 + ``` + +3. **No OLM installed**: + ``` + /olm:detect-version + ``` + + Output: + ``` + Checking for OLM v0 (traditional OLM)... + + βœ— OLM v0 not detected + + Checking for OLM v1 (next-generation OLM)... + + βœ— OLM v1 not detected + + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + πŸ“Š Summary: No OLM installation detected + + To install OLM: + + For OLM v0: https://olm.operatorframework.io/ + For OLM v1: https://operator-framework.github.io/operator-controller/ + ``` + +## Arguments +None - this command takes no arguments + +## Notes + +- **Cluster access required**: The command needs access to a Kubernetes/OpenShift cluster +- **Read-only**: This command only reads cluster state, it makes no changes +- **CLI requirements**: Works best with both `oc` and `kubectl` installed +- **Multiple versions**: It's possible (and sometimes useful) to have both OLM v0 and v1 installed +- **Feature gates**: For OLM v1, feature gates like `WebhookProviderCertManager` affect functionality +- **Next step**: After detecting OLM version(s), use `/olm:use-version` to set your context + diff --git a/plugins/olm/commands/diagnose.md b/plugins/olm/commands/diagnose.md index 83f6d27..2c13b04 100644 --- a/plugins/olm/commands/diagnose.md +++ b/plugins/olm/commands/diagnose.md @@ -1,5 +1,5 @@ --- -description: Diagnose and optionally fix common OLM and operator issues +description: Diagnose and optionally fix common OLM and operator issues (OLM v0 only) argument-hint: [operator-name] [namespace] [--fix] [--cluster] --- @@ -14,6 +14,8 @@ olm:diagnose ## Description The `olm:diagnose` command diagnoses common OLM and operator issues, including orphaned CRDs, stuck namespaces, failed installations, and catalog source problems. It can optionally attempt to fix detected issues automatically. +**⚠️ OLM v0 ONLY**: This command currently only supports OLM v0 diagnostics. + This command helps you: - Detect and clean up orphaned CRDs from deleted operators - Fix namespaces stuck in Terminating state @@ -27,7 +29,29 @@ This command helps you: The command performs the following steps: -1. **Parse Arguments**: +1. **Check OLM Version** (v0 ONLY): + ```bash + # Check if version context is set + if [ -f .work/olm/context.txt ]; then + OLM_VERSION=$(cat .work/olm/context.txt) + if [ "$OLM_VERSION" == "v1" ]; then + echo "❌ Command not available for OLM v1" + echo "" + echo "The /olm:diagnose command currently only supports OLM v0." + echo "Current context: v1" + echo "" + echo "For OLM v1 diagnostics:" + echo " - Use: /olm:status --version v1" + echo " - Use: /olm:fix-rbac --version v1" + echo "" + echo "To use this command with v0:" + echo " /olm:use-version v0" + exit 1 + fi + fi + ``` + +2. **Parse Arguments**: - `$1`: Operator name (optional) - Specific operator to diagnose - `$2`: Namespace (optional) - Specific namespace to check - `$3+`: Flags (optional): diff --git a/plugins/olm/commands/fix-rbac.md b/plugins/olm/commands/fix-rbac.md new file mode 100644 index 0000000..4f4d8b6 --- /dev/null +++ b/plugins/olm/commands/fix-rbac.md @@ -0,0 +1,320 @@ +--- +description: Fix RBAC permission issues for a ClusterExtension (OLM v1 only) +argument-hint: +--- + +## Name +olm:fix-rbac + +## Synopsis +``` +/olm:fix-rbac +``` + +## Description +The `olm:fix-rbac` command diagnoses and fixes RBAC permission issues for a ClusterExtension that failed preflight checks in OLM v1. + +**⚠️ OLM v1 ONLY**: This command only works with OLM v1. OLM v0 manages RBAC automatically via cluster-admin privileges. + +When a ClusterExtension fails to install due to missing RBAC permissions (pre-authorization failures), this command: +- Identifies the missing permissions from status conditions +- Parses the RBAC requirements +- Updates the ClusterRole automatically or provides manual instructions +- Verifies the fix worked + +## Implementation + +The command performs the following steps: + +1. **Check OLM Version** (v1 ONLY): + ```bash + # Check if version context is set + if [ -f .work/olm/context.txt ]; then + OLM_VERSION=$(cat .work/olm/context.txt) + if [ "$OLM_VERSION" == "v0" ]; then + echo "❌ Command not available for OLM v0" + echo "" + echo "The /olm:fix-rbac command is only available for OLM v1." + echo "Current context: v0" + echo "" + echo "OLM v0 manages RBAC automatically via cluster-admin privileges." + echo "" + echo "To use this command with v1:" + echo " /olm:use-version v1" + exit 1 + fi + fi + ``` + +2. **Prerequisites Check**: + ```bash + if ! command -v kubectl &> /dev/null; then + echo "❌ 'kubectl' command not found" + exit 1 + fi + + if ! kubectl get namespace olmv1-system &> /dev/null; then + echo "❌ OLM v1 not installed" + exit 1 + fi + ``` + +3. **Verify ClusterExtension exists**: + ```bash + if ! kubectl get clusterextension {extension-name} &> /dev/null; then + echo "❌ ClusterExtension not found: {extension-name}" + echo "" + echo "List available extensions: /olm:list" + exit 1 + fi + ``` + +4. **Get ClusterExtension status**: + ```bash + EXT=$(kubectl get clusterextension {extension-name} -o json) + + NAMESPACE=$(echo "$EXT" | jq -r '.spec.namespace') + SA_NAME=$(echo "$EXT" | jq -r '.spec.serviceAccount.name') + ``` + +5. **Check for pre-authorization failure**: + ```bash + PRE_AUTH_MSG=$(echo "$EXT" | jq -r '.status.conditions[] | + select(.message | contains("pre-authorization failed")) | .message') + + if [ -z "$PRE_AUTH_MSG" ]; then + echo "βœ“ No pre-authorization errors found" + echo "" + echo "The ClusterExtension may already be installed or have different issues." + echo "Check status: /olm:status {extension-name}" + exit 0 + fi + ``` + +6. **Parse missing permissions**: + ```bash + echo "Analyzing RBAC permissions for extension: {extension-name}" + echo "" + echo "Found pre-authorization failure in status conditions." + echo "" + + # Extract permission lines from error message + # Format: Namespace:"" APIGroups:[] Resources:[services] Verbs:[list,watch] + + PERMISSION_LINES=$(echo "$PRE_AUTH_MSG" | grep -E '^\s*Namespace:') + + # Parse each line into structured format + # This requires parsing: + # - Namespace value (empty string means cluster-scoped) + # - APIGroups list (empty [] means core group "") + # - Resources list + # - Verbs list + ``` + +7. **Find existing ClusterRole**: + ```bash + # Find ClusterRoleBinding for this ServiceAccount + CRB_NAME=$(kubectl get clusterrolebindings -o json | \ + jq -r --arg sa "$SA_NAME" --arg ns "$NAMESPACE" \ + '.items[] | select(.subjects[]? | + select(.kind=="ServiceAccount" and .name==$sa and .namespace==$ns)) | + .metadata.name' | head -1) + + if [ -z "$CRB_NAME" ]; then + echo "❌ Cannot find ClusterRoleBinding for ServiceAccount: $SA_NAME" + echo "The extension may not have been installed with proper RBAC." + echo "" + echo "Reinstall: /olm:install {extension-name} --channel --namespace $NAMESPACE" + exit 1 + fi + + CR_NAME=$(kubectl get clusterrolebinding $CRB_NAME -o jsonpath='{.roleRef.name}') + echo "Found ClusterRole: $CR_NAME" + ``` + +8. **Display missing permissions**: + ```bash + echo "" + echo "Missing RBAC Permissions:" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "" + + # Parse and display permissions grouped by scope + # - Cluster-scoped (Namespace:"") + # - Namespace-scoped (Namespace:"xxx") + + echo "Cluster-scoped permissions needed:" + # Display parsed permissions with API groups, resources, verbs + + echo "" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "" + echo "Current ServiceAccount: $SA_NAME (namespace: $NAMESPACE)" + echo "Current ClusterRole: $CR_NAME" + ``` + +9. **Offer to apply fixes**: + ```bash + read -p "Apply these fixes? (yes/no/show-yaml): " CHOICE + + case "$CHOICE" in + yes|y) + # Fetch current ClusterRole + CURRENT_CR=$(kubectl get clusterrole $CR_NAME -o json) + + # Generate new rules from parsed permissions + # Combine with existing rules + + # Apply updated ClusterRole + echo "$UPDATED_CR" | kubectl apply -f - + echo "βœ“ ClusterRole updated successfully" + ;; + show-yaml|show) + # Display the complete updated ClusterRole YAML + echo "" + echo "Apply with: kubectl apply -f " + echo "$UPDATED_CR" + ;; + *) + echo "Skipping automatic fix" + exit 0 + ;; + esac + ``` + +10. **Monitor reconciliation**: + ```bash + if [ "$CHOICE" == "yes" ] || [ "$CHOICE" == "y" ]; then + echo "" + echo "Waiting for operator-controller to retry installation..." + sleep 5 + + # Check if pre-authorization error is cleared + for i in {1..30}; do + NEW_MSG=$(kubectl get clusterextension {extension-name} -o jsonpath='{.status.conditions[?(@.type=="Progressing")].message}') + + if [[ "$NEW_MSG" != *"pre-authorization failed"* ]]; then + echo "βœ“ Pre-authorization check passed" + + INSTALLED=$(kubectl get clusterextension {extension-name} -o jsonpath='{.status.conditions[?(@.type=="Installed")].status}') + if [ "$INSTALLED" == "True" ]; then + echo "βœ“ Installation completed successfully" + else + echo "βœ“ Installation is now progressing" + fi + break + fi + sleep 2 + done + + echo "" + echo "Monitor with: kubectl get clusterextension {extension-name} -w" + fi + ``` + +## Return Value +- **Success**: RBAC fixed and extension installation proceeding +- **No errors**: Extension already has proper RBAC +- **Error**: ClusterExtension not found, no ClusterRole, or permission denied + +## Examples + +### Example 1: Fix RBAC for failed extension + +```bash +/olm:fix-rbac postgres-operator +``` + +Output: +``` +Analyzing RBAC permissions for extension: postgres-operator + +Found pre-authorization failure in status conditions. + +Missing RBAC Permissions: +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +Cluster-scoped permissions needed: +1. Core resources (APIGroup: "") + - Resources: persistentvolumeclaims + - Verbs: create, delete, get, list + +2. Apps API (APIGroup: apps) + - Resources: statefulsets + - Verbs: create, update, patch, delete + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +Current ServiceAccount: postgres-operator-sa (namespace: postgres-operator) +Current ClusterRole: postgres-operator-installer + +Apply these fixes? (yes/no/show-yaml): yes + +Updating ClusterRole: postgres-operator-installer... +βœ“ ClusterRole updated successfully + +Waiting for operator-controller to retry installation... +βœ“ Pre-authorization check passed +βœ“ Installation is now progressing + +Monitor with: kubectl get clusterextension postgres-operator -w +``` + +### Example 2: No errors found + +```bash +/olm:fix-rbac cert-manager +``` + +Output: +``` +Analyzing RBAC permissions for extension: cert-manager + +βœ“ No pre-authorization errors found + +The ClusterExtension is successfully installed with proper RBAC permissions. + +Current RBAC configuration: +- ServiceAccount: cert-manager-sa (namespace: cert-manager) +- ClusterRole: cert-manager-installer +- All required permissions are granted +``` + +## Arguments +- **$1** (extension-name): Name of the ClusterExtension to fix (required) + +## Notes + +### Prerequisites +- OLM v1 must be installed +- Ideally, `PreflightPermissions` feature gate should be enabled for detailed error messages +- User must have permissions to update ClusterRoles + +### Parsing Error Format +The pre-authorization error format from operator-controller: +``` +pre-authorization failed: service account requires the following permissions to manage cluster extension: + Namespace:"" APIGroups:[] Resources:[services] Verbs:[list,watch] + Namespace:"myns" APIGroups:[apps] Resources:[deployments] Verbs:[create] +``` + +Rules: +- `Namespace:""` β†’ cluster-scoped +- `APIGroups:[]` β†’ core API group (use `""` in YAML) +- Parse comma-separated lists in brackets + +### Automatic Retry +Once RBAC is fixed, operator-controller automatically retries installation without manual intervention. + +### Feature Gate +If `PreflightPermissions` is not enabled: +- RBAC errors won't be caught early +- Installation will fail with less helpful error messages +- This command can still help but may require more manual investigation + +### Troubleshooting +- If fix doesn't work, check operator-controller logs +- Verify feature gates are enabled correctly +- Ensure ServiceAccount and ClusterRole exist +- Use `/olm:status {extension-name}` for detailed status + diff --git a/plugins/olm/commands/install.md b/plugins/olm/commands/install.md index ccc0bcf..03d088f 100644 --- a/plugins/olm/commands/install.md +++ b/plugins/olm/commands/install.md @@ -1,6 +1,6 @@ --- -description: Install a day-2 operator using Operator Lifecycle Manager -argument-hint: [namespace] [channel] [source] [--approval=Automatic|Manual] +description: Install an operator (v0) or extension (v1) using OLM +argument-hint: [options] [--version v0|v1] --- ## Name @@ -8,265 +8,575 @@ olm:install ## Synopsis ``` -/olm:install [namespace] [channel] [source] [--approval=Automatic|Manual] +/olm:install [options] [--version v0|v1] ``` ## Description -The `olm:install` command installs a day-2 operator in an OpenShift cluster using Operator Lifecycle Manager (OLM). It automates the creation of the required namespace, OperatorGroup, and Subscription resources needed to install an operator. +The `olm:install` command installs a Kubernetes operator or extension using Operator Lifecycle Manager. This unified command supports both OLM v0 (traditional) and OLM v1 (next-generation) architectures. -This command handles the complete operator installation workflow: -- Creates or verifies the target namespace exists -- Creates an OperatorGroup if needed -- Creates a Subscription to install the operator -- Verifies the installation by checking the operator's CSV (ClusterServiceVersion) status -- Provides detailed feedback on the installation progress +**You must explicitly specify which OLM version to use** via: +- `--version` flag on this command, OR +- Setting the context with `/olm:use-version v0|v1` -The command is designed to work with operators from the OperatorHub catalog, including Red Hat certified operators, community operators, and custom catalog sources. +**OLM v0 (Traditional):** +- Installs operators using Subscription and CSV resources +- Requires OperatorGroup in the namespace +- Uses PackageManifest for operator discovery +- CLI: `oc` (OpenShift CLI) + +**OLM v1 (Next-Generation):** +- Installs extensions using ClusterExtension resources +- Requires user-managed ServiceAccount with RBAC permissions +- Uses ClusterCatalog for package discovery +- CLI: `kubectl` +- More setup required but provides better control ## Implementation -The command performs the following steps: +### 1. Determine OLM Version + +**See [skills/version-detection/SKILL.md](../../skills/version-detection/SKILL.md) for complete logic.** + +```bash +# Check for --version flag in arguments +# If not found, check context file: .work/olm/context.txt +# If neither found, display error and exit +# Validate version is v0 or v1 +``` + +### 2. Branch to Version-Specific Implementation + +Based on the determined version, execute the appropriate implementation: + +--- + +## OLM v0 Implementation + +Used when `--version v0` or context is set to v0. -1. **Parse Arguments**: - - `$1`: Operator name (required) - The name of the operator to install (e.g., "openshift-cert-manager-operator") - - `$2`: Namespace (optional) - Target namespace for the operator. If not provided, defaults to `{operator-name}-operator` (e.g., "cert-manager-operator") - - `$3`: Channel (optional) - Subscription channel. If not provided, discovers the default channel from the operator's PackageManifest - - `$4`: Source (optional) - CatalogSource name. Defaults to "redhat-operators" for Red Hat operators - - `$5+`: Flags (optional): - - `--approval=Automatic|Manual`: InstallPlan approval mode (default: Automatic) - - Automatic: Operator upgrades are automatically installed - - Manual: Operator upgrades require manual approval via `/olm:approve` or `oc patch` +### Synopsis (v0) +``` +/olm:install [namespace] [channel] [source] [--approval=Automatic|Manual] [--version v0] +``` + +### Steps + +1. **Parse v0 Arguments**: + - `$1`: Operator name (required) - e.g., "openshift-cert-manager-operator" + - `$2`: Namespace (optional) - defaults to `{operator-name}` + - `$3`: Channel (optional) - auto-discovered from PackageManifest if not provided + - `$4`: Source (optional) - defaults to "redhat-operators" + - `--approval=Automatic|Manual`: InstallPlan approval mode (default: Automatic) + - `--version v0`: OLM version (optional if context is set) 2. **Prerequisites Check**: - - Verify `oc` CLI is installed: `which oc` - - Verify cluster access: `oc whoami` - - Check if user has cluster-admin or sufficient privileges - - If not installed or not authenticated, provide clear instructions + ```bash + # Verify oc CLI is installed + if ! command -v oc &> /dev/null; then + echo "❌ 'oc' command not found" + echo "Install from: https://docs.openshift.com/container-platform/latest/cli_reference/openshift_cli/getting-started-cli.html" + exit 1 + fi + + # Verify cluster access + if ! oc whoami &> /dev/null; then + echo "❌ Not logged in to OpenShift cluster" + echo "Run: oc login " + exit 1 + fi + ``` 3. **Discover Operator Metadata** (if channel or source not provided): - - Search for the operator in available catalogs: - ```bash - oc get packagemanifests -n openshift-marketplace | grep {operator-name} - ``` - - Get the PackageManifest details: - ```bash - oc get packagemanifest {operator-name} -n openshift-marketplace -o json - ``` - - Extract: - - Default channel: `.status.defaultChannel` - - CatalogSource: `.status.catalogSource` - - CatalogSourceNamespace: `.status.catalogSourceNamespace` - - If operator not found, provide error with list of available operators + ```bash + # Search for operator + oc get packagemanifests -n openshift-marketplace | grep {operator-name} + + # Get PackageManifest details + oc get packagemanifest {operator-name} -n openshift-marketplace -o json + + # Extract metadata + DEFAULT_CHANNEL=$(oc get packagemanifest {operator-name} -n openshift-marketplace -o jsonpath='{.status.defaultChannel}') + CATALOG_SOURCE=$(oc get packagemanifest {operator-name} -n openshift-marketplace -o jsonpath='{.status.catalogSource}') + CATALOG_SOURCE_NS=$(oc get packagemanifest {operator-name} -n openshift-marketplace -o jsonpath='{.status.catalogSourceNamespace}') + ``` 4. **Create Namespace**: - - Check if namespace exists: `oc get namespace {namespace} --ignore-not-found` - - If not exists, create it: - ```bash + ```bash + # Check if namespace exists + if ! oc get namespace {namespace} &> /dev/null; then oc create namespace {namespace} - ``` - - If exists, inform user and continue + echo "βœ“ Created namespace: {namespace}" + else + echo "ℹ️ Namespace already exists: {namespace}" + fi + ``` 5. **Create OperatorGroup**: - - Check if OperatorGroup exists in the namespace: - ```bash - oc get operatorgroup -n {namespace} --ignore-not-found - ``` - - If no OperatorGroup exists, create one: - ```yaml - apiVersion: operators.coreos.com/v1 - kind: OperatorGroup - metadata: - name: {namespace}-operatorgroup - namespace: {namespace} - spec: - targetNamespaces: - - {namespace} - ``` - - Save to temporary file and apply: - ```bash - oc apply -f /tmp/operatorgroup-{operator-name}.yaml - ``` - - If OperatorGroup already exists, inform user and continue + ```bash + # Check if OperatorGroup exists + OG_EXISTS=$(oc get operatorgroup -n {namespace} --no-headers 2>/dev/null | wc -l) + + if [ "$OG_EXISTS" -eq 0 ]; then + cat </dev/null | grep {operator-name} | awk '{print $1}' | head -1) + if [ -n "$CSV_NAME" ]; then + CSV_PHASE=$(oc get csv $CSV_NAME -n {namespace} -o jsonpath='{.status.phase}') + if [ "$CSV_PHASE" == "Succeeded" ]; then + break + fi + fi + sleep 10 + done + ``` 8. **Display Results**: - - Show the installed operator's CSV name and version - - Show the operator deployment status: - ```bash + ```bash + if [ "$CSV_PHASE" == "Succeeded" ]; then + echo "βœ“ Operator installed successfully" + echo "" + echo "CSV: $CSV_NAME" + echo "Status: $CSV_PHASE" + echo "Namespace: {namespace}" + echo "" oc get deployments -n {namespace} - ``` - - List any pods created by the operator: - ```bash + echo "" oc get pods -n {namespace} - ``` - - Display success message with next steps or usage instructions + else + echo "⚠️ Installation may still be in progress" + echo "Check status with: /olm:status {operator-name} {namespace}" + fi + ``` -9. **Cleanup Temporary Files**: - - Remove temporary YAML files created during installation: - ```bash - rm -f /tmp/operatorgroup-{operator-name}.yaml /tmp/subscription-{operator-name}.yaml - ``` +--- -## Return Value -- **Success**: Operator installed successfully with details about the CSV, deployments, and pods -- **Error**: Installation failed with specific error message and troubleshooting suggestions -- **Format**: Structured output showing: - - Namespace created/used - - OperatorGroup status - - Subscription created - - CSV status and version - - Deployment and pod status +## OLM v1 Implementation -## Examples +Used when `--version v1` or context is set to v1. -1. **Install cert-manager-operator with defaults**: - ``` - /olm:install openshift-cert-manager-operator - ``` - This will: - - Create namespace `cert-manager-operator` - - Discover default channel from PackageManifest - - Use `redhat-operators` catalog source - - Install the operator +### Synopsis (v1) +``` +/olm:install [--channel ] [--version ] [--catalog ] [--namespace ] [--version v1] +``` -2. **Install cert-manager-operator with custom namespace**: - ``` - /olm:install openshift-cert-manager-operator my-cert-manager - ``` - This will install the operator in the `my-cert-manager` namespace. +### Steps -3. **Install with specific channel**: - ``` - /olm:install openshift-cert-manager-operator cert-manager-operator stable-v1 - ``` - This will install from the `stable-v1` channel. +1. **Parse v1 Arguments**: + - `$1`: Extension name (required) - e.g., "cert-manager" + - `--channel `: Channel to track (optional) + - `--version `: Version constraint (optional, e.g., "1.14.5" or ">=1.14.0 <1.15.0") + - `--catalog `: ClusterCatalog name (optional, auto-detected if not specified) + - `--namespace `: Target namespace (required for installation) + - `--version v1`: OLM version (optional if context is set) + + Note: Either `--channel` OR `--version` should be specified, not both. -4. **Install from community catalog**: +2. **Prerequisites Check**: + ```bash + # Verify kubectl CLI is installed + if ! command -v kubectl &> /dev/null; then + echo "❌ 'kubectl' command not found" + echo "Install from: https://kubernetes.io/docs/tasks/tools/" + exit 1 + fi + + # Verify cluster access + if ! kubectl auth can-i get clusterextensions &> /dev/null; then + echo "❌ Cannot access cluster or insufficient permissions" + exit 1 + fi + + # Check if OLM v1 is installed + if ! kubectl get namespace olmv1-system &> /dev/null; then + echo "❌ OLM v1 not installed in this cluster" + echo "Install from: https://operator-framework.github.io/operator-controller/" + exit 1 + fi ``` - /olm:install prometheus community-operators stable community-operators + +3. **Check operator-controller Feature Gates**: + ```bash + echo "Checking operator-controller configuration..." + + FEATURE_GATES=$(kubectl get deployment operator-controller-controller-manager -n olmv1-system \ + -o jsonpath='{.spec.template.spec.containers[0].args}' | grep -o 'feature-gates=[^"]*' || echo "none") + + echo "Feature gates: $FEATURE_GATES" + + # Check if webhook support is enabled + if [[ "$FEATURE_GATES" != *"WebhookProviderCertManager"* ]] && [[ "$FEATURE_GATES" != *"WebhookProviderOpenshiftServiceCA"* ]]; then + echo "⚠️ Webhook support not enabled - operators with webhooks will fail" + echo "To enable: kubectl patch deployment operator-controller-controller-manager -n olmv1-system --type=json \\" + echo " -p='[{\"op\": \"add\", \"path\": \"/spec/template/spec/containers/0/args/-\", \"value\": \"--feature-gates=WebhookProviderCertManager=true\"}]'" + fi ``` - This will install Prometheus from the community-operators catalog. -5. **Install Red Hat Advanced Cluster Security**: +4. **Validate Extension Exists**: + ```bash + echo "Searching for extension: {extension-name}" + + # If catalog specified, search only that catalog + if [ -n "{catalog}" ]; then + FOUND=$(kubectl get packages -A -l catalog={catalog} | grep {extension-name} || true) + else + # Search all catalogs + FOUND=$(kubectl get packages -A | grep {extension-name} || true) + fi + + if [ -z "$FOUND" ]; then + echo "❌ Extension not found: {extension-name}" + echo "Search for available extensions: /olm:search {extension-name} --version v1" + exit 1 + fi + + echo "βœ“ Extension found in catalog" ``` - /olm:install rhacs-operator rhacs-operator stable + +5. **Create Namespace**: + ```bash + if ! kubectl get namespace {namespace} &> /dev/null; then + kubectl create namespace {namespace} + echo "βœ“ Created namespace: {namespace}" + else + echo "ℹ️ Namespace already exists: {namespace}" + fi ``` -6. **Install with manual approval mode**: +6. **Create ServiceAccount**: + ```bash + SA_NAME="{extension-name}-sa" + + kubectl create serviceaccount $SA_NAME -n {namespace} --dry-run=client -o yaml | kubectl apply -f - + echo "βœ“ Created ServiceAccount: $SA_NAME" ``` - /olm:install openshift-cert-manager-operator cert-manager-operator stable-v1 redhat-operators --approval=Manual + +7. **Create Baseline ClusterRole with RBAC**: + ```bash + cat </dev/null || echo "Unknown") + PROGRESSING=$(kubectl get clusterextension {extension-name} -o jsonpath='{.status.conditions[?(@.type=="Progressing")].status}' 2>/dev/null || echo "Unknown") + + if [ "$STATUS" == "True" ]; then + echo "βœ“ Installation completed successfully" + break + fi + + # Check for errors + ERROR_MSG=$(kubectl get clusterextension {extension-name} -o jsonpath='{.status.conditions[?(@.type=="Progressing")].message}' 2>/dev/null || echo "") + + # Check for webhook errors + if [[ "$ERROR_MSG" == *"webhookDefinitions are not supported"* ]]; then + echo "" + echo "❌ Webhook support required but not enabled" + echo "" + echo "This extension requires webhooks. Enable the feature gate:" + echo " kubectl patch deployment operator-controller-controller-manager -n olmv1-system --type=json \\" + echo " -p='[{\"op\": \"add\", \"path\": \"/spec/template/spec/containers/0/args/-\", \"value\": \"--feature-gates=WebhookProviderCertManager=true\"}]'" + echo "" + echo "Then trigger reconciliation:" + echo " kubectl annotate clusterextension {extension-name} reconcile=\"\$(date +%s)\" --overwrite" + exit 1 + fi + + # Check for RBAC errors + if [[ "$ERROR_MSG" == *"pre-authorization failed"* ]]; then + echo "" + echo "⚠️ RBAC permission issues detected" + echo "" + echo "$ERROR_MSG" + echo "" + echo "Missing permissions need to be added to the ClusterRole." + echo "Use: /olm:fix-rbac {extension-name} --version v1" + echo "" + # Don't exit, continue monitoring in case of auto-fix + fi + + sleep 5 + done + ``` + +11. **Display Results**: + ```bash + echo "" + echo "═══════════════════════════════════════════════════════════════" + echo "Installation Summary" + echo "═══════════════════════════════════════════════════════════════" + echo "" + + # Get resolved version + RESOLVED_VERSION=$(kubectl get clusterextension {extension-name} -o jsonpath='{.status.resolution.bundle.version}') + RESOLVED_CHANNEL=$(kubectl get clusterextension {extension-name} -o jsonpath='{.status.resolution.bundle.channel}') + + echo "Extension: {extension-name}" + echo "Version: $RESOLVED_VERSION" + echo "Channel: $RESOLVED_CHANNEL" + echo "Namespace: {namespace}" + echo "ServiceAccount: $SA_NAME" + echo "ClusterRole: {extension-name}-installer" + echo "" + + # Show CRDs + echo "Custom Resource Definitions:" + kubectl get crds -l operators.coreos.com/clusterextension={extension-name} --no-headers 2>/dev/null | awk '{print " - " $1}' + echo "" + + # Show workloads + echo "Workloads in {namespace}:" + kubectl get deployments,statefulsets,daemonsets -n {namespace} --no-headers 2>/dev/null | awk '{print " - " $1 " (" $2 ")"}' + echo "" + + echo "Next steps:" + echo " - Check status: /olm:status {extension-name} --version v1" + echo " - List all extensions: /olm:list --version v1" + ``` + +--- + +## Return Value + +### OLM v0 +- **Success**: Operator installed with CSV in Succeeded state +- **Format**: + - Namespace created/used + - OperatorGroup status + - Subscription created + - CSV status and version + - Deployment and pod status + +### OLM v1 +- **Success**: Extension installed with ClusterExtension in Installed state +- **Format**: + - Namespace created/used + - ServiceAccount and RBAC created + - ClusterExtension status + - Resolved version and channel + - CRDs and workloads + +## Examples + +### Example 1: Install with OLM v0 (using context) + +```bash +# Set context once +/olm:use-version v0 + +# Install operator with defaults +/olm:install openshift-cert-manager-operator + +# Install with custom namespace and channel +/olm:install external-secrets-operator eso-operator stable-v0.10 +``` + +### Example 2: Install with OLM v1 (using flag) + +```bash +# Install extension with explicit version flag +/olm:install cert-manager --version v1 --channel stable --namespace cert-manager + +# Install with specific version constraint +/olm:install postgres-operator --version v1 --version ">=1.0.0 <2.0.0" --namespace postgres +``` + +### Example 3: Mixed workflow + +```bash +# Set default to v0 +/olm:use-version v0 + +# Install v0 operator (uses context) +/olm:install openshift-pipelines-operator + +# Install v1 extension (override with flag) +/olm:install argocd --version v1 --channel stable --namespace argocd +``` + +### Example 4: Manual approval mode (v0 only) + +```bash +/olm:install prometheus --version v0 --approval=Manual +# Then later approve with: /olm:approve prometheus +``` + ## Arguments -- **$1** (operator-name): The name of the operator to install (required) - - Example: "openshift-cert-manager-operator" - - Must match the name in the operator's PackageManifest -- **$2** (namespace): Target namespace for the operator installation (optional) - - Default: `{operator-name}` (operator name without "openshift-" prefix if present) - - Example: "cert-manager-operator" -- **$3** (channel): Subscription channel (optional) - - Default: Auto-discovered from PackageManifest's default channel - - Example: "stable-v1", "tech-preview", "stable" -- **$4** (source): CatalogSource name (optional) - - Default: "redhat-operators" - - Other options: "certified-operators", "community-operators", "redhat-marketplace" -- **$5+** (flags): Optional flags - - `--approval=Automatic|Manual`: InstallPlan approval mode - - **Automatic** (default): Operator upgrades are automatically installed without user intervention - - **Manual**: Operator upgrades require explicit approval. Useful for: - - Production environments requiring change control - - Testing upgrades before applying - - Preventing unexpected operator updates - - Reference: https://docs.redhat.com/en/documentation/openshift_container_platform/4.20/html/operators/administrator-tasks#olm-approving-operator-upgrades_olm-updating-operators + +### Common +- **--version v0|v1**: OLM version to use (optional if context is set) + +### OLM v0 Specific +- **$1** (operator-name): Name of the operator (required) +- **$2** (namespace): Target namespace (optional, defaults to operator name) +- **$3** (channel): Subscription channel (optional, auto-discovered) +- **$4** (source): CatalogSource name (optional, defaults to "redhat-operators") +- **--approval=Automatic|Manual**: InstallPlan approval mode (default: Automatic) + +### OLM v1 Specific +- **$1** (extension-name): Name of the extension (required) +- **--channel **: Channel to track (optional, conflicts with --version) +- **--version **: Version constraint (optional, conflicts with --channel) +- **--catalog **: ClusterCatalog name (optional, auto-detected) +- **--namespace **: Target namespace (required) ## Notes -- **Automatic Channel Discovery**: If no channel is specified, the command automatically discovers and uses the operator's default channel from its PackageManifest -- **Namespace Convention**: By default, operators are installed in a namespace following the pattern `{operator-name}-operator` -- **OperatorGroup Scope**: The created OperatorGroup targets only the installation namespace for better isolation -- **InstallPlan Approval**: Set to "Automatic" by default for seamless installation. Can be changed to "Manual" using `--approval=Manual` flag -- **Manual Approval Mode**: When using `--approval=Manual`: - - Initial installation may require manual approval of the InstallPlan - - All future upgrades will require explicit approval via `/olm:approve` command - - Provides better control over operator updates in production environments -- **Verification Timeout**: The command waits up to 5 minutes for the operator to install successfully (10 minutes for manual approval mode) -- **Cleanup**: Temporary YAML files are automatically removed after installation - -## Troubleshooting - -- **Operator not found**: Run `oc get packagemanifests -n openshift-marketplace` to see available operators -- **Permission denied**: Ensure you have cluster-admin privileges or the necessary RBAC permissions -- **Installation timeout**: Check the InstallPlan and CSV status manually: - ```bash - oc get installplan -n {namespace} - oc get csv -n {namespace} - oc describe csv -n {namespace} - ``` -- **Operator pod not starting**: Check pod logs: - ```bash - oc logs -n {namespace} deployment/{operator-deployment} - ``` +### OLM v0 Notes +- Namespace convention: Defaults to `{operator-name}` +- OperatorGroup is automatically created if none exists +- InstallPlan approval can be Automatic or Manual +- Verification timeout: 5 minutes + +### OLM v1 Notes +- **CRITICAL**: User must provide ServiceAccount with RBAC (unlike v0 which has cluster-admin) +- Baseline RBAC is created but may need additional permissions +- If preflight checks fail, use `/olm:fix-rbac` to add missing permissions +- Webhook support requires feature gate enabled +- Either specify `--channel` OR `--version`, not both +- Version constraints support semver ranges (e.g., ">=1.0.0 <2.0.0", "~1.14.0") +### Common Notes +- Use `/olm:detect-version` if unsure which OLM version is installed +- Use `/olm:use-version` to set context and avoid repeating --version flag +- Flag always overrides context +- No default version - must be explicitly specified diff --git a/plugins/olm/commands/list.md b/plugins/olm/commands/list.md index f93abae..383bebb 100644 --- a/plugins/olm/commands/list.md +++ b/plugins/olm/commands/list.md @@ -1,6 +1,6 @@ --- -description: List installed operators in the cluster -argument-hint: [namespace] [--all-namespaces] +description: List installed operators (v0) or extensions (v1) in the cluster +argument-hint: [namespace] [--all-namespaces] [--version v0|v1] --- ## Name @@ -8,167 +8,445 @@ olm:list ## Synopsis ``` -/olm:list [namespace] [--all-namespaces] +/olm:list [namespace] [--all-namespaces] [--version v0|v1] ``` ## Description -The `olm:list` command lists all installed operators in an OpenShift cluster, showing their status, version, and namespace. This command provides a quick overview of the operator landscape in your cluster. +The `olm:list` command lists all installed operators (OLM v0) or extensions (OLM v1) in your cluster, showing their status, version, and location. This provides a quick overview of what's currently installed. -This command helps you: -- Discover what operators are currently installed -- Check operator versions and status at a glance -- Identify operators that may need attention (failed, upgrading, etc.) -- Get a comprehensive view across namespaces +**You must explicitly specify which OLM version to use** via: +- `--version` flag on this command, OR +- Setting the context with `/olm:use-version v0|v1` -The command presents information in an easy-to-read table format with key details about each operator's ClusterServiceVersion (CSV) and Subscription. +**OLM v0:** Lists ClusterServiceVersions (CSVs) and their associated Subscriptions + +**OLM v1:** Lists ClusterExtensions and their status ## Implementation -The command performs the following steps: +### 1. Determine OLM Version + +**See [skills/version-detection/SKILL.md](../../skills/version-detection/SKILL.md) for complete logic.** + +### 2. Branch to Version-Specific Implementation + +--- + +## OLM v0 Implementation + +### Synopsis (v0) +``` +/olm:list [namespace] [--all-namespaces|-A] [--version v0] +``` + +### Steps -1. **Parse Arguments**: - - `$1`: Namespace (optional) - Target namespace to list operators from - - `$2`: Flag (optional): - - `--all-namespaces` or `-A`: List operators across all namespaces (default behavior if no namespace specified) +1. **Parse v0 Arguments**: + - `$1`: Namespace (optional) - if provided, list only operators in this namespace + - `--all-namespaces` or `-A`: List operators across all namespaces (default if no namespace) + - `--version v0`: OLM version (optional if context is set) 2. **Prerequisites Check**: - - Verify `oc` CLI is installed: `which oc` - - Verify cluster access: `oc whoami` - - If not installed or not authenticated, provide clear instructions + ```bash + if ! command -v oc &> /dev/null; then + echo "❌ 'oc' command not found" + exit 1 + fi + + if ! oc whoami &> /dev/null; then + echo "❌ Not logged in to cluster" + exit 1 + fi + ``` 3. **Determine Scope**: - - If namespace is specified: List operators only in that namespace - - If `--all-namespaces` flag or no arguments: List operators cluster-wide - - Default behavior: Show all operators across all namespaces - -4. **Fetch Operator Data**: - - Get all ClusterServiceVersions (CSVs): - ```bash - # For specific namespace - oc get csv -n {namespace} -o json + ```bash + if [ -n "{namespace}" ]; then + SCOPE_FLAG="-n {namespace}" + echo "Listing operators in namespace: {namespace}" + else + SCOPE_FLAG="--all-namespaces" + echo "Listing operators across all namespaces" + fi + ``` + +4. **Fetch CSV Data**: + ```bash + # Get all CSVs in scope + CSVS=$(oc get csv $SCOPE_FLAG -o json 2>/dev/null) + + # Check if any CSVs found + CSV_COUNT=$(echo "$CSVS" | jq '.items | length') + if [ "$CSV_COUNT" -eq 0 ]; then + echo "No operators found" + exit 0 + fi + ``` + +5. **Fetch Subscription Data**: + ```bash + # Get all Subscriptions in scope + SUBS=$(oc get subscription $SCOPE_FLAG -o json 2>/dev/null) + ``` + +6. **Process and Display**: + ```bash + echo "" + echo "Installed Operators:" + echo "" + printf "%-40s %-20s %-15s %-15s %-20s\n" "NAME" "NAMESPACE" "VERSION" "STATUS" "CHANNEL" + echo "────────────────────────────────────────────────────────────────────────────────────────────────────────" + + # Process each CSV + echo "$CSVS" | jq -r '.items[] | + [.metadata.name, + .metadata.namespace, + .spec.version, + .status.phase, + (.metadata.namespace + "/" + .spec.displayName)] | + @tsv' | while IFS=$'\t' read -r name namespace version phase display; do + + # Get subscription info for this CSV + CHANNEL=$(echo "$SUBS" | jq -r --arg ns "$namespace" --arg csv "$name" \ + '.items[] | select(.metadata.namespace==$ns and .status.installedCSV==$csv) | .spec.channel' 2>/dev/null || echo "unknown") - # For all namespaces - oc get csv --all-namespaces -o json - ``` - - Get all Subscriptions: - ```bash - # For specific namespace - oc get subscription -n {namespace} -o json + # Format status with emoji + case "$phase" in + Succeeded) + STATUS="βœ“ $phase" + ;; + Installing|Pending) + STATUS="⏳ $phase" + ;; + Failed|Replacing) + STATUS="βœ— $phase" + ;; + *) + STATUS="$phase" + ;; + esac - # For all namespaces - oc get subscription --all-namespaces -o json - ``` - -5. **Parse and Correlate Data**: - - For each CSV, extract: - - Name: `.metadata.name` - - Namespace: `.metadata.namespace` - - Display Name: `.spec.displayName` - - Version: `.spec.version` - - Phase/Status: `.status.phase` (e.g., "Succeeded", "Installing", "Failed") - - Install Time: `.metadata.creationTimestamp` - - For each Subscription, extract: - - Operator Name: `.spec.name` - - Channel: `.spec.channel` - - Source: `.spec.source` - - Installed CSV: `.status.installedCSV` - - Current CSV: `.status.currentCSV` - - Correlate Subscriptions with CSVs to show complete operator information - -6. **Format Output as Table**: - Create a formatted table with columns: + printf "%-40s %-20s %-15s %-15s %-20s\n" \ + "${name:0:38}" \ + "${namespace:0:18}" \ + "${version:0:13}" \ + "$STATUS" \ + "${CHANNEL:0:18}" + done ``` - NAMESPACE OPERATOR NAME VERSION STATUS CHANNEL SOURCE - cert-manager-operator cert-manager-operator v1.13.1 Succeeded stable-v1 redhat-operators - external-secrets-operator external-secrets-operator v0.10.5 Succeeded stable-v0.10 redhat-operators - openshift-pipelines openshift-pipelines-operator-rh v1.14.4 Succeeded latest redhat-operators + +7. **Display Summary**: + ```bash + echo "" + echo "────────────────────────────────────────────────────────────────────────────────────────────────────────" + + # Count by status + SUCCEEDED=$(echo "$CSVS" | jq '[.items[] | select(.status.phase=="Succeeded")] | length') + INSTALLING=$(echo "$CSVS" | jq '[.items[] | select(.status.phase=="Installing" or .status.phase=="Pending")] | length') + FAILED=$(echo "$CSVS" | jq '[.items[] | select(.status.phase=="Failed")] | length') + + echo "Total: $CSV_COUNT operators ($SUCCEEDED healthy, $INSTALLING installing, $FAILED failed)" + + # Show operators needing attention + if [ "$FAILED" -gt 0 ] || [ "$INSTALLING" -gt 0 ]; then + echo "" + echo "Operators requiring attention:" + + if [ "$FAILED" -gt 0 ]; then + echo "" + echo "Failed operators:" + echo "$CSVS" | jq -r '.items[] | select(.status.phase=="Failed") | + " - " + .metadata.name + " in " + .metadata.namespace' + echo " Check with: /olm:status --version v0" + fi + + if [ "$INSTALLING" -gt 0 ]; then + echo "" + echo "Installing operators:" + echo "$CSVS" | jq -r '.items[] | select(.status.phase=="Installing" or .status.phase=="Pending") | + " - " + .metadata.name + " in " + .metadata.namespace' + fi + fi ``` -7. **Add Summary Statistics**: - - Total operators installed: X - - By status: - - Succeeded: X - - Installing: X - - Upgrading: X - - Failed: X - - By catalog source: - - redhat-operators: X - - certified-operators: X - - community-operators: X - - custom catalogs: X - -8. **Highlight Issues** (if any): - - List operators with status other than "Succeeded": - ``` - ⚠️ Operators requiring attention: - - namespace/operator-name: Failed (reason: ...) - - namespace/operator-name: Installing (waiting for...) - ``` - -9. **Provide Actionable Suggestions**: - - If operators are in "Failed" state, suggest: `/olm:status {operator-name} {namespace}` for details - - If no operators found, suggest: `/olm:search {operator-name}` to find available operators - - If upgrades available, suggest: `/olm:status {operator-name}` to check upgrade options +--- -## Return Value -- **Success**: Formatted table of installed operators with summary statistics -- **Empty**: No operators found message with suggestion to install operators -- **Error**: Connection or permission error with troubleshooting guidance -- **Format**: - - Table with columns: NAMESPACE, OPERATOR NAME, VERSION, STATUS, CHANNEL, SOURCE - - Summary statistics - - Warnings for operators requiring attention +## OLM v1 Implementation -## Examples +### Synopsis (v1) +``` +/olm:list [--all-namespaces|-A] [--version v1] +``` + +### Steps + +1. **Parse v1 Arguments**: + - `--all-namespaces` or `-A`: Show namespace information for each extension (informational, ClusterExtensions are cluster-scoped) + - `--version v1`: OLM version (optional if context is set) + +2. **Prerequisites Check**: + ```bash + if ! command -v kubectl &> /dev/null; then + echo "❌ 'kubectl' command not found" + exit 1 + fi + + if ! kubectl auth can-i get clusterextensions &> /dev/null; then + echo "❌ Cannot access cluster" + exit 1 + fi + + if ! kubectl get namespace olmv1-system &> /dev/null; then + echo "❌ OLM v1 not installed" + exit 1 + fi + ``` -1. **List all operators cluster-wide**: +3. **Fetch ClusterExtension Data**: + ```bash + echo "Listing installed extensions" + echo "" + + EXTENSIONS=$(kubectl get clusterextensions -o json 2>/dev/null) + + EXT_COUNT=$(echo "$EXTENSIONS" | jq '.items | length') + if [ "$EXT_COUNT" -eq 0 ]; then + echo "No extensions found" + echo "" + echo "Install an extension: /olm:install --version v1 --channel --namespace " + exit 0 + fi ``` - /olm:list + +4. **Display ClusterExtensions**: + ```bash + echo "Installed Extensions:" + echo "" + printf "%-30s %-20s %-15s %-15s %-25s\n" "NAME" "NAMESPACE" "VERSION" "STATUS" "CHANNEL" + echo "─────────────────────────────────────────────────────────────────────────────────────────────────────" + + echo "$EXTENSIONS" | jq -r '.items[] | + { + name: .metadata.name, + namespace: .spec.namespace, + version: .status.resolution.bundle.version // "unknown", + channel: .status.resolution.bundle.channel // "unknown", + installed: (.status.conditions[] | select(.type=="Installed") | .status), + progressing: (.status.conditions[] | select(.type=="Progressing") | .status) + } | + [.name, .namespace, .version, (.installed // "unknown"), .channel] | + @tsv' | while IFS=$'\t' read -r name namespace version installed channel; do + + # Determine status + if [ "$installed" == "True" ]; then + STATUS="βœ“ Installed" + elif [ "$installed" == "False" ]; then + # Check if progressing + PROGRESSING=$(echo "$EXTENSIONS" | jq -r --arg name "$name" \ + '.items[] | select(.metadata.name==$name) | + (.status.conditions[] | select(.type=="Progressing") | .status)') + + if [ "$PROGRESSING" == "True" ]; then + STATUS="⏳ Installing" + else + STATUS="βœ— Failed" + fi + else + STATUS="❓ Unknown" + fi + + printf "%-30s %-20s %-15s %-15s %-25s\n" \ + "${name:0:28}" \ + "${namespace:0:18}" \ + "${version:0:13}" \ + "$STATUS" \ + "${channel:0:23}" + done ``` -2. **List operators in a specific namespace**: +5. **Display Summary and Issues**: + ```bash + echo "" + echo "─────────────────────────────────────────────────────────────────────────────────────────────────────" + + # Count by status + INSTALLED=$(echo "$EXTENSIONS" | jq '[.items[] | select((.status.conditions[] | select(.type=="Installed") | .status) == "True")] | length') + PROGRESSING=$(echo "$EXTENSIONS" | jq '[.items[] | select((.status.conditions[] | select(.type=="Progressing") | .status) == "True")] | length') + FAILED=$(echo "$EXTENSIONS" | jq '[.items[] | select( + ((.status.conditions[] | select(.type=="Installed") | .status) == "False") and + ((.status.conditions[] | select(.type=="Progressing") | .status) != "True") + )] | length') + + echo "Total: $EXT_COUNT extensions ($INSTALLED installed, $PROGRESSING installing, $FAILED failed)" + + # Show extensions needing attention + if [ "$FAILED" -gt 0 ] || [ "$PROGRESSING" -gt 0 ]; then + echo "" + echo "Extensions requiring attention:" + + if [ "$FAILED" -gt 0 ]; then + echo "" + echo "Failed extensions:" + echo "$EXTENSIONS" | jq -r '.items[] | + select(((.status.conditions[] | select(.type=="Installed") | .status) == "False") and + ((.status.conditions[] | select(.type=="Progressing") | .status) != "True")) | + " - " + .metadata.name + + " (Reason: " + ((.status.conditions[] | select(.type=="Progressing") | .reason) // "unknown") + ")"' + echo "" + echo " Check with: /olm:status --version v1" + echo " Fix RBAC: /olm:fix-rbac --version v1" + fi + + if [ "$PROGRESSING" -gt 0 ]; then + echo "" + echo "Installing extensions:" + echo "$EXTENSIONS" | jq -r '.items[] | + select((.status.conditions[] | select(.type=="Progressing") | .status) == "True") | + " - " + .metadata.name' + fi + fi + + # Check for RBAC or webhook issues + HAS_RBAC_ISSUES=$(echo "$EXTENSIONS" | jq '[.items[] | + select(.status.conditions[] | select(.message | contains("pre-authorization failed")))] | length') + + HAS_WEBHOOK_ISSUES=$(echo "$EXTENSIONS" | jq '[.items[] | + select(.status.conditions[] | select(.message | contains("webhookDefinitions are not supported")))] | length') + + if [ "$HAS_RBAC_ISSUES" -gt 0 ]; then + echo "" + echo "⚠️ $HAS_RBAC_ISSUES extension(s) have RBAC permission issues" + echo " Use /olm:fix-rbac to automatically resolve" + fi + + if [ "$HAS_WEBHOOK_ISSUES" -gt 0 ]; then + echo "" + echo "⚠️ $HAS_WEBHOOK_ISSUES extension(s) require webhook support" + echo " Enable: kubectl patch deployment operator-controller-controller-manager -n olmv1-system --type=json \\" + echo " -p='[{\"op\": \"add\", \"path\": \"/spec/template/spec/containers/0/args/-\", \"value\": \"--feature-gates=WebhookProviderCertManager=true\"}]'" + fi ``` - /olm:list cert-manager-operator - `` + +--- + +## Return Value + +### OLM v0 +- **Format**: Table with columns: NAME, NAMESPACE, VERSION, STATUS, CHANNEL +- **Summary**: Count of operators by status (healthy, installing, failed) +- **Alerts**: List of operators requiring attention + +### OLM v1 +- **Format**: Table with columns: NAME, NAMESPACE, VERSION, STATUS, CHANNEL +- **Summary**: Count of extensions by status (installed, installing, failed) +- **Alerts**: RBAC issues, webhook issues, failed installations + +## Examples + +### Example 1: List all operators (v0 with context) + +```bash +/olm:use-version v0 +/olm:list +``` + +Output: +``` +Listing operators across all namespaces + +Installed Operators: + +NAME NAMESPACE VERSION STATUS CHANNEL +cert-manager-operator.v1.14.0 cert-manager 1.14.0 βœ“ Succeeded stable-v1 +external-secrets-operator.v0.10.0 eso-operator 0.10.0 βœ“ Succeeded stable-v0.10 +prometheus.v2.45.0 monitoring 2.45.0 ⏳ Installing beta + +──────────────────────────────────────────────────────────────────────────────────────────────────────── +Total: 3 operators (2 healthy, 1 installing, 0 failed) + +Installing operators: + - prometheus.v2.45.0 in monitoring +``` + +### Example 2: List extensions (v1 with flag) + +```bash +/olm:list --version v1 +``` + +Output: +``` +Listing installed extensions + +Installed Extensions: + +NAME NAMESPACE VERSION STATUS CHANNEL +cert-manager cert-manager 1.14.5 βœ“ Installed stable +argocd argocd 2.10.0 βœ“ Installed stable +postgres-operator postgres 1.2.0 βœ— Failed stable + +───────────────────────────────────────────────────────────────────────────────────────────────────── +Total: 3 extensions (2 installed, 0 installing, 1 failed) + +Failed extensions: + - postgres-operator (Reason: PreAuthorizationFailed) + + Check with: /olm:status postgres-operator --version v1 + Fix RBAC: /olm:fix-rbac postgres-operator --version v1 + +⚠️ 1 extension(s) have RBAC permission issues + Use /olm:fix-rbac to automatically resolve +``` + +### Example 3: List operators in specific namespace (v0) + +```bash +/olm:list cert-manager-operator --version v0 +``` + +Output: +``` +Listing operators in namespace: cert-manager-operator + +Installed Operators: + +NAME NAMESPACE VERSION STATUS CHANNEL +cert-manager-operator.v1.14.0 cert-manager 1.14.0 βœ“ Succeeded stable-v1 + +──────────────────────────────────────────────────────────────────────────────────────────────────────── +Total: 1 operators (1 healthy, 0 installing, 0 failed) +``` ## Arguments -- **$1** (namespace): Target namespace to list operators from (optional) - - If not provided, lists operators from all namespaces - - Example: "cert-manager-operator" -- **$2** (flag): Optional flag (optional) - - `--all-namespaces` or `-A`: Explicitly list all operators cluster-wide - - Default behavior if no namespace is provided + +### Common +- **--version v0|v1**: OLM version to use (optional if context is set) + +### OLM v0 Specific +- **$1** (namespace): Target namespace (optional, defaults to all namespaces) +- **--all-namespaces** or **-A**: Explicitly list across all namespaces + +### OLM v1 Specific +- **--all-namespaces** or **-A**: Show namespace column (ClusterExtensions are cluster-scoped but have target namespaces) ## Notes -- **Performance**: For large clusters with many operators, the command may take a few seconds to collect all data -- **Status Values**: Common CSV status values include: - - `Succeeded`: Operator is healthy and running - - `Installing`: Operator is being installed - - `Upgrading`: Operator is being upgraded - - `Failed`: Operator installation or operation failed - - `Replacing`: Old version being replaced - - `Deleting`: Operator is being removed -- **Correlation**: The command correlates Subscriptions with CSVs to provide complete operator information -- **Sorting**: Results are sorted by namespace, then by operator name - -## Troubleshooting - -- **Permission denied**: Ensure you have permissions to list CSVs and Subscriptions: - ```bash - oc auth can-i list csv --all-namespaces - oc auth can-i list subscription --all-namespaces - ``` -- **Slow response**: For large clusters, use namespace-specific queries to speed up results -- **Missing operators**: Some operators may not have Subscriptions if installed manually; these will still appear based on CSV presence -- **Version mismatch**: If Subscription's `installedCSV` differs from `currentCSV`, an upgrade may be in progress - -## Related Commands - -- `/olm:status [namespace]` - Get detailed status of a specific operator -- `/olm:install ` - Install a new operator -- `/olm:search ` - Search for available operators in catalogs - -## Additional Resources -- [Operator Lifecycle Manager Documentation](https://olm.operatorframework.io/) +### OLM v0 Notes +- Lists ClusterServiceVersions (CSVs) in the cluster +- Shows associated Subscription channel +- CSV status phases: Succeeded, Installing, Pending, Failed, Replacing +- Default behavior lists all namespaces unless specific namespace provided + +### OLM v1 Notes +- Lists ClusterExtensions (cluster-scoped resources) +- Shows target namespace for each extension +- Extension status based on Installed and Progressing conditions +- Highlights RBAC and webhook issues +- Use `/olm:fix-rbac` for permission issues +- Use `/olm:status` for detailed troubleshooting +### Common Notes +- No default version - must be explicitly specified +- Use `/olm:use-version` to set context +- Flag overrides context +- Empty results suggest either nothing installed or wrong version selected diff --git a/plugins/olm/commands/search.md b/plugins/olm/commands/search.md index 72773c6..98327ab 100644 --- a/plugins/olm/commands/search.md +++ b/plugins/olm/commands/search.md @@ -1,6 +1,6 @@ --- -description: Search for available operators in catalog sources -argument-hint: [query] [--catalog ] +description: Search for available operators (v0) or extensions (v1) in catalogs +argument-hint: [query] [--catalog ] [--version v0|v1] --- ## Name @@ -8,240 +8,228 @@ olm:search ## Synopsis ``` -/olm:search [query] [--catalog ] +/olm:search [query] [--catalog ] [--version v0|v1] ``` ## Description -The `olm:search` command searches for available operators in the cluster's catalog sources (OperatorHub). It helps you discover operators that can be installed, showing their names, descriptions, versions, channels, and catalog sources. +The `olm:search` command searches for available operators (OLM v0) or extensions (OLM v1) in catalog sources, helping you discover what can be installed. -This command helps you: -- Find operators by name, description, or keywords -- Discover what operators are available for installation -- View operator details before installing -- Check available versions and channels -- Identify which catalog source contains a specific operator - -The command searches across all available catalog sources (redhat-operators, certified-operators, community-operators, redhat-marketplace, and custom catalogs) and presents results in an easy-to-read format. +**You must explicitly specify which OLM version to use** via: +- `--version` flag on this command, OR +- Setting the context with `/olm:use-version v0|v1` ## Implementation -The command performs the following steps: +### 1. Determine OLM Version + +**See [skills/version-detection/SKILL.md](../../skills/version-detection/SKILL.md) for complete logic.** + +### 2. Branch to Version-Specific Implementation + +--- + +## OLM v0 Implementation + +### Synopsis (v0) +``` +/olm:search [query] [--catalog ] [--exact] [--version v0] +``` + +### Steps 1. **Parse Arguments**: - - `$1`: Query string (optional) - Search term for filtering operators - - If not provided, lists all available operators - - Can be partial name, keyword, or description - - `$2+`: Flags (optional): - - `--catalog `: Limit search to specific catalog source - - `--exact`: Only show exact name matches - - `--installed`: Show only installed operators (combination with /olm:list) - -2. **Prerequisites Check**: - - Verify `oc` CLI is installed: `which oc` - - Verify cluster access: `oc whoami` - - If not installed or not authenticated, provide clear instructions - -3. **Fetch Catalog Data**: - - Get all PackageManifests from openshift-marketplace: - ```bash - oc get packagemanifests -n openshift-marketplace -o json - ``` - - If `--catalog` flag is specified, filter by catalog source: - ```bash - oc get packagemanifests -n openshift-marketplace -o json | jq '.items[] | select(.status.catalogSource=="{catalog-name}")' - ``` - -4. **Parse PackageManifest Data**: - - For each PackageManifest, extract: - - Name: `.metadata.name` - - Display Name: `.status.channels[0].currentCSVDesc.displayName` - - Description: `.status.channels[0].currentCSVDesc.description` - - Provider: `.status.provider.name` - - Catalog Source: `.status.catalogSource` - - Catalog Namespace: `.status.catalogSourceNamespace` - - Default Channel: `.status.defaultChannel` - - All Channels: `.status.channels[].name` - - Latest Version: `.status.channels[] | select(.name==.status.defaultChannel) | .currentCSVDesc.version` - - Categories: `.status.channels[0].currentCSVDesc.annotations["categories"]` - - Capabilities: `.status.channels[0].currentCSVDesc.annotations["capabilities"]` - -5. **Apply Search Filter** (if query provided): - - Case-insensitive search across: - - Operator name (`.metadata.name`) - - Display name (`.status.channels[0].currentCSVDesc.displayName`) - - Description (`.status.channels[0].currentCSVDesc.description`) - - Provider name (`.status.provider.name`) - - Categories - - If `--exact` flag, only match exact operator names - -6. **Sort Results**: - - Primary sort: By catalog source (redhat-operators first, then certified, community, etc.) - - Secondary sort: By operator name alphabetically - -7. **Format Search Results**: - - **A. Summary Header** - ``` - Found X operators matching "{query}" - ``` - - **B. Results List** - For each operator: - ``` - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ - β”‚ cert-manager-operator for Red Hat OpenShift - β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ - β”‚ Name: openshift-cert-manager-operator - β”‚ Provider: Red Hat - β”‚ Catalog: redhat-operators - β”‚ Default: stable-v1 - β”‚ Channels: stable-v1, tech-preview-v1.13 - β”‚ Version: v1.13.1 - β”‚ Categories: Security - β”‚ - β”‚ Description: Manages the lifecycle of TLS certificates... - β”‚ - β”‚ Install: /olm:install openshift-cert-manager-operator - └───────────────────────────────────────────────────────────── + - `$1`: Query string (optional) - search term + - `--catalog `: Filter by specific CatalogSource + - `--exact`: Only exact name matches + - `--version v0`: OLM version + +2. **Fetch PackageManifests**: + ```bash + if [ -n "{catalog}" ]; then + PACKAGES=$(oc get packagemanifests -n openshift-marketplace -o json | \ + jq --arg cat "{catalog}" '.items[] | select(.status.catalogSource==$cat)') + else + PACKAGES=$(oc get packagemanifests -n openshift-marketplace -o json | jq '.items[]') + fi + ``` + +3. **Filter by Query**: + ```bash + if [ -n "{query}" ]; then + if [ "{exact}" == "true" ]; then + PACKAGES=$(echo "$PACKAGES" | jq --arg q "{query}" 'select(.metadata.name==$q)') + else + PACKAGES=$(echo "$PACKAGES" | jq --arg q "{query}" \ + 'select(.metadata.name | test($q; "i")) or + select(.status.channels[0].currentCSVDesc.displayName | test($q; "i")) or + select(.status.channels[0].currentCSVDesc.description | test($q; "i"))') + fi + fi + ``` + +4. **Display Results**: + ```bash + echo "$PACKAGES" | jq -r ' + .metadata.name + "|" + + .status.catalogSource + "|" + + .status.defaultChannel + "|" + + (.status.channels[0].currentCSVDesc.displayName // "N/A") + "|" + + ((.status.channels[0].currentCSVDesc.description // "N/A") | .[0:80])' | \ + while IFS='|' read -r name catalog channel display desc; do + echo "Name: $name" + echo " Catalog: $catalog" + echo " Channel: $channel" + echo " Display: $display" + echo " Description: $desc" + echo "" + echo " Install: /olm:install $name --version v0" + echo "" + done ``` -8. **Group by Catalog** (optional, for better readability): - ``` - ═════════════════════════════════════════════════════════════ - RED HAT OPERATORS (3) - ═════════════════════════════════════════════════════════════ - - [List of operators from redhat-operators] +--- + +## OLM v1 Implementation + +### Synopsis (v1) +``` +/olm:search [query] [--catalog ] [--version v1] +``` + +### Steps + +1. **Parse Arguments**: + - `$1`: Query string (optional) + - `--catalog `: Filter by specific ClusterCatalog + - `--version v1`: OLM version + +2. **Check Prerequisites**: + ```bash + if ! kubectl get namespace olmv1-system &> /dev/null; then + echo "❌ OLM v1 not installed" + exit 1 + fi - ═════════════════════════════════════════════════════════════ - CERTIFIED OPERATORS (1) - ═════════════════════════════════════════════════════════════ + if ! kubectl get service catalogd-service -n olmv1-system &> /dev/null; then + echo "❌ catalogd-service not found" + exit 1 + fi + ``` + +3. **Get ClusterCatalogs**: + ```bash + if [ -n "{catalog}" ]; then + CATALOGS="{catalog}" + else + CATALOGS=$(kubectl get clustercatalogs --no-headers 2>/dev/null | awk '{print $1}') + fi - [List of operators from certified-operators] + if [ -z "$CATALOGS" ]; then + echo "No catalogs found" + echo "Add a catalog: /olm:catalog add --version v1" + exit 0 + fi + ``` + +4. **Set up port forwarding to catalogd**: + ```bash + kubectl -n olmv1-system port-forward svc/catalogd-service 8443:443 & + PORT_FORWARD_PID=$! + sleep 2 - ═════════════════════════════════════════════════════════════ - COMMUNITY OPERATORS (2) - ═════════════════════════════════════════════════════════════ + # Ensure cleanup on exit + trap "kill $PORT_FORWARD_PID 2>/dev/null" EXIT + ``` + +5. **Query each catalog**: + ```bash + for CATALOG in $CATALOGS; do + echo "Searching catalog: $CATALOG" + echo "" + + # Fetch all packages + PACKAGES=$(curl -sk "https://localhost:8443/catalogs/$CATALOG/api/v1/all" | \ + jq -s '.[] | select(.schema == "olm.package")') + + # Filter by query if provided + if [ -n "{query}" ]; then + PACKAGES=$(echo "$PACKAGES" | jq --arg q "{query}" 'select(.name | test($q; "i"))') + fi + + # Display each package + echo "$PACKAGES" | jq -r '.name' | while read -r PKG_NAME; do + # Get package details + PKG_INFO=$(echo "$PACKAGES" | jq --arg name "$PKG_NAME" 'select(.name==$name)') + DEFAULT_CHANNEL=$(echo "$PKG_INFO" | jq -r '.defaultChannel') + DESCRIPTION=$(echo "$PKG_INFO" | jq -r '.description // "N/A"') + + # Get channels + CHANNELS=$(curl -sk "https://localhost:8443/catalogs/$CATALOG/api/v1/all" | \ + jq -s --arg pkg "$PKG_NAME" '.[] | select(.schema == "olm.channel" and .package==$pkg) | .name' | tr '\n' ',' | sed 's/,$//') + + # Get latest version + LATEST_VERSION=$(curl -sk "https://localhost:8443/catalogs/$CATALOG/api/v1/all" | \ + jq -s --arg pkg "$PKG_NAME" --arg ch "$DEFAULT_CHANNEL" \ + '.[] | select(.schema == "olm.channel" and .package==$pkg and .name==$ch) | .entries[0].name' | \ + grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1) + + echo "Name: $PKG_NAME" + echo " Catalog: $CATALOG" + echo " Default Channel: $DEFAULT_CHANNEL" + echo " Available Channels: $CHANNELS" + echo " Latest Version: ${LATEST_VERSION:-unknown}" + echo " Description: ${DESCRIPTION:0:80}" + echo "" + echo " Install: /olm:install $PKG_NAME --version v1 --channel $DEFAULT_CHANNEL --namespace " + echo "" + done + done - [List of operators from community-operators] + # Cleanup + kill $PORT_FORWARD_PID 2>/dev/null ``` -9. **Provide Installation Guidance**: - - For each operator, show ready-to-use install command: - ``` - To install: /olm:install {operator-name} - ``` - - For operators with specific channel recommendations, note them - -10. **Handle No Results**: - - If no operators match the query: - ``` - No operators found matching "{query}" - - Suggestions: - - Try a broader search term - - List all available operators: /olm:search - - Check specific catalog: /olm:search {query} --catalog redhat-operators - ``` - -11. **Show Popular/Recommended Operators** (if no query provided): - - Highlight commonly used operators: - - cert-manager - - external-secrets-operator - - OpenShift Pipelines - - OpenShift GitOps - - Service Mesh - - etc. +--- ## Return Value -- **Success**: List of matching operators with detailed information -- **No Results**: Message indicating no matches with suggestions -- **Error**: Connection or permission error with troubleshooting guidance -- **Format**: - - Summary of search results - - Detailed operator information cards - - Installation commands for each operator - - Grouped by catalog source + +### OLM v0 +- List of matching PackageManifests with install commands + +### OLM v1 +- List of matching packages from ClusterCatalogs with install commands ## Examples -1. **Search for cert-manager operator**: - ``` - /olm:search cert-manager - ``` +### Example 1: Search all operators (v0) -2. **Search for secrets-related operators**: - ``` - /olm:search secrets - ``` - Output listing multiple operators related to secrets management. +```bash +/olm:use-version v0 +/olm:search cert-manager +``` -3. **List all operators** (no query): - ``` - /olm:search - ``` +### Example 2: Search specific catalog (v1) -4. **Search in specific catalog**: - ``` - /olm:search prometheus --catalog community-operators - ``` - Output showing only Prometheus-related operators from community-operators catalog. +```bash +/olm:search postgres --catalog operatorhubio --version v1 +``` -5. **Exact name match**: - ``` - /olm:search external-secrets-operator --exact - ``` - Output showing only the exact match for external-secrets-operator. +### Example 3: List all available (v0) -6. **Search for operators by category** (e.g., security): - ``` - /olm:search security - ``` - Output listing all security-related operators. +```bash +/olm:search --version v0 +``` ## Arguments -- **$1** (query): Search term to filter operators (optional) - - If not provided, lists all available operators (may be very long) - - Searches across name, display name, description, provider - - Case-insensitive partial matching - - Example: "cert", "secrets", "security", "monitoring" -- **$2+** (flags): Optional flags - - `--catalog `: Limit search to specific catalog - - Values: "redhat-operators", "certified-operators", "community-operators", "redhat-marketplace", or custom catalog name - - `--exact`: Only show exact name matches (no partial matching) - - `--installed`: Show only operators that are currently installed - - -## Troubleshooting - -- **No operators found**: - - Verify catalog sources are available: - ```bash - oc get catalogsources -n openshift-marketplace - ``` - - Check if catalog sources are healthy: - ```bash - oc get pods -n openshift-marketplace - ``` -- **Slow search**: - - Use more specific search terms - - Search in specific catalog: `--catalog redhat-operators` -- **Incomplete information**: - - Some operators may have limited metadata in their PackageManifest -- **Permission denied**: - - Ensure you can read PackageManifests: - ```bash - oc auth can-i list packagemanifests -n openshift-marketplace - ``` - -## Related Commands - -- `/olm:install ` - Install an operator found in search results -- `/olm:list` - List installed operators -- `/olm:status ` - Check status of an installed operator - -## Additional Resources - -- [OperatorHub.io](https://operatorhub.io/) - Browse operators online -- [Operator Lifecycle Manager Documentation](https://olm.operatorframework.io/) +- **$1** (query): Search term (optional) +- **--catalog **: Filter by catalog +- **--version v0|v1**: OLM version (optional if context set) +- **--exact**: Exact match only (v0 only) + +## Notes + +- **v0**: Searches PackageManifests in openshift-marketplace +- **v1**: Queries ClusterCatalogs via catalogd API, requires port-forwarding +- Empty query lists all available packages +- Use install command shown in output to install diff --git a/plugins/olm/commands/status.md b/plugins/olm/commands/status.md index 603ceb0..8b9974e 100644 --- a/plugins/olm/commands/status.md +++ b/plugins/olm/commands/status.md @@ -1,6 +1,6 @@ --- -description: Get detailed status and health information for an operator -argument-hint: [namespace] +description: Get detailed status of an operator (v0) or extension (v1) +argument-hint: [namespace] [--version v0|v1] --- ## Name @@ -8,344 +8,207 @@ olm:status ## Synopsis ``` -/olm:status [namespace] +/olm:status [namespace] [--version v0|v1] ``` ## Description -The `olm:status` command provides comprehensive health and status information for a specific operator in an OpenShift cluster. It displays detailed information about the operator's CSV, Subscription, InstallPlan, deployments, and pods to help diagnose issues and verify proper operation. +Get comprehensive health and status information for a specific operator (OLM v0) or extension (OLM v1). -This command helps you: -- Check if an operator is running correctly -- Diagnose installation or upgrade problems -- View operator version and available updates -- Inspect operator deployments and pods -- Review recent events and conditions -- Identify resource issues or configuration problems +**You must explicitly specify which OLM version to use** via `--version` flag or context. ## Implementation -The command performs the following steps: +### 1. Determine OLM Version +**See [skills/version-detection/SKILL.md](../../skills/version-detection/SKILL.md)** -1. **Parse Arguments**: - - `$1`: Operator name (required) - Name of the operator to inspect - - `$2`: Namespace (optional) - Namespace where operator is installed - - If not provided, searches for the operator across all namespaces - - If multiple instances found, prompts user to specify namespace - -2. **Prerequisites Check**: - - Verify `oc` CLI is installed: `which oc` - - Verify cluster access: `oc whoami` - - If not installed or not authenticated, provide clear instructions - -3. **Locate Operator**: - - If namespace provided, verify operator exists in that namespace: - ```bash - oc get subscription {operator-name} -n {namespace} --ignore-not-found - ``` - - If no namespace provided, search across all namespaces: - ```bash - oc get subscription --all-namespaces -o json | jq -r '.items[] | select(.spec.name=="{operator-name}") | .metadata.namespace' - ``` - - If not found, display error with suggestions - - If multiple instances found, list them and ask user to specify namespace - -4. **Gather Subscription Information**: - - Get Subscription details: - ```bash - oc get subscription {operator-name} -n {namespace} -o json - ``` - - Extract: - - Channel: `.spec.channel` - - Install Plan Approval: `.spec.installPlanApproval` - - Source: `.spec.source` - - Source Namespace: `.spec.sourceNamespace` - - Installed CSV: `.status.installedCSV` - - Current CSV: `.status.currentCSV` - - State: `.status.state` - - Conditions: `.status.conditions[]` - -5. **Gather CSV Information**: - - Get CSV details: - ```bash - oc get csv {csv-name} -n {namespace} -o json - ``` - - Extract: - - Display Name: `.spec.displayName` - - Version: `.spec.version` - - Phase: `.status.phase` - - Message: `.status.message` - - Reason: `.status.reason` - - Creation Time: `.metadata.creationTimestamp` - - Conditions: `.status.conditions[]` - - Requirements: `.status.requirementStatus[]` +--- -6. **Gather InstallPlan Information**: - - Get related InstallPlans: - ```bash - oc get installplan -n {namespace} -o json - ``` - - Find InstallPlans related to this operator by checking `.spec.clusterServiceVersionNames` - - Extract: - - Name: `.metadata.name` - - Phase: `.status.phase` (e.g., "Complete", "Installing", "Failed") - - Approved: `.spec.approved` - - Bundle Resources: `.status.bundleLookups[]` +## OLM v0 Implementation + +### Steps + +1. **Parse Arguments**: `` [namespace] [--version v0] + +2. **Get CSV**: + ```bash + if [ -z "{namespace}" ]; then + # Auto-discover namespace + CSV=$(oc get csv --all-namespaces -o json | \ + jq --arg op "{operator-name}" '.items[] | select(.metadata.name | contains($op)) | {name: .metadata.name, namespace: .metadata.namespace}' | head -1) + NAMESPACE=$(echo "$CSV" | jq -r '.namespace') + else + NAMESPACE="{namespace}" + fi + + CSV_NAME=$(oc get csv -n $NAMESPACE -o json | \ + jq -r --arg op "{operator-name}" '.items[] | select(.metadata.name | contains($op)) | .metadata.name' | head -1) + ``` -7. **Gather Deployment Information**: - - Get deployments owned by the CSV: - ```bash - oc get deployments -n {namespace} -o json - ``` - - Filter deployments with owner reference to the CSV - - For each deployment, extract: - - Name: `.metadata.name` - - Ready Replicas: `.status.readyReplicas` / `.status.replicas` - - Available: `.status.availableReplicas` - - Conditions: `.status.conditions[]` +3. **Get Subscription**: + ```bash + SUB=$(oc get subscription -n $NAMESPACE -o json | \ + jq --arg csv "$CSV_NAME" '.items[] | select(.status.installedCSV==$csv)' | head -1) + ``` -8. **Gather Pod Information**: - - Get pods managed by operator deployments: - ```bash - oc get pods -n {namespace} -l app={operator-label} -o json - ``` - - For each pod, extract: - - Name: `.metadata.name` - - Status: `.status.phase` - - Ready: Count of ready containers vs total - - Restarts: Sum of `.status.containerStatuses[].restartCount` - - Age: Calculate from `.metadata.creationTimestamp` +4. **Display Status**: + ```bash + CSV_PHASE=$(oc get csv $CSV_NAME -n $NAMESPACE -o jsonpath='{.status.phase}') + CSV_VERSION=$(oc get csv $CSV_NAME -n $NAMESPACE -o jsonpath='{.spec.version}') + CSV_MESSAGE=$(oc get csv $CSV_NAME -n $NAMESPACE -o jsonpath='{.status.message}') + + SUB_CHANNEL=$(echo "$SUB" | jq -r '.spec.channel') + SUB_SOURCE=$(echo "$SUB" | jq -r '.spec.source') + SUB_APPROVAL=$(echo "$SUB" | jq -r '.spec.installPlanApproval') + + echo "Status: {operator-name}" + echo "" + echo "Overall Health: $([ "$CSV_PHASE" == "Succeeded" ] && echo "βœ“ Healthy" || echo "⚠️ Unhealthy")" + echo "Installation Status: $CSV_PHASE" + echo "CSV: $CSV_NAME" + echo "Version: $CSV_VERSION" + echo "Namespace: $NAMESPACE" + echo "Channel: $SUB_CHANNEL" + echo "Catalog: $SUB_SOURCE" + echo "Approval Mode: $SUB_APPROVAL" + + if [ -n "$CSV_MESSAGE" ]; then + echo "" + echo "Message: $CSV_MESSAGE" + fi + ``` -9. **Check for Recent Events**: - - Get events related to the operator: - ```bash - oc get events -n {namespace} --field-selector involvedObject.name={csv-name} --sort-by='.lastTimestamp' - ``` - - Show last 5-10 events, especially warnings and errors +5. **Show Workloads**: + ```bash + echo "" + echo "Workloads:" + oc get deployments,statefulsets -n $NAMESPACE -o wide + echo "" + echo "Pods:" + oc get pods -n $NAMESPACE + ``` -10. **Check for Available Updates**: - - Get PackageManifest to check for newer versions: - ```bash - oc get packagemanifest {operator-name} -n openshift-marketplace -o json - ``` - - Extract current channel information: - - Current channel from Subscription: `.spec.channel` - - Latest version in current channel - - Available channels - - Compare installed CSV version with latest available version - - Check for pending InstallPlans: - ```bash - oc get installplan -n {namespace} -o json | jq '.items[] | select(.spec.approved==false)' - ``` - - Determine if manual approval is required: - ```bash - oc get subscription {operator-name} -n {namespace} -o jsonpath='{.spec.installPlanApproval}' - ``` - - Reference: https://docs.redhat.com/en/documentation/openshift_container_platform/4.20/html/operators/administrator-tasks#olm-approving-operator-upgrades_olm-updating-operators +6. **Check for Updates**: + ```bash + CURRENT_CSV=$(echo "$SUB" | jq -r '.status.currentCSV') + INSTALLED_CSV=$(echo "$SUB" | jq -r '.status.installedCSV') + + if [ "$CURRENT_CSV" != "$INSTALLED_CSV" ]; then + echo "" + echo "⚠️ Update Available:" + echo " Current: $CURRENT_CSV" + echo " Installed: $INSTALLED_CSV" + echo " Upgrade: /olm:upgrade {operator-name} $NAMESPACE --version v0" + fi + ``` -11. **Format Comprehensive Report**: - Create a structured report with sections: - - **A. Overview** - ``` - Operator: {display-name} - Name: {operator-name} - Namespace: {namespace} - Version: {version} - Status: {phase} - ``` - - **B. Subscription** - ``` - Channel: {channel} - Source: {source} - Install Plan Approval: {approval-mode} (Automatic|Manual) - State: {state} - Installed CSV: {installed-csv-name} - Current CSV: {current-csv-name} - ``` - - **C. ClusterServiceVersion (CSV)** - ``` - Name: {csv-name} - Phase: {phase} - Message: {message} - Requirements: [list requirements status] - ``` - - **D. InstallPlan** - ``` - Name: {installplan-name} - Phase: {phase} (Complete|Installing|RequiresApproval|Failed) - Approved: {true/false} - - [If Phase=RequiresApproval and Approved=false:] - ⚠️ Manual approval required for installation/upgrade - To approve: /olm:approve {operator-name} {namespace} - Or manually: oc patch installplan {installplan-name} -n {namespace} \ - --type merge --patch '{"spec":{"approved":true}}' - ``` - - **E. Deployments** - ``` - NAME READY AVAILABLE AGE - cert-manager 1/1 1 5d - cert-manager-webhook 1/1 1 5d - ``` - - **F. Pods** - ``` - NAME STATUS READY RESTARTS AGE - cert-manager-7d4f8f8b4-abcde Running 1/1 0 5d - cert-manager-webhook-6b7c9d5f-fghij Running 1/1 0 5d - ``` - - **G. Recent Events** (if any warnings/errors) - ``` - 5m Warning InstallPlanFailed Failed to install... - 2m Normal InstallSucceeded Successfully installed - ``` - - **H. Update Information** - ``` - Current Version: {current-version} - Latest Available: {latest-version} (in channel: {channel}) - Update Status: [Up to date | Update available | Unknown] - - Available Channels: - - stable-v1 (latest: v1.13.1) - - tech-preview-v1.14 (latest: v1.14.0) - - [If update available in current channel:] - πŸ“¦ Update available: {current-version} β†’ {latest-version} - To update: /olm:upgrade {operator-name} {namespace} - - [If newer version in different channel:] - πŸ’‘ Newer version available in channel '{new-channel}': {newer-version} - To switch channels: /olm:upgrade {operator-name} {namespace} --channel={new-channel} - ``` - - **I. Health Summary** - ``` - βœ… Operator is healthy and running - ⚠️ Operator has warnings (see events) - ❌ Operator is not healthy (see details) - πŸ”„ Operator is upgrading (Current: {old-version} β†’ Target: {new-version}) - ⏸️ Operator upgrade pending manual approval - ``` +--- -12. **Provide Actionable Recommendations**: - - If operator is failed: - ``` - ❌ Operator failed: {reason} - - Troubleshooting steps: - 1. Check operator logs: oc logs -n {namespace} deployment/{operator-deployment} - 2. Check events: oc get events -n {namespace} --sort-by='.lastTimestamp' - 3. Check CSV conditions: oc describe csv {csv-name} -n {namespace} - 4. Run diagnostics: /olm:diagnose {operator-name} {namespace} - ``` - - If upgrade available: - ``` - πŸ“¦ Update available: {current} β†’ {latest} - To upgrade: /olm:upgrade {operator-name} {namespace} - ``` - - If pods are crashing: - ``` - ⚠️ Pods are crashing (restarts: {count}) - Check logs: oc logs -n {namespace} {pod-name} - Previous logs: oc logs -n {namespace} {pod-name} --previous - ``` - - If InstallPlan requires approval: - ``` - ⏸️ InstallPlan requires manual approval - - InstallPlan: {installplan-name} - Version: {target-version} - - To approve: /olm:approve {operator-name} {namespace} - Or manually: oc patch installplan {installplan-name} -n {namespace} \ - --type merge --patch '{"spec":{"approved":true}}' - - To switch to automatic approvals: - oc patch subscription {operator-name} -n {namespace} \ - --type merge --patch '{"spec":{"installPlanApproval":"Automatic"}}' - ``` - - If operator is upgrading: - ``` - πŸ”„ Operator upgrade in progress: {old-version} β†’ {new-version} - Monitor progress: watch oc get csv,installplan -n {namespace} - ``` +## OLM v1 Implementation -## Return Value -- **Success**: Comprehensive status report with all operator details -- **Not Found**: Error message with suggestions to list operators or check spelling -- **Multiple Instances**: List of namespaces where operator is installed -- **Error**: Connection or permission error with troubleshooting guidance -- **Format**: Multi-section report with: - - Overview - - Subscription details - - CSV status - - InstallPlan status - - Deployment status - - Pod status - - Recent events - - Health summary - - Recommendations +### Steps -## Examples +1. **Parse Arguments**: `` [--version v1] -1. **Check status of cert-manager operator**: - ``` - /olm:status openshift-cert-manager-operator +2. **Get ClusterExtension**: + ```bash + EXT=$(kubectl get clusterextension {extension-name} -o json 2>/dev/null) + if [ -z "$EXT" ]; then + echo "❌ Extension not found: {extension-name}" + exit 1 + fi ``` -2. **Check status with specific namespace**: +3. **Parse Status**: + ```bash + NAMESPACE=$(echo "$EXT" | jq -r '.spec.namespace') + VERSION=$(echo "$EXT" | jq -r '.status.resolution.bundle.version // "unknown"') + CHANNEL=$(echo "$EXT" | jq -r '.status.resolution.bundle.channel // "unknown"') + SA_NAME=$(echo "$EXT" | jq -r '.spec.serviceAccount.name') + + INSTALLED=$(echo "$EXT" | jq -r '.status.conditions[] | select(.type=="Installed") | .status') + PROGRESSING=$(echo "$EXT" | jq -r '.status.conditions[] | select(.type=="Progressing") | .status') + PROG_MSG=$(echo "$EXT" | jq -r '.status.conditions[] | select(.type=="Progressing") | .message') ``` - /olm:status external-secrets-operator external-secrets-operator - ``` - -## Arguments -- **$1** (operator-name): Name of the operator to inspect (required) - - Example: "openshift-cert-manager-operator" - - Must match the operator's Subscription name -- **$2** (namespace): Namespace where operator is installed (optional) - - If not provided, searches all namespaces - - Example: "cert-manager-operator" -## Notes +4. **Check for Issues**: + ```bash + # Check for RBAC errors + if [[ "$PROG_MSG" == *"pre-authorization failed"* ]]; then + HAS_RBAC_ISSUES=true + fi + + # Check for webhook errors + if [[ "$PROG_MSG" == *"webhookDefinitions are not supported"* ]]; then + HAS_WEBHOOK_ISSUES=true + fi + ``` -- **Comprehensive View**: This command aggregates data from multiple resources (Subscription, CSV, InstallPlan, Deployments, Pods) for a complete picture -- **Permissions**: Requires read permissions for subscriptions, csvs, installplans, deployments, pods, and events in the target namespace -- **Performance**: May take a few seconds to gather all information for large operators with many resources -- **Auto-Discovery**: If namespace is not specified, the command automatically finds the operator across all namespaces -- **Health Checks**: The command evaluates multiple factors to determine overall operator health -- **Troubleshooting**: Provides context-aware recommendations based on detected issues +5. **Display Status**: + ```bash + echo "Status: {extension-name}" + echo "" + + if [ "$INSTALLED" == "True" ]; then + echo "Overall Health: βœ“ Healthy" + elif [ "$PROGRESSING" == "True" ]; then + echo "Overall Health: ⏳ Installing" + else + echo "Overall Health: βœ— Failed" + fi + + echo "Installation Status: $([ "$INSTALLED" == "True" ] && echo "Installed" || echo "Not Installed")" + echo "Version: $VERSION" + echo "Channel: $CHANNEL" + echo "Namespace: $NAMESPACE" + echo "ServiceAccount: $SA_NAME" + + if [ "$HAS_RBAC_ISSUES" == "true" ]; then + echo "" + echo "⚠️ RBAC Permission Issues Detected" + echo "" + echo "$PROG_MSG" + echo "" + echo "Fix with: /olm:fix-rbac {extension-name} --version v1" + fi + + if [ "$HAS_WEBHOOK_ISSUES" == "true" ]; then + echo "" + echo "⚠️ Webhook Support Required" + echo "Enable: kubectl patch deployment operator-controller-controller-manager -n olmv1-system --type=json \\" + echo " -p='[{\"op\": \"add\", \"path\": \"/spec/template/spec/containers/0/args/-\", \"value\": \"--feature-gates=WebhookProviderCertManager=true\"}]'" + fi + ``` -## Troubleshooting +6. **Show Resources**: + ```bash + echo "" + echo "Custom Resource Definitions:" + kubectl get crds -l operators.coreos.com/clusterextension={extension-name} --no-headers | awk '{print " - " $1}' + + echo "" + echo "Workloads in $NAMESPACE:" + kubectl get deployments,statefulsets,daemonsets -n $NAMESPACE + ``` -- **Operator not found**: - - Verify operator name: `oc get subscriptions --all-namespaces | grep {operator-name}` - - List all operators: `/olm:list` -- **Multiple instances found**: - - Specify namespace explicitly: `/olm:status {operator-name} {namespace}` -- **Permission denied**: - - Ensure you have read permissions in the target namespace - - Check: `oc auth can-i get csv -n {namespace}` -- **Incomplete information**: - - Some operators may not have all resources (e.g., manually installed CSVs without Subscriptions) +--- -## Related Commands +## Return Value +- Comprehensive status including health, version, workloads, and issues +- Actionable recommendations for problems -- `/olm:list` - List all installed operators -- `/olm:install ` - Install a new operator -- `/olm:uninstall ` - Uninstall an operator -- `/olm:upgrade ` - Upgrade an operator -- `/olm:approve ` - Approve pending InstallPlans -- `/olm:diagnose ` - Diagnose and fix operator issues +## Examples -## Additional Resources +```bash +/olm:status cert-manager --version v1 +/olm:status openshift-pipelines-operator openshift-operators --version v0 +``` -- [Viewing Operator Status](https://docs.redhat.com/en/documentation/openshift_container_platform/4.20/html/operators/administrator-tasks#olm-status-viewing-operator-status) -- [Updating Installed Operators](https://docs.redhat.com/en/documentation/openshift_container_platform/4.20/html/operators/administrator-tasks#olm-updating-operators) -- [Troubleshooting Operator Issues](https://docs.redhat.com/en/documentation/openshift_container_platform/4.20/html/operators/administrator-tasks#olm-troubleshooting-operator-issues) +## Arguments +- **$1** (name): Operator/extension name (required) +- **$2** (namespace): Namespace (optional for v0, auto-discovered; N/A for v1) +- **--version v0|v1**: OLM version +## Notes +- **v0**: Shows CSV, Subscription, workloads, and pending updates +- **v1**: Shows ClusterExtension, RBAC issues, webhook issues, and workloads +- Use `/olm:fix-rbac` for v1 RBAC problems diff --git a/plugins/olm/commands/uninstall.md b/plugins/olm/commands/uninstall.md index 36c3ec1..16e6b1c 100644 --- a/plugins/olm/commands/uninstall.md +++ b/plugins/olm/commands/uninstall.md @@ -1,6 +1,6 @@ --- -description: Uninstall a day-2 operator and optionally remove its resources -argument-hint: [namespace] [--remove-crds] [--remove-namespace] +description: Uninstall an operator (v0) or extension (v1) from the cluster +argument-hint: [namespace] [--remove-crds] [--remove-namespace] [--version v0|v1] --- ## Name @@ -8,385 +8,220 @@ olm:uninstall ## Synopsis ``` -/olm:uninstall [namespace] [--remove-crds] [--remove-namespace] +/olm:uninstall [namespace] [--remove-crds] [--remove-namespace] [--version v0|v1] ``` ## Description -The `olm:uninstall` command uninstalls a day-2 operator from an OpenShift cluster by removing its Subscription, ClusterServiceVersion (CSV), and optionally its Custom Resource Definitions (CRDs) and namespace. +Safely uninstall an operator (OLM v0) or extension (OLM v1) from the cluster with optional cleanup of CRDs and namespaces. -This command provides a comprehensive uninstallation workflow: -- Removes the operator's Subscription -- Deletes the ClusterServiceVersion (CSV) -- Optionally removes operator-managed deployments -- Optionally deletes Custom Resource Definitions (CRDs) -- Optionally removes the operator's namespace -- Provides detailed feedback on each step - -The command is designed to safely clean up operators installed via OLM, with optional flags for thorough cleanup of all operator-related resources. +**You must explicitly specify which OLM version to use** via `--version` flag or context. ## Implementation -The command performs the following steps: +### 1. Determine OLM Version +**See [skills/version-detection/SKILL.md](../../skills/version-detection/SKILL.md)** + +--- + +## OLM v0 Implementation + +### Steps 1. **Parse Arguments**: - - `$1`: Operator name (required) - The name of the operator to uninstall - - `$2`: Namespace (optional) - The namespace where operator is installed. If not provided, defaults to `{operator-name}-operator` - - `$3+`: Flags (optional): - - `--remove-crds`: Remove Custom Resource Definitions after uninstalling - - `--remove-namespace`: Remove the operator's namespace after cleanup - - `--force`: Skip confirmation prompts - -2. **Prerequisites Check**: - - Verify `oc` CLI is installed: `which oc` - - Verify cluster access: `oc whoami` - - Check if user has cluster-admin or sufficient privileges - -3. **Verify Operator Installation**: - - Check if namespace exists: - ```bash - oc get namespace {namespace} --ignore-not-found - ``` - - Check if subscription exists: - ```bash - oc get subscription {operator-name} -n {namespace} --ignore-not-found - ``` - - If not found, display error: "Operator {operator-name} is not installed in namespace {namespace}" - - List what will be uninstalled - -4. **Display Uninstallation Plan**: - - Show operator details: - ```bash - oc get subscription {operator-name} -n {namespace} -o yaml - oc get csv -n {namespace} - ``` - - Display what will be removed: - - Subscription name and namespace - - CSV name and version - - Deployments (if any) - - CRDs (if `--remove-crds` flag is set) - - Namespace (if `--remove-namespace` flag is set) - -5. **Request User Confirmation** (unless `--force` flag is set): - - Display warning: - ``` - WARNING: You are about to uninstall {operator-name} from namespace {namespace}. - This will remove: - - Subscription: {subscription-name} - - ClusterServiceVersion: {csv-name} - - Operator deployments - [- Custom Resource Definitions (if --remove-crds is set)] - [- Namespace {namespace} (if --remove-namespace is set)] - - Are you sure you want to continue? (yes/no) - ``` - - Wait for user confirmation - - If user says no, abort operation - -6. **Delete Subscription**: - - Remove the operator's subscription: - ```bash - oc delete subscription {operator-name} -n {namespace} - ``` - - Verify deletion: - ```bash - oc get subscription {operator-name} -n {namespace} --ignore-not-found - ``` - - Display result - -7. **Delete ClusterServiceVersion (CSV)**: - - Get the CSV name: - ```bash - oc get csv -n {namespace} -o jsonpath='{.items[?(@.spec.displayName contains "{operator-name}")].metadata.name}' - ``` - - Delete the CSV: - ```bash - oc delete csv {csv-name} -n {namespace} - ``` - - This will automatically remove operator deployments - - Verify CSV is deleted: - ```bash - oc get csv -n {namespace} --ignore-not-found - ``` - -8. **Remove Operator Deployments** (if still present): - - List deployments created by the operator: - ```bash - oc get deployments -n {namespace} - ``` - - For operators like cert-manager with labeled resources: - ```bash - oc delete deployment -n {namespace} -l app.kubernetes.io/instance={operator-base-name} - ``` - - Verify deployments are deleted: - ```bash - oc get deployments -n {namespace} - ``` - -8.5. **Check for Orphaned Custom Resources** (before removing CRDs): - - Get list of CRDs managed by the operator from CSV: - ```bash - oc get csv -n {namespace} -o jsonpath='{.items[0].spec.customresourcedefinitions.owned[*].name}' - ``` - - For each CRD, search for CR instances across all namespaces: - ```bash - oc get --all-namespaces --ignore-not-found - ``` - - If CRs exist, list them with details: - ``` - WARNING: Found custom resources that may prevent clean uninstallation: - - namespace-1/ (kind: ) - - namespace-2/ (kind: ) - - These resources should be deleted before uninstalling the operator. - Do you want to delete these custom resources? (yes/no) - ``` - - If user confirms, delete each CR: - ```bash - oc delete -n - ``` - - This prevents namespace from getting stuck in Terminating state - - Reference: https://docs.redhat.com/en/documentation/openshift_container_platform/4.20/html/operators/administrator-tasks#olm-reinstalling-operators-after-failed-uninstallation_olm-troubleshooting-operator-issues - -9. **Remove Custom Resource Definitions** (if `--remove-crds` flag is set): - - **WARNING**: Display critical warning to user: - ``` - WARNING: Removing CRDs will delete ALL custom resources of these types across the entire cluster! - This action is irreversible and will affect all namespaces. - - Are you absolutely sure you want to remove CRDs? (yes/no) - ``` - - If user confirms, proceed with CRD removal - - Get list of CRDs owned by the operator: - ```bash - oc get csv {csv-name} -n {namespace} -o jsonpath='{.spec.customresourcedefinitions.owned[*].name}' - ``` - - For each CRD, check if custom resources exist: - ```bash - oc get {crd-name} --all-namespaces --ignore-not-found - ``` - - Display warning if custom resources exist - - Delete CRDs: - ```bash - oc delete crd {crd-name} - ``` - -10. **Remove Namespace** (if `--remove-namespace` flag is set): - - **WARNING**: Display warning: - ``` - WARNING: Removing namespace {namespace} will delete all resources in this namespace! - - Are you sure you want to remove namespace {namespace}? (yes/no) - ``` - - If user confirms: - ```bash - oc delete namespace {namespace} - ``` - - Monitor namespace deletion with timeout: - ```bash - oc wait --for=delete namespace/{namespace} --timeout=120s - ``` - - If namespace gets stuck in "Terminating" state after 120 seconds: - - Check for resources preventing deletion: - ```bash - oc api-resources --verbs=list --namespaced -o name | \ - xargs -n 1 oc get --show-kind --ignore-not-found -n {namespace} - ``` - - Check for finalizers on the namespace: - ```bash - oc get namespace {namespace} -o jsonpath='{.metadata.finalizers}' - ``` - - Display helpful error message: - ``` - ERROR: Namespace {namespace} is stuck in Terminating state. - - Possible causes: - - Resources with finalizers preventing deletion - - API services that are unavailable - - Custom resources that cannot be deleted - - To diagnose and fix, run: /olm:diagnose {operator-name} {namespace} - - Manual troubleshooting: - 1. Check remaining resources: - oc api-resources --verbs=list --namespaced -o name | \ - xargs -n 1 oc get --show-kind --ignore-not-found -n {namespace} - - 2. Check namespace finalizers: - oc get namespace {namespace} -o yaml | grep -A5 finalizers - - WARNING: Do NOT force-delete the namespace as it can lead to unstable cluster behavior. - See: https://access.redhat.com/solutions/4165791 - ``` - - Exit with error code - - Note: OperatorGroup will be automatically deleted with the namespace - -11. **Post-Uninstall Verification**: - - Verify all resources are cleaned up: - ```bash - oc get subscription,csv,installplan -n {namespace} --ignore-not-found - ``` - - Check if any CRDs remain (if they were supposed to be deleted): - ```bash - oc get crd | grep - ``` - - If uninstalling without `--remove-namespace`, check namespace is clean: - ```bash - oc get all -n {namespace} - ``` - - Display any remaining resources with suggestions for cleanup - -12. **Display Uninstallation Summary**: - - Show what was successfully removed: - ``` - βœ“ Uninstallation Summary: - βœ“ Subscription '{operator-name}' deleted - βœ“ CSV '{csv-name}' deleted - βœ“ Operator deployments removed - [βœ“ X custom resources deleted] - [βœ“ Y CRDs removed] - [βœ“ Namespace '{namespace}' deleted] - ``` - - If CRDs or namespace were NOT removed, provide instructions: - ``` - Note: The following resources were NOT removed: - - Custom Resource Definitions (use --remove-crds to remove) - - Namespace {namespace} (use --remove-namespace to remove) - - To completely remove all operator resources, run: - /olm:uninstall {operator-name} {namespace} --remove-crds --remove-namespace - ``` - - **Important warning about reinstallation**: - ``` - IMPORTANT: Before reinstalling this operator, verify all resources are cleaned: - - oc get subscription,csv,installplan -n {namespace} - oc get crd | grep - - Failure to completely uninstall may cause reinstallation issues. - See: https://docs.redhat.com/en/documentation/openshift_container_platform/4.20/html/operators/administrator-tasks#olm-reinstalling-operators-after-failed-uninstallation_olm-troubleshooting-operator-issues - ``` + - `` (required) + - `[namespace]` (optional, auto-discovered if not provided) + - `--remove-crds`: Remove CRDs (WARNING: affects entire cluster) + - `--remove-namespace`: Remove namespace after uninstall + - `--force`: Skip confirmation prompts + +2. **Find Operator**: + ```bash + if [ -z "{namespace}" ]; then + CSV=$(oc get csv --all-namespaces -o json | \ + jq --arg op "{operator-name}" '.items[] | select(.metadata.name | contains($op))' | head -1) + NAMESPACE=$(echo "$CSV" | jq -r '.metadata.namespace') + CSV_NAME=$(echo "$CSV" | jq -r '.metadata.name') + else + NAMESPACE="{namespace}" + CSV_NAME=$(oc get csv -n $NAMESPACE | grep {operator-name} | awk '{print $1}') + fi + ``` -## Return Value -- **Success**: Operator uninstalled successfully with summary of removed resources -- **Partial Success**: Some resources removed with warnings about remaining resources -- **Error**: Uninstallation failed with specific error message -- **Format**: Structured output showing: - - Subscription deletion status - - CSV deletion status - - Deployment removal status - - CRD removal status (if applicable) - - Namespace deletion status (if applicable) +3. **Show What Will Be Removed**: + ```bash + echo "Preparing to uninstall: {operator-name}" + echo "" + echo "The following will be removed:" + echo " - Subscription" + echo " - CSV: $CSV_NAME" + echo " - Namespace: $NAMESPACE" + + if [ "{remove-crds}" == "true" ]; then + CRD_COUNT=$(oc get crds -o json | jq --arg csv "$CSV_NAME" \ + '[.items[] | select(.metadata.annotations["olm.managed"]=="true")] | length') + echo " - CRDs: $CRD_COUNT (⚠️ AFFECTS ENTIRE CLUSTER)" + fi + ``` -## Examples +4. **Confirm with User** (if not --force): + ```bash + if [ "{force}" != "true" ]; then + read -p "Do you want to proceed? (y/N): " CONFIRM + if [ "$CONFIRM" != "y" ]; then + echo "Uninstall cancelled" + exit 0 + fi + fi + ``` + +5. **Delete Subscription**: + ```bash + SUB_NAME=$(oc get subscription -n $NAMESPACE -o json | \ + jq -r --arg csv "$CSV_NAME" '.items[] | select(.status.installedCSV==$csv) | .metadata.name') + + if [ -n "$SUB_NAME" ]; then + oc delete subscription $SUB_NAME -n $NAMESPACE + echo "βœ“ Deleted Subscription: $SUB_NAME" + fi + ``` + +6. **Delete CSV**: + ```bash + oc delete csv $CSV_NAME -n $NAMESPACE + echo "βœ“ Deleted CSV: $CSV_NAME" + ``` + +7. **Delete CRDs** (if requested): + ```bash + if [ "{remove-crds}" == "true" ]; then + CRDS=$(oc get crds -o json | \ + jq -r --arg csv "$CSV_NAME" \ + '.items[] | select(.metadata.annotations["olm.managed"]=="true") | .metadata.name') + + for CRD in $CRDS; do + oc delete crd $CRD + echo "βœ“ Deleted CRD: $CRD" + done + fi + ``` -1. **Uninstall cert-manager-operator (basic)**: +8. **Delete Namespace** (if requested): + ```bash + if [ "{remove-namespace}" == "true" ]; then + oc delete namespace $NAMESPACE + echo "βœ“ Deleted Namespace: $NAMESPACE" + fi ``` - /olm:uninstall openshift-cert-manager-operator + +--- + +## OLM v1 Implementation + +### Steps + +1. **Parse Arguments**: + - `` (required) + - `--remove-crds`: Remove CRDs + - `--remove-namespace`: Remove namespace + - `--force`: Skip confirmation + +2. **Get ClusterExtension**: + ```bash + EXT=$(kubectl get clusterextension {extension-name} -o json 2>/dev/null) + if [ -z "$EXT" ]; then + echo "❌ Extension not found: {extension-name}" + exit 1 + fi + + NAMESPACE=$(echo "$EXT" | jq -r '.spec.namespace') ``` -2. **Uninstall with custom namespace**: +3. **Show What Will Be Removed**: + ```bash + echo "Preparing to uninstall: {extension-name}" + echo "" + + CRD_COUNT=$(kubectl get crds -l operators.coreos.com/clusterextension={extension-name} --no-headers | wc -l) + + echo "The following will be removed:" + echo " - ClusterExtension: {extension-name}" + echo " - ServiceAccount and RBAC" + echo " - Namespace: $NAMESPACE" + + if [ "{remove-crds}" == "true" ]; then + echo " - CRDs: $CRD_COUNT (⚠️ AFFECTS ENTIRE CLUSTER)" + fi ``` - /olm:uninstall openshift-cert-manager-operator my-cert-manager + +4. **Confirm** (if not --force): + ```bash + if [ "{force}" != "true" ]; then + read -p "Proceed with uninstall? (y/N): " CONFIRM + if [ "$CONFIRM" != "y" ]; then + exit 0 + fi + fi ``` -3. **Complete cleanup including namespace**: +5. **Delete ClusterExtension**: + ```bash + kubectl delete clusterextension {extension-name} + echo "βœ“ Deleted ClusterExtension: {extension-name}" ``` - /olm:uninstall openshift-cert-manager-operator cert-manager-operator --remove-crds --remove-namespace + +6. **Delete RBAC**: + ```bash + kubectl delete clusterrolebinding {extension-name}-installer --ignore-not-found + kubectl delete clusterrole {extension-name}-installer --ignore-not-found + kubectl delete serviceaccount {extension-name}-sa -n $NAMESPACE --ignore-not-found + echo "βœ“ Deleted RBAC resources" ``` - This performs a complete cleanup of all operator-related resources. -4. **Force uninstall without prompts**: +7. **Delete CRDs** (if requested): + ```bash + if [ "{remove-crds}" == "true" ]; then + kubectl delete crds -l operators.coreos.com/clusterextension={extension-name} + echo "βœ“ Deleted CRDs" + fi ``` - /olm:uninstall openshift-cert-manager-operator cert-manager-operator --force + +8. **Delete Namespace** (if requested): + ```bash + if [ "{remove-namespace}" == "true" ]; then + kubectl delete namespace $NAMESPACE + echo "βœ“ Deleted Namespace: $NAMESPACE" + fi ``` - Skips all confirmation prompts (use with caution!). -## Arguments -- **$1** (operator-name): The name of the operator to uninstall (required) - - Example: "openshift-cert-manager-operator" - - Must match the Subscription name -- **$2** (namespace): The namespace where operator is installed (optional) - - Default: `{operator-name}` (operator name without "openshift-" prefix) - - Example: "cert-manager-operator" -- **$3+** (flags): Optional flags (can combine multiple): - - `--remove-crds`: Remove Custom Resource Definitions (WARNING: affects entire cluster) - - `--remove-namespace`: Remove the operator's namespace and all its resources - - `--force`: Skip all confirmation prompts (use with caution) - -## Safety Features - -1. **Multiple Confirmations**: Separate confirmations for CRD and namespace removal -2. **Detailed Warnings**: Clear warnings about the scope of deletions -3. **Verification Steps**: Checks that resources exist before attempting deletion -4. **Summary Report**: Detailed summary of what was and wasn't removed -5. **Graceful Failures**: Continues with remaining steps if individual deletions fail - -## Troubleshooting - -- **Subscription not found**: Verify the operator name and namespace: - ```bash - oc get subscriptions --all-namespaces | grep {operator-name} - ``` -- **CSV won't delete**: Check for finalizers: - ```bash - oc get csv {csv-name} -n {namespace} -o yaml | grep finalizers - ``` - If finalizers are present, they may be waiting for resources to be cleaned up. Check operator logs and events. - -- **Namespace stuck in Terminating**: This is a common issue after operator uninstallation. - ```bash - # Find remaining resources - oc api-resources --verbs=list --namespaced -o name | \ - xargs -n 1 oc get --show-kind --ignore-not-found -n {namespace} - - # Check namespace finalizers - oc get namespace {namespace} -o yaml | grep -A5 finalizers - ``` - **IMPORTANT**: Do not force-delete the namespace. This can cause cluster instability. - Instead, use `/olm:diagnose {operator-name} {namespace}` to diagnose and fix the issue. - -- **CRDs won't delete**: Check for remaining custom resources: - ```bash - oc get {crd-name} --all-namespaces - ``` - CRDs cannot be deleted while CR instances exist. Delete all CRs first. - -- **Custom resources won't delete**: Some CRs may have finalizers preventing deletion: - ```bash - oc get -n -o yaml | grep finalizers - ``` - The operator controller (if still running) should remove finalizers. If operator is already deleted, you may need to manually patch the CR to remove finalizers (use with extreme caution). - -- **Permission denied**: Ensure you have cluster-admin privileges for CRD deletion: - ```bash - oc auth can-i delete crd - ``` - -- **Reinstallation fails after uninstall**: This usually means cleanup was incomplete. - Run these checks before reinstalling: - ```bash - # Check for remaining subscriptions/CSVs - oc get subscription,csv -n {namespace} - - # Check for remaining CRDs - oc get crd | grep - - # Check if namespace is clean or stuck - oc get namespace {namespace} - ``` - See: https://docs.redhat.com/en/documentation/openshift_container_platform/4.20/html/operators/administrator-tasks#olm-reinstalling-operators-after-failed-uninstallation_olm-troubleshooting-operator-issues - -## Related Commands - -- `/olm:install` - Install a day-2 operator -- `/olm:list` - List installed operators -- `/olm:status` - Check operator status before uninstalling -- `/olm:diagnose` - Diagnose and fix uninstallation issues -- `/olm:upgrade` - Upgrade an operator - -## Additional Resources - -- [Red Hat OpenShift: Deleting Operators from a cluster](https://docs.redhat.com/en/documentation/openshift_container_platform/4.20/html/operators/administrator-tasks#olm-deleting-operators-from-a-cluster) -- [Red Hat OpenShift: Reinstalling Operators after failed uninstallation](https://docs.redhat.com/en/documentation/openshift_container_platform/4.20/html/operators/administrator-tasks#olm-reinstalling-operators-after-failed-uninstallation_olm-troubleshooting-operator-issues) -- [Operator Lifecycle Manager Documentation](https://olm.operatorframework.io/) +--- + +## Return Value +- Confirmation of deleted resources +- Warning if any resources couldn't be deleted + +## Examples +```bash +# Basic uninstall +/olm:uninstall cert-manager --version v1 + +# Full cleanup +/olm:uninstall postgres-operator --remove-crds --remove-namespace --version v0 + +# Force without confirmation +/olm:uninstall legacy-operator --force --version v0 +``` + +## Arguments +- **$1** (name): Operator/extension name (required) +- **$2** (namespace): Namespace (v0 only, optional) +- **--remove-crds**: Remove CRDs (⚠️ WARNING: affects entire cluster) +- **--remove-namespace**: Remove namespace +- **--force**: Skip confirmation prompts +- **--version v0|v1**: OLM version + +## Notes +- **CRD Removal**: Use with caution - affects entire cluster and deletes all custom resources +- **v0**: Deletes Subscription and CSV +- **v1**: Deletes ClusterExtension and associated RBAC +- Always backs up important custom resources before uninstalling diff --git a/plugins/olm/commands/upgrade.md b/plugins/olm/commands/upgrade.md index 75434f6..c77ac6f 100644 --- a/plugins/olm/commands/upgrade.md +++ b/plugins/olm/commands/upgrade.md @@ -1,6 +1,6 @@ --- -description: Update an operator to the latest version or switch channels -argument-hint: [namespace] [--channel=] [--approve] +description: Upgrade an operator (v0) or extension (v1) to a new version +argument-hint: [namespace] [--channel ] [--approve] [--version v0|v1] --- ## Name @@ -8,342 +8,172 @@ olm:upgrade ## Synopsis ``` -/olm:upgrade [namespace] [--channel=] [--approve] +/olm:upgrade [namespace] [--channel ] [--approve] [--version v0|v1] ``` ## Description -The `olm:upgrade` command updates an installed operator to the latest version in its current channel or switches to a different channel. It can also approve pending InstallPlans for operators with manual approval mode. +Upgrade an operator (OLM v0) or extension (OLM v1) to a new version or switch channels. -This command helps you: -- Update operators to the latest version in their channel -- Switch operators to different channels (e.g., stable to tech-preview) -- Approve pending upgrade InstallPlans for manual approval mode -- Monitor upgrade progress -- Rollback on failure (if possible via OLM) +**You must explicitly specify which OLM version to use** via `--version` flag or context. ## Implementation -The command performs the following steps: +### 1. Determine OLM Version +**See [skills/version-detection/SKILL.md](../../skills/version-detection/SKILL.md)** -1. **Parse Arguments**: - - `$1`: Operator name (required) - Name of the operator to upgrade - - `$2`: Namespace (optional) - Namespace where operator is installed - - If not provided, searches for the operator across all namespaces - - `$3+`: Flags (optional): - - `--channel=`: Switch to a different channel - - `--approve`: Automatically approve pending InstallPlan (for manual approval mode) - -2. **Prerequisites Check**: - - Verify `oc` CLI is installed: `which oc` - - Verify cluster access: `oc whoami` - - Check if user has sufficient privileges - -3. **Locate Operator**: - - If namespace provided, verify operator exists: - ```bash - oc get subscription {operator-name} -n {namespace} --ignore-not-found - ``` - - If no namespace provided, search across all namespaces: - ```bash - oc get subscription --all-namespaces -o json | jq -r '.items[] | select(.spec.name=="{operator-name}") | .metadata.namespace' - ``` - - If not found, display error with suggestions - - If multiple instances found, prompt user to specify namespace +--- -4. **Get Current State**: - - Get current Subscription: - ```bash - oc get subscription {operator-name} -n {namespace} -o json - ``` - - Extract: - - Current channel: `.spec.channel` - - Install plan approval: `.spec.installPlanApproval` - - Installed CSV: `.status.installedCSV` - - Current CSV: `.status.currentCSV` - - Get current CSV version: - ```bash - oc get csv {installed-csv} -n {namespace} -o jsonpath='{.spec.version}' - ``` +## OLM v0 Implementation -5. **Check for Available Updates**: - - Get PackageManifest: - ```bash - oc get packagemanifest {operator-name} -n openshift-marketplace -o json - ``` - - Extract available channels and their latest versions - - If `--channel` flag is specified, verify channel exists - - If no channel flag, check for updates in current channel - - Compare current version with latest available version - - Reference: https://docs.redhat.com/en/documentation/openshift_container_platform/4.20/html/operators/administrator-tasks#olm-updating-operators +### Steps -6. **Display Upgrade Plan**: - ``` - Operator Upgrade Plan: - - Operator: {display-name} - Namespace: {namespace} - Current Version: {current-version} - Current Channel: {current-channel} - - [If switching channels:] - Target Channel: {new-channel} - Target Version: {new-version} - - [If upgrading in same channel:] - Latest Version: {latest-version} (in channel: {current-channel}) +1. **Parse Arguments**: + - `` (required) + - `[namespace]` (optional, auto-discovered) + - `--channel `: Switch to different channel + - `--approve`: Approve pending InstallPlan + +2. **Get Subscription**: + ```bash + if [ -z "{namespace}" ]; then + SUB=$(oc get subscription --all-namespaces -o json | \ + jq --arg op "{operator-name}" '.items[] | select(.metadata.name | contains($op))' | head -1) + NAMESPACE=$(echo "$SUB" | jq -r '.metadata.namespace') + else + NAMESPACE="{namespace}" + SUB=$(oc get subscription {operator-name} -n $NAMESPACE -o json) + fi - Approval Mode: {Automatic|Manual} - ``` - -7. **Check for Pending InstallPlans** (for manual approval mode): - - Get pending InstallPlans: - ```bash - oc get installplan -n {namespace} -o json | jq '.items[] | select(.spec.approved==false)' - ``` - - If pending InstallPlan exists and `--approve` flag is set: - - Display InstallPlan details - - Approve the InstallPlan (skip to step 9) - - If pending InstallPlan exists and no `--approve` flag: - ``` - ⏸️ Pending InstallPlan found (requires manual approval) - - InstallPlan: {installplan-name} - Target Version: {target-version} - - To approve: /olm:upgrade {operator-name} {namespace} --approve - Or use: /olm:approve {operator-name} {namespace} - ``` - - Exit, waiting for user to approve - -8. **Perform Channel Switch** (if `--channel` flag provided): - - Confirm with user (unless `--force` flag): - ``` - WARNING: Switching channels may upgrade or downgrade the operator. - - Current: {current-channel} ({current-version}) - Target: {new-channel} ({target-version}) - - Continue? (yes/no) - ``` - - Update Subscription to new channel: - ```bash - oc patch subscription {operator-name} -n {namespace} \ - --type merge --patch '{"spec":{"channel":"{new-channel}"}}' - ``` - - Display confirmation: - ``` - βœ“ Subscription updated to channel: {new-channel} - ``` - -9. **Approve Pending InstallPlan** (if `--approve` flag or automatic approval): - - If approval mode is Manual and `--approve` flag is set: - ```bash - oc patch installplan {installplan-name} -n {namespace} \ - --type merge --patch '{"spec":{"approved":true}}' - ``` - - Display approval confirmation: - ``` - βœ“ InstallPlan approved: {installplan-name} - ``` - -10. **Monitor Upgrade Progress**: - - Wait for new InstallPlan to be created (if switching channels): - ```bash - oc get installplan -n {namespace} -w --timeout=60s - ``` - - Wait for new CSV to reach "Succeeded" phase: - ```bash - oc get csv -n {namespace} -w --timeout=300s - ``` - - Display progress updates: - ``` - πŸ”„ Upgrade in progress... - ⏳ Waiting for InstallPlan to complete... - ⏳ New CSV installing: {new-csv-name} - ⏳ Old CSV replacing: {old-csv-name} - ``` - - Poll every 10 seconds to check status - - Timeout: 10 minutes for upgrade to complete - -11. **Verify Upgrade Success**: - - Check new CSV status: - ```bash - oc get csv -n {namespace} -o json - ``` - - Verify new CSV phase is "Succeeded" - - Get new version: - ```bash - oc get csv {new-csv-name} -n {namespace} -o jsonpath='{.spec.version}' - ``` - - Check deployments are healthy: - ```bash - oc get deployments -n {namespace} - ``` - - Check pods are running: - ```bash - oc get pods -n {namespace} - ``` - -12. **Display Upgrade Summary**: - ``` - βœ“ Operator Upgrade Complete! - - Operator: {display-name} - Namespace: {namespace} - Previous Version: {old-version} - Current Version: {new-version} - Channel: {channel} - - Deployment Status: - - {deployment-1}: 1/1 replicas ready - - {deployment-2}: 1/1 replicas ready - - To check status: /olm:status {operator-name} {namespace} - ``` - -13. **Handle Upgrade Failures**: - - If upgrade fails or times out: - ``` - ❌ Operator upgrade failed - - Current State: - - CSV: {csv-name} (Phase: {phase}) - - Message: {error-message} - - Troubleshooting steps: - 1. Check CSV status: oc describe csv {csv-name} -n {namespace} - 2. Check events: oc get events -n {namespace} --sort-by='.lastTimestamp' - 3. Check InstallPlan: oc get installplan -n {namespace} - 4. Run diagnostics: /olm:diagnose {operator-name} {namespace} - - To rollback (if OLM supports): - oc patch subscription {operator-name} -n {namespace} \ - --type merge --patch '{"spec":{"channel":"{old-channel}"}}' - ``` - -## Return Value -- **Success**: Operator upgraded successfully with new version details -- **Pending Approval**: Upgrade waiting for manual approval with instructions -- **No Update Available**: Operator is already at the latest version -- **Error**: Upgrade failed with specific error message and troubleshooting guidance -- **Format**: Structured output showing: - - Previous and current versions - - Channel information - - Deployment and pod status - - Next steps or related commands - -## Examples - -1. **Check for and install updates in current channel**: - ``` - /olm:upgrade openshift-cert-manager-operator + CURRENT_CHANNEL=$(echo "$SUB" | jq -r '.spec.channel') + CURRENT_CSV=$(echo "$SUB" | jq -r '.status.currentCSV') + INSTALLED_CSV=$(echo "$SUB" | jq -r '.status.installedCSV') ``` -2. **Upgrade with specific namespace**: - ``` - /olm:upgrade external-secrets-operator eso-operator +3. **Check for Channel Switch**: + ```bash + if [ -n "{channel}" ] && [ "{channel}" != "$CURRENT_CHANNEL" ]; then + echo "Switching channel: $CURRENT_CHANNEL β†’ {channel}" + oc patch subscription {operator-name} -n $NAMESPACE --type=merge \ + -p "{\"spec\":{\"channel\":\"{channel}\"}}" + echo "βœ“ Channel updated" + fi ``` -3. **Switch to a different channel**: - ``` - /olm:upgrade openshift-cert-manager-operator cert-manager-operator --channel=tech-preview-v1.14 +4. **Check for Pending Updates**: + ```bash + if [ "$CURRENT_CSV" != "$INSTALLED_CSV" ]; then + echo "Update available:" + echo " Current: $CURRENT_CSV" + echo " Installed: $INSTALLED_CSV" + fi ``` - This switches from stable-v1 to tech-preview-v1.14 channel. -4. **Approve pending upgrade (manual approval mode)**: - ``` - /olm:upgrade openshift-cert-manager-operator --approve +5. **Approve InstallPlan** (if --approve or Manual mode): + ```bash + if [ "{approve}" == "true" ]; then + PENDING_PLAN=$(oc get installplan -n $NAMESPACE -o json | \ + jq -r '.items[] | select(.spec.approved==false) | .metadata.name' | head -1) + + if [ -n "$PENDING_PLAN" ]; then + oc patch installplan $PENDING_PLAN -n $NAMESPACE --type=merge \ + -p '{"spec":{"approved":true}}' + echo "βœ“ Approved InstallPlan: $PENDING_PLAN" + fi + fi ``` -5. **Switch channel and approve in one command**: - ``` - /olm:upgrade prometheus prometheus-operator --channel=beta --approve +6. **Monitor Upgrade**: + ```bash + echo "Monitoring upgrade..." + for i in {1..30}; do + NEW_CSV=$(oc get subscription {operator-name} -n $NAMESPACE -o jsonpath='{.status.installedCSV}') + CSV_PHASE=$(oc get csv $NEW_CSV -n $NAMESPACE -o jsonpath='{.status.phase}' 2>/dev/null) + + if [ "$CSV_PHASE" == "Succeeded" ]; then + echo "βœ“ Upgrade completed: $NEW_CSV" + break + fi + sleep 10 + done ``` -## Arguments -- **$1** (operator-name): Name of the operator to upgrade (required) - - Example: "openshift-cert-manager-operator" - - Must match the operator's Subscription name -- **$2** (namespace): Namespace where operator is installed (optional) - - If not provided, searches all namespaces - - Example: "cert-manager-operator" -- **$3+** (flags): Optional flags - - `--channel=`: Switch to specified channel - - Example: `--channel=stable-v1`, `--channel=tech-preview` - - Triggers upgrade/downgrade to the version in that channel - - `--approve`: Automatically approve pending InstallPlan - - Only needed for operators with Manual approval mode - - Equivalent to `/olm:approve` command - -## Notes +--- -- **Automatic Updates**: Operators with `installPlanApproval: Automatic` will upgrade automatically when new versions are available in their channel -- **Manual Approval**: Operators with `installPlanApproval: Manual` require explicit approval via `--approve` flag or `/olm:approve` command -- **Channel Switching**: Changing channels may result in upgrade or downgrade depending on the versions in each channel -- **Rollback**: OLM has limited rollback support. Switching back to the previous channel may work, but data migration issues may occur -- **Upgrade Timing**: Upgrades happen according to the operator's upgrade strategy (some may cause downtime) +## OLM v1 Implementation -## Troubleshooting +### Steps -- **No updates available**: - ```bash - # Check current version - oc get csv -n {namespace} - - # Check available versions - oc get packagemanifest {operator-name} -n openshift-marketplace -o json - ``` +1. **Parse Arguments**: + - `` (required) + - `--channel `: Switch channel + - `--version `: Pin to specific version + +2. **Get ClusterExtension**: + ```bash + EXT=$(kubectl get clusterextension {extension-name} -o json) + CURRENT_VERSION=$(echo "$EXT" | jq -r '.status.resolution.bundle.version') + CURRENT_CHANNEL=$(echo "$EXT" | jq -r '.status.resolution.bundle.channel // .spec.source.catalog.channel') + ``` -- **Upgrade stuck or pending**: - ```bash - # Check InstallPlan status - oc get installplan -n {namespace} - - # Check for events - oc get events -n {namespace} --sort-by='.lastTimestamp' | tail -20 - ``` +3. **Update ClusterExtension**: + ```bash + if [ -n "{channel}" ]; then + echo "Updating to channel: {channel}" + kubectl patch clusterextension {extension-name} --type=merge \ + -p '{"spec":{"source":{"catalog":{"channel":"{channel}"}}}}' + elif [ -n "{version}" ]; then + echo "Pinning to version: {version}" + kubectl patch clusterextension {extension-name} --type=merge \ + -p '{"spec":{"source":{"catalog":{"version":"{version}"}}}}' + fi + ``` -- **Manual approval required**: - ```bash - # List pending InstallPlans - oc get installplan -n {namespace} -o json | jq '.items[] | select(.spec.approved==false)' - - # Approve specific InstallPlan - /olm:approve {operator-name} {namespace} - ``` +4. **Monitor Upgrade**: + ```bash + echo "Monitoring upgrade..." + for i in {1..60}; do + NEW_VERSION=$(kubectl get clusterextension {extension-name} \ + -o jsonpath='{.status.resolution.bundle.version}') + INSTALLED=$(kubectl get clusterextension {extension-name} \ + -o jsonpath='{.status.conditions[?(@.type=="Installed")].status}') + + if [ "$INSTALLED" == "True" ] && [ "$NEW_VERSION" != "$CURRENT_VERSION" ]; then + echo "βœ“ Upgraded: $CURRENT_VERSION β†’ $NEW_VERSION" + break + fi + sleep 5 + done + ``` -- **Upgrade failed**: - ```bash - # Check CSV status - oc describe csv -n {namespace} - - # Check operator logs - oc logs -n {namespace} deployment/{operator-deployment} - - # Run diagnostics - /olm:diagnose {operator-name} {namespace} - ``` +--- -- **Rollback needed**: - - OLM doesn't have built-in rollback - - Can try switching back to previous channel, but may have issues: - ```bash - oc patch subscription {operator-name} -n {namespace} \ - --type merge --patch '{"spec":{"channel":"{old-channel}"}}' - ``` - - Consider backup/restore of custom resources before upgrading +## Return Value +- Upgrade status and new version +- Any errors or required actions -## Related Commands +## Examples -- `/olm:status ` - Check current version and available updates -- `/olm:approve ` - Approve pending InstallPlans -- `/olm:install ` - Install an operator -- `/olm:diagnose ` - Diagnose upgrade issues +```bash +# Upgrade to latest in channel +/olm:upgrade cert-manager --version v1 -## Additional Resources +# Switch channel +/olm:upgrade postgres-operator --channel stable --version v0 -- [Red Hat OpenShift: Updating Installed Operators](https://docs.redhat.com/en/documentation/openshift_container_platform/4.20/html/operators/administrator-tasks#olm-updating-operators) -- [Red Hat OpenShift: Approving Operator Upgrades](https://docs.redhat.com/en/documentation/openshift_container_platform/4.20/html/operators/administrator-tasks#olm-approving-operator-upgrades_olm-updating-operators) -- [Operator Lifecycle Manager Documentation](https://olm.operatorframework.io/) +# Approve pending upgrade +/olm:upgrade prometheus --approve --version v0 +``` +## Arguments +- **$1** (name): Operator/extension name (required) +- **$2** (namespace): Namespace (v0 only, optional) +- **--channel **: Switch to channel +- **--version **: Pin to version (v1 only) +- **--approve**: Approve InstallPlan (v0 only) +- **--version v0|v1**: OLM version +## Notes +- **v0**: Updates Subscription channel or approves InstallPlan +- **v1**: Updates ClusterExtension version/channel constraint +- Channel switching may trigger immediate upgrade +- Monitor upgrade with `/olm:status` diff --git a/plugins/olm/commands/use-version.md b/plugins/olm/commands/use-version.md new file mode 100644 index 0000000..4b4eaf5 --- /dev/null +++ b/plugins/olm/commands/use-version.md @@ -0,0 +1,224 @@ +--- +description: Set or view the OLM version context for this session +argument-hint: [v0|v1|clear] +--- + +## Name +olm:use-version + +## Synopsis +``` +/olm:use-version [v0|v1|clear] +``` + +## Description +The `olm:use-version` command manages the OLM version context for your current session. This allows you to set the OLM version once and have all subsequent OLM commands use that version automatically, eliminating the need to specify `--version` flag on every command. + +**Why use this command:** +- Reduces repetition when working with multiple OLM commands +- Makes workflows cleaner and easier to read +- Provides explicit control over which OLM version is being used +- Can be changed at any time during your session + +**Context storage:** The version context is stored in `.work/olm/context.txt` and persists for the duration of your session. + +## Implementation + +1. **Parse the argument**: + - If no argument provided: Display current context + - If argument is `v0` or `v1`: Set context to that version + - If argument is `clear`: Remove the context file + - If argument is invalid: Show error and usage help + +2. **Create context directory** (if setting version): + ```bash + mkdir -p .work/olm + ``` + +3. **Handle "view current context" (no argument)**: + ```bash + if [ -f .work/olm/context.txt ]; then + CURRENT_VERSION=$(cat .work/olm/context.txt) + echo "Current OLM version context: $CURRENT_VERSION" + else + echo "No OLM version context is set" + echo "" + echo "To set a context:" + echo " /olm:use-version v0 (for traditional OLM)" + echo " /olm:use-version v1 (for next-generation OLM)" + echo "" + echo "Or use --version flag on each command:" + echo " /olm:install --version v0 [options]" + echo "" + echo "Not sure which version to use? Run:" + echo " /olm:detect-version" + fi + exit 0 + ``` + +4. **Handle "set to v0"**: + ```bash + echo "v0" > .work/olm/context.txt + echo "βœ“ OLM version context set to: v0" + echo "" + echo "All OLM commands will now use OLM v0 (traditional OLM) by default." + echo "You can override this per-command with the --version flag." + echo "" + echo "OLM v0 uses:" + echo " - Resources: Subscription, CSV, InstallPlan, OperatorGroup" + echo " - Catalogs: CatalogSource, PackageManifest" + echo " - CLI: oc (OpenShift CLI)" + echo "" + echo "To switch to v1: /olm:use-version v1" + echo "To clear context: /olm:use-version clear" + ``` + +5. **Handle "set to v1"**: + ```bash + echo "v1" > .work/olm/context.txt + echo "βœ“ OLM version context set to: v1" + echo "" + echo "All OLM commands will now use OLM v1 (next-generation OLM) by default." + echo "You can override this per-command with the --version flag." + echo "" + echo "OLM v1 uses:" + echo " - Resources: ClusterExtension, ClusterCatalog" + echo " - RBAC: User-managed ServiceAccount + ClusterRole" + echo " - CLI: kubectl" + echo "" + echo "To switch to v0: /olm:use-version v0" + echo "To clear context: /olm:use-version clear" + ``` + +6. **Handle "clear"**: + ```bash + if [ -f .work/olm/context.txt ]; then + rm -f .work/olm/context.txt + echo "βœ“ OLM version context cleared" + echo "" + echo "You will need to specify --version flag on each command, or set a new context." + else + echo "No context was set" + fi + ``` + +7. **Handle invalid argument**: + ```bash + echo "❌ Invalid argument: $1" + echo "" + echo "Usage: /olm:use-version [v0|v1|clear]" + echo "" + echo "Options:" + echo " v0 - Set context to OLM v0 (traditional OLM)" + echo " v1 - Set context to OLM v1 (next-generation OLM)" + echo " clear - Clear the context" + echo " (none) - View current context" + exit 1 + ``` + +## Return Value +- **Success (view)**: Displays current context or message if not set +- **Success (set)**: Confirmation message with version set and helpful information +- **Success (clear)**: Confirmation that context was cleared +- **Error**: Invalid argument with usage help +- **Format**: Human-readable status messages + +## Examples + +1. **View current context**: + ``` + /olm:use-version + ``` + + Output (when set): + ``` + Current OLM version context: v0 + ``` + + Output (when not set): + ``` + No OLM version context is set + + To set a context: + /olm:use-version v0 (for traditional OLM) + /olm:use-version v1 (for next-generation OLM) + ``` + +2. **Set context to OLM v0**: + ``` + /olm:use-version v0 + ``` + + Output: + ``` + βœ“ OLM version context set to: v0 + + All OLM commands will now use OLM v0 (traditional OLM) by default. + You can override this per-command with the --version flag. + + OLM v0 uses: + - Resources: Subscription, CSV, InstallPlan, OperatorGroup + - Catalogs: CatalogSource, PackageManifest + - CLI: oc (OpenShift CLI) + ``` + +3. **Set context to OLM v1**: + ``` + /olm:use-version v1 + ``` + + Output: + ``` + βœ“ OLM version context set to: v1 + + All OLM commands will now use OLM v1 (next-generation OLM) by default. + You can override this per-command with the --version flag. + + OLM v1 uses: + - Resources: ClusterExtension, ClusterCatalog + - RBAC: User-managed ServiceAccount + ClusterRole + - CLI: kubectl + ``` + +4. **Clear context**: + ``` + /olm:use-version clear + ``` + + Output: + ``` + βœ“ OLM version context cleared + + You will need to specify --version flag on each command, or set a new context. + ``` + +5. **Typical workflow**: + ``` + # Set context once + /olm:use-version v0 + + # All commands now use v0 + /olm:search cert-manager + /olm:install cert-manager-operator + /olm:status cert-manager-operator + + # Switch to v1 for different workflow + /olm:use-version v1 + /olm:install argocd --channel stable + ``` + +## Arguments +- **$1** (version): Optional argument specifying the action + - `v0`: Set context to OLM v0 (traditional OLM with Subscription/CSV) + - `v1`: Set context to OLM v1 (next-generation OLM with ClusterExtension) + - `clear`: Remove the context, requiring explicit --version flags + - (empty): View the current context + +## Notes + +- **Persistence**: The context is stored in `.work/olm/context.txt` which is ignored by git (in `.gitignore`) +- **Session-scoped**: The context persists for your current work session but does not survive across different machines or repository clones +- **Override**: You can always override the context with `--version` flag on any command +- **No default**: If no context is set and no `--version` flag is provided, commands will error with helpful guidance +- **Switching**: You can switch between v0 and v1 at any time without affecting already-installed operators/extensions + diff --git a/plugins/olm/skills/version-detection/SKILL.md b/plugins/olm/skills/version-detection/SKILL.md new file mode 100644 index 0000000..59b2ee9 --- /dev/null +++ b/plugins/olm/skills/version-detection/SKILL.md @@ -0,0 +1,341 @@ +--- +name: OLM Version Detection +description: Determine which OLM version to use based on context and flags +--- + +# OLM Version Detection Skill + +This skill provides the logic for determining which OLM version (v0 or v1) to use in unified OLM commands. All unified commands should use this logic at the beginning of their implementation. + +## When to Use This Skill + +Use this skill in any OLM command that supports both v0 and v1 implementations: +- `/olm:install` +- `/olm:list` +- `/olm:search` +- `/olm:status` +- `/olm:uninstall` +- `/olm:upgrade` +- `/olm:catalog` + +## Prerequisites + +- User has access to the workspace directory (for reading `.work/olm/context.txt`) +- Command arguments have been parsed + +## Version Determination Logic + +### Priority Order + +The version is determined in this order (highest to lowest priority): + +1. **`--version` flag in command arguments** (overrides everything) +2. **Context file** at `.work/olm/context.txt` (session default) +3. **No version found** β†’ Error with helpful message + +### Implementation Steps + +#### Step 1: Check for --version Flag + +Parse the command arguments for a `--version` flag: + +```bash +OLM_VERSION="" + +# Parse arguments for --version flag +for arg in "$@"; do + case $arg in + --version=*) + OLM_VERSION="${arg#*=}" + shift + ;; + --version) + shift + OLM_VERSION="$1" + shift + ;; + esac +done +``` + +#### Step 2: Check Context File (if flag not provided) + +If no `--version` flag was found, check the context file: + +```bash +if [ -z "$OLM_VERSION" ]; then + if [ -f .work/olm/context.txt ]; then + OLM_VERSION=$(cat .work/olm/context.txt) + echo "Using OLM version from context: $OLM_VERSION" + echo "" + fi +fi +``` + +#### Step 3: Validate Version + +Ensure the version is valid (v0 or v1): + +```bash +if [ -n "$OLM_VERSION" ]; then + if [ "$OLM_VERSION" != "v0" ] && [ "$OLM_VERSION" != "v1" ]; then + echo "❌ Invalid OLM version: $OLM_VERSION" + echo "" + echo "Valid versions are: v0, v1" + exit 1 + fi +fi +``` + +#### Step 4: Error if No Version Found + +If still no version is found, display a helpful error: + +```bash +if [ -z "$OLM_VERSION" ]; then + echo "❌ OLM version not specified" + echo "" + echo "You must explicitly specify the OLM version:" + echo "" + echo "Option 1 - Set context for this session:" + echo " /olm:use-version v0 (for traditional OLM)" + echo " /olm:use-version v1 (for next-generation OLM)" + echo "" + echo "Option 2 - Use per-command flag:" + echo " /olm:install --version v0 [options]" + echo " /olm:install --version v1 [options]" + echo "" + echo "Not sure which version to use?" + echo " /olm:detect-version" + echo "" + exit 1 +fi +``` + +#### Step 5: Branch to Version-Specific Implementation + +Now branch based on the determined version: + +```bash +if [ "$OLM_VERSION" == "v0" ]; then + echo "Using OLM v0 (traditional OLM)" + echo "" + # ... Execute v0-specific implementation + +elif [ "$OLM_VERSION" == "v1" ]; then + echo "Using OLM v1 (next-generation OLM)" + echo "" + # ... Execute v1-specific implementation +fi +``` + +## Complete Reusable Template + +Here's a complete template that can be used in any unified command: + +```bash +#!/bin/bash + +# ============================================================================ +# OLM Version Detection (Shared Logic) +# ============================================================================ + +OLM_VERSION="" + +# Step 1: Check for --version flag +for arg in "$@"; do + case $arg in + --version=*) + OLM_VERSION="${arg#*=}" + ;; + --version) + # Next argument is the version + NEXT_IS_VERSION=true + ;; + *) + if [ "$NEXT_IS_VERSION" == "true" ]; then + OLM_VERSION="$arg" + NEXT_IS_VERSION=false + fi + ;; + esac +done + +# Step 2: Check context file if flag not provided +if [ -z "$OLM_VERSION" ]; then + if [ -f .work/olm/context.txt ]; then + OLM_VERSION=$(cat .work/olm/context.txt) + echo "ℹ️ Using OLM version from context: $OLM_VERSION" + echo "" + fi +fi + +# Step 3: Validate version +if [ -n "$OLM_VERSION" ]; then + if [ "$OLM_VERSION" != "v0" ] && [ "$OLM_VERSION" != "v1" ]; then + echo "❌ Invalid OLM version: $OLM_VERSION" + echo "" + echo "Valid versions are: v0, v1" + exit 1 + fi +fi + +# Step 4: Error if no version found +if [ -z "$OLM_VERSION" ]; then + cat << 'EOF' +❌ OLM version not specified + +You must explicitly specify the OLM version: + +Option 1 - Set context for this session: + /olm:use-version v0 (for traditional OLM) + /olm:use-version v1 (for next-generation OLM) + +Option 2 - Use per-command flag: + /olm:install --version v0 [options] + /olm:install --version v1 [options] + +Not sure which version to use? + /olm:detect-version + +EOF + exit 1 +fi + +# ============================================================================ +# Version-Specific Implementation +# ============================================================================ + +if [ "$OLM_VERSION" == "v0" ]; then + echo "═══════════════════════════════════════════════════════════════" + echo "Using OLM v0 (Traditional OLM)" + echo "═══════════════════════════════════════════════════════════════" + echo "" + + # ... OLM v0 implementation here ... + +elif [ "$OLM_VERSION" == "v1" ]; then + echo "═══════════════════════════════════════════════════════════════" + echo "Using OLM v1 (Next-Generation OLM)" + echo "═══════════════════════════════════════════════════════════════" + echo "" + + # ... OLM v1 implementation here ... +fi +``` + +## Usage in Command Files + +In your command markdown files, reference this skill in the Implementation section: + +```markdown +## Implementation + +1. **Determine OLM version** (see [skills/version-detection/SKILL.md](../../skills/version-detection/SKILL.md)): + - Check for `--version` flag in arguments + - If no flag: Check context file `.work/olm/context.txt` + - If neither: Display error and exit + - Validate version is `v0` or `v1` + +2. **Branch to version-specific implementation**: + +--- + +### OLM v0 Implementation + +[v0-specific steps here] + +--- + +### OLM v1 Implementation + +[v1-specific steps here] +``` + +## Examples + +### Example 1: Using Context + +```bash +# User sets context +/olm:use-version v0 + +# Command runs, reads context +/olm:install cert-manager-operator +# β†’ Detects v0 from .work/olm/context.txt +# β†’ Executes v0 implementation +``` + +### Example 2: Using Flag + +```bash +# No context set, user provides flag +/olm:install cert-manager --version v1 --channel stable +# β†’ Detects v1 from --version flag +# β†’ Executes v1 implementation +``` + +### Example 3: Flag Overrides Context + +```bash +# User sets context to v0 +/olm:use-version v0 + +# But uses flag to override +/olm:install argocd --version v1 --channel stable +# β†’ Flag takes precedence +# β†’ Executes v1 implementation +``` + +### Example 4: No Version Specified (Error) + +```bash +# No context set, no flag provided +/olm:install cert-manager +# β†’ No version found +# β†’ Displays error message with help +# β†’ Exits with code 1 +``` + +## Testing Checklist + +When implementing a unified command, test these scenarios: + +- [ ] Command works with `--version v0` flag +- [ ] Command works with `--version v1` flag +- [ ] Command works with v0 context set +- [ ] Command works with v1 context set +- [ ] Command errors helpfully with no version +- [ ] Flag overrides context correctly +- [ ] Invalid version value shows error +- [ ] Error messages are clear and actionable + +## Best Practices + +1. **Always use this skill first** - Version detection should be the first step in unified commands +2. **Clear separation** - Keep v0 and v1 implementations clearly separated in the code +3. **Consistent messaging** - Use the same error messages across all commands +4. **No defaults** - Never default to v0 or v1, always require explicit selection +5. **Helpful errors** - Always guide users toward solutions when version is missing +6. **Context indicator** - Show which version is being used (from context or flag) + +## Troubleshooting + +### Issue: Context file not readable + +**Symptom**: Command can't read `.work/olm/context.txt` even though it exists + +**Solution**: Check file permissions and ensure `.work/olm/` directory exists and is accessible + +### Issue: Version persists unexpectedly + +**Symptom**: User thinks they cleared context but commands still use a version + +**Solution**: Check if `.work/olm/context.txt` still exists. Run `/olm:use-version` to verify. + +### Issue: Flag not recognized + +**Symptom**: `--version v0` is not parsed correctly + +**Solution**: Ensure flag parsing happens before positional arguments. The version detection logic should be at the very beginning of command parsing. +