@mark1russell7/kind 0.6.0 → 0.7.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/README.md CHANGED
@@ -137,6 +137,13 @@ From 0.5.0, the lab installs the flavor `ambient` too:
137
137
  - **The kernel.** istio-cni writes iptables rules in each pod and on each node. Thus `kind.yml` loads their modules first, and an ambient cell waits when one does not load.
138
138
  - **The log of ztunnel.** For a cell in the ambient mode, the watcher follows each ztunnel pod in istio-system (`followsZtunnel`). Each line of its log becomes a `ztunnel` line, stamped at its arrival, and each ztunnel pod is a `ztunnel-pod` line. No band reads them.
139
139
 
140
+ From 0.7.0, a cell can restart ztunnel, and it can set the environment of ztunnel:
141
+
142
+ - **The watcher.** It follows the ztunnel pods for each cell in the flavor `ambient`, also for a cell of sidecar pods there. The lines of the ztunnel pods are the evidence of a restart that no pod of the cell sees.
143
+ - **The environment.** `mesh.ztunnel` gives variables of the DaemonSet of ztunnel for one cell, for example `CONNECTION_TERMINATION_DEADLINE`. Before the cell, `setZtunnelEnv` sets them with `kubectl set env` (`ztunnelEnvArgs`). Then it waits for the rollout, and until no old ztunnel pod is left. After the cell, it removes them in the same way.
144
+ - **The reference `restart`.** It is the first deletion timestamp of a ztunnel pod in the run, as the watcher receives it (`restartOf`). A run of the trigger `ztunnel-restart` ends when each deleted ztunnel pod is gone, and each node has a ready new one (`ztunnelReplaced`).
145
+ - **The DaemonSet.** The chart of ztunnel sets `maxSurge` 1. Then the controller of the DaemonSet of Kubernetes v1.37.0 skips a pod with a deletion timestamp. It makes a new pod on that node at once (`daemon_controller.go`, lines 863–924). Thus the new ztunnel runs beside the old one while the old one drains.
146
+
140
147
  A new member of the union `Template` breaks a reader that switches on it. That is a breaking change before 1.0.0, thus the version is 0.3.0. The record format stays `/2`, with the optional field `mesh`. A judge before 0.3.0 cannot read a record of T15.
141
148
 
142
149
  ## The image
@@ -175,6 +182,7 @@ The lab image (`image/`) holds the service of a cell on `@mark1russell7/service`
175
182
  | `cpu-throttle` | `cpu.max` in the cgroup of the container of the first replica |
176
183
  | `authorization-policy` | `kubectl apply` of a DENY AuthorizationPolicy on the server pods for the principal of an account (`account`, the account `default` of the clients when not given), then `kubectl delete` after the hold |
177
184
  | `idle` | SIGUSR1 to the gRPC client of each client pod, and SIGUSR2 after the hold: a gap of the calls (the target `clients`). The restore sends SIGUSR2 again |
185
+ | `ztunnel-restart` | `kubectl delete pod` of the ztunnel pod of each node, with its grace (`ZTUNNEL_PODS`). The flow of each client crosses the ztunnel of its own node. The restore waits for the rollout of the DaemonSet |
178
186
 
179
187
  A cgroup path that is not the scope of one container is refused. A write to the root of the node throttles or freezes each pod of the node.
180
188
 
@@ -229,6 +237,8 @@ From 0.6.0, the prediction `ends` is the end of the socket of each client, from
229
237
  - With a window (`window`), the failed requests must also agree with that window. The observation lasts until each socket can end, and until each request of the window ended.
230
238
  - The facts of a run give the first close of each client after the reference (`closes`).
231
239
 
240
+ A new member of the union `TriggerKind`, `ztunnel-restart`, and a new member of the union `Reference`, `restart`, break a reader that switches on them. Each is a breaking change before 1.0.0, thus the version is 0.7.0. The record format stays `/2`, with the optional field `mesh.ztunnel`.
241
+
232
242
  A new member of the union `Prediction`, `ends`, and a new member of the union `TriggerKind`, `idle`, break a reader that switches on them. The union `Target` has the new member `clients` too. Each is a breaking change before 1.0.0, thus the version is 0.6.0. The record format stays `/2`, with the optional field `closes`: the lines `sock` and `gap` are new lines of a run.
233
243
 
