@mark1russell7/kind 0.13.1 → 0.13.3

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/build/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as unitOf, $n as scenario, $t as REDIS, A as TriggerV1, An as Template, At as recordsOf, B as RunCheck, Bn as KubeProxyMode, Bt as sliceReadyAt, C as KindCellResult, Cn as PodSettings, Ct as intakeOf, D as PredictionV1, Dn as Replica, Dt as periodOf, E as LoadSample, En as Reference, Et as outcomesOf, F as KIND_NOISE, Fn as DATAPLANES, Ft as sessionsAt, G as factsOf, Gn as ZONE_LOST, Gt as transitionOf, H as checkRun, Hn as NodeImage, Ht as slicesOf, I as KindDecision, In as Dataplane, It as signalOf, J as observationEnd, Jn as goDuration, Jt as ztunnelReplaced, K as judgeKind, Kn as cidrOverlap, Kt as tunnelsOf, L as KindVerdict, Ln as KUBE_PROXY_MODES, Lt as signalsOf, M as upgrade, Mn as TriggerKind, Mt as restartOf, N as upgradeCell, Nn as WindowPrediction, Nt as restartsAt, O as RunCheckV1, On as ResetReuse, Ot as podsAt, P as Deleted, Pn as Workload, Pt as rulesOf, Q as reusesReset, Qn as nodeNames, Qt as PORT, R as LAST_SLACK, Rn as KindConfig, Rt as sliceDropOf, S as KindCellRecordV1, Sn as NonePrediction, St as failuresOf, T as KindVerdictV1, Tn as RedisDeclaration, Tt as kernelCounts, U as cyclesOf, Un as ZONE_KEPT, Ut as socketsOf, V as RunFacts, Vn as NODE_IMAGES, Vt as sliceReadyOf, W as deletionsOf, Wn as ZONE_LABEL, Wt as stoppingOf, X as propagationSource, Xn as kindConfig, Xt as HEALTH_PORT, Y as propagationOf, Yn as isKubeProxyMode, Yt as CLIENT, Z as referenceOf, Zn as kubeProxyPatch, Zt as LOG_LABEL, _ as ClusterManifest, _n as KindRun, _t as byClients, a as STAGES, an as overshootBand, at as PodLine, b as FORMAT_V1, bn as MeshFlavor, bt as dropOf, c as readRecord, cn as secondsOf, ct as Request, d as calibrationOf, dn as Band, dt as SliceLine, en as SERVER, er as scenarioProblems, et as updatesOf, f as cellsTable, fn as Cycle, ft as SocketLine, g as BandV1, gn as KindCell, gt as backendsAt, h as timeSpread, hn as Flap, ht as ZtunnelPodLine, i as quantileOf, in as drainBand, it as Period, j as judge, jn as Trigger, jt as requestsOf, k as RunFactsV1, kn as Stack, kt as podsOf, l as Judged, ln as showBand, lt as RulesLine, m as predictionText, mn as EdgeProtocol, mt as TunnelLine, n as medianInterval, nn as backlogEnd, nt as HBONE_PORT, o as kindCellRecordSchema, on as requestBand, ot as PropagationSource, p as medianText, pn as Declaration, pt as TCP_STATE, q as observationAfter, qn as cidrRange, qt as ztunnelPodsOf, r as middle, rn as bandOf, rt as Line, s as kindCellRecordV1Schema, sn as seconds, st as RecordLine, t as RELATIVE, tn as CountBand, tr as zoneOf, tt as Endpoint, u as TimeSpread, un as BacklogTerm, ut as Sessions, v as EnvironmentManifest, vn as KubeletProbe, vt as byNode, w as KindCellV1, wn as Prediction, wt as isTunnelState, x as KindCellRecord, xn as MeshMode, xt as emptyOf, y as FORMAT, yn as Mesh, yt as deletionOf, z as Propagated, zn as KindScenario, zt as sliceEmptyOf } from "./judge-CSWVew2-.js";
1
+ import { $ as unitOf, $n as cidrRange, $t as OUTSIDE, A as TriggerV1, An as Reference, At as recordsOf, B as RunCheck, Bn as Workload, Bt as sliceReadyAt, C as KindCellResult, Cn as MeshFlavor, Ct as intakeOf, D as PredictionV1, Dn as PodSettings, Dt as periodOf, E as LoadSample, En as PermittedWindow, Et as outcomesOf, F as KIND_NOISE, Fn as Trigger, Ft as sessionsAt, G as factsOf, Gn as KindScenario, Gt as transitionOf, H as checkRun, Hn as Dataplane, Ht as slicesOf, I as KindDecision, In as TriggerKind, It as signalOf, J as observationEnd, Jn as NodeImage, Jt as ztunnelReplaced, K as judgeKind, Kn as KubeProxyMode, Kt as tunnelsOf, L as KindVerdict, Ln as VipAnnouncerName, Lt as signalsOf, M as upgrade, Mn as ResetReuse, Mt as restartOf, N as upgradeCell, Nn as Stack, Nt as restartsAt, O as RunCheckV1, On as Prediction, Ot as podsAt, P as Deleted, Pn as Template, Pt as rulesOf, Q as reusesReset, Qn as cidrOverlap, Qt as LOG_LABEL, R as LAST_SLACK, Rn as VipSettings, Rt as sliceDropOf, S as KindCellRecordV1, Sn as Mesh, St as failuresOf, T as KindVerdictV1, Tn as NonePrediction, Tt as kernelCounts, U as cyclesOf, Un as KUBE_PROXY_MODES, Ut as socketsOf, V as RunFacts, Vn as DATAPLANES, Vt as sliceReadyOf, W as deletionsOf, Wn as KindConfig, Wt as stoppingOf, X as propagationSource, Xn as ZONE_LABEL, Xt as HEALTH_PORT, Y as propagationOf, Yn as ZONE_KEPT, Yt as CLIENT, Z as referenceOf, Zn as ZONE_LOST, Zt as LB_CLASS, _ as ClusterManifest, _n as EdgeProtocol, _t as byClients, a as STAGES, an as backlogEnd, ar as scenario, at as PodLine, b as FORMAT_V1, bn as KindRun, bt as dropOf, c as readRecord, cn as overshootBand, ct as Request, d as calibrationOf, dn as secondsOf, dt as SliceLine, en as PORT, er as goDuration, et as updatesOf, f as cellsTable, fn as showBand, ft as SocketLine, g as BandV1, gn as Declaration, gt as backendsAt, h as timeSpread, hn as Cycle, ht as ZtunnelPodLine, i as quantileOf, in as CountBand, ir as nodeNames, it as Period, j as judge, jn as Replica, jt as requestsOf, k as RunFactsV1, kn as RedisDeclaration, kt as podsOf, l as Judged, ln as requestBand, lt as RulesLine, m as predictionText, mn as Band, mt as TunnelLine, n as medianInterval, nn as SERVER, nr as kindConfig, nt as HBONE_PORT, o as kindCellRecordSchema, on as bandOf, or as scenarioProblems, ot as PropagationSource, p as medianText, pn as BacklogTerm, pt as TCP_STATE, q as observationAfter, qn as NODE_IMAGES, qt as ztunnelPodsOf, r as middle, rn as VIP_ANNOTATION, rr as kubeProxyPatch, rt as Line, s as kindCellRecordV1Schema, sn as drainBand, sr as zoneOf, st as RecordLine, t as RELATIVE, tn as REDIS, tr as isKubeProxyMode, tt as Endpoint, u as TimeSpread, un as seconds, ut as Sessions, v as EnvironmentManifest, vn as Flap, vt as byNode, w as KindCellV1, wn as MeshMode, wt as isTunnelState, x as KindCellRecord, xn as KubeletProbe, xt as emptyOf, y as FORMAT, yn as KindCell, yt as deletionOf, z as Propagated, zn as WindowPrediction, zt as sliceEmptyOf } from "./judge-DhLShDUj.js";
2
2
  import { Quantity } from "@mark1russell7/quantity";
