fix(setup): converge the workload felis-config mirror on every apply path (#52)
felis setup's in-TUI applies (storage / connection / edge) refreshed only the control-namespace felis-config Secret; the workload-namespace mirror kept the render from the previous run's startup pass until the next setup or installer run. Found live: after 's -> Local' the minecraft copy still carried user_uploads_context = s3://felis-wizard-uploads while the control copy and both tomls were local. The 'configure email' path already overwrote both mirrors, so storage/connection were the odd ones out. Move the mirror refresh into applyFelisConfigSecret — the single choke point every apply path calls — best-effort with a warning, since a control-plane default install may not have the workload namespace at all. The smtp helper drops its now-duplicate felis-config block.
This commit is contained in:
2 files changed
+47
-19
No files matched your search
@@ -133,6 +133,11 @@ func writeConfig(path string, cfg *config.Config) error {
|
|||||||
return os.Rename(tmpPath, path)
|
return os.Rename(tmpPath, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// applyFelisConfigSecret applies the rendered config to the control namespace and
|
||||||
|
// then converges the workload-namespace mirror best-effort. The mirror feeds the
|
||||||
|
// backup/restore/fileedit Jobs and the reaper; without this refresh a reconfigure
|
||||||
|
// here would leave those readers on the previous render until the next `felis
|
||||||
|
// setup` run (startup pass) or installer re-run.
|
||||||
func applyFelisConfigSecret(ctx context.Context) error {
|
func applyFelisConfigSecret(ctx context.Context) error {
|
||||||
out, err := kubectlOutput(ctx,
|
out, err := kubectlOutput(ctx,
|
||||||
"-n", "felis", "create", "secret", "generic", "felis-config",
|
"-n", "felis", "create", "secret", "generic", "felis-config",
|
||||||
@@ -142,7 +147,41 @@ func applyFelisConfigSecret(ctx context.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return kubectlWithInput(ctx, out, "apply", "-f", "-")
|
if err := kubectlWithInput(ctx, out, "apply", "-f", "-"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := replicateFelisConfigToWorkloadNamespace(ctx); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "felis setup: warning: the control-plane config is applied, but the workload-namespace mirror could not be refreshed (%v); re-run felis setup once that is fixed\n", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// replicateFelisConfigToWorkloadNamespace overwrites the workload-namespace
|
||||||
|
// felis-config mirror with the freshly rendered pod config. Deliberately a full
|
||||||
|
// replace, not create-if-absent: a stale mirror is exactly what silently hands
|
||||||
|
// the Jobs that mount it old settings after a reconfigure. No-op when the
|
||||||
|
// workload namespace is unset or is the control namespace itself.
|
||||||
|
func replicateFelisConfigToWorkloadNamespace(ctx context.Context) error {
|
||||||
|
cfg, err := config.Load(hostSetupConfigPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ns := cfg.K8s.Namespace
|
||||||
|
if ns == "" || ns == "felis" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
manifest, err := kubectlOutput(ctx,
|
||||||
|
"-n", ns, "create", "secret", "generic", "felis-config",
|
||||||
|
"--from-file=felis.toml="+podSetupConfigPath,
|
||||||
|
"--dry-run=client", "-o", "yaml",
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("render felis-config for %s: %w", ns, err)
|
||||||
|
}
|
||||||
|
if err := kubectlWithInput(ctx, manifest, "-n", ns, "apply", "-f", "-"); err != nil {
|
||||||
|
return fmt.Errorf("replicate felis-config to %s: %w", ns, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func installCloudflaredService(ctx context.Context, cloudflaredBin, configPath string) error {
|
func installCloudflaredService(ctx context.Context, cloudflaredBin, configPath string) error {
|
||||||
|
|||||||
+7
-18
@@ -384,13 +384,13 @@ func applySMTPSecret(ctx context.Context, password string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// replicateSMTPToWorkloadNamespace refreshes the workload-namespace (minecraft)
|
// replicateSMTPToWorkloadNamespace refreshes the workload-namespace (minecraft)
|
||||||
// copies of felis-smtp and felis-config after email is reconfigured. The
|
// copy of felis-smtp after email is reconfigured. The reaper's CronJob runs
|
||||||
// reaper's CronJob runs there and resolves both by local reference — a
|
// there and resolves the password by local reference — a secretKeyRef is
|
||||||
// secretKeyRef is namespace-local, and `felis setup` creates the felis-config
|
// namespace-local — so without this refresh a later SMTP change would never
|
||||||
// replica create-if-absent, so without this refresh a later SMTP change would
|
// reach the pre-reap warning emails. Deliberately OVERWRITES: this is a mirror
|
||||||
// never reach the pre-reap warning emails. Deliberately OVERWRITES both: these
|
// of the control-namespace source, and a stale mirror is exactly the failure
|
||||||
// are mirrors of the control-namespace sources, and a stale mirror is exactly
|
// this closes. The felis-config mirror rides along in applyFelisConfigSecret,
|
||||||
// the failure this closes.
|
// which every apply path refreshes.
|
||||||
func replicateSMTPToWorkloadNamespace(ctx context.Context, password string) error {
|
func replicateSMTPToWorkloadNamespace(ctx context.Context, password string) error {
|
||||||
cfg, err := config.Load(hostSetupConfigPath)
|
cfg, err := config.Load(hostSetupConfigPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -407,16 +407,5 @@ func replicateSMTPToWorkloadNamespace(ctx context.Context, password string) erro
|
|||||||
if err := kubectlWithInput(ctx, smtpManifest, "-n", ns, "apply", "-f", "-"); err != nil {
|
if err := kubectlWithInput(ctx, smtpManifest, "-n", ns, "apply", "-f", "-"); err != nil {
|
||||||
return fmt.Errorf("replicate %s to %s: %w", platform.SMTPSecretName, ns, err)
|
return fmt.Errorf("replicate %s to %s: %w", platform.SMTPSecretName, ns, err)
|
||||||
}
|
}
|
||||||
manifest, err := kubectlOutput(ctx,
|
|
||||||
"-n", ns, "create", "secret", "generic", "felis-config",
|
|
||||||
"--from-file=felis.toml="+podSetupConfigPath,
|
|
||||||
"--dry-run=client", "-o", "yaml",
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("render felis-config for %s: %w", ns, err)
|
|
||||||
}
|
|
||||||
if err := kubectlWithInput(ctx, manifest, "-n", ns, "apply", "-f", "-"); err != nil {
|
|
||||||
return fmt.Errorf("replicate felis-config to %s: %w", ns, err)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user