@intentius/chant-lexicon-k8s 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 +9 -4
- package/dist/manifest.json +1 -1
- package/dist/skills/chant-k8s-aks.md +146 -0
- package/{src/skills/kubernetes-patterns.md → dist/skills/chant-k8s-deployment-strategies.md} +1 -1
- package/dist/skills/chant-k8s-eks.md +156 -0
- package/dist/skills/chant-k8s-gke.md +246 -0
- package/{src/skills/kubernetes-security.md → dist/skills/chant-k8s-security.md} +1 -1
- package/dist/skills/chant-k8s.md +66 -3
- package/package.json +20 -2
- package/src/composites/adot-collector.ts +34 -22
- package/src/composites/agic-ingress.ts +14 -6
- package/src/composites/aks-external-dns-agent.ts +29 -18
- package/src/composites/alb-ingress.ts +14 -6
- package/src/composites/autoscaled-service.ts +25 -20
- package/src/composites/azure-disk-storage-class.ts +14 -6
- package/src/composites/azure-file-storage-class.ts +14 -6
- package/src/composites/azure-monitor-collector.ts +34 -22
- package/src/composites/batch-job.ts +25 -17
- package/src/composites/cockroachdb-cluster.ts +148 -58
- package/src/composites/composites.test.ts +369 -363
- package/src/composites/config-connector-context.ts +15 -8
- package/src/composites/configured-app.ts +21 -15
- package/src/composites/cron-workload.ts +25 -20
- package/src/composites/ebs-storage-class.ts +14 -6
- package/src/composites/efs-storage-class.ts +14 -6
- package/src/composites/external-dns-agent.ts +26 -20
- package/src/composites/filestore-storage-class.ts +14 -6
- package/src/composites/fluent-bit-agent.ts +30 -24
- package/src/composites/gce-ingress.ts +14 -6
- package/src/composites/gce-pd-storage-class.ts +14 -6
- package/src/composites/gke-external-dns-agent.ts +34 -21
- package/src/composites/gke-fluent-bit-agent.ts +34 -22
- package/src/composites/gke-gateway.ts +19 -12
- package/src/composites/gke-otel-collector.ts +34 -22
- package/src/composites/irsa-service-account.ts +22 -14
- package/src/composites/metrics-server.ts +41 -26
- package/src/composites/monitored-service.ts +26 -19
- package/src/composites/namespace-env.ts +26 -17
- package/src/composites/network-isolated-app.ts +21 -16
- package/src/composites/node-agent.ts +33 -22
- package/src/composites/secure-ingress.ts +19 -11
- package/src/composites/sidecar-app.ts +17 -12
- package/src/composites/stateful-app.ts +21 -12
- package/src/composites/web-app.ts +25 -21
- package/src/composites/worker-pool.ts +40 -26
- package/src/composites/workload-identity-sa.ts +22 -14
- package/src/composites/workload-identity-service-account.ts +22 -16
- package/src/plugin.ts +130 -614
- package/src/serializer.ts +3 -0
- package/src/skills/chant-k8s-deployment-strategies.md +183 -0
- package/src/skills/chant-k8s-gke.md +55 -0
- package/src/skills/chant-k8s-patterns.md +245 -0
- package/src/skills/chant-k8s-security.md +237 -0
- package/src/skills/chant-k8s.md +305 -0
package/dist/skills/chant-k8s.md
CHANGED
|
@@ -8,7 +8,7 @@ user-invocable: true
|
|
|
8
8
|
|
|
9
9
|
## How chant and Kubernetes relate
|
|
10
10
|
|
|
11
|
-
chant is a **synthesis
|
|
11
|
+
chant is a **synthesis compiler** — it compiles TypeScript source files into Kubernetes YAML manifests. `chant build` does not call the Kubernetes API; synthesis is pure and deterministic. The optional `chant state snapshot` command queries the Kubernetes API to capture deployment metadata (pod names, status, UIDs) for observability. Your job as an agent is to bridge synthesis and deployment:
|
|
12
12
|
|
|
13
13
|
- Use **chant** for: build, lint, diff (local YAML comparison)
|
|
14
14
|
- Use **kubectl / k8s API** for: apply, rollback, monitoring, troubleshooting
|
|
@@ -152,7 +152,7 @@ kubectl apply -f manifests.yaml --dry-run=client
|
|
|
152
152
|
|
|
153
153
|
Composites are higher-level functions that produce multiple coordinated K8s resources from a single call. They return plain prop objects — not class instances.
|
|
154
154
|
|
|
155
|
-
### Decision Tree
|
|
155
|
+
### Decision Tree — Core Composites
|
|
156
156
|
|
|
157
157
|
| Need | Composite | Resources |
|
|
158
158
|
|------|-----------|-----------|
|
|
@@ -169,6 +169,13 @@ Composites are higher-level functions that produce multiple coordinated K8s reso
|
|
|
169
169
|
| Namespace with quotas and isolation | **NamespaceEnv** | Namespace + ResourceQuota + LimitRange + NetworkPolicy |
|
|
170
170
|
| Per-node agent (custom) | **NodeAgent** | DaemonSet + RBAC + optional ConfigMap |
|
|
171
171
|
| Multi-host TLS Ingress (cert-manager) | **SecureIngress** | Ingress + optional Certificate |
|
|
172
|
+
| HPA metrics provider | **MetricsServer** | Deployment + Service + RBAC + APIService |
|
|
173
|
+
| CockroachDB cluster | **CockroachDbCluster** | StatefulSet + Services + PVCs + RBAC + optional CertificateRequests |
|
|
174
|
+
|
|
175
|
+
### Decision Tree — AWS (EKS) Composites
|
|
176
|
+
|
|
177
|
+
| Need | Composite | Resources |
|
|
178
|
+
|------|-----------|-----------|
|
|
172
179
|
| EKS IRSA ServiceAccount | **IrsaServiceAccount** | ServiceAccount + optional RBAC |
|
|
173
180
|
| AWS ALB Ingress | **AlbIngress** | Ingress with ALB annotations |
|
|
174
181
|
| EBS StorageClass | **EbsStorageClass** | StorageClass (ebs.csi.aws.com) |
|
|
@@ -177,6 +184,30 @@ Composites are higher-level functions that produce multiple coordinated K8s reso
|
|
|
177
184
|
| ExternalDNS for Route53 | **ExternalDnsAgent** | Deployment + IRSA SA + ClusterRole |
|
|
178
185
|
| ADOT for CloudWatch/X-Ray | **AdotCollector** | DaemonSet + RBAC + ConfigMap |
|
|
179
186
|
|
|
187
|
+
### Decision Tree — GCP (GKE) Composites
|
|
188
|
+
|
|
189
|
+
| Need | Composite | Resources |
|
|
190
|
+
|------|-----------|-----------|
|
|
191
|
+
| GKE Gateway API Ingress | **GkeGateway** | Gateway + HTTPRoute + optional HealthCheckPolicy |
|
|
192
|
+
| GKE Ingress (classic) | **GceIngress** | Ingress with GCE annotations + optional BackendConfig |
|
|
193
|
+
| GKE Workload Identity SA | **WorkloadIdentityServiceAccount** | ServiceAccount + optional RBAC (GCP IAM binding annotation) |
|
|
194
|
+
| GCE Persistent Disk StorageClass | **GcePdStorageClass** | StorageClass (pd.csi.storage.gke.io) |
|
|
195
|
+
| Filestore StorageClass | **FilestoreStorageClass** | StorageClass (filestore.csi.storage.gke.io) |
|
|
196
|
+
| GKE Fluent Bit agent | **GkeFluentBitAgent** | DaemonSet + RBAC + ConfigMap (Cloud Logging) |
|
|
197
|
+
| GKE ExternalDNS agent | **GkeExternalDnsAgent** | Deployment + WI SA + ClusterRole (Cloud DNS) |
|
|
198
|
+
| GKE OpenTelemetry Collector | **GkeOtelCollector** | DaemonSet + RBAC + ConfigMap (Cloud Trace/Monitoring) |
|
|
199
|
+
| Config Connector context | **ConfigConnectorContext** | ConfigConnectorContext + Namespace + RBAC |
|
|
200
|
+
|
|
201
|
+
### Decision Tree — Azure (AKS) Composites
|
|
202
|
+
|
|
203
|
+
| Need | Composite | Resources |
|
|
204
|
+
|------|-----------|-----------|
|
|
205
|
+
| AKS AGIC Ingress | **AgicIngress** | Ingress with AGIC annotations + optional BackendConfig |
|
|
206
|
+
| Azure Disk StorageClass | **AzureDiskStorageClass** | StorageClass (disk.csi.azure.com) |
|
|
207
|
+
| Azure File StorageClass | **AzureFileStorageClass** | StorageClass (file.csi.azure.com) |
|
|
208
|
+
| AKS ExternalDNS agent | **AksExternalDnsAgent** | Deployment + WI SA + ClusterRole (Azure DNS) |
|
|
209
|
+
| Azure Monitor Collector | **AzureMonitorCollector** | DaemonSet + RBAC + ConfigMap (Azure Monitor) |
|
|
210
|
+
|
|
180
211
|
### Hardening options (available on Deployment-based composites)
|
|
181
212
|
|
|
182
213
|
- `minAvailable` — creates a PodDisruptionBudget (WebApp, StatefulApp, WorkerPool; AutoscaledService always has one)
|
|
@@ -199,14 +230,46 @@ Composites are higher-level functions that produce multiple coordinated K8s reso
|
|
|
199
230
|
| Pod stuck in Pending | Insufficient CPU/memory on nodes | Scale up cluster or reduce resource requests |
|
|
200
231
|
| Pod stuck in Pending | PVC not bound | Check StorageClass exists, PV available |
|
|
201
232
|
| Pod stuck in Pending | Node selector/affinity mismatch | Verify node labels match selectors |
|
|
233
|
+
| Pod stuck in Pending | Too many pods on node | Check `kubectl describe node` for Allocatable vs Allocated |
|
|
202
234
|
| Pod stuck in ContainerCreating | ConfigMap/Secret not found | Ensure referenced ConfigMaps/Secrets exist |
|
|
235
|
+
| Pod stuck in ContainerCreating | Volume mount timeout | Check CSI driver logs, storage provider status |
|
|
203
236
|
| Service returns 503 | No ready endpoints | Check pod readiness probes, selector match |
|
|
237
|
+
| Service returns 503 | Endpoints exist but pod failing probes | Increase `initialDelaySeconds`, check probe path |
|
|
204
238
|
| Ingress returns 404 | Backend service not found | Check Ingress rules, service name/port |
|
|
205
|
-
|
|
|
239
|
+
| Ingress returns 502 | Backend pods not ready | Check pod readiness, container port matches Service targetPort |
|
|
240
|
+
| HPA not scaling | Metrics server not installed | Install metrics-server or MetricsServer composite |
|
|
206
241
|
| HPA not scaling | Resource requests not set | Add CPU/memory requests to containers |
|
|
242
|
+
| HPA stuck at max | Target utilization too low | Raise `targetCPUUtilizationPercentage`, add nodes |
|
|
207
243
|
| CronJob not running | Invalid cron expression | Validate cron syntax (5-field format) |
|
|
244
|
+
| CronJob not running | `concurrencyPolicy: Forbid` with long jobs | Increase job deadline or switch to `Replace` |
|
|
208
245
|
| NetworkPolicy blocking | Default deny applied | Add explicit allow rules for required traffic |
|
|
209
246
|
| RBAC permission denied | Missing Role/RoleBinding | Check ServiceAccount bindings and verb permissions |
|
|
247
|
+
| RBAC permission denied | ClusterRole vs namespaced Role | Use ClusterRoleBinding for cluster-scoped resources |
|
|
248
|
+
| PDB preventing eviction | minAvailable too high | Lower minAvailable or increase replicas |
|
|
249
|
+
| StatefulSet stuck on update | Pod ordinal blocked | Check PVC status for ordinal, delete stuck pod |
|
|
250
|
+
|
|
251
|
+
## Troubleshooting decision tree
|
|
252
|
+
|
|
253
|
+
```
|
|
254
|
+
Pod not running?
|
|
255
|
+
├─ Pending
|
|
256
|
+
│ ├─ "Insufficient cpu/memory" → scale cluster or lower requests
|
|
257
|
+
│ ├─ "no nodes match" → fix nodeSelector / tolerations
|
|
258
|
+
│ └─ "unbound PVC" → check StorageClass, provision PV
|
|
259
|
+
├─ ContainerCreating
|
|
260
|
+
│ ├─ "secret not found" → create missing Secret
|
|
261
|
+
│ └─ "timeout waiting for volume" → check CSI driver
|
|
262
|
+
├─ CrashLoopBackOff
|
|
263
|
+
│ ├─ OOMKilled → increase memory limit
|
|
264
|
+
│ ├─ exit code 1 → check app logs (`kubectl logs --previous`)
|
|
265
|
+
│ └─ exit code 137 → SIGKILL — liveness probe too aggressive
|
|
266
|
+
├─ ImagePullBackOff
|
|
267
|
+
│ ├─ 401 Unauthorized → check imagePullSecrets
|
|
268
|
+
│ └─ manifest unknown → verify image:tag exists in registry
|
|
269
|
+
└─ Running but not Ready
|
|
270
|
+
├─ readinessProbe failing → check probe path/port
|
|
271
|
+
└─ startup probe failing → increase `failureThreshold * periodSeconds`
|
|
272
|
+
```
|
|
210
273
|
|
|
211
274
|
## Quick reference
|
|
212
275
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-k8s",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.24",
|
|
4
|
+
"description": "Kubernetes lexicon for chant — declarative IaC in TypeScript",
|
|
4
5
|
"license": "Apache-2.0",
|
|
6
|
+
"homepage": "https://intentius.io/chant",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/intentius/chant.git",
|
|
10
|
+
"directory": "lexicons/k8s"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/intentius/chant/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"infrastructure-as-code",
|
|
17
|
+
"iac",
|
|
18
|
+
"typescript",
|
|
19
|
+
"kubernetes",
|
|
20
|
+
"k8s",
|
|
21
|
+
"chant"
|
|
22
|
+
],
|
|
5
23
|
"type": "module",
|
|
6
24
|
"files": [
|
|
7
25
|
"src/",
|
|
@@ -25,7 +43,7 @@
|
|
|
25
43
|
"prepack": "bun run generate && bun run bundle && bun run validate"
|
|
26
44
|
},
|
|
27
45
|
"dependencies": {
|
|
28
|
-
"@intentius/chant": "0.0.
|
|
46
|
+
"@intentius/chant": "0.0.22"
|
|
29
47
|
},
|
|
30
48
|
"devDependencies": {
|
|
31
49
|
"typescript": "^5.9.3"
|
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
* with pre-configured pipelines for AWS observability.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import { Composite, mergeDefaults } from "@intentius/chant";
|
|
9
|
+
import { DaemonSet, ServiceAccount, ClusterRole, ClusterRoleBinding, ConfigMap } from "../generated";
|
|
10
|
+
|
|
8
11
|
export interface AdotCollectorProps {
|
|
9
12
|
/** AWS region. */
|
|
10
13
|
region: string;
|
|
@@ -30,14 +33,22 @@ export interface AdotCollectorProps {
|
|
|
30
33
|
memoryLimit?: string;
|
|
31
34
|
/** IAM Role ARN for IRSA (adds eks.amazonaws.com/role-arn annotation to ServiceAccount). */
|
|
32
35
|
iamRoleArn?: string;
|
|
36
|
+
/** Per-member defaults for fine-grained overrides. */
|
|
37
|
+
defaults?: {
|
|
38
|
+
daemonSet?: Partial<Record<string, unknown>>;
|
|
39
|
+
serviceAccount?: Partial<Record<string, unknown>>;
|
|
40
|
+
clusterRole?: Partial<Record<string, unknown>>;
|
|
41
|
+
clusterRoleBinding?: Partial<Record<string, unknown>>;
|
|
42
|
+
configMap?: Partial<Record<string, unknown>>;
|
|
43
|
+
};
|
|
33
44
|
}
|
|
34
45
|
|
|
35
46
|
export interface AdotCollectorResult {
|
|
36
|
-
daemonSet:
|
|
37
|
-
serviceAccount:
|
|
38
|
-
clusterRole:
|
|
39
|
-
clusterRoleBinding:
|
|
40
|
-
configMap:
|
|
47
|
+
daemonSet: InstanceType<typeof DaemonSet>;
|
|
48
|
+
serviceAccount: InstanceType<typeof ServiceAccount>;
|
|
49
|
+
clusterRole: InstanceType<typeof ClusterRole>;
|
|
50
|
+
clusterRoleBinding: InstanceType<typeof ClusterRoleBinding>;
|
|
51
|
+
configMap: InstanceType<typeof ConfigMap>;
|
|
41
52
|
}
|
|
42
53
|
|
|
43
54
|
/**
|
|
@@ -56,7 +67,7 @@ export interface AdotCollectorResult {
|
|
|
56
67
|
* });
|
|
57
68
|
* ```
|
|
58
69
|
*/
|
|
59
|
-
export
|
|
70
|
+
export const AdotCollector = Composite<AdotCollectorProps>((props) => {
|
|
60
71
|
const {
|
|
61
72
|
region,
|
|
62
73
|
clusterName,
|
|
@@ -70,6 +81,7 @@ export function AdotCollector(props: AdotCollectorProps): AdotCollectorResult {
|
|
|
70
81
|
cpuLimit = "500m",
|
|
71
82
|
memoryLimit = "512Mi",
|
|
72
83
|
iamRoleArn,
|
|
84
|
+
defaults: defs,
|
|
73
85
|
} = props;
|
|
74
86
|
|
|
75
87
|
const saName = `${name}-sa`;
|
|
@@ -159,7 +171,7 @@ service:
|
|
|
159
171
|
},
|
|
160
172
|
};
|
|
161
173
|
|
|
162
|
-
const
|
|
174
|
+
const daemonSet = new DaemonSet(mergeDefaults({
|
|
163
175
|
metadata: {
|
|
164
176
|
name,
|
|
165
177
|
namespace,
|
|
@@ -179,18 +191,18 @@ service:
|
|
|
179
191
|
},
|
|
180
192
|
},
|
|
181
193
|
},
|
|
182
|
-
};
|
|
194
|
+
}, defs?.daemonSet));
|
|
183
195
|
|
|
184
|
-
const
|
|
196
|
+
const serviceAccount = new ServiceAccount(mergeDefaults({
|
|
185
197
|
metadata: {
|
|
186
198
|
name: saName,
|
|
187
199
|
namespace,
|
|
188
200
|
labels: { ...commonLabels, "app.kubernetes.io/component": "agent" },
|
|
189
201
|
...(iamRoleArn ? { annotations: { "eks.amazonaws.com/role-arn": iamRoleArn } } : {}),
|
|
190
202
|
},
|
|
191
|
-
};
|
|
203
|
+
}, defs?.serviceAccount));
|
|
192
204
|
|
|
193
|
-
const
|
|
205
|
+
const clusterRole = new ClusterRole(mergeDefaults({
|
|
194
206
|
metadata: {
|
|
195
207
|
name: clusterRoleName,
|
|
196
208
|
labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
|
|
@@ -203,9 +215,9 @@ service:
|
|
|
203
215
|
{ apiGroups: [""], resources: ["nodes/stats", "configmaps", "events"], verbs: ["create", "get"] },
|
|
204
216
|
{ apiGroups: [""], resources: ["configmaps"], verbs: ["get", "update", "create"], resourceNames: ["otel-container-insight-clusterleader"] },
|
|
205
217
|
],
|
|
206
|
-
};
|
|
218
|
+
}, defs?.clusterRole));
|
|
207
219
|
|
|
208
|
-
const
|
|
220
|
+
const clusterRoleBinding = new ClusterRoleBinding(mergeDefaults({
|
|
209
221
|
metadata: {
|
|
210
222
|
name: bindingName,
|
|
211
223
|
labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
|
|
@@ -222,9 +234,9 @@ service:
|
|
|
222
234
|
namespace,
|
|
223
235
|
},
|
|
224
236
|
],
|
|
225
|
-
};
|
|
237
|
+
}, defs?.clusterRoleBinding));
|
|
226
238
|
|
|
227
|
-
const
|
|
239
|
+
const configMap = new ConfigMap(mergeDefaults({
|
|
228
240
|
metadata: {
|
|
229
241
|
name: configMapName,
|
|
230
242
|
namespace,
|
|
@@ -233,13 +245,13 @@ service:
|
|
|
233
245
|
data: {
|
|
234
246
|
"config.yaml": adotConfig,
|
|
235
247
|
},
|
|
236
|
-
};
|
|
248
|
+
}, defs?.configMap));
|
|
237
249
|
|
|
238
250
|
return {
|
|
239
|
-
daemonSet
|
|
240
|
-
serviceAccount
|
|
241
|
-
clusterRole
|
|
242
|
-
clusterRoleBinding
|
|
243
|
-
configMap
|
|
251
|
+
daemonSet,
|
|
252
|
+
serviceAccount,
|
|
253
|
+
clusterRole,
|
|
254
|
+
clusterRoleBinding,
|
|
255
|
+
configMap,
|
|
244
256
|
};
|
|
245
|
-
}
|
|
257
|
+
}, "AdotCollector");
|
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
* WAF policy, backend path prefix, and cookie-based affinity.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import { Composite, mergeDefaults } from "@intentius/chant";
|
|
9
|
+
import { Ingress } from "../generated";
|
|
10
|
+
|
|
8
11
|
export interface AgicIngressHost {
|
|
9
12
|
/** Hostname (e.g., "api.example.com"). */
|
|
10
13
|
hostname: string;
|
|
@@ -40,10 +43,14 @@ export interface AgicIngressProps {
|
|
|
40
43
|
labels?: Record<string, string>;
|
|
41
44
|
/** Namespace for all resources. */
|
|
42
45
|
namespace?: string;
|
|
46
|
+
/** Per-member defaults for fine-grained overrides. */
|
|
47
|
+
defaults?: {
|
|
48
|
+
ingress?: Partial<Record<string, unknown>>;
|
|
49
|
+
};
|
|
43
50
|
}
|
|
44
51
|
|
|
45
52
|
export interface AgicIngressResult {
|
|
46
|
-
ingress:
|
|
53
|
+
ingress: InstanceType<typeof Ingress>;
|
|
47
54
|
}
|
|
48
55
|
|
|
49
56
|
/**
|
|
@@ -68,7 +75,7 @@ export interface AgicIngressResult {
|
|
|
68
75
|
* });
|
|
69
76
|
* ```
|
|
70
77
|
*/
|
|
71
|
-
export
|
|
78
|
+
export const AgicIngress = Composite<AgicIngressProps>((props) => {
|
|
72
79
|
const {
|
|
73
80
|
name,
|
|
74
81
|
hosts,
|
|
@@ -81,6 +88,7 @@ export function AgicIngress(props: AgicIngressProps): AgicIngressResult {
|
|
|
81
88
|
annotations: extraAnnotations = {},
|
|
82
89
|
labels: extraLabels = {},
|
|
83
90
|
namespace,
|
|
91
|
+
defaults: defs,
|
|
84
92
|
} = props;
|
|
85
93
|
|
|
86
94
|
const commonLabels: Record<string, string> = {
|
|
@@ -132,7 +140,7 @@ export function AgicIngress(props: AgicIngressProps): AgicIngressResult {
|
|
|
132
140
|
},
|
|
133
141
|
}));
|
|
134
142
|
|
|
135
|
-
const
|
|
143
|
+
const ingress = new Ingress(mergeDefaults({
|
|
136
144
|
metadata: {
|
|
137
145
|
name,
|
|
138
146
|
...(namespace && { namespace }),
|
|
@@ -142,7 +150,7 @@ export function AgicIngress(props: AgicIngressProps): AgicIngressResult {
|
|
|
142
150
|
spec: {
|
|
143
151
|
rules: ingressRules,
|
|
144
152
|
},
|
|
145
|
-
};
|
|
153
|
+
}, defs?.ingress));
|
|
146
154
|
|
|
147
|
-
return { ingress
|
|
148
|
-
}
|
|
155
|
+
return { ingress };
|
|
156
|
+
}, "AgicIngress");
|
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
* instead of IRSA for Azure DNS management.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import { Composite, mergeDefaults } from "@intentius/chant";
|
|
9
|
+
import { Deployment, ServiceAccount, ClusterRole, ClusterRoleBinding } from "../generated";
|
|
10
|
+
|
|
8
11
|
export interface AksExternalDnsAgentProps {
|
|
9
12
|
/** Azure managed identity client ID for Workload Identity. */
|
|
10
13
|
clientId: string;
|
|
@@ -28,13 +31,20 @@ export interface AksExternalDnsAgentProps {
|
|
|
28
31
|
namespace?: string;
|
|
29
32
|
/** Additional labels. */
|
|
30
33
|
labels?: Record<string, string>;
|
|
34
|
+
/** Per-member defaults for fine-grained overrides. */
|
|
35
|
+
defaults?: {
|
|
36
|
+
deployment?: Partial<Record<string, unknown>>;
|
|
37
|
+
serviceAccount?: Partial<Record<string, unknown>>;
|
|
38
|
+
clusterRole?: Partial<Record<string, unknown>>;
|
|
39
|
+
clusterRoleBinding?: Partial<Record<string, unknown>>;
|
|
40
|
+
};
|
|
31
41
|
}
|
|
32
42
|
|
|
33
43
|
export interface AksExternalDnsAgentResult {
|
|
34
|
-
deployment:
|
|
35
|
-
serviceAccount:
|
|
36
|
-
clusterRole:
|
|
37
|
-
clusterRoleBinding:
|
|
44
|
+
deployment: InstanceType<typeof Deployment>;
|
|
45
|
+
serviceAccount: InstanceType<typeof ServiceAccount>;
|
|
46
|
+
clusterRole: InstanceType<typeof ClusterRole>;
|
|
47
|
+
clusterRoleBinding: InstanceType<typeof ClusterRoleBinding>;
|
|
38
48
|
}
|
|
39
49
|
|
|
40
50
|
/**
|
|
@@ -56,7 +66,7 @@ export interface AksExternalDnsAgentResult {
|
|
|
56
66
|
* });
|
|
57
67
|
* ```
|
|
58
68
|
*/
|
|
59
|
-
export
|
|
69
|
+
export const AksExternalDnsAgent = Composite<AksExternalDnsAgentProps>((props) => {
|
|
60
70
|
const {
|
|
61
71
|
clientId,
|
|
62
72
|
resourceGroup,
|
|
@@ -69,6 +79,7 @@ export function AksExternalDnsAgent(props: AksExternalDnsAgentProps): AksExterna
|
|
|
69
79
|
image = "registry.k8s.io/external-dns/external-dns:v0.14.0",
|
|
70
80
|
namespace = "kube-system",
|
|
71
81
|
labels: extraLabels = {},
|
|
82
|
+
defaults: defs,
|
|
72
83
|
} = props;
|
|
73
84
|
|
|
74
85
|
const saName = `${name}-sa`;
|
|
@@ -98,7 +109,7 @@ export function AksExternalDnsAgent(props: AksExternalDnsAgentProps): AksExterna
|
|
|
98
109
|
args.push(`--txt-owner-id=${txtOwnerId}`);
|
|
99
110
|
}
|
|
100
111
|
|
|
101
|
-
const
|
|
112
|
+
const deployment = new Deployment(mergeDefaults({
|
|
102
113
|
metadata: {
|
|
103
114
|
name,
|
|
104
115
|
namespace,
|
|
@@ -142,9 +153,9 @@ export function AksExternalDnsAgent(props: AksExternalDnsAgentProps): AksExterna
|
|
|
142
153
|
},
|
|
143
154
|
},
|
|
144
155
|
},
|
|
145
|
-
};
|
|
156
|
+
}, defs?.deployment));
|
|
146
157
|
|
|
147
|
-
const
|
|
158
|
+
const serviceAccount = new ServiceAccount(mergeDefaults({
|
|
148
159
|
metadata: {
|
|
149
160
|
name: saName,
|
|
150
161
|
namespace,
|
|
@@ -157,9 +168,9 @@ export function AksExternalDnsAgent(props: AksExternalDnsAgentProps): AksExterna
|
|
|
157
168
|
"azure.workload.identity/client-id": clientId,
|
|
158
169
|
},
|
|
159
170
|
},
|
|
160
|
-
};
|
|
171
|
+
}, defs?.serviceAccount));
|
|
161
172
|
|
|
162
|
-
const
|
|
173
|
+
const clusterRole = new ClusterRole(mergeDefaults({
|
|
163
174
|
metadata: {
|
|
164
175
|
name: clusterRoleName,
|
|
165
176
|
labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
|
|
@@ -169,9 +180,9 @@ export function AksExternalDnsAgent(props: AksExternalDnsAgentProps): AksExterna
|
|
|
169
180
|
{ apiGroups: ["extensions", "networking.k8s.io"], resources: ["ingresses"], verbs: ["get", "watch", "list"] },
|
|
170
181
|
{ apiGroups: [""], resources: ["nodes"], verbs: ["list", "watch"] },
|
|
171
182
|
],
|
|
172
|
-
};
|
|
183
|
+
}, defs?.clusterRole));
|
|
173
184
|
|
|
174
|
-
const
|
|
185
|
+
const clusterRoleBinding = new ClusterRoleBinding(mergeDefaults({
|
|
175
186
|
metadata: {
|
|
176
187
|
name: bindingName,
|
|
177
188
|
labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
|
|
@@ -188,12 +199,12 @@ export function AksExternalDnsAgent(props: AksExternalDnsAgentProps): AksExterna
|
|
|
188
199
|
namespace,
|
|
189
200
|
},
|
|
190
201
|
],
|
|
191
|
-
};
|
|
202
|
+
}, defs?.clusterRoleBinding));
|
|
192
203
|
|
|
193
204
|
return {
|
|
194
|
-
deployment
|
|
195
|
-
serviceAccount
|
|
196
|
-
clusterRole
|
|
197
|
-
clusterRoleBinding
|
|
205
|
+
deployment,
|
|
206
|
+
serviceAccount,
|
|
207
|
+
clusterRole,
|
|
208
|
+
clusterRoleBinding,
|
|
198
209
|
};
|
|
199
|
-
}
|
|
210
|
+
}, "AksExternalDnsAgent");
|
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
* (shared ALB), SSL redirect, subnets, security groups.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import { Composite, mergeDefaults } from "@intentius/chant";
|
|
9
|
+
import { Ingress } from "../generated";
|
|
10
|
+
|
|
8
11
|
export interface AlbIngressHost {
|
|
9
12
|
/** Hostname (e.g., "api.example.com"). */
|
|
10
13
|
hostname: string;
|
|
@@ -43,10 +46,14 @@ export interface AlbIngressProps {
|
|
|
43
46
|
labels?: Record<string, string>;
|
|
44
47
|
/** Namespace for all resources. */
|
|
45
48
|
namespace?: string;
|
|
49
|
+
/** Per-member defaults for fine-grained overrides. */
|
|
50
|
+
defaults?: {
|
|
51
|
+
ingress?: Partial<Record<string, unknown>>;
|
|
52
|
+
};
|
|
46
53
|
}
|
|
47
54
|
|
|
48
55
|
export interface AlbIngressResult {
|
|
49
|
-
ingress:
|
|
56
|
+
ingress: InstanceType<typeof Ingress>;
|
|
50
57
|
}
|
|
51
58
|
|
|
52
59
|
/**
|
|
@@ -72,7 +79,7 @@ export interface AlbIngressResult {
|
|
|
72
79
|
* });
|
|
73
80
|
* ```
|
|
74
81
|
*/
|
|
75
|
-
export
|
|
82
|
+
export const AlbIngress = Composite<AlbIngressProps>((props) => {
|
|
76
83
|
const {
|
|
77
84
|
name,
|
|
78
85
|
hosts,
|
|
@@ -86,6 +93,7 @@ export function AlbIngress(props: AlbIngressProps): AlbIngressResult {
|
|
|
86
93
|
annotations: extraAnnotations = {},
|
|
87
94
|
labels: extraLabels = {},
|
|
88
95
|
namespace,
|
|
96
|
+
defaults: defs,
|
|
89
97
|
} = props;
|
|
90
98
|
|
|
91
99
|
const commonLabels: Record<string, string> = {
|
|
@@ -135,7 +143,7 @@ export function AlbIngress(props: AlbIngressProps): AlbIngressResult {
|
|
|
135
143
|
},
|
|
136
144
|
}));
|
|
137
145
|
|
|
138
|
-
const
|
|
146
|
+
const ingress = new Ingress(mergeDefaults({
|
|
139
147
|
metadata: {
|
|
140
148
|
name,
|
|
141
149
|
...(namespace && { namespace }),
|
|
@@ -146,7 +154,7 @@ export function AlbIngress(props: AlbIngressProps): AlbIngressResult {
|
|
|
146
154
|
ingressClassName: "alb",
|
|
147
155
|
rules: ingressRules,
|
|
148
156
|
},
|
|
149
|
-
};
|
|
157
|
+
}, defs?.ingress));
|
|
150
158
|
|
|
151
|
-
return { ingress
|
|
152
|
-
}
|
|
159
|
+
return { ingress };
|
|
160
|
+
}, "AlbIngress");
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* PDB selectors match pod labels, and resource requests are set.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { Composite, mergeDefaults } from "@intentius/chant";
|
|
10
|
+
import { Deployment, Service, HorizontalPodAutoscaler, PodDisruptionBudget } from "../generated";
|
|
9
11
|
import type { ContainerSecurityContext } from "./security-context";
|
|
10
12
|
|
|
11
13
|
export interface AutoscaledServiceProps {
|
|
@@ -69,13 +71,20 @@ export interface AutoscaledServiceProps {
|
|
|
69
71
|
volumeMounts?: Array<Record<string, unknown>>;
|
|
70
72
|
/** Convenience: auto-generate emptyDir volumes + mounts for writable temp dirs (e.g. ["/tmp", "/var/cache/nginx"]). */
|
|
71
73
|
tmpDirs?: string[];
|
|
74
|
+
/** Per-member defaults for fine-grained overrides. */
|
|
75
|
+
defaults?: {
|
|
76
|
+
deployment?: Partial<Record<string, unknown>>;
|
|
77
|
+
service?: Partial<Record<string, unknown>>;
|
|
78
|
+
hpa?: Partial<Record<string, unknown>>;
|
|
79
|
+
pdb?: Partial<Record<string, unknown>>;
|
|
80
|
+
};
|
|
72
81
|
}
|
|
73
82
|
|
|
74
83
|
export interface AutoscaledServiceResult {
|
|
75
|
-
deployment:
|
|
76
|
-
service:
|
|
77
|
-
hpa:
|
|
78
|
-
pdb:
|
|
84
|
+
deployment: InstanceType<typeof Deployment>;
|
|
85
|
+
service: InstanceType<typeof Service>;
|
|
86
|
+
hpa: InstanceType<typeof HorizontalPodAutoscaler>;
|
|
87
|
+
pdb: InstanceType<typeof PodDisruptionBudget>;
|
|
79
88
|
}
|
|
80
89
|
|
|
81
90
|
/**
|
|
@@ -95,7 +104,7 @@ export interface AutoscaledServiceResult {
|
|
|
95
104
|
* });
|
|
96
105
|
* ```
|
|
97
106
|
*/
|
|
98
|
-
export
|
|
107
|
+
export const AutoscaledService = Composite<AutoscaledServiceProps>((props) => {
|
|
99
108
|
const {
|
|
100
109
|
name,
|
|
101
110
|
image,
|
|
@@ -123,6 +132,7 @@ export function AutoscaledService(props: AutoscaledServiceProps): AutoscaledServ
|
|
|
123
132
|
volumes: explicitVolumes = [],
|
|
124
133
|
volumeMounts: explicitMounts = [],
|
|
125
134
|
tmpDirs = [],
|
|
135
|
+
defaults: defs,
|
|
126
136
|
} = props;
|
|
127
137
|
|
|
128
138
|
const commonLabels: Record<string, string> = {
|
|
@@ -164,7 +174,7 @@ export function AutoscaledService(props: AutoscaledServiceProps): AutoscaledServ
|
|
|
164
174
|
: {}),
|
|
165
175
|
};
|
|
166
176
|
|
|
167
|
-
const
|
|
177
|
+
const deployment = new Deployment(mergeDefaults({
|
|
168
178
|
metadata: {
|
|
169
179
|
name,
|
|
170
180
|
...(namespace && { namespace }),
|
|
@@ -213,9 +223,9 @@ export function AutoscaledService(props: AutoscaledServiceProps): AutoscaledServ
|
|
|
213
223
|
},
|
|
214
224
|
},
|
|
215
225
|
},
|
|
216
|
-
};
|
|
226
|
+
}, defs?.deployment));
|
|
217
227
|
|
|
218
|
-
const
|
|
228
|
+
const service = new Service(mergeDefaults({
|
|
219
229
|
metadata: {
|
|
220
230
|
name,
|
|
221
231
|
...(namespace && { namespace }),
|
|
@@ -226,7 +236,7 @@ export function AutoscaledService(props: AutoscaledServiceProps): AutoscaledServ
|
|
|
226
236
|
ports: [{ port: 80, targetPort: port, protocol: "TCP", name: "http" }],
|
|
227
237
|
type: "ClusterIP",
|
|
228
238
|
},
|
|
229
|
-
};
|
|
239
|
+
}, defs?.service));
|
|
230
240
|
|
|
231
241
|
const metrics: Array<Record<string, unknown>> = [
|
|
232
242
|
{
|
|
@@ -248,7 +258,7 @@ export function AutoscaledService(props: AutoscaledServiceProps): AutoscaledServ
|
|
|
248
258
|
});
|
|
249
259
|
}
|
|
250
260
|
|
|
251
|
-
const
|
|
261
|
+
const hpa = new HorizontalPodAutoscaler(mergeDefaults({
|
|
252
262
|
metadata: {
|
|
253
263
|
name,
|
|
254
264
|
...(namespace && { namespace }),
|
|
@@ -264,9 +274,9 @@ export function AutoscaledService(props: AutoscaledServiceProps): AutoscaledServ
|
|
|
264
274
|
maxReplicas,
|
|
265
275
|
metrics,
|
|
266
276
|
},
|
|
267
|
-
};
|
|
277
|
+
}, defs?.hpa));
|
|
268
278
|
|
|
269
|
-
const
|
|
279
|
+
const pdb = new PodDisruptionBudget(mergeDefaults({
|
|
270
280
|
metadata: {
|
|
271
281
|
name,
|
|
272
282
|
...(namespace && { namespace }),
|
|
@@ -276,12 +286,7 @@ export function AutoscaledService(props: AutoscaledServiceProps): AutoscaledServ
|
|
|
276
286
|
minAvailable,
|
|
277
287
|
selector: { matchLabels: { "app.kubernetes.io/name": name } },
|
|
278
288
|
},
|
|
279
|
-
};
|
|
289
|
+
}, defs?.pdb));
|
|
280
290
|
|
|
281
|
-
return {
|
|
282
|
-
|
|
283
|
-
service: serviceProps,
|
|
284
|
-
hpa: hpaProps,
|
|
285
|
-
pdb: pdbProps,
|
|
286
|
-
};
|
|
287
|
-
}
|
|
291
|
+
return { deployment, service, hpa, pdb };
|
|
292
|
+
}, "AutoscaledService");
|