proxmox: config block, IDs, marks, state mapping, classify, registration
Phase 2 of the proxmox provider plan. Adds the proxmox: config block with its validation, registers the type in the config allow-list and the constructor map, and starts internal/provider/proxmox: the api seam and its data types, providerIDs (vms/<vmid>/<name>) with the UID-derived VMID, the description mark, state mapping, and error classification. Tests read the responses captured from pv1-1 in Phase 0 rather than repeating Proxmox's wording, and every matcher is run against every captured error so none fires on the wrong message. The contract methods are Transient stubs until Phases 5 to 7. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
package proxmox
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gitea.home.hrajfrisbee.cz/kacerr/egress-proxies-operator/internal/provider"
|
||||
)
|
||||
|
||||
// createdAtKey is the third line of the mark; the first two use the
|
||||
// contract's label names.
|
||||
const createdAtKey = "proxy-operator-created-at"
|
||||
|
||||
// instanceMark is the GC mark as read back from a VM's description (spec
|
||||
// entry 8).
|
||||
type instanceMark struct {
|
||||
Managed bool
|
||||
UID string
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
// formatDescription renders the mark written in the clone call.
|
||||
func formatDescription(uid string, createdAt time.Time) string {
|
||||
return provider.LabelManaged + "=" + provider.LabelManagedYes + "\n" +
|
||||
provider.LabelUID + "=" + uid + "\n" +
|
||||
createdAtKey + "=" + createdAt.UTC().Format(time.RFC3339)
|
||||
}
|
||||
|
||||
// parseDescription reads key=value lines, tolerating CRLF, blank lines and
|
||||
// lines an admin added. The first occurrence of a key wins. Managed only
|
||||
// when the value is exactly LabelManagedYes; an unparsable created-at gives
|
||||
// the zero time, which GC treats as old.
|
||||
func parseDescription(desc string) instanceMark {
|
||||
var m instanceMark
|
||||
seen := map[string]bool{}
|
||||
for line := range strings.SplitSeq(desc, "\n") {
|
||||
key, value, ok := strings.Cut(strings.TrimSpace(line), "=")
|
||||
if !ok || seen[key] {
|
||||
continue
|
||||
}
|
||||
seen[key] = true
|
||||
switch key {
|
||||
case provider.LabelManaged:
|
||||
m.Managed = value == provider.LabelManagedYes
|
||||
case provider.LabelUID:
|
||||
m.UID = value
|
||||
case createdAtKey:
|
||||
if t, err := time.Parse(time.RFC3339, value); err == nil {
|
||||
m.CreatedAt = t
|
||||
}
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
Reference in New Issue
Block a user