@intentius/chant-lexicon-k8s 0.0.22 → 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.
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 +1 -1
  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 +148 -58
  20. package/src/composites/composites.test.ts +369 -363
  21. package/src/composites/config-connector-context.ts +15 -8
  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 +3 -0
  50. package/src/skills/chant-k8s-deployment-strategies.md +183 -0
  51. package/src/skills/chant-k8s-gke.md +55 -0
  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
  * annotation for IAM Roles for Service Accounts (IRSA).
6
6
  */
7
7
 
8
+ import { Composite, mergeDefaults } from "@intentius/chant";
9
+ import { ServiceAccount, Role, RoleBinding } from "../generated";
10
+
8
11
  export interface IrsaServiceAccountProps {
9
12
  /** ServiceAccount name — used in metadata and labels. */
10
13
  name: string;
@@ -20,12 +23,18 @@ export interface IrsaServiceAccountProps {
20
23
  labels?: Record<string, string>;
21
24
  /** Namespace for all resources. */
22
25
  namespace?: string;
26
+ /** Per-member defaults for fine-grained overrides. */
27
+ defaults?: {
28
+ serviceAccount?: Partial<Record<string, unknown>>;
29
+ role?: Partial<Record<string, unknown>>;
30
+ roleBinding?: Partial<Record<string, unknown>>;
31
+ };
23
32
  }
24
33
 
25
34
  export interface IrsaServiceAccountResult {
26
- serviceAccount: Record<string, unknown>;
27
- role?: Record<string, unknown>;
28
- roleBinding?: Record<string, unknown>;
35
+ serviceAccount: InstanceType<typeof ServiceAccount>;
36
+ role?: InstanceType<typeof Role>;
37
+ roleBinding?: InstanceType<typeof RoleBinding>;
29
38
  }
30
39
 
31
40
  /**
@@ -46,13 +55,14 @@ export interface IrsaServiceAccountResult {
46
55
  * });
47
56
  * ```
48
57
  */
49
- export function IrsaServiceAccount(props: IrsaServiceAccountProps): IrsaServiceAccountResult {
58
+ export const IrsaServiceAccount = Composite<IrsaServiceAccountProps>((props) => {
50
59
  const {
51
60
  name,
52
61
  iamRoleArn,
53
62
  rbacRules,
54
63
  labels: extraLabels = {},
55
64
  namespace,
65
+ defaults: defs,
56
66
  } = props;
57
67
 
58
68
  const roleName = `${name}-role`;
@@ -64,7 +74,7 @@ export function IrsaServiceAccount(props: IrsaServiceAccountProps): IrsaServiceA
64
74
  ...extraLabels,
65
75
  };
66
76
 
67
- const serviceAccountProps: Record<string, unknown> = {
77
+ const serviceAccount = new ServiceAccount(mergeDefaults({
68
78
  metadata: {
69
79
  name,
70
80
  ...(namespace && { namespace }),
@@ -73,23 +83,21 @@ export function IrsaServiceAccount(props: IrsaServiceAccountProps): IrsaServiceA
73
83
  "eks.amazonaws.com/role-arn": iamRoleArn,
74
84
  },
75
85
  },
76
- };
86
+ }, defs?.serviceAccount));
77
87
 
78
- const result: IrsaServiceAccountResult = {
79
- serviceAccount: serviceAccountProps,
80
- };
88
+ const result: Record<string, any> = { serviceAccount };
81
89
 
82
90
  if (rbacRules && rbacRules.length > 0) {
83
- result.role = {
91
+ result.role = new Role(mergeDefaults({
84
92
  metadata: {
85
93
  name: roleName,
86
94
  ...(namespace && { namespace }),
87
95
  labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
88
96
  },
89
97
  rules: rbacRules,
90
- };
98
+ }, defs?.role));
91
99
 
92
- result.roleBinding = {
100
+ result.roleBinding = new RoleBinding(mergeDefaults({
93
101
  metadata: {
94
102
  name: bindingName,
95
103
  ...(namespace && { namespace }),
@@ -107,8 +115,8 @@ export function IrsaServiceAccount(props: IrsaServiceAccountProps): IrsaServiceA
107
115
  ...(namespace && { namespace }),
108
116
  },
109
117
  ],
110
- };
118
+ }, defs?.roleBinding));
111
119
  }
112
120
 
113
121
  return result;
114
- }
122
+ }, "IrsaServiceAccount");
@@ -5,6 +5,9 @@
5
5
  * EKS managed addon — it needs K8s workloads. Uses in-cluster RBAC only (no IRSA).
6
6
  */
7
7
 
8
+ import { Composite, mergeDefaults } from "@intentius/chant";
9
+ import { Deployment, Service, ServiceAccount, ClusterRole, ClusterRoleBinding, APIService } from "../generated";
10
+
8
11
  export interface MetricsServerProps {
9
12
  /** Agent name (default: "metrics-server"). */
10
13
  name?: string;
@@ -16,20 +19,31 @@ export interface MetricsServerProps {
16
19
  namespace?: string;
17
20
  /** Additional labels. */
18
21
  labels?: Record<string, string>;
22
+ /** Per-member defaults for fine-grained overrides. */
23
+ defaults?: {
24
+ deployment?: Partial<Record<string, unknown>>;
25
+ service?: Partial<Record<string, unknown>>;
26
+ serviceAccount?: Partial<Record<string, unknown>>;
27
+ clusterRole?: Partial<Record<string, unknown>>;
28
+ clusterRoleBinding?: Partial<Record<string, unknown>>;
29
+ aggregatedClusterRole?: Partial<Record<string, unknown>>;
30
+ authDelegatorBinding?: Partial<Record<string, unknown>>;
31
+ apiService?: Partial<Record<string, unknown>>;
32
+ };
19
33
  }
20
34
 
21
35
  export interface MetricsServerResult {
22
- deployment: Record<string, unknown>;
23
- service: Record<string, unknown>;
24
- serviceAccount: Record<string, unknown>;
25
- clusterRole: Record<string, unknown>;
26
- clusterRoleBinding: Record<string, unknown>;
36
+ deployment: InstanceType<typeof Deployment>;
37
+ service: InstanceType<typeof Service>;
38
+ serviceAccount: InstanceType<typeof ServiceAccount>;
39
+ clusterRole: InstanceType<typeof ClusterRole>;
40
+ clusterRoleBinding: InstanceType<typeof ClusterRoleBinding>;
27
41
  /** ClusterRole for aggregated API access. */
28
- aggregatedClusterRole: Record<string, unknown>;
42
+ aggregatedClusterRole: InstanceType<typeof ClusterRole>;
29
43
  /** Binding for aggregated API auth-delegator. */
30
- authDelegatorBinding: Record<string, unknown>;
44
+ authDelegatorBinding: InstanceType<typeof ClusterRoleBinding>;
31
45
  /** APIService registration for v1beta1.metrics.k8s.io. */
32
- apiService: Record<string, unknown>;
46
+ apiService: InstanceType<typeof APIService>;
33
47
  }
34
48
 
35
49
  /**
@@ -43,13 +57,14 @@ export interface MetricsServerResult {
43
57
  * const ms = MetricsServer({});
44
58
  * ```
45
59
  */
46
- export function MetricsServer(props: MetricsServerProps): MetricsServerResult {
60
+ export const MetricsServer = Composite<MetricsServerProps>((props) => {
47
61
  const {
48
62
  name = "metrics-server",
49
63
  image = "registry.k8s.io/metrics-server/metrics-server:v0.7.2",
50
64
  replicas = 1,
51
65
  namespace = "kube-system",
52
66
  labels: extraLabels = {},
67
+ defaults: defs,
53
68
  } = props;
54
69
 
55
70
  const saName = `${name}-sa`;
@@ -60,7 +75,7 @@ export function MetricsServer(props: MetricsServerProps): MetricsServerResult {
60
75
  ...extraLabels,
61
76
  };
62
77
 
63
- const deployment: Record<string, unknown> = {
78
+ const deployment = new Deployment(mergeDefaults({
64
79
  metadata: {
65
80
  name,
66
81
  namespace,
@@ -114,9 +129,9 @@ export function MetricsServer(props: MetricsServerProps): MetricsServerResult {
114
129
  },
115
130
  },
116
131
  },
117
- };
132
+ }, defs?.deployment));
118
133
 
119
- const service: Record<string, unknown> = {
134
+ const service = new Service(mergeDefaults({
120
135
  metadata: {
121
136
  name,
122
137
  namespace,
@@ -131,17 +146,17 @@ export function MetricsServer(props: MetricsServerProps): MetricsServerResult {
131
146
  selector: { "app.kubernetes.io/name": name },
132
147
  ports: [{ port: 443, targetPort: 10250, protocol: "TCP", name: "https" }],
133
148
  },
134
- };
149
+ }, defs?.service));
135
150
 
136
- const serviceAccount: Record<string, unknown> = {
151
+ const serviceAccount = new ServiceAccount(mergeDefaults({
137
152
  metadata: {
138
153
  name: saName,
139
154
  namespace,
140
155
  labels: { ...commonLabels, "app.kubernetes.io/component": "metrics" },
141
156
  },
142
- };
157
+ }, defs?.serviceAccount));
143
158
 
144
- const clusterRole: Record<string, unknown> = {
159
+ const clusterRole = new ClusterRole(mergeDefaults({
145
160
  metadata: {
146
161
  name: `system:${name}`,
147
162
  labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
@@ -150,9 +165,9 @@ export function MetricsServer(props: MetricsServerProps): MetricsServerResult {
150
165
  { apiGroups: [""], resources: ["pods", "nodes", "namespaces", "configmaps"], verbs: ["get", "list", "watch"] },
151
166
  { apiGroups: [""], resources: ["nodes/metrics", "nodes/stats"], verbs: ["get"] },
152
167
  ],
153
- };
168
+ }, defs?.clusterRole));
154
169
 
155
- const clusterRoleBinding: Record<string, unknown> = {
170
+ const clusterRoleBinding = new ClusterRoleBinding(mergeDefaults({
156
171
  metadata: {
157
172
  name: `system:${name}`,
158
173
  labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
@@ -163,9 +178,9 @@ export function MetricsServer(props: MetricsServerProps): MetricsServerResult {
163
178
  name: `system:${name}`,
164
179
  },
165
180
  subjects: [{ kind: "ServiceAccount", name: saName, namespace }],
166
- };
181
+ }, defs?.clusterRoleBinding));
167
182
 
168
- const aggregatedClusterRole: Record<string, unknown> = {
183
+ const aggregatedClusterRole = new ClusterRole(mergeDefaults({
169
184
  metadata: {
170
185
  name: `system:${name}-aggregated-reader`,
171
186
  labels: {
@@ -179,9 +194,9 @@ export function MetricsServer(props: MetricsServerProps): MetricsServerResult {
179
194
  rules: [
180
195
  { apiGroups: ["metrics.k8s.io"], resources: ["pods", "nodes"], verbs: ["get", "list", "watch"] },
181
196
  ],
182
- };
197
+ }, defs?.aggregatedClusterRole));
183
198
 
184
- const authDelegatorBinding: Record<string, unknown> = {
199
+ const authDelegatorBinding = new ClusterRoleBinding(mergeDefaults({
185
200
  metadata: {
186
201
  name: `${name}:system:auth-delegator`,
187
202
  labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
@@ -192,9 +207,9 @@ export function MetricsServer(props: MetricsServerProps): MetricsServerResult {
192
207
  name: "system:auth-delegator",
193
208
  },
194
209
  subjects: [{ kind: "ServiceAccount", name: saName, namespace }],
195
- };
210
+ }, defs?.authDelegatorBinding));
196
211
 
197
- const apiService: Record<string, unknown> = {
212
+ const apiService = new APIService(mergeDefaults({
198
213
  apiVersion: "apiregistration.k8s.io/v1",
199
214
  kind: "APIService",
200
215
  metadata: {
@@ -209,7 +224,7 @@ export function MetricsServer(props: MetricsServerProps): MetricsServerResult {
209
224
  groupPriorityMinimum: 100,
210
225
  versionPriority: 100,
211
226
  },
212
- };
227
+ }, defs?.apiService));
213
228
 
214
229
  return {
215
230
  deployment,
@@ -221,4 +236,4 @@ export function MetricsServer(props: MetricsServerProps): MetricsServerResult {
221
236
  authDelegatorBinding,
222
237
  apiService,
223
238
  };
224
- }
239
+ }, "MetricsServer");
@@ -6,6 +6,8 @@
6
6
  * as raw objects that can be serialized alongside native K8s resources.
7
7
  */
8
8
 
9
+ import { Composite, mergeDefaults } from "@intentius/chant";
10
+ import { Deployment, Service } from "../generated";
9
11
  import type { ContainerSecurityContext } from "./security-context";
10
12
 
11
13
  export interface AlertRule {
@@ -54,13 +56,20 @@ export interface MonitoredServiceProps {
54
56
  env?: Array<{ name: string; value: string }>;
55
57
  /** Container security context (supports PSS restricted fields). */
56
58
  securityContext?: ContainerSecurityContext;
59
+ /** Per-member defaults for fine-grained overrides. */
60
+ defaults?: {
61
+ deployment?: Partial<Record<string, unknown>>;
62
+ service?: Partial<Record<string, unknown>>;
63
+ serviceMonitor?: Partial<Record<string, unknown>>;
64
+ prometheusRule?: Partial<Record<string, unknown>>;
65
+ };
57
66
  }
58
67
 
59
68
  export interface MonitoredServiceResult {
60
- deployment: Record<string, unknown>;
61
- service: Record<string, unknown>;
62
- serviceMonitor: Record<string, unknown>;
63
- prometheusRule?: Record<string, unknown>;
69
+ deployment: InstanceType<typeof Deployment>;
70
+ service: InstanceType<typeof Service>;
71
+ serviceMonitor: InstanceType<typeof Deployment>; // CRD — use Deployment as proxy type
72
+ prometheusRule?: InstanceType<typeof Deployment>; // CRD — use Deployment as proxy type
64
73
  }
65
74
 
66
75
  /**
@@ -82,7 +91,7 @@ export interface MonitoredServiceResult {
82
91
  * });
83
92
  * ```
84
93
  */
85
- export function MonitoredService(props: MonitoredServiceProps): MonitoredServiceResult {
94
+ export const MonitoredService = Composite<MonitoredServiceProps>((props) => {
86
95
  const {
87
96
  name,
88
97
  image,
@@ -100,6 +109,7 @@ export function MonitoredService(props: MonitoredServiceProps): MonitoredService
100
109
  namespace,
101
110
  env,
102
111
  securityContext,
112
+ defaults: defs,
103
113
  } = props;
104
114
 
105
115
  const commonLabels: Record<string, string> = {
@@ -115,7 +125,7 @@ export function MonitoredService(props: MonitoredServiceProps): MonitoredService
115
125
  ports.push({ containerPort: metricsPort, name: "metrics" });
116
126
  }
117
127
 
118
- const deploymentProps: Record<string, unknown> = {
128
+ const deployment = new Deployment(mergeDefaults({
119
129
  metadata: {
120
130
  name,
121
131
  ...(namespace && { namespace }),
@@ -143,7 +153,7 @@ export function MonitoredService(props: MonitoredServiceProps): MonitoredService
143
153
  },
144
154
  },
145
155
  },
146
- };
156
+ }, defs?.deployment));
147
157
 
148
158
  const servicePorts: Array<Record<string, unknown>> = [
149
159
  { port: 80, targetPort: port, protocol: "TCP", name: "http" },
@@ -152,7 +162,7 @@ export function MonitoredService(props: MonitoredServiceProps): MonitoredService
152
162
  servicePorts.push({ port: metricsPort, targetPort: metricsPort, protocol: "TCP", name: "metrics" });
153
163
  }
154
164
 
155
- const serviceProps: Record<string, unknown> = {
165
+ const service = new Service(mergeDefaults({
156
166
  metadata: {
157
167
  name,
158
168
  ...(namespace && { namespace }),
@@ -163,9 +173,10 @@ export function MonitoredService(props: MonitoredServiceProps): MonitoredService
163
173
  ports: servicePorts,
164
174
  type: "ClusterIP",
165
175
  },
166
- };
176
+ }, defs?.service));
167
177
 
168
- const serviceMonitorProps: Record<string, unknown> = {
178
+ // ServiceMonitor is a CRD — use Deployment constructor as a generic Declarable wrapper
179
+ const serviceMonitor = new Deployment(mergeDefaults({
169
180
  metadata: {
170
181
  name,
171
182
  ...(namespace && { namespace }),
@@ -183,16 +194,12 @@ export function MonitoredService(props: MonitoredServiceProps): MonitoredService
183
194
  },
184
195
  ],
185
196
  },
186
- };
197
+ }, defs?.serviceMonitor));
187
198
 
188
- const result: MonitoredServiceResult = {
189
- deployment: deploymentProps,
190
- service: serviceProps,
191
- serviceMonitor: serviceMonitorProps,
192
- };
199
+ const result: Record<string, any> = { deployment, service, serviceMonitor };
193
200
 
194
201
  if (alertRules && alertRules.length > 0) {
195
- result.prometheusRule = {
202
+ result.prometheusRule = new Deployment(mergeDefaults({
196
203
  metadata: {
197
204
  name: `${name}-alerts`,
198
205
  ...(namespace && { namespace }),
@@ -214,8 +221,8 @@ export function MonitoredService(props: MonitoredServiceProps): MonitoredService
214
221
  },
215
222
  ],
216
223
  },
217
- };
224
+ }, defs?.prometheusRule));
218
225
  }
219
226
 
220
227
  return result;
221
- }
228
+ }, "MonitoredService");
@@ -5,6 +5,9 @@
5
5
  * resource guardrails and network isolation.
6
6
  */
7
7
 
8
+ import { Composite, mergeDefaults } from "@intentius/chant";
9
+ import { Namespace, ResourceQuota, LimitRange, NetworkPolicy } from "../generated";
10
+
8
11
  export interface NamespaceEnvProps {
9
12
  /** Namespace name. */
10
13
  name: string;
@@ -28,13 +31,20 @@ export interface NamespaceEnvProps {
28
31
  defaultDenyEgress?: boolean;
29
32
  /** Additional labels to apply to all resources. */
30
33
  labels?: Record<string, string>;
34
+ /** Per-member defaults for fine-grained overrides. */
35
+ defaults?: {
36
+ namespace?: Partial<Record<string, unknown>>;
37
+ resourceQuota?: Partial<Record<string, unknown>>;
38
+ limitRange?: Partial<Record<string, unknown>>;
39
+ networkPolicy?: Partial<Record<string, unknown>>;
40
+ };
31
41
  }
32
42
 
33
43
  export interface NamespaceEnvResult {
34
- namespace: Record<string, unknown>;
35
- resourceQuota?: Record<string, unknown>;
36
- limitRange?: Record<string, unknown>;
37
- networkPolicy?: Record<string, unknown>;
44
+ namespace: InstanceType<typeof Namespace>;
45
+ resourceQuota?: InstanceType<typeof ResourceQuota>;
46
+ limitRange?: InstanceType<typeof LimitRange>;
47
+ networkPolicy?: InstanceType<typeof NetworkPolicy>;
38
48
  }
39
49
 
40
50
  /**
@@ -55,7 +65,7 @@ export interface NamespaceEnvResult {
55
65
  * });
56
66
  * ```
57
67
  */
58
- export function NamespaceEnv(props: NamespaceEnvProps): NamespaceEnvResult {
68
+ export const NamespaceEnv = Composite<NamespaceEnvProps>((props) => {
59
69
  const {
60
70
  name,
61
71
  cpuQuota,
@@ -68,6 +78,7 @@ export function NamespaceEnv(props: NamespaceEnvProps): NamespaceEnvResult {
68
78
  defaultDenyIngress = true,
69
79
  defaultDenyEgress = false,
70
80
  labels: extraLabels = {},
81
+ defaults: defs,
71
82
  } = props;
72
83
 
73
84
  const commonLabels: Record<string, string> = {
@@ -76,16 +87,14 @@ export function NamespaceEnv(props: NamespaceEnvProps): NamespaceEnvResult {
76
87
  ...extraLabels,
77
88
  };
78
89
 
79
- const namespaceProps: Record<string, unknown> = {
90
+ const namespace = new Namespace(mergeDefaults({
80
91
  metadata: {
81
92
  name,
82
93
  labels: { ...commonLabels, "app.kubernetes.io/component": "namespace" },
83
94
  },
84
- };
95
+ }, defs?.namespace));
85
96
 
86
- const result: NamespaceEnvResult = {
87
- namespace: namespaceProps,
88
- };
97
+ const result: Record<string, any> = { namespace };
89
98
 
90
99
  // ResourceQuota — only if at least one quota prop is set
91
100
  const hasQuota = cpuQuota || memoryQuota || maxPods !== undefined;
@@ -95,14 +104,14 @@ export function NamespaceEnv(props: NamespaceEnvProps): NamespaceEnvResult {
95
104
  if (memoryQuota) hard["limits.memory"] = memoryQuota;
96
105
  if (maxPods !== undefined) hard.pods = String(maxPods);
97
106
 
98
- result.resourceQuota = {
107
+ result.resourceQuota = new ResourceQuota(mergeDefaults({
99
108
  metadata: {
100
109
  name: `${name}-quota`,
101
110
  namespace: name,
102
111
  labels: { ...commonLabels, "app.kubernetes.io/component": "quota" },
103
112
  },
104
113
  spec: { hard },
105
- };
114
+ }, defs?.resourceQuota));
106
115
  }
107
116
 
108
117
  // LimitRange — only if at least one default limit prop is set
@@ -127,7 +136,7 @@ export function NamespaceEnv(props: NamespaceEnvProps): NamespaceEnvResult {
127
136
  if (Object.keys(defaultLimits).length > 0) limit.default = defaultLimits;
128
137
  if (Object.keys(defaultRequests).length > 0) limit.defaultRequest = defaultRequests;
129
138
 
130
- result.limitRange = {
139
+ result.limitRange = new LimitRange(mergeDefaults({
131
140
  metadata: {
132
141
  name: `${name}-limits`,
133
142
  namespace: name,
@@ -136,7 +145,7 @@ export function NamespaceEnv(props: NamespaceEnvProps): NamespaceEnvResult {
136
145
  spec: {
137
146
  limits: [limit],
138
147
  },
139
- };
148
+ }, defs?.limitRange));
140
149
  }
141
150
 
142
151
  // NetworkPolicy — default-deny ingress and/or egress
@@ -146,7 +155,7 @@ export function NamespaceEnv(props: NamespaceEnvProps): NamespaceEnvResult {
146
155
  if (defaultDenyIngress) policyTypes.push("Ingress");
147
156
  if (defaultDenyEgress) policyTypes.push("Egress");
148
157
 
149
- result.networkPolicy = {
158
+ result.networkPolicy = new NetworkPolicy(mergeDefaults({
150
159
  metadata: {
151
160
  name: `${name}-default-deny`,
152
161
  namespace: name,
@@ -156,8 +165,8 @@ export function NamespaceEnv(props: NamespaceEnvProps): NamespaceEnvResult {
156
165
  podSelector: {},
157
166
  policyTypes,
158
167
  },
159
- };
168
+ }, defs?.networkPolicy));
160
169
  }
161
170
 
162
171
  return result;
163
- }
172
+ }, "NamespaceEnv");
@@ -5,6 +5,8 @@
5
5
  * Creates fine-grained ingress/egress policies for a single application.
6
6
  */
7
7
 
8
+ import { Composite, mergeDefaults } from "@intentius/chant";
9
+ import { Deployment, Service, NetworkPolicy } from "../generated";
8
10
  import type { ContainerSecurityContext } from "./security-context";
9
11
 
10
12
  export interface NetworkPolicyPeer {
@@ -48,12 +50,18 @@ export interface NetworkIsolatedAppProps {
48
50
  env?: Array<{ name: string; value: string }>;
49
51
  /** Container security context (supports PSS restricted fields). */
50
52
  securityContext?: ContainerSecurityContext;
53
+ /** Per-member defaults for fine-grained overrides. */
54
+ defaults?: {
55
+ deployment?: Partial<Record<string, unknown>>;
56
+ service?: Partial<Record<string, unknown>>;
57
+ networkPolicy?: Partial<Record<string, unknown>>;
58
+ };
51
59
  }
52
60
 
53
61
  export interface NetworkIsolatedAppResult {
54
- deployment: Record<string, unknown>;
55
- service: Record<string, unknown>;
56
- networkPolicy: Record<string, unknown>;
62
+ deployment: InstanceType<typeof Deployment>;
63
+ service: InstanceType<typeof Service>;
64
+ networkPolicy: InstanceType<typeof NetworkPolicy>;
57
65
  }
58
66
 
59
67
  /**
@@ -77,7 +85,7 @@ export interface NetworkIsolatedAppResult {
77
85
  * });
78
86
  * ```
79
87
  */
80
- export function NetworkIsolatedApp(props: NetworkIsolatedAppProps): NetworkIsolatedAppResult {
88
+ export const NetworkIsolatedApp = Composite<NetworkIsolatedAppProps>((props) => {
81
89
  const {
82
90
  name,
83
91
  image,
@@ -93,6 +101,7 @@ export function NetworkIsolatedApp(props: NetworkIsolatedAppProps): NetworkIsola
93
101
  namespace,
94
102
  env,
95
103
  securityContext,
104
+ defaults: defs,
96
105
  } = props;
97
106
 
98
107
  const commonLabels: Record<string, string> = {
@@ -101,7 +110,7 @@ export function NetworkIsolatedApp(props: NetworkIsolatedAppProps): NetworkIsola
101
110
  ...extraLabels,
102
111
  };
103
112
 
104
- const deploymentProps: Record<string, unknown> = {
113
+ const deployment = new Deployment(mergeDefaults({
105
114
  metadata: {
106
115
  name,
107
116
  ...(namespace && { namespace }),
@@ -129,9 +138,9 @@ export function NetworkIsolatedApp(props: NetworkIsolatedAppProps): NetworkIsola
129
138
  },
130
139
  },
131
140
  },
132
- };
141
+ }, defs?.deployment));
133
142
 
134
- const serviceProps: Record<string, unknown> = {
143
+ const service = new Service(mergeDefaults({
135
144
  metadata: {
136
145
  name,
137
146
  ...(namespace && { namespace }),
@@ -142,7 +151,7 @@ export function NetworkIsolatedApp(props: NetworkIsolatedAppProps): NetworkIsola
142
151
  ports: [{ port: 80, targetPort: port, protocol: "TCP", name: "http" }],
143
152
  type: "ClusterIP",
144
153
  },
145
- };
154
+ }, defs?.service));
146
155
 
147
156
  // Build network policy
148
157
  const policyTypes: string[] = [];
@@ -185,18 +194,14 @@ export function NetworkIsolatedApp(props: NetworkIsolatedAppProps): NetworkIsola
185
194
  policySpec.policyTypes = policyTypes;
186
195
  }
187
196
 
188
- const networkPolicyProps: Record<string, unknown> = {
197
+ const networkPolicy = new NetworkPolicy(mergeDefaults({
189
198
  metadata: {
190
199
  name: `${name}-policy`,
191
200
  ...(namespace && { namespace }),
192
201
  labels: { ...commonLabels, "app.kubernetes.io/component": "network-policy" },
193
202
  },
194
203
  spec: policySpec,
195
- };
204
+ }, defs?.networkPolicy));
196
205
 
197
- return {
198
- deployment: deploymentProps,
199
- service: serviceProps,
200
- networkPolicy: networkPolicyProps,
201
- };
202
- }
206
+ return { deployment, service, networkPolicy };
207
+ }, "NetworkIsolatedApp");