@intentius/chant-lexicon-gcp 0.0.24 → 0.1.4

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.
@@ -1,41 +1,41 @@
1
1
  {
2
2
  "algorithm": "xxhash64",
3
3
  "artifacts": {
4
- "manifest.json": "1a93f9f8be77c3c6",
4
+ "manifest.json": "b2c3c0befed259f3",
5
5
  "meta.json": "4b53e87923a434ef",
6
6
  "types/index.d.ts": "c7cc45a739cefe9d",
7
7
  "rules/hardcoded-region.ts": "d230565c5cc6b600",
8
- "rules/hardcoded-project.ts": "8ce1e3f6f7f7d217",
9
8
  "rules/public-iam.ts": "a569c09c0402dc12",
10
- "rules/wgc301.ts": "7481759f8344dc46",
9
+ "rules/hardcoded-project.ts": "8ce1e3f6f7f7d217",
10
+ "rules/wgc203.ts": "40a8831e701d4882",
11
+ "rules/wgc108.ts": "4ed90d7ccb04a93",
11
12
  "rules/wgc105.ts": "2e6a93ea14234e53",
12
- "rules/gcp-helpers.ts": "76fcd4774c99093c",
13
- "rules/wgc302.ts": "f2a5f2ea4efec1b",
13
+ "rules/schema-registry.ts": "6327d2dc2fed726e",
14
+ "rules/wgc109.ts": "58a4010d5a5e3cfc",
15
+ "rules/wgc103.ts": "e0a3c0606cb1fe1",
14
16
  "rules/wgc110.ts": "2a9da9543e34d8de",
15
17
  "rules/wgc201.ts": "173c4cfb020c3593",
16
- "rules/wgc303.ts": "4be04d7faa6b2f1e",
17
- "rules/wgc102.ts": "ee34a5b1d58643b8",
18
- "rules/wgc103.ts": "e0a3c0606cb1fe1",
19
- "rules/wgc108.ts": "4ed90d7ccb04a93",
20
- "rules/wgc203.ts": "40a8831e701d4882",
18
+ "rules/wgc302.ts": "f2a5f2ea4efec1b",
21
19
  "rules/wgc111.ts": "474a4ab06596ecd0",
22
- "rules/wgc202.ts": "b6036fce2553d15b",
23
- "rules/wgc403.ts": "a873a8708f82f0a9",
24
- "rules/wgc204.ts": "bf9cb93ace50c4b0",
25
- "rules/wgc401.ts": "35fcebf42c7379c7",
26
- "rules/schema-registry.ts": "6327d2dc2fed726e",
27
- "rules/wgc101.ts": "170fc08848092171",
28
- "rules/wgc104.ts": "56b3c40af42e9302",
29
20
  "rules/wgc112.ts": "34b22234dfca1a17",
30
- "rules/wgc107.ts": "ae6dcd327490da06",
31
- "rules/wgc109.ts": "58a4010d5a5e3cfc",
32
21
  "rules/wgc402.ts": "7f054e29d146290f",
22
+ "rules/gcp-helpers.ts": "76fcd4774c99093c",
33
23
  "rules/wgc106.ts": "180629dfc4f2934",
34
24
  "rules/wgc113.ts": "677724b28a9dbd5c",
25
+ "rules/wgc202.ts": "b6036fce2553d15b",
26
+ "rules/wgc303.ts": "4be04d7faa6b2f1e",
27
+ "rules/wgc107.ts": "ae6dcd327490da06",
28
+ "rules/wgc101.ts": "170fc08848092171",
29
+ "rules/wgc401.ts": "35fcebf42c7379c7",
30
+ "rules/wgc301.ts": "7481759f8344dc46",
31
+ "rules/wgc104.ts": "56b3c40af42e9302",
32
+ "rules/wgc403.ts": "a873a8708f82f0a9",
33
+ "rules/wgc102.ts": "ee34a5b1d58643b8",
34
+ "rules/wgc204.ts": "bf9cb93ace50c4b0",
35
35
  "skills/chant-gcp.md": "13a559014514fdb0",
36
36
  "skills/chant-gcp-security.md": "9ed168e1fb54d31b",
37
37
  "skills/chant-gcp-patterns.md": "6cd0a4a78933323c",
38
38
  "skills/chant-gcp-gke.md": "f185f6c0de514ba0"
39
39
  },
40
- "composite": "2fcb40fd58eb2860"
40
+ "composite": "b99c7c6bb17a778c"
41
41
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gcp",
3
- "version": "0.0.24",
3
+ "version": "0.1.4",
4
4
  "chantVersion": ">=0.1.0",
5
5
  "namespace": "GCP",
6
6
  "intrinsics": [],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/chant-lexicon-gcp",
3
- "version": "0.0.24",
3
+ "version": "0.1.4",
4
4
  "description": "Google Cloud lexicon for chant — declarative IaC in TypeScript",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://intentius.io/chant",
@@ -43,11 +43,14 @@
43
43
  "prepack": "bun run generate && bun run bundle && bun run validate"
44
44
  },
