Skip to content

Commit 4613e4c

Browse files
committed
feat(providers): SelfHostEnrollment resource, gateway-resource tests, crossplane generator fix (#1164)
Synced from sferarc/pgbeam@5d49e15
1 parent c78beda commit 4613e4c

3 files changed

Lines changed: 372 additions & 0 deletions

File tree

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export type {
2020
ProjectStatusKey as ProjectStatus,
2121
Replica as ReplicaData,
2222
RowFilter,
23+
SelfHostEnrollment as SelfHostEnrollmentData,
2324
SSLModeKey as SSLMode,
2425
StatementRules,
2526
WebhookEndpoint as WebhookEndpointData,
@@ -48,5 +49,6 @@ export {
4849
} from "./project.gen.js";
4950
export { configure } from "./provider.js";
5051
export { Replica, type ReplicaArgs } from "./replica.gen.js";
52+
export { SelfHostEnrollment, type SelfHostEnrollmentArgs } from "./selfHostEnrollment.gen.js";
5153
export { SpendLimit, type SpendLimitArgs } from "./spendLimit.gen.js";
5254
export { WebhookEndpoint, type WebhookEndpointArgs } from "./webhookEndpoint.gen.js";

src/resources.test.ts

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,219 @@ describe("SpendLimit resource", () => {
559559
});
560560
});
561561

