Skip to main content

gmp-migrate

Run the gmp-migrate CLI tool to convert Prometheus Operator manifests (PodMonitor, ServiceMonitor) to Google Managed Prometheus (GMP) CRDs (PodMonitoring, ClusterPodMonitoring), and reconcile generated TODOs, port placeholders, and errors.

Source facts

Repository
GoogleCloudPlatform/prometheus-engine
Last source activity
August 27, 2026 at 09:50
Detected SKILL.md language
English
Stars
233
Forks
109

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
gmp-migrate
description
Run the gmp-migrate CLI tool to convert Prometheus Operator manifests (PodMonitor, ServiceMonitor) to Google Managed Prometheus (GMP) CRDs (PodMonitoring, ClusterPodMonitoring), and reconcile generated TODOs, port placeholders, and errors.
# GMP Migration & Reconciliation Skill This skill guides agents through executing the migration CLI tool, interpreting migration reports, diagnosing `Stderr` logs, resolving safety guardrails and `gmp.googleapis.com/todo-*` annotations, and safely validating converted GMP manifests. --- ## 1. Tool Execution Interface > [!NOTE] > All commands in this skill invoke the `gmp-migrate` binary. If the underlying CLI binary name or command syntax changes in the future, only this invocation section needs to be updated. ### Core CLI Invocations 1. **Default Mode (Ready-only)**: Emits strictly 100% ready manifests to `Stdout`. Omits any best-effort drafts requiring human/agent review. ```bash gmp-migrate -f <input-path> > ready_manifests.yaml 2> migration.log ``` 2. **Full Review Mode (`--all` / `-a`)**: Emits all converted manifests to `Stdout`, including best-effort draft configurations with inline `gmp.googleapis.com/todo-*` annotations for human / agent reconciliation. ```bash gmp-migrate --all -f <input-path> > all_manifests.yaml 2> migration.log ``` 3. **Multiple Input Sources (Monitors + Backing Services/Secrets)**: ```bash gmp-migrate --all -f path/to/monitors/ -f path/to/services/ > all_manifests.yaml 2> migration.log ``` 4. **Live Cluster Ingestion via Stdin**: ```bash kubectl get podmonitors,servicemonitors,services,configmaps,secrets -A -o yaml | gmp-migrate --all -f - > all_manifests.yaml 2> migration.log ``` --- ## 2. Input Discovery Strategy 1. **Local Files**: - Check the workspace for Prometheus Operator YAML manifests (`kind: PodMonitor` or `kind: ServiceMonitor`). - When migrating local files, also include directories containing backing `kind: Service`, `kind: Secret`, and `kind: ConfigMap` resources so the tool can perform cross-resource port and auth resolution. 2. **Live Cluster Context**: - If no local manifests exist, or if the user asks to migrate an active cluster, stream cluster resources directly via `kubectl ... | gmp-migrate --all -f -`. 3. **Ambiguous Source**: - If both local files and an active `kubectl` context exist, ask the user whether they want to migrate local manifests or pull live resources from the cluster. --- ## 3. Exit Code, Stderr Logs & Diagnostic Handling The CLI strictly separates streams: converted YAML manifests are written to `Stdout`, while diagnostics and summary tables are written to `Stderr`. Workload selectors (`spec.selector.matchLabels` and `spec.selector.matchExpressions`) remain **100% pure and untouched**. ``` ========================================= Migration Complete Summary: Successfully Migrated: X Migrated with Warnings: Y Migrated with Action Items: Z Skipped (Unsupported): W Failed: V ========================================= ``` | Exit Code / Report | Status | Stream Behavior & Recommended Agent Action | |:--------------------------------------------------------------|:-------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Exit Code 0** (`ActionItemsCount == 0`, `FailedCount == 0`) | Clean Parity | All manifests are 100% ready. Written to `Stdout`. Proceed directly to dry-run verification and diff presentation. | | **Exit Code 1** (`ActionItemsCount > 0`, `FailedCount == 0`) | Action Items Present | • Default mode: emits only ready manifests to `Stdout` and notes omitted drafts on `Stderr`.<br>• `--all` mode: emits all manifests (including drafts with inline `gmp.googleapis.com/todo-*` annotations) to `Stdout`.<br>Follow Section 5 to reconcile drafts. | | **Exit Code 1** (`FailedCount > 0`) | Fatal Conversion Failure | Zero manifests were written to `Stdout` (0 bytes). Inspect `Stderr` logs to identify missing dependencies or malformed YAML inputs, resolve them, and re-run. | ### Inspecting CLI Diagnostics in `Stderr` Logs: When investigating why a TODO or warning was added, inspect the `Stderr` log (or `migration.log`) for pre-scoped resource logs: ```bash # Filter logs for a specific resource grep "PodMonitor:default/my-app" migration.log # Filter all warnings and fatal errors grep -E "\[WARNING\]|\[ERROR\]" migration.log ``` --- ## 4. Secret Creation & Namespacing Rules * **`PodMonitoring` (Namespaced CRD)**: Kubernetes forbids cross-namespace Secret references. If a Secret or converted ConfigMap is referenced, **it must exist in the same namespace as the `PodMonitoring`**. `gmp-migrate` automatically generates a companion `Secret` clone in every target namespace where the `PodMonitoring` is created. * **`ClusterPodMonitoring` (Cluster-Scoped CRD)**: Supports an explicit `namespace` field in `SecretKeySelector`. Companion Secrets live in a central namespace (e.g. `gmp-system`), and `secret.namespace` is explicitly populated. --- ## 5. Action Plan Catalog for TODO Reconciliation > [!CAUTION] > **Strict Read-Only Investigation Policy**: > All `kubectl` commands executed during investigation (Recipes 1–6) MUST be strictly READ-ONLY (`get`, `describe`, `logs`, `--dry-run=client`). > Under NO circumstances should an agent run state-changing commands (`kubectl apply`, `kubectl create`, `kubectl patch`, `kubectl delete`) against a live cluster without reaching Section 7 and receiving explicit user approval. All TODO annotations follow the format: `gmp.googleapis.com/todo-N: "[WARNING|ERROR] <reason> ACTION: <action>"`. Match the placeholder or annotation message against the recipes below: --- ### Recipe 1: Port & Pod Selector Resolution #### 1.1 Unresolved Named Port (`TODO_RESOLVE_PORT_<NAME>`) * **Annotation**: `[WARNING] Named port "<name>" was not found on Service "<svc>"... ACTION: Replace TODO_RESOLVE_PORT_<NAME> with the target container port name or number.` * **Commands**: ```bash kubectl get svc <service-name> -n <namespace> -o jsonpath='{.spec.ports}' | jq . kubectl get pod -n <namespace> -l <selector> -o jsonpath='{.items[0].spec.containers[*].ports}' | jq . ``` * **Resolution**: 1. If Service `targetPort` is an integer (e.g. `8080`), replace placeholder with integer `8080`. 2. If Service `targetPort` is a named string (e.g. `http-metrics`), set `port: http-metrics`. 3. If Service `targetPort` is omitted, replace with the Service's integer `port`. * **Diff**: ```diff spec: endpoints: - - port: TODO_RESOLVE_PORT_METRICS + - port: 8080 interval: 30s ``` #### 1.2 Missing Backing Service (`TODO_RESOLVE_PORT` & `TODO_SET_POD_LABELS`) * **Context**: `gmp-migrate` emits `TODO_SET_POD_LABELS: TODO_SET_POD_LABELS` as a safe guardrail placeholder. Replace this placeholder with the complete set of pod template labels for the target workload. * **Annotation**: `[ERROR] Corresponding Kubernetes Service was not found... ACTION: Define target pod selector in 'spec.selector.matchLabels' and verify endpoint ports.` * **Commands**: ```bash kubectl get svc -n <namespace> -o wide kubectl get deployment,statefulset,daemonset -n <namespace> -o wide ``` * **Agent Interactive Step**: - If a matching Service or workload is identified, copy its pod label selector into `spec.selector.matchLabels` and resolve endpoint ports. - If multiple ambiguous workloads match, prompt the user: > *"Could not find a backing Service for `<name>`. Discovered candidate workloads: `[app=payment-processor, app=payment-worker]`. Please confirm the target pod labels."* * **Diff**: ```diff metadata: - annotations: - gmp.googleapis.com/todo-1: "[ERROR] Corresponding Kubernetes Service was not found..." spec: selector: matchLabels: - TODO_SET_POD_LABELS: TODO_SET_POD_LABELS + app.kubernetes.io/name: payment-processor + app.kubernetes.io/component: backend endpoints: - - port: TODO_RESOLVE_PORT + - port: 9102 ``` #### 1.3 Missing Endpoint Port (`TODO_SET_PORT`) * **Annotation**: `[ERROR] Endpoint [N] does not specify a 'port' or 'targetPort'...` * **Commands**: ```bash kubectl get pod -n <namespace> -l <selector> -o jsonpath='{.items[0].spec.containers[*].ports}' | jq . ``` * **Agent Interactive Step**: - If a single container metrics port is found, resolve to that port. - If the pod has multiple containers or multiple ports (e.g. `8080` vs `15090`), **do not guess**—prompt the user to choose the intended metrics port. * **Diff**: ```diff spec: endpoints: - - port: TODO_SET_PORT + - port: metrics ``` --- ### Recipe 2: Missing or Incomplete Secrets & ConfigMaps #### Security Policy: Zero Secret Ingestion & Human-In-The-Loop * **Do Not Read Secrets via CLI**: Agents must never run `kubectl get secret` to inspect secret payloads. Reading cluster secrets risks leaking sensitive credentials (passwords, tokens, private keys) into agent context logs and transcripts. * **Dual-Path User Handoff**: When a Secret placeholder (`TODO_SET_USERNAME_FROM_SECRET_*` or `TODO_SET_CLIENT-ID_FROM_SECRET_*`) is encountered, the agent must output the targeted `jsonpath` command for the user to run in their terminal, along with the exact resource identifier, file link, field path, and resolution options: 1. **Option A (Interactive)**: The user replies in chat with the non-sensitive string (e.g. `username: <output>`) and the agent updates the manifest and removes the TODO annotation. 2. **Option B (Direct Edit)**: The user updates the manifest directly using the provided file link, target field path, and diff snippet. #### 2.1 Missing Source Secret / ConfigMap (`TODO_SET_<KEY>_FROM_<KIND>_<NAME>`) * **Annotation**: `[ERROR] Referenced SECRET "<name>" for key "<key>" was not found in migration inputs...` * **Agent Handoff Output Format**: In GMP, `basicAuth.username` is configured directly as a string, while `password` remains securely referenced from Secret `<secret-name>`. ### 1. Retrieve the username in your terminal: ```bash kubectl get secret <secret-name> -n <namespace> -o jsonpath='{.data.<key>}' | base64 -d ``` ### 2. Resolution Options: * **Option A (Interactive)**: Reply with `The username is: <value>` and I will update the manifest and remove the TODOs for you. * **Option B (Direct Edit)**: * **Resource**: `PodMonitoring:<namespace>/<name>` * **File**: [`<path-to-manifest>.yaml`](file:///<path-to-manifest>.yaml#L<line>) * **Target Field**: `spec.endpoints[<index>].basicAuth.username` * **Diff**: ```diff spec: endpoints: - basicAuth: - username: TODO_SET_<KEY>_FROM_SECRET_<NAME> + username: "<your-retrieved-username>" password: secret: name: <secret-name> key: password ```
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub