diff --git a/.gitignore b/.gitignore index 8465bde..047ccb5 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ # go /vendor/ + +# Python bytecode written by configs/test_felhom_os_apply.py +configs/__pycache__/ diff --git a/cmd/felhom-agent/main.go b/cmd/felhom-agent/main.go index 7140f02..29dca44 100644 --- a/cmd/felhom-agent/main.go +++ b/cmd/felhom-agent/main.go @@ -3496,8 +3496,12 @@ func (f *selftestFlag) Set(v string) error { f.mode = "identity-consume" case "controller-swap": f.mode = "controller-swap" + case "os-update": + f.mode = "os-update" + case "wgtunnel": // dispatched since S3 but refused here until 2026-10-04 (TestSelftestFlag_AcceptsEveryDispatchedMode) + f.mode = "wgtunnel" default: - return fmt.Errorf("invalid --selftest value %q (want read|task|hub|storage|backup|restore-test|restore-test-due|pbs-verify|bring-up|provision|escrow-create|escrow-consume|identity-consume|controller-swap)", v) + return fmt.Errorf("invalid --selftest value %q (want read|task|hub|storage|backup|restore-test|restore-test-due|pbs-verify|lanresolver|wgtunnel|bring-up|provision|escrow-create|escrow-consume|identity-consume|controller-swap|os-update)", v) } return nil } diff --git a/cmd/felhom-agent/selftest_flag_test.go b/cmd/felhom-agent/selftest_flag_test.go new file mode 100644 index 0000000..4386c43 --- /dev/null +++ b/cmd/felhom-agent/selftest_flag_test.go @@ -0,0 +1,39 @@ +package main + +import ( + "os" + "regexp" + "strings" + "testing" +) + +// Every mode the dispatcher (`switch selftest.mode`) runs must be ACCEPTED by the --selftest flag. Found live +// 2026-10-04: --selftest=os-update had a dispatch case and a function but the flag's allow-list refused it, so the +// debug action could not run. Red-proof: drop the "os-update" case from selftestFlag.Set and this fails. +func TestSelftestFlag_AcceptsEveryDispatchedMode(t *testing.T) { + src, err := os.ReadFile("main.go") + if err != nil { + t.Fatal(err) + } + s := string(src) + i := strings.Index(s, "switch selftest.mode {") + if i < 0 { + t.Fatal("dispatch switch not found") + } + block := s[i:] + block = block[:strings.Index(block, "\n\t}\n")] + modes := regexp.MustCompile(`(?m)^\tcase "([a-z-]+)":`).FindAllStringSubmatch(block, -1) + if len(modes) < 5 { + t.Fatalf("parsed only %d dispatch cases — the parser is wrong", len(modes)) + } + var bad []string + for _, m := range modes { + var f selftestFlag + if err := f.Set(m[1]); err != nil { + bad = append(bad, m[1]) + } + } + if len(bad) > 0 { + t.Fatalf("dispatched but refused by --selftest: %v", bad) + } +}