1
0
Fork 0
mirror of https://git.sr.ht/~goorzhel/turboprop synced 2024-12-15 17:50:52 +00:00

Re-implement service-builder

`apiVersions` gave me a headache while writing the foldl so I made it
a separate input.

Now the service modules have this signature, without my having to
change any code in the modules themselves:

{charts, etc, ...} -> [apiVersion] -> {out, extra}
This commit is contained in:
Antonio Gurgel 2023-12-03 19:53:14 -08:00
parent 6b97777fe9
commit 97dbdec7f7
5 changed files with 106 additions and 53 deletions

View file

@ -36,15 +36,9 @@
in { in {
packages = { packages = {
inherit charts lib; inherit charts lib;
default = { default = user:
# TODO: move to default.nix
charts ? charts,
lib ? lib,
pkgs ? pkgs,
user ? {},
}:
import ./src { import ./src {
inherit charts lib pkgs user; inherit charts haumea lib pkgs user;
}; };
}; };
# TODO: make a template # TODO: make a template

View file

@ -38,6 +38,10 @@ in rec {
# Some charts lack diligence in setting `Release.Namespace` # Some charts lack diligence in setting `Release.Namespace`
# on the objects they create, necessitating a round-trip through # on the objects they create, necessitating a round-trip through
# yamlStream, which sets namespaces on all objects lacking one. # yamlStream, which sets namespaces on all objects lacking one.
# BUG: However, this creates a derivation with no knowledge of
# the Helm chart derivation that is its input, which would be
# useful to debug with.
in in
yamlStream {inherit name namespace objs;}; yamlStream {inherit name namespace objs;};

View file

@ -11,6 +11,13 @@
parseYAMLsFile = p: kubelib.fromYAML (builtins.readFile p); parseYAMLsFile = p: kubelib.fromYAML (builtins.readFile p);
parseYAMLFile = p: builtins.head (parseYAMLsFile p); parseYAMLFile = p: builtins.head (parseYAMLsFile p);
liftDefault = _: mod:
# h.lib.transformers.liftDefault uses pkgs.lib.attrsets.unionOfDisjoint,
# which fails here because mod.default is a function, not a set.
if mod ? default
then mod.default
else mod;
# Helm cannot see my cluster from within the sandbox, so it cannot # Helm cannot see my cluster from within the sandbox, so it cannot
# infer capabilities from it. Therefore, API versions must be gathered # infer capabilities from it. Therefore, API versions must be gathered
# from charts that provide them. # from charts that provide them.
@ -60,15 +67,39 @@
# and remove this transformer # and remove this transformer
}; };
mkStages = map (src: mkSvcTrees = src:
haumea.lib.load { haumea.lib.load {
inherit src; inherit src;
loader = haumea.lib.loaders.verbatim; loader = haumea.lib.loaders.verbatim;
transformer = _: mod: transformer = liftDefault;
# transformers.liftDefault uses pkgs.lib.attrsets.unionOfDisjoint, };
# which fails here because mod.default is a function, not a set.
if mod ? default # Borrowed from divnix/digga, with minor modifications:
then mod.default # https://github.com/divnix/digga/blob/baa54f8/src/importers.nix#L2-L59
else mod; flattenTree = tree: let
}); op = sum: path: val: let
pathStr = builtins.concatStringsSep "/" path;
in
if builtins.isFunction val
then
# builtins.trace "${toString val} is a path"
(sum
// {
"${pathStr}" = val;
})
else if builtins.isAttrs val
then
# builtins.trace "${builtins.toJSON val} is an attrset"
(recurse sum path val)
else
# builtins.trace "${toString path} is something else"
sum; # ignore val
recurse = sum: path: val:
builtins.foldl'
(sum: key: op sum (path ++ [key]) val.${key})
sum
(builtins.attrNames val);
in
recurse {} [] tree;
} }

View file

