Feature 57 (config and provisioning): modules declare config and provisions, their files rendered from templates; synced with main (issues of feature 57, 874)
This commit is contained in:
@@ -33,7 +33,32 @@ func main() {
|
||||
return
|
||||
}
|
||||
var h *Harness
|
||||
if receives := os.Getenv("MESH_RECEIVES"); receives == "" {
|
||||
if consumers := handedConsumersFile(os.Getenv, os.Stat); consumers != "" {
|
||||
// Handed to the provisioner (novox/hq ADR 0373): the provider helper answers the consumers its
|
||||
// machine's client fills the file with; the grant directory is not read. Retirement is the
|
||||
// harness's, never run, so its guards and its tools stand (issue 780).
|
||||
h = &Harness{
|
||||
Resource: ProvisionName,
|
||||
Adapter: provisioner{pg: pg, announce: announce},
|
||||
Log: func(format string, args ...any) { fmt.Fprintf(os.Stderr, format+"\n", args...) },
|
||||
Announce: func(event string, body map[string]any) {
|
||||
if err := stdio.Emit(event, body); err != nil {
|
||||
say("emit %s failed: %v", event, err)
|
||||
}
|
||||
},
|
||||
Node: os.Getenv("MESH_NODE"),
|
||||
}
|
||||
run, p, bus, err := moved(consumers, h)
|
||||
if err != nil {
|
||||
say("%v", err)
|
||||
} else {
|
||||
go func() {
|
||||
if err := run.Run(context.Background(), p, bus); err != nil {
|
||||
say("the provider helper stopped: %v", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
} else if receives := os.Getenv("MESH_RECEIVES"); receives == "" {
|
||||
say("MESH_RECEIVES is not set — the provisioner cannot run without it")
|
||||
} else {
|
||||
h = &Harness{
|
||||
@@ -52,6 +77,15 @@ func main() {
|
||||
}
|
||||
go h.Run(context.Background())
|
||||
}
|
||||
// Started on the grant path while the module is to be handed, it restarts itself when its client first fills
|
||||
// the consumers' file, so the first fill moves it onto the helper without a hand restart (issue 780): `restart-on`
|
||||
// names a service or a container, and the only one here is the database.
|
||||
if at := os.Getenv("MESH_CONSUMERS_FILE"); at != "" && handedConsumersFile(os.Getenv, os.Stat) == "" {
|
||||
go exitWhenFilled(at, os.Stat, 5*time.Second, func() {
|
||||
say("%s is filled: restarting to answer from it", at)
|
||||
os.Exit(0)
|
||||
})
|
||||
}
|
||||
go audit()
|
||||
// The store's reader is narrowed to what modules declare readable, at once and every minute, whether
|
||||
// or not the provisioner runs: without a contributions file it is given nothing (novox/hq issue 337).
|
||||
@@ -64,6 +98,31 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
// handedConsumersFile is the consumers' file when postgres is handed to the provisioner: the file MESH_CONSUMERS_FILE
|
||||
// names, which the controller places only where it hands the module. Empty, where it is not set or the file is not
|
||||
// there, and postgres then reads the grant directory exactly as it always did (issue 780).
|
||||
func handedConsumersFile(getenv func(string) string, stat func(string) (os.FileInfo, error)) string {
|
||||
at := getenv("MESH_CONSUMERS_FILE")
|
||||
if at == "" {
|
||||
return ""
|
||||
}
|
||||
if _, err := stat(at); err != nil {
|
||||
return ""
|
||||
}
|
||||
return at
|
||||
}
|
||||
|
||||
// exitWhenFilled calls filled once the file is there, asking every so often.
|
||||
func exitWhenFilled(at string, stat func(string) (os.FileInfo, error), every time.Duration, filled func()) {
|
||||
for {
|
||||
if _, err := stat(at); err == nil {
|
||||
filled()
|
||||
return
|
||||
}
|
||||
time.Sleep(every)
|
||||
}
|
||||
}
|
||||
|
||||
// announce emits a lifecycle event without letting a broker hiccup fail the provisioning itself.
|
||||
func announce(event string, body map[string]string) {
|
||||
if err := stdio.Emit(event, body); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user