@intentius/chant-lexicon-k8s 0.0.13 → 0.0.15

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 +20 -15
  2. package/dist/manifest.json +1 -1
  3. package/dist/rules/wk8204.ts +33 -1
  4. package/dist/rules/wk8304.ts +70 -0
  5. package/dist/rules/wk8305.ts +115 -0
  6. package/dist/rules/wk8306.ts +50 -0
  7. package/dist/skills/chant-k8s-eks.md +156 -0
  8. package/dist/skills/chant-k8s-patterns.md +245 -0
  9. package/dist/skills/chant-k8s.md +36 -227
  10. package/package.json +27 -24
  11. package/src/codegen/docs.ts +5 -5
  12. package/src/composites/adot-collector.ts +245 -0
  13. package/src/composites/agic-ingress.ts +149 -0
  14. package/src/composites/alb-ingress.ts +152 -0
  15. package/src/composites/autoscaled-service.ts +51 -0
  16. package/src/composites/azure-disk-storage-class.ts +82 -0
  17. package/src/composites/azure-file-storage-class.ts +77 -0
  18. package/src/composites/azure-monitor-collector.ts +232 -0
  19. package/src/composites/batch-job.ts +221 -0
  20. package/src/composites/composites.test.ts +1584 -0
  21. package/src/composites/config-connector-context.ts +62 -0
  22. package/src/composites/configured-app.ts +224 -0
  23. package/src/composites/cron-workload.ts +6 -0
  24. package/src/composites/ebs-storage-class.ts +96 -0
  25. package/src/composites/efs-storage-class.ts +77 -0
  26. package/src/composites/external-dns-agent.ts +174 -0
  27. package/src/composites/filestore-storage-class.ts +79 -0
  28. package/src/composites/fluent-bit-agent.ts +220 -0
  29. package/src/composites/gce-pd-storage-class.ts +85 -0
  30. package/src/composites/gke-gateway.ts +143 -0
  31. package/src/composites/index.ts +47 -0
  32. package/src/composites/irsa-service-account.ts +114 -0
  33. package/src/composites/metrics-server.ts +224 -0
  34. package/src/composites/monitored-service.ts +221 -0
  35. package/src/composites/network-isolated-app.ts +202 -0
  36. package/src/composites/node-agent.ts +6 -0
  37. package/src/composites/secure-ingress.ts +149 -0
  38. package/src/composites/security-context.ts +10 -0
  39. package/src/composites/sidecar-app.ts +207 -0
  40. package/src/composites/stateful-app.ts +67 -15
  41. package/src/composites/web-app.ts +104 -35
  42. package/src/composites/worker-pool.ts +38 -4
  43. package/src/composites/workload-identity-sa.ts +118 -0
  44. package/src/composites/workload-identity-service-account.ts +116 -0
  45. package/src/index.ts +24 -2
  46. package/src/lint/post-synth/post-synth.test.ts +362 -1
  47. package/src/lint/post-synth/wk8204.ts +33 -1
  48. package/src/lint/post-synth/wk8304.ts +70 -0
  49. package/src/lint/post-synth/wk8305.ts +115 -0
  50. package/src/lint/post-synth/wk8306.ts +50 -0
  51. package/src/plugin.test.ts +2 -2
  52. package/src/plugin.ts +556 -242
  53. package/src/serializer.test.ts +120 -0
  54. package/src/serializer.ts +16 -4
@@ -0,0 +1,62 @@
1
+ /**
2
+ * ConfigConnectorContext composite — bootstrap Config Connector per-namespace context.
3
+ *
4
+ * @gke Creates a ConfigConnectorContext resource that configures
5
+ * Config Connector to manage GCP resources in a specific namespace.
6
+ */
7
+
8
+ export interface ConfigConnectorContextProps {
9
+ /** Context name (default: "configconnectorcontext.core.cnrm.cloud.google.com"). */
10
+ name?: string;
11
+ /** Google service account email for Config Connector to use. */
12
+ googleServiceAccountEmail: string;
13
+ /** Namespace for the context (default: "default"). */
14
+ namespace?: string;
15
+ /** Whether to sync status into spec (default: "absent"). */
16
+ stateIntoSpec?: "absent" | "merge";
17
+ }
18
+
19
+ export interface ConfigConnectorContextResult {
20
+ context: Record<string, unknown>;
21
+ }
22
+
23
+ /**
24
+ * Create a ConfigConnectorContext composite — returns prop objects for
25
+ * a ConfigConnectorContext resource.
26
+ *
27
+ * @gke
28
+ * @example
29
+ * ```ts
30
+ * import { ConfigConnectorContext } from "@intentius/chant-lexicon-k8s";
31
+ *
32
+ * const { context } = ConfigConnectorContext({
33
+ * googleServiceAccountEmail: "cnrm@my-project.iam.gserviceaccount.com",
34
+ * namespace: "config-connector",
35
+ * });
36
+ * ```
37
+ */
38
+ export function ConfigConnectorContext(
39
+ props: ConfigConnectorContextProps,
40
+ ): ConfigConnectorContextResult {
41
+ const {
42
+ name = "configconnectorcontext.core.cnrm.cloud.google.com",
43
+ googleServiceAccountEmail,
44
+ namespace = "default",
45
+ stateIntoSpec = "absent",
46
+ } = props;
47
+
48
+ const contextProps: Record<string, unknown> = {
49
+ apiVersion: "core.cnrm.cloud.google.com/v1beta1",
50
+ kind: "ConfigConnectorContext",
51
+ metadata: {
52
+ name,
53
+ namespace,
54
+ },
55
+ spec: {
56
+ googleServiceAccount: googleServiceAccountEmail,
57
+ stateIntoSpec,
58
+ },
59
+ };
60
+
61
+ return { context: contextProps };
62
+ }
@@ -0,0 +1,224 @@
1
+ /**
2
+ * ConfiguredApp composite — Deployment + Service + optional ConfigMap.
3
+ *
4
+ * Wires ConfigMap→Volume→VolumeMount and Secret→Volume→VolumeMount
5
+ * triangles, plus envFrom injection. Covers cdk8s-plus Volume.fromConfigMap(),
6
+ * Volume.fromSecret(), and container.mount() patterns.
7
+ */
8
+
9
+ import type { ContainerSecurityContext } from "./security-context";
10
+
11
+ export interface ConfiguredAppProps {
12
+ /** Application name — used in metadata and labels. */
13
+ name: string;
14
+ /** Container image. */
15
+ image: string;
16
+ /** Container port (default: 80). */
17
+ port?: number;
18
+ /** Number of replicas (default: 2). */
19
+ replicas?: number;
20
+ /** Config data — creates a ConfigMap. */
21
+ configData?: Record<string, string>;
22
+ /** Mount path for the ConfigMap volume. */
23
+ configMountPath?: string;
24
+ /** Existing Secret name to mount as a volume. */
25
+ secretName?: string;
26
+ /** Mount path for the Secret volume. */
27
+ secretMountPath?: string;
28
+ /** Inject config/secrets as environment variables. */
29
+ envFrom?: {
30
+ configMapRef?: string;
31
+ secretRef?: string;
32
+ };
33
+ /** Init containers (e.g., migrations, cert setup). */
34
+ initContainers?: Array<{
35
+ name: string;
36
+ image: string;
37
+ command?: string[];
38
+ args?: string[];
39
+ }>;
40
+ /** Additional labels to apply to all resources. */
41
+ labels?: Record<string, string>;
42
+ /** CPU limit (default: "500m"). */
43
+ cpuLimit?: string;
44
+ /** Memory limit (default: "256Mi"). */
45
+ memoryLimit?: string;
46
+ /** CPU request (default: "100m"). */
47
+ cpuRequest?: string;
48
+ /** Memory request (default: "128Mi"). */
49
+ memoryRequest?: string;
50
+ /** Namespace for all resources. */
51
+ namespace?: string;
52
+ /** Environment variables for the container. */
53
+ env?: Array<{ name: string; value: string }>;
54
+ /** Container security context (supports PSS restricted fields). */
55
+ securityContext?: ContainerSecurityContext;
56
+ }
57
+
58
+ export interface ConfiguredAppResult {
59
+ deployment: Record<string, unknown>;
60
+ service: Record<string, unknown>;
61
+ configMap?: Record<string, unknown>;
62
+ }
63
+
64
+ /**
65
+ * Create a ConfiguredApp composite — returns prop objects for
66
+ * a Deployment, Service, and optional ConfigMap.
67
+ *
68
+ * @example
69
+ * ```ts
70
+ * import { ConfiguredApp } from "@intentius/chant-lexicon-k8s";
71
+ *
72
+ * const { deployment, service, configMap } = ConfiguredApp({
73
+ * name: "api",
74
+ * image: "api:1.0",
75
+ * port: 8080,
76
+ * configData: { "app.conf": "key=value" },
77
+ * configMountPath: "/etc/api",
78
+ * secretName: "api-creds",
79
+ * secretMountPath: "/secrets",
80
+ * envFrom: { secretRef: "api-env-secret" },
81
+ * });
82
+ * ```
83
+ */
84
+ export function ConfiguredApp(props: ConfiguredAppProps): ConfiguredAppResult {
85
+ const {
86
+ name,
87
+ image,
88
+ port = 80,
89
+ replicas = 2,
90
+ configData,
91
+ configMountPath,
92
+ secretName,
93
+ secretMountPath,
94
+ envFrom,
95
+ initContainers,
96
+ labels: extraLabels = {},
97
+ cpuLimit = "500m",
98
+ memoryLimit = "256Mi",
99
+ cpuRequest = "100m",
100
+ memoryRequest = "128Mi",
101
+ namespace,
102
+ env,
103
+ securityContext,
104
+ } = props;
105
+
106
+ const configMapName = `${name}-config`;
107
+
108
+ const commonLabels: Record<string, string> = {
109
+ "app.kubernetes.io/name": name,
110
+ "app.kubernetes.io/managed-by": "chant",
111
+ ...extraLabels,
112
+ };
113
+
114
+ // Build volumes and volumeMounts
115
+ const volumes: Array<Record<string, unknown>> = [];
116
+ const volumeMounts: Array<Record<string, unknown>> = [];
117
+
118
+ if (configData && configMountPath) {
119
+ volumes.push({
120
+ name: "config",
121
+ configMap: { name: configMapName },
122
+ });
123
+ volumeMounts.push({
124
+ name: "config",
125
+ mountPath: configMountPath,
126
+ readOnly: true,
127
+ });
128
+ }
129
+
130
+ if (secretName && secretMountPath) {
131
+ volumes.push({
132
+ name: "secret",
133
+ secret: { secretName },
134
+ });
135
+ volumeMounts.push({
136
+ name: "secret",
137
+ mountPath: secretMountPath,
138
+ readOnly: true,
139
+ });
140
+ }
141
+
142
+ // Build envFrom array
143
+ const envFromList: Array<Record<string, unknown>> = [];
144
+ if (envFrom?.configMapRef) {
145
+ envFromList.push({ configMapRef: { name: envFrom.configMapRef } });
146
+ }
147
+ if (envFrom?.secretRef) {
148
+ envFromList.push({ secretRef: { name: envFrom.secretRef } });
149
+ }
150
+
151
+ const container: Record<string, unknown> = {
152
+ name,
153
+ image,
154
+ ports: [{ containerPort: port, name: "http" }],
155
+ resources: {
156
+ limits: { cpu: cpuLimit, memory: memoryLimit },
157
+ requests: { cpu: cpuRequest, memory: memoryRequest },
158
+ },
159
+ ...(env && { env }),
160
+ ...(envFromList.length > 0 && { envFrom: envFromList }),
161
+ ...(volumeMounts.length > 0 && { volumeMounts }),
162
+ ...(securityContext && { securityContext }),
163
+ };
164
+
165
+ const podSpec: Record<string, unknown> = {
166
+ containers: [container],
167
+ ...(volumes.length > 0 && { volumes }),
168
+ ...(initContainers && {
169
+ initContainers: initContainers.map((ic) => ({
170
+ name: ic.name,
171
+ image: ic.image,
172
+ ...(ic.command && { command: ic.command }),
173
+ ...(ic.args && { args: ic.args }),
174
+ })),
175
+ }),
176
+ };
177
+
178
+ const deploymentProps: Record<string, unknown> = {
179
+ metadata: {
180
+ name,
181
+ ...(namespace && { namespace }),
182
+ labels: { ...commonLabels, "app.kubernetes.io/component": "server" },
183
+ },
184
+ spec: {
185
+ replicas,
186
+ selector: { matchLabels: { "app.kubernetes.io/name": name } },
187
+ template: {
188
+ metadata: { labels: { "app.kubernetes.io/name": name, ...extraLabels } },
189
+ spec: podSpec,
190
+ },
191
+ },
192
+ };
193
+
194
+ const serviceProps: Record<string, unknown> = {
195
+ metadata: {
196
+ name,
197
+ ...(namespace && { namespace }),
198
+ labels: { ...commonLabels, "app.kubernetes.io/component": "server" },
199
+ },
200
+ spec: {
201
+ selector: { "app.kubernetes.io/name": name },
202
+ ports: [{ port: 80, targetPort: port, protocol: "TCP", name: "http" }],
203
+ type: "ClusterIP",
204
+ },
205
+ };
206
+
207
+ const result: ConfiguredAppResult = {
208
+ deployment: deploymentProps,
209
+ service: serviceProps,
210
+ };
211
+
212
+ if (configData) {
213
+ result.configMap = {
214
+ metadata: {
215
+ name: configMapName,
216
+ ...(namespace && { namespace }),
217
+ labels: { ...commonLabels, "app.kubernetes.io/component": "config" },
218
+ },
219
+ data: configData,
220
+ };
221
+ }
222
+
223
+ return result;
224
+ }
@@ -5,6 +5,8 @@
5
5
  * proper RBAC permissions.
