| index 91dce0b54..24ddf82aa 100644 |
| --- a/internal/console/plancaps_doors_test.go |
| +++ b/internal/console/plancaps_doors_test.go |
| @@ -5,10 +5,12 @@ import ( |
| "fmt" |
| "net/http" |
| "net/url" |
| + "strings" |
| "sync" |
| "testing" |
| |
| "github.com/carlosframework/platform/internal/plans" |
| + "github.com/carlosframework/platform/internal/provision" |
| ) |
| |
| // atRunningCap turns plans on and leaves the fixture's ops account with |
| @@ -148,3 +150,76 @@ func TestCreateAppWithoutACatalogUnchanged(t *testing.T) { |
| t.Fatalf("create with no catalog = %d %v", status, out) |
| } |
| } |
| + |
| +// sponsorCustomDomains keeps the cap as atRunningCap left it and adds custom |
| +// domains, so a first-route attach meets the running-things cap rather than |
| +// the custom-domain gate. |
| +func sponsorCustomDomains(t *testing.T, fx *consoleFixture, acct *Account) { |
| + t.Helper() |
| + row, err := fx.st.AccountPlan(acct.ID) |
| + if err != nil || row == nil || row.Sponsored == nil { |
| + t.Fatalf("plan row: %+v, %v", row, err) |
| + } |
| + sp := *row.Sponsored |
| + sp.CustomDomains = true |
| + if _, err := fx.st.SetAccountPlan(acct.ID, "free", nil, PlanSourceSponsored, &sp, "test", "ops@example.com", planNow); err != nil { |
| + t.Fatal(err) |
| + } |
| +} |
| + |
| +func TestInstanceCreateRefusedAtTheRunningThingsCap(t *testing.T) { |
| + fx, token := instanceFixture(t, "code-cap-instance") |
| + enableInstances(t, fx, "titogo", titoManifest()) |
| + atRunningCap(t, fx, 3) |
| + status, _, out := rawReq(t, http.MethodPost, instancesURL(fx, "bab", "titogo"), token, `{"host":"acme.go.tito.io","region":"ie"}`) |
| + if status != http.StatusConflict || !strings.Contains(out, `"code":"cap"`) { |
| + t.Fatalf("instance create at the cap = %d %s, want 409 cap", status, out) |
| + } |
| + if _, err := provision.GetRecord(context.Background(), fx.rel, "bab", "titogo", "acme.go.tito.io"); err == nil { |
| + t.Fatal("an instance record was written past the cap") |
| + } |
| +} |
| + |
| +func TestFirstRouteAttachRefusedAtTheRunningThingsCap(t *testing.T) { |
| + fx, token := instanceFixture(t, "code-cap-firstroute") |
| + shipVersion(t, fx, "titogo", "v1") |
| + seedChannel(t, fx, "titogo", "canary/live", "v1") |
| + acct := atRunningCap(t, fx, 3) |
| + sponsorCustomDomains(t, fx, acct) |
| + status, _, out := rawReq(t, http.MethodPost, domainsURL(fx, "bab", "titogo"), token, `{"host":"shop.example.com","kind":"static"}`) |
| + if status != http.StatusConflict { |
| + t.Fatalf("first-route attach at the cap = %d %s, want 409", status, out) |
| + } |
| + if _, err := provision.GetRecord(context.Background(), fx.rel, "bab", "titogo", "shop.example.com"); err == nil { |
| + t.Fatal("a first-route record was written past the cap") |
| + } |
| +} |
| + |
| +func TestSidecarCreateRefusedAtTheSidecarCap(t *testing.T) { |
| + fx, token := instanceFixture(t, "code-cap-sidecar") |
| + enableSidecars(t, fx, "titogo", titoSidecarManifest()) |
| + fx.srv.cfg.PlanCatalog = examplePlanCatalog(t) |
| + acct, _ := fx.st.AccountBySqid("bab") |
| + capsSidecar(t, fx, acct, "titogo", "first") |
| + status, _, out := rawReq(t, http.MethodPost, sidecarsURL(fx, "bab", "titogo"), token, `{"name":"bot","region":"ie"}`) |
| + if status != http.StatusConflict || !strings.Contains(out, `"code":"cap"`) { |
| + t.Fatalf("second sidecar on free = %d %s, want 409 cap", status, out) |
| + } |
| + if _, _, err := fx.rel.Get(context.Background(), provision.SidecarRecordKey("bab", "titogo", "bot")); err == nil { |
| + t.Fatal("a sidecar record was written past the cap") |
| + } |
| +} |
| + |
| +func TestInstanceAndSidecarCreateWithoutACatalogUnchanged(t *testing.T) { |
| + fx, token := instanceFixture(t, "code-cap-inst-nocat") |
| + enableInstances(t, fx, "titogo", titoManifest()) |
| + if status, _, out := rawReq(t, http.MethodPost, instancesURL(fx, "bab", "titogo"), token, `{"host":"acme.go.tito.io","region":"ie"}`); status != http.StatusCreated { |
| + t.Fatalf("instance create with no catalog = %d %s", status, out) |
| + } |
| + enableSidecars(t, fx, "titogo", titoSidecarManifest()) |
| + acct, _ := fx.st.AccountBySqid("bab") |
| + capsSidecar(t, fx, acct, "titogo", "first") |
| + if status, _, out := rawReq(t, http.MethodPost, sidecarsURL(fx, "bab", "titogo"), token, `{"name":"bot","region":"ie"}`); status != http.StatusCreated { |
| + t.Fatalf("sidecar create with no catalog = %d %s", status, out) |
| + } |
| +} |