@ -1,20 +1,40 @@
{ {
charts, charts,
haumea,
lib, lib,
pkgs, pkgs,
user ? {}, user ? {},
}: let }: let
mkNamespace = name: extraMetadata: {
};
flakeBuilders = (import ./flake-builders.nix) {inherit charts lib pkgs user;}; flakeBuilders = (import ./flake-builders.nix) {inherit charts lib pkgs user;};
buildServices = roots: kubeVersion: {};
in { in {
inherit flakeBuilders; # TODO: remove after debugging inherit flakeBuilders; # TODO: remove after debugging
inherit (lib) mkCharts; inherit (lib) mkCharts;
mkServices = src: kubeVersion: let
modules = haumea.lib.load {
inherit src;
inputs = {inherit charts lib pkgs user kubeVersion;};
loader = flakeBuilders.serviceLoader;
transformer = lib.liftDefault;
};
folder = acc: path: mod: let
module = mod acc.apis;
outPath = "${module.srcPath}/SERVICE.yaml:${module.out.outPath}";
outPaths =
if module ? extra
then [outPath "${module.srcPath}/EXTRA.yaml:${module.extra.outPath}"]
else [outPath];
in {
apis = acc.apis ++ (lib.gatherApis module.out.outPath);
paths = acc.paths ++ outPaths;
};
in
pkgs.lib.attrsets.foldlAttrs
folder
{ apis = []; paths = []; }
(lib.flattenTree modules);
mkNamespaces = { mkNamespaces = {
roots, roots,
extraMetadata ? {}, extraMetadata ? {},
@ -48,15 +68,11 @@ in {
namespaceData, namespaceData,
kubeVersion, kubeVersion,
src, src,
}: let }:
builtServices = buildServices serviceData kubeVersion;
in
pkgs.stdenv.mkDerivation { pkgs.stdenv.mkDerivation {
inherit pname version src; inherit pname version src;
derivation_paths = flakeBuilders.paths { derivation_paths = []; # TODO
services = builtServices; namespace_drv = []; # TODO:
};
namespace_drv = flakeBuilders.namespaces namespaceData;
phases = ["installPhase"]; phases = ["installPhase"];
installPhase = builtins.readFile ./src/output.sh; installPhase = builtins.readFile ./src/output.sh;

View file

@ -10,32 +10,40 @@
mapAttrs = builtins.mapAttrs; mapAttrs = builtins.mapAttrs;
in { in {
serviceLoader = { serviceLoader = {
inputs, # {charts, lib, pkgs, user, kubeVersion, apiVersions} charts,
lib,
pkgs,
user,
kubeVersion,
... ...
}: p: let } @ inputs: p: let
module = import p inputs; module = import p inputs;
name = builtins.baseNameOf p; # p is `.../${ns}/${name}/default.nix`
namespace = builtins.baseNameOf (builtins.dirOf p); name = with builtins; baseNameOf (dirOf p);
in { namespace = with builtins; baseNameOf (dirOf (dirOf p));
out = module.builder (module.args in
// { apiVersions: {
# By injecting `name` and `namespace` here, I remove out = module.builder (module.args
# the need to specify it in every service in the flake; // {
# the directory structure can speak for me instead. # By injecting `name` and `namespace` here, I remove
inherit name namespace; # the need to specify it in every service in the flake;
# the directory structure can speak for me instead.
# Values understood by lib.builders.helmChart
# and ignored by the rest.
inherit (inputs) kubeVersion apiVersions;
});
extra =
if module ? extraObjects
then
lib.builders.yamlStream {
inherit name namespace; inherit name namespace;
objs = module.extraObjects;
} # Values understood by lib.builders.helmChart
else null; # and ignored by the rest.
}; inherit (inputs) kubeVersion;
});
extra =
if module ? extraObjects
then
lib.builders.yamlStream {
inherit name namespace;
objs = module.extraObjects;
}
else null;
srcPath = builtins.dirOf p;
};
} }