|  | package kubernetes | 
|  |  | 
|  | import ( | 
|  | "context" | 
|  | "fmt" | 
|  | "net" | 
|  |  | 
|  | "source.monogon.dev/go/net/tinylb" | 
|  | "source.monogon.dev/metropolis/node" | 
|  | ipb "source.monogon.dev/metropolis/node/core/curator/proto/api" | 
|  | "source.monogon.dev/metropolis/pkg/event/memory" | 
|  | ) | 
|  |  | 
|  | // updateLoadBalancerAPIServers provides a tinylb BackendSet memory value with | 
|  | // the currently known nodes running a Kubernetes apiserver as retrieved from the | 
|  | // given curator client. | 
|  | func updateLoadbalancerAPIServers(ctx context.Context, val *memory.Value[tinylb.BackendSet], cur ipb.CuratorClient) error { | 
|  | w, err := cur.Watch(ctx, &ipb.WatchRequest{ | 
|  | Kind: &ipb.WatchRequest_NodesInCluster_{ | 
|  | NodesInCluster: &ipb.WatchRequest_NodesInCluster{}, | 
|  | }, | 
|  | }) | 
|  | if err != nil { | 
|  | return fmt.Errorf("watch failed: %w", err) | 
|  | } | 
|  | defer w.CloseSend() | 
|  |  | 
|  | set := &tinylb.BackendSet{} | 
|  | val.Set(set.Clone()) | 
|  | for { | 
|  | ev, err := w.Recv() | 
|  | if err != nil { | 
|  | return fmt.Errorf("receive failed: %w", err) | 
|  | } | 
|  |  | 
|  | for _, n := range ev.Nodes { | 
|  | if n.Status == nil || n.Status.ExternalAddress == "" { | 
|  | set.Delete(n.Id) | 
|  | continue | 
|  | } | 
|  | if n.Roles.KubernetesController == nil { | 
|  | set.Delete(n.Id) | 
|  | continue | 
|  | } | 
|  | set.Insert(n.Id, &tinylb.SimpleTCPBackend{Remote: net.JoinHostPort(n.Status.ExternalAddress, node.KubernetesAPIPort.PortString())}) | 
|  | } | 
|  | for _, t := range ev.NodeTombstones { | 
|  | set.Delete(t.NodeId) | 
|  | } | 
|  | val.Set(set.Clone()) | 
|  | } | 
|  | } |