562+
// ---------------------------------------------------------------------------
563+
// AgentCredential
564+
// ---------------------------------------------------------------------------
565+
describe("AgentCredential resource", () => {
566+
it("exports AgentCredential class", async () => {
567+
const { AgentCredential } = await import("./agentCredential.gen");
568+
expect(AgentCredential).toBeDefined();
569+
expect(typeof AgentCredential).toBe("function");
570+
});
571+
572+
it("can be instantiated with required args", async () => {
573+
const { AgentCredential } = await import("./agentCredential.gen");
574+
const cred = new AgentCredential("test-cred", {
575+
projectId: "prj_123",
576+
policyProfileId: "pol_123",
577+
name: "reporting-agent",
578+
});
579+
expect(cred).toBeDefined();
580+
});
581+
582+
it("accepts optional principal type, status, and expiry", async () => {
583+
const { AgentCredential } = await import("./agentCredential.gen");
584+
const cred = new AgentCredential("test-cred-optional", {
585+
projectId: "prj_123",
586+
policyProfileId: "pol_123",
587+
name: "human-operator",
588+
principalType: "human",
589+
status: "disabled",
590+
expiresAt: "2027-01-01T00:00:00Z",
591+
});
592+
expect(cred).toBeDefined();
593+
});
594+
595+
it("initializes computed outputs (including one-time secrets) as undefined", async () => {
596+
const { AgentCredential } = await import("./agentCredential.gen");
597+
const cred = new AgentCredential("test-cred-outputs", {
598+
projectId: "prj_123",
599+
policyProfileId: "pol_123",
600+
name: "reporting-agent",
601+
}) as unknown as Record<string, unknown>;
602+
603+
expect(cred.pgUsername).toBeUndefined();
604+
expect(cred.authMethod).toBeUndefined();
605+
expect(cred.connectionString).toBeUndefined();
606+
expect(cred.mcpUrl).toBeUndefined();
607+
expect(cred.mcpToken).toBeUndefined();
608+
});
609+
610+
it("marks the one-time secrets as additionalSecretOutputs", async () => {
611+
const pulumi = await import("@pulumi/pulumi");
612+
const { AgentCredential } = await import("./agentCredential.gen");
613+
new AgentCredential("test-cred-secrets", {
614+
projectId: "prj_123",
615+
policyProfileId: "pol_123",
616+
name: "reporting-agent",
617+
});
618+
const calls = (pulumi.dynamic.Resource as unknown as { mock: { calls: unknown[][] } }).mock
619+
.calls;
620+
const opts = calls[calls.length - 1][3] as { additionalSecretOutputs?: string[] };
621+
expect(opts.additionalSecretOutputs).toContain("connectionString");
622+
expect(opts.additionalSecretOutputs).toContain("mcpToken");
623+
});
624+
});
625+
626+
// ---------------------------------------------------------------------------
627+
// PolicyProfile
628+
// ---------------------------------------------------------------------------
629+
describe("PolicyProfile resource", () => {
630+
it("exports PolicyProfile class", async () => {
631+
const { PolicyProfile } = await import("./policyProfile.gen");
632+
expect(PolicyProfile).toBeDefined();
633+
expect(typeof PolicyProfile).toBe("function");
634+
});
635+
636+
it("can be instantiated with required args", async () => {
637+
const { PolicyProfile } = await import("./policyProfile.gen");
638+
const profile = new PolicyProfile("test-profile", {
639+
projectId: "prj_123",
640+
name: "read-only-agents",
641+
});
642+
expect(profile).toBeDefined();
643+
});
644+
645+
it("accepts structured enforcement config", async () => {
646+
const { PolicyProfile } = await import("./policyProfile.gen");
647+
const profile = new PolicyProfile("test-profile-full", {
648+
projectId: "prj_123",
649+
name: "guarded",
650+
accessMode: "read_only",
651+
tableAllowlist: ["public.orders", "public.customers"],
652+
tableDenylist: ["public.secrets"],
653+
maskingRules: [{ table: "public.customers", column: "email", kind: "redact" }],
654+
rowFilters: [{ table: "public.orders", predicate: "region = 'eu'" }],
655+
statementRules: { allow: ["select"], deny: ["truncate"] },
656+
budgetQueriesPerHour: 1000,
657+
maxRows: 500,
658+
writeMode: "rollback",
659+
approvalMode: "writes",
660+
migrationSafety: "block",
661+
maxAffectedRows: 100,
662+
});
663+
expect(profile).toBeDefined();
664+
});
665+
666+
it("initializes computed outputs as undefined", async () => {
667+
const { PolicyProfile } = await import("./policyProfile.gen");
668+
const profile = new PolicyProfile("test-profile-outputs", {
669+
projectId: "prj_123",
670+
name: "read-only-agents",
671+
}) as unknown as Record<string, unknown>;
672+
673+
expect(profile.createdAt).toBeUndefined();
674+
expect(profile.updatedAt).toBeUndefined();
675+
});
676+
});
677+
678+
// ---------------------------------------------------------------------------
679+
// WebhookEndpoint
680+
// ---------------------------------------------------------------------------
681+
describe("WebhookEndpoint resource", () => {
682+
it("exports WebhookEndpoint class", async () => {
683+
const { WebhookEndpoint } = await import("./webhookEndpoint.gen");
684+
expect(WebhookEndpoint).toBeDefined();
685+
expect(typeof WebhookEndpoint).toBe("function");
686+
});
687+
688+
it("can be instantiated with required args", async () => {
689+
const { WebhookEndpoint } = await import("./webhookEndpoint.gen");
690+
const hook = new WebhookEndpoint("test-hook", {
691+
projectId: "prj_123",
692+
url: "https://example.com/hooks/audit",
693+
});
694+
expect(hook).toBeDefined();
695+
});
696+
697+
it("accepts the write-only signing secret and delivery options", async () => {
698+
const { WebhookEndpoint } = await import("./webhookEndpoint.gen");
699+
const hook = new WebhookEndpoint("test-hook-full", {
700+
projectId: "prj_123",
701+
url: "https://example.com/hooks/audit",
702+
format: "json",
703+
eventTypes: ["audit.query", "anomaly.detected"],
704+
enabled: true,
705+
description: "SIEM export",
706+
secret: "whsec_test",
707+
});
708+
expect(hook).toBeDefined();
709+
});
710+
711+
it("initializes computed outputs as undefined", async () => {
712+
const { WebhookEndpoint } = await import("./webhookEndpoint.gen");
713+
const hook = new WebhookEndpoint("test-hook-outputs", {
714+
projectId: "prj_123",
715+
url: "https://example.com/hooks/audit",
716+
}) as unknown as Record<string, unknown>;
717+
718+
expect(hook.createdAt).toBeUndefined();
719+
expect(hook.updatedAt).toBeUndefined();
720+
});
721+
});
722+
723+
// ---------------------------------------------------------------------------
724+
// SelfHostEnrollment
725+
// ---------------------------------------------------------------------------
726+
describe("SelfHostEnrollment resource", () => {
727+
it("exports SelfHostEnrollment class", async () => {
728+
const { SelfHostEnrollment } = await import("./selfHostEnrollment.gen");
729+
expect(SelfHostEnrollment).toBeDefined();
730+
expect(typeof SelfHostEnrollment).toBe("function");
731+
});
732+
733+
it("can be instantiated with required args", async () => {
734+
const { SelfHostEnrollment } = await import("./selfHostEnrollment.gen");
735+
const enrollment = new SelfHostEnrollment("test-enrollment", {
736+
orgId: "org_123",
737+
});
738+
expect(enrollment).toBeDefined();
739+
});
740+
741+
it("accepts optional region label and description", async () => {
742+
const { SelfHostEnrollment } = await import("./selfHostEnrollment.gen");
743+
const enrollment = new SelfHostEnrollment("test-enrollment-labeled", {
744+
orgId: "org_123",
745+
regionLabel: "customer-vpc-us-east",
746+
description: "prod cluster",
747+
});
748+
expect(enrollment).toBeDefined();
749+
});
750+
751+
it("initializes computed outputs (including the one-time token) as undefined", async () => {
752+
const { SelfHostEnrollment } = await import("./selfHostEnrollment.gen");
753+
const enrollment = new SelfHostEnrollment("test-enrollment-outputs", {
754+
orgId: "org_123",
755+
}) as unknown as Record<string, unknown>;
756+
757+
expect(enrollment.createdBy).toBeUndefined();
758+
expect(enrollment.createdAt).toBeUndefined();
759+
expect(enrollment.token).toBeUndefined();
760+
});
761+
762+
it("marks the one-time token as an additionalSecretOutput", async () => {
763+
const pulumi = await import("@pulumi/pulumi");
764+
const { SelfHostEnrollment } = await import("./selfHostEnrollment.gen");
765+
new SelfHostEnrollment("test-enrollment-secret", {
766+
orgId: "org_123",
767+
});
768+
const calls = (pulumi.dynamic.Resource as unknown as { mock: { calls: unknown[][] } }).mock
769+
.calls;
770+
const opts = calls[calls.length - 1][3] as { additionalSecretOutputs?: string[] };
771+
expect(opts.additionalSecretOutputs).toContain("token");
772+
});
773+
});
774+
562775
// ---------------------------------------------------------------------------
563776
// Index re-exports
564777
// ---------------------------------------------------------------------------
@@ -571,6 +784,10 @@ describe("Pulumi package index", () => {
571784
expect(mod.CustomDomain).toBeDefined();
572785
expect(mod.Replica).toBeDefined();
573786
expect(mod.SpendLimit).toBeDefined();
787+
expect(mod.AgentCredential).toBeDefined();
788+
expect(mod.PolicyProfile).toBeDefined();
789+
expect(mod.WebhookEndpoint).toBeDefined();
790+
expect(mod.SelfHostEnrollment).toBeDefined();
574791
expect(mod.configure).toBeDefined();
575792
expect(mod.verifyCustomDomain).toBeDefined();
576793
});
@@ -593,5 +810,9 @@ describe("Pulumi package index", () => {
593810
expect(typeof mod.CustomDomain).toBe("function");
594811
expect(typeof mod.Replica).toBe("function");
595812
expect(typeof mod.SpendLimit).toBe("function");
813+
expect(typeof mod.AgentCredential).toBe("function");
814+
expect(typeof mod.PolicyProfile).toBe("function");
815+
expect(typeof mod.WebhookEndpoint).toBe("function");
816+
expect(typeof mod.SelfHostEnrollment).toBe("function");
596817
});
597818
});

0 commit comments

Comments
 (0)