6
6
  */
7
7
 
8
+ import type { ContainerSecurityContext } from "./security-context";
9
+
8
10
  export interface CronWorkloadProps {
9
11
  /** Workload name — used in metadata and labels. */
10
12
  name: string;
@@ -33,6 +35,8 @@ export interface CronWorkloadProps {
33
35
  namespace?: string;
34
36
  /** Environment variables. */
35
37
  env?: Array<{ name: string; value: string }>;
38
+ /** Container security context (supports PSS restricted fields). */
39
+ securityContext?: ContainerSecurityContext;
36
40
  }
37
41
 
38
42
  export interface CronWorkloadResult {
@@ -75,6 +79,7 @@ export function CronWorkload(props: CronWorkloadProps): CronWorkloadResult {
75
79
  labels: extraLabels = {},
76
80
  namespace,
77
81
  env,
82
+ securityContext,
78
83
  } = props;
79
84
 
80
85
  const saName = `${name}-sa`;
@@ -110,6 +115,7 @@ export function CronWorkload(props: CronWorkloadProps): CronWorkloadResult {
110
115
  ...(command && { command }),
111
116
  ...(args && { args }),
112
117
  ...(env && { env }),
118
+ ...(securityContext && { securityContext }),
113
119
  },
114
120
  ],
115
121
  },
