@intentius/chant-lexicon-k8s 0.0.18 → 0.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/integrity.json +9 -4
- package/dist/manifest.json +1 -1
- package/dist/skills/chant-k8s-aks.md +146 -0
- package/{src/skills/kubernetes-patterns.md → dist/skills/chant-k8s-deployment-strategies.md} +1 -1
- package/dist/skills/chant-k8s-eks.md +156 -0
- package/dist/skills/chant-k8s-gke.md +246 -0
- package/{src/skills/kubernetes-security.md → dist/skills/chant-k8s-security.md} +1 -1
- package/dist/skills/chant-k8s.md +66 -3
- package/package.json +20 -2
- package/src/composites/adot-collector.ts +34 -22
- package/src/composites/agic-ingress.ts +14 -6
- package/src/composites/aks-external-dns-agent.ts +29 -18
- package/src/composites/alb-ingress.ts +14 -6
- package/src/composites/autoscaled-service.ts +25 -20
- package/src/composites/azure-disk-storage-class.ts +14 -6
- package/src/composites/azure-file-storage-class.ts +14 -6
- package/src/composites/azure-monitor-collector.ts +34 -22
- package/src/composites/batch-job.ts +25 -17
- package/src/composites/cockroachdb-cluster.ts +148 -58
- package/src/composites/composites.test.ts +369 -363
- package/src/composites/config-connector-context.ts +15 -8
- package/src/composites/configured-app.ts +21 -15
- package/src/composites/cron-workload.ts +25 -20
- package/src/composites/ebs-storage-class.ts +14 -6
- package/src/composites/efs-storage-class.ts +14 -6
- package/src/composites/external-dns-agent.ts +26 -20
- package/src/composites/filestore-storage-class.ts +14 -6
- package/src/composites/fluent-bit-agent.ts +30 -24
- package/src/composites/gce-ingress.ts +14 -6
- package/src/composites/gce-pd-storage-class.ts +14 -6
- package/src/composites/gke-external-dns-agent.ts +34 -21
- package/src/composites/gke-fluent-bit-agent.ts +34 -22
- package/src/composites/gke-gateway.ts +19 -12
- package/src/composites/gke-otel-collector.ts +34 -22
- package/src/composites/irsa-service-account.ts +22 -14
- package/src/composites/metrics-server.ts +41 -26
- package/src/composites/monitored-service.ts +26 -19
- package/src/composites/namespace-env.ts +26 -17
- package/src/composites/network-isolated-app.ts +21 -16
- package/src/composites/node-agent.ts +33 -22
- package/src/composites/secure-ingress.ts +19 -11
- package/src/composites/sidecar-app.ts +17 -12
- package/src/composites/stateful-app.ts +21 -12
- package/src/composites/web-app.ts +25 -21
- package/src/composites/worker-pool.ts +40 -26
- package/src/composites/workload-identity-sa.ts +22 -14
- package/src/composites/workload-identity-service-account.ts +22 -16
- package/src/plugin.ts +130 -614
- package/src/serializer.ts +3 -0
- package/src/skills/chant-k8s-deployment-strategies.md +183 -0
- package/src/skills/chant-k8s-gke.md +55 -0
- package/src/skills/chant-k8s-patterns.md +245 -0
- package/src/skills/chant-k8s-security.md +237 -0
- package/src/skills/chant-k8s.md +305 -0
|
@@ -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:
|
|
27
|
-
role?:
|
|
28
|
-
roleBinding?:
|
|
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
|
|
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
|
|
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:
|
|
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:
|
|
23
|
-
service:
|
|
24
|
-
serviceAccount:
|
|
25
|
-
clusterRole:
|
|
26
|
-
clusterRoleBinding:
|
|
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:
|
|
42
|
+
aggregatedClusterRole: InstanceType<typeof ClusterRole>;
|
|
29
43
|
/** Binding for aggregated API auth-delegator. */
|
|
30
|
-
authDelegatorBinding:
|
|
44
|
+
authDelegatorBinding: InstanceType<typeof ClusterRoleBinding>;
|
|
31
45
|
/** APIService registration for v1beta1.metrics.k8s.io. */
|
|
32
|
-
apiService:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
61
|
-
service:
|
|
62
|
-
serviceMonitor:
|
|
63
|
-
prometheusRule?:
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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:
|
|
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:
|
|
35
|
-
resourceQuota?:
|
|
36
|
-
limitRange?:
|
|
37
|
-
networkPolicy?:
|
|
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
|
|
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
|
|
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:
|
|
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:
|
|
55
|
-
service:
|
|
56
|
-
networkPolicy:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
199
|
-
service: serviceProps,
|
|
200
|
-
networkPolicy: networkPolicyProps,
|
|
201
|
-
};
|
|
202
|
-
}
|
|
206
|
+
return { deployment, service, networkPolicy };
|
|
207
|
+
}, "NetworkIsolatedApp");
|