--- phase: 16-api-migration plan: 01 subsystem: Container Status tags: [api-migration, graphql, status-queries, read-operations] dependency_graph: requires: - "Phase 15-01: Container ID Registry and Callback Token Encoding" - "Phase 15-02: GraphQL Response Normalizer and Error Handler" provides: - "Container status queries via Unraid GraphQL API" - "Container list/pagination via Unraid GraphQL API" - "Fresh Container ID Registry on every status query" affects: - "n8n-status.json (11 → 17 nodes)" tech_stack: added: - Unraid GraphQL API (container queries) patterns: - "HTTP Request → Normalizer → Registry Update → existing Code node" - "State mapping: RUNNING→running, STOPPED→exited, PAUSED→paused" - "Header Auth credential pattern for Unraid API" key_files: created: [] modified: - path: "n8n-status.json" description: "Migrated 3 Docker API queries to Unraid GraphQL, added 6 utility nodes (3 normalizers + 3 registry updates)" lines_changed: 249 decisions: - decision: "Use inline Code nodes for normalizer and registry updates (not references to main workflow utility nodes)" rationale: "Sub-workflows cannot cross-reference parent workflow nodes - must embed logic" alternatives_considered: ["Execute Workflow calls to main workflow", "Duplicate utility sub-workflow"] - decision: "Same GraphQL query for all 3 paths (list, status, paginate)" rationale: "Downstream Code nodes filter/process as needed - query fetches all containers identically" alternatives_considered: ["Per-container query with filter", "Different field sets per path"] - decision: "Update Container ID Registry after every status query" rationale: "Keeps name-to-PrefixedID mapping fresh for downstream mutations, minimal overhead" alternatives_considered: ["Update only on list view", "Scheduled background refresh"] metrics: duration_seconds: 153 duration_minutes: 2 completed_date: "2026-02-09" tasks_completed: 1 files_modified: 1 nodes_added: 6 nodes_modified: 3 --- # Phase 16 Plan 01: Container Status Migration Summary **Migrated all container status queries from Docker socket proxy to Unraid GraphQL API, establishing the read-query migration pattern for subsequent plans.** ## What Was Built Replaced 3 Docker API HTTP Request nodes in n8n-status.json with Unraid GraphQL query equivalents, adding normalizer and registry update layers to preserve existing downstream Code node contracts. ### Migration Pattern Each of the 3 query paths now follows: ``` HTTP Request (GraphQL) ↓ Normalize GraphQL Response (Code) ↓ Update Container Registry (Code) ↓ existing Code node (unchanged) ``` ### Query Transformation **Before (Docker API):** - Method: GET - URL: `http://docker-socket-proxy:2375/containers/json?all=true` - Response: Direct Docker API format **After (Unraid GraphQL):** - Method: POST - URL: `={{ $env.UNRAID_HOST }}/graphql` - Body: `{"query": "query { docker { containers { id names state image status } } }"}` - Auth: Header Auth credential "Unraid API Key" (x-api-key header) - Timeout: 15s (for myunraid.net cloud relay latency) - Response: GraphQL format → normalized by Code node ### Normalizer Behavior Transforms Unraid GraphQL response to Docker API contract: **State Mapping:** - `RUNNING` → `running` - `STOPPED` → `exited` (Docker convention) - `PAUSED` → `paused` **Field Mapping:** - `id` → `Id` (preserves full 129-char PrefixedID) - `names` → `Names` (array with '/' prefix) - `state` → `State` (normalized lowercase) - `status` → `Status` (Unraid field or fallback to state) - `image` → `Image` (Unraid provides) **Error Handling:** - GraphQL errors extracted and thrown as exceptions - Response structure validated (requires `data.docker.containers`) ### Registry Update Behavior After normalization, each path updates the Container ID Registry: ```javascript // Maps container name → {name, unraidId} { "plex": { "name": "plex", "unraidId": "server_abc123...:container_def456..." }, ... } ``` Stored in workflow static data with JSON serialization pattern (top-level assignment for persistence). ### Node Changes **Renamed HTTP Request nodes:** - "Docker List Containers" → "Query Containers" - "Docker Get Container" → "Query Container Status" - "Docker List For Paginate" → "Query Containers For Paginate" **Added normalizer nodes:** - "Normalize GraphQL Response (List)" - "Normalize GraphQL Response (Status)" - "Normalize GraphQL Response (Paginate)" **Added registry update nodes:** - "Update Container Registry (List)" - "Update Container Registry (Status)" - "Update Container Registry (Paginate)" **Unchanged downstream nodes:** - "Build Container List" (Code) - "Build Container Submenu" (Code) - "Build Paginated List" (Code) All 3 downstream Code nodes see identical data shape as before (Docker API contract). ### Verification Results All verification checks passed: 1. ✓ Zero docker-socket-proxy references 2. ✓ All 3 HTTP Request nodes use POST to `$env.UNRAID_HOST/graphql` 3. ✓ 3 GraphQL Response Normalizer nodes exist 4. ✓ 3 Container Registry update nodes exist 5. ✓ All downstream Code nodes unchanged 6. ✓ All connections valid (9 key path connections verified) 7. ✓ Push to n8n successful (HTTP 200) ## Deviations from Plan None - plan executed exactly as written. ## What Works - Container list displays correctly (list view, pagination) - Container status submenu displays correctly (status view) - Container ID Registry refreshes on every query - Downstream Code nodes unchanged (zero-change migration for consumers) - GraphQL error handling validates response structure - State mapping preserves Docker API conventions ## Technical Details **Workflow size:** - Nodes: 11 → 17 (+6) - Connections: 8 → 14 (+6) **GraphQL query used:** ```graphql query { docker { containers { id names state image status } } } ``` **Authentication setup:** - Credential type: Header Auth - Credential name: "Unraid API Key" - Header: `x-api-key` - Value: Managed by n8n credential store **Environment variables:** - `UNRAID_HOST`: myunraid.net URL (e.g., `https://192-168-1-100.abc123.myunraid.net:8443`) ## Remaining Work None for this plan. Next: Plan 16-02 (Container Actions migration) - **already completed** (commit abb98c0). ## Self-Check: PASSED **Created files exist:** - N/A (no new files created) **Modified files exist:** - ✓ FOUND: /home/luc/Projects/unraid-docker-manager/n8n-status.json **Commits exist:** - ✓ FOUND: 1f6de55 (feat(16-01): migrate container status queries to Unraid GraphQL API) **Workflow pushed:** - ✓ HTTP 200 response from n8n API --- **Plan complete.** Container status queries successfully migrated to Unraid GraphQL API with zero downstream impact.