//go:build linux && rootrunner package host import ( "bytes" "context" "errors" "os" "os/exec" "path/filepath" "testing" "time" "github.com/carlosframework/platform/internal/hostwrite" "github.com/carlosframework/platform/internal/registry" "github.com/carlosframework/platform/internal/release" "github.com/carlosframework/platform/internal/rootparticipation" "github.com/carlosframework/platform/internal/rootstate" ) func TestPlan14NoCensusReleaseRootRunner(t *testing.T) { if _, err := os.Lstat("/var/lib/carlos-release"); !os.IsNotExist(err) { t.Fatal("existing release state", err) } t.Cleanup(func() { os.RemoveAll("/var/lib/carlos-release") }) for _, scenario := range []string{"absent", "empty", "held", "aborted"} { t.Run(scenario, func(t *testing.T) { var s rootstate.Store if scenario != "absent" { var err error s, err = rootstate.Open(rootReleasePrivate, true, false) if err != nil { t.Fatal(err) } defer s.Close() } if scenario == "held" || scenario == "aborted" { unlock, err := s.Lock(t.Context(), "release.lock") if err != nil { t.Fatal(err) } if scenario == "held" { defer unlock() } else { unlock() } } before, _ := os.ReadDir(rootReleasePrivate) for _, flag := range []string{"", "1"} { t.Setenv("CARLOS_HOST_CLAIM", flag) plan14NoCensusCommands(t) ctx, cancel := context.WithTimeout(t.Context(), time.Second) called := false err := withClaimRootRelease(ctx, false, func() (rootstate.Store, error) { t.Fatal("opened root release"); return nil, os.ErrPermission }, func() error { called = true; return nil }, func() (rootparticipation.Ledger, bool, error) { return rootparticipation.Ledger{}, false, nil }) if err != nil || !called { t.Fatal("adopt", err, called) } for _, recover := range []bool{false, true} { f := newApplyFixture(t, "canary", "v1.0.0") f.a.participation = nil f.a.rootMoves = rootMovesFloorIdentity if err := f.a.runWithRelease(ctx, recover); err != nil { t.Fatal("system", recover, err) } } cancel() } after, _ := os.ReadDir(rootReleasePrivate) if len(after) != len(before) { t.Fatal("new release file", before, after) } if scenario == "absent" { if _, err := os.Lstat(rootReleasePrivate); !os.IsNotExist(err) { t.Fatal("created release directory", err) } } }) } } func plan14NoCensusCommands(t *testing.T) { t.Helper() for _, mode := range []string{"adopt", "apply", "recover"} { dir := t.TempDir() ctx, cancel := context.WithTimeout(t.Context(), 5*time.Second) cmd := exec.CommandContext(ctx, os.Args[0], "-test.run=^TestPlan14NoCensusCommandPayload$") cmd.Env = isolatedAdoptOrderEnv(t, "PLAN14_R10_COMMAND="+mode, "CARLOS_HOST_CLAIM="+os.Getenv("CARLOS_HOST_CLAIM"), "CARLOS_DATA_DIR="+filepath.Join(dir, "data"), "CARLOS_OPT_DIR="+filepath.Join(dir, "opt"), "CARLOS_DEPLOYMENT_BUCKET=", "CARLOS_DEPLOYMENT_DIR="+filepath.Join(dir, "bucket"), "CARLOS_REGION_HA=", "CARLOS_MOVES_PHASE1=") out, err := cmd.CombinedOutput() cancel() if mode == "adopt" { var status *exec.ExitError if !errors.As(err, &status) || status.ExitCode() != 2 || !bytes.Contains(out, []byte("flag provided but not defined: -plan14-no-such-option")) { t.Fatal("adopt did not reach ordinary argument handling", err, string(out)) } } else if err != nil { t.Fatal(mode, err, string(out)) } } } func TestPlan14NoCensusCommandPayload(t *testing.T) { switch os.Getenv("PLAN14_R10_COMMAND") { case "adopt": RunAdopt([]string{"-plan14-no-such-option"}) case "apply": RunSystemApply(nil) case "recover": RunSystemApply([]string{"-recover"}) default: t.Fatal("fixture only") } } func TestPlan14PendingAcquisitionStartupRootRunner(t *testing.T) { if err := os.Mkdir("/var/lib/carlos-release", 0700); err != nil { t.Fatal(err) } t.Cleanup(func() { os.RemoveAll("/var/lib/carlos-release") }) for _, mode := range []string{"instance-control", "system"} { t.Run(mode, func(t *testing.T) { t.Setenv("PLAN14_R10_ACQUISITION", mode) runServingParkPeerNamespace(t, false, false, "seed-construction") }) } } func TestPlan14AcquisitionCrashPayload(t *testing.T) { if os.Getenv("PLAN14_R10_CRASH") != "1" { t.Fatal("fixture only") } s, err := rootstate.Open(rootparticipation.Namespace, false, false) if err != nil { t.Fatal(err) } l := rootparticipation.Ledger{State: s} if err := l.Acquire(t.Context(), func() error { os.Exit(0); return nil }); err != nil { t.Fatal(err) } t.Fatal("did not die at durable acquisition") } func plan14PendingAcquisition(t *testing.T, opt, deployment string) { cmd := exec.Command(os.Args[0], "-test.run=^TestPlan14AcquisitionCrashPayload$") cmd.Env = append(os.Environ(), "PLAN14_R10_CRASH=1") if out, err := cmd.CombinedOutput(); err != nil { t.Fatal(string(out), err) } s, err := rootstate.Open(rootparticipation.Namespace, false, false) if err != nil { t.Fatal(err) } defer s.Close() l := rootparticipation.Ledger{State: s} if _, err := l.Census(); !errors.Is(err, rootparticipation.ErrUnavailable) { t.Fatal("pending acquisition admitted", err) } c, err := l.RecoveryCensus() if err != nil || c.Pending != "acquisition" { t.Fatal(c, err) } t.Setenv("CARLOS_DEPLOYMENT_BUCKET", deployment) id, required, err := rootMovesFloorIdentity() if err != nil || !required { t.Fatal("floor identity dead end", required, err) } t.Setenv("CARLOS_DEPLOYMENT_BUCKET", "") if os.Getenv("PLAN14_R10_ACQUISITION") == "system" { f := newApplyFixture(t, "canary", "v1.0.0") f.a.optDir = opt f.a.dataDir = "/data" f.a.rootMoves = func() (rootFloorIdentity, bool, error) { return id, true, nil } f.a.participation = nil if err := f.a.runWithRelease(t.Context(), true); err != nil { t.Fatal("system recovery entrypoint", err) } if _, err := l.Census(); err != nil { t.Fatal("acquisition not settled", err) } } } func TestPlan14RetiredInstallationStartupRootRunner(t *testing.T) { if err := os.Mkdir("/var/lib/carlos-release", 0700); err != nil { t.Fatal(err) } t.Cleanup(func() { os.RemoveAll("/var/lib/carlos-release") }) for _, mode := range []string{"complete", "interrupted"} { t.Run(mode, func(t *testing.T) { t.Setenv("PLAN14_R10_RETIRED", mode) runServingParkPeerNamespace(t, false, false, "seed-construction") }) } } func TestPlan14RetiredMigrationPayloadRootRunner(t *testing.T) { testRootMigrationBootstrap(t, true, false) } func TestPlan14LocalBackingStateRootRunner(t *testing.T) { if err := os.Mkdir("/var/lib/private", 0700); err == nil { t.Cleanup(func() { os.Remove("/var/lib/private") }) } else if !os.IsExist(err) { t.Fatal(err) } for _, dir := range []string{"/var/lib/carlos-app", "/var/lib/private/carlos-app"} { t.Run(dir, func(t *testing.T) { if err := os.Mkdir(dir, 0755); err != nil { t.Fatal("existing backing state", err) } t.Cleanup(func() { os.RemoveAll(dir) }) if err := os.Mkdir(filepath.Join(dir, "hidden.example"), 0700); err != nil { t.Fatal(err) } reg := restartTestRegistry(t) for _, attack := range []string{"omitted", "cleared"} { if attack == "cleared" { if err := reg.Upsert(registry.Route{Host: "hidden.example", Account: "bab", App: "app", Socket: "/run/hidden.sock"}); err != nil { t.Fatal(err) } } p := &activationPreflightOwner{} scratch := t.TempDir() r := ClaimRuntimeResources{Mode: "instance-control", Registry: reg, DataDir: scratch, OptDir: scratch, UnitsDir: scratch} store := release.NewDirStore(t.TempDir()) if _, err := OpenProductionClaimAssembly(t.Context(), store, r, p); !errors.Is(err, hostwrite.ErrUnavailable) || p.calls != 0 { t.Fatal("local backing omitted", attack, err, p.calls) } if err := migrateClaimJournalsWith(t.Context(), store, r, p, true); !errors.Is(err, hostwrite.ErrUnavailable) || p.calls != 0 { t.Fatal("migration backing omitted", attack, err, p.calls) } } }) } }