3
3
  import { CheckFn, Coupling, Finding, HealthServer, Poll, Scenario, ServiceBuilder, ServiceDescription, Stage, StopWay, Timing, TransportImpl, Verdict } from "@mark1russell7/service";
4
4
  import { BuildImage } from "@mark1russell7/harness";
@@ -75,6 +75,29 @@ interface Cluster {
75
75
  */
76
76
  export declare const createCluster: (scenario: KindScenario, dir: string) => Promise<Cluster>;
77
77
  //#endregion
78
+ //#region src/helm.d.ts
79
+ /**
80
+ * This module installs a Helm chart that is pinned by the sha256 of its file. The installs of Cilium
81
+ * (`cilium.ts`) and of MetalLB (`metallb.ts`) use it. Helm keeps its own files in the folder of the
82
+ * cluster, thus two clusters do not share a cache of Helm.
83
+ */
84
+ /** A pinned chart is a Helm chart: its name, its version, the URL of its file and the sha256 of that file. */
85
+ interface PinnedChart {
86
+ readonly name: string;
87
+ readonly version: string;
88
+ readonly url: string;
89
+ readonly sha256: string;
90
+ }
91
+ /** This function gives the path of a chart in the cache, after a download when the cache does not have it. It refuses a file whose sha256 is not the pinned value. */
92
+ export declare const ensurePinnedChart: (chart: PinnedChart, cache?: string) => Promise<string>;
93
+ /**
94
+ * This function installs a pinned chart in a cluster with the values `values`. It writes the values
95
+ * to a file in the folder of the cluster. Helm waits for each workload of the chart, for up to 10 min.
96
+ */
97
+ export declare const helmInstall: (cluster: Pick<Cluster, "dir" | "kubeconfig">, release: string, chart: PinnedChart, namespace: string, values: Readonly<Record<string, unknown>>, options?: {
98
+ readonly createNamespace?: boolean;
99
+ }) => Promise<void>;
100
+ //#endregion
78
101
  //#region src/cilium.d.ts
79
102
  /**
80
103
  * This module installs Cilium 1.20.4 in a kind cluster with Helm, from images pinned by digest.
@@ -84,10 +107,7 @@ export declare const createCluster: (scenario: KindScenario, dir: string) => Pro
84
107
  /** This version is the release of Cilium of the lab, from 2026-10-23: the version of the chart and the tag of each image. */
85
108
  export declare const CILIUM_VERSION = "1.20.4";
86
109
  /** This chart is the Helm chart of Cilium 1.20.4. The sha256 is of the file on `helm.cilium.io` (read on 2026-10-27). */
87
- export declare const CILIUM_CHART: {
88
- readonly url: string;
89
- readonly sha256: string;
90
- };
110
+ export declare const CILIUM_CHART: PinnedChart;
91
111
  /**
92
112
  * These are the images that the install needs, pinned by the digests that the chart of 1.20.4 names
93
113
  * (`values.yaml`). The agent, the operator and Envoy are the only images: the install has no
@@ -581,6 +601,20 @@ interface LdsSpec {
581
601
  readonly pid: number;
582
602
  }>;
583
603
  }
604
+ /**
605
+ * This function gives the MAC address of `ip` in a table of /proc/net/arp, in lower case. It gives
606
+ * null if the table has no row for `ip`, or if the row has the flags 0x0: no MAC yet. The ARP watch
607
+ * of `client.mjs` reads the table the same way.
608
+ */
609
+ export declare const arpMacOf: (table: string, ip: string) => string | null;
610
+ /** An outside spec is the clients outside the cluster: their target, interval, timeout and count, and the address whose MAC they watch. */
611
+ interface OutsideSpec {
612
+ readonly target: string;
613
+ readonly every: Quantity;
614
+ readonly timeout: Quantity;
615
+ readonly count: number;
616
+ readonly arp: string;
617
+ }
584
618
  /** A kind lab is the instruments of one cluster: a sidecar pair on each node, the watcher of the API and the prober. */
585
619
  interface KindLab {
586
620
  readonly cluster: Cluster;
@@ -607,6 +641,18 @@ interface KindLab {
607
641
  }): Promise<void>;
608
642
  probe(netns: readonly number[]): Promise<void>;
609
643
  stopProbe(): Promise<void>;
644
+ /**
645
+ * This method starts the clients outside the cluster of a VIP (`KindCell.vip`). Each one is a
646
+ * container of the lab image on the Docker network of the nodes, and runs `client.mjs`. Its lines
647
+ * have the node `outside`, and a line `arp` at each change of the MAC address of the VIP. A
648
+ * call stops the clients of the last call first. With null, it only stops them.
649
+ */
650
+ outside(spec: OutsideSpec | null): Promise<void>;
651
+ /** This method gives the MAC address of `ip` in the neighbour table of each client outside the cluster. It is null for a client with no MAC for it. */
652
+ outsideMacs(ip: string): Promise<ReadonlyArray<{
653
+ readonly client: string;
654
+ readonly mac: string | null;
655
+ }>>;
610
656
  /** This method asks each agent to poll the backends of a Service in the rules of its node, `every` apart, or to stop with null. */
611
657
  rules(rule: (ServiceRule & {
612
658
  readonly every: Quantity;
@@ -660,6 +706,288 @@ export declare const openKindLab: (cluster: Cluster, image: string) => Promise<K
660
706
  /** This function pins a Docker image by digest under a local tag that holds the digest, for `kind load` and `imagePullPolicy: Never`. */
661
707
  export declare const localPin: (image: string) => Promise<string>;
662
708
  //#endregion
709
+ //#region src/kubevip.d.ts
710
+ /**
711
+ * This module installs kube-vip 1.3.1 in a kind cluster (SYS-51). The install gives a Service of type
712
+ * LoadBalancer an address on the Docker network of the nodes: the VIP. In ARP mode, one node holds
713
+ * the VIP on its link, and it sends a gratuitous ARP for it each `vip_arpRate`. A Lease elects that
714
+ * node. Each value of the install is in `kubeVipObjects`, with its reason.
715
+ *
716
+ * The lab uses a VIP of a Service, not a VIP of the control plane. A VIP of the control plane needs
717
+ * three control-plane nodes and TLS on port 6443. A VIP of a Service needs one DaemonSet on the
718
+ * workers, and it serves the server of the cell.
719
+ *
720
+ * Each term of the election comes from the source of v1.3.1:
721
+ * - With `svc_election` off, one election of the lease `plndr-svcs-lock` gives each VIP to one
722
+ * node (pkg/manager/worker/common.go, `GlobalLeader`). The lease is in the namespace of the pod.
723
+ * - The election is `leaderelection.RunOrDie` of client-go v0.37.1, with a Lease lock and
724
+ * `ReleaseOnCancel` (pkg/election/election.go). The identity is the name of the node.
725
+ * - A leader that loses its lease stops the process (`OnStoppedLeading`), and the kubelet starts it again.
726
+ * - The ARP manager sends a gratuitous ARP for each VIP at each tick of one ticker of
727
+ * `vip_arpRate`. A new VIP gets its first one at the next tick, not at once (pkg/arp/arp.go).
728
+ */
729
+ /** This version is the release of kube-vip of the lab, from 2026-10-19: the tag of its image. */
730
+ export declare const KUBE_VIP_VERSION = "1.3.1";
731
+ /**
732
+ * This image is kube-vip 1.3.1 for linux/amd64, pinned by the digest of its manifest. The digest of
733
+ * the index of the tag is sha256:1962f9daf226503f7e6b107f595cb28b7917fd2d0113957075e19a3e5a6c1e33.
734
+ * The manifest of one platform loads into kind with no index.
735
+ */
736
+ export declare const KUBE_VIP_IMAGE = "ghcr.io/kube-vip/kube-vip:v1.3.1@sha256:47353c7bde7fec21642cf621bc3fda2b999c051342912efda468999a399be667";
737
+ /** This is the name of kube-vip: of its ServiceAccount, its DaemonSet and its container. */
738
+ export declare const KUBE_VIP = "kube-vip";
739
+ /** This is the Lease of the election of the VIPs of the Services (`svc_leasename`, cmd/kube-vip.go of v1.3.1). */
740
+ export declare const KUBE_VIP_LEASE: {
741
+ readonly namespace: string;
742
+ readonly name: string;
743
+ };
744
+ /**
745
+ * These are the times of the election, as the install sets them. Each one is the default of the
746
+ * flags of v1.3.1 (cmd/kube-vip.go, lines 91–94). They are a lease of 15 s, a renew deadline of 10 s
747
+ * and a retry period of 2 s. The install sets each one in the environment, thus a new default cannot
748
+ * change a cell.
749
+ */
750
+ export declare const KUBE_VIP_ELECTION: {
751
+ readonly lease: Quantity;
752
+ readonly renew: Quantity;
753
+ readonly retry: Quantity;
754
+ };
755
+ /** This time is the interval of the gratuitous ARPs, the default of the flag `arpRate` of v1.3.1 (cmd/kube-vip.go, line 61). */
756
+ export declare const KUBE_VIP_ARP_RATE: Quantity;
757
+ /** This label of a node selects the nodes of kube-vip: the DaemonSet has a pod only on a node with it. */
758
+ export declare const VIP_LABEL = "lab.systems/vip";
759
+ /**
760
+ * This function gives the objects of kube-vip in kube-system. They are its ServiceAccount, its
761
+ * ClusterRole and binding, and its DaemonSet. The rules of the role are those of the manifest that
762
+ * v1.3.1 generates (pkg/kubevip/config_generator.go, lines 95–134). The DaemonSet:
763
+ * - is on the host network, with NET_ADMIN and NET_RAW. It adds the VIP to `eth0` and sends ARP.
764
+ * - has a pod only on a node with `VIP_LABEL`. Thus the lab chooses the holder of the VIP.
765
+ * - sets ARP mode, the Services, one election for all VIPs, and each time of the election.
766
+ * - takes the image from the node (`imagePullPolicy: Never`).
767
+ */
768
+ export declare const kubeVipObjects: (image: string) => unknown[];
769
+ /** This is the Lease of the election, as the API gives it: its holder and its times. */
770
+ interface VipLease {
771
+ readonly holder: string | null;
772
+ readonly acquireTime: string | null;
773
+ readonly renewTime: string | null;
774
+ readonly leaseDurationSeconds: number | null;
775
+ readonly leaseTransitions: number | null;
776
+ }
777
+ /** This function gives the Lease of the election, or null when it is not there yet. */
778
+ export declare const vipLeaseOf: (cluster: Pick<Cluster, "kubectl">) => Promise<VipLease | null>;
779
+ /** This is the Docker network of a cluster: its IPv4 subnet, and the MAC address of each container on it, by name. */
780
+ interface VipNetwork {
781
+ readonly subnet: string;
782
+ readonly macs: Readonly<Record<string, string>>;
783
+ }
784
+ /** This function reads the Docker network of a cluster: its IPv4 subnet, and the MAC address of each container. */
785
+ export declare const vipNetworkOf: (network: string) => Promise<VipNetwork>;
786
+ /**
787
+ * This function gives the VIP of a subnet: the sixth address from its end. Docker gives the address
788
+ * of each container from the start of the subnet, thus no container takes it.
789
+ */
790
+ export declare const vipOf: (subnet: string) => string;
791
+ /** This is a pod of kube-vip that is not deleted: its name, its node, if it is ready, and the restarts of its container. */
792
+ interface KubeVipPod {
793
+ readonly name: string;
794
+ readonly node: string;
795
+ readonly ready: boolean;
796
+ readonly restarts: number;
797
+ }
798
+ /** This function gives the pods of kube-vip that are not deleted. */
799
+ export declare const kubeVipPods: (cluster: Pick<Cluster, "kubectl">) => Promise<KubeVipPod[]>;
800
+ /** This function gives the nodes with a ready pod of kube-vip that is not deleted. */
801
+ export declare const kubeVipReady: (cluster: Pick<Cluster, "kubectl">) => Promise<string[]>;
802
+ /**
803
+ * This function makes `holder` the holder of the VIP, with a ready pod of kube-vip on each node of
804
+ * `nodes`. It gives null, or why it could not in `within` ms. If another node holds the lease, the
805
+ * function takes the label from each other node. The DaemonSet then deletes their pods. The leader
806
+ * gives back its lease at its stop (`ReleaseOnCancel`). The function gives each label back after
807
+ * `holder` takes the lease.
808
+ *
809
+ * A leader that lost its lease restarted its container. The kubelet gives a container a longer
810
+ * back-off at each restart, thus the function first deletes each pod of kube-vip with a restart.
811
+ * The DaemonSet then makes a new pod with no back-off.
812
+ */
813
+ export declare const holdVip: (cluster: Pick<Cluster, "kubectl">, holder: string, nodes: readonly string[], within?: number) => Promise<string | null>;
814
+ /**
815
+ * This function installs kube-vip in a cluster, with its image on each node (`cluster.load`), and
816
+ * makes `holder` the holder of the VIP. A failed install gives the pods of kube-vip and the tail of
817
+ * their logs.
818
+ */
819
+ export declare const installKubeVip: (cluster: Cluster, image: string, holder: string, nodes: readonly string[]) => Promise<void>;
820
+ /**
821
+ * This function waits until the Service of a VIP has the VIP in its status: kube-vip took it. It
822
+ * gives null, or why not in `within` ms.
823
+ */
824
+ export declare const vipServed: (cluster: Pick<Cluster, "kubectl">, namespace: string, service: string, vip: string, within?: number) => Promise<string | null>;
825
+ //#endregion
826
+ //#region src/announcer.d.ts
827
+ /**
828
+ * This module gives one shape to each announcer of a VIP: kube-vip (SYS-51) and MetalLB in L2 mode
829
+ * (SYS-53). The lab, the Service of the VIP and the clients outside the cluster are the same for
830
+ * each one. Only the install, the choice of the VIP, the hold before each run and the record differ.
831
+ */
832
+ /** This is how the Service of a VIP selects its announcer: its class of load balancer, or none, and the annotation of its address. */
833
+ interface VipService {
834
+ readonly loadBalancerClass: string | null;
835
+ readonly annotation: string;
836
+ }
837
+ /** An announcer is one way to give a Service of type LoadBalancer a VIP on the Docker network of the nodes. */
838
+ interface VipAnnouncer {
839
+ readonly name: VipAnnouncerName;
840
+ /** These are the images of the announcer, pinned by digest, by their names in the manifest of a record. */
841
+ readonly images: Readonly<Record<string, string>>;
842
+ readonly service: VipService;
843
+ /** This time is the most from the end of a hold to the first gratuitous ARP of the holder. */
844
+ readonly settle: Quantity;
845
+ /** This function gives the VIP of a subnet, with `owner` its holder among `nodes`. */
846
+ readonly vipOf: (subnet: string, owner: string, nodes: readonly string[]) => string;
847
+ /** This function installs the announcer, with the local tags of its images, by the names of `images`. */
848
+ readonly install: (cluster: Cluster, local: Readonly<Record<string, string>>, owner: string, nodes: readonly string[], vip: string) => Promise<void>;
849
+ /** This function makes `owner` the holder of the VIP before a run. It gives null, or why not. */
850
+ readonly hold: (cluster: Cluster, owner: string, nodes: readonly string[], namespace: string, service: string) => Promise<string | null>;
851
+ /** This function gives the state of the announcer after a run, for the line `vip`. */
852
+ readonly record: (cluster: Cluster, namespace: string, service: string) => Promise<Record<string, unknown>>;
853
+ }
854
+ /** This announcer is kube-vip 1.3.1 in ARP mode, with one Lease for each VIP of a Service (`kubevip.ts`). */
855
+ export declare const KUBE_VIP_ANNOUNCER: VipAnnouncer;
856
+ /** This announcer is MetalLB 0.16.1 in L2 mode, with its speakers in memberlist (`metallb.ts`). */
857
+ export declare const METALLB_ANNOUNCER: VipAnnouncer;
858
+ /** This function gives the announcer of the VIP of a cell: kube-vip when the cell names none. */
859
+ export declare const announcerOf: (cell: Pick<KindCell, "vip">) => VipAnnouncer;
860
+ /** This function gives null if each client sends to `mac`, or the clients that do not. */
861
+ export declare const macsAt: (found: ReadonlyArray<{
862
+ readonly client: string;
863
+ readonly mac: string | null;
864
+ }>, mac: string, count: number) => string | null;
865
+ //#endregion
866
+ //#region src/metallb.d.ts
867
+ /**
868
+ * This module installs MetalLB 0.16.1 in L2 mode in a kind cluster (SYS-53). The controller of
869
+ * MetalLB gives a Service of type LoadBalancer an address from a pool: the VIP. A speaker on each
870
+ * worker answers ARP for the VIP if its node owns the VIP. The VIP is on no interface of a node.
871
+ * Thus a frozen speaker answers nothing.
872
+ *
873
+ * Each term of the owner comes from the source of the tag v0.16.1 (commit 791dfcc6):
874
+ * - The owner of a VIP is the first node in the order of sha256(node + "#" + VIP), of the nodes with
875
+ * a usable speaker (speaker/layer2_controller.go, lines 83–129). A usable speaker is a member of
876
+ * memberlist that is not dead (internal/speakerlist/speakerlist.go, lines 303–320).
877
+ * - The speakers start memberlist from `DefaultLANConfig` (speakerlist.go, line 72). A file
878
+ * /etc/metallb/memberlist/config.json replaces that config (lines 77–84). The install makes no
879
+ * such file, thus each value is the default of hashicorp/memberlist v0.5.1.
880
+ * - Each event of memberlist (a join, a leave or an update) calls `ForceSync` (speakerlist.go, lines
881
+ * 339–349). `ForceSync` reconciles each Service at once, with no delay (internal/k8s/k8s.go, lines
882
+ * 181–184, and internal/k8s/controllers/service_controller_reload.go, lines 62–118).
883
+ * - The owner sends a gratuitous ARP at each reconcile. It sends one at once, then one each 1100 ms
884
+ * for 5 s (internal/layer2/announcer.go, lines 157–197 and 258–272).
885
+ */
886
+ /** This version is the release of MetalLB of the lab: the tag v0.16.1, the commit 791dfcc63ced7a6b3e869131eae75e645150fff0. */
887
+ export declare const METALLB_VERSION = "0.16.1";
888
+ /** This chart is the Helm chart of MetalLB 0.16.1. The sha256 is of the file of the release, and it is the digest in the index of the charts. */
889
+ export declare const METALLB_CHART: PinnedChart;
890
+ /**
891
+ * These are the images of MetalLB 0.16.1 for linux/amd64, pinned by the digest of the manifest of the
892
+ * platform. The lab pulls each one by its digest, tags it (`localPin`), and loads it into each node.
893
+ */
894
+ export declare const METALLB_IMAGES: {
895
+ readonly speaker: string;
896
+ readonly controller: string;
897
+ };
898
+ /** These are the local tags of the images of MetalLB, after the pull by digest. */
899
+ interface MetallbImages {
900
+ readonly speaker: string;
901
+ readonly controller: string;
902
+ }
903
+ /** This namespace holds MetalLB: its controller, its speakers and its objects. */
904
+ export declare const METALLB_NAMESPACE = "metallb-system";
905
+ /** This annotation of a Service gives the controller of MetalLB the address of its VIP. */
906
+ export declare const METALLB_ANNOTATION = "metallb.io/loadBalancerIPs";
907
+ /** This name is the name of the pool of the VIP and of its L2Advertisement. */
908
+ export declare const METALLB_POOL = "lab-vip";
909
+ /** This annotation of the Service makes each speaker reconcile it. The owner then sends its gratuitous ARPs. */
910
+ export declare const ANNOUNCE_ANNOTATION = "lab.systems/announce";
911
+ /**
912
+ * These are the terms of memberlist v0.5.1 that the speakers use: the defaults of `DefaultLANConfig`
913
+ * (config.go, lines 302–341).
914
+ * - `probeInterval` is the interval of the probes (line 318). The awareness of a healthy member does not scale it.
915
+ * - `probeTimeout` is the wait for the ack of a direct ping (line 317).
916
+ * - `suspicionMult` and `suspicionMaxTimeoutMult` give the time from suspect to dead (lines 314–315).
917
+ * - `pushPullInterval` is the interval of the full exchange of state (line 316).
918
+ * - `gossipInterval` is the interval of the gossip (line 323).
919
+ */
920
+ export declare const MEMBERLIST: {
921
+ readonly probeInterval: Quantity;
922
+ readonly probeTimeout: Quantity;
923
+ readonly suspicionMult: number;
924
+ readonly suspicionMaxTimeoutMult: number;
925
+ readonly pushPullInterval: Quantity;
926
+ readonly gossipInterval: Quantity;
927
+ };
928
+ /** These are the gratuitous ARPs of the owner at each reconcile: one at once, then one each `every` until `for` (announcer.go, lines 172–182). */
929
+ export declare const METALLB_SPAM: {
930
+ readonly every: Quantity;
931
+ readonly for: Quantity;
932
+ };
933
+ /**
934
+ * This function gives the time from suspect to dead in memberlist v0.5.1, for a cluster of `members`
935
+ * members with no peer that can confirm. The terms:
936
+ * - `suspicionTimeout` is SuspicionMult × max(1, log10(n)) × ProbeInterval (util.go, lines 71–76).
937
+ * - `suspectNode` sets k = SuspicionMult − 2 confirmations, and k = 0 if n − 2 < k (state.go, lines 1216–1224).
938
+ * - With k = 0, the timer fires at the minimum, not at the maximum (suspicion.go, lines 70–76).
939
+ * With confirmations to wait for, the function gives the maximum: SuspicionMaxTimeoutMult times the minimum.
940
+ */
941
+ export declare const suspicionOf: (members: number, terms?: Pick<typeof MEMBERLIST, "probeInterval" | "suspicionMult" | "suspicionMaxTimeoutMult">) => Quantity;
942
+ /**
943
+ * This function gives the Helm values of the install. The values that are not the defaults of the chart:
944
+ * - No FRR and no frr-k8s: the lab uses L2 mode only, thus it needs no BGP.
945
+ * - A speaker only on a node with `VIP_LABEL`, the workers. Thus memberlist has the workers as its
946
+ * members, and the control plane does not answer ARP.
947
+ * - The controller on the control plane. A zone loss of a worker then does not take it away.
948
+ * - Each image from the node (`pullPolicy: Never`).
949
+ */
950
+ export declare const metallbValues: (images: MetallbImages) => Record<string, unknown>;
951
+ /** This function gives the pool of the VIP and its L2Advertisement. The pool has only the VIP. */
952
+ export declare const metallbObjects: (vip: string) => unknown[];
953
+ /** This function gives the nodes in the order of the election of the owner of `vip`: by sha256(node + "#" + vip), as bytes (layer2_controller.go, lines 115–120). */
954
+ export declare const ownerOrder: (nodes: readonly string[], vip: string) => string[];
955
+ /**
956
+ * This function gives the VIP of a subnet for MetalLB. It looks down from the sixth address from the
957
+ * end, and it gives the first address that `owner` owns, of the nodes `nodes`. Docker gives the address of each container
958
+ * from the start of the subnet, thus no container takes it.
959
+ */
960
+ export declare const metallbVipOf: (subnet: string, owner: string, nodes: readonly string[]) => string;
961
+ /** This is a ServiceL2Status of MetalLB: the node that announces a Service, and the time of the object. */
962
+ interface Announcement {
963
+ readonly node: string;
964
+ readonly created: string | null;
965
+ }
966
+ /** This function gives the nodes that announce a Service, from the ServiceL2Status objects of the speakers. */
967
+ export declare const announcementsOf: (cluster: Pick<Cluster, "kubectl">, namespace: string, service: string) => Promise<Announcement[]>;
968
+ /** This function gives the nodes with a ready speaker that is not deleted. */
969
+ export declare const speakersReady: (cluster: Pick<Cluster, "kubectl">) => Promise<string[]>;
970
+ /**
971
+ * This function makes `owner` the only node that announces the Service, with a ready speaker on each
972
+ * node of `nodes`. It gives null, or why it could not in `within` ms. After a heal, the other node
973
+ * stops when it sees that the owner is alive again. The function then annotates the Service. Each
974
+ * speaker reconciles it, and the owner sends its gratuitous ARPs for 5 s. Thus each client learns
975
+ * the MAC address of the owner.
976
+ */
977
+ export declare const holdMetallb: (cluster: Pick<Cluster, "kubectl">, owner: string, nodes: readonly string[], namespace: string, service: string, within?: number) => Promise<string | null>;
978
+ /**
979
+ * This function installs MetalLB in a cluster, with its images on each node, the speakers on `nodes`,
980
+ * and a pool of the VIP. The webhook of the controller checks the pool, thus the function tries the
981
+ * pool again until the webhook answers. A failed install gives the pods of MetalLB and the tail of
982
+ * their logs.
983
+ */
984
+ export declare const installMetallb: (cluster: Cluster, images: MetallbImages, nodes: readonly string[], vip: string) => Promise<void>;
985
+ /**
986
+ * This function gives the record of MetalLB after a run: the nodes that announce the Service, and
987
+ * some lines of each speaker. The lines are about memberlist and the announces, with the times of the kubelet.
988
+ */
989
+ export declare const metallbRecord: (cluster: Pick<Cluster, "kubectl">, namespace: string, service: string) => Promise<Record<string, unknown>>;
990
+ //#endregion
663
991
  //#region src/lds.d.ts
664
992
  /**
665
993
  * This filter of RE2 selects the two counters of the listener manager of Envoy that an update of LDS
@@ -709,11 +1037,23 @@ export declare const namespaceObject: (cell: Pick<KindCell, "mesh">, namespace:
709
1037
  export declare const probeOf: (path: string | null, probe: KubeletProbe, service?: string) => Record<string, unknown>;
710
1038
  /** These are the objects of Redis: one replica behind a Service, with no persistence. */
711
1039
  export declare const redisObjects: (namespace: string, image: string) => unknown[];
1040
+ /**
1041
+ * This function gives the Service of a VIP (`announcer.ts`). It is of type LoadBalancer, with the
1042
+ * class of its announcer, if the announcer has one. The annotation of the announcer has the address
1043
+ * of the VIP. Without `service`, the announcer is kube-vip. The policy `Cluster` lets each node
1044
+ * send a request to a replica on another node. The holder writes the address to the status of the
1045
+ * Service. Then kube-proxy has the rules of the address on each node.
1046
+ */
1047
+ export declare const vipService: (namespace: string, vip: string, ports: readonly unknown[], service?: VipService) => unknown;
712
1048
  /**
713
1049
  * These are the objects of the server: a Service of type ClusterIP, and the Deployment with the
714
1050
  * settings of the cell. The image is the lab image for the service, or the image of grpc-go.
1051
+ *
1052
+ * With a VIP (`KindCell.vip`), the Service is of type LoadBalancer, with the address `vip` and the
1053
+ * class of its announcer (`vipService`). No replica is in the lost zone. Thus a zone loss takes away
1054
+ * only the holder of the VIP.
715
1055
  */
716
- export declare const serverObjects: (cell: KindCell, namespace: string, image: string, version?: number) => unknown[];
1056
+ export declare const serverObjects: (cell: KindCell, namespace: string, image: string, version?: number, vip?: string | null) => unknown[];
717
1057
  /**
718
1058
  * These are the objects of the clients: a DaemonSet with one client on each node, the control plane
719
1059
  * too. The client of the service is `client.mjs`, and the client of grpc-go is `client-grpc.mjs`.
@@ -1011,5 +1351,5 @@ export declare const toolPath: (tool: Tool, key?: string, cache?: string) => str
1011
1351
  */
1012
1352
  export declare const ensureTool: (tool: Tool, key?: string, cache?: string) => Promise<string>;
1013
1353
  //#endregion
1014
- export { type BacklogTerm, type Band, type BandV1, CLIENT, type CiliumImages, type Cluster, type ClusterHosts, type ClusterManifest, type CountBand, type Credentials, type Cycle, DATAPLANES, DRAIN_RULES, type Dataplane, type Declaration, type Deleted, type DeletionWindow, type EdgeProtocol, type EdsSpec, Endpoint, type EnvironmentManifest, FORMAT, FORMAT_V1, type FaultPlan, type Flap, HBONE_PORT, 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, type LeafCertificate, type LearnWindow, Line, type ListenerCounts, type LoadSample, type Mesh, type MeshFlavor, type MeshImages, type MeshMode, NODE_IMAGES, type NodeImage, type NodeLifecycle, type NonePrediction, O04, O09, O10, O16, PORT, type Parts, Period, 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, Sessions, SliceLine, SocketLine, type Stack, type Stamp, type Step, TCP_STATE, type Target, type Template, type TimeSpread, type Tool, type Trigger, type TriggerKind, type TriggerV1, TunnelLine, type Verdicts, type WindowPrediction, type Workload, ZONE_KEPT, ZONE_LABEL, ZONE_LOST, ZtunnelPodLine, backendsAt, backlogEnd, bandOf, byClients, byNode, calibrationOf, cellsTable, checkRun, cidrOverlap, cidrRange, cyclesOf, deletionOf, deletionsOf, drainBand, dropOf, emptyOf, factsOf, failuresOf, goDuration, intakeOf, isKubeProxyMode, isTunnelState, judge, judgeKind, kernelCounts, kindCellRecordSchema, kindCellRecordV1Schema, kindConfig, kubeProxyPatch, medianInterval, medianText, middle, nodeNames, observationAfter, observationEnd, outcomesOf, overshootBand, periodOf, podsAt, podsOf, predictionText, propagationOf, propagationSource, quantileOf, readRecord, recordsOf, referenceOf, requestBand, requestsOf, restartOf, restartsAt, reusesReset, rulesOf, scenario, scenarioProblems, seconds, secondsOf, sessionsAt, showBand, signalOf, signalsOf, sliceDropOf, sliceEmptyOf, sliceReadyAt, sliceReadyOf, slicesOf, socketsOf, stoppingOf, timeSpread, transitionOf, tunnelsOf, unitOf, updatesOf, upgrade, upgradeCell, zoneOf, ztunnelPodsOf, ztunnelReplaced };
1354
+ export { type Announcement, type BacklogTerm, type Band, type BandV1, CLIENT, type CiliumImages, type Cluster, type ClusterHosts, type ClusterManifest, type CountBand, type Credentials, type Cycle, DATAPLANES, DRAIN_RULES, type Dataplane, type Declaration, type Deleted, type DeletionWindow, type EdgeProtocol, type EdsSpec, Endpoint, type EnvironmentManifest, FORMAT, FORMAT_V1, type FaultPlan, type Flap, HBONE_PORT, 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 KubeVipPod, type KubeletProbe, LAST_SLACK, LB_CLASS, LOG_LABEL, type LdsSpec, type LeafCertificate, type LearnWindow, Line, type ListenerCounts, type LoadSample, type Mesh, type MeshFlavor, type MeshImages, type MeshMode, type MetallbImages, NODE_IMAGES, type NodeImage, type NodeLifecycle, type NonePrediction, O04, O09, O10, O16, OUTSIDE, type OutsideSpec, PORT, type Parts, Period, type PermittedWindow, type PinnedChart, 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, Sessions, SliceLine, SocketLine, type Stack, type Stamp, type Step, TCP_STATE, type Target, type Template, type TimeSpread, type Tool, type Trigger, type TriggerKind, type TriggerV1, TunnelLine, VIP_ANNOTATION, type Verdicts, type VipAnnouncer, type VipAnnouncerName, type VipLease, type VipNetwork, type VipService, type VipSettings, type WindowPrediction, type Workload, ZONE_KEPT, ZONE_LABEL, ZONE_LOST, ZtunnelPodLine, backendsAt, backlogEnd, bandOf, byClients, byNode, calibrationOf, cellsTable, checkRun, cidrOverlap, cidrRange, cyclesOf, deletionOf, deletionsOf, drainBand, dropOf, emptyOf, factsOf, failuresOf, goDuration, intakeOf, isKubeProxyMode, isTunnelState, judge, judgeKind, kernelCounts, kindCellRecordSchema, kindCellRecordV1Schema, kindConfig, kubeProxyPatch, medianInterval, medianText, middle, nodeNames, observationAfter, observationEnd, outcomesOf, overshootBand, periodOf, podsAt, podsOf, predictionText, propagationOf, propagationSource, quantileOf, readRecord, recordsOf, referenceOf, requestBand, requestsOf, restartOf, restartsAt, reusesReset, rulesOf, scenario, scenarioProblems, seconds, secondsOf, sessionsAt, showBand, signalOf, signalsOf, sliceDropOf, sliceEmptyOf, sliceReadyAt, sliceReadyOf, slicesOf, socketsOf, stoppingOf, timeSpread, transitionOf, tunnelsOf, unitOf, updatesOf, upgrade, upgradeCell, zoneOf, ztunnelPodsOf, ztunnelReplaced };
1015
1355
  //# sourceMappingURL=index.d.ts.map