@cyc-seattle/platform 0.7.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +6 -6
- package/dist/index.js +6 -19
- package/dist/kubernetes.d.ts +1 -1
- package/dist/kubernetes.js +3 -39
- package/dist/outputs.js +25 -65
- package/dist/scheduled-job.d.ts +1 -1
- package/dist/scheduled-job.js +8 -45
- package/dist/services.js +2 -38
- package/dist/web-service.d.ts +1 -1
- package/dist/web-service.js +8 -46
- package/dist/workload.d.ts +1 -1
- package/dist/workload.js +8 -50
- package/package.json +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { clusterProvider, type ClusterProviderArgs } from "./kubernetes";
|
|
2
|
-
export { getPlatformOutputs, parsePlatformOutputs, platformOutputsSchema, readPlatformOutputs, stateBucket, type PlatformOutputs, type PlatformOutputsArgs, } from "./outputs";
|
|
3
|
-
export { ScheduledJob, type ScheduledJobArgs } from "./scheduled-job";
|
|
4
|
-
export { enableService } from "./services";
|
|
5
|
-
export { WebService, type WebServiceArgs } from "./web-service";
|
|
6
|
-
export { Workload, type PodArgs, type WorkloadArgs, type WorkloadVolume } from "./workload";
|
|
1
|
+
export { clusterProvider, type ClusterProviderArgs } from "./kubernetes.ts";
|
|
2
|
+
export { getPlatformOutputs, parsePlatformOutputs, platformOutputsSchema, readPlatformOutputs, stateBucket, type PlatformOutputs, type PlatformOutputsArgs, } from "./outputs.ts";
|
|
3
|
+
export { ScheduledJob, type ScheduledJobArgs } from "./scheduled-job.ts";
|
|
4
|
+
export { enableService } from "./services.ts";
|
|
5
|
+
export { WebService, type WebServiceArgs } from "./web-service.ts";
|
|
6
|
+
export { Workload, type PodArgs, type WorkloadArgs, type WorkloadVolume } from "./workload.ts";
|
package/dist/index.js
CHANGED
|
@@ -1,19 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Object.defineProperty(exports, "getPlatformOutputs", { enumerable: true, get: function () { return outputs_1.getPlatformOutputs; } });
|
|
8
|
-
Object.defineProperty(exports, "parsePlatformOutputs", { enumerable: true, get: function () { return outputs_1.parsePlatformOutputs; } });
|
|
9
|
-
Object.defineProperty(exports, "platformOutputsSchema", { enumerable: true, get: function () { return outputs_1.platformOutputsSchema; } });
|
|
10
|
-
Object.defineProperty(exports, "readPlatformOutputs", { enumerable: true, get: function () { return outputs_1.readPlatformOutputs; } });
|
|
11
|
-
Object.defineProperty(exports, "stateBucket", { enumerable: true, get: function () { return outputs_1.stateBucket; } });
|
|
12
|
-
var scheduled_job_1 = require("./scheduled-job");
|
|
13
|
-
Object.defineProperty(exports, "ScheduledJob", { enumerable: true, get: function () { return scheduled_job_1.ScheduledJob; } });
|
|
14
|
-
var services_1 = require("./services");
|
|
15
|
-
Object.defineProperty(exports, "enableService", { enumerable: true, get: function () { return services_1.enableService; } });
|
|
16
|
-
var web_service_1 = require("./web-service");
|
|
17
|
-
Object.defineProperty(exports, "WebService", { enumerable: true, get: function () { return web_service_1.WebService; } });
|
|
18
|
-
var workload_1 = require("./workload");
|
|
19
|
-
Object.defineProperty(exports, "Workload", { enumerable: true, get: function () { return workload_1.Workload; } });
|
|
1
|
+
export { clusterProvider } from "./kubernetes.js";
|
|
2
|
+
export { getPlatformOutputs, parsePlatformOutputs, platformOutputsSchema, readPlatformOutputs, stateBucket, } from "./outputs.js";
|
|
3
|
+
export { ScheduledJob } from "./scheduled-job.js";
|
|
4
|
+
export { enableService } from "./services.js";
|
|
5
|
+
export { WebService } from "./web-service.js";
|
|
6
|
+
export { Workload } from "./workload.js";
|
package/dist/kubernetes.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as k8s from "@pulumi/kubernetes";
|
|
2
2
|
import * as pulumi from "@pulumi/pulumi";
|
|
3
|
-
import type { PlatformOutputs } from "./outputs";
|
|
3
|
+
import type { PlatformOutputs } from "./outputs.ts";
|
|
4
4
|
export interface ClusterProviderArgs {
|
|
5
5
|
/**
|
|
6
6
|
* Keeps a kubeconfig that is unknown or changes, such as during a cluster update, from replacing
|
package/dist/kubernetes.js
CHANGED
|
@@ -1,48 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.clusterProvider = clusterProvider;
|
|
37
|
-
const k8s = __importStar(require("@pulumi/kubernetes"));
|
|
38
|
-
const pulumi = __importStar(require("@pulumi/pulumi"));
|
|
1
|
+
import * as k8s from "@pulumi/kubernetes";
|
|
2
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
39
3
|
/**
|
|
40
4
|
* A Kubernetes provider for the environment's cluster. Its kubeconfig runs gke-gcloud-auth-plugin
|
|
41
5
|
* with Application Default Credentials, so it is the same on every run, unlike one that embeds an
|
|
42
6
|
* access token. The plugin must be on PATH: `mise run install` adds it. The cluster stack passes
|
|
43
7
|
* only the endpoint, because it writes the rest.
|
|
44
8
|
*/
|
|
45
|
-
function clusterProvider(platform, name = "cluster", opts, args = {}) {
|
|
9
|
+
export function clusterProvider(platform, name = "cluster", opts, args = {}) {
|
|
46
10
|
// The DNS-based endpoint serves a publicly trusted certificate, so the kubeconfig needs no CA.
|
|
47
11
|
const kubeconfig = pulumi.output(platform).clusterEndpoint.apply((endpoint) => JSON.stringify({
|
|
48
12
|
apiVersion: "v1",
|
package/dist/outputs.js
CHANGED
|
@@ -1,71 +1,31 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.outputsObject = exports.platformOutputsSchema = void 0;
|
|
37
|
-
exports.stateBucket = stateBucket;
|
|
38
|
-
exports.parsePlatformOutputs = parsePlatformOutputs;
|
|
39
|
-
exports.readPlatformOutputs = readPlatformOutputs;
|
|
40
|
-
exports.getPlatformOutputs = getPlatformOutputs;
|
|
41
|
-
const gcp = __importStar(require("@pulumi/gcp"));
|
|
42
|
-
const pulumi = __importStar(require("@pulumi/pulumi"));
|
|
43
|
-
const zod_1 = require("zod");
|
|
1
|
+
import * as gcp from "@pulumi/gcp";
|
|
2
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
3
|
+
import { z } from "zod";
|
|
44
4
|
// The cluster stack writes this object to each environment's state bucket, because a StackReference
|
|
45
5
|
// can't cross from a dev stack into prod's backend (cyc-seattle/isthmia#215).
|
|
46
|
-
|
|
47
|
-
project:
|
|
48
|
-
projectNumber:
|
|
49
|
-
region:
|
|
50
|
-
cluster:
|
|
51
|
-
clusterEndpoint:
|
|
52
|
-
namespace:
|
|
53
|
-
gateway:
|
|
54
|
-
domain:
|
|
55
|
-
sqlConnectionName:
|
|
6
|
+
export const platformOutputsSchema = z.object({
|
|
7
|
+
project: z.string().min(1),
|
|
8
|
+
projectNumber: z.string().regex(/^\d+$/),
|
|
9
|
+
region: z.string().min(1),
|
|
10
|
+
cluster: z.string().min(1),
|
|
11
|
+
clusterEndpoint: z.string().min(1),
|
|
12
|
+
namespace: z.string().min(1),
|
|
13
|
+
gateway: z.object({ name: z.string().min(1), namespace: z.string().min(1) }),
|
|
14
|
+
domain: z.string().min(1),
|
|
15
|
+
sqlConnectionName: z.string().min(1),
|
|
56
16
|
/** The environment's Cloud SQL private IP, which pods reach directly. */
|
|
57
|
-
sqlHost:
|
|
17
|
+
sqlHost: z.string().min(1),
|
|
58
18
|
/** The shared Gateway's IPv4 address, for an app's own DNS records. */
|
|
59
|
-
gatewayAddress:
|
|
60
|
-
registry:
|
|
19
|
+
gatewayAddress: z.string().min(1),
|
|
20
|
+
registry: z.string().min(1),
|
|
61
21
|
});
|
|
62
|
-
|
|
22
|
+
export const outputsObject = "platform/outputs.json";
|
|
63
23
|
/** The state bucket of an environment, as `stacks/bootstrap/state.ts` names it. */
|
|
64
|
-
function stateBucket(project, environment) {
|
|
24
|
+
export function stateBucket(project, environment) {
|
|
65
25
|
return `${project}-pulumi-${environment}`;
|
|
66
26
|
}
|
|
67
27
|
/** Parses and validates the outputs file's text. `source` names the file in error messages. */
|
|
68
|
-
function parsePlatformOutputs(text, source) {
|
|
28
|
+
export function parsePlatformOutputs(text, source) {
|
|
69
29
|
let json;
|
|
70
30
|
try {
|
|
71
31
|
json = JSON.parse(text);
|
|
@@ -73,20 +33,20 @@ function parsePlatformOutputs(text, source) {
|
|
|
73
33
|
catch (e) {
|
|
74
34
|
throw new Error(`${source} is not valid JSON: ${e.message}`);
|
|
75
35
|
}
|
|
76
|
-
const result =
|
|
36
|
+
const result = platformOutputsSchema.safeParse(json);
|
|
77
37
|
if (!result.success) {
|
|
78
|
-
throw new Error(`${source} doesn't hold the platform outputs:\n${
|
|
38
|
+
throw new Error(`${source} doesn't hold the platform outputs:\n${z.prettifyError(result.error)}`);
|
|
79
39
|
}
|
|
80
40
|
return result.data;
|
|
81
41
|
}
|
|
82
42
|
/** Reads this environment's platform values from its state bucket. Most programs want `getPlatformOutputs`. */
|
|
83
|
-
async function readPlatformOutputs(args = {}) {
|
|
43
|
+
export async function readPlatformOutputs(args = {}) {
|
|
84
44
|
const project = args.project ?? new pulumi.Config("gcp").require("project");
|
|
85
45
|
const bucket = stateBucket(project, args.environment ?? pulumi.getStack());
|
|
86
|
-
const source = `gs://${bucket}/${
|
|
46
|
+
const source = `gs://${bucket}/${outputsObject}`;
|
|
87
47
|
let content;
|
|
88
48
|
try {
|
|
89
|
-
({ content } = await gcp.storage.getBucketObjectContent({ bucket, name:
|
|
49
|
+
({ content } = await gcp.storage.getBucketObjectContent({ bucket, name: outputsObject }));
|
|
90
50
|
}
|
|
91
51
|
catch (e) {
|
|
92
52
|
throw new Error(`Can't read ${source}. The cluster stack writes it.\n${e.message}`);
|
|
@@ -97,6 +57,6 @@ async function readPlatformOutputs(args = {}) {
|
|
|
97
57
|
return parsePlatformOutputs(content, source);
|
|
98
58
|
}
|
|
99
59
|
/** Reads this environment's platform values from its state bucket. */
|
|
100
|
-
function getPlatformOutputs(args = {}) {
|
|
60
|
+
export function getPlatformOutputs(args = {}) {
|
|
101
61
|
return pulumi.output(readPlatformOutputs(args));
|
|
102
62
|
}
|
package/dist/scheduled-job.d.ts
CHANGED
package/dist/scheduled-job.js
CHANGED
|
@@ -1,57 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.ScheduledJob = void 0;
|
|
37
|
-
const k8s = __importStar(require("@pulumi/kubernetes"));
|
|
38
|
-
const pulumi = __importStar(require("@pulumi/pulumi"));
|
|
39
|
-
const workload_1 = require("./workload");
|
|
1
|
+
import * as k8s from "@pulumi/kubernetes";
|
|
2
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
3
|
+
import { checkRequests, podSpec, serviceAccount, workloadMember } from "./workload.js";
|
|
40
4
|
/**
|
|
41
5
|
* A CronJob with the platform's secure defaults, and a Kubernetes ServiceAccount, both named `name`.
|
|
42
6
|
* A run never overlaps the one before it. Its pods get no IAM; grant roles to `member`.
|
|
43
7
|
*/
|
|
44
|
-
class ScheduledJob extends pulumi.ComponentResource {
|
|
8
|
+
export class ScheduledJob extends pulumi.ComponentResource {
|
|
45
9
|
/** The pods' Workload Identity principal, for IAM grants. */
|
|
46
10
|
member;
|
|
47
11
|
serviceAccountName;
|
|
48
12
|
constructor(name, args, opts) {
|
|
49
13
|
super("cyc-seattle:platform:ScheduledJob", name, {}, opts);
|
|
50
|
-
|
|
14
|
+
checkRequests("ScheduledJob", name, args.requests);
|
|
51
15
|
const platform = pulumi.output(args.platform);
|
|
52
16
|
const labels = { "app.kubernetes.io/name": name };
|
|
53
17
|
const child = { parent: this, provider: args.provider };
|
|
54
|
-
const account =
|
|
18
|
+
const account = serviceAccount(name, args, child);
|
|
55
19
|
new k8s.batch.v1.CronJob(name, {
|
|
56
20
|
metadata: { name, namespace: platform.namespace, labels },
|
|
57
21
|
spec: {
|
|
@@ -65,7 +29,7 @@ class ScheduledJob extends pulumi.ComponentResource {
|
|
|
65
29
|
backoffLimit: args.backoffLimit ?? 0,
|
|
66
30
|
template: {
|
|
67
31
|
metadata: { labels },
|
|
68
|
-
spec:
|
|
32
|
+
spec: podSpec(name, args, account.metadata.name).apply((spec) => ({
|
|
69
33
|
...spec,
|
|
70
34
|
restartPolicy: "Never",
|
|
71
35
|
})),
|
|
@@ -75,8 +39,7 @@ class ScheduledJob extends pulumi.ComponentResource {
|
|
|
75
39
|
},
|
|
76
40
|
}, child);
|
|
77
41
|
this.serviceAccountName = account.metadata.name;
|
|
78
|
-
this.member =
|
|
42
|
+
this.member = workloadMember(platform, this.serviceAccountName);
|
|
79
43
|
this.registerOutputs({ member: this.member, serviceAccountName: this.serviceAccountName });
|
|
80
44
|
}
|
|
81
45
|
}
|
|
82
|
-
exports.ScheduledJob = ScheduledJob;
|
package/dist/services.js
CHANGED
|
@@ -1,40 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.enableService = enableService;
|
|
37
|
-
const gcp = __importStar(require("@pulumi/gcp"));
|
|
1
|
+
import * as gcp from "@pulumi/gcp";
|
|
38
2
|
const enabled = new Map();
|
|
39
3
|
/**
|
|
40
4
|
* Enables a Google Cloud API, memoized so repeated calls for the same API return the same resource.
|
|
@@ -42,7 +6,7 @@ const enabled = new Map();
|
|
|
42
6
|
* therefore be created only after it is enabled. Enable each API from the file that uses it, rather
|
|
43
7
|
* than maintaining a central list.
|
|
44
8
|
*/
|
|
45
|
-
function enableService(service) {
|
|
9
|
+
export function enableService(service) {
|
|
46
10
|
const existing = enabled.get(service);
|
|
47
11
|
if (existing) {
|
|
48
12
|
return existing;
|
package/dist/web-service.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as k8s from "@pulumi/kubernetes";
|
|
2
2
|
import * as pulumi from "@pulumi/pulumi";
|
|
3
|
-
import { type WorkloadArgs } from "./workload";
|
|
3
|
+
import { type WorkloadArgs } from "./workload.ts";
|
|
4
4
|
type Probe = k8s.types.input.core.v1.Probe;
|
|
5
5
|
export interface WebServiceArgs extends WorkloadArgs {
|
|
6
6
|
/** The public hostname. It must be in the environment's domain. */
|
package/dist/web-service.js
CHANGED
|
@@ -1,45 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.WebService = void 0;
|
|
37
|
-
exports.checkHostname = checkHostname;
|
|
38
|
-
const k8s = __importStar(require("@pulumi/kubernetes"));
|
|
39
|
-
const pulumi = __importStar(require("@pulumi/pulumi"));
|
|
40
|
-
const workload_1 = require("./workload");
|
|
1
|
+
import * as k8s from "@pulumi/kubernetes";
|
|
2
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
3
|
+
import { checkRequests, deployment, workloadMember } from "./workload.js";
|
|
41
4
|
/** Returns `hostname` if it is the environment's domain or a name under it, and throws otherwise. */
|
|
42
|
-
function checkHostname(hostname, domain) {
|
|
5
|
+
export function checkHostname(hostname, domain) {
|
|
43
6
|
const host = hostname.toLowerCase();
|
|
44
7
|
const base = domain.toLowerCase();
|
|
45
8
|
if (host !== base && !host.endsWith(`.${base}`)) {
|
|
@@ -52,7 +15,7 @@ function checkHostname(hostname, domain) {
|
|
|
52
15
|
* Kubernetes ServiceAccount, plus an HTTPRoute and a HealthCheckPolicy. Its pods get no IAM; grant
|
|
53
16
|
* roles to `member`.
|
|
54
17
|
*/
|
|
55
|
-
class WebService extends pulumi.ComponentResource {
|
|
18
|
+
export class WebService extends pulumi.ComponentResource {
|
|
56
19
|
/** The pods' Workload Identity principal, for IAM grants. */
|
|
57
20
|
member;
|
|
58
21
|
serviceAccountName;
|
|
@@ -61,7 +24,7 @@ class WebService extends pulumi.ComponentResource {
|
|
|
61
24
|
url;
|
|
62
25
|
constructor(name, args, opts) {
|
|
63
26
|
super("cyc-seattle:platform:WebService", name, {}, opts);
|
|
64
|
-
|
|
27
|
+
checkRequests("WebService", name, args.requests);
|
|
65
28
|
if (!args.readinessProbe?.httpGet) {
|
|
66
29
|
throw new Error(`WebService "${name}" needs an HTTP readiness probe.`);
|
|
67
30
|
}
|
|
@@ -70,7 +33,7 @@ class WebService extends pulumi.ComponentResource {
|
|
|
70
33
|
const hostname = platform.domain.apply((domain) => checkHostname(args.hostname, domain));
|
|
71
34
|
const metadata = { name, namespace: platform.namespace, labels: { "app.kubernetes.io/name": name } };
|
|
72
35
|
const child = { parent: this, provider: args.provider };
|
|
73
|
-
const { serviceAccount, service } =
|
|
36
|
+
const { serviceAccount, service } = deployment(this, name, args, args.port);
|
|
74
37
|
new k8s.apiextensions.CustomResource(name, {
|
|
75
38
|
apiVersion: "gateway.networking.k8s.io/v1",
|
|
76
39
|
kind: "HTTPRoute",
|
|
@@ -100,7 +63,7 @@ class WebService extends pulumi.ComponentResource {
|
|
|
100
63
|
},
|
|
101
64
|
}, child);
|
|
102
65
|
this.serviceAccountName = serviceAccount.metadata.name;
|
|
103
|
-
this.member =
|
|
66
|
+
this.member = workloadMember(platform, this.serviceAccountName);
|
|
104
67
|
this.host = name;
|
|
105
68
|
this.url = pulumi.interpolate `https://${hostname}/`;
|
|
106
69
|
this.registerOutputs({
|
|
@@ -111,4 +74,3 @@ class WebService extends pulumi.ComponentResource {
|
|
|
111
74
|
});
|
|
112
75
|
}
|
|
113
76
|
}
|
|
114
|
-
exports.WebService = WebService;
|
package/dist/workload.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as k8s from "@pulumi/kubernetes";
|
|
2
2
|
import * as pulumi from "@pulumi/pulumi";
|
|
3
|
-
import type { PlatformOutputs } from "./outputs";
|
|
3
|
+
import type { PlatformOutputs } from "./outputs.ts";
|
|
4
4
|
type Probe = k8s.types.input.core.v1.Probe;
|
|
5
5
|
type EnvVar = k8s.types.input.core.v1.EnvVar;
|
|
6
6
|
type EnvFromSource = k8s.types.input.core.v1.EnvFromSource;
|
package/dist/workload.js
CHANGED
|
@@ -1,58 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.Workload = void 0;
|
|
37
|
-
exports.workloadMember = workloadMember;
|
|
38
|
-
exports.checkRequests = checkRequests;
|
|
39
|
-
exports.serviceAccount = serviceAccount;
|
|
40
|
-
exports.podSpec = podSpec;
|
|
41
|
-
exports.deployment = deployment;
|
|
42
|
-
const k8s = __importStar(require("@pulumi/kubernetes"));
|
|
43
|
-
const pulumi = __importStar(require("@pulumi/pulumi"));
|
|
1
|
+
import * as k8s from "@pulumi/kubernetes";
|
|
2
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
44
3
|
/** The pods' Workload Identity principal, for IAM grants. */
|
|
45
|
-
function workloadMember(platform, serviceAccountName) {
|
|
4
|
+
export function workloadMember(platform, serviceAccountName) {
|
|
46
5
|
return pulumi.interpolate `principal://iam.googleapis.com/projects/${platform.projectNumber}/locations/global/workloadIdentityPools/${platform.project}.svc.id.goog/subject/ns/${platform.namespace}/sa/${serviceAccountName}`;
|
|
47
6
|
}
|
|
48
|
-
function checkRequests(kind, name, requests) {
|
|
7
|
+
export function checkRequests(kind, name, requests) {
|
|
49
8
|
// The types already require them, but a JavaScript caller or a cast can skip them.
|
|
50
9
|
if (!requests?.cpu || !requests?.memory) {
|
|
51
10
|
throw new Error(`${kind} "${name}" needs CPU and memory requests.`);
|
|
52
11
|
}
|
|
53
12
|
}
|
|
54
13
|
/** A ServiceAccount named `name` that mounts no token. */
|
|
55
|
-
function serviceAccount(name, args, opts) {
|
|
14
|
+
export function serviceAccount(name, args, opts) {
|
|
56
15
|
const platform = pulumi.output(args.platform);
|
|
57
16
|
return new k8s.core.v1.ServiceAccount(name, {
|
|
58
17
|
metadata: {
|
|
@@ -65,7 +24,7 @@ function serviceAccount(name, args, opts) {
|
|
|
65
24
|
}, opts);
|
|
66
25
|
}
|
|
67
26
|
/** A pod spec with the platform's secure defaults: non-root, read-only, no token, and Spot in dev only. */
|
|
68
|
-
function podSpec(name, args, serviceAccountName, container = {}) {
|
|
27
|
+
export function podSpec(name, args, serviceAccountName, container = {}) {
|
|
69
28
|
const volumes = args.volumes ?? [];
|
|
70
29
|
// The namespace is the environment's name.
|
|
71
30
|
return pulumi.output(args.platform).namespace.apply((namespace) => ({
|
|
@@ -118,7 +77,7 @@ function podSpec(name, args, serviceAccountName, container = {}) {
|
|
|
118
77
|
* The Deployment, ServiceAccount, and Service of a `Workload` or a `WebService`, as children of
|
|
119
78
|
* `parent`. `http` is a `WebService`'s port, which its Service exposes as port 80.
|
|
120
79
|
*/
|
|
121
|
-
function deployment(parent, name, args, http) {
|
|
80
|
+
export function deployment(parent, name, args, http) {
|
|
122
81
|
const platform = pulumi.output(args.platform);
|
|
123
82
|
const labels = { "app.kubernetes.io/name": name };
|
|
124
83
|
const metadata = { name, namespace: platform.namespace, labels };
|
|
@@ -185,7 +144,7 @@ function deployment(parent, name, args, http) {
|
|
|
185
144
|
* A long-running process with no route: a Deployment, a Kubernetes ServiceAccount, and, when it has
|
|
186
145
|
* ports, a ClusterIP Service, all named `name`. Its pods get no IAM; grant roles to `member`.
|
|
187
146
|
*/
|
|
188
|
-
class Workload extends pulumi.ComponentResource {
|
|
147
|
+
export class Workload extends pulumi.ComponentResource {
|
|
189
148
|
/** The pods' Workload Identity principal, for IAM grants. */
|
|
190
149
|
member;
|
|
191
150
|
serviceAccountName;
|
|
@@ -201,4 +160,3 @@ class Workload extends pulumi.ComponentResource {
|
|
|
201
160
|
this.registerOutputs({ member: this.member, serviceAccountName: this.serviceAccountName, host: this.host });
|
|
202
161
|
}
|
|
203
162
|
}
|
|
204
|
-
exports.Workload = Workload;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyc-seattle/platform",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Pulumi components for CYC's shared Google Cloud platform: WebService, the platform outputs reader, and the stacks that build the platform",
|
|
5
5
|
"author": "CYC Community Sailing Center",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -16,9 +16,10 @@
|
|
|
16
16
|
"access": "public"
|
|
17
17
|
},
|
|
18
18
|
"engines": {
|
|
19
|
-
"node": ">=22"
|
|
19
|
+
"node": ">=22.18"
|
|
20
20
|
},
|
|
21
21
|
"packageManager": "pnpm@10.34.7",
|
|
22
|
+
"type": "module",
|
|
22
23
|
"prettier": "@cyc-seattle/ts-config/prettier",
|
|
23
24
|
"exports": {
|
|
24
25
|
".": {
|