mirror of
https://git.sr.ht/~goorzhel/turboprop
synced 2024-12-14 11:37:37 +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:
parent
6b97777fe9
commit
97dbdec7f7
5 changed files with 106 additions and 53 deletions
10
flake.nix
10
flake.nix
|
@ -36,15 +36,9 @@
|
|||
in {
|
||||
packages = {
|
||||
inherit charts lib;
|
||||
default = {
|
||||
# TODO: move to default.nix
|
||||
charts ? charts,
|
||||
lib ? lib,
|
||||
pkgs ? pkgs,
|
||||
user ? {},
|
||||
}:
|
||||
default = user:
|
||||
import ./src {
|
||||
inherit charts lib pkgs user;
|
||||
inherit charts haumea lib pkgs user;
|
||||
};
|
||||
};
|
||||
# TODO: make a template
|
||||
|
|
|
@ -38,6 +38,10 @@ in rec {
|
|||
# Some charts lack diligence in setting `Release.Namespace`
|
||||
# on the objects they create, necessitating a round-trip through
|
||||
# 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
|
||||
yamlStream {inherit name namespace objs;};
|
||||
|
||||
|
|
|
@ -11,6 +11,13 @@
|
|||
parseYAMLsFile = p: kubelib.fromYAML (builtins.readFile 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
|
||||
# infer capabilities from it. Therefore, API versions must be gathered
|
||||
# from charts that provide them.
|
||||
|
@ -60,15 +67,39 @@
|
|||
# and remove this transformer
|
||||
};
|
||||
|
||||
mkStages = map (src:
|
||||
mkSvcTrees = src:
|
||||
haumea.lib.load {
|
||||
inherit src;
|
||||
loader = haumea.lib.loaders.verbatim;
|
||||
transformer = _: mod:
|
||||
# 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;
|
||||
});
|
||||
transformer = liftDefault;
|
||||
};
|
||||
|
||||
# Borrowed from divnix/digga, with minor modifications:
|
||||
# https://github.com/divnix/digga/blob/baa54f8/src/importers.nix#L2-L59
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -1,20 +1,40 @@
|
|||
{
|
||||
charts,
|
||||
haumea,
|
||||
lib,
|
||||
pkgs,
|
||||
user ? {},
|
||||
}: let
|
||||
mkNamespace = name: extraMetadata: {
|
||||
};
|
||||
|
||||
flakeBuilders = (import ./flake-builders.nix) {inherit charts lib pkgs user;};
|
||||
|
||||
buildServices = roots: kubeVersion: {};
|
||||
in {
|
||||
inherit flakeBuilders; # TODO: remove after debugging
|
||||
|
||||
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 = {
|
||||
roots,
|
||||
extraMetadata ? {},
|
||||
|
@ -48,15 +68,11 @@ in {
|
|||
namespaceData,
|
||||
kubeVersion,
|
||||
src,
|
||||
}: let
|
||||
builtServices = buildServices serviceData kubeVersion;
|
||||
in
|
||||
}:
|
||||
pkgs.stdenv.mkDerivation {
|
||||
inherit pname version src;
|
||||
derivation_paths = flakeBuilders.paths {
|
||||
services = builtServices;
|
||||
};
|
||||
namespace_drv = flakeBuilders.namespaces namespaceData;
|
||||
derivation_paths = []; # TODO
|
||||
namespace_drv = []; # TODO:
|
||||
|
||||
phases = ["installPhase"];
|
||||
installPhase = builtins.readFile ./src/output.sh;
|
||||
|
|
|
@ -10,32 +10,40 @@
|
|||
mapAttrs = builtins.mapAttrs;
|
||||
in {
|
||||
serviceLoader = {
|
||||
inputs, # {charts, lib, pkgs, user, kubeVersion, apiVersions}
|
||||
charts,
|
||||
lib,
|
||||
pkgs,
|
||||
user,
|
||||
kubeVersion,
|
||||
...
|
||||
}: p: let
|
||||
} @ inputs: p: let
|
||||
module = import p inputs;
|
||||
name = builtins.baseNameOf p;
|
||||
namespace = builtins.baseNameOf (builtins.dirOf p);
|
||||
in {
|
||||
out = module.builder (module.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 (inputs) kubeVersion apiVersions;
|
||||
});
|
||||
|
||||
extra =
|
||||
if module ? extraObjects
|
||||
then
|
||||
lib.builders.yamlStream {
|
||||
# p is `.../${ns}/${name}/default.nix`
|
||||
name = with builtins; baseNameOf (dirOf p);
|
||||
namespace = with builtins; baseNameOf (dirOf (dirOf p));
|
||||
in
|
||||
apiVersions: {
|
||||
out = module.builder (module.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;
|
||||
objs = module.extraObjects;
|
||||
}
|
||||
else null;
|
||||
};
|
||||
|
||||
# Values understood by lib.builders.helmChart
|
||||
# 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;
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue