@intentius/chant-lexicon-gcp 0.0.18 → 0.0.24
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/integrity.json +12 -8
- package/dist/manifest.json +1 -1
- package/dist/meta.json +18141 -0
- package/dist/rules/schema-registry.ts +91 -0
- package/dist/rules/wgc101.ts +1 -1
- package/dist/rules/wgc401.ts +59 -0
- package/dist/rules/wgc402.ts +54 -0
- package/dist/rules/wgc403.ts +84 -0
- package/dist/skills/{chant-gke.md → chant-gcp-gke.md} +1 -1
- package/dist/skills/chant-gcp-patterns.md +3 -2
- package/dist/skills/chant-gcp-security.md +3 -2
- package/dist/skills/chant-gcp.md +363 -28
- package/package.json +20 -2
- package/src/codegen/docs.test.ts +16 -0
- package/src/codegen/generate.test.ts +18 -0
- package/src/codegen/generate.ts +11 -0
- package/src/codegen/package.test.ts +16 -0
- package/src/composites/cloud-function.ts +23 -15
- package/src/composites/cloud-run-service.ts +20 -13
- package/src/composites/cloud-sql-instance.ts +18 -14
- package/src/composites/composites.test.ts +94 -62
- package/src/composites/gcs-bucket.ts +13 -9
- package/src/composites/gke-cluster.ts +91 -16
- package/src/composites/index.ts +11 -11
- package/src/composites/managed-certificate.ts +19 -15
- package/src/composites/private-service.ts +23 -15
- package/src/composites/pubsub-pipeline.ts +30 -18
- package/src/composites/secure-project.ts +42 -27
- package/src/composites/vpc-network.ts +42 -35
- package/src/generated/lexicon-gcp.json +18141 -0
- package/src/import/import-fixtures.test.ts +98 -0
- package/src/index.ts +11 -11
- package/src/lint/post-synth/gcp-helpers.test.ts +166 -0
- package/src/lint/post-synth/post-synth.test.ts +132 -1
- package/src/lint/post-synth/schema-registry.ts +91 -0
- package/src/lint/post-synth/wgc101.test.ts +40 -0
- package/src/lint/post-synth/wgc101.ts +1 -1
- package/src/lint/post-synth/wgc102.test.ts +38 -0
- package/src/lint/post-synth/wgc103.test.ts +38 -0
- package/src/lint/post-synth/wgc104.test.ts +37 -0
- package/src/lint/post-synth/wgc105.test.ts +46 -0
- package/src/lint/post-synth/wgc106.test.ts +38 -0
- package/src/lint/post-synth/wgc107.test.ts +38 -0
- package/src/lint/post-synth/wgc108.test.ts +42 -0
- package/src/lint/post-synth/wgc109.test.ts +46 -0
- package/src/lint/post-synth/wgc110.test.ts +37 -0
- package/src/lint/post-synth/wgc111.test.ts +46 -0
- package/src/lint/post-synth/wgc112.test.ts +48 -0
- package/src/lint/post-synth/wgc113.test.ts +36 -0
- package/src/lint/post-synth/wgc201.test.ts +38 -0
- package/src/lint/post-synth/wgc202.test.ts +38 -0
- package/src/lint/post-synth/wgc203.test.ts +45 -0
- package/src/lint/post-synth/wgc204.test.ts +42 -0
- package/src/lint/post-synth/wgc301.test.ts +39 -0
- package/src/lint/post-synth/wgc302.test.ts +36 -0
- package/src/lint/post-synth/wgc303.test.ts +37 -0
- package/src/lint/post-synth/wgc401.test.ts +46 -0
- package/src/lint/post-synth/wgc401.ts +59 -0
- package/src/lint/post-synth/wgc402.test.ts +40 -0
- package/src/lint/post-synth/wgc402.ts +54 -0
- package/src/lint/post-synth/wgc403.test.ts +59 -0
- package/src/lint/post-synth/wgc403.ts +84 -0
- package/src/plugin.test.ts +4 -1
- package/src/plugin.ts +258 -177
- package/src/skills/{chant-gke.md → chant-gcp-gke.md} +1 -1
- package/src/skills/chant-gcp-patterns.md +3 -2
- package/src/skills/chant-gcp-security.md +3 -2
- package/src/skills/chant-gcp.md +363 -28
package/src/skills/chant-gcp.md
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
skill: chant-gcp
|
|
3
3
|
description: Build, validate, and deploy GCP Config Connector manifests from a chant project
|
|
4
|
-
source: chant-lexicon
|
|
5
4
|
user-invocable: true
|
|
6
5
|
---
|
|
7
6
|
|
|
@@ -9,7 +8,7 @@ user-invocable: true
|
|
|
9
8
|
|
|
10
9
|
## How chant and Config Connector relate
|
|
11
10
|
|
|
12
|
-
chant is a **synthesis
|
|
11
|
+
chant is a **synthesis compiler** — it compiles TypeScript source files into Config Connector YAML manifests. `chant build` does not call GCP APIs; synthesis is pure and deterministic. Config Connector resources are Kubernetes objects, so the optional `chant state snapshot` command queries the Kubernetes API to capture deployment metadata (resource status, conditions, observed state) for observability. Your job as an agent is to bridge synthesis and deployment:
|
|
13
12
|
|
|
14
13
|
- Use **chant** for: build, lint, diff (local YAML comparison)
|
|
15
14
|
- Use **kubectl** for: apply, rollback, monitoring, troubleshooting
|
|
@@ -18,44 +17,117 @@ The source of truth for infrastructure is the TypeScript in `src/`. The generate
|
|
|
18
17
|
|
|
19
18
|
## Prerequisites
|
|
20
19
|
|
|
21
|
-
1. A GKE cluster with Config Connector installed
|
|
22
|
-
2. A ConfigConnectorContext resource per namespace
|
|
23
|
-
3. A GCP Service Account with appropriate IAM roles
|
|
20
|
+
1. A GKE cluster with Config Connector installed and the controller running
|
|
21
|
+
2. A ConfigConnectorContext resource per namespace binding an IAM service account
|
|
22
|
+
3. A GCP Service Account with appropriate IAM roles for the resources you declare
|
|
23
|
+
4. `kubectl` configured with credentials for the target cluster
|
|
24
|
+
5. `chant` installed (`npm install --save-dev @intentius/chant @intentius/chant-lexicon-gcp`)
|
|
25
|
+
6. Workload Identity enabled on the GKE node pool (recommended over key-based auth)
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
Verify Config Connector is healthy before your first deploy:
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
```bash
|
|
30
|
+
kubectl get configconnectorcontexts -A
|
|
31
|
+
kubectl get pods -n cnrm-system
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Both should show `Running` / `Healthy`. If the controller pod is crashlooping, no resources will reconcile.
|
|
35
|
+
|
|
36
|
+
## Build and validate workflow
|
|
37
|
+
|
|
38
|
+
### 1. Lint the source
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
chant lint src/
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Runs pre-synth static analysis on your TypeScript. Fix all warnings before building.
|
|
45
|
+
|
|
46
|
+
### 2. Build manifests
|
|
28
47
|
|
|
29
48
|
```bash
|
|
30
49
|
chant build src/ --output manifests.yaml
|
|
31
50
|
```
|
|
32
51
|
|
|
33
|
-
|
|
52
|
+
Synthesizes TypeScript into Config Connector YAML and runs post-synth checks on the output.
|
|
53
|
+
|
|
54
|
+
### 3. Server-side dry run
|
|
34
55
|
|
|
35
56
|
```bash
|
|
36
|
-
|
|
57
|
+
kubectl apply -f manifests.yaml --dry-run=server
|
|
37
58
|
```
|
|
38
59
|
|
|
60
|
+
Validates the manifests against the Kubernetes API server schema. Catches CRD version mismatches, unknown fields, and missing namespaces.
|
|
61
|
+
|
|
39
62
|
### What each step catches
|
|
40
63
|
|
|
41
|
-
| Step | Catches | When to run |
|
|
42
|
-
|
|
43
|
-
| `chant lint` | Hardcoded project IDs
|
|
44
|
-
| `chant
|
|
64
|
+
| Step | Rule IDs | Catches | When to run |
|
|
65
|
+
|------|----------|---------|-------------|
|
|
66
|
+
| `chant lint` | WGC001 | Hardcoded project IDs | Every edit |
|
|
67
|
+
| `chant lint` | WGC002 | Hardcoded regions | Every edit |
|
|
68
|
+
| `chant lint` | WGC003 | Public IAM bindings (allUsers/allAuthenticatedUsers) | Every edit |
|
|
69
|
+
| `chant build` (post-synth) | WGC101 | Missing encryption (CMEK or Google-managed) | Before apply |
|
|
70
|
+
| `chant build` (post-synth) | WGC102 | Public IAM bindings in synthesized output | Before apply |
|
|
71
|
+
| `chant build` (post-synth) | WGC103 | Missing project annotation on resource | Before apply |
|
|
72
|
+
| `chant build` (post-synth) | WGC104 | Missing uniform bucket-level access on GCS | Before apply |
|
|
73
|
+
| `chant build` (post-synth) | WGC105 | Public Cloud SQL (ipConfiguration.ipv4Enabled) | Before apply |
|
|
74
|
+
| `chant build` (post-synth) | WGC106 | Missing deletion policy annotation | Before apply |
|
|
75
|
+
| `chant build` (post-synth) | WGC107 | Missing versioning on GCS buckets | Before apply |
|
|
76
|
+
| `chant build` (post-synth) | WGC108 | Missing backup configuration on Cloud SQL | Before apply |
|
|
77
|
+
| `chant build` (post-synth) | WGC109 | Open firewall rules (0.0.0.0/0) | Before apply |
|
|
78
|
+
| `chant build` (post-synth) | WGC110 | Missing key rotation period on KMS keys | Before apply |
|
|
79
|
+
| `chant build` (post-synth) | WGC111 | Dangling resource reference (resourceRef target missing) | Before apply |
|
|
80
|
+
| `chant build` (post-synth) | WGC112 | Missing or invalid apiVersion on CRD | Before apply |
|
|
81
|
+
| `chant build` (post-synth) | WGC113 | Alpha API version (unstable, may break) | Before apply |
|
|
82
|
+
| `chant build` (post-synth) | WGC201 | Missing managed-by label | Before apply |
|
|
83
|
+
| `chant build` (post-synth) | WGC202 | Missing Workload Identity on GKE node pool | Before apply |
|
|
84
|
+
| `chant build` (post-synth) | WGC203 | Overly broad cloud-platform OAuth scope | Before apply |
|
|
85
|
+
| `chant build` (post-synth) | WGC204 | Missing shielded VM config on GKE nodes | Before apply |
|
|
86
|
+
| `chant build` (post-synth) | WGC301 | No audit logging configured on project | Before apply |
|
|
87
|
+
| `chant build` (post-synth) | WGC302 | Service API not enabled for resource type | Before apply |
|
|
88
|
+
| `chant build` (post-synth) | WGC303 | Missing VPC Service Controls perimeter | Before apply |
|
|
89
|
+
| `chant build` (post-synth) | WGC401 | Unknown spec field (typo or wrong CRD version) | Before apply |
|
|
90
|
+
| `chant build` (post-synth) | WGC402 | Missing required field in spec | Before apply |
|
|
91
|
+
| `chant build` (post-synth) | WGC403 | Type/structure mismatch (string vs object, etc.) | Before apply |
|
|
92
|
+
| `kubectl --dry-run=server` | — | CRD not installed, namespace missing, schema violations | Before apply |
|
|
45
93
|
|
|
46
94
|
## Applying to Kubernetes
|
|
47
95
|
|
|
48
96
|
```bash
|
|
49
|
-
# Build
|
|
97
|
+
# 1. Build
|
|
50
98
|
chant build src/ --output manifests.yaml
|
|
51
99
|
|
|
52
|
-
#
|
|
100
|
+
# 2. See what changed since last deploy (compares current build against last snapshot's digest)
|
|
101
|
+
chant state diff staging gcp
|
|
102
|
+
|
|
103
|
+
# 3. Diff against live cluster state
|
|
104
|
+
kubectl diff -f manifests.yaml
|
|
105
|
+
|
|
106
|
+
# 4. Dry run against API server
|
|
53
107
|
kubectl apply -f manifests.yaml --dry-run=server
|
|
54
108
|
|
|
55
|
-
# Apply
|
|
109
|
+
# 5. Apply
|
|
56
110
|
kubectl apply -f manifests.yaml
|
|
57
111
|
```
|
|
58
112
|
|
|
113
|
+
## Diffing and change preview
|
|
114
|
+
|
|
115
|
+
Use `kubectl diff` to see exactly what will change before applying:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
kubectl diff -f manifests.yaml
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
This compares your local manifests against the live cluster state. Exit code 0 means no changes; exit code 1 means differences exist. The output is a unified diff showing additions, removals, and modifications.
|
|
122
|
+
|
|
123
|
+
For chant-level diffing (comparing against the last snapshot rather than live state):
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
chant state diff staging gcp
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
This is faster (no cluster access needed) and works offline, but only reflects the last time you captured a snapshot.
|
|
130
|
+
|
|
59
131
|
## Resource reference patterns
|
|
60
132
|
|
|
61
133
|
Config Connector resources reference each other using `resourceRef`:
|
|
@@ -70,6 +142,19 @@ resourceRef:
|
|
|
70
142
|
external: projects/my-project/global/networks/my-network
|
|
71
143
|
```
|
|
72
144
|
|
|
145
|
+
Use in-namespace `name` references when both resources are in the same chant project and namespace. Use `external` references for pre-existing resources or cross-project dependencies.
|
|
146
|
+
|
|
147
|
+
### Common reference patterns
|
|
148
|
+
|
|
149
|
+
| Source resource | Target resource | Reference field |
|
|
150
|
+
|----------------|----------------|-----------------|
|
|
151
|
+
| ComputeSubnetwork | ComputeNetwork | `spec.networkRef` |
|
|
152
|
+
| ComputeFirewall | ComputeNetwork | `spec.networkRef` |
|
|
153
|
+
| SQLInstance | ComputeNetwork | `spec.settings.ipConfiguration.privateNetworkRef` |
|
|
154
|
+
| IAMPolicyMember | Any | `spec.resourceRef` |
|
|
155
|
+
| DNSRecordSet | DNSManagedZone | `spec.managedZoneRef` |
|
|
156
|
+
| ContainerNodePool | ContainerCluster | `spec.clusterRef` |
|
|
157
|
+
|
|
73
158
|
## Project binding
|
|
74
159
|
|
|
75
160
|
Bind resources to a GCP project via annotations:
|
|
@@ -88,21 +173,271 @@ export const annotations = defaultAnnotations({
|
|
|
88
173
|
});
|
|
89
174
|
```
|
|
90
175
|
|
|
91
|
-
|
|
176
|
+
### Folder and org binding
|
|
177
|
+
|
|
178
|
+
For organization-level resources, use the equivalent annotations:
|
|
179
|
+
|
|
180
|
+
```yaml
|
|
181
|
+
# Folder-scoped
|
|
182
|
+
cnrm.cloud.google.com/folder-id: "123456789"
|
|
183
|
+
|
|
184
|
+
# Organization-scoped
|
|
185
|
+
cnrm.cloud.google.com/organization-id: "987654321"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Composites reference
|
|
189
|
+
|
|
190
|
+
Composites group related Config Connector resources with secure defaults. Each returns an object containing the individual resources.
|
|
191
|
+
|
|
192
|
+
| Composite | Creates | Secure defaults |
|
|
193
|
+
|-----------|---------|-----------------|
|
|
194
|
+
| `GkeCluster` | ContainerCluster + ContainerNodePool | Workload Identity, shielded nodes, private cluster, VPC-native |
|
|
195
|
+
| `CloudRunServiceComposite` | RunService + IAMPolicyMember | No allUsers by default, concurrency limits, CPU throttling |
|
|
196
|
+
| `CloudSqlInstance` | SQLInstance + SQLDatabase + SQLUser | Private IP, backups enabled, deletion protection, SSL required |
|
|
197
|
+
| `GcsBucket` | StorageBucket | Uniform access, versioning, encryption, deletion policy |
|
|
198
|
+
| `VpcNetwork` | ComputeNetwork + ComputeSubnetwork(s) + ComputeFirewall(s) | Private Google Access, flow logs, no default 0.0.0.0/0 rule |
|
|
199
|
+
| `PubSubPipeline` | PubSubTopic + PubSubSubscription | Message retention, dead letter topic, ack deadline |
|
|
200
|
+
| `CloudFunctionWithTrigger` | CloudFunction + EventTrigger or HttpsTrigger | VPC connector, ingress settings, service account |
|
|
201
|
+
| `PrivateService` | ComputeGlobalAddress + ServiceNetworkingConnection | RFC 1918 range, automatic peering |
|
|
202
|
+
| `ManagedCertificate` | ComputeManagedSslCertificate | Auto-renewal via Google-managed cert |
|
|
203
|
+
| `SecureProject` | Project + IAMAuditConfig + essential Service resources | Audit logging, required APIs enabled, org policy constraints |
|
|
204
|
+
|
|
205
|
+
### Example: GKE cluster with secure defaults
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
import { GkeCluster } from "@intentius/chant-lexicon-gcp";
|
|
209
|
+
|
|
210
|
+
const { cluster, nodePool } = GkeCluster({
|
|
211
|
+
name: "prod-cluster",
|
|
212
|
+
location: "us-central1",
|
|
213
|
+
initialNodeCount: 3,
|
|
214
|
+
minNodeCount: 1,
|
|
215
|
+
maxNodeCount: 5,
|
|
216
|
+
machineType: "e2-standard-4",
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Example: Cloud SQL with private networking
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
import { CloudSqlInstance, PrivateService } from "@intentius/chant-lexicon-gcp";
|
|
224
|
+
|
|
225
|
+
const { globalAddress, connection } = PrivateService({
|
|
226
|
+
name: "sql-peering",
|
|
227
|
+
networkName: "default",
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
const { instance, database } = CloudSqlInstance({
|
|
231
|
+
name: "app-db",
|
|
232
|
+
databaseVersion: "POSTGRES_15",
|
|
233
|
+
tier: "db-custom-2-8192",
|
|
234
|
+
privateNetworkRef: { name: "default" },
|
|
235
|
+
});
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Deploy lifecycle
|
|
239
|
+
|
|
240
|
+
### 1. Build and validate
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
chant build src/ --output manifests.yaml
|
|
244
|
+
chant lint src/
|
|
245
|
+
kubectl apply -f manifests.yaml --dry-run=server
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### 2. Apply
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
kubectl apply -f manifests.yaml
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### 3. Wait for Ready
|
|
255
|
+
|
|
256
|
+
Config Connector resources reconcile asynchronously. Wait for the `Ready` condition:
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
# Watch all Config Connector resources
|
|
260
|
+
kubectl get gcp -w
|
|
261
|
+
|
|
262
|
+
# Wait for a specific resource
|
|
263
|
+
kubectl wait --for=condition=Ready sqldatabase/app-db --timeout=600s
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Most resources reconcile in 30-120 seconds. Cloud SQL instances can take 5-10 minutes. GKE clusters can take 10-20 minutes.
|
|
267
|
+
|
|
268
|
+
### 4. Verify
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
# Check all resource statuses
|
|
272
|
+
kubectl get gcp
|
|
273
|
+
|
|
274
|
+
# Detailed status for a specific resource
|
|
275
|
+
kubectl describe computeinstance/web-server
|
|
276
|
+
|
|
277
|
+
# Capture a snapshot for future diffing
|
|
278
|
+
chant state snapshot staging gcp
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### 5. Rollback
|
|
282
|
+
|
|
283
|
+
To roll back, revert the TypeScript source, rebuild, and reapply:
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
git checkout HEAD~1 -- src/
|
|
287
|
+
chant build src/ --output manifests.yaml
|
|
288
|
+
kubectl apply -f manifests.yaml
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
For emergency rollback of a single resource, delete it from the cluster. Config Connector will NOT delete the underlying GCP resource unless the deletion policy annotation is set to `abandon: false`:
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
# Check deletion policy first
|
|
295
|
+
kubectl get computeinstance/web-server -o jsonpath='{.metadata.annotations.cnrm\.cloud\.google\.com/deletion-policy}'
|
|
296
|
+
|
|
297
|
+
# If "abandon" (default), deleting the K8s object leaves the GCP resource intact
|
|
298
|
+
kubectl delete computeinstance/web-server
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
## Multi-project patterns
|
|
302
|
+
|
|
303
|
+
### Namespace-per-project
|
|
304
|
+
|
|
305
|
+
Create a Kubernetes namespace per GCP project, each with its own ConfigConnectorContext:
|
|
306
|
+
|
|
307
|
+
```yaml
|
|
308
|
+
apiVersion: core.cnrm.cloud.google.com/v1beta1
|
|
309
|
+
kind: ConfigConnectorContext
|
|
310
|
+
metadata:
|
|
311
|
+
name: configconnectorcontext.core.cnrm.cloud.google.com
|
|
312
|
+
namespace: project-a
|
|
313
|
+
spec:
|
|
314
|
+
googleServiceAccount: cnrm-sa@project-a.iam.gserviceaccount.com
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
Then target a namespace when applying:
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
kubectl apply -f manifests-project-a.yaml -n project-a
|
|
321
|
+
kubectl apply -f manifests-project-b.yaml -n project-b
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Cross-project references
|
|
325
|
+
|
|
326
|
+
Use `external` refs to reference resources in other projects:
|
|
327
|
+
|
|
328
|
+
```typescript
|
|
329
|
+
const subnet = new ComputeSubnetwork({
|
|
330
|
+
name: "app-subnet",
|
|
331
|
+
networkRef: {
|
|
332
|
+
external: "projects/shared-vpc-project/global/networks/shared-vpc",
|
|
333
|
+
},
|
|
334
|
+
});
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Shared VPC pattern
|
|
338
|
+
|
|
339
|
+
In a Shared VPC setup, the host project owns the VPC and the service projects consume subnets:
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
// In host project namespace
|
|
343
|
+
const { network, subnets } = VpcNetwork({
|
|
344
|
+
name: "shared-vpc",
|
|
345
|
+
subnets: [
|
|
346
|
+
{ name: "svc-a-subnet", cidr: "10.0.1.0/24", region: "us-central1" },
|
|
347
|
+
{ name: "svc-b-subnet", cidr: "10.0.2.0/24", region: "us-central1" },
|
|
348
|
+
],
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
// In service project namespace — reference by external
|
|
352
|
+
const instance = new ComputeInstance({
|
|
353
|
+
name: "app-vm",
|
|
354
|
+
subnetworkRef: {
|
|
355
|
+
external: "projects/host-project/regions/us-central1/subnetworks/svc-a-subnet",
|
|
356
|
+
},
|
|
357
|
+
});
|
|
358
|
+
```
|
|
92
359
|
|
|
93
|
-
|
|
94
|
-
|--------|---------|-----|
|
|
95
|
-
| UpToDate | Resource is in sync | None needed |
|
|
96
|
-
| UpdateFailed | GCP API error | Check `kubectl describe` events |
|
|
97
|
-
| DependencyNotReady | Waiting for referenced resource | Ensure dependency exists |
|
|
98
|
-
| DeletionFailed | Cannot delete GCP resource | Check IAM permissions |
|
|
360
|
+
## Troubleshooting decision tree
|
|
99
361
|
|
|
100
|
-
|
|
362
|
+
### Resource stuck in a non-Ready state
|
|
363
|
+
|
|
364
|
+
```
|
|
365
|
+
Is the resource status "UpToDate"?
|
|
366
|
+
YES -> Resource is reconciled. Done.
|
|
367
|
+
NO -> Check the status condition:
|
|
368
|
+
"UpdateFailed"
|
|
369
|
+
-> kubectl describe <resource> — read the Events section
|
|
370
|
+
-> Common causes:
|
|
371
|
+
- IAM permission denied -> Grant the missing role to the Config Connector SA
|
|
372
|
+
- Quota exceeded -> Request quota increase or reduce resource count
|
|
373
|
+
- Invalid field value -> Fix the TypeScript source and rebuild
|
|
374
|
+
"DependencyNotReady"
|
|
375
|
+
-> The resourceRef target hasn't reconciled yet
|
|
376
|
+
-> Check the referenced resource: kubectl get <target-kind>/<target-name>
|
|
377
|
+
-> If the target doesn't exist, add it to your chant source
|
|
378
|
+
"DeletionFailed"
|
|
379
|
+
-> Cannot delete the GCP resource
|
|
380
|
+
-> Check IAM permissions for deletion
|
|
381
|
+
-> Some resources (Cloud SQL, GKE) have deletion protection; disable it first
|
|
382
|
+
"Updating"
|
|
383
|
+
-> Resource is actively being updated. Wait.
|
|
384
|
+
-> If stuck for >10 min: kubectl describe to check for errors
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### Common error patterns
|
|
388
|
+
|
|
389
|
+
| Error message | Cause | Fix |
|
|
390
|
+
|--------------|-------|-----|
|
|
391
|
+
| `Permission denied on resource` | Config Connector SA lacks IAM role | `gcloud projects add-iam-policy-binding` |
|
|
392
|
+
| `Resource already exists` | Resource was created outside Config Connector | Use `cnrm.cloud.google.com/state-into-spec: absent` to adopt |
|
|
393
|
+
| `Quota exceeded` | Project quota limit reached | Request increase or adjust resource sizing |
|
|
394
|
+
| `Invalid value for field` | Spec value rejected by GCP API | Check field constraints in GCP docs |
|
|
395
|
+
| `The referenced resource does not exist` | Dangling resourceRef | Ensure the referenced resource is defined and in the same namespace or use `external` |
|
|
396
|
+
| `Namespace not found` | Target namespace doesn't exist | `kubectl create namespace <ns>` |
|
|
397
|
+
| `no matches for kind` | Config Connector CRD not installed | Install or update Config Connector |
|
|
398
|
+
| `alpha API version in use` | Using v1alpha1 CRD that may change | Pin to v1beta1 or v1 if available |
|
|
399
|
+
|
|
400
|
+
### Adopting existing resources
|
|
401
|
+
|
|
402
|
+
To bring a pre-existing GCP resource under Config Connector management:
|
|
403
|
+
|
|
404
|
+
```yaml
|
|
405
|
+
metadata:
|
|
406
|
+
annotations:
|
|
407
|
+
cnrm.cloud.google.com/state-into-spec: absent
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
This tells Config Connector to adopt the resource without overwriting its current settings.
|
|
411
|
+
|
|
412
|
+
## Quick reference commands
|
|
101
413
|
|
|
102
414
|
| Command | Description |
|
|
103
415
|
|---------|-------------|
|
|
104
|
-
| `chant build src/` | Synthesize manifests |
|
|
105
|
-
| `chant
|
|
106
|
-
| `
|
|
416
|
+
| `chant build src/` | Synthesize Config Connector manifests |
|
|
417
|
+
| `chant build src/ --output manifests.yaml` | Synthesize to a specific file |
|
|
418
|
+
| `chant lint src/` | Check for anti-patterns (pre-synth + post-synth) |
|
|
419
|
+
| `chant state diff staging gcp` | Compare current build against last snapshot |
|
|
420
|
+
| `chant state snapshot staging gcp` | Capture current cluster state |
|
|
421
|
+
| `kubectl apply -f manifests.yaml` | Apply manifests to cluster |
|
|
422
|
+
| `kubectl apply -f manifests.yaml --dry-run=server` | Validate against API server |
|
|
423
|
+
| `kubectl diff -f manifests.yaml` | Preview changes against live state |
|
|
107
424
|
| `kubectl get gcp` | List all Config Connector resources |
|
|
108
|
-
| `kubectl
|
|
425
|
+
| `kubectl get gcp -w` | Watch Config Connector resource status |
|
|
426
|
+
| `kubectl describe <kind>/<name>` | Detailed resource status and events |
|
|
427
|
+
| `kubectl wait --for=condition=Ready <kind>/<name> --timeout=300s` | Block until resource is ready |
|
|
428
|
+
| `kubectl delete <kind>/<name>` | Remove from cluster (deletion policy controls GCP resource) |
|
|
429
|
+
| `kubectl get configconnectorcontexts -A` | Check Config Connector health |
|
|
430
|
+
| `kubectl get pods -n cnrm-system` | Check Config Connector controller pods |
|
|
431
|
+
| `kubectl logs -n cnrm-system -l cnrm.cloud.google.com/component=cnrm-controller-manager` | Controller logs |
|
|
432
|
+
|
|
433
|
+
## Labels and annotations reference
|
|
434
|
+
|
|
435
|
+
| Annotation / Label | Purpose | Example |
|
|
436
|
+
|-------------------|---------|---------|
|
|
437
|
+
| `cnrm.cloud.google.com/project-id` | Bind resource to a GCP project | `my-project-id` |
|
|
438
|
+
| `cnrm.cloud.google.com/folder-id` | Bind to a folder | `123456789` |
|
|
439
|
+
| `cnrm.cloud.google.com/organization-id` | Bind to an org | `987654321` |
|
|
440
|
+
| `cnrm.cloud.google.com/deletion-policy` | Control GCP resource on K8s delete | `abandon` (default) or `delete` |
|
|
441
|
+
| `cnrm.cloud.google.com/state-into-spec` | Adopt existing resources | `absent` |
|
|
442
|
+
| `cnrm.cloud.google.com/force-conflicts` | Allow Config Connector to overwrite | `true` |
|
|
443
|
+
| `managed-by` label | Operational tracking (WGC201) | `chant` |
|