@intentius/chant-lexicon-k8s 0.0.22 → 0.1.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.
Files changed (54) hide show
  1. package/dist/integrity.json +9 -4
  2. package/dist/manifest.json +1 -1
  3. package/dist/skills/chant-k8s-aks.md +146 -0
  4. package/{src/skills/kubernetes-patterns.md → dist/skills/chant-k8s-deployment-strategies.md} +1 -1
  5. package/dist/skills/chant-k8s-eks.md +156 -0
  6. package/dist/skills/chant-k8s-gke.md +246 -0
  7. package/{src/skills/kubernetes-security.md → dist/skills/chant-k8s-security.md} +1 -1
  8. package/dist/skills/chant-k8s.md +65 -2
  9. package/package.json +5 -4
  10. package/src/composites/adot-collector.ts +34 -22
  11. package/src/composites/agic-ingress.ts +14 -6
  12. package/src/composites/aks-external-dns-agent.ts +29 -18
  13. package/src/composites/alb-ingress.ts +14 -6
  14. package/src/composites/autoscaled-service.ts +25 -20
  15. package/src/composites/azure-disk-storage-class.ts +14 -6
  16. package/src/composites/azure-file-storage-class.ts +14 -6
  17. package/src/composites/azure-monitor-collector.ts +34 -22
  18. package/src/composites/batch-job.ts +25 -17
  19. package/src/composites/cockroachdb-cluster.ts +164 -58
  20. package/src/composites/composites.test.ts +371 -365
  21. package/src/composites/config-connector-context.ts +18 -11
  22. package/src/composites/configured-app.ts +21 -15
  23. package/src/composites/cron-workload.ts +25 -20
  24. package/src/composites/ebs-storage-class.ts +14 -6
  25. package/src/composites/efs-storage-class.ts +14 -6
  26. package/src/composites/external-dns-agent.ts +26 -20
  27. package/src/composites/filestore-storage-class.ts +14 -6
  28. package/src/composites/fluent-bit-agent.ts +30 -24
  29. package/src/composites/gce-ingress.ts +14 -6
  30. package/src/composites/gce-pd-storage-class.ts +14 -6
  31. package/src/composites/gke-external-dns-agent.ts +34 -21
  32. package/src/composites/gke-fluent-bit-agent.ts +34 -22
  33. package/src/composites/gke-gateway.ts +19 -12
  34. package/src/composites/gke-otel-collector.ts +34 -22
  35. package/src/composites/irsa-service-account.ts +22 -14
  36. package/src/composites/metrics-server.ts +41 -26
  37. package/src/composites/monitored-service.ts +26 -19
  38. package/src/composites/namespace-env.ts +26 -17
  39. package/src/composites/network-isolated-app.ts +21 -16
  40. package/src/composites/node-agent.ts +33 -22
  41. package/src/composites/secure-ingress.ts +19 -11
  42. package/src/composites/sidecar-app.ts +17 -12
  43. package/src/composites/stateful-app.ts +21 -12
  44. package/src/composites/web-app.ts +25 -21
  45. package/src/composites/worker-pool.ts +40 -26
  46. package/src/composites/workload-identity-sa.ts +22 -14
  47. package/src/composites/workload-identity-service-account.ts +22 -16
  48. package/src/plugin.ts +40 -614
  49. package/src/serializer.ts +7 -0
  50. package/src/skills/chant-k8s-deployment-strategies.md +183 -0
  51. package/src/skills/chant-k8s-gke.md +56 -1
  52. package/src/skills/chant-k8s-patterns.md +245 -0
  53. package/src/skills/chant-k8s-security.md +237 -0
  54. package/src/skills/chant-k8s.md +305 -0