@@ -0,0 +1,96 @@
1
+ /**
2
+ * EbsStorageClass composite — StorageClass for AWS EBS CSI driver.
3
+ *
4
+ * @eks Creates a StorageClass with the `ebs.csi.aws.com` provisioner.
5
+ */
6
+
7
+ export interface EbsStorageClassProps {
8
+ /** StorageClass name. */
9
+ name: string;
10
+ /** EBS volume type (default: "gp3"). */
11
+ type?: string;
12
+ /** IOPS for io1/io2/gp3 volumes. */
13
+ iops?: string | number;
14
+ /** Throughput for gp3 volumes (MiB/s). */
15
+ throughput?: string | number;
16
+ /** Enable encryption (default: true). */
17
+ encrypted?: boolean;
18
+ /** KMS key ID for encryption. */
19
+ kmsKeyId?: string;
20
+ /** Filesystem type (default: "ext4"). */
21
+ fsType?: string;
22
+ /** Reclaim policy (default: "Delete"). */
23
+ reclaimPolicy?: string;
24
+ /** Volume binding mode (default: "WaitForFirstConsumer"). */
25
+ volumeBindingMode?: string;
26
+ /** Allow volume expansion (default: true). */
27
+ allowVolumeExpansion?: boolean;
28
+ /** Additional labels. */
29
+ labels?: Record<string, string>;
30
+ }
31
+
32
+ export interface EbsStorageClassResult {
33
+ storageClass: Record<string, unknown>;
34
+ }
35
+
36
+ /**
37
+ * Create an EbsStorageClass composite — returns prop objects for
38
+ * a StorageClass with the EBS CSI provisioner.
39
+ *
40
+ * @eks
41
+ * @example
42
+ * ```ts
43
+ * import { EbsStorageClass } from "@intentius/chant-lexicon-k8s";
44
+ *
45
+ * const { storageClass } = EbsStorageClass({
46
+ * name: "gp3-encrypted",
47
+ * type: "gp3",
48
+ * encrypted: true,
49
+ * });
50
+ * ```
51
+ */
52
+ export function EbsStorageClass(props: EbsStorageClassProps): EbsStorageClassResult {
53
+ const {
54
+ name,
55
+ type = "gp3",
56
+ iops,
57
+ throughput,
58
+ encrypted = true,
59
+ kmsKeyId,
60
+ fsType = "ext4",
61
+ reclaimPolicy = "Delete",
62
+ volumeBindingMode = "WaitForFirstConsumer",
63
+ allowVolumeExpansion = true,
64
+ labels: extraLabels = {},
65
+ } = props;
66
+
67
+ const commonLabels: Record<string, string> = {
68
+ "app.kubernetes.io/name": name,
69
+ "app.kubernetes.io/managed-by": "chant",
70
+ ...extraLabels,
71
+ };
72
+
73
+ const parameters: Record<string, string> = {
74
+ type,
75
+ fsType,
76
+ encrypted: String(encrypted),
77
+ };
78
+
79
+ if (iops !== undefined) parameters.iops = String(iops);
80
+ if (throughput !== undefined) parameters.throughput = String(throughput);
81
+ if (kmsKeyId) parameters.kmsKeyId = kmsKeyId;
82
+
83
+ const storageClassProps: Record<string, unknown> = {
84
+ metadata: {
85
+ name,
86
+ labels: { ...commonLabels, "app.kubernetes.io/component": "storage" },
87
+ },
88
+ provisioner: "ebs.csi.aws.com",
89
+ parameters,
90
+ reclaimPolicy,
91
+ volumeBindingMode,
92
+ allowVolumeExpansion,
93
+ };
94
+
95
+ return { storageClass: storageClassProps };
96
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * EfsStorageClass composite — StorageClass for AWS EFS CSI driver.
3
+ *
4
+ * @eks Creates a StorageClass with the `efs.csi.aws.com` provisioner.
5
+ * EFS provides ReadWriteMany access mode (shared across pods/nodes).
6
+ */
7
+
8
+ export interface EfsStorageClassProps {
9
+ /** StorageClass name. */
10
+ name: string;
11
+ /** EFS filesystem ID (required). */
12
+ fileSystemId: string;
13
+ /** Directory permissions (default: "700"). */
14
+ directoryPerms?: string;
15
+ /** Base path for dynamic provisioning (default: "/dynamic_provisioning"). */
16
+ basePath?: string;
17
+ /** Reclaim policy (default: "Delete"). */
18
+ reclaimPolicy?: string;
19
+ /** Provisioning mode (default: "efs-ap"). */
20
+ provisioningMode?: string;
21
+ /** Additional labels. */
22
+ labels?: Record<string, string>;
23
+ }
24
+
25
+ export interface EfsStorageClassResult {
26
+ storageClass: Record<string, unknown>;
27
+ }
28
+
29
+ /**
30
+ * Create an EfsStorageClass composite — returns prop objects for
31
+ * a StorageClass with the EFS CSI provisioner.
32
+ *
33
+ * @eks
34
+ * @example
35
+ * ```ts
36
+ * import { EfsStorageClass } from "@intentius/chant-lexicon-k8s";
37
+ *
38
+ * const { storageClass } = EfsStorageClass({
39
+ * name: "efs-shared",
40
+ * fileSystemId: "fs-12345678",
41
+ * });
42
+ * ```
43
+ */
44
+ export function EfsStorageClass(props: EfsStorageClassProps): EfsStorageClassResult {
45
+ const {
46
+ name,
47
+ fileSystemId,
48
+ directoryPerms = "700",
49
+ basePath = "/dynamic_provisioning",
50
+ reclaimPolicy = "Delete",
51
+ provisioningMode = "efs-ap",
52
+ labels: extraLabels = {},
53
+ } = props;
54
+
55
+ const commonLabels: Record<string, string> = {
56
+ "app.kubernetes.io/name": name,
57
+ "app.kubernetes.io/managed-by": "chant",
58
+ ...extraLabels,
59
+ };
60
+
61
+ const storageClassProps: Record<string, unknown> = {
62
+ metadata: {
63
+ name,
64
+ labels: { ...commonLabels, "app.kubernetes.io/component": "storage" },
65
+ },
66
+ provisioner: "efs.csi.aws.com",
67
+ parameters: {
68
+ provisioningMode,
69
+ fileSystemId,
70
+ directoryPerms,
71
+ basePath,
72
+ },
73
+ reclaimPolicy,
74
+ };
75
+
76
+ return { storageClass: storageClassProps };
77
+ }
@@ -0,0 +1,174 @@
1
+ /**
2
+ * ExternalDnsAgent composite — Deployment + IRSA ServiceAccount + ClusterRole + ClusterRoleBinding.
3
+ *
4
+ * @eks ExternalDNS for Route53 DNS management. Common in production EKS setups
5
+ * where Ingress/Service hostnames should automatically create DNS records.
6
+ */
7
+
8
+ export interface ExternalDnsAgentProps {
9
+ /** IAM Role ARN for IRSA (needs Route53 permissions). */
10
+ iamRoleArn: string;
11
+ /** Domain filters — only manage DNS records for these domains. */
12
+ domainFilters: string[];
13
+ /** DNS provider (default: "aws"). */
14
+ provider?: string;
15
+ /** Source of DNS records (default: "ingress"). */
16
+ source?: string;
17
+ /** TXT record owner ID for identifying managed records. */
18
+ txtOwnerId?: string;
19
+ /** Agent name (default: "external-dns"). */
20
+ name?: string;
21
+ /** Container image (default: "registry.k8s.io/external-dns/external-dns:v0.14.0"). */
22
+ image?: string;
23
+ /** Namespace (default: "kube-system"). */
24
+ namespace?: string;
25
+ /** Additional labels. */
26
+ labels?: Record<string, string>;
27
+ }
28
+
29
+ export interface ExternalDnsAgentResult {
30
+ deployment: Record<string, unknown>;
31
+ serviceAccount: Record<string, unknown>;
32
+ clusterRole: Record<string, unknown>;
33
+ clusterRoleBinding: Record<string, unknown>;
34
+ }
35
+
36
+ /**
37
+ * Create an ExternalDnsAgent composite — returns prop objects for
38
+ * a Deployment, ServiceAccount (with IRSA), ClusterRole, and ClusterRoleBinding.
39
+ *
40
+ * @eks
41
+ * @example
42
+ * ```ts
43
+ * import { ExternalDnsAgent } from "@intentius/chant-lexicon-k8s";
44
+ *
45
+ * const { deployment, serviceAccount, clusterRole, clusterRoleBinding } = ExternalDnsAgent({
46
+ * iamRoleArn: "arn:aws:iam::123456789012:role/external-dns-role",
47
+ * domainFilters: ["example.com"],
48
+ * txtOwnerId: "my-cluster",
49
+ * });
50
+ * ```
51
+ */
52
+ export function ExternalDnsAgent(props: ExternalDnsAgentProps): ExternalDnsAgentResult {
53
+ const {
54
+ iamRoleArn,
55
+ domainFilters,
56
+ provider = "aws",
57
+ source = "ingress",
58
+ txtOwnerId,
59
+ name = "external-dns",
60
+ image = "registry.k8s.io/external-dns/external-dns:v0.14.0",
61
+ namespace = "kube-system",
62
+ labels: extraLabels = {},
63
+ } = props;
64
+
65
+ const saName = `${name}-sa`;
66
+ const clusterRoleName = `${name}-role`;
67
+ const bindingName = `${name}-binding`;
68
+
69
+ const commonLabels: Record<string, string> = {
70
+ "app.kubernetes.io/name": name,
71
+ "app.kubernetes.io/managed-by": "chant",
72
+ ...extraLabels,
73
+ };
74
+
75
+ // Build args for external-dns
76
+ const args: string[] = [
77
+ `--source=${source}`,
78
+ `--provider=${provider}`,
79
+ "--policy=upsert-only",
80
+ "--registry=txt",
81
+ ];
82
+
83
+ for (const domain of domainFilters) {
84
+ args.push(`--domain-filter=${domain}`);
85
+ }
86
+
87
+ if (txtOwnerId) {
88
+ args.push(`--txt-owner-id=${txtOwnerId}`);
89
+ }
90
+
91
+ const deploymentProps: Record<string, unknown> = {
92
+ metadata: {
93
+ name,
94
+ namespace,
95
+ labels: { ...commonLabels, "app.kubernetes.io/component": "dns" },
96
+ },
97
+ spec: {
98
+ replicas: 1,
99
+ selector: { matchLabels: { "app.kubernetes.io/name": name } },
100
+ template: {
101
+ metadata: { labels: { "app.kubernetes.io/name": name, ...extraLabels } },
102
+ spec: {
103
+ serviceAccountName: saName,
104
+ containers: [
105
+ {
106
+ name,
107
+ image,
108
+ args,
109
+ resources: {
110
+ requests: { cpu: "50m", memory: "64Mi" },
111
+ limits: { cpu: "100m", memory: "128Mi" },
112
+ },
113
+ securityContext: {
114
+ runAsNonRoot: true,
115
+ runAsUser: 65534,
116
+ readOnlyRootFilesystem: true,
117
+ allowPrivilegeEscalation: false,
118
+ },
119
+ },
120
+ ],
121
+ },
122
+ },
123
+ },
124
+ };
125
+
126
+ const serviceAccountProps: Record<string, unknown> = {
127
+ metadata: {
128
+ name: saName,
129
+ namespace,
130
+ labels: { ...commonLabels, "app.kubernetes.io/component": "dns" },
131
+ annotations: {
132
+ "eks.amazonaws.com/role-arn": iamRoleArn,
133
+ },
134
+ },
135
+ };
136
+
137
+ const clusterRoleProps: Record<string, unknown> = {
138
+ metadata: {
139
+ name: clusterRoleName,
140
+ labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
141
+ },
142
+ rules: [
143
+ { apiGroups: [""], resources: ["services", "endpoints", "pods"], verbs: ["get", "watch", "list"] },
144
+ { apiGroups: ["extensions", "networking.k8s.io"], resources: ["ingresses"], verbs: ["get", "watch", "list"] },
145
+ { apiGroups: [""], resources: ["nodes"], verbs: ["list", "watch"] },
146
+ ],
147
+ };
148
+
149
+ const clusterRoleBindingProps: Record<string, unknown> = {
150
+ metadata: {
151
+ name: bindingName,
152
+ labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
153
+ },
154
+ roleRef: {
155
+ apiGroup: "rbac.authorization.k8s.io",
156
+ kind: "ClusterRole",
157
+ name: clusterRoleName,
158
+ },
159
+ subjects: [
160
+ {
161
+ kind: "ServiceAccount",
162
+ name: saName,
163
+ namespace,
164
+ },
165
+ ],
166
+ };
167
+
168
+ return {
169
+ deployment: deploymentProps,
170
+ serviceAccount: serviceAccountProps,
171
+ clusterRole: clusterRoleProps,
172
+ clusterRoleBinding: clusterRoleBindingProps,
173
+ };
174
+ }