234
244
  A new member of the union `Target`, `servers`, breaks a reader that switches on it. `KindLab` also has a new method, `tables`, which each implementation must have. Each is a breaking change before 1.0.0, thus the version is 0.5.0. The record format stays `/2`: the lines `tables`, `ztunnel` and `ztunnel-pod` are new lines of a run.
package/build/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as updatesOf, $t as RedisDeclaration, A as TriggerV1, At as socketsOf, B as RunCheck, Bt as seconds, C as KindCellResult, Ct as restartsAt, D as PredictionV1, Dt as sliceDropOf, E as LoadSample, Et as signalsOf, F as KIND_NOISE, Ft as LOG_LABEL, G as judgeKind, Gt as KindCell, H as checkRun, Ht as showBand, I as KindDecision, It as PORT, J as propagationOf, Jt as Mesh, K as observationAfter, Kt as KindRun, L as KindVerdict, Lt as REDIS, M as upgrade, Mt as transitionOf, N as upgradeCell, Nt as CLIENT, O as RunCheckV1, Ot as sliceEmptyOf, P as Deleted, Pt as HEALTH_PORT, Q as unitOf, Qt as Prediction, R as LAST_SLACK, Rt as SERVER, S as KindCellRecordV1, Sn as scenarioProblems, St as requestsOf, T as KindVerdictV1, Tt as signalOf, U as deletionsOf, Ut as Band, V as RunFacts, Vt as secondsOf, W as factsOf, Wt as Declaration, X as referenceOf, Xt as MeshMode, Y as propagationSource, Yt as MeshFlavor, Z as reusesReset, Zt as PodSettings, _ as ClusterManifest, _n as goDuration, _t as kernelCounts, a as STAGES, an as Trigger, at as Request, b as FORMAT_V1, bn as nodeNames, bt as podsOf, c as readRecord, cn as Workload, ct as SocketLine, d as calibrationOf, dn as KindScenario, dt as byNode, en as Reference, et as Endpoint, f as cellsTable, fn as KubeProxyMode, ft as deletionOf, g as BandV1, gn as cidrRange, gt as intakeOf, h as timeSpread, hn as cidrOverlap, ht as failuresOf, i as quantileOf, in as Template, it as RecordLine, j as judge, jt as stoppingOf, k as RunFactsV1, kt as slicesOf, l as Judged, ln as KUBE_PROXY_MODES, lt as backendsAt, m as predictionText, mn as NodeImage, mt as emptyOf, n as medianInterval, nn as ResetReuse, nt as PodLine, o as kindCellRecordSchema, on as TriggerKind, ot as RulesLine, p as medianText, pn as NODE_IMAGES, pt as dropOf, q as observationEnd, qt as KubeletProbe, r as middle, rn as Stack, rt as PropagationSource, s as kindCellRecordV1Schema, sn as WindowPrediction, st as SliceLine, t as RELATIVE, tn as Replica, tt as Line, u as TimeSpread, un as KindConfig, ut as byClients, v as EnvironmentManifest, vn as kindConfig, vt as outcomesOf, w as KindCellV1, wt as rulesOf, x as KindCellRecord, xn as scenario, xt as recordsOf, y as FORMAT, yn as kubeProxyPatch, yt as podsAt, z as Propagated, zt as bandOf } from "./judge-B9kVpFE-.js";
1
+ import { $ as updatesOf, $t as MeshFlavor, A as TriggerV1, At as sliceEmptyOf, B as RunCheck, Bt as PORT, C as KindCellResult, Cn as kubeProxyPatch, Ct as requestsOf, D as PredictionV1, Dt as signalOf, E as LoadSample, En as scenarioProblems, Et as rulesOf, F as KIND_NOISE, Ft as ztunnelPodsOf, G as judgeKind, Gt as secondsOf, H as checkRun, Ht as SERVER, I as KindDecision, It as ztunnelReplaced, J as propagationOf, Jt as Declaration, K as observationAfter, Kt as showBand, L as KindVerdict, Lt as CLIENT, M as upgrade, Mt as socketsOf, N as upgradeCell, Nt as stoppingOf, O as RunCheckV1, Ot as signalsOf, P as Deleted, Pt as transitionOf, Q as unitOf, Qt as Mesh, R as LAST_SLACK, Rt as HEALTH_PORT, S as KindCellRecordV1, Sn as kindConfig, St as recordsOf, T as KindVerdictV1, Tn as scenario, Tt as restartsAt, U as deletionsOf, Ut as bandOf, V as RunFacts, Vt as REDIS, W as factsOf, Wt as seconds, X as referenceOf, Xt as KindRun, Y as propagationSource, Yt as KindCell, Z as reusesReset, Zt as KubeletProbe, _ as ClusterManifest, _n as NODE_IMAGES, _t as intakeOf, a as STAGES, an as Replica, at as Request, b as FORMAT_V1, bn as cidrRange, bt as podsAt, c as readRecord, cn as Template, ct as SocketLine, d as calibrationOf, dn as WindowPrediction, dt as byClients, en as MeshMode, et as Endpoint, f as cellsTable, fn as Workload, ft as byNode, g as BandV1, gn as KubeProxyMode, gt as failuresOf, h as timeSpread, hn as KindScenario, ht as emptyOf, i as quantileOf, in as Reference, it as RecordLine, j as judge, jt as slicesOf, k as RunFactsV1, kt as sliceDropOf, l as Judged, ln as Trigger, lt as ZtunnelPodLine, m as predictionText, mn as KindConfig, mt as dropOf, n as medianInterval, nn as Prediction, nt as PodLine, o as kindCellRecordSchema, on as ResetReuse, ot as RulesLine, p as medianText, pn as KUBE_PROXY_MODES, pt as deletionOf, q as observationEnd, qt as Band, r as middle, rn as RedisDeclaration, rt as PropagationSource, s as kindCellRecordV1Schema, sn as Stack, st as SliceLine, t as RELATIVE, tn as PodSettings, tt as Line, u as TimeSpread, un as TriggerKind, ut as backendsAt, v as EnvironmentManifest, vn as NodeImage, vt as kernelCounts, w as KindCellV1, wn as nodeNames, wt as restartOf, x as KindCellRecord, xn as goDuration, xt as podsOf, y as FORMAT, yn as cidrOverlap, yt as outcomesOf, z as Propagated, zt as LOG_LABEL } from "./judge-B1nSdbS0.js";
2
2
  import { Quantity } from "@mark1russell7/quantity";
