@intentius/chant-lexicon-k8s 0.0.13 → 0.0.14
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 +17 -15
- package/dist/manifest.json +1 -1
- package/dist/skills/chant-k8s-eks.md +156 -0
- package/dist/skills/chant-k8s-patterns.md +245 -0
- package/dist/skills/chant-k8s.md +36 -227
- package/package.json +2 -2
- package/src/codegen/docs.ts +4 -4
- package/src/composites/adot-collector.ts +239 -0
- package/src/composites/alb-ingress.ts +151 -0
- package/src/composites/autoscaled-service.ts +33 -0
- package/src/composites/batch-job.ts +188 -0
- package/src/composites/composites.test.ts +883 -0
- package/src/composites/configured-app.ts +218 -0
- package/src/composites/ebs-storage-class.ts +96 -0
- package/src/composites/efs-storage-class.ts +77 -0
- package/src/composites/external-dns-agent.ts +168 -0
- package/src/composites/fluent-bit-agent.ts +215 -0
- package/src/composites/index.ts +28 -0
- package/src/composites/irsa-service-account.ts +114 -0
- package/src/composites/metrics-server.ts +224 -0
- package/src/composites/monitored-service.ts +215 -0
- package/src/composites/network-isolated-app.ts +196 -0
- package/src/composites/secure-ingress.ts +149 -0
- package/src/composites/sidecar-app.ts +201 -0
- package/src/composites/stateful-app.ts +70 -15
- package/src/composites/web-app.ts +107 -35
- package/src/composites/worker-pool.ts +41 -4
- package/src/index.ts +19 -2
- package/src/plugin.ts +552 -241
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SidecarApp composite — multi-container Deployment + Service.
|
|
3
|
+
*
|
|
4
|
+
* Sidecar and init container patterns (envoy proxy, log forwarder,
|
|
5
|
+
* DB migration init). Supports shared volumes between containers.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface SidecarContainer {
|
|
9
|
+
/** Sidecar container name. */
|
|
10
|
+
name: string;
|
|
11
|
+
/** Container image. */
|
|
12
|
+
image: string;
|
|
13
|
+
/** Container ports. */
|
|
14
|
+
ports?: Array<{ containerPort: number; name?: string }>;
|
|
15
|
+
/** Resource limits and requests. */
|
|
16
|
+
resources?: {
|
|
17
|
+
limits?: { cpu?: string; memory?: string };
|
|
18
|
+
requests?: { cpu?: string; memory?: string };
|
|
19
|
+
};
|
|
20
|
+
/** Environment variables. */
|
|
21
|
+
env?: Array<{ name: string; value: string }>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface InitContainer {
|
|
25
|
+
/** Init container name. */
|
|
26
|
+
name: string;
|
|
27
|
+
/** Container image. */
|
|
28
|
+
image: string;
|
|
29
|
+
/** Command to run. */
|
|
30
|
+
command?: string[];
|
|
31
|
+
/** Arguments to the command. */
|
|
32
|
+
args?: string[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface SharedVolume {
|
|
36
|
+
/** Volume name. */
|
|
37
|
+
name: string;
|
|
38
|
+
/** Use emptyDir (default). */
|
|
39
|
+
emptyDir?: Record<string, unknown>;
|
|
40
|
+
/** Use a ConfigMap by name. */
|
|
41
|
+
configMapName?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface SidecarAppProps {
|
|
45
|
+
/** Application name — used in metadata and labels. */
|
|
46
|
+
name: string;
|
|
47
|
+
/** Primary container image. */
|
|
48
|
+
image: string;
|
|
49
|
+
/** Primary container port (default: 80). */
|
|
50
|
+
port?: number;
|
|
51
|
+
/** Number of replicas (default: 2). */
|
|
52
|
+
replicas?: number;
|
|
53
|
+
/** Sidecar containers. */
|
|
54
|
+
sidecars: SidecarContainer[];
|
|
55
|
+
/** Init containers (run before main containers). */
|
|
56
|
+
initContainers?: InitContainer[];
|
|
57
|
+
/** Shared volumes between containers. */
|
|
58
|
+
sharedVolumes?: SharedVolume[];
|
|
59
|
+
/** Additional labels to apply to all resources. */
|
|
60
|
+
labels?: Record<string, string>;
|
|
61
|
+
/** CPU limit for the primary container (default: "500m"). */
|
|
62
|
+
cpuLimit?: string;
|
|
63
|
+
/** Memory limit for the primary container (default: "256Mi"). */
|
|
64
|
+
memoryLimit?: string;
|
|
65
|
+
/** CPU request for the primary container (default: "100m"). */
|
|
66
|
+
cpuRequest?: string;
|
|
67
|
+
/** Memory request for the primary container (default: "128Mi"). */
|
|
68
|
+
memoryRequest?: string;
|
|
69
|
+
/** Namespace for all resources. */
|
|
70
|
+
namespace?: string;
|
|
71
|
+
/** Environment variables for the primary container. */
|
|
72
|
+
env?: Array<{ name: string; value: string }>;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface SidecarAppResult {
|
|
76
|
+
deployment: Record<string, unknown>;
|
|
77
|
+
service: Record<string, unknown>;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Create a SidecarApp composite — returns prop objects for
|
|
82
|
+
* a multi-container Deployment and Service.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* import { SidecarApp } from "@intentius/chant-lexicon-k8s";
|
|
87
|
+
*
|
|
88
|
+
* const { deployment, service } = SidecarApp({
|
|
89
|
+
* name: "api",
|
|
90
|
+
* image: "api:1.0",
|
|
91
|
+
* port: 8080,
|
|
92
|
+
* sidecars: [
|
|
93
|
+
* { name: "envoy", image: "envoyproxy/envoy:v1.28", ports: [{ containerPort: 9901 }] },
|
|
94
|
+
* ],
|
|
95
|
+
* initContainers: [
|
|
96
|
+
* { name: "migrate", image: "api:1.0", command: ["python", "manage.py", "migrate"] },
|
|
97
|
+
* ],
|
|
98
|
+
* sharedVolumes: [{ name: "tmp", emptyDir: {} }],
|
|
99
|
+
* });
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export function SidecarApp(props: SidecarAppProps): SidecarAppResult {
|
|
103
|
+
const {
|
|
104
|
+
name,
|
|
105
|
+
image,
|
|
106
|
+
port = 80,
|
|
107
|
+
replicas = 2,
|
|
108
|
+
sidecars,
|
|
109
|
+
initContainers,
|
|
110
|
+
sharedVolumes,
|
|
111
|
+
labels: extraLabels = {},
|
|
112
|
+
cpuLimit = "500m",
|
|
113
|
+
memoryLimit = "256Mi",
|
|
114
|
+
cpuRequest = "100m",
|
|
115
|
+
memoryRequest = "128Mi",
|
|
116
|
+
namespace,
|
|
117
|
+
env,
|
|
118
|
+
} = props;
|
|
119
|
+
|
|
120
|
+
const commonLabels: Record<string, string> = {
|
|
121
|
+
"app.kubernetes.io/name": name,
|
|
122
|
+
"app.kubernetes.io/managed-by": "chant",
|
|
123
|
+
...extraLabels,
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// Primary container
|
|
127
|
+
const primaryContainer: Record<string, unknown> = {
|
|
128
|
+
name,
|
|
129
|
+
image,
|
|
130
|
+
ports: [{ containerPort: port, name: "http" }],
|
|
131
|
+
resources: {
|
|
132
|
+
limits: { cpu: cpuLimit, memory: memoryLimit },
|
|
133
|
+
requests: { cpu: cpuRequest, memory: memoryRequest },
|
|
134
|
+
},
|
|
135
|
+
...(env && { env }),
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// Sidecar containers
|
|
139
|
+
const sidecarContainers = sidecars.map((sc) => ({
|
|
140
|
+
name: sc.name,
|
|
141
|
+
image: sc.image,
|
|
142
|
+
...(sc.ports && { ports: sc.ports }),
|
|
143
|
+
...(sc.resources && { resources: sc.resources }),
|
|
144
|
+
...(sc.env && { env: sc.env }),
|
|
145
|
+
}));
|
|
146
|
+
|
|
147
|
+
// Build volumes from sharedVolumes
|
|
148
|
+
const volumes: Array<Record<string, unknown>> | undefined = sharedVolumes?.map((sv) => {
|
|
149
|
+
if (sv.configMapName) {
|
|
150
|
+
return { name: sv.name, configMap: { name: sv.configMapName } };
|
|
151
|
+
}
|
|
152
|
+
return { name: sv.name, emptyDir: sv.emptyDir ?? {} };
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
const podSpec: Record<string, unknown> = {
|
|
156
|
+
containers: [primaryContainer, ...sidecarContainers],
|
|
157
|
+
...(initContainers && {
|
|
158
|
+
initContainers: initContainers.map((ic) => ({
|
|
159
|
+
name: ic.name,
|
|
160
|
+
image: ic.image,
|
|
161
|
+
...(ic.command && { command: ic.command }),
|
|
162
|
+
...(ic.args && { args: ic.args }),
|
|
163
|
+
})),
|
|
164
|
+
}),
|
|
165
|
+
...(volumes && volumes.length > 0 && { volumes }),
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const deploymentProps: Record<string, unknown> = {
|
|
169
|
+
metadata: {
|
|
170
|
+
name,
|
|
171
|
+
...(namespace && { namespace }),
|
|
172
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "server" },
|
|
173
|
+
},
|
|
174
|
+
spec: {
|
|
175
|
+
replicas,
|
|
176
|
+
selector: { matchLabels: { "app.kubernetes.io/name": name } },
|
|
177
|
+
template: {
|
|
178
|
+
metadata: { labels: { "app.kubernetes.io/name": name, ...extraLabels } },
|
|
179
|
+
spec: podSpec,
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const serviceProps: Record<string, unknown> = {
|
|
185
|
+
metadata: {
|
|
186
|
+
name,
|
|
187
|
+
...(namespace && { namespace }),
|
|
188
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "server" },
|
|
189
|
+
},
|
|
190
|
+
spec: {
|
|
191
|
+
selector: { "app.kubernetes.io/name": name },
|
|
192
|
+
ports: [{ port: 80, targetPort: port, protocol: "TCP", name: "http" }],
|
|
193
|
+
type: "ClusterIP",
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
deployment: deploymentProps,
|
|
199
|
+
service: serviceProps,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
@@ -20,6 +20,26 @@ export interface StatefulAppProps {
|
|
|
20
20
|
storageClassName?: string;
|
|
21
21
|
/** Volume mount path inside the container (default: "/data"). */
|
|
22
22
|
mountPath?: string;
|
|
23
|
+
/** PodDisruptionBudget minAvailable — if set, creates a PDB. */
|
|
24
|
+
minAvailable?: number | string;
|
|
25
|
+
/** Init containers (e.g., schema migrations, permission setup). */
|
|
26
|
+
initContainers?: Array<{
|
|
27
|
+
name: string;
|
|
28
|
+
image: string;
|
|
29
|
+
command?: string[];
|
|
30
|
+
args?: string[];
|
|
31
|
+
}>;
|
|
32
|
+
/** Pod security context. */
|
|
33
|
+
securityContext?: {
|
|
34
|
+
runAsNonRoot?: boolean;
|
|
35
|
+
readOnlyRootFilesystem?: boolean;
|
|
36
|
+
runAsUser?: number;
|
|
37
|
+
runAsGroup?: number;
|
|
38
|
+
};
|
|
39
|
+
/** Termination grace period in seconds. */
|
|
40
|
+
terminationGracePeriodSeconds?: number;
|
|
41
|
+
/** Priority class name for pod scheduling. */
|
|
42
|
+
priorityClassName?: string;
|
|
23
43
|
/** Additional labels to apply to all resources. */
|
|
24
44
|
labels?: Record<string, string>;
|
|
25
45
|
/** CPU limit (e.g., "1"). */
|
|
@@ -35,6 +55,7 @@ export interface StatefulAppProps {
|
|
|
35
55
|
export interface StatefulAppResult {
|
|
36
56
|
statefulSet: Record<string, unknown>;
|
|
37
57
|
service: Record<string, unknown>;
|
|
58
|
+
pdb?: Record<string, unknown>;
|
|
38
59
|
}
|
|
39
60
|
|
|
40
61
|
/**
|
|
@@ -63,6 +84,11 @@ export function StatefulApp(props: StatefulAppProps): StatefulAppResult {
|
|
|
63
84
|
storageSize = "10Gi",
|
|
64
85
|
storageClassName,
|
|
65
86
|
mountPath = "/data",
|
|
87
|
+
minAvailable,
|
|
88
|
+
initContainers,
|
|
89
|
+
securityContext,
|
|
90
|
+
terminationGracePeriodSeconds,
|
|
91
|
+
priorityClassName,
|
|
66
92
|
labels: extraLabels = {},
|
|
67
93
|
cpuLimit = "1",
|
|
68
94
|
memoryLimit = "1Gi",
|
|
@@ -76,6 +102,32 @@ export function StatefulApp(props: StatefulAppProps): StatefulAppResult {
|
|
|
76
102
|
...extraLabels,
|
|
77
103
|
};
|
|
78
104
|
|
|
105
|
+
const container: Record<string, unknown> = {
|
|
106
|
+
name,
|
|
107
|
+
image,
|
|
108
|
+
ports: [{ containerPort: port, name: "app" }],
|
|
109
|
+
resources: {
|
|
110
|
+
limits: { cpu: cpuLimit, memory: memoryLimit },
|
|
111
|
+
},
|
|
112
|
+
volumeMounts: [{ name: "data", mountPath }],
|
|
113
|
+
...(env && { env }),
|
|
114
|
+
...(securityContext && { securityContext }),
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const podSpec: Record<string, unknown> = {
|
|
118
|
+
containers: [container],
|
|
119
|
+
...(initContainers && {
|
|
120
|
+
initContainers: initContainers.map((ic) => ({
|
|
121
|
+
name: ic.name,
|
|
122
|
+
image: ic.image,
|
|
123
|
+
...(ic.command && { command: ic.command }),
|
|
124
|
+
...(ic.args && { args: ic.args }),
|
|
125
|
+
})),
|
|
126
|
+
}),
|
|
127
|
+
...(terminationGracePeriodSeconds !== undefined && { terminationGracePeriodSeconds }),
|
|
128
|
+
...(priorityClassName && { priorityClassName }),
|
|
129
|
+
};
|
|
130
|
+
|
|
79
131
|
const statefulSetProps: Record<string, unknown> = {
|
|
80
132
|
metadata: {
|
|
81
133
|
name,
|
|
@@ -88,20 +140,7 @@ export function StatefulApp(props: StatefulAppProps): StatefulAppResult {
|
|
|
88
140
|
selector: { matchLabels: { "app.kubernetes.io/name": name } },
|
|
89
141
|
template: {
|
|
90
142
|
metadata: { labels: { "app.kubernetes.io/name": name, ...extraLabels } },
|
|
91
|
-
spec:
|
|
92
|
-
containers: [
|
|
93
|
-
{
|
|
94
|
-
name,
|
|
95
|
-
image,
|
|
96
|
-
ports: [{ containerPort: port, name: "app" }],
|
|
97
|
-
resources: {
|
|
98
|
-
limits: { cpu: cpuLimit, memory: memoryLimit },
|
|
99
|
-
},
|
|
100
|
-
volumeMounts: [{ name: "data", mountPath }],
|
|
101
|
-
...(env && { env }),
|
|
102
|
-
},
|
|
103
|
-
],
|
|
104
|
-
},
|
|
143
|
+
spec: podSpec,
|
|
105
144
|
},
|
|
106
145
|
volumeClaimTemplates: [
|
|
107
146
|
{
|
|
@@ -130,5 +169,21 @@ export function StatefulApp(props: StatefulAppProps): StatefulAppResult {
|
|
|
130
169
|
},
|
|
131
170
|
};
|
|
132
171
|
|
|
133
|
-
|
|
172
|
+
const result: StatefulAppResult = { statefulSet: statefulSetProps, service: serviceProps };
|
|
173
|
+
|
|
174
|
+
if (minAvailable !== undefined) {
|
|
175
|
+
result.pdb = {
|
|
176
|
+
metadata: {
|
|
177
|
+
name,
|
|
178
|
+
...(namespace && { namespace }),
|
|
179
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "disruption-budget" },
|
|
180
|
+
},
|
|
181
|
+
spec: {
|
|
182
|
+
minAvailable,
|
|
183
|
+
selector: { matchLabels: { "app.kubernetes.io/name": name } },
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return result;
|
|
134
189
|
}
|
|
@@ -18,6 +18,33 @@ export interface WebAppProps {
|
|
|
18
18
|
ingressHost?: string;
|
|
19
19
|
/** Ingress TLS secret name — if set, enables TLS on the Ingress. */
|
|
20
20
|
ingressTlsSecret?: string;
|
|
21
|
+
/** Multi-path ingress rules — overrides the default single "/" path. */
|
|
22
|
+
ingressPaths?: Array<{
|
|
23
|
+
path: string;
|
|
24
|
+
pathType?: string;
|
|
25
|
+
serviceName?: string;
|
|
26
|
+
servicePort?: number;
|
|
27
|
+
}>;
|
|
28
|
+
/** PodDisruptionBudget minAvailable — if set, creates a PDB. */
|
|
29
|
+
minAvailable?: number | string;
|
|
30
|
+
/** Init containers (e.g., migrations, cert setup). */
|
|
31
|
+
initContainers?: Array<{
|
|
32
|
+
name: string;
|
|
33
|
+
image: string;
|
|
34
|
+
command?: string[];
|
|
35
|
+
args?: string[];
|
|
36
|
+
}>;
|
|
37
|
+
/** Pod security context — safe defaults when enabled. */
|
|
38
|
+
securityContext?: {
|
|
39
|
+
runAsNonRoot?: boolean;
|
|
40
|
+
readOnlyRootFilesystem?: boolean;
|
|
41
|
+
runAsUser?: number;
|
|
42
|
+
runAsGroup?: number;
|
|
43
|
+
};
|
|
44
|
+
/** Termination grace period in seconds. */
|
|
45
|
+
terminationGracePeriodSeconds?: number;
|
|
46
|
+
/** Priority class name for pod scheduling. */
|
|
47
|
+
priorityClassName?: string;
|
|
21
48
|
/** Additional labels to apply to all resources. */
|
|
22
49
|
labels?: Record<string, string>;
|
|
23
50
|
/** CPU limit (e.g., "500m"). */
|
|
@@ -38,6 +65,7 @@ export interface WebAppResult {
|
|
|
38
65
|
deployment: Record<string, unknown>;
|
|
39
66
|
service: Record<string, unknown>;
|
|
40
67
|
ingress?: Record<string, unknown>;
|
|
68
|
+
pdb?: Record<string, unknown>;
|
|
41
69
|
}
|
|
42
70
|
|
|
43
71
|
/**
|
|
@@ -72,6 +100,11 @@ export function WebApp(props: WebAppProps): WebAppResult {
|
|
|
72
100
|
memoryRequest = "128Mi",
|
|
73
101
|
namespace,
|
|
74
102
|
env,
|
|
103
|
+
initContainers,
|
|
104
|
+
securityContext,
|
|
105
|
+
terminationGracePeriodSeconds,
|
|
106
|
+
priorityClassName,
|
|
107
|
+
minAvailable,
|
|
75
108
|
} = props;
|
|
76
109
|
|
|
77
110
|
const commonLabels: Record<string, string> = {
|
|
@@ -80,6 +113,42 @@ export function WebApp(props: WebAppProps): WebAppResult {
|
|
|
80
113
|
...extraLabels,
|
|
81
114
|
};
|
|
82
115
|
|
|
116
|
+
const container: Record<string, unknown> = {
|
|
117
|
+
name,
|
|
118
|
+
image,
|
|
119
|
+
ports: [{ containerPort: port, name: "http" }],
|
|
120
|
+
resources: {
|
|
121
|
+
limits: { cpu: cpuLimit, memory: memoryLimit },
|
|
122
|
+
requests: { cpu: cpuRequest, memory: memoryRequest },
|
|
123
|
+
},
|
|
124
|
+
livenessProbe: {
|
|
125
|
+
httpGet: { path: "/", port },
|
|
126
|
+
initialDelaySeconds: 10,
|
|
127
|
+
periodSeconds: 10,
|
|
128
|
+
},
|
|
129
|
+
readinessProbe: {
|
|
130
|
+
httpGet: { path: "/", port },
|
|
131
|
+
initialDelaySeconds: 5,
|
|
132
|
+
periodSeconds: 5,
|
|
133
|
+
},
|
|
134
|
+
...(env && { env }),
|
|
135
|
+
...(securityContext && { securityContext }),
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const podSpec: Record<string, unknown> = {
|
|
139
|
+
containers: [container],
|
|
140
|
+
...(initContainers && {
|
|
141
|
+
initContainers: initContainers.map((ic) => ({
|
|
142
|
+
name: ic.name,
|
|
143
|
+
image: ic.image,
|
|
144
|
+
...(ic.command && { command: ic.command }),
|
|
145
|
+
...(ic.args && { args: ic.args }),
|
|
146
|
+
})),
|
|
147
|
+
}),
|
|
148
|
+
...(terminationGracePeriodSeconds !== undefined && { terminationGracePeriodSeconds }),
|
|
149
|
+
...(priorityClassName && { priorityClassName }),
|
|
150
|
+
};
|
|
151
|
+
|
|
83
152
|
// We return plain objects that users pass to constructors.
|
|
84
153
|
// The actual resource instantiation happens in user code with the generated classes.
|
|
85
154
|
const deploymentProps: Record<string, unknown> = {
|
|
@@ -93,30 +162,7 @@ export function WebApp(props: WebAppProps): WebAppResult {
|
|
|
93
162
|
selector: { matchLabels: { "app.kubernetes.io/name": name } },
|
|
94
163
|
template: {
|
|
95
164
|
metadata: { labels: { "app.kubernetes.io/name": name, ...extraLabels } },
|
|
96
|
-
spec:
|
|
97
|
-
containers: [
|
|
98
|
-
{
|
|
99
|
-
name,
|
|
100
|
-
image,
|
|
101
|
-
ports: [{ containerPort: port, name: "http" }],
|
|
102
|
-
resources: {
|
|
103
|
-
limits: { cpu: cpuLimit, memory: memoryLimit },
|
|
104
|
-
requests: { cpu: cpuRequest, memory: memoryRequest },
|
|
105
|
-
},
|
|
106
|
-
livenessProbe: {
|
|
107
|
-
httpGet: { path: "/", port },
|
|
108
|
-
initialDelaySeconds: 10,
|
|
109
|
-
periodSeconds: 10,
|
|
110
|
-
},
|
|
111
|
-
readinessProbe: {
|
|
112
|
-
httpGet: { path: "/", port },
|
|
113
|
-
initialDelaySeconds: 5,
|
|
114
|
-
periodSeconds: 5,
|
|
115
|
-
},
|
|
116
|
-
...(env && { env }),
|
|
117
|
-
},
|
|
118
|
-
],
|
|
119
|
-
},
|
|
165
|
+
spec: podSpec,
|
|
120
166
|
},
|
|
121
167
|
},
|
|
122
168
|
};
|
|
@@ -140,6 +186,28 @@ export function WebApp(props: WebAppProps): WebAppResult {
|
|
|
140
186
|
};
|
|
141
187
|
|
|
142
188
|
if (props.ingressHost) {
|
|
189
|
+
// Build paths — use ingressPaths if provided, otherwise default single "/"
|
|
190
|
+
const paths = props.ingressPaths
|
|
191
|
+
? props.ingressPaths.map((p) => ({
|
|
192
|
+
path: p.path,
|
|
193
|
+
pathType: p.pathType ?? "Prefix",
|
|
194
|
+
backend: {
|
|
195
|
+
service: {
|
|
196
|
+
name: p.serviceName ?? name,
|
|
197
|
+
port: { number: p.servicePort ?? 80 },
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
}))
|
|
201
|
+
: [
|
|
202
|
+
{
|
|
203
|
+
path: "/",
|
|
204
|
+
pathType: "Prefix",
|
|
205
|
+
backend: {
|
|
206
|
+
service: { name, port: { number: 80 } },
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
];
|
|
210
|
+
|
|
143
211
|
const ingressProps: Record<string, unknown> = {
|
|
144
212
|
metadata: {
|
|
145
213
|
name,
|
|
@@ -150,17 +218,7 @@ export function WebApp(props: WebAppProps): WebAppResult {
|
|
|
150
218
|
rules: [
|
|
151
219
|
{
|
|
152
220
|
host: props.ingressHost,
|
|
153
|
-
http: {
|
|
154
|
-
paths: [
|
|
155
|
-
{
|
|
156
|
-
path: "/",
|
|
157
|
-
pathType: "Prefix",
|
|
158
|
-
backend: {
|
|
159
|
-
service: { name, port: { number: 80 } },
|
|
160
|
-
},
|
|
161
|
-
},
|
|
162
|
-
],
|
|
163
|
-
},
|
|
221
|
+
http: { paths },
|
|
164
222
|
},
|
|
165
223
|
],
|
|
166
224
|
...(props.ingressTlsSecret && {
|
|
@@ -176,5 +234,19 @@ export function WebApp(props: WebAppProps): WebAppResult {
|
|
|
176
234
|
result.ingress = ingressProps;
|
|
177
235
|
}
|
|
178
236
|
|
|
237
|
+
if (minAvailable !== undefined) {
|
|
238
|
+
result.pdb = {
|
|
239
|
+
metadata: {
|
|
240
|
+
name,
|
|
241
|
+
...(namespace && { namespace }),
|
|
242
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "disruption-budget" },
|
|
243
|
+
},
|
|
244
|
+
spec: {
|
|
245
|
+
minAvailable,
|
|
246
|
+
selector: { matchLabels: { "app.kubernetes.io/name": name } },
|
|
247
|
+
},
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
|
|
179
251
|
return result;
|
|
180
252
|
}
|
|
@@ -30,6 +30,19 @@ export interface WorkerPoolProps {
|
|
|
30
30
|
maxReplicas: number;
|
|
31
31
|
targetCPUPercent?: number;
|
|
32
32
|
};
|
|
33
|
+
/** PodDisruptionBudget minAvailable — if set, creates a PDB. */
|
|
34
|
+
minAvailable?: number | string;
|
|
35
|
+
/** Pod security context. */
|
|
36
|
+
securityContext?: {
|
|
37
|
+
runAsNonRoot?: boolean;
|
|
38
|
+
readOnlyRootFilesystem?: boolean;
|
|
39
|
+
runAsUser?: number;
|
|
40
|
+
runAsGroup?: number;
|
|
41
|
+
};
|
|
42
|
+
/** Termination grace period in seconds. */
|
|
43
|
+
terminationGracePeriodSeconds?: number;
|
|
44
|
+
/** Priority class name for pod scheduling. */
|
|
45
|
+
priorityClassName?: string;
|
|
33
46
|
/** CPU request (default: "100m"). */
|
|
34
47
|
cpuRequest?: string;
|
|
35
48
|
/** Memory request (default: "128Mi"). */
|
|
@@ -53,6 +66,7 @@ export interface WorkerPoolResult {
|
|
|
53
66
|
roleBinding?: Record<string, unknown>;
|
|
54
67
|
configMap?: Record<string, unknown>;
|
|
55
68
|
hpa?: Record<string, unknown>;
|
|
69
|
+
pdb?: Record<string, unknown>;
|
|
56
70
|
}
|
|
57
71
|
|
|
58
72
|
/**
|
|
@@ -81,6 +95,10 @@ export function WorkerPool(props: WorkerPoolProps): WorkerPoolResult {
|
|
|
81
95
|
config,
|
|
82
96
|
rbacRules,
|
|
83
97
|
autoscaling,
|
|
98
|
+
minAvailable,
|
|
99
|
+
securityContext,
|
|
100
|
+
terminationGracePeriodSeconds,
|
|
101
|
+
priorityClassName,
|
|
84
102
|
cpuRequest = "100m",
|
|
85
103
|
memoryRequest = "128Mi",
|
|
86
104
|
cpuLimit = "500m",
|
|
@@ -122,6 +140,14 @@ export function WorkerPool(props: WorkerPoolProps): WorkerPoolResult {
|
|
|
122
140
|
...(config && {
|
|
123
141
|
envFrom: [{ configMapRef: { name: configMapName } }],
|
|
124
142
|
}),
|
|
143
|
+
...(securityContext && { securityContext }),
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const podSpec: Record<string, unknown> = {
|
|
147
|
+
...(createRbac && { serviceAccountName: saName }),
|
|
148
|
+
containers: [container],
|
|
149
|
+
...(terminationGracePeriodSeconds !== undefined && { terminationGracePeriodSeconds }),
|
|
150
|
+
...(priorityClassName && { priorityClassName }),
|
|
125
151
|
};
|
|
126
152
|
|
|
127
153
|
const deploymentProps: Record<string, unknown> = {
|
|
@@ -135,10 +161,7 @@ export function WorkerPool(props: WorkerPoolProps): WorkerPoolResult {
|
|
|
135
161
|
selector: { matchLabels: { "app.kubernetes.io/name": name } },
|
|
136
162
|
template: {
|
|
137
163
|
metadata: { labels: { "app.kubernetes.io/name": name, ...extraLabels } },
|
|
138
|
-
spec:
|
|
139
|
-
...(createRbac && { serviceAccountName: saName }),
|
|
140
|
-
containers: [container],
|
|
141
|
-
},
|
|
164
|
+
spec: podSpec,
|
|
142
165
|
},
|
|
143
166
|
},
|
|
144
167
|
};
|
|
@@ -197,6 +220,20 @@ export function WorkerPool(props: WorkerPoolProps): WorkerPoolResult {
|
|
|
197
220
|
};
|
|
198
221
|
}
|
|
199
222
|
|
|
223
|
+
if (minAvailable !== undefined) {
|
|
224
|
+
result.pdb = {
|
|
225
|
+
metadata: {
|
|
226
|
+
name,
|
|
227
|
+
...(namespace && { namespace }),
|
|
228
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "disruption-budget" },
|
|
229
|
+
},
|
|
230
|
+
spec: {
|
|
231
|
+
minAvailable,
|
|
232
|
+
selector: { matchLabels: { "app.kubernetes.io/name": name } },
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
200
237
|
if (autoscaling) {
|
|
201
238
|
const targetCPUPercent = autoscaling.targetCPUPercent ?? 70;
|
|
202
239
|
result.hpa = {
|
package/src/index.ts
CHANGED
|
@@ -16,8 +16,25 @@ export { K8sLabels, K8sAnnotations } from "./variables";
|
|
|
16
16
|
export * from "./generated/index";
|
|
17
17
|
|
|
18
18
|
// Composites
|
|
19
|
-
export {
|
|
20
|
-
|
|
19
|
+
export {
|
|
20
|
+
WebApp, StatefulApp, CronWorkload, AutoscaledService, WorkerPool, NamespaceEnv, NodeAgent,
|
|
21
|
+
BatchJob, SecureIngress, ConfiguredApp, SidecarApp, MonitoredService, NetworkIsolatedApp,
|
|
22
|
+
IrsaServiceAccount, AlbIngress, EbsStorageClass, EfsStorageClass, FluentBitAgent, ExternalDnsAgent, AdotCollector,
|
|
23
|
+
MetricsServer,
|
|
24
|
+
} from "./composites/index";
|
|
25
|
+
export type {
|
|
26
|
+
WebAppProps, WebAppResult, StatefulAppProps, StatefulAppResult, CronWorkloadProps, CronWorkloadResult,
|
|
27
|
+
AutoscaledServiceProps, AutoscaledServiceResult, WorkerPoolProps, WorkerPoolResult,
|
|
28
|
+
NamespaceEnvProps, NamespaceEnvResult, NodeAgentProps, NodeAgentResult,
|
|
29
|
+
BatchJobProps, BatchJobResult, SecureIngressProps, SecureIngressResult,
|
|
30
|
+
ConfiguredAppProps, ConfiguredAppResult, SidecarAppProps, SidecarAppResult,
|
|
31
|
+
MonitoredServiceProps, MonitoredServiceResult, NetworkIsolatedAppProps, NetworkIsolatedAppResult,
|
|
32
|
+
IrsaServiceAccountProps, IrsaServiceAccountResult, AlbIngressProps, AlbIngressResult,
|
|
33
|
+
EbsStorageClassProps, EbsStorageClassResult, EfsStorageClassProps, EfsStorageClassResult,
|
|
34
|
+
FluentBitAgentProps, FluentBitAgentResult, ExternalDnsAgentProps, ExternalDnsAgentResult,
|
|
35
|
+
AdotCollectorProps, AdotCollectorResult,
|
|
36
|
+
MetricsServerProps, MetricsServerResult,
|
|
37
|
+
} from "./composites/index";
|
|
21
38
|
|
|
22
39
|
// RBAC verb constants
|
|
23
40
|
export * from "./actions/index";
|