@intentius/chant-lexicon-k8s 0.0.22 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +65 -2
- package/package.json +5 -4
- 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 +164 -58
- package/src/composites/composites.test.ts +371 -365
- package/src/composites/config-connector-context.ts +18 -11
- 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 +40 -614
- package/src/serializer.ts +7 -0
- package/src/skills/chant-k8s-deployment-strategies.md +183 -0
- package/src/skills/chant-k8s-gke.md +56 -1
- 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
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
* CockroachDbCluster per cloud, sharing joinAddresses across clouds.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import { Composite, mergeDefaults } from "@intentius/chant";
|
|
11
|
+
import { StatefulSet, Service, ServiceAccount, Role, RoleBinding, ClusterRole, ClusterRoleBinding, PodDisruptionBudget, Job } from "../generated";
|
|
12
|
+
|
|
10
13
|
export interface CockroachDbClusterProps {
|
|
11
14
|
/** Cluster name — used in metadata, labels, and service names. */
|
|
12
15
|
name: string;
|
|
@@ -34,26 +37,79 @@ export interface CockroachDbClusterProps {
|
|
|
34
37
|
joinAddresses?: string[];
|
|
35
38
|
/** Enable TLS via self-signed CA certs (default: true). */
|
|
36
39
|
secure?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Skip the cockroach init Job (default: false).
|
|
42
|
+
* Set true for secondary regions in a multi-region cluster — only ONE region
|
|
43
|
+
* should run `cockroach init` to bootstrap the unified cluster. Secondary
|
|
44
|
+
* nodes start fresh and auto-join the cluster via the joinAddresses.
|
|
45
|
+
*/
|
|
46
|
+
skipInit?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Skip the cert-gen Job (default: false).
|
|
49
|
+
* Set true for multi-region deployments where a shared CA and node certs are
|
|
50
|
+
* pre-generated externally (e.g. via generate-certs.sh) and distributed via
|
|
51
|
+
* External Secrets Operator or direct kubectl. Each region's cert-gen creates
|
|
52
|
+
* a separate CA, breaking cross-region TLS — so all regions must use the same CA.
|
|
53
|
+
*/
|
|
54
|
+
skipCertGen?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Extra DNS names / IPs to include in node cert SANs beyond the auto-generated
|
|
57
|
+
* cluster-local names. Use for cross-region or external hostnames.
|
|
58
|
+
* E.g. ["cockroachdb-0.east.crdb.internal", "cockroachdb-1.east.crdb.internal"].
|
|
59
|
+
*/
|
|
60
|
+
extraCertNodeAddresses?: string[];
|
|
61
|
+
/**
|
|
62
|
+
* Domain suffix for cross-cluster advertise address (e.g. "east.crdb.internal").
|
|
63
|
+
* When set, nodes advertise "${HOSTNAME}.${advertiseHostDomain}" instead of the
|
|
64
|
+
* cluster-local FQDN from $(hostname -f). Required for multi-region clusters so
|
|
65
|
+
* that gossip addresses are resolvable from other Kubernetes clusters.
|
|
66
|
+
* E.g. pod "cockroachdb-0" in east advertises "cockroachdb-0.east.crdb.internal".
|
|
67
|
+
*/
|
|
68
|
+
advertiseHostDomain?: string;
|
|
69
|
+
/**
|
|
70
|
+
* Mount the client certs secret (`${name}-client-certs`) into pods at
|
|
71
|
+
* `/cockroach/cockroach-client-certs` (default: false).
|
|
72
|
+
*
|
|
73
|
+
* Enable for multi-region deployments where `cockroach init`, `cockroach sql`,
|
|
74
|
+
* and backup schedule setup run inside a pod via `kubectl exec`. The client cert
|
|
75
|
+
* is separate from the node cert and is NOT included in the node certs secret.
|
|
76
|
+
* Without this flag you must inject client certs manually (e.g. via /tmp).
|
|
77
|
+
*/
|
|
78
|
+
mountClientCerts?: boolean;
|
|
37
79
|
/** Additional labels to apply to all resources. */
|
|
38
80
|
labels?: Record<string, string>;
|
|
81
|
+
/** Per-member defaults for fine-grained overrides. */
|
|
82
|
+
defaults?: {
|
|
83
|
+
serviceAccount?: Partial<Record<string, unknown>>;
|
|
84
|
+
role?: Partial<Record<string, unknown>>;
|
|
85
|
+
roleBinding?: Partial<Record<string, unknown>>;
|
|
86
|
+
clusterRole?: Partial<Record<string, unknown>>;
|
|
87
|
+
clusterRoleBinding?: Partial<Record<string, unknown>>;
|
|
88
|
+
publicService?: Partial<Record<string, unknown>>;
|
|
89
|
+
headlessService?: Partial<Record<string, unknown>>;
|
|
90
|
+
pdb?: Partial<Record<string, unknown>>;
|
|
91
|
+
statefulSet?: Partial<Record<string, unknown>>;
|
|
92
|
+
initJob?: Partial<Record<string, unknown>>;
|
|
93
|
+
certGenJob?: Partial<Record<string, unknown>>;
|
|
94
|
+
};
|
|
39
95
|
}
|
|
40
96
|
|
|
41
97
|
export interface CockroachDbClusterResult {
|
|
42
|
-
serviceAccount:
|
|
43
|
-
role:
|
|
44
|
-
roleBinding:
|
|
45
|
-
clusterRole:
|
|
46
|
-
clusterRoleBinding:
|
|
98
|
+
serviceAccount: InstanceType<typeof ServiceAccount>;
|
|
99
|
+
role: InstanceType<typeof Role>;
|
|
100
|
+
roleBinding: InstanceType<typeof RoleBinding>;
|
|
101
|
+
clusterRole: InstanceType<typeof ClusterRole>;
|
|
102
|
+
clusterRoleBinding: InstanceType<typeof ClusterRoleBinding>;
|
|
47
103
|
/** Client-facing service (ClusterIP, ports 26257+8080). */
|
|
48
|
-
publicService:
|
|
104
|
+
publicService: InstanceType<typeof Service>;
|
|
49
105
|
/** Pod discovery service (headless, publishNotReadyAddresses). */
|
|
50
|
-
headlessService:
|
|
51
|
-
pdb:
|
|
52
|
-
statefulSet:
|
|
53
|
-
/** One-shot cockroach init job. */
|
|
54
|
-
initJob
|
|
55
|
-
/** Generates self-signed CA + node certs, stores in Secrets. */
|
|
56
|
-
certGenJob
|
|
106
|
+
headlessService: InstanceType<typeof Service>;
|
|
107
|
+
pdb: InstanceType<typeof PodDisruptionBudget>;
|
|
108
|
+
statefulSet: InstanceType<typeof StatefulSet>;
|
|
109
|
+
/** One-shot cockroach init job. Absent when skipInit is true. */
|
|
110
|
+
initJob?: InstanceType<typeof Job>;
|
|
111
|
+
/** Generates self-signed CA + node certs, stores in Secrets. Absent when skipCertGen is true. */
|
|
112
|
+
certGenJob?: InstanceType<typeof Job>;
|
|
57
113
|
}
|
|
58
114
|
|
|
59
115
|
/**
|
|
@@ -77,7 +133,7 @@ export interface CockroachDbClusterResult {
|
|
|
77
133
|
* });
|
|
78
134
|
* ```
|
|
79
135
|
*/
|
|
80
|
-
export
|
|
136
|
+
export const CockroachDbCluster = Composite<CockroachDbClusterProps>((props) => {
|
|
81
137
|
const {
|
|
82
138
|
name,
|
|
83
139
|
namespace,
|
|
@@ -92,11 +148,18 @@ export function CockroachDbCluster(props: CockroachDbClusterProps): CockroachDbC
|
|
|
92
148
|
locality,
|
|
93
149
|
joinAddresses = [],
|
|
94
150
|
secure = true,
|
|
151
|
+
skipInit = false,
|
|
152
|
+
skipCertGen = false,
|
|
153
|
+
extraCertNodeAddresses = [],
|
|
154
|
+
advertiseHostDomain,
|
|
155
|
+
mountClientCerts = false,
|
|
95
156
|
labels: extraLabels = {},
|
|
157
|
+
defaults: defs,
|
|
96
158
|
} = props;
|
|
97
159
|
|
|
98
160
|
const saName = name;
|
|
99
161
|
const certsDir = "/cockroach/cockroach-certs";
|
|
162
|
+
const clientCertsDir = "/cockroach/cockroach-client-certs";
|
|
100
163
|
const dataDir = "/cockroach/cockroach-data";
|
|
101
164
|
|
|
102
165
|
const commonLabels: Record<string, string> = {
|
|
@@ -105,28 +168,28 @@ export function CockroachDbCluster(props: CockroachDbClusterProps): CockroachDbC
|
|
|
105
168
|
...extraLabels,
|
|
106
169
|
};
|
|
107
170
|
|
|
108
|
-
//
|
|
171
|
+
// -- RBAC --
|
|
109
172
|
|
|
110
|
-
const serviceAccount
|
|
173
|
+
const serviceAccount = new ServiceAccount(mergeDefaults({
|
|
111
174
|
metadata: {
|
|
112
175
|
name: saName,
|
|
113
176
|
...(namespace && { namespace }),
|
|
114
177
|
labels: { ...commonLabels, "app.kubernetes.io/component": "database" },
|
|
115
178
|
},
|
|
116
|
-
};
|
|
179
|
+
}, defs?.serviceAccount));
|
|
117
180
|
|
|
118
|
-
const role
|
|
181
|
+
const role = new Role(mergeDefaults({
|
|
119
182
|
metadata: {
|
|
120
183
|
name,
|
|
121
184
|
...(namespace && { namespace }),
|
|
122
185
|
labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
|
|
123
186
|
},
|
|
124
187
|
rules: [
|
|
125
|
-
{ apiGroups: [""], resources: ["secrets"], verbs: ["get", "create", "patch"] },
|
|
188
|
+
{ apiGroups: [""], resources: ["secrets"], verbs: ["get", "create", "update", "patch"] },
|
|
126
189
|
],
|
|
127
|
-
};
|
|
190
|
+
}, defs?.role));
|
|
128
191
|
|
|
129
|
-
const roleBinding
|
|
192
|
+
const roleBinding = new RoleBinding(mergeDefaults({
|
|
130
193
|
metadata: {
|
|
131
194
|
name,
|
|
132
195
|
...(namespace && { namespace }),
|
|
@@ -140,9 +203,9 @@ export function CockroachDbCluster(props: CockroachDbClusterProps): CockroachDbC
|
|
|
140
203
|
subjects: [
|
|
141
204
|
{ kind: "ServiceAccount", name: saName, ...(namespace && { namespace }) },
|
|
142
205
|
],
|
|
143
|
-
};
|
|
206
|
+
}, defs?.roleBinding));
|
|
144
207
|
|
|
145
|
-
const clusterRole
|
|
208
|
+
const clusterRole = new ClusterRole(mergeDefaults({
|
|
146
209
|
metadata: {
|
|
147
210
|
name,
|
|
148
211
|
labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
|
|
@@ -150,9 +213,9 @@ export function CockroachDbCluster(props: CockroachDbClusterProps): CockroachDbC
|
|
|
150
213
|
rules: [
|
|
151
214
|
{ apiGroups: ["certificates.k8s.io"], resources: ["certificatesigningrequests"], verbs: ["get", "create", "watch"] },
|
|
152
215
|
],
|
|
153
|
-
};
|
|
216
|
+
}, defs?.clusterRole));
|
|
154
217
|
|
|
155
|
-
const clusterRoleBinding
|
|
218
|
+
const clusterRoleBinding = new ClusterRoleBinding(mergeDefaults({
|
|
156
219
|
metadata: {
|
|
157
220
|
name,
|
|
158
221
|
labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
|
|
@@ -165,11 +228,11 @@ export function CockroachDbCluster(props: CockroachDbClusterProps): CockroachDbC
|
|
|
165
228
|
subjects: [
|
|
166
229
|
{ kind: "ServiceAccount", name: saName, ...(namespace && { namespace }) },
|
|
167
230
|
],
|
|
168
|
-
};
|
|
231
|
+
}, defs?.clusterRoleBinding));
|
|
169
232
|
|
|
170
|
-
//
|
|
233
|
+
// -- Services --
|
|
171
234
|
|
|
172
|
-
const publicService
|
|
235
|
+
const publicService = new Service(mergeDefaults({
|
|
173
236
|
metadata: {
|
|
174
237
|
name: `${name}-public`,
|
|
175
238
|
...(namespace && { namespace }),
|
|
@@ -183,9 +246,9 @@ export function CockroachDbCluster(props: CockroachDbClusterProps): CockroachDbC
|
|
|
183
246
|
],
|
|
184
247
|
type: "ClusterIP",
|
|
185
248
|
},
|
|
186
|
-
};
|
|
249
|
+
}, defs?.publicService));
|
|
187
250
|
|
|
188
|
-
const headlessService
|
|
251
|
+
const headlessService = new Service(mergeDefaults({
|
|
189
252
|
metadata: {
|
|
190
253
|
name,
|
|
191
254
|
...(namespace && { namespace }),
|
|
@@ -203,11 +266,11 @@ export function CockroachDbCluster(props: CockroachDbClusterProps): CockroachDbC
|
|
|
203
266
|
clusterIP: "None",
|
|
204
267
|
publishNotReadyAddresses: true,
|
|
205
268
|
},
|
|
206
|
-
};
|
|
269
|
+
}, defs?.headlessService));
|
|
207
270
|
|
|
208
|
-
//
|
|
271
|
+
// -- PodDisruptionBudget --
|
|
209
272
|
|
|
210
|
-
const pdb
|
|
273
|
+
const pdb = new PodDisruptionBudget(mergeDefaults({
|
|
211
274
|
metadata: {
|
|
212
275
|
name,
|
|
213
276
|
...(namespace && { namespace }),
|
|
@@ -217,22 +280,31 @@ export function CockroachDbCluster(props: CockroachDbClusterProps): CockroachDbC
|
|
|
217
280
|
maxUnavailable: 1,
|
|
218
281
|
selector: { matchLabels: { "app.kubernetes.io/name": name } },
|
|
219
282
|
},
|
|
220
|
-
};
|
|
283
|
+
}, defs?.pdb));
|
|
284
|
+
|
|
285
|
+
// -- StatefulSet --
|
|
221
286
|
|
|
222
|
-
//
|
|
287
|
+
// Build the cockroach start command as a shell string so that $(hostname -f)
|
|
288
|
+
// is expanded at runtime. K8s exec-form args do NOT invoke a shell, so
|
|
289
|
+
// $(...) substitutions are never evaluated unless we wrap with sh -c.
|
|
290
|
+
// When advertiseHostDomain is set, advertise the cross-cluster ExternalDNS name
|
|
291
|
+
// (e.g. "cockroachdb-0.east.crdb.internal") so gossip addresses are resolvable
|
|
292
|
+
// from other Kubernetes clusters. Otherwise fall back to the cluster-local FQDN.
|
|
293
|
+
const advertiseHostFlag = advertiseHostDomain
|
|
294
|
+
? `--advertise-host=\${HOSTNAME}.${advertiseHostDomain}`
|
|
295
|
+
: `--advertise-host=$(hostname -f)`;
|
|
223
296
|
|
|
224
|
-
const
|
|
225
|
-
"start",
|
|
297
|
+
const cockroachFlags = [
|
|
226
298
|
`--logtostderr=WARNING`,
|
|
227
|
-
`--certs-dir=${
|
|
228
|
-
|
|
229
|
-
`--advertise-host=$(hostname -f)`,
|
|
299
|
+
...(secure ? [`--certs-dir=${certsDir}`] : ["--insecure"]),
|
|
300
|
+
advertiseHostFlag,
|
|
230
301
|
`--http-addr=0.0.0.0`,
|
|
231
302
|
`--cache=${cachePercent}`,
|
|
232
303
|
`--max-sql-memory=${sqlMemoryPercent}`,
|
|
233
304
|
...(joinAddresses.length > 0 ? [`--join=${joinAddresses.join(",")}`] : []),
|
|
234
305
|
...(locality ? [`--locality=${locality}`] : []),
|
|
235
306
|
];
|
|
307
|
+
const cockroachStartCmd = `/cockroach/cockroach start ${cockroachFlags.join(" ")}`;
|
|
236
308
|
|
|
237
309
|
const volumes: Record<string, unknown>[] = [];
|
|
238
310
|
const volumeMounts: Record<string, unknown>[] = [
|
|
@@ -242,6 +314,10 @@ export function CockroachDbCluster(props: CockroachDbClusterProps): CockroachDbC
|
|
|
242
314
|
if (secure) {
|
|
243
315
|
volumes.push({ name: "certs", secret: { secretName: `${name}-node-certs`, defaultMode: 0o400 } });
|
|
244
316
|
volumeMounts.push({ name: "certs", mountPath: certsDir });
|
|
317
|
+
if (mountClientCerts) {
|
|
318
|
+
volumes.push({ name: "client-certs", secret: { secretName: `${name}-client-certs`, defaultMode: 0o400 } });
|
|
319
|
+
volumeMounts.push({ name: "client-certs", mountPath: clientCertsDir });
|
|
320
|
+
}
|
|
245
321
|
}
|
|
246
322
|
|
|
247
323
|
const container: Record<string, unknown> = {
|
|
@@ -251,8 +327,8 @@ export function CockroachDbCluster(props: CockroachDbClusterProps): CockroachDbC
|
|
|
251
327
|
{ containerPort: 26257, name: "grpc" },
|
|
252
328
|
{ containerPort: 8080, name: "http" },
|
|
253
329
|
],
|
|
254
|
-
command: ["/
|
|
255
|
-
args:
|
|
330
|
+
command: ["/bin/sh", "-c"],
|
|
331
|
+
args: [cockroachStartCmd],
|
|
256
332
|
resources: {
|
|
257
333
|
limits: { cpu: cpuLimit, memory: memoryLimit },
|
|
258
334
|
requests: { cpu: cpuLimit, memory: memoryLimit },
|
|
@@ -274,7 +350,7 @@ export function CockroachDbCluster(props: CockroachDbClusterProps): CockroachDbC
|
|
|
274
350
|
},
|
|
275
351
|
};
|
|
276
352
|
|
|
277
|
-
const statefulSet
|
|
353
|
+
const statefulSet = new StatefulSet(mergeDefaults({
|
|
278
354
|
metadata: {
|
|
279
355
|
name,
|
|
280
356
|
...(namespace && { namespace }),
|
|
@@ -318,26 +394,56 @@ export function CockroachDbCluster(props: CockroachDbClusterProps): CockroachDbC
|
|
|
318
394
|
},
|
|
319
395
|
],
|
|
320
396
|
},
|
|
321
|
-
};
|
|
397
|
+
}, defs?.statefulSet));
|
|
322
398
|
|
|
323
|
-
//
|
|
399
|
+
// -- cert-gen Job --
|
|
324
400
|
|
|
325
401
|
// Generates self-signed CA and node certs, stores them in K8s Secrets.
|
|
326
402
|
// Each node's cert includes the pod DNS names (pod-N.svc.namespace.svc.cluster.local).
|
|
403
|
+
// NOTE: The cert-gen Job uses `curl` to create K8s Secrets via the API server.
|
|
404
|
+
// CockroachDB UBI images (v24+) include curl. For multi-region deployments,
|
|
405
|
+
// use an external cert generation script instead (see generate-certs.sh).
|
|
327
406
|
const nodeNames = Array.from({ length: replicas }, (_, i) => `${name}-${i}.${name}`);
|
|
407
|
+
// Include both short names (for in-cluster init job) and FQDNs (for cross-namespace/init connections).
|
|
328
408
|
const nodeAddresses = namespace
|
|
329
|
-
? nodeNames.map((n) => `${n}.${namespace}.svc.cluster.local`)
|
|
330
|
-
: nodeNames.map((n) => `${n}.default.svc.cluster.local`);
|
|
409
|
+
? [...nodeNames, ...nodeNames.map((n) => `${n}.${namespace}.svc.cluster.local`)]
|
|
410
|
+
: [...nodeNames, ...nodeNames.map((n) => `${n}.default.svc.cluster.local`)];
|
|
411
|
+
|
|
412
|
+
const ns = namespace ?? "default";
|
|
413
|
+
const nodeSecretName = `${name}-node-certs`;
|
|
414
|
+
const clientSecretName = `${name}-client-certs`;
|
|
415
|
+
|
|
416
|
+
const allCertNodeAddresses = [...nodeAddresses, ...extraCertNodeAddresses];
|
|
331
417
|
|
|
332
418
|
const certGenScript = [
|
|
333
419
|
"set -ex",
|
|
334
420
|
"cd /cockroach",
|
|
335
421
|
"cockroach cert create-ca --certs-dir=certs --ca-key=certs/ca.key",
|
|
336
|
-
`cockroach cert create-node ${
|
|
422
|
+
`cockroach cert create-node ${allCertNodeAddresses.join(" ")} localhost 127.0.0.1 --certs-dir=certs --ca-key=certs/ca.key`,
|
|
337
423
|
"cockroach cert create-client root --certs-dir=certs --ca-key=certs/ca.key",
|
|
338
|
-
|
|
424
|
+
// Store certs in K8s Secrets via the API using the ServiceAccount token.
|
|
425
|
+
`TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)`,
|
|
426
|
+
`K8S_CA=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt`,
|
|
427
|
+
`API=https://kubernetes.default.svc`,
|
|
428
|
+
`NS=${ns}`,
|
|
429
|
+
`encode() { base64 | tr -d '\\n'; }`,
|
|
430
|
+
// Build JSON payloads for the two secrets.
|
|
431
|
+
`NODE_PAYLOAD=$(printf '{"apiVersion":"v1","kind":"Secret","metadata":{"name":"${nodeSecretName}","namespace":"%s"},"type":"Opaque","data":{"ca.crt":"%s","node.crt":"%s","node.key":"%s"}}' "$NS" "$(cat certs/ca.crt | encode)" "$(cat certs/node.crt | encode)" "$(cat certs/node.key | encode)")`,
|
|
432
|
+
`CLIENT_PAYLOAD=$(printf '{"apiVersion":"v1","kind":"Secret","metadata":{"name":"${clientSecretName}","namespace":"%s"},"type":"Opaque","data":{"ca.crt":"%s","client.root.crt":"%s","client.root.key":"%s"}}' "$NS" "$(cat certs/ca.crt | encode)" "$(cat certs/client.root.crt | encode)" "$(cat certs/client.root.key | encode)")`,
|
|
433
|
+
// Create or update each secret.
|
|
434
|
+
`for SECRET_INFO in "${nodeSecretName}:$NODE_PAYLOAD" "${clientSecretName}:$CLIENT_PAYLOAD"; do`,
|
|
435
|
+
` SECRET_NAME=\${SECRET_INFO%%:*}`,
|
|
436
|
+
` PAYLOAD=\${SECRET_INFO#*:}`,
|
|
437
|
+
` STATUS=$(curl -s --cacert $K8S_CA -H "Authorization: Bearer $TOKEN" -o /dev/null -w '%{http_code}' $API/api/v1/namespaces/$NS/secrets/$SECRET_NAME)`,
|
|
438
|
+
` if [ "$STATUS" = "200" ]; then`,
|
|
439
|
+
` curl -sf --cacert $K8S_CA -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -X PUT $API/api/v1/namespaces/$NS/secrets/$SECRET_NAME -d "$PAYLOAD"`,
|
|
440
|
+
` else`,
|
|
441
|
+
` curl -sf --cacert $K8S_CA -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -X POST $API/api/v1/namespaces/$NS/secrets -d "$PAYLOAD"`,
|
|
442
|
+
` fi`,
|
|
443
|
+
`done`,
|
|
444
|
+
].join("\n");
|
|
339
445
|
|
|
340
|
-
const certGenJob
|
|
446
|
+
const certGenJob = skipCertGen ? undefined : new Job(mergeDefaults({
|
|
341
447
|
metadata: {
|
|
342
448
|
name: `${name}-cert-gen`,
|
|
343
449
|
...(namespace && { namespace }),
|
|
@@ -361,9 +467,9 @@ export function CockroachDbCluster(props: CockroachDbClusterProps): CockroachDbC
|
|
|
361
467
|
},
|
|
362
468
|
},
|
|
363
469
|
},
|
|
364
|
-
};
|
|
470
|
+
}, defs?.certGenJob));
|
|
365
471
|
|
|
366
|
-
//
|
|
472
|
+
// -- init Job (only when skipCertGen is false) --
|
|
367
473
|
|
|
368
474
|
const initArgs = secure
|
|
369
475
|
? [`--certs-dir=${certsDir}`, `--host=${name}-0.${name}`]
|
|
@@ -372,11 +478,11 @@ export function CockroachDbCluster(props: CockroachDbClusterProps): CockroachDbC
|
|
|
372
478
|
const initVolumes: Record<string, unknown>[] = [];
|
|
373
479
|
const initVolumeMounts: Record<string, unknown>[] = [];
|
|
374
480
|
if (secure) {
|
|
375
|
-
initVolumes.push({ name: "client-certs", secret: { secretName: `${name}-
|
|
481
|
+
initVolumes.push({ name: "client-certs", secret: { secretName: `${name}-client-certs`, defaultMode: 0o400 } });
|
|
376
482
|
initVolumeMounts.push({ name: "client-certs", mountPath: certsDir });
|
|
377
483
|
}
|
|
378
484
|
|
|
379
|
-
const initJob
|
|
485
|
+
const initJob = skipInit ? undefined : new Job(mergeDefaults({
|
|
380
486
|
metadata: {
|
|
381
487
|
name: `${name}-init`,
|
|
382
488
|
...(namespace && { namespace }),
|
|
@@ -403,7 +509,7 @@ export function CockroachDbCluster(props: CockroachDbClusterProps): CockroachDbC
|
|
|
403
509
|
},
|
|
404
510
|
},
|
|
405
511
|
},
|
|
406
|
-
};
|
|
512
|
+
}, defs?.initJob));
|
|
407
513
|
|
|
408
514
|
return {
|
|
409
515
|
serviceAccount,
|
|
@@ -415,7 +521,7 @@ export function CockroachDbCluster(props: CockroachDbClusterProps): CockroachDbC
|
|
|
415
521
|
headlessService,
|
|
416
522
|
pdb,
|
|
417
523
|
statefulSet,
|
|
418
|
-
initJob,
|
|
419
|
-
certGenJob,
|
|
524
|
+
...(initJob && { initJob }),
|
|
525
|
+
...(certGenJob && { certGenJob }),
|
|
420
526
|
};
|
|
421
|
-
}
|
|
527
|
+
}, "CockroachDbCluster");
|