Feature 57 (config and provisioning): release mesh-controller, the reviewed release branch merged with main, on top of main
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/novox/mesh-controller/internal/inventory"
|
||||
)
|
||||
|
||||
// movePlacementAnswer is what the move of placement says it did, or would do (issue 736).
|
||||
type movePlacementAnswer struct {
|
||||
// DryRun is true when nothing was moved: asked without --confirm.
|
||||
DryRun bool `json:"dry-run"`
|
||||
// Moved is each layer that held a placement key among its settings, and which keys.
|
||||
Moved []inventory.MovedLayer `json:"moved"`
|
||||
}
|
||||
|
||||
// movePlacementCommand is `move-placement`: the move of placement out of the settings layers (novox/hq ADR 0348
|
||||
// clause 11, issue 736), one of the moves of data a release runs once after its delivery (design 57).
|
||||
func movePlacementCommand(ctx context.Context, args []string) error {
|
||||
set := flag.NewFlagSet("move-placement", flag.ContinueOnError)
|
||||
asJSON := set.Bool("json", false, "answer as JSON")
|
||||
confirm := set.Bool("confirm", false, "move the keys, rather than only say which layers hold them")
|
||||
f := addHandActFlags(set)
|
||||
positionals, err := parseAround(set, args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(positionals) != 0 {
|
||||
return errors.New("move-placement [--json] [--confirm --why <text>]")
|
||||
}
|
||||
if !*confirm && f.given() {
|
||||
return errors.New("move-placement takes --why only with --confirm: without it nothing is moved. Nothing was done")
|
||||
}
|
||||
if *confirm {
|
||||
// A move a person asks for says why, before anything is asked of the store.
|
||||
if err := f.require("move-placement"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
open, err := openStores(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer open.Close()
|
||||
if *confirm {
|
||||
f.record(ctx, "move-placement", nil)
|
||||
}
|
||||
answer, err := runMovePlacement(ctx, open.inventory, *confirm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if *asJSON {
|
||||
encoder := json.NewEncoder(os.Stdout)
|
||||
encoder.SetIndent("", " ")
|
||||
return encoder.Encode(answer)
|
||||
}
|
||||
fmt.Print(describeMovePlacement(answer))
|
||||
return nil
|
||||
}
|
||||
|
||||
// runMovePlacement is the move against a store: a dry run says what it would move.
|
||||
func runMovePlacement(ctx context.Context, inv *inventory.Inventory, apply bool) (movePlacementAnswer, error) {
|
||||
moved, err := inv.MovePlacement(ctx, apply)
|
||||
if err != nil {
|
||||
return movePlacementAnswer{}, err
|
||||
}
|
||||
return movePlacementAnswer{DryRun: !apply, Moved: moved}, nil
|
||||
}
|
||||
|
||||
// describeMovePlacement says the answer as a person reads it.
|
||||
func describeMovePlacement(a movePlacementAnswer) string {
|
||||
if len(a.Moved) == 0 {
|
||||
return "no settings layer holds a placement key: nothing to move\n"
|
||||
}
|
||||
var b strings.Builder
|
||||
verb := "moved"
|
||||
if a.DryRun {
|
||||
verb = "would move"
|
||||
}
|
||||
for _, m := range a.Moved {
|
||||
where := m.Node
|
||||
if where == "" {
|
||||
where = "the whole mesh"
|
||||
}
|
||||
fmt.Fprintf(&b, "%s on %s: %s %s\n", m.Module, where, verb, strings.Join(m.Keys, ", "))
|
||||
}
|
||||
if a.DryRun {
|
||||
fmt.Fprintf(&b, "%d layer(s); nothing was moved — with --confirm --why <text> they are\n", len(a.Moved))
|
||||
} else {
|
||||
fmt.Fprintf(&b, "%d layer(s) moved beside their assignments, each kept whole in its history first\n", len(a.Moved))
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
Reference in New Issue
Block a user