1
0
Fork 0
mirror of https://git.sr.ht/~goorzhel/turboprop synced 2024-12-15 17:50:52 +00:00
turboprop/lib/flake-builders.nix
Antonio Gurgel 1444cb9b18 s/release/service/g
"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.
2023-11-24 17:35:15 -08:00

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;
};
}