@microagi/alchemy-gcp 0.5.1 → 0.6.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/lib/Auth/Credentials.d.ts +10 -4
- package/lib/Auth/Credentials.d.ts.map +1 -1
- package/lib/Auth/Credentials.js +13 -4
- package/lib/Auth/Credentials.js.map +1 -1
- package/lib/Compute/Address.d.ts +97 -0
- package/lib/Compute/Address.d.ts.map +1 -0
- package/lib/Compute/Address.js +143 -0
- package/lib/Compute/Address.js.map +1 -0
- package/lib/Compute/Firewall.d.ts +108 -0
- package/lib/Compute/Firewall.d.ts.map +1 -0
- package/lib/Compute/Firewall.js +163 -0
- package/lib/Compute/Firewall.js.map +1 -0
- package/lib/Compute/ForwardingRule.d.ts +106 -0
- package/lib/Compute/ForwardingRule.d.ts.map +1 -0
- package/lib/Compute/ForwardingRule.js +152 -0
- package/lib/Compute/ForwardingRule.js.map +1 -0
- package/lib/Compute/index.d.ts +3 -0
- package/lib/Compute/index.d.ts.map +1 -1
- package/lib/Compute/index.js +3 -0
- package/lib/Compute/index.js.map +1 -1
- package/lib/Container/Cluster.d.ts +20 -0
- package/lib/Container/Cluster.d.ts.map +1 -1
- package/lib/Container/Cluster.js +5 -2
- package/lib/Container/Cluster.js.map +1 -1
- package/lib/Container/NodePool.d.ts +26 -1
- package/lib/Container/NodePool.d.ts.map +1 -1
- package/lib/Container/NodePool.js +45 -8
- package/lib/Container/NodePool.js.map +1 -1
- package/lib/Kubernetes/Secret.d.ts +89 -0
- package/lib/Kubernetes/Secret.d.ts.map +1 -0
- package/lib/Kubernetes/Secret.js +139 -0
- package/lib/Kubernetes/Secret.js.map +1 -0
- package/lib/Kubernetes/client.d.ts +58 -0
- package/lib/Kubernetes/client.d.ts.map +1 -0
- package/lib/Kubernetes/client.js +131 -0
- package/lib/Kubernetes/client.js.map +1 -0
- package/lib/Kubernetes/index.d.ts +2 -0
- package/lib/Kubernetes/index.d.ts.map +1 -0
- package/lib/Kubernetes/index.js +2 -0
- package/lib/Kubernetes/index.js.map +1 -0
- package/lib/ManagedLustre/Instance.d.ts.map +1 -1
- package/lib/ManagedLustre/Instance.js +25 -5
- package/lib/ManagedLustre/Instance.js.map +1 -1
- package/lib/Providers.d.ts +1 -1
- package/lib/Providers.d.ts.map +1 -1
- package/lib/Providers.js +9 -1
- package/lib/Providers.js.map +1 -1
- package/lib/Sqladmin/Instance.d.ts.map +1 -1
- package/lib/Sqladmin/Instance.js +28 -6
- package/lib/Sqladmin/Instance.js.map +1 -1
- 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 +1 -1
- package/src/Auth/Credentials.ts +15 -5
- package/src/Compute/Address.ts +288 -0
- package/src/Compute/Firewall.ts +330 -0
- package/src/Compute/ForwardingRule.ts +301 -0
- package/src/Compute/index.ts +3 -0
- package/src/Container/Cluster.ts +25 -2
- package/src/Container/NodePool.ts +87 -13
- package/src/Kubernetes/Secret.ts +274 -0
- package/src/Kubernetes/client.ts +219 -0
- package/src/Kubernetes/index.ts +1 -0
- package/src/ManagedLustre/Instance.ts +35 -6
- package/src/Providers.ts +18 -0
- package/src/Sqladmin/Instance.ts +36 -7
- package/src/index.ts +1 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Credentials } from "@distilled.cloud/gcp";
|
|
2
|
+
import { AlchemyProfile } from "alchemy/Auth/Profile";
|
|
3
3
|
import * as Config from "effect/Config";
|
|
4
4
|
import * as Layer from "effect/Layer";
|
|
5
5
|
export { Credentials } from "@distilled.cloud/gcp";
|
|
@@ -12,8 +12,14 @@ export { Credentials } from "@distilled.cloud/gcp";
|
|
|
12
12
|
*
|
|
13
13
|
* Prefer {@link fromAuthProvider} when the stack runs through
|
|
14
14
|
* `alchemy login` / `ALCHEMY_PROFILE`.
|
|
15
|
+
*
|
|
16
|
+
* The `Credentials` service is lazy (its value is an `Effect<Config>`
|
|
17
|
+
* re-evaluated per SDK call), so minting happens at request time —
|
|
18
|
+
* `google-auth-library` caches and refreshes underneath. Failures
|
|
19
|
+
* become defects: the service channel carries no typed error, matching
|
|
20
|
+
* distilled's own `CredentialsFromEnv`.
|
|
15
21
|
*/
|
|
16
|
-
export declare const fromADC: (project?: string) => Layer.Layer<Credentials,
|
|
22
|
+
export declare const fromADC: (project?: string) => Layer.Layer<Credentials, never, never>;
|
|
17
23
|
/**
|
|
18
24
|
* Build a `Credentials` Layer that resolves GCP credentials via the
|
|
19
25
|
* Alchemy AuthProvider registry, using the active profile (from
|
|
@@ -25,5 +31,5 @@ export declare const fromADC: (project?: string) => Layer.Layer<Credentials, Con
|
|
|
25
31
|
* ultimately call `mintToken`, which is just a thin wrapper over
|
|
26
32
|
* `google-auth-library`.
|
|
27
33
|
*/
|
|
28
|
-
export declare const fromAuthProvider: () => Layer.Layer<Credentials,
|
|
34
|
+
export declare const fromAuthProvider: () => Layer.Layer<Credentials, Config.ConfigError | import("alchemy/Auth/AuthProvider").AuthError, import("alchemy").AuthProviders | AlchemyProfile>;
|
|
29
35
|
//# sourceMappingURL=Credentials.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Credentials.d.ts","sourceRoot":"","sources":["../../src/Auth/Credentials.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"Credentials.d.ts","sourceRoot":"","sources":["../../src/Auth/Credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEhE,OAAO,EAAmB,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAQtC,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AASnD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,OAAO,GAAI,UAAU,MAAM,2CAIrC,CAAC;AAEJ;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,sJAwB1B,CAAC"}
|
package/lib/Auth/Credentials.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ConfigError, Credentials } from "@distilled.cloud/gcp";
|
|
2
2
|
import { getAuthProvider } from "alchemy/Auth/AuthProvider";
|
|
3
|
-
import { ALCHEMY_PROFILE,
|
|
3
|
+
import { ALCHEMY_PROFILE, AlchemyProfile } from "alchemy/Auth/Profile";
|
|
4
4
|
import * as Config from "effect/Config";
|
|
5
5
|
import * as Effect from "effect/Effect";
|
|
6
6
|
import * as Layer from "effect/Layer";
|
|
@@ -18,8 +18,14 @@ const toConfigError = (e) => new ConfigError({
|
|
|
18
18
|
*
|
|
19
19
|
* Prefer {@link fromAuthProvider} when the stack runs through
|
|
20
20
|
* `alchemy login` / `ALCHEMY_PROFILE`.
|
|
21
|
+
*
|
|
22
|
+
* The `Credentials` service is lazy (its value is an `Effect<Config>`
|
|
23
|
+
* re-evaluated per SDK call), so minting happens at request time —
|
|
24
|
+
* `google-auth-library` caches and refreshes underneath. Failures
|
|
25
|
+
* become defects: the service channel carries no typed error, matching
|
|
26
|
+
* distilled's own `CredentialsFromEnv`.
|
|
21
27
|
*/
|
|
22
|
-
export const fromADC = (project) => Layer.
|
|
28
|
+
export const fromADC = (project) => Layer.succeed(Credentials, mintToken({ project }).pipe(Effect.mapError(toConfigError), Effect.orDie));
|
|
23
29
|
/**
|
|
24
30
|
* Build a `Credentials` Layer that resolves GCP credentials via the
|
|
25
31
|
* Alchemy AuthProvider registry, using the active profile (from
|
|
@@ -32,11 +38,14 @@ export const fromADC = (project) => Layer.effect(Credentials, mintToken({ projec
|
|
|
32
38
|
* `google-auth-library`.
|
|
33
39
|
*/
|
|
34
40
|
export const fromAuthProvider = () => Layer.effect(Credentials, Effect.gen(function* () {
|
|
35
|
-
const profile = yield*
|
|
41
|
+
const profile = yield* AlchemyProfile;
|
|
36
42
|
const auth = yield* getAuthProvider(GCP_AUTH_PROVIDER_NAME);
|
|
37
43
|
const profileName = yield* ALCHEMY_PROFILE;
|
|
38
44
|
const ci = yield* Config.boolean("CI").pipe(Config.withDefault(false));
|
|
39
45
|
const ctx = yield* Effect.context();
|
|
40
|
-
|
|
46
|
+
// The service value is itself an Effect (lazy credentials):
|
|
47
|
+
// profile/provider wiring resolves once at layer build, while
|
|
48
|
+
// loadOrConfigure + token read run per SDK call.
|
|
49
|
+
return profile.loadOrConfigure(auth, profileName, { ci }).pipe(Effect.flatMap((cfg) => auth.read(profileName, cfg)), Effect.map(({ accessToken, project }) => ({ accessToken, project })), Effect.mapError(toConfigError), Effect.provide(ctx), Effect.orDie);
|
|
41
50
|
}));
|
|
42
51
|
//# sourceMappingURL=Credentials.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Credentials.js","sourceRoot":"","sources":["../../src/Auth/Credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"Credentials.js","sourceRoot":"","sources":["../../src/Auth/Credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EACL,sBAAsB,EAGtB,SAAS,GACV,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,MAAM,aAAa,GAAG,CAAC,CAAiC,EAAE,EAAE,CAC1D,IAAI,WAAW,CAAC;IACd,OAAO,EAAE,sCACN,CAA0B,EAAE,OAAO,IAAI,MAAM,CAAC,CAAC,CAClD,EAAE;CACH,CAAC,CAAC;AAEL;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,OAAgB,EAAE,EAAE,CAC1C,KAAK,CAAC,OAAO,CACX,WAAW,EACX,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAC1E,CAAC;AAEJ;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,EAAE,CACnC,KAAK,CAAC,MAAM,CACV,WAAW,EACX,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,cAAc,CAAC;IACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,eAAe,CAGjC,sBAAsB,CAAC,CAAC;IAC1B,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC;IAC3C,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;IACvE,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,EAAS,CAAC;IAE3C,4DAA4D;IAC5D,8DAA8D;IAC9D,iDAAiD;IACjD,OAAO,OAAO,CAAC,eAAe,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAC5D,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,GAAoB,CAAC,CAAC,EACrE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC,EACpE,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,EAC9B,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EACnB,MAAM,CAAC,KAAK,CACb,CAAC;AACJ,CAAC,CAAC,CACH,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { Resource } from "alchemy";
|
|
2
|
+
import * as Provider from "alchemy/Provider";
|
|
3
|
+
import type * as GCP from "../Providers.ts";
|
|
4
|
+
/**
|
|
5
|
+
* A regional compute Address. The intended use here is a **Private
|
|
6
|
+
* Service Connect consumer endpoint IP** — a single internal address
|
|
7
|
+
* reserved in a subnet (`addressType=INTERNAL`, `purpose=GCE_ENDPOINT`)
|
|
8
|
+
* that a `ForwardingRule` then binds to a producer service attachment
|
|
9
|
+
* (e.g. a Cloud SQL instance in another VPC).
|
|
10
|
+
*
|
|
11
|
+
* For global PSA *ranges* (`purpose=VPC_PEERING`) use
|
|
12
|
+
* {@link GlobalAddress} — that is a different API surface
|
|
13
|
+
* (`globalAddresses` vs regional `addresses`).
|
|
14
|
+
*
|
|
15
|
+
* Adoption uses the labels field (Address carries `labels` +
|
|
16
|
+
* `labelFingerprint`).
|
|
17
|
+
*
|
|
18
|
+
* @section Reserving a PSC endpoint IP
|
|
19
|
+
* @example Internal address inside a subnet for a PSC forwarding rule
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const endpointIp = yield* GCP.Address("DbPscAddress", {
|
|
22
|
+
* project: hostProject.projectId,
|
|
23
|
+
* region: "europe-west1",
|
|
24
|
+
* subnetwork: pscSubnet.selfLink,
|
|
25
|
+
* address: "10.0.16.5",
|
|
26
|
+
* });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export type AddressProps = {
|
|
30
|
+
/** GCP project ID hosting the address. Immutable — replace if changed. */
|
|
31
|
+
project: string;
|
|
32
|
+
/** GCP region. Addresses are regional — a different region requires replace. */
|
|
33
|
+
region: string;
|
|
34
|
+
/**
|
|
35
|
+
* Address name. Defaults to `createPhysicalName({ id, lowercase: true,
|
|
36
|
+
* maxLength: 63 })`. Immutable — replace if changed.
|
|
37
|
+
*/
|
|
38
|
+
name?: string;
|
|
39
|
+
/** Description (free-form). Set on create; immutable. */
|
|
40
|
+
description?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Internal vs external. Defaults to `INTERNAL` (the only value that
|
|
43
|
+
* makes sense for a PSC endpoint IP). Immutable — replace.
|
|
44
|
+
*/
|
|
45
|
+
addressType?: "INTERNAL" | "EXTERNAL";
|
|
46
|
+
/**
|
|
47
|
+
* Address purpose. For a PSC endpoint IP use `GCE_ENDPOINT` (the
|
|
48
|
+
* default GCP assigns to plain internal addresses). Immutable — replace.
|
|
49
|
+
*/
|
|
50
|
+
purpose?: "GCE_ENDPOINT" | "SHARED_LOADBALANCER_VIP" | "DNS_RESOLVER";
|
|
51
|
+
/**
|
|
52
|
+
* URL of the subnetwork the address is allocated from. Pass
|
|
53
|
+
* `subnet.selfLink` from a `GCP.Subnetwork` to make alchemy sequence
|
|
54
|
+
* the address after the subnet. Required for INTERNAL addresses.
|
|
55
|
+
* Immutable — replace.
|
|
56
|
+
*/
|
|
57
|
+
subnetwork: string;
|
|
58
|
+
/**
|
|
59
|
+
* Explicit IP to reserve inside the subnet's range. If omitted, GCP
|
|
60
|
+
* picks one. Immutable — replace.
|
|
61
|
+
*/
|
|
62
|
+
address?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Resource labels. Alchemy internal labels (`alchemy_app`,
|
|
65
|
+
* `alchemy_stage`, `alchemy_id`) are merged on top automatically and
|
|
66
|
+
* are reserved. Mutable via `setLabels`.
|
|
67
|
+
*/
|
|
68
|
+
labels?: Record<string, string>;
|
|
69
|
+
};
|
|
70
|
+
export type AddressAttributes = {
|
|
71
|
+
/** Address name. */
|
|
72
|
+
name: string;
|
|
73
|
+
/** GCP project ID, threaded through from props for delete/read. */
|
|
74
|
+
project: string;
|
|
75
|
+
/** GCP region, threaded through from props for delete/read. */
|
|
76
|
+
region: string;
|
|
77
|
+
/** Server-defined URL. */
|
|
78
|
+
selfLink: string;
|
|
79
|
+
/** Server-assigned numeric id. */
|
|
80
|
+
id: string;
|
|
81
|
+
/** The reserved IP. */
|
|
82
|
+
address: string;
|
|
83
|
+
/** Address type. */
|
|
84
|
+
addressType: string | undefined;
|
|
85
|
+
/** Purpose. */
|
|
86
|
+
purpose: string | undefined;
|
|
87
|
+
/** Subnetwork URL. */
|
|
88
|
+
subnetwork: string | undefined;
|
|
89
|
+
/** Status: `RESERVING`, `RESERVED`, `IN_USE`. */
|
|
90
|
+
status: string | undefined;
|
|
91
|
+
/** Labels currently set, including the alchemy internals. */
|
|
92
|
+
labels: Record<string, string>;
|
|
93
|
+
};
|
|
94
|
+
export type Address = Resource<"GCP.Address", AddressProps, AddressAttributes, never, GCP.Providers>;
|
|
95
|
+
export declare const Address: import("alchemy").ResourceClass<Address>;
|
|
96
|
+
export declare const AddressProvider: () => import("effect/Layer").Layer<Provider.Provider<Address>, never, import("alchemy").Stack | import("alchemy").Stage | import("@distilled.cloud/gcp").Credentials | import("effect/unstable/http/HttpClient").HttpClient>;
|
|
97
|
+
//# sourceMappingURL=Address.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Address.d.ts","sourceRoot":"","sources":["../../src/Compute/Address.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAKnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAG7C,OAAO,KAAK,KAAK,GAAG,MAAM,iBAAiB,CAAC;AAG5C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,WAAW,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IACtC;;;OAGG;IACH,OAAO,CAAC,EAAE,cAAc,GAAG,yBAAyB,GAAG,cAAc,CAAC;IACtE;;;;;OAKG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB;IACpB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,eAAe;IACf,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,sBAAsB;IACtB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,iDAAiD;IACjD,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,QAAQ,CAC5B,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,KAAK,EACL,GAAG,CAAC,SAAS,CACd,CAAC;AACF,eAAO,MAAM,OAAO,0CAAmC,CAAC;AAmBxD,eAAO,MAAM,eAAe,8NA6JzB,CAAC"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import * as compute from "@distilled.cloud/gcp/compute-v1";
|
|
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 * as Effect from "effect/Effect";
|
|
8
|
+
import { gcpInternalLabels, hasAlchemyLabels } from "../Tags.js";
|
|
9
|
+
import { makeAwaitRegionOperation } from "./Operations.js";
|
|
10
|
+
export const Address = Resource("GCP.Address");
|
|
11
|
+
const toAddressAttributes = (a, parent) => ({
|
|
12
|
+
name: a.name ?? "",
|
|
13
|
+
project: parent.project,
|
|
14
|
+
region: parent.region,
|
|
15
|
+
selfLink: a.selfLink ?? "",
|
|
16
|
+
id: a.id ?? "",
|
|
17
|
+
address: a.address ?? "",
|
|
18
|
+
addressType: a.addressType,
|
|
19
|
+
purpose: a.purpose,
|
|
20
|
+
subnetwork: a.subnetwork,
|
|
21
|
+
status: a.status,
|
|
22
|
+
labels: { ...(a.labels ?? {}) },
|
|
23
|
+
});
|
|
24
|
+
export const AddressProvider = () => Provider.effect(Address, Effect.gen(function* () {
|
|
25
|
+
const getAddresses = yield* compute.getAddresses;
|
|
26
|
+
const insertAddresses = yield* compute.insertAddresses;
|
|
27
|
+
const deleteAddresses = yield* compute.deleteAddresses;
|
|
28
|
+
const setLabelsAddresses = yield* compute.setLabelsAddresses;
|
|
29
|
+
const getRegionOperations = yield* compute.getRegionOperations;
|
|
30
|
+
const awaitOp = makeAwaitRegionOperation(getRegionOperations);
|
|
31
|
+
const observe = (project, region, name) => getAddresses({ project, region, address: name }).pipe(Effect.catchTag("NotFound", () => Effect.succeed(undefined)), Effect.catchTag("Forbidden", () => Effect.succeed(undefined)));
|
|
32
|
+
const syncLabels = Effect.fn(function* (args) {
|
|
33
|
+
if (deepEqual(args.observed.labels ?? {}, args.desired))
|
|
34
|
+
return;
|
|
35
|
+
const op = yield* setLabelsAddresses({
|
|
36
|
+
project: args.project,
|
|
37
|
+
region: args.region,
|
|
38
|
+
resource: args.observed.name ?? "",
|
|
39
|
+
body: {
|
|
40
|
+
labels: args.desired,
|
|
41
|
+
labelFingerprint: args.observed.labelFingerprint,
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
if (op.name) {
|
|
45
|
+
yield* awaitOp(args.project, args.region, op.name, args.session);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
return {
|
|
49
|
+
stables: ["name", "project", "region", "selfLink", "id", "address"],
|
|
50
|
+
diff: Effect.fn(function* ({ news, olds = {} }) {
|
|
51
|
+
if (!isResolved(news))
|
|
52
|
+
return undefined;
|
|
53
|
+
if (somePropsAreDifferent(olds, news, [
|
|
54
|
+
"project",
|
|
55
|
+
"region",
|
|
56
|
+
"name",
|
|
57
|
+
"addressType",
|
|
58
|
+
"purpose",
|
|
59
|
+
"subnetwork",
|
|
60
|
+
"address",
|
|
61
|
+
])) {
|
|
62
|
+
return { action: "replace" };
|
|
63
|
+
}
|
|
64
|
+
return undefined;
|
|
65
|
+
}),
|
|
66
|
+
reconcile: Effect.fn(function* ({ id, news, session }) {
|
|
67
|
+
const internalLabels = yield* gcpInternalLabels(id);
|
|
68
|
+
const desiredName = news.name ??
|
|
69
|
+
(yield* createPhysicalName({ id, maxLength: 63 })).toLowerCase();
|
|
70
|
+
const desiredLabels = {
|
|
71
|
+
...(news.labels ?? {}),
|
|
72
|
+
...internalLabels,
|
|
73
|
+
};
|
|
74
|
+
let observed = yield* observe(news.project, news.region, desiredName);
|
|
75
|
+
if (!observed) {
|
|
76
|
+
const body = {
|
|
77
|
+
name: desiredName,
|
|
78
|
+
...(news.description ? { description: news.description } : {}),
|
|
79
|
+
addressType: news.addressType ?? "INTERNAL",
|
|
80
|
+
...(news.purpose ? { purpose: news.purpose } : {}),
|
|
81
|
+
subnetwork: news.subnetwork,
|
|
82
|
+
...(news.address ? { address: news.address } : {}),
|
|
83
|
+
labels: desiredLabels,
|
|
84
|
+
};
|
|
85
|
+
const op = yield* insertAddresses({
|
|
86
|
+
project: news.project,
|
|
87
|
+
region: news.region,
|
|
88
|
+
body,
|
|
89
|
+
}).pipe(Effect.catchTag("Conflict", () => Effect.succeed(undefined)));
|
|
90
|
+
if (op?.name) {
|
|
91
|
+
yield* awaitOp(news.project, news.region, op.name, session);
|
|
92
|
+
}
|
|
93
|
+
observed = yield* getAddresses({
|
|
94
|
+
project: news.project,
|
|
95
|
+
region: news.region,
|
|
96
|
+
address: desiredName,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
yield* syncLabels({
|
|
100
|
+
project: news.project,
|
|
101
|
+
region: news.region,
|
|
102
|
+
observed,
|
|
103
|
+
desired: desiredLabels,
|
|
104
|
+
session,
|
|
105
|
+
});
|
|
106
|
+
const final = yield* getAddresses({
|
|
107
|
+
project: news.project,
|
|
108
|
+
region: news.region,
|
|
109
|
+
address: desiredName,
|
|
110
|
+
});
|
|
111
|
+
return toAddressAttributes(final, {
|
|
112
|
+
project: news.project,
|
|
113
|
+
region: news.region,
|
|
114
|
+
});
|
|
115
|
+
}),
|
|
116
|
+
delete: Effect.fn(function* ({ output, session }) {
|
|
117
|
+
yield* deleteAddresses({
|
|
118
|
+
project: output.project,
|
|
119
|
+
region: output.region,
|
|
120
|
+
address: output.name,
|
|
121
|
+
}).pipe(Effect.flatMap((op) => op.name
|
|
122
|
+
? awaitOp(output.project, output.region, op.name, session)
|
|
123
|
+
: Effect.succeed(op)), Effect.catchTag("NotFound", () => Effect.void));
|
|
124
|
+
}),
|
|
125
|
+
read: Effect.fn(function* ({ id, output, olds }) {
|
|
126
|
+
const project = output?.project ?? olds?.project;
|
|
127
|
+
const region = output?.region ?? olds?.region;
|
|
128
|
+
if (!project || !region)
|
|
129
|
+
return undefined;
|
|
130
|
+
const name = output?.name ??
|
|
131
|
+
olds?.name ??
|
|
132
|
+
(yield* createPhysicalName({ id, maxLength: 63 })).toLowerCase();
|
|
133
|
+
const observed = yield* observe(project, region, name);
|
|
134
|
+
if (!observed)
|
|
135
|
+
return undefined;
|
|
136
|
+
const attrs = toAddressAttributes(observed, { project, region });
|
|
137
|
+
return (yield* hasAlchemyLabels(id, observed.labels))
|
|
138
|
+
? attrs
|
|
139
|
+
: Unowned(attrs);
|
|
140
|
+
}),
|
|
141
|
+
};
|
|
142
|
+
}));
|
|
143
|
+
//# sourceMappingURL=Address.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Address.js","sourceRoot":"","sources":["../../src/Compute/Address.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { Resource } from "alchemy";
|
|
2
|
+
import * as Provider from "alchemy/Provider";
|
|
3
|
+
import type * as GCP from "../Providers.ts";
|
|
4
|
+
/** One allow entry: a protocol plus optional port list. */
|
|
5
|
+
export type FirewallAllowed = {
|
|
6
|
+
/** `tcp` | `udp` | `icmp` | `esp` | `ah` | `sctp` | protocol number. */
|
|
7
|
+
IPProtocol: string;
|
|
8
|
+
/** Ports / ranges (`"8000"`, `"8000-8100"`). Omit = all ports. */
|
|
9
|
+
ports?: ReadonlyArray<string>;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* A VPC firewall rule (allow rules only — `denied` is not modelled;
|
|
13
|
+
* add it when a consumer needs it).
|
|
14
|
+
*
|
|
15
|
+
* Firewalls have no `labels` field, so adoption gating uses the
|
|
16
|
+
* alchemy marker embedded in `description` (same as `GCP.Network`).
|
|
17
|
+
* Unlike Network, firewall `description` IS mutable, and the sync step
|
|
18
|
+
* keeps the marker prefix in place on every reconcile.
|
|
19
|
+
*
|
|
20
|
+
* GCP rejects rules carrying BOTH `targetTags` and
|
|
21
|
+
* `targetServiceAccounts` — prefer service accounts for GKE node
|
|
22
|
+
* targeting: node tags embed a per-cluster random suffix and go stale
|
|
23
|
+
* on every cluster rebuild, while the compute default SA is stable.
|
|
24
|
+
*
|
|
25
|
+
* @section Creating a firewall rule
|
|
26
|
+
* @example GCLB health checks → GKE pods on 8000
|
|
27
|
+
* ```typescript
|
|
28
|
+
* yield* GCP.Firewall("LbHealthChecks", {
|
|
29
|
+
* project: host.projectId,
|
|
30
|
+
* network: vpc.selfLink,
|
|
31
|
+
* name: "k8s-app-hc",
|
|
32
|
+
* sourceRanges: ["130.211.0.0/22", "35.191.0.0/16"],
|
|
33
|
+
* allowed: [{ IPProtocol: "tcp", ports: ["8000"] }],
|
|
34
|
+
* targetServiceAccounts: [nodeSa],
|
|
35
|
+
* });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export type FirewallProps = {
|
|
39
|
+
/** GCP project ID hosting the rule. Immutable — replace if changed. */
|
|
40
|
+
project: string;
|
|
41
|
+
/**
|
|
42
|
+
* Rule name. Defaults to `createPhysicalName({ id, lowercase: true,
|
|
43
|
+
* maxLength: 63 })`. Immutable — replace if changed.
|
|
44
|
+
*/
|
|
45
|
+
name?: string;
|
|
46
|
+
/**
|
|
47
|
+
* VPC the rule attaches to — short name or selfLink. Immutable —
|
|
48
|
+
* replace if changed.
|
|
49
|
+
*/
|
|
50
|
+
network: string;
|
|
51
|
+
/** User-visible description (stored after the alchemy marker). Mutable. */
|
|
52
|
+
description?: string;
|
|
53
|
+
/** INGRESS (default) or EGRESS. Immutable — replace if changed. */
|
|
54
|
+
direction?: "INGRESS" | "EGRESS";
|
|
55
|
+
/** 0–65535, lower wins. GCP default 1000. Mutable. */
|
|
56
|
+
priority?: number;
|
|
57
|
+
/** Source CIDRs (INGRESS). Mutable. */
|
|
58
|
+
sourceRanges?: ReadonlyArray<string>;
|
|
59
|
+
/** Destination CIDRs (EGRESS). Mutable. */
|
|
60
|
+
destinationRanges?: ReadonlyArray<string>;
|
|
61
|
+
/** Allow entries. Required — this resource models allow rules only. Mutable. */
|
|
62
|
+
allowed: ReadonlyArray<FirewallAllowed>;
|
|
63
|
+
/**
|
|
64
|
+
* Instance network tags the rule applies to. Mutually exclusive with
|
|
65
|
+
* `targetServiceAccounts`. Mutable.
|
|
66
|
+
*/
|
|
67
|
+
targetTags?: ReadonlyArray<string>;
|
|
68
|
+
/**
|
|
69
|
+
* Service accounts whose instances the rule applies to. Preferred
|
|
70
|
+
* over tags for GKE nodes (stable across cluster rebuilds). Mutually
|
|
71
|
+
* exclusive with `targetTags`. Mutable.
|
|
72
|
+
*/
|
|
73
|
+
targetServiceAccounts?: ReadonlyArray<string>;
|
|
74
|
+
/** Rule disabled (kept but not enforced). Mutable. */
|
|
75
|
+
disabled?: boolean;
|
|
76
|
+
};
|
|
77
|
+
export type FirewallAttributes = {
|
|
78
|
+
/** Rule name. */
|
|
79
|
+
name: string;
|
|
80
|
+
/** GCP project ID, threaded through from props for delete/read. */
|
|
81
|
+
project: string;
|
|
82
|
+
/** Server-defined URL. */
|
|
83
|
+
selfLink: string;
|
|
84
|
+
/** Server-assigned numeric id. */
|
|
85
|
+
id: string;
|
|
86
|
+
/** VPC selfLink the rule is attached to. */
|
|
87
|
+
network: string;
|
|
88
|
+
/** INGRESS / EGRESS. */
|
|
89
|
+
direction: string | undefined;
|
|
90
|
+
/** Effective priority. */
|
|
91
|
+
priority: number | undefined;
|
|
92
|
+
/** Source CIDRs. */
|
|
93
|
+
sourceRanges: ReadonlyArray<string> | undefined;
|
|
94
|
+
/** Allow entries. */
|
|
95
|
+
allowed: ReadonlyArray<FirewallAllowed> | undefined;
|
|
96
|
+
/** Target network tags. */
|
|
97
|
+
targetTags: ReadonlyArray<string> | undefined;
|
|
98
|
+
/** Target service accounts. */
|
|
99
|
+
targetServiceAccounts: ReadonlyArray<string> | undefined;
|
|
100
|
+
/** User description (alchemy marker stripped). */
|
|
101
|
+
description: string | undefined;
|
|
102
|
+
/** Disabled flag. */
|
|
103
|
+
disabled: boolean | undefined;
|
|
104
|
+
};
|
|
105
|
+
export type Firewall = Resource<"GCP.Firewall", FirewallProps, FirewallAttributes, never, GCP.Providers>;
|
|
106
|
+
export declare const Firewall: import("alchemy").ResourceClass<Firewall>;
|
|
107
|
+
export declare const FirewallProvider: () => import("effect/Layer").Layer<Provider.Provider<Firewall>, never, import("alchemy").Stack | import("alchemy").Stage | import("@distilled.cloud/gcp").Credentials | import("effect/unstable/http/HttpClient").HttpClient>;
|
|
108
|
+
//# sourceMappingURL=Firewall.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Firewall.d.ts","sourceRoot":"","sources":["../../src/Compute/Firewall.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAInC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAO7C,OAAO,KAAK,KAAK,GAAG,MAAM,iBAAiB,CAAC;AAG5C,2DAA2D;AAC3D,MAAM,MAAM,eAAe,GAAG;IAC5B,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,KAAK,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAC/B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,SAAS,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACjC,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,YAAY,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACrC,2CAA2C;IAC3C,iBAAiB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC1C,gFAAgF;IAChF,OAAO,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IACxC;;;OAGG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACnC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC9C,sDAAsD;IACtD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,wBAAwB;IACxB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,oBAAoB;IACpB,YAAY,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;IAChD,qBAAqB;IACrB,OAAO,EAAE,aAAa,CAAC,eAAe,CAAC,GAAG,SAAS,CAAC;IACpD,2BAA2B;IAC3B,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;IAC9C,+BAA+B;IAC/B,qBAAqB,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;IACzD,kDAAkD;IAClD,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,qBAAqB;IACrB,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAC7B,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,KAAK,EACL,GAAG,CAAC,SAAS,CACd,CAAC;AACF,eAAO,MAAM,QAAQ,2CAAqC,CAAC;AAqD3D,eAAO,MAAM,gBAAgB,+NAsJ1B,CAAC"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import * as compute from "@distilled.cloud/gcp/compute-v1";
|
|
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 * as Effect from "effect/Effect";
|
|
8
|
+
import { descriptionHasAlchemyMarker, gcpAlchemyDescription, stripAlchemyMarker, } from "../Tags.js";
|
|
9
|
+
import { makeAwaitGlobalOperation } from "./Operations.js";
|
|
10
|
+
export const Firewall = Resource("GCP.Firewall");
|
|
11
|
+
const toFirewallAttributes = (f, parent) => ({
|
|
12
|
+
name: f.name ?? "",
|
|
13
|
+
project: parent.project,
|
|
14
|
+
selfLink: f.selfLink ?? "",
|
|
15
|
+
id: f.id ?? "",
|
|
16
|
+
network: f.network ?? "",
|
|
17
|
+
direction: f.direction,
|
|
18
|
+
priority: f.priority,
|
|
19
|
+
sourceRanges: f.sourceRanges,
|
|
20
|
+
allowed: f.allowed,
|
|
21
|
+
targetTags: f.targetTags,
|
|
22
|
+
targetServiceAccounts: f.targetServiceAccounts,
|
|
23
|
+
description: stripAlchemyMarker(f.description),
|
|
24
|
+
disabled: f.disabled,
|
|
25
|
+
});
|
|
26
|
+
/**
|
|
27
|
+
* Normalize for drift comparison: GCP reorders list fields and the
|
|
28
|
+
* `allowed` entries' ports — compare order-insensitively so a
|
|
29
|
+
* cosmetic reordering doesn't trigger a PATCH every reconcile.
|
|
30
|
+
*/
|
|
31
|
+
const normalized = (f) => ({
|
|
32
|
+
priority: f.priority ?? 1000,
|
|
33
|
+
sourceRanges: [...(f.sourceRanges ?? [])].sort(),
|
|
34
|
+
destinationRanges: [...(f.destinationRanges ?? [])].sort(),
|
|
35
|
+
allowed: [...(f.allowed ?? [])]
|
|
36
|
+
.map((a) => ({
|
|
37
|
+
IPProtocol: (a.IPProtocol ?? "").toLowerCase(),
|
|
38
|
+
ports: [...(a.ports ?? [])].sort(),
|
|
39
|
+
}))
|
|
40
|
+
.sort((x, y) => x.IPProtocol.localeCompare(y.IPProtocol)),
|
|
41
|
+
targetTags: [...(f.targetTags ?? [])].sort(),
|
|
42
|
+
targetServiceAccounts: [...(f.targetServiceAccounts ?? [])].sort(),
|
|
43
|
+
disabled: f.disabled ?? false,
|
|
44
|
+
description: f.description,
|
|
45
|
+
});
|
|
46
|
+
export const FirewallProvider = () => Provider.effect(Firewall, Effect.gen(function* () {
|
|
47
|
+
const getFirewalls = yield* compute.getFirewalls;
|
|
48
|
+
const insertFirewalls = yield* compute.insertFirewalls;
|
|
49
|
+
const patchFirewalls = yield* compute.patchFirewalls;
|
|
50
|
+
const deleteFirewalls = yield* compute.deleteFirewalls;
|
|
51
|
+
const getGlobalOperations = yield* compute.getGlobalOperations;
|
|
52
|
+
const awaitOp = makeAwaitGlobalOperation(getGlobalOperations);
|
|
53
|
+
const observe = (project, name) => getFirewalls({ project, firewall: name }).pipe(Effect.catchTag("NotFound", () => Effect.succeed(undefined)), Effect.catchTag("Forbidden", () => Effect.succeed(undefined)));
|
|
54
|
+
return {
|
|
55
|
+
stables: ["name", "project", "selfLink", "id", "network"],
|
|
56
|
+
diff: Effect.fn(function* ({ news, olds = {} }) {
|
|
57
|
+
if (!isResolved(news))
|
|
58
|
+
return undefined;
|
|
59
|
+
if (somePropsAreDifferent(olds, news, [
|
|
60
|
+
"project",
|
|
61
|
+
"name",
|
|
62
|
+
"network",
|
|
63
|
+
"direction",
|
|
64
|
+
])) {
|
|
65
|
+
return { action: "replace" };
|
|
66
|
+
}
|
|
67
|
+
return undefined;
|
|
68
|
+
}),
|
|
69
|
+
reconcile: Effect.fn(function* ({ id, news, session }) {
|
|
70
|
+
if (news.targetTags?.length && news.targetServiceAccounts?.length) {
|
|
71
|
+
return yield* Effect.fail(new Error("Firewall: targetTags and targetServiceAccounts are mutually exclusive (GCP rejects rules with both)"));
|
|
72
|
+
}
|
|
73
|
+
const desiredName = news.name ??
|
|
74
|
+
(yield* createPhysicalName({ id, maxLength: 63 })).toLowerCase();
|
|
75
|
+
const desiredDescription = yield* gcpAlchemyDescription(id, news.description);
|
|
76
|
+
const mutableBody = () => ({
|
|
77
|
+
description: desiredDescription,
|
|
78
|
+
...(news.priority !== undefined ? { priority: news.priority } : {}),
|
|
79
|
+
...(news.sourceRanges
|
|
80
|
+
? { sourceRanges: [...news.sourceRanges] }
|
|
81
|
+
: {}),
|
|
82
|
+
...(news.destinationRanges
|
|
83
|
+
? { destinationRanges: [...news.destinationRanges] }
|
|
84
|
+
: {}),
|
|
85
|
+
allowed: news.allowed.map((a) => ({
|
|
86
|
+
IPProtocol: a.IPProtocol,
|
|
87
|
+
...(a.ports ? { ports: [...a.ports] } : {}),
|
|
88
|
+
})),
|
|
89
|
+
// Always send both target fields: switching tags → service
|
|
90
|
+
// accounts must CLEAR the other side, and PATCH leaves
|
|
91
|
+
// omitted fields untouched.
|
|
92
|
+
targetTags: [...(news.targetTags ?? [])],
|
|
93
|
+
targetServiceAccounts: [...(news.targetServiceAccounts ?? [])],
|
|
94
|
+
disabled: news.disabled ?? false,
|
|
95
|
+
});
|
|
96
|
+
// 1. Observe — collapse 403 to "missing" alongside 404.
|
|
97
|
+
let observed = yield* observe(news.project, desiredName);
|
|
98
|
+
// 2. Ensure — create if missing. `Conflict` covers concurrent
|
|
99
|
+
// creates and state-persistence races.
|
|
100
|
+
if (!observed) {
|
|
101
|
+
const op = yield* insertFirewalls({
|
|
102
|
+
project: news.project,
|
|
103
|
+
body: {
|
|
104
|
+
name: desiredName,
|
|
105
|
+
network: news.network,
|
|
106
|
+
...(news.direction ? { direction: news.direction } : {}),
|
|
107
|
+
...mutableBody(),
|
|
108
|
+
},
|
|
109
|
+
}).pipe(Effect.catchTag("Conflict", () => Effect.succeed(undefined)));
|
|
110
|
+
if (op?.name)
|
|
111
|
+
yield* awaitOp(news.project, op.name, session);
|
|
112
|
+
observed = yield* getFirewalls({
|
|
113
|
+
project: news.project,
|
|
114
|
+
firewall: desiredName,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
// 3. Sync — everything except name/network/direction is
|
|
118
|
+
// PATCHable. Diff against OBSERVED state (cloud is
|
|
119
|
+
// authoritative), order-insensitively.
|
|
120
|
+
const desired = mutableBody();
|
|
121
|
+
if (!deepEqual(normalized(observed), normalized(desired))) {
|
|
122
|
+
const op = yield* patchFirewalls({
|
|
123
|
+
project: news.project,
|
|
124
|
+
firewall: desiredName,
|
|
125
|
+
body: desired,
|
|
126
|
+
});
|
|
127
|
+
if (op.name)
|
|
128
|
+
yield* awaitOp(news.project, op.name, session);
|
|
129
|
+
}
|
|
130
|
+
const final = yield* getFirewalls({
|
|
131
|
+
project: news.project,
|
|
132
|
+
firewall: desiredName,
|
|
133
|
+
});
|
|
134
|
+
return toFirewallAttributes(final, { project: news.project });
|
|
135
|
+
}),
|
|
136
|
+
delete: Effect.fn(function* ({ output, session }) {
|
|
137
|
+
yield* deleteFirewalls({
|
|
138
|
+
project: output.project,
|
|
139
|
+
firewall: output.name,
|
|
140
|
+
}).pipe(Effect.flatMap((op) => op.name
|
|
141
|
+
? awaitOp(output.project, op.name, session)
|
|
142
|
+
: Effect.succeed(op)), Effect.catchTag("NotFound", () => Effect.void));
|
|
143
|
+
}),
|
|
144
|
+
read: Effect.fn(function* ({ id, output, olds }) {
|
|
145
|
+
const project = output?.project ?? olds?.project;
|
|
146
|
+
if (!project)
|
|
147
|
+
return undefined;
|
|
148
|
+
const name = output?.name ??
|
|
149
|
+
olds?.name ??
|
|
150
|
+
(yield* createPhysicalName({ id, maxLength: 63 })).toLowerCase();
|
|
151
|
+
const observed = yield* observe(project, name);
|
|
152
|
+
if (!observed)
|
|
153
|
+
return undefined;
|
|
154
|
+
const attrs = toFirewallAttributes(observed, { project });
|
|
155
|
+
// Adoption gate via the description marker — firewalls have
|
|
156
|
+
// no labels field (same situation as GCP.Network).
|
|
157
|
+
return (yield* descriptionHasAlchemyMarker(id, observed.description))
|
|
158
|
+
? attrs
|
|
159
|
+
: Unowned(attrs);
|
|
160
|
+
}),
|
|
161
|
+
};
|
|
162
|
+
}));
|
|
163
|
+
//# sourceMappingURL=Firewall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Firewall.js","sourceRoot":"","sources":["../../src/Compute/Firewall.ts"],"names":[],"mappings":"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"}
|