mirror of
https://git.sr.ht/~goorzhel/turboprop
synced 2024-12-15 17:50:52 +00:00
1444cb9b18
"Helm releases" is what I'd been terming individual services, but it makes no sense outside of the internal context of the Helm builder. I also didn't want to call them "apps", however shorter that term is. These are not apps.
112 lines
3.8 KiB
Nix
112 lines
3.8 KiB
Nix
{
|
|
charts,
|
|
lib,
|
|
pkgs,
|
|
...
|
|
}: let
|
|
mapAttrs = builtins.mapAttrs;
|
|
in {
|
|
# The first two builders take bi-level attrsets generated by `./rake.nix`.
|
|
# Each leaf of the input attrset represents an unbuilt derivation,
|
|
# its type being:
|
|
# - for chart data, `{repo, chart, version, hash}`, or
|
|
# - for service data: `{lib} -> {builder, args, extraObjects}`.
|
|
# In other words, these builders transform these:
|
|
# - repos.bjw-s.app-template = {repo, chart, version, hash}
|
|
# - serviceData.svc.breezewiki = {lib}: {builder, args, extraObjects}
|
|
# into:
|
|
# - charts.bjw-s.app-template = <derivation>
|
|
# - services.svc.breezewiki = {out = <derivation>; extra = <derivation> (or null);}
|
|
|
|
# I considered giving chart modules the same signature as service ones,
|
|
# so that I could use one builder for both attrsets, but I decided against
|
|
# it. The vast majority of my services are available in a Helm repo;
|
|
# gitChart and remoteYAMLFile calls, by comparison, are rare.
|
|
charts =
|
|
mapAttrs
|
|
(reponame: charts:
|
|
mapAttrs
|
|
(chartname: chartspec: lib.fetchers.helmChart chartspec)
|
|
charts);
|
|
|
|
services = serviceData: clusterData:
|
|
mapAttrs
|
|
(namespace: services:
|
|
mapAttrs
|
|
(name: module: (
|
|
let
|
|
service = module {inherit charts lib pkgs;};
|
|
in {
|
|
out = service.builder (service.args
|
|
// {
|
|
# By injecting `name` and `namespace` here, I remove
|
|
# the need to specify it in every service in the flake;
|
|
# the directory structure can speak for me instead.
|
|
inherit name namespace;
|
|
|
|
# Values understood by lib.builders.helmChart
|
|
# and ignored by the rest.
|
|
inherit (clusterData) kubeVersion apiVersions;
|
|
});
|
|
|
|
extra =
|
|
if service ? extraObjects
|
|
then
|
|
lib.builders.yamlStream {
|
|
inherit name namespace;
|
|
objs = service.extraObjects;
|
|
}
|
|
else null;
|
|
}
|
|
))
|
|
services)
|
|
serviceData;
|
|
|
|
# Transforms an service tree keyed by root directory:
|
|
# {services = {svc = {...}; ...}; system = {};}
|
|
# into a list of strings mapping target paths to derivations:
|
|
# ["services/svc/calibre/SERVICE.yaml:$derivation_path" ... ]
|
|
# I have no idea how I'm going to walk future-me through this function,
|
|
# but here's an attempt:
|
|
paths = trees:
|
|
with builtins;
|
|
with pkgs.lib;
|
|
lists.flatten
|
|
(attrValues
|
|
# I key `trees` by root dir (e.g.: "services") because the service trees
|
|
# don't know the name of their own root. But the output needs to be a list,
|
|
# so I lop the `services =` part off with `attrValues`.
|
|
(mapAttrs
|
|
(
|
|
root: tree:
|
|
# root=="services"; tree=={svc={breezewiki={...};};
|
|
attrsets.mapAttrsToList
|
|
(
|
|
namespace: names:
|
|
# (attrNames names)==["breezewiki" ...];
|
|
map
|
|
(name: let
|
|
servicePath = "${root}/${namespace}/${name}";
|
|
service = getAttr name (getAttr namespace tree);
|
|
pathPair = ["${servicePath}/SERVICE.yaml:${service.out.outPath}"];
|
|
in
|
|
if service.extra != null
|
|
then [pathPair "${servicePath}/EXTRA.yaml:${service.extra.outPath}"]
|
|
else [pathPair])
|
|
(attrNames names)
|
|
)
|
|
tree
|
|
)
|
|
trees));
|
|
|
|
# This builder's signature is:
|
|
# [attrsets] -> <derivation>
|
|
# Each attrset is a Kubernetes object.
|
|
# The output is a YAML stream of rendered namespaces.
|
|
namespaces = objs:
|
|
lib.builders.yamlStream {
|
|
name = "namespaces";
|
|
namespace = "CLUSTER"; # ignored in `kubectl create`
|
|
inherit objs;
|
|
};
|
|
}
|