Full web : fichiers restants
This commit is contained in:
1 parent
ec3b7c9a01
commit
4826fa5b82
26 files changed
+2537
-793
No files matched your search
+78
-11
@@ -4,6 +4,7 @@ package engine
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
@@ -42,6 +43,9 @@ func Read(ctx context.Context, c *pve.Client, kinds []model.Kind, mode adapter.R
|
||||
if need[model.KindVNet] {
|
||||
need[model.KindZone] = true
|
||||
}
|
||||
if need[model.KindPassword] {
|
||||
need[model.KindUser] = true
|
||||
}
|
||||
var all []model.Object
|
||||
for _, a := range adapter.All() {
|
||||
if !need[a.Kind()] {
|
||||
@@ -74,21 +78,43 @@ const (
|
||||
|
||||
// Change is one planned action. Set holds the new values, Old the current ones.
|
||||
type Change struct {
|
||||
Kind model.Kind `json:"kind" yaml:"kind"`
|
||||
ID string `json:"id" yaml:"id"`
|
||||
Op Op `json:"op" yaml:"op"`
|
||||
Set map[string]any `json:"set,omitempty" yaml:"set,omitempty"`
|
||||
Unset []string `json:"unset,omitempty" yaml:"unset,omitempty"`
|
||||
Old map[string]any `json:"old,omitempty" yaml:"old,omitempty"`
|
||||
Target model.Object `json:"-" yaml:"-"`
|
||||
Kind model.Kind `json:"kind"`
|
||||
ID string `json:"id"`
|
||||
Op Op `json:"op"`
|
||||
Set map[string]any `json:"set,omitempty"`
|
||||
Unset []string `json:"unset,omitempty"`
|
||||
Old map[string]any `json:"old,omitempty"`
|
||||
Target model.Object `json:"-"`
|
||||
}
|
||||
|
||||
// MarshalJSON hides the secret fields (password hashes): plans are shown in the
|
||||
// UI and kept in the journal, the real values only live in memory until applied.
|
||||
func (c Change) MarshalJSON() ([]byte, error) {
|
||||
type plain Change
|
||||
red := func(m map[string]any) map[string]any {
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
out := make(map[string]any, len(m))
|
||||
for k, v := range m {
|
||||
if adapter.IsSensitive(c.Kind, k) {
|
||||
v = adapter.Redact(v)
|
||||
}
|
||||
out[k] = v
|
||||
}
|
||||
return out
|
||||
}
|
||||
p := plain(c)
|
||||
p.Set, p.Old = red(c.Set), red(c.Old)
|
||||
return json.Marshal(p)
|
||||
}
|
||||
|
||||
// Plan is the list of changes for one client, in execution order.
|
||||
type Plan struct {
|
||||
Client string `json:"client" yaml:"client"`
|
||||
Changes []Change `json:"changes" yaml:"changes"`
|
||||
Errors []string `json:"errors,omitempty" yaml:"errors,omitempty"`
|
||||
Warnings []string `json:"warnings,omitempty" yaml:"warnings,omitempty"`
|
||||
Client string `json:"client"`
|
||||
Changes []Change `json:"changes"`
|
||||
Errors []string `json:"errors,omitempty"`
|
||||
Warnings []string `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// HasSDN tells whether the plan writes SDN objects (lock + reload needed).
|
||||
@@ -187,6 +213,7 @@ func MakePlan(cfg *config.Config, cl *config.Client, ref, actual []model.Object)
|
||||
}
|
||||
}
|
||||
}
|
||||
checkParents(&plan, cl.Name, actual)
|
||||
// deletions last, dependents first (subnets, vnets, zones)
|
||||
sort.SliceStable(deletes, func(i, j int) bool {
|
||||
if deletes[i].Kind != deletes[j].Kind {
|
||||
@@ -198,6 +225,46 @@ func MakePlan(cfg *config.Config, cl *config.Client, ref, actual []model.Object)
|
||||
return plan
|
||||
}
|
||||
|
||||
// checkParents blocks the objects whose parents (groups of an account, account
|
||||
// of a password) are neither on the target nor created by the plan.
|
||||
func checkParents(plan *Plan, client string, actual []model.Object) {
|
||||
have := map[string]bool{}
|
||||
for _, o := range actual {
|
||||
have[o.Key()] = true
|
||||
}
|
||||
for _, c := range plan.Changes {
|
||||
if c.Op == OpCreate {
|
||||
have[c.Key()] = true
|
||||
}
|
||||
}
|
||||
for _, c := range plan.Changes {
|
||||
if c.Op == OpDelete {
|
||||
continue
|
||||
}
|
||||
for _, p := range adapter.Parents(Desired(c)) {
|
||||
if !have[p] {
|
||||
plan.Errors = append(plan.Errors, fmt.Sprintf("%s: %s absent on target %s and not replicated", c.Key(), p, client))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Desired is the object as it will be after the change (fields of the target
|
||||
// with the new values).
|
||||
func Desired(c Change) model.Object {
|
||||
f := map[string]any{}
|
||||
for k, v := range c.Target.Fields {
|
||||
f[k] = v
|
||||
}
|
||||
for _, k := range c.Unset {
|
||||
delete(f, k)
|
||||
}
|
||||
for k, v := range c.Set {
|
||||
f[k] = v
|
||||
}
|
||||
return model.Object{Kind: c.Kind, ID: c.ID, Fields: f}
|
||||
}
|
||||
|
||||
func kindRank(k model.Kind) int {
|
||||
for i, x := range model.Kinds {
|
||||
if x == k {
|
||||
|
||||
Reference in new issue
Block a user