3
3
  import { CheckFn, Finding, HealthServer, Poll, Rule, Scenario, ServiceBuilder, ServiceDescription, Stage, Timing, TransportImpl, Verdict } from "@mark1russell7/service";
4
4
  import { RedisClient } from "@mark1russell7/service/redis";
@@ -169,6 +169,8 @@ interface FaultPlan {
169
169
  export declare const POLICY = "lab-deny";
170
170
  /** This service account is the account of the clients: their pods name no other account. */
171
171
  export declare const CLIENT_ACCOUNT = "default";
172
+ /** This selector gives the ztunnel pods in istio-system: the label `app` of the chart of ztunnel. */
173
+ export declare const ZTUNNEL_PODS = "app=ztunnel";
172
174
  /**
173
175
  * This function gives the AuthorizationPolicy of the trigger `authorization-policy`. It denies each
174
176
  * request to the server pods from the principal of the service account `account`. Istio gives a
@@ -268,8 +270,23 @@ export declare const serverCluster: (namespace: string) => string;
268
270
  export declare const EDS_EVERY: Quantity;
269
271
  /** This time is the interval of the LDS poll of each server sidecar, the same as the poll of EDS. */
270
272
  export declare const LDS_EVERY: Quantity;
271
- /** This function tells if the watcher follows the log of each ztunnel for a cell: a cell in ambient mode. */
273
+ /**
274
+ * This function tells if the watcher follows each ztunnel pod and its log for a cell: a cell in the
275
+ * flavor `ambient`. A cell of sidecar pods in that flavor needs the lines of the ztunnel pods too.
276
+ * They show the restart of ztunnel, which its pods do not see.
277
+ */
272
278
  export declare const followsZtunnel: (cell: Pick<KindCell, "mesh">) => boolean;
279
+ /**
280
+ * This function gives the arguments of kubectl that set the environment of ztunnel for a cell, or
281
+ * remove it (`undo`). The variables go in the sequence of their names.
282
+ */
283
+ export declare const ztunnelEnvArgs: (env: Readonly<Record<string, string>>, undo: boolean) => string[];
284
+ /**
285
+ * This function sets the environment of ztunnel for a cell, or removes it (`undo`). Then it waits for
286
+ * the rollout of the DaemonSet, and until no old ztunnel pod is left. An old pod drains for its
287
+ * deadline after the rollout replaces it. Thus no run starts beside a ztunnel pod that is going.
288
+ */
289
+ export declare const setZtunnelEnv: (cluster: Cluster, env: Readonly<Record<string, string>>, undo: boolean) => Promise<void>;
273
290
  /** This function tells if the lab polls the LDS updates of the server sidecars of a cell: a policy in a sidecar mesh. */
274
291
  export declare const pollsListeners: (cell: Pick<KindCell, "mesh" | "trigger">) => boolean;
275
292
  //#endregion
@@ -629,5 +646,5 @@ export declare const toolPath: (tool: Tool, key?: string, cache?: string) => str
629
646
  */
630
647
  export declare const ensureTool: (tool: Tool, key?: string, cache?: string) => Promise<string>;
631
648
  //#endregion
632
- export { type Band, type BandV1, CLIENT, type Cluster, type ClusterHosts, type ClusterManifest, type Credentials, type Declaration, type Deleted, type DeletionWindow, type EdsSpec, Endpoint, type EnvironmentManifest, FORMAT, FORMAT_V1, type FaultPlan, HEALTH_PORT, type Judged, KIND_NOISE, KUBE_PROXY_MODES, type KindCell, type KindCellRecord, type KindCellRecordV1, type KindCellResult, type KindCellV1, type KindConfig, type KindDecision, type KindLab, type KindRun, type KindScenario, type KindVerdict, type KindVerdictV1, type KubeProxyMode, type KubeletProbe, LAST_SLACK, LOG_LABEL, type LdsSpec, Line, type ListenerCounts, type LoadSample, type Mesh, type MeshFlavor, type MeshImages, type MeshMode, NODE_IMAGES, type NodeImage, PORT, type Parts, PodLine, type PodSettings, type Prediction, type PredictionV1, type Propagated, type Propagation, PropagationSource, REDIS, RELATIVE, RecordLine, type RedisDeclaration, type Reference, type Replica, Request, type ResetReuse, RulesLine, type RunCheck, type RunCheckV1, type RunFacts, type RunFactsV1, type RunOptions, SERVER, STAGES, type ServiceRule, SliceLine, SocketLine, type Stack, type Stamp, type Step, type Target, type Template, type TimeSpread, type Tool, type Trigger, type TriggerKind, type TriggerV1, type Verdicts, type WindowPrediction, type Workload, backendsAt, bandOf, byClients, byNode, calibrationOf, cellsTable, checkRun, cidrOverlap, cidrRange, deletionOf, deletionsOf, dropOf, emptyOf, factsOf, failuresOf, goDuration, intakeOf, judge, judgeKind, kernelCounts, kindCellRecordSchema, kindCellRecordV1Schema, kindConfig, kubeProxyPatch, medianInterval, medianText, middle, nodeNames, observationAfter, observationEnd, outcomesOf, podsAt, podsOf, predictionText, propagationOf, propagationSource, quantileOf, readRecord, recordsOf, referenceOf, requestsOf, restartsAt, reusesReset, rulesOf, scenario, scenarioProblems, seconds, secondsOf, showBand, signalOf, signalsOf, sliceDropOf, sliceEmptyOf, slicesOf, socketsOf, stoppingOf, timeSpread, transitionOf, unitOf, updatesOf, upgrade, upgradeCell };
649
+ export { type Band, type BandV1, CLIENT, type Cluster, type ClusterHosts, type ClusterManifest, type Credentials, type Declaration, type Deleted, type DeletionWindow, type EdsSpec, Endpoint, type EnvironmentManifest, FORMAT, FORMAT_V1, type FaultPlan, HEALTH_PORT, type Judged, KIND_NOISE, KUBE_PROXY_MODES, type KindCell, type KindCellRecord, type KindCellRecordV1, type KindCellResult, type KindCellV1, type KindConfig, type KindDecision, type KindLab, type KindRun, type KindScenario, type KindVerdict, type KindVerdictV1, type KubeProxyMode, type KubeletProbe, LAST_SLACK, LOG_LABEL, type LdsSpec, Line, type ListenerCounts, type LoadSample, type Mesh, type MeshFlavor, type MeshImages, type MeshMode, NODE_IMAGES, type NodeImage, PORT, type Parts, PodLine, type PodSettings, type Prediction, type PredictionV1, type Propagated, type Propagation, PropagationSource, REDIS, RELATIVE, RecordLine, type RedisDeclaration, type Reference, type Replica, Request, type ResetReuse, RulesLine, type RunCheck, type RunCheckV1, type RunFacts, type RunFactsV1, type RunOptions, SERVER, STAGES, type ServiceRule, SliceLine, SocketLine, type Stack, type Stamp, type Step, type Target, type Template, type TimeSpread, type Tool, type Trigger, type TriggerKind, type TriggerV1, type Verdicts, type WindowPrediction, type Workload, ZtunnelPodLine, backendsAt, bandOf, byClients, byNode, calibrationOf, cellsTable, checkRun, cidrOverlap, cidrRange, deletionOf, deletionsOf, dropOf, emptyOf, factsOf, failuresOf, goDuration, intakeOf, judge, judgeKind, kernelCounts, kindCellRecordSchema, kindCellRecordV1Schema, kindConfig, kubeProxyPatch, medianInterval, medianText, middle, nodeNames, observationAfter, observationEnd, outcomesOf, podsAt, podsOf, predictionText, propagationOf, propagationSource, quantileOf, readRecord, recordsOf, referenceOf, requestsOf, restartOf, restartsAt, reusesReset, rulesOf, scenario, scenarioProblems, seconds, secondsOf, showBand, signalOf, signalsOf, sliceDropOf, sliceEmptyOf, slicesOf, socketsOf, stoppingOf, timeSpread, transitionOf, unitOf, updatesOf, upgrade, upgradeCell, ztunnelPodsOf, ztunnelReplaced };
633
650
  //# sourceMappingURL=index.d.ts.map
package/build/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as slicesOf, A as medianInterval, B as intakeOf, C as propagationOf, D as unitOf, E as reusesReset, F as byNode, G as recordsOf, H as outcomesOf, I as deletionOf, J as rulesOf, K as requestsOf, L as dropOf, M as quantileOf, N as backendsAt, O as updatesOf, P as byClients, Q as sliceEmptyOf, R as emptyOf, S as observationEnd, T as referenceOf, U as podsAt, V as kernelCounts, W as podsOf, X as signalsOf, Y as signalOf, Z as sliceDropOf, _ as checkRun, a as calibrationOf, at as LOG_LABEL, b as judgeKind, c as predictionText, ct as SERVER, d as FORMAT_V1, dt as secondsOf, et as socketsOf, f as judge, ft as showBand, g as LAST_SLACK, h as KIND_NOISE, i as readRecord, it as HEALTH_PORT, j as middle, k as RELATIVE, l as timeSpread, lt as bandOf, m as upgradeCell, n as kindCellRecordSchema, nt as transitionOf, o as cellsTable, ot as PORT, p as upgrade, q as restartsAt, r as kindCellRecordV1Schema, rt as CLIENT, s as medianText, st as REDIS, t as STAGES, tt as stoppingOf, u as FORMAT, ut as seconds, v as deletionsOf, w as propagationSource, x as observationAfter, y as factsOf, z as failuresOf } from "./judge-DNCI5vvt.js";
1
+ import { $ as sliceEmptyOf, A as medianInterval, B as intakeOf, C as propagationOf, D as unitOf, E as reusesReset, F as byNode, G as recordsOf, H as outcomesOf, I as deletionOf, J as restartsAt, K as requestsOf, L as dropOf, M as quantileOf, N as backendsAt, O as updatesOf, P as byClients, Q as sliceDropOf, R as emptyOf, S as observationEnd, T as referenceOf, U as podsAt, V as kernelCounts, W as podsOf, X as signalOf, Y as rulesOf, Z as signalsOf, _ as checkRun, a as calibrationOf, at as ztunnelReplaced, b as judgeKind, c as predictionText, ct as LOG_LABEL, d as FORMAT_V1, dt as SERVER, et as slicesOf, f as judge, ft as bandOf, g as LAST_SLACK, h as KIND_NOISE, ht as showBand, i as readRecord, it as ztunnelPodsOf, j as middle, k as RELATIVE, l as timeSpread, lt as PORT, m as upgradeCell, mt as secondsOf, n as kindCellRecordSchema, nt as stoppingOf, o as cellsTable, ot as CLIENT, p as upgrade, pt as seconds, q as restartOf, r as kindCellRecordV1Schema, rt as transitionOf, s as medianText, st as HEALTH_PORT, t as STAGES, tt as socketsOf, u as FORMAT, ut as REDIS, v as deletionsOf, w as propagationSource, x as observationAfter, y as factsOf, z as failuresOf } from "./judge-CmiF-Fcs.js";
2
2
  import { valueIn } from "@mark1russell7/quantity";
