2023-01-20 07:53:01 +01:00
|
|
|
{ lib }:
|
|
|
|
rec {
|
|
|
|
# checks if given listener configuration has type as a resource
|
|
|
|
isListenerType = type: l: lib.any (r: lib.any (n: n == type) r.names) l.resources;
|
|
|
|
# Get the first listener that includes the given resource from worker
|
|
|
|
firstListenerOfType = type: ls: lib.lists.findFirst (isListenerType type)
|
2024-01-27 07:33:47 +01:00
|
|
|
(throw "No listener with resource: ${type} configured")
|
2023-01-20 07:53:01 +01:00
|
|
|
ls;
|
|
|
|
# Get an attrset of the host and port from a listener
|
|
|
|
connectionInfo = l: {
|
|
|
|
host = lib.head l.bind_addresses;
|
|
|
|
port = l.port;
|
|
|
|
};
|
|
|
|
|
|
|
|
# Get an attrset of the host and port from a worker given a type
|
|
|
|
workerConnectionResource = r: w: let
|
|
|
|
l = firstListenerOfType r w.settings.worker_listeners;
|
|
|
|
in connectionInfo l;
|
|
|
|
|
2023-12-23 20:31:45 +01:00
|
|
|
mapWorkersToUpstreamsByType = workerInstances:
|
|
|
|
lib.pipe workerInstances [
|
|
|
|
lib.attrValues
|
|
|
|
|
|
|
|
# Index by worker type
|
|
|
|
(lib.foldl (acc: worker: acc // {
|
|
|
|
${worker.type} = (acc.${worker.type} or [ ]) ++ [ worker ];
|
|
|
|
}) { })
|
|
|
|
|
|
|
|
# Subindex by resource names, listener types, and convert to upstreams
|
|
|
|
(lib.mapAttrs (_: workers: lib.pipe workers [
|
|
|
|
(lib.concatMap (worker: worker.settings.worker_listeners))
|
2024-03-13 06:22:24 +01:00
|
|
|
lib.lists.head # only select one listener for the worker to avoid cache thrashing
|
2023-12-23 20:31:45 +01:00
|
|
|
lib.flatten
|
|
|
|
mapListenersToUpstreamsByType
|
|
|
|
]))
|
|
|
|
];
|
|
|
|
|
|
|
|
mapListenersToUpstreamsByType = listenerInstances:
|
|
|
|
lib.pipe listenerInstances [
|
|
|
|
# Index by resource names
|
|
|
|
(lib.concatMap (listener: lib.pipe listener [
|
|
|
|
(listener: let
|
|
|
|
allResourceNames = lib.pipe listener.resources [
|
|
|
|
(map (resource: resource.names))
|
|
|
|
lib.flatten
|
|
|
|
lib.unique
|
|
|
|
];
|
|
|
|
in if allResourceNames == [ ]
|
|
|
|
then { "empty" = listener; }
|
|
|
|
else lib.genAttrs allResourceNames (_: listener))
|
|
|
|
lib.attrsToList
|
|
|
|
]))
|
|
|
|
|
|
|
|
(lib.foldl (acc: listener: acc // {
|
|
|
|
${listener.name} = (acc.${listener.name} or [ ]) ++ [ listener.value ];
|
|
|
|
}) { })
|
|
|
|
|
|
|
|
# Index by listener type
|
|
|
|
(lib.mapAttrs (_:
|
|
|
|
(lib.foldl (acc: listener: acc // {
|
|
|
|
${listener.type} = (acc.${listener.type} or [ ]) ++ [ listener ];
|
|
|
|
}) { })
|
|
|
|
))
|
|
|
|
|
|
|
|
# Convert listeners to upstream URIs
|
|
|
|
(lib.mapAttrs (_:
|
|
|
|
(lib.mapAttrs (_: listeners:
|
|
|
|
lib.pipe listeners [
|
|
|
|
(lib.concatMap (listener:
|
|
|
|
if listener.path != null
|
|
|
|
then [ "unix:${listener.path}" ]
|
|
|
|
else (map (addr: "${addr}:${toString listener.port}") listener.bind_addresses)
|
|
|
|
))
|
|
|
|
# NOTE: Adding ` = { }` to every upstream might seem unnecessary in isolation,
|
|
|
|
# but it makes it easier to set upstreams in the nginx module.
|
|
|
|
(uris: lib.genAttrs uris (_: { }))
|
|
|
|
]
|
|
|
|
))
|
|
|
|
))
|
|
|
|
];
|
2023-01-20 07:53:01 +01:00
|
|
|
}
|