@microagi/alchemy-gcp 0.2.1 → 0.3.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/CHANGELOG.md +65 -0
- package/README.md +54 -2
- package/lib/Providers.d.ts.map +1 -1
- package/lib/Providers.js +5 -1
- package/lib/Providers.js.map +1 -1
- package/lib/Run/IamMember.d.ts +70 -0
- package/lib/Run/IamMember.d.ts.map +1 -0
- package/lib/Run/IamMember.js +65 -0
- package/lib/Run/IamMember.js.map +1 -0
- package/lib/Run/IamSync.d.ts +80 -0
- package/lib/Run/IamSync.d.ts.map +1 -0
- package/lib/Run/IamSync.js +73 -0
- package/lib/Run/IamSync.js.map +1 -0
- package/lib/Run/Job.d.ts +167 -0
- package/lib/Run/Job.d.ts.map +1 -0
- package/lib/Run/Job.js +199 -0
- package/lib/Run/Job.js.map +1 -0
- package/lib/Run/Operations.d.ts +47 -0
- package/lib/Run/Operations.d.ts.map +1 -0
- package/lib/Run/Operations.js +46 -0
- package/lib/Run/Operations.js.map +1 -0
- package/lib/Run/Service.d.ts +193 -0
- package/lib/Run/Service.d.ts.map +1 -0
- package/lib/Run/Service.js +247 -0
- package/lib/Run/Service.js.map +1 -0
- package/lib/Run/Validation.d.ts +54 -0
- package/lib/Run/Validation.d.ts.map +1 -0
- package/lib/Run/Validation.js +129 -0
- package/lib/Run/Validation.js.map +1 -0
- package/lib/Run/index.d.ts +51 -0
- package/lib/Run/index.d.ts.map +1 -0
- package/lib/Run/index.js +4 -0
- package/lib/Run/index.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/package.json +5 -4
- package/src/Providers.ts +6 -0
- package/src/Run/IamMember.ts +79 -0
- package/src/Run/IamSync.ts +134 -0
- package/src/Run/Job.ts +453 -0
- package/src/Run/Operations.ts +77 -0
- package/src/Run/Service.ts +541 -0
- package/src/Run/Validation.ts +153 -0
- package/src/Run/index.ts +52 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Job.d.ts","sourceRoot":"","sources":["../../src/Run/Job.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,6BAA6B,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAKnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAK7C,OAAO,KAAK,KAAK,GAAG,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAe,KAAK,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAUvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiFG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC;;;OAGG;IACH,WAAW,CAAC,EACR,OAAO,GACP,MAAM,GACN,IAAI,GACJ,cAAc,GACd,WAAW,GACX,YAAY,CAAC;IACjB,wDAAwD;IACxD,mBAAmB,CAAC,EAAE,GAAG,CAAC,mCAAmC,CAAC;IAC9D;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,yEAAyE;IACzE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,EAAE,GAAG,CAAC,iCAAiC,CAAC;CACjD,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,2BAA2B;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,qCAAqC;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,sBAAsB;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,2DAA2D;IAC3D,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,mCAAmC;IACnC,iBAAiB,EAAE,GAAG,CAAC,yBAAyB,GAAG,SAAS,CAAC;IAC7D,iDAAiD;IACjD,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,gEAAgE;IAChE,sBAAsB,EAAE,GAAG,CAAC,kCAAkC,GAAG,SAAS,CAAC;IAC3E,oEAAoE;IACpE,WAAW,EAAE,OAAO,GAAG,SAAS,CAAC;IACjC,mCAAmC;IACnC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,qBAAqB;IACrB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,0BAA0B;IAC1B,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,GAAG,GAAG,QAAQ,CACxB,SAAS,EACT,QAAQ,EACR,aAAa,EACb,qBAAqB,EACrB,GAAG,CAAC,SAAS,CACd,CAAC;AACF,eAAO,MAAM,GAAG,sCAA2B,CAAC;AAgG5C,eAAO,MAAM,WAAW,0NAgKrB,CAAC"}
|
package/lib/Run/Job.js
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import * as run from "@distilled.cloud/gcp/run-v2";
|
|
2
|
+
import { Resource } from "alchemy";
|
|
3
|
+
import { Unowned } from "alchemy/AdoptPolicy";
|
|
4
|
+
import { deepEqual, isResolved, somePropsAreDifferent } from "alchemy/Diff";
|
|
5
|
+
import { createPhysicalName } from "alchemy/PhysicalName";
|
|
6
|
+
import * as Provider from "alchemy/Provider";
|
|
7
|
+
import { diffTags } from "alchemy/Tags";
|
|
8
|
+
import * as Duration from "effect/Duration";
|
|
9
|
+
import * as Effect from "effect/Effect";
|
|
10
|
+
import * as Schedule from "effect/Schedule";
|
|
11
|
+
import { gcpInternalLabels, hasAlchemyLabels } from "../Tags.js";
|
|
12
|
+
import { makeSyncIam } from "./IamSync.js";
|
|
13
|
+
import { makeAwaitOperation } from "./Operations.js";
|
|
14
|
+
import { reshapeBadRequest, validateAnnotations, validateContainers, validateLabels, validateRunName, } from "./Validation.js";
|
|
15
|
+
export const Job = Resource("GCP.Job");
|
|
16
|
+
const fqName = (project, location, name) => `projects/${project}/locations/${location}/jobs/${name}`;
|
|
17
|
+
const toJobBody = (news, desiredLabels) => ({
|
|
18
|
+
labels: desiredLabels,
|
|
19
|
+
...(news.annotations ? { annotations: news.annotations } : {}),
|
|
20
|
+
...(news.launchStage ? { launchStage: news.launchStage } : {}),
|
|
21
|
+
...(news.binaryAuthorization
|
|
22
|
+
? { binaryAuthorization: news.binaryAuthorization }
|
|
23
|
+
: {}),
|
|
24
|
+
...(news.startExecutionToken
|
|
25
|
+
? { startExecutionToken: news.startExecutionToken }
|
|
26
|
+
: {}),
|
|
27
|
+
...(news.runExecutionToken
|
|
28
|
+
? { runExecutionToken: news.runExecutionToken }
|
|
29
|
+
: {}),
|
|
30
|
+
template: news.template,
|
|
31
|
+
});
|
|
32
|
+
const toAttributes = (j, parent) => ({
|
|
33
|
+
name: parent.name,
|
|
34
|
+
uid: j.uid ?? "",
|
|
35
|
+
resourceName: j.name ?? fqName(parent.project, parent.location, parent.name),
|
|
36
|
+
project: parent.project,
|
|
37
|
+
location: parent.location,
|
|
38
|
+
generation: j.generation,
|
|
39
|
+
observedGeneration: j.observedGeneration,
|
|
40
|
+
terminalCondition: j.terminalCondition,
|
|
41
|
+
executionCount: j.executionCount,
|
|
42
|
+
latestCreatedExecution: j.latestCreatedExecution,
|
|
43
|
+
reconciling: j.reconciling,
|
|
44
|
+
etag: j.etag,
|
|
45
|
+
labels: { ...(j.labels ?? {}) },
|
|
46
|
+
createTime: j.createTime,
|
|
47
|
+
updateTime: j.updateTime,
|
|
48
|
+
});
|
|
49
|
+
/**
|
|
50
|
+
* Decide whether anything mutable on the Job changed since the last
|
|
51
|
+
* reconcile. Job's `patch` has no `updateMask` parameter — the server
|
|
52
|
+
* diffs the full body — so we just emit a single "changed / unchanged"
|
|
53
|
+
* verdict and re-send the whole body if it differs.
|
|
54
|
+
*
|
|
55
|
+
* Labels go through `diffTags` (consistent with every other GCP
|
|
56
|
+
* resource here); everything else is a `deepEqual` on the relevant
|
|
57
|
+
* field. The `template` deep-equal is the load-bearing check —
|
|
58
|
+
* Cloud Run injects server-side defaults into `template.template`
|
|
59
|
+
* (e.g. `maxRetries: 3` when omitted), so the observed template may
|
|
60
|
+
* have keys we never sent. Deep-equal on the OBSERVED side ⊆ NEWS
|
|
61
|
+
* side is too strict; we rely on the user re-sending equivalent
|
|
62
|
+
* inputs across reconciles so observed==news after the first patch.
|
|
63
|
+
*/
|
|
64
|
+
const jobMutated = (observed, news, desiredLabels) => {
|
|
65
|
+
const labelDiff = diffTags({ ...(observed.labels ?? {}) }, desiredLabels);
|
|
66
|
+
if (labelDiff.removed.length > 0 || labelDiff.upsert.length > 0)
|
|
67
|
+
return true;
|
|
68
|
+
if (!deepEqual(observed.annotations ?? {}, news.annotations ?? {}))
|
|
69
|
+
return true;
|
|
70
|
+
if (news.launchStage !== undefined && observed.launchStage !== news.launchStage) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
if (news.binaryAuthorization &&
|
|
74
|
+
!deepEqual(observed.binaryAuthorization, news.binaryAuthorization)) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
if (news.startExecutionToken !== undefined &&
|
|
78
|
+
observed.startExecutionToken !== news.startExecutionToken) {
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
if (news.runExecutionToken !== undefined &&
|
|
82
|
+
observed.runExecutionToken !== news.runExecutionToken) {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
if (!deepEqual(observed.template, news.template))
|
|
86
|
+
return true;
|
|
87
|
+
return false;
|
|
88
|
+
};
|
|
89
|
+
export const JobProvider = () => Provider.effect(Job, Effect.gen(function* () {
|
|
90
|
+
const getJob = yield* run.getProjectsLocationsJobs;
|
|
91
|
+
const createJob = yield* run.createProjectsLocationsJobs;
|
|
92
|
+
const patchJob = yield* run.patchProjectsLocationsJobs;
|
|
93
|
+
const deleteJob = yield* run.deleteProjectsLocationsJobs;
|
|
94
|
+
const getOperation = yield* run.getProjectsLocationsOperations;
|
|
95
|
+
const getIamPolicy = yield* run.getIamPolicyProjectsLocationsJobs;
|
|
96
|
+
const setIamPolicy = yield* run.setIamPolicyProjectsLocationsJobs;
|
|
97
|
+
const awaitOperation = makeAwaitOperation(getOperation);
|
|
98
|
+
const syncIam = makeSyncIam({ getIamPolicy, setIamPolicy });
|
|
99
|
+
const observe = (project, location, name) => getJob({ name: fqName(project, location, name) }).pipe(Effect.catchTag("NotFound", () => Effect.succeed(undefined)), Effect.catchTag("Forbidden", () => Effect.succeed(undefined)));
|
|
100
|
+
const syncMutable = Effect.fn(function* (args) {
|
|
101
|
+
if (!jobMutated(args.observed, args.news, args.desiredLabels))
|
|
102
|
+
return;
|
|
103
|
+
const bodyWithEtag = {
|
|
104
|
+
...toJobBody(args.news, args.desiredLabels),
|
|
105
|
+
...(args.observed.etag ? { etag: args.observed.etag } : {}),
|
|
106
|
+
};
|
|
107
|
+
const op = yield* patchJob({
|
|
108
|
+
name: args.name,
|
|
109
|
+
body: bodyWithEtag,
|
|
110
|
+
}).pipe(Effect.catchTag("BadRequest", reshapeBadRequest("Job", "patch")));
|
|
111
|
+
if (op.name)
|
|
112
|
+
yield* awaitOperation(op.name, args.session);
|
|
113
|
+
});
|
|
114
|
+
return {
|
|
115
|
+
stables: ["name", "uid", "resourceName", "project", "location"],
|
|
116
|
+
diff: Effect.fn(function* ({ news, olds = {} }) {
|
|
117
|
+
if (!isResolved(news))
|
|
118
|
+
return undefined;
|
|
119
|
+
if (somePropsAreDifferent(olds, news, [
|
|
120
|
+
"project",
|
|
121
|
+
"location",
|
|
122
|
+
"name",
|
|
123
|
+
])) {
|
|
124
|
+
return { action: "replace" };
|
|
125
|
+
}
|
|
126
|
+
return undefined;
|
|
127
|
+
}),
|
|
128
|
+
reconcile: Effect.fn(function* ({ id, news, session, bindings }) {
|
|
129
|
+
const internalLabels = yield* gcpInternalLabels(id);
|
|
130
|
+
const desiredName = news.name ??
|
|
131
|
+
(yield* createPhysicalName({ id, maxLength: 49 })).toLowerCase();
|
|
132
|
+
yield* validateRunName("Job", desiredName);
|
|
133
|
+
yield* validateLabels(news.labels);
|
|
134
|
+
yield* validateAnnotations(news.annotations);
|
|
135
|
+
// Job container constraint lives one level deeper (inside the
|
|
136
|
+
// ExecutionTemplate's TaskTemplate).
|
|
137
|
+
yield* validateContainers("Job", news.template.template?.containers);
|
|
138
|
+
const parent = `projects/${news.project}/locations/${news.location}`;
|
|
139
|
+
const name = fqName(news.project, news.location, desiredName);
|
|
140
|
+
const desiredLabels = {
|
|
141
|
+
...(news.labels ?? {}),
|
|
142
|
+
...internalLabels,
|
|
143
|
+
};
|
|
144
|
+
let observed = yield* observe(news.project, news.location, desiredName);
|
|
145
|
+
if (!observed) {
|
|
146
|
+
const op = yield* createJob({
|
|
147
|
+
parent,
|
|
148
|
+
jobId: desiredName,
|
|
149
|
+
body: toJobBody(news, desiredLabels),
|
|
150
|
+
}).pipe(Effect.retry({
|
|
151
|
+
while: (e) => e?._tag === "Forbidden" &&
|
|
152
|
+
/enabled this API recently|has not been used/i.test(e.message ?? ""),
|
|
153
|
+
schedule: Schedule.spaced(Duration.seconds(15)).pipe(Schedule.both(Schedule.recurs(20)), Schedule.tapOutput(() => session.note("Waiting for Cloud Run API enablement to propagate…"))),
|
|
154
|
+
}), Effect.catchTag("Conflict", () => Effect.succeed(undefined)), Effect.catchTag("BadRequest", reshapeBadRequest("Job", "create")));
|
|
155
|
+
if (op?.name)
|
|
156
|
+
yield* awaitOperation(op.name, session);
|
|
157
|
+
observed = yield* getJob({ name });
|
|
158
|
+
}
|
|
159
|
+
yield* syncMutable({
|
|
160
|
+
name,
|
|
161
|
+
observed,
|
|
162
|
+
news,
|
|
163
|
+
desiredLabels,
|
|
164
|
+
session,
|
|
165
|
+
});
|
|
166
|
+
yield* syncIam({ resource: name, bindings });
|
|
167
|
+
const final = yield* getJob({ name });
|
|
168
|
+
return toAttributes(final, {
|
|
169
|
+
project: news.project,
|
|
170
|
+
location: news.location,
|
|
171
|
+
name: desiredName,
|
|
172
|
+
});
|
|
173
|
+
}),
|
|
174
|
+
delete: Effect.fn(function* ({ output, session }) {
|
|
175
|
+
const name = fqName(output.project, output.location, output.name);
|
|
176
|
+
yield* deleteJob({
|
|
177
|
+
name,
|
|
178
|
+
...(output.etag ? { etag: output.etag } : {}),
|
|
179
|
+
}).pipe(Effect.flatMap((op) => op.name ? awaitOperation(op.name, session) : Effect.succeed(op)), Effect.catchTag("NotFound", () => Effect.void));
|
|
180
|
+
}),
|
|
181
|
+
read: Effect.fn(function* ({ id, output, olds }) {
|
|
182
|
+
const project = output?.project ?? olds?.project;
|
|
183
|
+
const location = output?.location ?? olds?.location;
|
|
184
|
+
if (!project || !location)
|
|
185
|
+
return undefined;
|
|
186
|
+
const name = output?.name ??
|
|
187
|
+
olds?.name ??
|
|
188
|
+
(yield* createPhysicalName({ id, maxLength: 49 })).toLowerCase();
|
|
189
|
+
const observed = yield* observe(project, location, name);
|
|
190
|
+
if (!observed)
|
|
191
|
+
return undefined;
|
|
192
|
+
const attrs = toAttributes(observed, { project, location, name });
|
|
193
|
+
return (yield* hasAlchemyLabels(id, observed.labels))
|
|
194
|
+
? attrs
|
|
195
|
+
: Unowned(attrs);
|
|
196
|
+
}),
|
|
197
|
+
};
|
|
198
|
+
}));
|
|
199
|
+
//# sourceMappingURL=Job.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Job.js","sourceRoot":"","sources":["../../src/Run/Job.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ConfigError } from "@distilled.cloud/gcp";
|
|
2
|
+
import * as run from "@distilled.cloud/gcp/run-v2";
|
|
3
|
+
import type { ScopedPlanStatusSession } from "alchemy/Cli/Cli";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
/**
|
|
6
|
+
* Resolved callable signature of `run.getProjectsLocationsOperations`.
|
|
7
|
+
*
|
|
8
|
+
* `run.getProjectsLocationsOperations` is itself an
|
|
9
|
+
* `Effect<callable, never, Credentials | HttpClient>`, so `Effect.Success`
|
|
10
|
+
* extracts the callable type — what you get back from
|
|
11
|
+
* `yield* run.getProjectsLocationsOperations`. Using a derived alias
|
|
12
|
+
* keeps the helper aligned with the SDK without us hand-writing the
|
|
13
|
+
* input/output/error union, which would drift if the patch set changes.
|
|
14
|
+
*/
|
|
15
|
+
type GetOperations = Effect.Success<typeof run.getProjectsLocationsOperations>;
|
|
16
|
+
/**
|
|
17
|
+
* Build the Cloud Run long-running-operation polling helper.
|
|
18
|
+
*
|
|
19
|
+
* Cloud Run `Operation`s use the standard `GoogleLongrunningOperation`
|
|
20
|
+
* shape — doneness is `.done === true` (NOT `.status === "DONE"` like
|
|
21
|
+
* the GKE Container API). Verified at
|
|
22
|
+
* `vendor/distilled/packages/gcp/src/services/run-v2.ts:2880–2900`.
|
|
23
|
+
*
|
|
24
|
+
* Operation names returned by run-v2 (`createProjectsLocationsServices`,
|
|
25
|
+
* `patchProjectsLocationsServices`, `deleteProjectsLocationsServices`)
|
|
26
|
+
* are already fully qualified
|
|
27
|
+
* (`projects/{p}/locations/{l}/operations/{id}`), so callers pass them
|
|
28
|
+
* straight through to `getProjectsLocationsOperations` — no `qualifyOp`
|
|
29
|
+
* dance needed (unlike Container, which returns bare ids).
|
|
30
|
+
*
|
|
31
|
+
* Schedule: exponential 1s → 1.5× growth, capped per-poll at 10s via
|
|
32
|
+
* `Schedule.either`, then a hard count cap of 60 retries via
|
|
33
|
+
* `Schedule.both(Schedule.recurs(60))` → ~10 min wall ceiling. Cloud
|
|
34
|
+
* Run create/patch typically completes in seconds to a couple minutes,
|
|
35
|
+
* with the long pole being container image pulls.
|
|
36
|
+
*
|
|
37
|
+
* The helper is a factory — the caller resolves
|
|
38
|
+
* `run.getProjectsLocationsOperations` once at provider construction
|
|
39
|
+
* (see `Container/Operations.ts` for the same idiom) and passes the
|
|
40
|
+
* resulting callable here, so we never re-resolve services on each
|
|
41
|
+
* await.
|
|
42
|
+
*/
|
|
43
|
+
export declare const makeAwaitOperation: (getOperations: GetOperations) => (operationName: string, session: ScopedPlanStatusSession) => Effect.Effect<run.GoogleLongrunningOperation, ConfigError | run.GetProjectsLocationsOperationsError | {
|
|
44
|
+
_tag: "OperationPending";
|
|
45
|
+
}, never>;
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=Operations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Operations.d.ts","sourceRoot":"","sources":["../../src/Run/Operations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,GAAG,MAAM,6BAA6B,CAAC;AACnD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAE/D,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAGxC;;;;;;;;;GASG;AACH,KAAK,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,GAAG,CAAC,8BAA8B,CAAC,CAAC;AAE/E;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,kBAAkB,GAAI,eAAe,aAAa;;SA8B3D,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ConfigError } from "@distilled.cloud/gcp";
|
|
2
|
+
import * as Duration from "effect/Duration";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Schedule from "effect/Schedule";
|
|
5
|
+
/**
|
|
6
|
+
* Build the Cloud Run long-running-operation polling helper.
|
|
7
|
+
*
|
|
8
|
+
* Cloud Run `Operation`s use the standard `GoogleLongrunningOperation`
|
|
9
|
+
* shape — doneness is `.done === true` (NOT `.status === "DONE"` like
|
|
10
|
+
* the GKE Container API). Verified at
|
|
11
|
+
* `vendor/distilled/packages/gcp/src/services/run-v2.ts:2880–2900`.
|
|
12
|
+
*
|
|
13
|
+
* Operation names returned by run-v2 (`createProjectsLocationsServices`,
|
|
14
|
+
* `patchProjectsLocationsServices`, `deleteProjectsLocationsServices`)
|
|
15
|
+
* are already fully qualified
|
|
16
|
+
* (`projects/{p}/locations/{l}/operations/{id}`), so callers pass them
|
|
17
|
+
* straight through to `getProjectsLocationsOperations` — no `qualifyOp`
|
|
18
|
+
* dance needed (unlike Container, which returns bare ids).
|
|
19
|
+
*
|
|
20
|
+
* Schedule: exponential 1s → 1.5× growth, capped per-poll at 10s via
|
|
21
|
+
* `Schedule.either`, then a hard count cap of 60 retries via
|
|
22
|
+
* `Schedule.both(Schedule.recurs(60))` → ~10 min wall ceiling. Cloud
|
|
23
|
+
* Run create/patch typically completes in seconds to a couple minutes,
|
|
24
|
+
* with the long pole being container image pulls.
|
|
25
|
+
*
|
|
26
|
+
* The helper is a factory — the caller resolves
|
|
27
|
+
* `run.getProjectsLocationsOperations` once at provider construction
|
|
28
|
+
* (see `Container/Operations.ts` for the same idiom) and passes the
|
|
29
|
+
* resulting callable here, so we never re-resolve services on each
|
|
30
|
+
* await.
|
|
31
|
+
*/
|
|
32
|
+
export const makeAwaitOperation = (getOperations) => Effect.fn(function* (operationName, session) {
|
|
33
|
+
const op = yield* getOperations({ name: operationName }).pipe(Effect.flatMap((current) => current.done === true
|
|
34
|
+
? Effect.succeed(current)
|
|
35
|
+
: Effect.fail({ _tag: "OperationPending" })), Effect.retry({
|
|
36
|
+
while: (e) => e?._tag === "OperationPending",
|
|
37
|
+
schedule: Schedule.exponential(Duration.seconds(1), 1.5).pipe(Schedule.either(Schedule.spaced(Duration.seconds(10))), Schedule.both(Schedule.recurs(60)), Schedule.tapOutput(() => session.note(`Waiting for Cloud Run operation ${operationName}…`))),
|
|
38
|
+
}));
|
|
39
|
+
if (op.error) {
|
|
40
|
+
return yield* new ConfigError({
|
|
41
|
+
message: `Cloud Run operation ${operationName} failed: ${op.error.message ?? JSON.stringify(op.error)}`,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return op;
|
|
45
|
+
});
|
|
46
|
+
//# sourceMappingURL=Operations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Operations.js","sourceRoot":"","sources":["../../src/Run/Operations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGnD,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAc5C;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,aAA4B,EAAE,EAAE,CACjE,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,EACjB,aAAqB,EACrB,OAAgC;IAEhC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC,IAAI,CAC3D,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CACzB,OAAO,CAAC,IAAI,KAAK,IAAI;QACnB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;QACzB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,kBAA2B,EAAE,CAAC,CACvD,EACD,MAAM,CAAC,KAAK,CAAC;QACX,KAAK,EAAE,CAAC,CAAoB,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,KAAK,kBAAkB;QAC/D,QAAQ,EAAE,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAC3D,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EACtD,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAClC,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,CACtB,OAAO,CAAC,IAAI,CAAC,mCAAmC,aAAa,GAAG,CAAC,CAClE,CACF;KACF,CAAC,CACH,CAAC;IACF,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC;QACb,OAAO,KAAK,CAAC,CAAC,IAAI,WAAW,CAAC;YAC5B,OAAO,EAAE,uBAAuB,aAAa,YAC3C,EAAE,CAAC,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,CAC7C,EAAE;SACH,CAAC,CAAC;IACL,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import * as run from "@distilled.cloud/gcp/run-v2";
|
|
2
|
+
import { Resource } from "alchemy";
|
|
3
|
+
import * as Provider from "alchemy/Provider";
|
|
4
|
+
import type * as GCP from "../Providers.ts";
|
|
5
|
+
import { type RunIamBindingContract } from "./IamSync.ts";
|
|
6
|
+
/**
|
|
7
|
+
* A Cloud Run v2 Service — a managed serverless HTTP endpoint. Cloud
|
|
8
|
+
* Run pulls a container image, scales it from zero up to the
|
|
9
|
+
* configured maximum based on request rate, and fronts it with a
|
|
10
|
+
* Google-managed URL (`https://{service}-{hash}-{region}.run.app`).
|
|
11
|
+
* Per-Service IAM controls who can invoke it.
|
|
12
|
+
*
|
|
13
|
+
* **Resource model.** A Service holds a `template` (the desired
|
|
14
|
+
* `RevisionTemplate`) plus traffic routing. Every change to `template`
|
|
15
|
+
* server-side spawns a new immutable `Revision`; `traffic` (this resource)
|
|
16
|
+
* picks which Revisions receive request percentages. Revisions and
|
|
17
|
+
* Executions are side-effects and are NOT modeled by this resource —
|
|
18
|
+
* inspect them via `getProjectsLocationsServicesRevisions` if needed.
|
|
19
|
+
*
|
|
20
|
+
* **Lifecycle.** observe → ensure (create, retrying on the well-known
|
|
21
|
+
* "API not yet enabled" 403) → sync (patch with updateMask of changed
|
|
22
|
+
* top-level fields) → sync IAM bindings → return.
|
|
23
|
+
*
|
|
24
|
+
* **Replace triggers.** Only identity fields (project, location, name)
|
|
25
|
+
* force replacement. Everything else — image, env, scaling, traffic,
|
|
26
|
+
* ingress, IAM — is in-place via `patch`. New revisions are auto-created
|
|
27
|
+
* by Cloud Run on any `template.*` change.
|
|
28
|
+
*
|
|
29
|
+
* **Optimistic concurrency.** Patch and delete pass through the
|
|
30
|
+
* observed `etag` so concurrent edits (e.g. from `gcloud run services
|
|
31
|
+
* update`) surface as `Conflict` instead of silently overwriting.
|
|
32
|
+
*
|
|
33
|
+
* **Adoption.** Label-gated: a Service whose `labels` lack our
|
|
34
|
+
* `alchemy_*` keys is wrapped in `Unowned(attrs)` from `read`, forcing
|
|
35
|
+
* `--adopt` before takeover.
|
|
36
|
+
*
|
|
37
|
+
* **IAM.** Use {@link import("./IamMember.ts").serviceIamMember} to
|
|
38
|
+
* bind `(role, member)` grants — the provider unions all bindings and
|
|
39
|
+
* applies them via a single `setIamPolicy` round-trip, preserving
|
|
40
|
+
* foreign roles + members.
|
|
41
|
+
*
|
|
42
|
+
* @section Creating a Cloud Run Service
|
|
43
|
+
* @example Minimal "hello" service, public via IAM
|
|
44
|
+
* ```typescript
|
|
45
|
+
* const helloApi = yield* GCP.Service("HelloApi", {
|
|
46
|
+
* project: project.projectId,
|
|
47
|
+
* location: "europe-west4",
|
|
48
|
+
* template: {
|
|
49
|
+
* containers: [{ image: "gcr.io/cloudrun/hello" }],
|
|
50
|
+
* },
|
|
51
|
+
* });
|
|
52
|
+
* yield* GCP.serviceIamMember(helloApi, "PublicInvoker", {
|
|
53
|
+
* role: "roles/run.invoker",
|
|
54
|
+
* member: "allUsers",
|
|
55
|
+
* });
|
|
56
|
+
* // helloApi.uri → https://hello-api-XXXXX-ew.a.run.app
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @example Internal-only service with explicit service account and scaling
|
|
60
|
+
* ```typescript
|
|
61
|
+
* const internal = yield* GCP.Service("Internal", {
|
|
62
|
+
* project: project.projectId,
|
|
63
|
+
* location: "europe-west4",
|
|
64
|
+
* ingress: "INGRESS_TRAFFIC_INTERNAL_ONLY",
|
|
65
|
+
* scaling: { minInstanceCount: 1, maxInstanceCount: 10 },
|
|
66
|
+
* template: {
|
|
67
|
+
* serviceAccount: sa.email,
|
|
68
|
+
* containers: [{
|
|
69
|
+
* image: "europe-west4-docker.pkg.dev/proj/repo/app:latest",
|
|
70
|
+
* resources: { limits: { cpu: "1000m", memory: "512Mi" } },
|
|
71
|
+
* }],
|
|
72
|
+
* },
|
|
73
|
+
* });
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export type ServiceProps = {
|
|
77
|
+
/** GCP project ID hosting the Service. Immutable — replace if changed. */
|
|
78
|
+
project: string;
|
|
79
|
+
/**
|
|
80
|
+
* Cloud Run region (e.g. `europe-west4`). Cloud Run is a regional
|
|
81
|
+
* product — there are no zonal Services. Immutable — replace if changed.
|
|
82
|
+
*/
|
|
83
|
+
location: string;
|
|
84
|
+
/**
|
|
85
|
+
* Service name. Defaults to `createPhysicalName({ id, lowercase: true,
|
|
86
|
+
* maxLength: 49 })`. Lowercase letters/digits/hyphens; must begin
|
|
87
|
+
* with a letter and not end with a hyphen; **fewer than 50 characters**.
|
|
88
|
+
* Immutable — replace if changed.
|
|
89
|
+
*/
|
|
90
|
+
name?: string;
|
|
91
|
+
/**
|
|
92
|
+
* User-visible description (≤512 chars). Mutable via `patch`.
|
|
93
|
+
*/
|
|
94
|
+
description?: string;
|
|
95
|
+
/**
|
|
96
|
+
* Resource labels. Alchemy internal labels (`alchemy_app`,
|
|
97
|
+
* `alchemy_stage`, `alchemy_id`) are merged on top automatically.
|
|
98
|
+
* Cloud Run rejects labels in `run.googleapis.com`,
|
|
99
|
+
* `cloud.googleapis.com`, `serving.knative.dev`, or
|
|
100
|
+
* `autoscaling.knative.dev` namespaces. Mutable via `patch`.
|
|
101
|
+
*/
|
|
102
|
+
labels?: Record<string, string>;
|
|
103
|
+
/**
|
|
104
|
+
* Free-form annotations for external tools. Cloud Run rejects the
|
|
105
|
+
* same reserved namespaces as `labels`. Mutable via `patch`.
|
|
106
|
+
*/
|
|
107
|
+
annotations?: Record<string, string>;
|
|
108
|
+
/**
|
|
109
|
+
* Launch stage. `BETA` (or higher) is required to use preview
|
|
110
|
+
* fields like GPU `nodeSelector` and Direct VPC `networkInterfaces`;
|
|
111
|
+
* leaving this unset defaults to `GA`, which silently rejects
|
|
112
|
+
* preview fields in the body. Mutable via `patch`.
|
|
113
|
+
*/
|
|
114
|
+
launchStage?: "ALPHA" | "BETA" | "GA" | "EARLY_ACCESS" | "PRELAUNCH" | "DEPRECATED";
|
|
115
|
+
/** Ingress traffic policy. Mutable via `patch`. */
|
|
116
|
+
ingress?: "INGRESS_TRAFFIC_ALL" | "INGRESS_TRAFFIC_INTERNAL_ONLY" | "INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER" | "INGRESS_TRAFFIC_NONE";
|
|
117
|
+
/**
|
|
118
|
+
* Disable the IAM permission check for invokers. When `true`, the
|
|
119
|
+
* Service is publicly reachable regardless of IAM policy — a
|
|
120
|
+
* deliberate footgun, surface it consciously. Prefer
|
|
121
|
+
* `serviceIamMember(svc, "Public", { role: "roles/run.invoker", member: "allUsers" })`
|
|
122
|
+
* for declarative public access. Mutable via `patch`.
|
|
123
|
+
*/
|
|
124
|
+
invokerIamDisabled?: boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Disable public resolution of the default `*.run.app` URI. When
|
|
127
|
+
* `true`, the service is reachable only via custom domains / load
|
|
128
|
+
* balancers. Mutable via `patch`.
|
|
129
|
+
*/
|
|
130
|
+
defaultUriDisabled?: boolean;
|
|
131
|
+
/** Service-level scaling. Mutable via `patch`. */
|
|
132
|
+
scaling?: run.GoogleCloudRunV2ServiceScaling;
|
|
133
|
+
/**
|
|
134
|
+
* Traffic routing across Revisions. Defaults server-side to 100% to
|
|
135
|
+
* the latest `Ready` revision. Mutable via `patch`.
|
|
136
|
+
*/
|
|
137
|
+
traffic?: ReadonlyArray<run.GoogleCloudRunV2TrafficTarget>;
|
|
138
|
+
/**
|
|
139
|
+
* Audiences encoded into the auth token, for cross-service auth.
|
|
140
|
+
* Mutable via `patch`.
|
|
141
|
+
*/
|
|
142
|
+
customAudiences?: ReadonlyArray<string>;
|
|
143
|
+
/**
|
|
144
|
+
* Binary Authorization policy. Mutable via `patch`.
|
|
145
|
+
*/
|
|
146
|
+
binaryAuthorization?: run.GoogleCloudRunV2BinaryAuthorization;
|
|
147
|
+
/**
|
|
148
|
+
* The Revision template — describes the desired Pod-equivalent.
|
|
149
|
+
* **Required at create.** Mutable via `patch`; any change spawns a
|
|
150
|
+
* new server-managed Revision.
|
|
151
|
+
*/
|
|
152
|
+
template: run.GoogleCloudRunV2RevisionTemplate;
|
|
153
|
+
};
|
|
154
|
+
export type ServiceAttributes = {
|
|
155
|
+
/** Service name (bare, without the `projects/.../services/` prefix). */
|
|
156
|
+
name: string;
|
|
157
|
+
/** Server-assigned UID — stable across rename-less mutations. */
|
|
158
|
+
uid: string;
|
|
159
|
+
/** Fully-qualified resource name `projects/{p}/locations/{l}/services/{n}`. */
|
|
160
|
+
resourceName: string;
|
|
161
|
+
/** GCP project ID, threaded through from props. */
|
|
162
|
+
project: string;
|
|
163
|
+
/** Region, threaded through from props. */
|
|
164
|
+
location: string;
|
|
165
|
+
/** Primary serving URI (`https://…run.app`). */
|
|
166
|
+
uri: string;
|
|
167
|
+
/** All URIs serving traffic (default + any tagged ones). */
|
|
168
|
+
urls: ReadonlyArray<string>;
|
|
169
|
+
/** Monotonically increasing generation, bumped on every patch. */
|
|
170
|
+
generation: string | undefined;
|
|
171
|
+
/** The generation currently serving traffic. */
|
|
172
|
+
observedGeneration: string | undefined;
|
|
173
|
+
/** Name of the latest Ready revision. */
|
|
174
|
+
latestReadyRevision: string | undefined;
|
|
175
|
+
/** Name of the latest created revision. */
|
|
176
|
+
latestCreatedRevision: string | undefined;
|
|
177
|
+
/** Overall readiness condition. */
|
|
178
|
+
terminalCondition: run.GoogleCloudRunV2Condition | undefined;
|
|
179
|
+
/** Per-traffic-target serving status. */
|
|
180
|
+
trafficStatuses: ReadonlyArray<run.GoogleCloudRunV2TrafficTargetStatus>;
|
|
181
|
+
/** Optimistic-concurrency etag. */
|
|
182
|
+
etag: string | undefined;
|
|
183
|
+
/** Labels currently set, including internals. */
|
|
184
|
+
labels: Record<string, string>;
|
|
185
|
+
/** Creation time. */
|
|
186
|
+
createTime: string | undefined;
|
|
187
|
+
/** Last-modified time. */
|
|
188
|
+
updateTime: string | undefined;
|
|
189
|
+
};
|
|
190
|
+
export type Service = Resource<"GCP.Service", ServiceProps, ServiceAttributes, RunIamBindingContract, GCP.Providers>;
|
|
191
|
+
export declare const Service: import("alchemy").ResourceClass<Service>;
|
|
192
|
+
export declare const ServiceProvider: () => import("effect/Layer").Layer<Provider.Provider<Service>, never, import("effect/unstable/http/HttpClient").HttpClient | import("alchemy").Stage | import("alchemy").Stack | import("@distilled.cloud/gcp").Credentials>;
|
|
193
|
+
//# sourceMappingURL=Service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Service.d.ts","sourceRoot":"","sources":["../../src/Run/Service.ts"],"names":[],"mappings":"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"}
|