3
3
  import { execFile, execFileSync } from "node:child_process";
4
4
  import { chmodSync, copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
@@ -637,6 +637,8 @@ const DELETION_COST = "controller.kubernetes.io/pod-deletion-cost";
637
637
  const POLICY = "lab-deny";
638
638
  /** This service account is the account of the clients: their pods name no other account. */
639
639
  const CLIENT_ACCOUNT = "default";
640
+ /** This selector gives the ztunnel pods in istio-system: the label `app` of the chart of ztunnel. */
641
+ const ZTUNNEL_PODS = "app=ztunnel";
640
642
  /**
641
643
  * This function gives the AuthorizationPolicy of the trigger `authorization-policy`. It denies each
642
644
  * request to the server pods from the principal of the service account `account`. Istio gives a
@@ -968,6 +970,33 @@ const planOf = (cell) => {
968
970
  signal: "SIGUSR2"
969
971
  }]
970
972
  };
973
+ case "ztunnel-restart": return {
974
+ inject: [{
975
+ do: "kubectl",
976
+ args: [
977
+ "-n",
978
+ "istio-system",
979
+ "delete",
980
+ "pod",
981
+ "-l",
982
+ ZTUNNEL_PODS,
983
+ "--wait=false"
984
+ ]
985
+ }],
986
+ hold: null,
987
+ heal: [],
988
+ restore: [{
989
+ do: "kubectl",
990
+ args: [
991
+ "-n",
992
+ "istio-system",
993
+ "rollout",
994
+ "status",
995
+ "daemonset/ztunnel",
996
+ "--timeout=300s"
997
+ ]
998
+ }]
999
+ };
971
1000
  }
972
1001
  };
973
1002
  /** This function tells if a trigger stops a pod of the service with its grace: a deletion, an eviction, a scale-in or a rollout. */
@@ -1296,8 +1325,55 @@ const LDS_EVERY = {
1296
1325
  value: 50,
1297
1326
  unit: "ms"
1298
1327
  };
1299
- /** This function tells if the watcher follows the log of each ztunnel for a cell: a cell in ambient mode. */
1300
- const followsZtunnel = (cell) => cell.mesh?.mode === "ambient";
1328
+ /**
1329
+ * This function tells if the watcher follows each ztunnel pod and its log for a cell: a cell in the
1330
+ * flavor `ambient`. A cell of sidecar pods in that flavor needs the lines of the ztunnel pods too.
1331
+ * They show the restart of ztunnel, which its pods do not see.
1332
+ */
1333
+ const followsZtunnel = (cell) => cell.mesh?.flavor === "ambient";
1334
+ /**
1335
+ * This function gives the arguments of kubectl that set the environment of ztunnel for a cell, or
1336
+ * remove it (`undo`). The variables go in the sequence of their names.
1337
+ */
1338
+ const ztunnelEnvArgs = (env, undo) => [
1339
+ "-n",
1340
+ "istio-system",
1341
+ "set",
1342
+ "env",
1343
+ "daemonset/ztunnel",
1344
+ ...Object.keys(env).sort().map((key) => undo ? `${key}-` : `${key}=${env[key]}`)
1345
+ ];
1346
+ /**
1347
+ * This function sets the environment of ztunnel for a cell, or removes it (`undo`). Then it waits for
1348
+ * the rollout of the DaemonSet, and until no old ztunnel pod is left. An old pod drains for its
1349
+ * deadline after the rollout replaces it. Thus no run starts beside a ztunnel pod that is going.
1350
+ */
1351
+ const setZtunnelEnv = async (cluster, env, undo) => {
1352
+ await cluster.kubectl(ztunnelEnvArgs(env, undo));
1353
+ await cluster.kubectl([
1354
+ "-n",
1355
+ "istio-system",
1356
+ "rollout",
1357
+ "status",
1358
+ "daemonset/ztunnel",
1359
+ "--timeout=300s"
1360
+ ]);
1361
+ const until = Date.now() + 12e4;
1362
+ for (;;) {
1363
+ if (JSON.parse(await cluster.kubectl([
1364
+ "-n",
1365
+ "istio-system",
1366
+ "get",
1367
+ "pods",
1368
+ "-l",
1369
+ "app=ztunnel",
1370
+ "-o",
1371
+ "json"
1372
+ ])).items.every((item) => item.metadata.deletionTimestamp === void 0)) return;
1373
+ if (Date.now() > until) throw new Error("an old ztunnel pod is still going 120 s after the rollout");
1374
+ await new Promise((resolve) => setTimeout(resolve, 2e3));
1375
+ }
1376
+ };
1301
1377
  /** This function tells if the lab polls the LDS updates of the server sidecars of a cell: a policy in a sidecar mesh. */
1302
1378
  const pollsListeners = (cell) => cell.mesh?.mode === "sidecar" && cell.trigger.kind === "authorization-policy";
1303
1379
  //#endregion
@@ -2791,6 +2867,7 @@ const over = (ctx, run, lines) => {
2791
2867
  ].includes(kind) && (ctx.cell.template === "T07" || ctx.cell.template === "T15")) return kind === "scale-in" || kind === "node-drain" ? run.replicas.some((replica) => !ctx.tracker.pods.has(replica.pod)) : !ctx.tracker.pods.has(run.target.pod);
2792
2868
  if (kind === "rolling-update" || kind === "rollout") return run.replicas.every((replica) => !ctx.tracker.pods.has(replica.pod));
2793
2869
  if (kind === "app-stall") return lines.some((line) => line.ev === "stall" && line["phase"] === "end");
2870
+ if (kind === "ztunnel-restart") return ztunnelReplaced(lines, ctx.cluster.nodes);
2794
2871
  return true;
2795
2872
  };
2796
2873
  /** This function gives the replica that the trigger stopped. For a scale-in or a drain, the controller chooses it. */
@@ -3050,7 +3127,9 @@ const runKindCells = async (cells, options) => {
3050
3127
  const tracker = new Tracker();
3051
3128
  const off = lab.listen(tracker.see);
3052
3129
  const loads = [];
3130
+ const ztunnelEnv = cell.mesh?.ztunnel;
3053
3131
  try {
3132
+ if (ztunnelEnv !== void 0) await setZtunnelEnv(cluster, ztunnelEnv, false);
3054
3133
  const clusterIp = await deploy(lab, cluster, cell, namespace, images);
3055
3134
  for (const name of [...lab.own(), loader.getName().replace(/^\//, "")]) ours.add(name);
3056
3135
  const ctx = {
@@ -3112,6 +3191,7 @@ const runKindCells = async (cells, options) => {
3112
3191
  "--wait=true",
3113
3192
  "--timeout=300s"
3114
3193
  ]).catch((error) => options.log(` ${String(error)}`));
3194
+ if (ztunnelEnv !== void 0) await setZtunnelEnv(cluster, ztunnelEnv, true).catch((error) => options.log(` the undo of the environment of ztunnel failed: ${String(error)}`));
3115
3195
  }
3116
3196
  }
3117
3197
  } finally {
@@ -3149,7 +3229,8 @@ const estimate = (cell, environments = 2) => {
3149
3229
  "cpu-throttle": hold + 40,
3150
3230
  rollout: hold + 50,
3151
3231
  "authorization-policy": hold + 20,
3152
- idle: hold + 5
3232
+ idle: hold + 5,
3233
+ "ztunnel-restart": 40
3153
3234
  };
3154
3235
  const after = observationAfter(cell);
3155
3236
  const observed = after === null ? 0 : hold + valueIn(after, "s");
@@ -3186,6 +3267,6 @@ const shardOf = (cells, index, count) => {
3186
3267
  return out;
3187
3268
  };
3188
3269
  //#endregion
3189
- export { ACCESS_LOG_FORMAT, CLIENT, CLIENT_ACCOUNT, CONTROLLER, DOCUMENTED, DRAIN_RULES, EDS_EVERY, FLAG_CHECK, FORMAT, FORMAT_V1, HEALTH_PORT, ISTIOCTL, ISTIO_IMAGES, ISTIO_VERSION, KEPT_KERNEL, KIND, KIND_NOISE, KUBECTL, KUBE_PROXY_MODES, LAST_SLACK, LDS_EVERY, LDS_FILTER, LOG_LABEL, MESH_IMAGES, MESH_WORKLOADS, NODE_IMAGES, O04, O09, O10, O16, POLICY, PORT, REDIS, REDIS_IMAGE, RELATIVE, ROUTE, RULES_EVERY, SERVER, STAGES, WATCHDOG, backendsAt, backendsOf, bandOf, byClients, byNode, cacheFolder, calibrationOf, capOf, cellsTable, checkRun, cidrOverlap, cidrRange, clientObjects, clusterFilter, compose, createCluster, deletes, deletionOf, deletionWindow, deletionsOf, describeCell, dropOf, emptyOf, ensureTool, estimatedTime, factsOf, failuresOf, followsZtunnel, goDuration, hostsOf, installMesh, intakeAfter, intakeOf, istioOperator, judge, judgeKind, kernelCounts, kindCellRecordSchema, kindCellRecordV1Schema, kindConfig, kubeProxyPatch, kubeletBand, labImage, latchBand, lintCell, listenerCountsOf, localPin, medianInterval, medianText, meshKey, middle, namespaceObject, namespaceOf, nodeNames, observationAfter, observationEnd, openKindLab, outboundCluster, outcomesOf, pausedWindow, planOf, platformKey, podsAt, podsOf, policyObject, pollsListeners, predictionText, probeOf, propagationOf, propagationSource, quantileOf, readRecord, recordsOf, redisObjects, referenceOf, removalBand, requestsOf, restartBand, restartsAt, reusesReset, rulesOf, runKindCells, scenario, scenarioOf, scenarioProblems, seconds, secondsOf, serverCluster, serverObjects, sha256, shardOf, showBand, signalOf, signalsOf, sliceDropOf, sliceEmptyOf, slicesOf, socketsOf, stackOf, stageLabImage, stallRemovalBand, stoppingOf, tarEntry, timeSpread, toolPath, transitionOf, unitOf, updatesOf, upgrade, upgradeCell, verdictsOf, writeResult };
3270
+ export { ACCESS_LOG_FORMAT, CLIENT, CLIENT_ACCOUNT, CONTROLLER, DOCUMENTED, DRAIN_RULES, EDS_EVERY, FLAG_CHECK, FORMAT, FORMAT_V1, HEALTH_PORT, ISTIOCTL, ISTIO_IMAGES, ISTIO_VERSION, KEPT_KERNEL, KIND, KIND_NOISE, KUBECTL, KUBE_PROXY_MODES, LAST_SLACK, LDS_EVERY, LDS_FILTER, LOG_LABEL, MESH_IMAGES, MESH_WORKLOADS, NODE_IMAGES, O04, O09, O10, O16, POLICY, PORT, REDIS, REDIS_IMAGE, RELATIVE, ROUTE, RULES_EVERY, SERVER, STAGES, WATCHDOG, ZTUNNEL_PODS, backendsAt, backendsOf, bandOf, byClients, byNode, cacheFolder, calibrationOf, capOf, cellsTable, checkRun, cidrOverlap, cidrRange, clientObjects, clusterFilter, compose, createCluster, deletes, deletionOf, deletionWindow, deletionsOf, describeCell, dropOf, emptyOf, ensureTool, estimatedTime, factsOf, failuresOf, followsZtunnel, goDuration, hostsOf, installMesh, intakeAfter, intakeOf, istioOperator, judge, judgeKind, kernelCounts, kindCellRecordSchema, kindCellRecordV1Schema, kindConfig, kubeProxyPatch, kubeletBand, labImage, latchBand, lintCell, listenerCountsOf, localPin, medianInterval, medianText, meshKey, middle, namespaceObject, namespaceOf, nodeNames, observationAfter, observationEnd, openKindLab, outboundCluster, outcomesOf, pausedWindow, planOf, platformKey, podsAt, podsOf, policyObject, pollsListeners, predictionText, probeOf, propagationOf, propagationSource, quantileOf, readRecord, recordsOf, redisObjects, referenceOf, removalBand, requestsOf, restartBand, restartOf, restartsAt, reusesReset, rulesOf, runKindCells, scenario, scenarioOf, scenarioProblems, seconds, secondsOf, serverCluster, serverObjects, setZtunnelEnv, sha256, shardOf, showBand, signalOf, signalsOf, sliceDropOf, sliceEmptyOf, slicesOf, socketsOf, stackOf, stageLabImage, stallRemovalBand, stoppingOf, tarEntry, timeSpread, toolPath, transitionOf, unitOf, updatesOf, upgrade, upgradeCell, verdictsOf, writeResult, ztunnelEnvArgs, ztunnelPodsOf, ztunnelReplaced };
3190
3271
 
3191
3272
  //# sourceMappingURL=index.js.map