@@ -5,6 +5,9 @@
5
5
  * (image, RBAC, CloudWatch output config).
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 FluentBitAgentProps {
9
12
  /** Agent name (default: "fluent-bit"). */
10
13
  name?: string;
@@ -30,14 +33,22 @@ export interface FluentBitAgentProps {
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 FluentBitAgentResult {
36
- daemonSet: Record<string, unknown>;
37
- serviceAccount: Record<string, unknown>;
38
- clusterRole: Record<string, unknown>;
39
- clusterRoleBinding: Record<string, unknown>;
40
- configMap: Record<string, unknown>;
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 FluentBitAgentResult {
56
67
  * });
57
68
  * ```
58
69
  */
59
- export function FluentBitAgent(props: FluentBitAgentProps): FluentBitAgentResult {
70
+ export const FluentBitAgent = Composite<FluentBitAgentProps>((props) => {
60
71
  const {
61
72
  name = "fluent-bit",
62
73
  image = "public.ecr.aws/aws-observability/aws-for-fluent-bit:stable",
@@ -70,6 +81,7 @@ export function FluentBitAgent(props: FluentBitAgentProps): FluentBitAgentResult
70
81
  cpuLimit = "200m",
71
82
  memoryLimit = "128Mi",
72
83
  iamRoleArn,
84
+ defaults: defs,
73
85
  } = props;
74
86
 
75
87
  const saName = `${name}-sa`;
@@ -137,7 +149,7 @@ export function FluentBitAgent(props: FluentBitAgentProps): FluentBitAgentResult
137
149
  },
138
150
  };
139
151
 
140
- const daemonSetProps: Record<string, unknown> = {
152
+ const daemonSet = new DaemonSet(mergeDefaults({
141
153
  metadata: {
142
154
  name,
143
155
  namespace,
@@ -159,18 +171,18 @@ export function FluentBitAgent(props: FluentBitAgentProps): FluentBitAgentResult
159
171
  },
160
172
  },
161
173
  },
162
- };
174
+ }, defs?.daemonSet));
163
175
 
164
- const serviceAccountProps: Record<string, unknown> = {
176
+ const serviceAccount = new ServiceAccount(mergeDefaults({
165
177
  metadata: {
166
178
  name: saName,
167
179
  namespace,
168
180
  labels: { ...commonLabels, "app.kubernetes.io/component": "agent" },
169
181
  ...(iamRoleArn ? { annotations: { "eks.amazonaws.com/role-arn": iamRoleArn } } : {}),
170
182
  },
171
- };
183
+ }, defs?.serviceAccount));
172
184
 
173
- const clusterRoleProps: Record<string, unknown> = {
185
+ const clusterRole = new ClusterRole(mergeDefaults({
174
186
  metadata: {
175
187
  name: clusterRoleName,
176
188
  labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
@@ -178,9 +190,9 @@ export function FluentBitAgent(props: FluentBitAgentProps): FluentBitAgentResult
178
190
  rules: [
179
191
  { apiGroups: [""], resources: ["namespaces", "pods"], verbs: ["get", "list", "watch"] },
180
192
  ],
181
- };
193
+ }, defs?.clusterRole));
182
194
 
183
- const clusterRoleBindingProps: Record<string, unknown> = {
195
+ const clusterRoleBinding = new ClusterRoleBinding(mergeDefaults({
184
196
  metadata: {
185
197
  name: bindingName,
186
198
  labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
@@ -197,9 +209,9 @@ export function FluentBitAgent(props: FluentBitAgentProps): FluentBitAgentResult
197
209
  namespace,
198
210
  },
199
211
  ],
200
- };
212
+ }, defs?.clusterRoleBinding));
201
213
 
202
- const configMapProps: Record<string, unknown> = {
214
+ const configMap = new ConfigMap(mergeDefaults({
203
215
  metadata: {
204
216
  name: configMapName,
205
217
  namespace,
@@ -208,13 +220,7 @@ export function FluentBitAgent(props: FluentBitAgentProps): FluentBitAgentResult
208
220
  data: {
209
221
  "fluent-bit.conf": fluentBitConfig,
210
222
  },
211
- };
223
+ }, defs?.configMap));
212
224
 
213
- return {
214
- daemonSet: daemonSetProps,
215
- serviceAccount: serviceAccountProps,
216
- clusterRole: clusterRoleProps,
217
- clusterRoleBinding: clusterRoleBindingProps,
218
- configMap: configMapProps,
219
- };
220
- }
225
+ return { daemonSet, serviceAccount, clusterRole, clusterRoleBinding, configMap };
226
+ }, "FluentBitAgent");
@@ -5,6 +5,9 @@
5
5
  * including static IP, managed certificates, and FrontendConfig.
6
6
  */
7
7
 
8
+ import { Composite, mergeDefaults } from "@intentius/chant";
9
+ import { Ingress } from "../generated";
10
+
8
11
  export interface GceIngressHost {
9
12
  /** Hostname (e.g., "api.example.com"). */
10
13
  hostname: string;
@@ -39,10 +42,14 @@ export interface GceIngressProps {
39
42
  labels?: Record<string, string>;
40
43
  /** Namespace for all resources. */
41
44
  namespace?: string;
45
+ /** Per-member defaults for fine-grained overrides. */
46
+ defaults?: {
47
+ ingress?: Partial<Record<string, unknown>>;
48
+ };
42
49
  }
43
50
 
44
51
  export interface GceIngressResult {
45
- ingress: Record<string, unknown>;
52
+ ingress: InstanceType<typeof Ingress>;
46
53
  }
47
54
 
48
55
  /**
@@ -67,7 +74,7 @@ export interface GceIngressResult {
67
74
  * });
68
75
  * ```
69
76
  */
70
- export function GceIngress(props: GceIngressProps): GceIngressResult {
77
+ export const GceIngress = Composite<GceIngressProps>((props) => {
71
78
  const {
72
79
  name,
73
80
  hosts,
@@ -79,6 +86,7 @@ export function GceIngress(props: GceIngressProps): GceIngressResult {
79
86
  annotations: extraAnnotations = {},
80
87
  labels: extraLabels = {},
81
88
  namespace,
89
+ defaults: defs,
82
90
  } = props;
83
91
 
84
92
  const commonLabels: Record<string, string> = {
@@ -127,7 +135,7 @@ export function GceIngress(props: GceIngressProps): GceIngressResult {
127
135
  },
128
136
  }));
129
137
 
130
- const ingressProps: Record<string, unknown> = {
138
+ const ingress = new Ingress(mergeDefaults({
131
139
  metadata: {
132
140
  name,
133
141
  ...(namespace && { namespace }),
@@ -137,7 +145,7 @@ export function GceIngress(props: GceIngressProps): GceIngressResult {
137
145
  spec: {
138
146
  rules: ingressRules,
139
147
  },
140
- };
148
+ }, defs?.ingress));
141
149
 
142
- return { ingress: ingressProps };
143
- }
150
+ return { ingress };
151
+ }, "GceIngress");
@@ -4,6 +4,9 @@
4
4
  * @gke Creates a StorageClass with the `pd.csi.storage.gke.io` provisioner.
5
5
  */
6
6
 
7
+ import { Composite, mergeDefaults } from "@intentius/chant";
8
+ import { StorageClass } from "../generated";
9
+
7
10
  export interface GcePdStorageClassProps {
8
11
  /** StorageClass name. */
9
12
  name: string;
@@ -21,10 +24,14 @@ export interface GcePdStorageClassProps {
21
24
  allowVolumeExpansion?: boolean;
22
25
  /** Additional labels. */
23
26
  labels?: Record<string, string>;
27
+ /** Per-member defaults for fine-grained overrides. */
28
+ defaults?: {
29
+ storageClass?: Partial<Record<string, unknown>>;
30
+ };
24
31
  }
25
32
 
26
33
  export interface GcePdStorageClassResult {
27
- storageClass: Record<string, unknown>;
34
+ storageClass: InstanceType<typeof StorageClass>;
28
35
  }
29
36
 
30
37
  /**
@@ -42,7 +49,7 @@ export interface GcePdStorageClassResult {
42
49
  * });
43
50
  * ```
44
51
  */
45
- export function GcePdStorageClass(props: GcePdStorageClassProps): GcePdStorageClassResult {
52
+ export const GcePdStorageClass = Composite<GcePdStorageClassProps>((props) => {
46
53
  const {
47
54
  name,
48
55
  type = "pd-balanced",
@@ -52,6 +59,7 @@ export function GcePdStorageClass(props: GcePdStorageClassProps): GcePdStorageCl
52
59
  volumeBindingMode = "WaitForFirstConsumer",
53
60
  allowVolumeExpansion = true,
54
61
  labels: extraLabels = {},
62
+ defaults: defs,
55
63
  } = props;
56
64
 
57
65
  const commonLabels: Record<string, string> = {
@@ -69,7 +77,7 @@ export function GcePdStorageClass(props: GcePdStorageClassProps): GcePdStorageCl
69
77
  parameters["replication-type"] = replicationType;
70
78
  }
71
79
 
72
- const storageClassProps: Record<string, unknown> = {
80
+ const storageClass = new StorageClass(mergeDefaults({
73
81
  metadata: {
74
82
  name,
75
83
  labels: { ...commonLabels, "app.kubernetes.io/component": "storage" },
@@ -79,7 +87,7 @@ export function GcePdStorageClass(props: GcePdStorageClassProps): GcePdStorageCl
79
87
  reclaimPolicy,
80
88
  volumeBindingMode,
81
89
  allowVolumeExpansion,
82
- };
90
+ }, defs?.storageClass));
83
91
 
84
- return { storageClass: storageClassProps };
85
- }
92
+ return { storageClass };
93
+ }, "GcePdStorageClass");
@@ -5,6 +5,9 @@
5
5
  * instead of IRSA for Cloud 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 GkeExternalDnsAgentProps {
9
12
  /** GCP service account email for Workload Identity (needs Cloud DNS permissions). */
10
13
  gcpServiceAccountEmail: string;
@@ -14,8 +17,8 @@ export interface GkeExternalDnsAgentProps {
14
17
  domainFilters: string[];
15
18
  /** TXT record owner ID for identifying managed records. */
16
19
  txtOwnerId?: string;
17
- /** Source of DNS records (default: "ingress"). */
18
- source?: string;
20
+ /** Source(s) of DNS records (default: "ingress"). Pass an array for multiple sources. */
21
+ source?: string | string[];
19
22
  /** Agent name (default: "external-dns"). */
20
23
  name?: string;
21
24
  /** Container image (default: "registry.k8s.io/external-dns/external-dns:v0.14.0"). */
@@ -24,13 +27,20 @@ export interface GkeExternalDnsAgentProps {
24
27
  namespace?: string;
25
28
  /** Additional labels. */
26
29
  labels?: Record<string, string>;
30
+ /** Per-member defaults for fine-grained overrides. */
31
+ defaults?: {
32
+ deployment?: Partial<Record<string, unknown>>;
33
+ serviceAccount?: Partial<Record<string, unknown>>;
34
+ clusterRole?: Partial<Record<string, unknown>>;
35
+ clusterRoleBinding?: Partial<Record<string, unknown>>;
36
+ };
27
37
  }
28
38
 
29
39
  export interface GkeExternalDnsAgentResult {
30
- deployment: Record<string, unknown>;
31
- serviceAccount: Record<string, unknown>;
32
- clusterRole: Record<string, unknown>;
33
- clusterRoleBinding: Record<string, unknown>;
40
+ deployment: InstanceType<typeof Deployment>;
41
+ serviceAccount: InstanceType<typeof ServiceAccount>;
42
+ clusterRole: InstanceType<typeof ClusterRole>;
43
+ clusterRoleBinding: InstanceType<typeof ClusterRoleBinding>;
34
44
  }
35
45
 
36
46
  /**
@@ -50,7 +60,7 @@ export interface GkeExternalDnsAgentResult {
50
60
  * });
51
61
  * ```
52
62
  */
53
- export function GkeExternalDnsAgent(props: GkeExternalDnsAgentProps): GkeExternalDnsAgentResult {
63
+ export const GkeExternalDnsAgent = Composite<GkeExternalDnsAgentProps>((props) => {
54
64
  const {
55
65
  gcpServiceAccountEmail,
56
66
  gcpProjectId,
@@ -61,6 +71,7 @@ export function GkeExternalDnsAgent(props: GkeExternalDnsAgentProps): GkeExterna
61
71
  image = "registry.k8s.io/external-dns/external-dns:v0.14.0",
62
72
  namespace = "kube-system",
63
73
  labels: extraLabels = {},
74
+ defaults: defs,
64
75
  } = props;
65
76
 
66
77
  const saName = `${name}-sa`;
@@ -73,8 +84,10 @@ export function GkeExternalDnsAgent(props: GkeExternalDnsAgentProps): GkeExterna
73
84
  ...extraLabels,
74
85
  };
75
86
 
87
+ const sources = Array.isArray(source) ? source : [source];
88
+
76
89
  const args: string[] = [
77
- `--source=${source}`,
90
+ ...sources.map((s) => `--source=${s}`),
78
91
  "--provider=google",
79
92
  `--google-project=${gcpProjectId}`,
80
93
  "--policy=upsert-only",
@@ -89,7 +102,7 @@ export function GkeExternalDnsAgent(props: GkeExternalDnsAgentProps): GkeExterna
89
102
  args.push(`--txt-owner-id=${txtOwnerId}`);
90
103
  }
91
104
 
92
- const deploymentProps: Record<string, unknown> = {
105
+ const deployment = new Deployment(mergeDefaults({
93
106
  metadata: {
94
107
  name,
95
108
  namespace,
@@ -122,9 +135,9 @@ export function GkeExternalDnsAgent(props: GkeExternalDnsAgentProps): GkeExterna
122
135
  },
123
136
  },
124
137
  },
125
- };
138
+ }, defs?.deployment));
126
139
 
127
- const serviceAccountProps: Record<string, unknown> = {
140
+ const serviceAccount = new ServiceAccount(mergeDefaults({
128
141
  metadata: {
129
142
  name: saName,
130
143
  namespace,
@@ -133,9 +146,9 @@ export function GkeExternalDnsAgent(props: GkeExternalDnsAgentProps): GkeExterna
133
146
  "iam.gke.io/gcp-service-account": gcpServiceAccountEmail,
134
147
  },
135
148
  },
136
- };
149
+ }, defs?.serviceAccount));
137
150
 
138
- const clusterRoleProps: Record<string, unknown> = {
151
+ const clusterRole = new ClusterRole(mergeDefaults({
139
152
  metadata: {
140
153
  name: clusterRoleName,
141
154
  labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
@@ -145,9 +158,9 @@ export function GkeExternalDnsAgent(props: GkeExternalDnsAgentProps): GkeExterna
145
158
  { apiGroups: ["extensions", "networking.k8s.io"], resources: ["ingresses"], verbs: ["get", "watch", "list"] },
146
159
  { apiGroups: [""], resources: ["nodes"], verbs: ["list", "watch"] },
147
160
  ],
148
- };
161
+ }, defs?.clusterRole));
149
162
 
150
- const clusterRoleBindingProps: Record<string, unknown> = {
163
+ const clusterRoleBinding = new ClusterRoleBinding(mergeDefaults({
151
164
  metadata: {
152
165
  name: bindingName,
153
166
  labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
@@ -164,12 +177,12 @@ export function GkeExternalDnsAgent(props: GkeExternalDnsAgentProps): GkeExterna
164
177
  namespace,
165
178
  },
166
179
  ],
167
- };
180
+ }, defs?.clusterRoleBinding));
168
181
 
169
182
  return {
170
- deployment: deploymentProps,
171
- serviceAccount: serviceAccountProps,
172
- clusterRole: clusterRoleProps,
173
- clusterRoleBinding: clusterRoleBindingProps,
183
+ deployment,
184
+ serviceAccount,
185
+ clusterRole,
186
+ clusterRoleBinding,
174
187
  };
175
- }
188
+ }, "GkeExternalDnsAgent");
@@ -5,6 +5,9 @@
5
5
  * output plugin and uses GKE Workload Identity instead of IRSA.
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 GkeFluentBitAgentProps {
9
12
  /** GKE cluster name — used as log stream prefix. */
10
13
  clusterName: string;
@@ -28,14 +31,22 @@ export interface GkeFluentBitAgentProps {
28
31
  cpuLimit?: string;
29
32
  /** Memory limit (default: "128Mi"). */
30
33
  memoryLimit?: string;
34
+ /** Per-member defaults for fine-grained overrides. */
35
+ defaults?: {
36
+ daemonSet?: Partial<Record<string, unknown>>;
37
+ serviceAccount?: Partial<Record<string, unknown>>;
38
+ clusterRole?: Partial<Record<string, unknown>>;
39
+ clusterRoleBinding?: Partial<Record<string, unknown>>;
40
+ configMap?: Partial<Record<string, unknown>>;
41
+ };
31
42
  }
32
43
 
33
44
  export interface GkeFluentBitAgentResult {
34
- daemonSet: Record<string, unknown>;
35
- serviceAccount: Record<string, unknown>;
36
- clusterRole: Record<string, unknown>;
37
- clusterRoleBinding: Record<string, unknown>;
38
- configMap: Record<string, unknown>;
45
+ daemonSet: InstanceType<typeof DaemonSet>;
46
+ serviceAccount: InstanceType<typeof ServiceAccount>;
47
+ clusterRole: InstanceType<typeof ClusterRole>;
48
+ clusterRoleBinding: InstanceType<typeof ClusterRoleBinding>;
49
+ configMap: InstanceType<typeof ConfigMap>;
39
50
  }
40
51
 
41
52
  /**
@@ -54,7 +65,7 @@ export interface GkeFluentBitAgentResult {
54
65
  * });
55
66
  * ```
56
67
  */
57
- export function GkeFluentBitAgent(props: GkeFluentBitAgentProps): GkeFluentBitAgentResult {
68
+ export const GkeFluentBitAgent = Composite<GkeFluentBitAgentProps>((props) => {
58
69
  const {
59
70
  clusterName,
60
71
  projectId,
@@ -67,6 +78,7 @@ export function GkeFluentBitAgent(props: GkeFluentBitAgentProps): GkeFluentBitAg
67
78
  memoryRequest = "64Mi",
68
79
  cpuLimit = "200m",
69
80
  memoryLimit = "128Mi",
81
+ defaults: defs,
70
82
  } = props;
71
83
 
72
84
  const saName = `${name}-sa`;
@@ -134,7 +146,7 @@ export function GkeFluentBitAgent(props: GkeFluentBitAgentProps): GkeFluentBitAg
134
146
  },
135
147
  };
136
148
 
137
- const daemonSetProps: Record<string, unknown> = {
149
+ const daemonSet = new DaemonSet(mergeDefaults({
138
150
  metadata: {
139
151
  name,
140
152
  namespace,
@@ -156,9 +168,9 @@ export function GkeFluentBitAgent(props: GkeFluentBitAgentProps): GkeFluentBitAg
156
168
  },
157
169
  },
158
170
  },
159
- };
171
+ }, defs?.daemonSet));
160
172
 
161
- const serviceAccountProps: Record<string, unknown> = {
173
+ const serviceAccount = new ServiceAccount(mergeDefaults({
162
174
  metadata: {
163
175
  name: saName,
164
176
  namespace,
@@ -167,9 +179,9 @@ export function GkeFluentBitAgent(props: GkeFluentBitAgentProps): GkeFluentBitAg
167
179
  ? { annotations: { "iam.gke.io/gcp-service-account": gcpServiceAccountEmail } }
168
180
  : {}),
169
181
  },
170
- };
182
+ }, defs?.serviceAccount));
171
183
 
172
- const clusterRoleProps: Record<string, unknown> = {
184
+ const clusterRole = new ClusterRole(mergeDefaults({
173
185
  metadata: {
174
186
  name: clusterRoleName,
175
187
  labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
@@ -177,9 +189,9 @@ export function GkeFluentBitAgent(props: GkeFluentBitAgentProps): GkeFluentBitAg
177
189
  rules: [
178
190
  { apiGroups: [""], resources: ["namespaces", "pods"], verbs: ["get", "list", "watch"] },
179
191
  ],
180
- };
192
+ }, defs?.clusterRole));
181
193
 
182
- const clusterRoleBindingProps: Record<string, unknown> = {
194
+ const clusterRoleBinding = new ClusterRoleBinding(mergeDefaults({
183
195
  metadata: {
184
196
  name: bindingName,
185
197
  labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
@@ -196,9 +208,9 @@ export function GkeFluentBitAgent(props: GkeFluentBitAgentProps): GkeFluentBitAg
196
208
  namespace,
197
209
  },
198
210
  ],
199
- };
211
+ }, defs?.clusterRoleBinding));
200
212
 
201
- const configMapProps: Record<string, unknown> = {
213
+ const configMap = new ConfigMap(mergeDefaults({
202
214
  metadata: {
203
215
  name: configMapName,
204
216
  namespace,
@@ -207,13 +219,13 @@ export function GkeFluentBitAgent(props: GkeFluentBitAgentProps): GkeFluentBitAg
207
219
  data: {
208
220
  "fluent-bit.conf": fluentBitConfig,
209
221
  },
210
- };
222
+ }, defs?.configMap));
211
223
 
212
224
  return {
213
- daemonSet: daemonSetProps,
214
- serviceAccount: serviceAccountProps,
215
- clusterRole: clusterRoleProps,
216
- clusterRoleBinding: clusterRoleBindingProps,
217
- configMap: configMapProps,
225
+ daemonSet,
226
+ serviceAccount,
227
+ clusterRole,
228
+ clusterRoleBinding,
229
+ configMap,
218
230
  };
219
- }
231
+ }, "GkeFluentBitAgent");
@@ -5,6 +5,9 @@
5
5
  * HTTPRoute resources for traffic routing.
