docs(01): fix plan checker blockers (research resolution, catalog updater)
This commit is contained in:
parent
c9ad50fdf2
commit
b1e4db0b6d
2 changed files with 47 additions and 16 deletions
|
|
@ -10,6 +10,7 @@ files_modified:
|
||||||
- internal/netbox/hwid_test.go
|
- internal/netbox/hwid_test.go
|
||||||
- internal/inventory/quality_gate.go
|
- internal/inventory/quality_gate.go
|
||||||
- internal/inventory/quality_gate_test.go
|
- internal/inventory/quality_gate_test.go
|
||||||
|
- internal/inventory/catalog_updater.go
|
||||||
- internal/inventory/types.go
|
- internal/inventory/types.go
|
||||||
- internal/netbox/tags.go
|
- internal/netbox/tags.go
|
||||||
- internal/netbox/tags_test.go
|
- internal/netbox/tags_test.go
|
||||||
|
|
@ -424,6 +425,45 @@ func BuildCustomFieldsPatch(hwID, catalogStatus string, photoURLs []string) map[
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
2b. Create `internal/inventory/catalog_updater.go` — wires quality gate transitions to NetBox persistence:
|
||||||
|
```go
|
||||||
|
package inventory
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.georgsen.dk/hwlab/internal/netbox"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CatalogUpdater persists quality gate transitions to NetBox.
|
||||||
|
type CatalogUpdater struct {
|
||||||
|
client *netbox.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCatalogUpdater creates a CatalogUpdater backed by the given NetBox client.
|
||||||
|
func NewCatalogUpdater(client *netbox.Client) *CatalogUpdater {
|
||||||
|
return &CatalogUpdater{client: client}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateCatalogStatus validates the transition from current to next status
|
||||||
|
// and persists the result to NetBox via PatchCustomFields.
|
||||||
|
// Returns the new status on success.
|
||||||
|
func (u *CatalogUpdater) UpdateCatalogStatus(ctx context.Context, deviceID int, current, next CatalogStatus) (CatalogStatus, error) {
|
||||||
|
newStatus, err := Transition(current, next)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
patch := map[string]interface{}{
|
||||||
|
"catalog_status": string(newStatus),
|
||||||
|
}
|
||||||
|
if err := u.client.PatchCustomFields(ctx, deviceID, patch); err != nil {
|
||||||
|
return "", fmt.Errorf("persist catalog_status to NetBox: %w", err)
|
||||||
|
}
|
||||||
|
return newStatus, nil
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
3. Create `internal/inventory/quality_gate_test.go`:
|
3. Create `internal/inventory/quality_gate_test.go`:
|
||||||
```go
|
```go
|
||||||
package inventory_test
|
package inventory_test
|
||||||
|
|
@ -645,6 +685,8 @@ func BuildCustomFieldsPatch(hwID, catalogStatus string, photoURLs []string) map[
|
||||||
- `grep "StatusComplete.*{}" internal/inventory/quality_gate.go` returns the terminal state entry with empty transitions
|
- `grep "StatusComplete.*{}" internal/inventory/quality_gate.go` returns the terminal state entry with empty transitions
|
||||||
- `grep "invalid transition" internal/inventory/quality_gate.go` returns error string in Transition()
|
- `grep "invalid transition" internal/inventory/quality_gate.go` returns error string in Transition()
|
||||||
- `ensureTag` in `internal/netbox/tags.go` is implemented with real go-netbox v4 TagRequest (not stub returning error string)
|
- `ensureTag` in `internal/netbox/tags.go` is implemented with real go-netbox v4 TagRequest (not stub returning error string)
|
||||||
|
- `grep "UpdateCatalogStatus" internal/inventory/catalog_updater.go` returns the function that calls Transition() then PatchCustomFields
|
||||||
|
- `grep "PatchCustomFields" internal/inventory/catalog_updater.go` confirms NetBox persistence wiring
|
||||||
- `go build ./internal/inventory/... ./internal/netbox/...` exits 0
|
- `go build ./internal/inventory/... ./internal/netbox/...` exits 0
|
||||||
</acceptance_criteria>
|
</acceptance_criteria>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -572,26 +572,15 @@ Create via DCIM API endpoints:
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Open Questions
|
## Open Questions (RESOLVED)
|
||||||
|
|
||||||
1. **Real NetBox API token**
|
1. **Real NetBox API token** — RESOLVED: Integration tests use `t.Skip()` when placeholder token detected. Operator generates real token via NetBox UI before running provisioning (Plan 03).
|
||||||
- What we know: The `.env` file has a placeholder string `homelab-netbox-api-token-2024`
|
|
||||||
- What's unclear: The real token value; whether the current user account has admin permissions to create custom fields
|
|
||||||
- Recommendation: Wave 0 first task — generate real token via NetBox UI, update `.env`
|
|
||||||
|
|
||||||
2. **netbox-inventory plugin installation (NB-03)**
|
2. **netbox-inventory plugin installation (NB-03)** — RESOLVED: Plan 03 implements runtime check via `/api/plugins/` endpoint with CLI warning if absent. Installation is a manual pre-requisite (SSH to LXC 130).
|
||||||
- What we know: Plugin exists at github.com/ArnesSI/netbox-inventory; requires SSH to LXC 130
|
|
||||||
- What's unclear: Whether the LXC 130 has internet access for pip install, or if the plugin must be transferred manually
|
|
||||||
- Recommendation: Treat as a manual pre-phase step with a Makefile verification target
|
|
||||||
|
|
||||||
3. **photo_urls field type**
|
3. **photo_urls field type** — RESOLVED: Plan 03 Task 1 uses `text` type with comma-separated URLs (simpler than JSON, sufficient for Phase 1).
|
||||||
- What we know: The requirement lists `photo_urls` as a custom field
|
|
||||||
- What's unclear: NetBox doesn't have a native array-of-URLs field type. Options: JSON field (store as JSON array string), multiline-text (one URL per line), or multiple object attachments
|
|
||||||
- Recommendation: Use `json` field type and store as a JSON array string; parse in Go
|
|
||||||
|
|
||||||
4. **PRD vs. REQUIREMENTS.md design system discrepancy**
|
4. **PRD vs. REQUIREMENTS.md design system discrepancy** — RESOLVED: CONTEXT.md and PROJECT.md specify ClickHouse design system. Plan 01 stub SPA uses ClickHouse colors.
|
||||||
- What we know: PRD says "Tokyo Night theme"; CONTEXT.md and PROJECT.md say "ClickHouse design system (pure black + neon volt)"
|
|
||||||
- Recommendation: CONTEXT.md wins — use ClickHouse design system. The stub Phase 1 frontend needs no real styling.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue