Files
pve-confsync/internal/adapter/datacenter.go
T

99 lines
3.0 KiB
Go

package adapter
import (
"context"
"errors"
"strings"
"pve-confsync/internal/model"
"pve-confsync/internal/pve"
)
// DatacenterID is the id of the single datacenter options object.
const DatacenterID = "datacenter"
// pveDefaultMACPrefix is injected by PVE on read when mac_prefix is unset
// (PROXMOX_OUI in pve-cluster DataCenterConfig.pm); it is not a real setting.
const pveDefaultMACPrefix = "BC:24:11"
// datacenter handles GET/PUT /cluster/options (datacenter.cfg).
// GET returns several options parsed into objects/lists, PUT expects property strings:
// the canonical form is the property string (lists joined with ';' like datacenter.cfg).
type datacenter struct{}
func (datacenter) Kind() model.Kind { return model.KindDatacenter }
func (datacenter) SDN() bool { return false }
func (datacenter) Singleton() bool { return true }
func (datacenter) List(ctx context.Context, c *pve.Client, _ ReadMode, _ []model.Object) ([]model.Object, []string, error) {
var raw map[string]any
if err := c.Get(ctx, "cluster/options", nil, &raw); err != nil {
return nil, nil, err
}
// allowed-tags: read-only, computed for the calling user.
fields := normalizeAPI(raw, "allowed-tags")
for k, v := range fields {
// top level lists (registered-tags) are stored as "a;b;c" in datacenter.cfg
if l, ok := v.([]string); ok {
fields[k] = strings.Join(l, ";")
}
}
if fields["description"] == "" {
delete(fields, "description")
}
if s, _ := fields["mac_prefix"].(string); strings.EqualFold(s, pveDefaultMACPrefix) {
delete(fields, "mac_prefix")
}
return []model.Object{{Kind: model.KindDatacenter, ID: DatacenterID, Fields: fields}}, nil, nil
}
// Fields synchronized by default; any other option is ignored unless the
// configuration says "sync".
var dcDefaultSync = map[string]bool{
"tag-style": true,
"registered-tags": true,
"user-tag-access": true,
"next-id": true,
}
func (datacenter) DefaultPolicy(f string) Policy {
if dcDefaultSync[f] {
return Sync
}
return Ignore
}
// Identity of the cluster or possible secrets (http_proxy may hold credentials).
func (datacenter) Forbidden(f string) bool {
switch f {
case "webauthn", "u2f", "http_proxy":
return true
}
return false
}
func (datacenter) Canonicalize(map[string]any) {}
func (datacenter) Required(model.Object) []string { return nil }
func (datacenter) Immutable(string) bool { return false }
func (datacenter) Create(context.Context, *pve.Client, model.Object, string) error {
return errors.New("datacenter options cannot be created")
}
func (datacenter) Delete(context.Context, *pve.Client, model.Object, string) error {
return errors.New("datacenter options cannot be deleted")
}
func (datacenter) Update(ctx context.Context, c *pve.Client, _ model.Object, set map[string]any, unset []string, _ string) error {
flat := map[string]any{}
for k, v := range set {
if l, ok := v.([]string); ok {
flat[k] = strings.Join(l, ";")
} else {
flat[k] = v
}
}
return c.Put(ctx, "cluster/options", form(flat, unset, ""), nil)
}