This skill should be used when tracing ManifestWork resources through the Maestro system to find relationships between user-created work names, resource IDs, and applied manifests, or to debug...
Trace ManifestWork resources through the complete Maestro lifecycle, connecting user-created work names, database resource IDs, and applied manifests on the management cluster.
Use this skill when you need to:
For debugging request lifecycle issues, use the trace-resource-request skill after obtaining the resource ID:
Example workflow:
trace-resource-request with that resource ID to trace request through logsCommon scenario: You have a manifest that isn't working correctly. Use this skill to map the manifest to its resource ID, then use trace-resource-request to analyze the log flow and identify where the request failed (server, broker, agent, or status updates).
The Maestro system transforms user-created ManifestWorks through multiple stages:
User Work Name āā Resource ID (DB) āā AppliedManifestWork āā Applied Manifests
This skill traces these relationships bidirectionally, combining database queries and kubectl commands to provide a complete view of a ManifestWork's lifecycle.
IMPORTANT: In Maestro colloquial usage, ManifestWork and resource bundle are the same concept and are used interchangeably:
/api/maestro/v1/resource-bundles)When users refer to "resource bundles," they are talking about ManifestWork resources. Both terms describe a collection of Kubernetes manifests packaged together for delivery to target clusters. The database stores these in the resources table, while the Kubernetes cluster manages them as ManifestWork/AppliedManifestWork CRs.
CRITICAL: Maestro uses a dual-cluster architecture:
When tracing, you must switch between cluster contexts:
User-Created Work Name: The name assigned by the user when creating a ManifestWork via gRPC client (e.g., e44ec579-9646-549a-b679-db8d19d6da37). Stored in DB as payload->'metadata'->>'name'.
Resource ID: The database primary key and CloudEvent resourceid (e.g., 55c61e54-a3f6-563d-9fec-b1fe297bdfdb). Used as spec.manifestWorkName in AppliedManifestWork.
AppliedManifestWork Name: Format {agentID}-{resourceID} (e.g., f1d8a1049b93dffc1929d57a719c3a09a4dcbfe0cd6e42840325be3b2dde73c8-55c61e54-a3f6-563d-9fec-b1fe297bdfdb).
Manifest: The actual Kubernetes resource (Deployment, Service, etc.) with an ownerReference to the AppliedManifestWork.
Ask the user which identifier they have:
Option A: Resource ID
resource_id (e.g., 55c61e54-a3f6-563d-9fec-b1fe297bdfdb)Option B: Manifest Details
manifest_kind (e.g., "deployment", "service", "configmap")manifest_name (e.g., "maestro-e2e-upgrade-test")manifest_namespace (optional, defaults to "default")Option C: User-Created Work Name
work_name (e.g., e44ec579-9646-549a-b679-db8d19d6da37)CRITICAL: Verify access to BOTH clusters (svc and mgmt)
Ask the user which setup they have:
If the user has one kubeconfig file with contexts for both clusters:
Ask for cluster context names:
svc-cluster-contextmgmt-cluster-contextVerify kubectl and contexts:
# Verify kubectl is available
which kubectl
# List available contexts
kubectl config get-contexts
# Verify service cluster access (database)
kubectl config use-context <svc-cluster-context>
kubectl cluster-info
kubectl get namespace maestro 2>/dev/null
# Verify management cluster access (agent)
kubectl config use-context <mgmt-cluster-context>
kubectl cluster-info
kubectl get appliedmanifestworks -A 2>/dev/null | head -n 5
Common context names:
aro-hcp-int, svc-cluster, maestro-servermgmt-cluster, management, hub-clusterIf the user has two separate kubeconfig files:
Ask for kubeconfig file paths:
/path/to/svc-kubeconfig.yaml/path/to/mgmt-kubeconfig.yamlVerify kubectl and kubeconfig files:
# Verify kubectl is available
which kubectl
# Verify service cluster kubeconfig (database)
kubectl --kubeconfig=/path/to/svc-kubeconfig.yaml cluster-info
kubectl --kubeconfig=/path/to/svc-kubeconfig.yaml get namespace maestro 2>/dev/null
# Verify management cluster kubeconfig (agent)
kubectl --kubeconfig=/path/to/mgmt-kubeconfig.yaml cluster-info
kubectl --kubeconfig=/path/to/mgmt-kubeconfig.yaml get appliedmanifestworks -A 2>/dev/null | head -n 5
If using separate files becomes cumbersome, merge them into one:
# Backup existing kubeconfig
cp ~/.kube/config ~/.kube/config.backup
# Merge kubeconfigs
KUBECONFIG=/path/to/svc-kubeconfig.yaml:/path/to/mgmt-kubeconfig.yaml \
kubectl config view --flatten > ~/.kube/config
# Verify merged contexts
kubectl config get-contexts
# Rename contexts for clarity (optional)
kubectl config rename-context <old-svc-context> svc-cluster
kubectl config rename-context <old-mgmt-context> mgmt-cluster
After merging, use Option A (contexts) for all future traces.
If prerequisites are missing:
Step 3A.1: Query Database for User Work Name
Switch to service cluster context:
kubectl config use-context <svc-cluster-context>
Determine database connection method:
# Check for postgres-breakglass (ARO-HCP INT)
kubectl -n maestro get pods -l app=postgres-breakglass 2>/dev/null
# Check for maestro-db (Service cluster)
kubectl -n maestro get pods -l name=maestro-db 2>/dev/null
Execute SQL query:
SELECT id,
payload->'metadata'->>'name' AS user_work_name,
payload->'spec'->'workload'->'manifests' AS manifests,
created_at, updated_at, deleted_at
FROM resources
WHERE id = '<resource_id>';
Example:
SELECT id,
payload->'metadata'->>'name' AS user_work_name,
payload->'spec'->'workload'->'manifests' AS manifests,
created_at, updated_at, deleted_at
FROM resources
WHERE id = '55c61e54-a3f6-563d-9fec-b1fe297bdfdb';
Step 3A.2: Query Cluster for AppliedManifestWork
Switch to management cluster context:
kubectl config use-context <mgmt-cluster-context>
Query for AppliedManifestWork:
# Find AppliedManifestWork by manifestWorkName
resource_id="<resource_id>"
amw_name=$(kubectl get appliedmanifestworks -o json | \
jq -r ".items[] | select(.spec.manifestWorkName == \"$resource_id\") | .metadata.name")
if [ -z "$amw_name" ]; then
echo "WARNING: AppliedManifestWork not found. Work may be deleted or not yet applied."
else
echo "AppliedManifestWork: $amw_name"
# Get applied resources
kubectl get appliedmanifestwork "$amw_name" -o yaml
# List applied manifests
kubectl get appliedmanifestwork "$amw_name" -o jsonpath='{range .status.appliedResources[*]}{.resource}{"\t"}{.namespace}{"\t"}{.name}{"\n"}{end}'
fi
Step 3B.1: Get AppliedManifestWork from Manifest
Switch to management cluster context (manifests are on mgmt cluster):
kubectl config use-context <mgmt-cluster-context>
Query for manifest and extract owner:
manifest_kind="<manifest_kind>"
manifest_name="<manifest_name>"
manifest_namespace="${manifest_namespace:-default}"
# Get manifest and extract ownerReference
if [ -n "$manifest_namespace" ]; then
amw_name=$(kubectl get "$manifest_kind" "$manifest_name" -n "$manifest_namespace" \
-o jsonpath='{.metadata.ownerReferences[?(@.kind=="AppliedManifestWork")].name}' 2>/dev/null)
else
amw_name=$(kubectl get "$manifest_kind" "$manifest_name" \
-o jsonpath='{.metadata.ownerReferences[?(@.kind=="AppliedManifestWork")].name}' 2>/dev/null)
fi
if [ -z "$amw_name" ]; then
echo "ERROR: Manifest not found or has no AppliedManifestWork owner"
exit 1
fi
echo "AppliedManifestWork: $amw_name"
Step 3B.2: Extract Resource ID from AppliedManifestWork
# Get manifestWorkName (Resource ID) from AppliedManifestWork
resource_id=$(kubectl get appliedmanifestwork "$amw_name" \
-o jsonpath='{.spec.manifestWorkName}' 2>/dev/null)
if [ -z "$resource_id" ]; then
echo "ERROR: Cannot extract manifestWorkName from AppliedManifestWork"
exit 1
fi
echo "Resource ID: $resource_id"
Step 3B.3: Query Database for User Work Name
Switch to service cluster context:
kubectl config use-context <svc-cluster-context>
Execute SQL query:
SELECT id,
payload->'metadata'->>'name' AS user_work_name,
created_at, updated_at, deleted_at
FROM resources
WHERE id = '<resource_id>';
Step 3B.4: Get All Applied Resources
Switch back to management cluster context:
kubectl config use-context <mgmt-cluster-context>
List all applied resources:
# List all applied resources in this work
kubectl get appliedmanifestwork "$amw_name" -o jsonpath='{range .status.appliedResources[*]}{.resource}{"\t"}{.namespace}{"\t"}{.name}{"\n"}{end}'
Step 3C.1: Query Database for Resource ID
Switch to service cluster context:
kubectl config use-context <svc-cluster-context>
Execute SQL query:
SELECT id,
payload->'metadata'->>'name' AS user_work_name,
payload->'spec'->'workload'->'manifests' AS manifests,
created_at, updated_at, deleted_at
FROM resources
WHERE payload->'metadata'->>'name' = '<work_name>';
Example:
SELECT id,
payload->'metadata'->>'name' AS user_work_name,
payload->'spec'->'workload'->'manifests' AS manifests,
created_at, updated_at, deleted_at
FROM resources
WHERE payload->'metadata'->>'name' = 'e44ec579-9646-549a-b679-db8d19d6da37';
Step 3C.2: Query Cluster for AppliedManifestWork
Switch to management cluster context:
kubectl config use-context <mgmt-cluster-context>
Query for AppliedManifestWork:
# Find AppliedManifestWork by manifestWorkName (use Resource ID from DB)
resource_id="<resource_id_from_db>"
amw_name=$(kubectl get appliedmanifestworks -o json | \
jq -r ".items[] | select(.spec.manifestWorkName == \"$resource_id\") | .metadata.name")
if [ -z "$amw_name" ]; then
echo "WARNING: AppliedManifestWork not found. Work may be deleted or not yet applied."
else
echo "AppliedManifestWork: $amw_name"
# Get applied resources
kubectl get appliedmanifestwork "$amw_name" -o yaml
# List applied manifests
kubectl get appliedmanifestwork "$amw_name" -o jsonpath='{range .status.appliedResources[*]}{.resource}{"\t"}{.namespace}{"\t"}{.name}{"\n"}{end}'
fi
IMPORTANT: Database pods are on the service cluster. Ensure you're on the svc cluster context before running these commands.
kubectl config use-context <svc-cluster-context>
Environment A: ARO-HCP INT (postgres-breakglass) - CRITICAL
This environment requires special handling with user confirmations for safety.
The trace.sh script automatically:
Checks if postgres-breakglass pod exists:
Shows SQL query for review:
Executes query via kubectl exec:
connect scriptInteractive flow:
Environment: ARO-HCP INT (CRITICAL)
Database: postgres-breakglass
ā ļø postgres-breakglass pod is not running
To start the pod, run:
kubectl -n maestro scale deployment postgres-breakglass --replicas 1
Would you like to scale up the pod now? (yes/no): yes
Scaling up postgres-breakglass deployment...
Waiting for pod to be ready (timeout: 60s)...
ā Pod ready: postgres-breakglass-7b8c9d6f5-abc12
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
SQL Query to execute:
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
SELECT id, payload->'metadata'->>'name' AS user_work_name
FROM resources WHERE id = '55c61e54...';
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā ļø CRITICAL ENVIRONMENT - Confirm before execution
Execute this query on ARO-HCP INT database? (yes/no): yes
Executing query on postgres-breakglass...
[Query results displayed]
Environment B: Service Cluster (maestro-db)
Standard database pod with direct query execution:
# Get database pod
pod_name=$(kubectl -n maestro get pods -l name=maestro-db -o jsonpath='{.items[0].metadata.name}')
# Execute query directly (no confirmation needed)
kubectl -n maestro exec -i "$pod_name" -- psql -U maestro -d maestro -c "<SQL_QUERY>"
Present a comprehensive trace showing all relationships:
ManifestWork Trace Results
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
User-Created Work Name: e44ec579-9646-549a-b679-db8d19d6da37
Resource ID (DB): 55c61e54-a3f6-563d-9fec-b1fe297bdfdb
AppliedManifestWork: f1d8a1049b93dffc1929d57a719c3a09a4dcbfe0cd6e42840325be3b2dde73c8-55c61e54-a3f6-563d-9fec-b1fe297bdfdb
Database Information:
āāāāāāāāāāāāāāāāāāāā
Created: 2024-01-15 10:30:00
Updated: 2024-01-15 10:32:15
Deleted: <null> (still active)
Applied Manifests (3 total):
āāāāāāāāāāāāāāāāāāāāāāāāāāāā
Resource Type Namespace Name
āāāāāāāāāāāāāāā āāāāāāāāāā āāāāāāāāāāāāāāāāāāāāā
Deployment default maestro-e2e-upgrade-test
Service default maestro-e2e-service
ConfigMap default maestro-e2e-config
Status: ā All manifests successfully applied to cluster
For deleted works:
ManifestWork Trace Results (DELETED)
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
User-Created Work Name: e44ec579-9646-549a-b679-db8d19d6da37
Resource ID (DB): 55c61e54-a3f6-563d-9fec-b1fe297bdfdb
AppliedManifestWork: Not found on cluster (work deleted)
Database Information:
āāāāāāāāāāāāāāāāāāāā
Created: 2024-01-15 10:30:00
Updated: 2024-01-15 10:32:15
Deleted: 2024-01-15 11:00:00
Original Manifests (from DB):
āāāāāāāāāāāāāāāāāāāāāāāāāāāāā
- Deployment/default/maestro-e2e-upgrade-test
- Service/default/maestro-e2e-service
- ConfigMap/default/maestro-e2e-config
Status: ā Work deleted from cluster, data available in DB only
Provide clear, actionable error messages:
| Error | Message | Next Steps |
|---|---|---|
| Resource not in DB | "No resource found with this ID/name" | Verify ID/name is correct; check for typos |
| AppliedManifestWork not found | "Work not applied to cluster" | Check if work was deleted; verify cluster connection |
| Manifest not found | "Manifest {kind}/{namespace}/{name} not found" | Verify manifest details; check if already deleted |
| No owner references | "Not managed by any ManifestWork" | Explain this is a standalone resource |
| kubectl unavailable | "kubectl is required" | Installation instructions |
| DB connection failed | "Cannot connect to database" | Verify kubectl access; check namespace |
| Multiple results | "Multiple resources found" | Show all results; ask user to be more specific |
Based on results:
If successful trace:
kubectl get appliedmanifestwork {name} -o yaml"kubectl get {kind} {name} -n {namespace} -o yaml"If work deleted:
deleted_at field in database"payload field"If resource not found:
SELECT id, payload->'metadata'->>'name' AS name, created_at, deleted_at
FROM resources
WHERE payload->'metadata'->>'name' LIKE '%{partial_name}%'
ORDER BY created_at DESC
LIMIT 10;
For further investigation:
kubectl logs -n maestro-agent -l app=maestro-agent"kubectl get events -n {namespace} --sort-by='.lastTimestamp'"events table for resourceid"The skill includes helper scripts for common operations.
# By resource ID
.claude/skills/trace-manifestwork/scripts/trace.sh \
--resource-id "55c61e54-a3f6-563d-9fec-b1fe297bdfdb" \
--svc-context svc-cluster \
--mgmt-context mgmt-cluster
# By user work name
.claude/skills/trace-manifestwork/scripts/trace.sh \
--work-name "e44ec579-9646-549a-b679-db8d19d6da37" \
--svc-context svc-cluster \
--mgmt-context mgmt-cluster
# By manifest details
.claude/skills/trace-manifestwork/scripts/trace.sh \
--manifest-kind deployment \
--manifest-name maestro-e2e-upgrade-test \
--manifest-namespace default \
--svc-context svc-cluster \
--mgmt-context mgmt-cluster
# By resource ID
.claude/skills/trace-manifestwork/scripts/trace.sh \
--resource-id "55c61e54-a3f6-563d-9fec-b1fe297bdfdb" \
--svc-kubeconfig ~/svc-cluster-kubeconfig.yaml \
--mgmt-kubeconfig ~/mgmt-cluster-kubeconfig.yaml
# By user work name
.claude/skills/trace-manifestwork/scripts/trace.sh \
--work-name "e44ec579-9646-549a-b679-db8d19d6da37" \
--svc-kubeconfig ~/svc-cluster-kubeconfig.yaml \
--mgmt-kubeconfig ~/mgmt-cluster-kubeconfig.yaml
# By manifest details
.claude/skills/trace-manifestwork/scripts/trace.sh \
--manifest-kind deployment \
--manifest-name maestro-e2e-upgrade-test \
--manifest-namespace default \
--svc-kubeconfig ~/svc-cluster-kubeconfig.yaml \
--mgmt-kubeconfig ~/mgmt-cluster-kubeconfig.yaml
Maestro Resource Data Flow:
e44ec579-9646-549a-b679-db8d19d6da37 via MaestroGRPCSourceWorkClient55c61e54-a3f6-563d-9fec-b1fe297bdfdb and sends CloudEvent with resourceid extensionresourceid as primary key (id column){agentID}-{resourceID} and applies manifestsDatabase Schema (resources table):
id: VARCHAR, primary key (= CloudEvent resourceid)payload: JSONB containing full CloudEventpayload->'metadata'->>'name': User-created work namepayload->'spec'->'workload'->'manifests': Array of manifestscreated_at, updated_at, deleted_at: TimestampsAppliedManifestWork Structure:
metadata.name: {agentID}-{resourceID} formatspec.manifestWorkName: Resource ID (used to link to DB)spec.agentID: Agent identifierstatus.appliedResources[]: Array of applied resourcesresource: Resource type (e.g., "deployments")namespace: Resource namespacename: Resource nameuid: Kubernetes UIDManifest ownerReference:
apiVersion: work.open-cluster-management.io/v1kind: AppliedManifestWorkname: Full AppliedManifestWork namescripts/trace.sh - Complete trace script supporting all entry pointsreferences/maestro-data-flow.md - Detailed Maestro resource flow documentationreferences/troubleshooting-guide.md - Common issues and solutionsexamples/trace-by-resource-id.md - Example: Resource ID traceexamples/trace-by-manifest.md - Example: Manifest name traceexamples/trace-by-work-name.md - Example: User work name trace