6
6
  */
7
7
 
8
+ import { Composite, mergeDefaults } from "@intentius/chant";
9
+ import { Deployment } from "../generated";
10
+
8
11
  export interface GkeGatewayHost {
9
12
  /** Hostname (e.g., "api.example.com"). */
10
13
  hostname: string;
@@ -32,11 +35,16 @@ export interface GkeGatewayProps {
32
35
  labels?: Record<string, string>;
33
36
  /** Namespace for all resources. */
34
37
  namespace?: string;
38
+ /** Per-member defaults for fine-grained overrides. */
39
+ defaults?: {
40
+ gateway?: Partial<Record<string, unknown>>;
41
+ httpRoute?: Partial<Record<string, unknown>>;
42
+ };
35
43
  }
36
44
 
37
45
  export interface GkeGatewayResult {
38
- gateway: Record<string, unknown>;
39
- httpRoute: Record<string, unknown>;
46
+ gateway: InstanceType<typeof Deployment>; // CRD — use Deployment as proxy Declarable
47
+ httpRoute: InstanceType<typeof Deployment>; // CRD — use Deployment as proxy Declarable
40
48
  }
41
49
 
42
50
  /**
@@ -60,7 +68,7 @@ export interface GkeGatewayResult {
60
68
  * });
61
69
  * ```
62
70
  */
63
- export function GkeGateway(props: GkeGatewayProps): GkeGatewayResult {
71
+ export const GkeGateway = Composite<GkeGatewayProps>((props) => {
64
72
  const {
65
73
  name,
66
74
  gatewayClassName = "gke-l7-global-external-managed",
@@ -68,6 +76,7 @@ export function GkeGateway(props: GkeGatewayProps): GkeGatewayResult {
68
76
  certificateName,
69
77
  labels: extraLabels = {},
70
78
  namespace,
79
+ defaults: defs,
71
80
  } = props;
72
81
 
73
82
  const routeName = `${name}-route`;
@@ -99,7 +108,8 @@ export function GkeGateway(props: GkeGatewayProps): GkeGatewayResult {
99
108
  });
100
109
  }
101
110
 
102
- const gatewayProps: Record<string, unknown> = {
111
+ // Gateway and HTTPRoute are CRDs — use Deployment constructor as a generic Declarable wrapper
112
+ const gateway = new Deployment(mergeDefaults({
103
113
  metadata: {
104
114
  name,
105
115
  ...(namespace && { namespace }),
@@ -109,7 +119,7 @@ export function GkeGateway(props: GkeGatewayProps): GkeGatewayResult {
109
119
  gatewayClassName,
110
120
  listeners,
111
121
  },
112
- };
122
+ }, defs?.gateway));
113
123
 
114
124
  // Build HTTPRoute rules
115
125
  const hostnames = hosts.map((h) => h.hostname);
@@ -123,7 +133,7 @@ export function GkeGateway(props: GkeGatewayProps): GkeGatewayResult {
123
133
  })),
124
134
  );
125
135
 
126
- const httpRouteProps: Record<string, unknown> = {
136
+ const httpRoute = new Deployment(mergeDefaults({
127
137
  metadata: {
128
138
  name: routeName,
129
139
  ...(namespace && { namespace }),
@@ -134,10 +144,7 @@ export function GkeGateway(props: GkeGatewayProps): GkeGatewayResult {
134
144
  hostnames,
135
145
  rules,
136
146
  },
137
- };
147
+ }, defs?.httpRoute));
138
148
 
139
- return {
140
- gateway: gatewayProps,
141
- httpRoute: httpRouteProps,
142
- };
143
- }
149
+ return { gateway, httpRoute };
150
+ }, "GkeGateway");