45
45
  "dependencies": {
46
- "@intentius/chant": "0.0.22",
47
46
  "fflate": "^0.8.2",
48
47
  "js-yaml": "^4.1.0"
49
48
  },
50
49
  "devDependencies": {
50
+ "@intentius/chant": "0.1.4",
51
51
  "typescript": "^5.9.3"
52
+ },
53
+ "peerDependencies": {
54
+ "@intentius/chant": "^0.1.0"
52
55
  }
53
56
  }
@@ -69,6 +69,12 @@ export const CloudSqlInstance = Composite<CloudSqlInstanceProps>((props) => {
69
69
  defaults: defs,
70
70
  } = props;
71
71
 
72
+ // K8s metadata name must be a valid DNS subdomain (no underscores).
73
+ // When databaseName differs from the instance name, prefix with instance name
74
+ // to guarantee uniqueness across instances sharing the same databaseName.
75
+ const sanitizedDbName = databaseName.replace(/_/g, "-");
76
+ const databaseK8sName = databaseName === name ? sanitizedDbName : `${name}-${sanitizedDbName}`;
77
+
72
78
  const commonLabels: Record<string, string> = {
73
79
  "app.kubernetes.io/name": name,
74
80
  "app.kubernetes.io/managed-by": "chant",
@@ -102,15 +108,21 @@ export const CloudSqlInstance = Composite<CloudSqlInstanceProps>((props) => {
102
108
 
103
109
  const database = new SQLDatabase(mergeDefaults({
104
110
  metadata: {
105
- name: databaseName,
111
+ name: databaseK8sName,
106
112
  ...(namespace && { namespace }),
107
113
  labels: { ...commonLabels, "app.kubernetes.io/component": "database" },
108
114
  },
109
115
  instanceRef: { name },
116
+ // resourceID sets the actual Cloud SQL database name when the K8s-safe name differs
117
+ ...(databaseName !== sanitizedDbName && { resourceID: databaseName }),
110
118
  } as Record<string, unknown>, defs?.database));
111
119
 
112
120
  const user = new SQLUser(mergeDefaults({
113
121
  metadata: {
122
+ // K8s name scoped to the instance for uniqueness (e.g. "mydb-admin").
123
+ // Without resourceID, Config Connector uses metadata.name as the actual
124
+ // Cloud SQL username — so the PG username IS the K8s resource name.
125
+ // Callers can override via defaults.user.resourceID if a shorter name is needed.
114
126
  name: `${name}-${userName}`,
115
127
  ...(namespace && { namespace }),
116
128
  labels: { ...commonLabels, "app.kubernetes.io/component": "database" },
@@ -18,3 +18,5 @@ export { ManagedCertificate } from "./managed-certificate";
18
18
  export type { ManagedCertificateProps } from "./managed-certificate";
19
19
  export { SecureProject } from "./secure-project";
20
20
  export type { SecureProjectProps } from "./secure-project";
21
+ export { MemorystoreRedis } from "./memorystore-redis";
22
+ export type { MemorystoreRedisProps } from "./memorystore-redis";
@@ -0,0 +1,101 @@
1
+ /**
2
+ * MemorystoreRedis composite — RedisInstance with purpose-driven defaults.
3
+ */
4
+
5
+ import { Composite, mergeDefaults } from "@intentius/chant";
6
+ import { RedisInstance } from "../generated";
7
+
8
+ export interface MemorystoreRedisProps {
9
+ /** Instance name. */
10
+ name: string;
11
+ /**
12
+ * Purpose drives the maxmemory-policy default:
13
+ * - "persistent" → "noeviction" (queues, shared_state must not evict)
14
+ * - "cache" → "allkeys-lru" (cache/sessions can evict LRU)
15
+ */
16
+ purpose: "persistent" | "cache";
17
+ /** Memorystore tier (e.g. "BASIC", "STANDARD_HA"). */
18
+ tier: string;
19
+ /** Memory size in GB. */
20
+ memorySizeGb: number;
21
+ /** GCP region. */
22
+ region: string;
23
+ /** authorizedNetworkRef.name — the VPC network to authorize. */
24
+ networkRef: string;
25
+ /** Redis version (default: "REDIS_7_0"). */
26
+ redisVersion?: string;
27
+ /** Enable AUTH (default: true). */
28
+ authEnabled?: boolean;
29
+ /** Namespace for all resources. */
30
+ namespace?: string;
31
+ /** Additional labels. */
32
+ labels?: Record<string, string>;
33
+ /** Per-member defaults for customizing individual resources. */
34
+ defaults?: {
35
+ instance?: Partial<Record<string, unknown>>;
36
+ };
37
+ }
38
+
39
+ /**
40
+ * Create a MemorystoreRedis composite.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * import { MemorystoreRedis } from "@intentius/chant-lexicon-gcp";
45
+ *
46
+ * const { instance } = MemorystoreRedis({
47
+ * name: "my-app-persistent",
48
+ * purpose: "persistent",
49
+ * tier: "STANDARD_HA",
50
+ * memorySizeGb: 5,
51
+ * region: "us-central1",
52
+ * networkRef: "my-vpc",
53
+ * });
54
+ * ```
55
+ */
56
+ export const MemorystoreRedis = Composite<MemorystoreRedisProps>((props) => {
57
+ const {
58
+ name,
59
+ purpose,
60
+ tier,
61
+ memorySizeGb,
62
+ region,
63
+ networkRef,
64
+ redisVersion = "REDIS_7_0",
65
+ authEnabled = true,
66
+ namespace,
67
+ labels: extraLabels = {},
68
+ defaults: defs,
69
+ } = props;
70
+
71
+ const maxmemoryPolicy = purpose === "persistent" ? "noeviction" : "allkeys-lru";
72
+
73
+ const commonLabels: Record<string, string> = {
74
+ "app.kubernetes.io/name": name,
75
+ "app.kubernetes.io/managed-by": "chant",
76
+ ...extraLabels,
77
+ };
78
+
79
+ const instance = new RedisInstance(mergeDefaults({
80
+ metadata: {
81
+ name,
82
+ ...(namespace && { namespace }),
83
+ labels: { ...commonLabels, "app.kubernetes.io/component": "cache" },
84
+ },
85
+ region,
86
+ tier,
87
+ memorySizeGb,
88
+ authEnabled,
89
+ redisVersion,
90
+ connectMode: "PRIVATE_SERVICE_ACCESS",
91
+ authorizedNetworkRef: { name: networkRef },
92
+ // TLS disabled: GitLab's redis-rb client requires either no TLS or a custom CA cert
93
+ // injected via REDIS_SSL_CA_FILE. AUTH (authEnabled: true) provides access control.
94
+ transitEncryptionMode: "DISABLED",
95
+ redisConfigs: {
96
+ "maxmemory-policy": maxmemoryPolicy,
97
+ },
98
+ } as Record<string, unknown>, defs?.instance));
99
+
100
+ return { instance };
101
+ }, "MemorystoreRedis");
@@ -5,6 +5,11 @@
5
5
  import { Composite, mergeDefaults } from "@intentius/chant";
6
6
  import { VPCNetwork, Subnetwork, Firewall, Router, RouterNAT } from "../generated";
7
7
 
8
+ export interface VpcSubnetSecondaryRange {
9
+ rangeName: string;
10
+ ipCidrRange: string;
11
+ }
12
+
8
13
  export interface VpcSubnet {
9
14
  /** Subnet name suffix. */
10
15
  name: string;
@@ -14,6 +19,8 @@ export interface VpcSubnet {
14
19
  region: string;
15
20
  /** Enable private Google access (default: true). */
16
21
  privateIpGoogleAccess?: boolean;
22
+ /** Secondary IP ranges for VPC-native GKE pods/services. */
23
+ secondaryIpRanges?: VpcSubnetSecondaryRange[];
17
24
  }
18
25
 
19
26
  export interface VpcNetworkProps {
@@ -104,6 +111,9 @@ export const VpcNetwork = Composite<VpcNetworkProps>((props) => {
104
111
  ipCidrRange: sub.ipCidrRange,
105
112
  region: sub.region,
106
113
  privateIpGoogleAccess: sub.privateIpGoogleAccess ?? true,
114
+ ...(sub.secondaryIpRanges && sub.secondaryIpRanges.length > 0 && {
115
+ secondaryIpRange: sub.secondaryIpRanges,
116
+ }),
107
117
  } as Record<string, unknown>);
108
118
  }
109
119
 
package/src/index.ts CHANGED
@@ -22,6 +22,7 @@ export * from "./generated/index";
22
22
  export {
23
23
  GkeCluster, CloudRunServiceComposite, CloudSqlInstance, GcsBucket, VpcNetwork,
24
24
  PubSubPipeline, CloudFunctionWithTrigger, PrivateService, ManagedCertificate, SecureProject,
25
+ MemorystoreRedis,
25
26
  } from "./composites/index";
26
27
  export type {
27
28
  GkeClusterProps,
@@ -34,6 +35,7 @@ export type {
34
35
  PrivateServiceProps,
35
36
  ManagedCertificateProps,
36
37
  SecureProjectProps,
38
+ MemorystoreRedisProps,
37
39
  } from "./composites/index";
38
40
 
39
41
  // IAM role constants