carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package host
2
3import (
4 "context"
5 "errors"
6 "runtime"
7 "testing"
8 "time"
9
10 "github.com/carlosframework/platform/internal/registry"
11 "github.com/carlosframework/platform/internal/release"
12)
13
14// Issue #315, through the fast loop's production options: an agent that is
15// not root hands a named-unit route to root's pass rather than repointing it
16// and failing systemd's permission check. An agent run as root keeps
17// restarting the unit itself.
18func TestFastSweepHandsANamedUnitToRoot(t *testing.T) {
19 for _, tc := range []struct {
20 name string
21 root bool
22 }{{"agent user", false}, {"root", true}} {
23 t.Run(tc.name, func(t *testing.T) {
24 was := agentRunsAsRoot
25 agentRunsAsRoot = func() bool { return tc.root }
26 t.Cleanup(func() { agentRunsAsRoot = was })
27
28 env := newFastFixture(t)
29 ctx := context.Background()
30 plat := runtime.GOOS + "-" + runtime.GOARCH
31 for _, v := range []string{"v1", "v2"} {
32 m := release.Manifest{App: "fastapp", Version: v, Kind: "binary",
33 Artifacts: map[string]release.Artifact{plat: {}}}
34 if err := release.Ship(ctx, env.store, "bab", m, map[string][]byte{plat: []byte("build " + v)}); err != nil {
35 t.Fatalf("Ship %s: %v", v, err)
36 }
37 }
38 if err := release.Promote(ctx, env.store, env.priv, "bab", "fastapp", "canary/dev", "v1"); err != nil {
39 t.Fatal(err)
40 }
41 if err := env.reg.Upsert(registry.Route{Host: "console.test", Kind: "instance", App: "fastapp",
42 Channel: "canary/dev", Status: "ready", Addr: "127.0.0.1:8090"}); err != nil {
43 t.Fatal(err)
44 }
45 if err := release.Pass(ctx, env.reg, env.store, env.pub, env.optDir, nil); err != nil {
46 t.Fatal(err)
47 }
48 if err := env.reg.SetUnit("console.test", "console.service"); err != nil {
49 t.Fatal(err)
50 }
51 if err := release.Promote(ctx, env.store, env.priv, "bab", "fastapp", "canary/dev", "v2"); err != nil {
52 t.Fatal(err)
53 }
54
55 var unitRestarts []string
56 restart := makeRestartRoute(env.reg, func(string) {},
57 unitOnly(func(u string) error { unitRestarts = append(unitRestarts, u); return nil }), nil)
58 var relayed []error
59 stageReq := func(host, ver string, err error) {
60 if host == "console.test" && ver == "v2" {
61 relayed = append(relayed, err)
62 }
63 }
64 d := env.deps(nil)
65 d.restart = restart
66 d.passOpts = fastPassOpts(env.dataDir, stageReq, restart, nil)
67
68 fastTick(ctx, d, time.Unix(1754640000, 0))
69
70 live, err := release.LiveVersion(env.optDir, "console.test")
71 if err != nil {
72 t.Fatal(err)
73 }
74 if tc.root {
75 if live != "v2" || len(unitRestarts) != 1 || len(relayed) != 0 {
76 t.Fatalf("root agent: live %q, unit restarts %v, relays %v; want v2, one restart, no relay", live, unitRestarts, relayed)
77 }
78 return
79 }
80 if live != "v1" || len(unitRestarts) != 0 {
81 t.Fatalf("agent user: live %q, unit restarts %v; want v1 untouched and no restart", live, unitRestarts)
82 }
83 if len(relayed) != 1 || !errors.Is(relayed[0], release.ErrUnitRestartNeedsRoot) {
84 t.Fatalf("relays = %v, want one ErrUnitRestartNeedsRoot", relayed)
85 }
86 })
87 }
88}
89