mirror of
https://github.com/TECHNOFAB11/kubenix.git
synced 2025-12-12 16:10:05 +01:00
switch formatting to nixpkgs-fmt
This commit is contained in:
parent
3598716c73
commit
2712e89716
65 changed files with 4839 additions and 5222 deletions
1
.vscode/extensions.json
vendored
1
.vscode/extensions.json
vendored
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"jnoortheen.nix-ide",
|
||||
"mkhl.direnv"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"git.detectSubmodules": false,
|
||||
"nix.formatterPath": "alejandra",
|
||||
"nix.enableLanguageServer": true,
|
||||
"search.exclude": {
|
||||
"docs/themes": true
|
||||
}
|
||||
|
|
|
|||
15
default.nix
15
default.nix
|
|
@ -1,14 +1,13 @@
|
|||
(
|
||||
import
|
||||
(
|
||||
let
|
||||
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
|
||||
in
|
||||
(
|
||||
let
|
||||
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
|
||||
in
|
||||
fetchTarball {
|
||||
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
|
||||
sha256 = lock.nodes.flake-compat.locked.narHash;
|
||||
}
|
||||
)
|
||||
{src = ./.;}
|
||||
)
|
||||
.defaultNix
|
||||
)
|
||||
{ src = ./.; }
|
||||
).defaultNix
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
deployment = import ./deployment {};
|
||||
testing = import ./testing {};
|
||||
deployment = import ./deployment { };
|
||||
testing = import ./testing { };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
{kubenix ? import ../../../..}:
|
||||
{ kubenix ? import ../../../.. }:
|
||||
kubenix.evalModules.${builtins.currentSystem} {
|
||||
module = {kubenix, ...}: {
|
||||
module = { kubenix, ... }: {
|
||||
# instead of defining everything inline, let's import it
|
||||
imports = [./module.nix];
|
||||
imports = [ ./module.nix ];
|
||||
|
||||
# annotate the generated resources with a project name
|
||||
kubenix.project = "example";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{kubenix, ...}: {
|
||||
imports = [kubenix.modules.k8s];
|
||||
{ kubenix, ... }: {
|
||||
imports = [ kubenix.modules.k8s ];
|
||||
|
||||
kubernetes.resources = {
|
||||
deployments.nginx.spec = {
|
||||
|
|
@ -50,12 +50,10 @@
|
|||
|
||||
services.nginx.spec = {
|
||||
selector.app = "nginx";
|
||||
ports = [
|
||||
{
|
||||
name = "http";
|
||||
port = 80;
|
||||
}
|
||||
];
|
||||
ports = [{
|
||||
name = "http";
|
||||
port = 80;
|
||||
}];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{kubenix ? import ../../../..}:
|
||||
{ kubenix ? import ../../../.. }:
|
||||
kubenix.evalModules.${builtins.currentSystem} {
|
||||
module = {kubenix, ...}: {
|
||||
imports = [kubenix.modules.helm];
|
||||
module = { kubenix, ... }: {
|
||||
imports = [ kubenix.modules.helm ];
|
||||
kubernetes.helm.releases.example = {
|
||||
chart = kubenix.lib.helm.fetch {
|
||||
repo = "https://charts.bitnami.com/bitnami";
|
||||
|
|
|
|||
|
|
@ -1,15 +1,10 @@
|
|||
{kubenix ? import ../../../..}:
|
||||
{ kubenix ? import ../../../.. }:
|
||||
kubenix.evalModules.${builtins.currentSystem} {
|
||||
module = {
|
||||
kubenix,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
imports = with kubenix.modules; [k8s docker];
|
||||
module = { kubenix, config, pkgs, ... }: {
|
||||
imports = with kubenix.modules; [ k8s docker ];
|
||||
docker = {
|
||||
registry.url = "docker.somewhere.io";
|
||||
images.example.image = pkgs.callPackage ./image.nix {};
|
||||
images.example.image = pkgs.callPackage ./image.nix { };
|
||||
};
|
||||
kubernetes.resources.pods.example.spec.containers = {
|
||||
custom.image = config.docker.images.example.path;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
{
|
||||
dockerTools,
|
||||
nginx,
|
||||
}:
|
||||
{ dockerTools, nginx }:
|
||||
dockerTools.buildLayeredImage {
|
||||
name = "nginx";
|
||||
contents = [nginx];
|
||||
contents = [ nginx ];
|
||||
extraCommands = ''
|
||||
mkdir -p etc
|
||||
chmod u+w etc
|
||||
|
|
@ -12,9 +9,9 @@ dockerTools.buildLayeredImage {
|
|||
echo "nginx:x:1000:nginx" > etc/group
|
||||
'';
|
||||
config = {
|
||||
Cmd = ["nginx" "-c" "/etc/nginx/nginx.conf"];
|
||||
Cmd = [ "nginx" "-c" "/etc/nginx/nginx.conf" ];
|
||||
ExposedPorts = {
|
||||
"80/tcp" = {};
|
||||
"80/tcp" = { };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{kubenix ? import ../../../..}:
|
||||
{ kubenix ? import ../../../.. }:
|
||||
kubenix.evalModules.${builtins.currentSystem} {
|
||||
module = {kubenix, ...}: {
|
||||
imports = [./module.nix];
|
||||
module = { kubenix, ... }: {
|
||||
imports = [ ./module.nix ];
|
||||
|
||||
kubenix.project = "multi-namespace-example";
|
||||
kubernetes.version = "1.24";
|
||||
|
|
|
|||
|
|
@ -1,11 +1,5 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
kubenix,
|
||||
...
|
||||
}: {
|
||||
imports = with kubenix.modules; [submodules k8s];
|
||||
{ config, lib, pkgs, kubenix, ... }: {
|
||||
imports = with kubenix.modules; [ submodules k8s ];
|
||||
|
||||
# Import submodule.
|
||||
submodules.imports = [
|
||||
|
|
@ -26,12 +20,10 @@
|
|||
# Now we can set the args options defined in the submodule.
|
||||
args.kubernetes.resources = {
|
||||
services.nginx.spec = {
|
||||
ports = [
|
||||
{
|
||||
name = "http";
|
||||
port = 80;
|
||||
}
|
||||
];
|
||||
ports = [{
|
||||
name = "http";
|
||||
port = 80;
|
||||
}];
|
||||
selector.app = "nginx";
|
||||
};
|
||||
};
|
||||
|
|
@ -41,12 +33,10 @@
|
|||
submodule = "namespaced";
|
||||
args.kubernetes.resources = {
|
||||
services.nginx.spec = {
|
||||
ports = [
|
||||
{
|
||||
name = "https";
|
||||
port = 443;
|
||||
}
|
||||
];
|
||||
ports = [{
|
||||
name = "https";
|
||||
port = 443;
|
||||
}];
|
||||
selector.app = "nginx";
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
{
|
||||
config,
|
||||
kubenix,
|
||||
lib,
|
||||
# Name of submodule instance.
|
||||
name,
|
||||
# This is a shorthand for config.submodule.args and contains
|
||||
{ config
|
||||
, kubenix
|
||||
, lib
|
||||
, # Name of submodule instance.
|
||||
name
|
||||
, # This is a shorthand for config.submodule.args and contains
|
||||
# final values of the args options.
|
||||
args,
|
||||
...
|
||||
args
|
||||
, ...
|
||||
}: {
|
||||
imports = with kubenix.modules; [
|
||||
# This needs to be imported in order to define a submodule.
|
||||
|
|
@ -25,7 +24,7 @@
|
|||
# to set kubernetes options from the k8s module which are already
|
||||
# precisely typed.
|
||||
type = lib.types.attrs;
|
||||
default = {};
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -54,9 +53,9 @@
|
|||
|
||||
kubernetes = lib.mkMerge [
|
||||
# Use instance name as namespace
|
||||
{namespace = name;}
|
||||
{ namespace = name; }
|
||||
# Create namespace object
|
||||
{resources.namespaces.${name} = {};}
|
||||
{ resources.namespaces.${name} = { }; }
|
||||
# All resources defined here will use the above namespace
|
||||
args.kubernetes
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
# let's creata a function whose only input is the kubenix package
|
||||
{kubenix ? import ../../../..}:
|
||||
{ kubenix ? import ../../../.. }:
|
||||
# evalModules is our main entrypoint
|
||||
kubenix.evalModules.${builtins.currentSystem} {
|
||||
# to it, we pass a module that accepts a (different) kubenix object
|
||||
module = {kubenix, ...}: {
|
||||
module = { kubenix, ... }: {
|
||||
# in order to define options, we need to import their definitions
|
||||
imports = [kubenix.modules.k8s];
|
||||
imports = [ kubenix.modules.k8s ];
|
||||
# now we have full access to define Kubernetes resources
|
||||
kubernetes.resources.pods = {
|
||||
# "example" is the name of our pod
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{kubenix ? import ../../../..}:
|
||||
{ kubenix ? import ../../../.. }:
|
||||
kubenix.evalModules.${builtins.currentSystem} {
|
||||
module = {kubenix, ...}: {
|
||||
imports = [kubenix.modules.k8s];
|
||||
module = { kubenix, ... }: {
|
||||
imports = [ kubenix.modules.k8s ];
|
||||
kubernetes.resources.secrets.example.stringData = {
|
||||
password = "ref+file:///path/to/secret";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,17 +1,15 @@
|
|||
{kubenix ? import ../../../..}:
|
||||
{ kubenix ? import ../../../.. }:
|
||||
kubenix.evalModules.x86_64-linux {
|
||||
module = {kubenix, ...}: {
|
||||
imports = [kubenix.modules.testing];
|
||||
module = { kubenix, ... }: {
|
||||
imports = [ kubenix.modules.testing ];
|
||||
testing = {
|
||||
tests = [./test.nix];
|
||||
common = [
|
||||
{
|
||||
features = ["k8s"];
|
||||
options = {
|
||||
kubernetes.version = "1.24";
|
||||
};
|
||||
}
|
||||
];
|
||||
tests = [ ./test.nix ];
|
||||
common = [{
|
||||
features = [ "k8s" ];
|
||||
options = {
|
||||
kubernetes.version = "1.24";
|
||||
};
|
||||
}];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
{
|
||||
kubenix,
|
||||
test,
|
||||
...
|
||||
}: {
|
||||
imports = [kubenix.modules.test];
|
||||
{ kubenix, test, ... }: {
|
||||
imports = [ kubenix.modules.test ];
|
||||
|
||||
test = {
|
||||
name = "example";
|
||||
|
|
|
|||
135
docs/default.nix
135
docs/default.nix
|
|
@ -1,14 +1,10 @@
|
|||
# adapted from: https://discourse.nixos.org/t/franken-script-to-generate-nixos-options-docs-with-custom-modules/1674/4
|
||||
{
|
||||
pkgs,
|
||||
options,
|
||||
}: let
|
||||
extraSources = [];
|
||||
{ pkgs, options }:
|
||||
let
|
||||
extraSources = [ ];
|
||||
lib = pkgs.lib;
|
||||
|
||||
optionsListVisible =
|
||||
lib.filter (opt: opt.visible && !opt.internal)
|
||||
(lib.optionAttrSetToDocList options);
|
||||
optionsListVisible = lib.filter (opt: opt.visible && !opt.internal) (lib.optionAttrSetToDocList options);
|
||||
|
||||
# Replace functions by the string <function>
|
||||
substFunction = x:
|
||||
|
|
@ -24,78 +20,75 @@
|
|||
|
||||
isPath = x: (builtins.typeOf x) == "path";
|
||||
|
||||
optionsListDesc = lib.flip map optionsListVisible (
|
||||
opt:
|
||||
opt
|
||||
// {
|
||||
description = let
|
||||
optionsListDesc = lib.flip map optionsListVisible (opt:
|
||||
opt // {
|
||||
description =
|
||||
let
|
||||
attempt = builtins.tryEval opt.description;
|
||||
in
|
||||
if attempt.success
|
||||
then attempt.value
|
||||
else "N/A";
|
||||
declarations = map stripAnyPrefixes opt.declarations;
|
||||
}
|
||||
// lib.optionalAttrs (opt ? example) {
|
||||
example = substFunction opt.example;
|
||||
}
|
||||
// lib.optionalAttrs (opt ? default) {
|
||||
default = substFunction opt.default;
|
||||
}
|
||||
// lib.optionalAttrs (opt ? type) {
|
||||
type = substFunction opt.type;
|
||||
}
|
||||
// lib.optionalAttrs
|
||||
(opt ? relatedPackages && opt.relatedPackages != [])
|
||||
{
|
||||
relatedPackages = genRelatedPackages opt.relatedPackages;
|
||||
}
|
||||
if attempt.success
|
||||
then attempt.value
|
||||
else "N/A";
|
||||
declarations = map stripAnyPrefixes opt.declarations;
|
||||
} // lib.optionalAttrs (opt ? example) {
|
||||
example = substFunction opt.example;
|
||||
} // lib.optionalAttrs (opt ? default) {
|
||||
default = substFunction opt.default;
|
||||
} // lib.optionalAttrs (opt ? type) {
|
||||
type = substFunction opt.type;
|
||||
} // lib.optionalAttrs (opt ? relatedPackages && opt.relatedPackages != [ ]) {
|
||||
relatedPackages = genRelatedPackages opt.relatedPackages;
|
||||
}
|
||||
);
|
||||
|
||||
genRelatedPackages = packages: let
|
||||
unpack = p:
|
||||
if lib.isString p
|
||||
then {name = p;}
|
||||
else if lib.isList p
|
||||
then {path = p;}
|
||||
else p;
|
||||
describe = args: let
|
||||
title = args.title or null;
|
||||
name = args.name or (lib.concatStringsSep "." args.path);
|
||||
path = args.path or [args.name];
|
||||
package =
|
||||
args.package
|
||||
or (lib.attrByPath path
|
||||
(throw
|
||||
"Invalid package attribute path '${toString path}'")
|
||||
pkgs);
|
||||
in
|
||||
"<listitem>"
|
||||
+ "<para><literal>${lib.optionalString (title != null)
|
||||
genRelatedPackages = packages:
|
||||
let
|
||||
unpack = p:
|
||||
if lib.isString p
|
||||
then { name = p; }
|
||||
else if lib.isList p
|
||||
then { path = p; }
|
||||
else p;
|
||||
describe = args:
|
||||
let
|
||||
title = args.title or null;
|
||||
name = args.name or (lib.concatStringsSep "." args.path);
|
||||
path = args.path or [ args.name ];
|
||||
package =
|
||||
args.package
|
||||
or (lib.attrByPath path
|
||||
(throw
|
||||
"Invalid package attribute path '${toString path}'")
|
||||
pkgs);
|
||||
in
|
||||
"<listitem>"
|
||||
+ "<para><literal>${lib.optionalString (title != null)
|
||||
"${title} aka "}pkgs.${name} (${package.meta.name})</literal>"
|
||||
+ lib.optionalString (!package.meta.available)
|
||||
" <emphasis>[UNAVAILABLE]</emphasis>"
|
||||
+ ": ${package.meta.description or "???"}.</para>"
|
||||
+ lib.optionalString (args ? comment)
|
||||
"\n<para>${args.comment}</para>"
|
||||
+ lib.optionalString (package.meta ? longDescription)
|
||||
"\n<programlisting>${package.meta.longDescription}"
|
||||
+ "</programlisting>"
|
||||
+ "</listitem>";
|
||||
in "<itemizedlist>${lib.concatStringsSep "\n" (map (p:
|
||||
+ lib.optionalString (!package.meta.available)
|
||||
" <emphasis>[UNAVAILABLE]</emphasis>"
|
||||
+ ": ${package.meta.description or "???"}.</para>"
|
||||
+ lib.optionalString (args ? comment)
|
||||
"\n<para>${args.comment}</para>"
|
||||
+ lib.optionalString (package.meta ? longDescription)
|
||||
"\n<programlisting>${package.meta.longDescription}"
|
||||
+ "</programlisting>"
|
||||
+ "</listitem>";
|
||||
in
|
||||
"<itemizedlist>${lib.concatStringsSep "\n" (map (p:
|
||||
describe (unpack p))
|
||||
packages)}</itemizedlist>";
|
||||
|
||||
optionLess = a: b: let
|
||||
ise = lib.hasPrefix "enable";
|
||||
isp = lib.hasPrefix "package";
|
||||
cmp =
|
||||
lib.splitByAndCompare ise lib.compare
|
||||
(lib.splitByAndCompare isp lib.compare lib.compare);
|
||||
in
|
||||
optionLess = a: b:
|
||||
let
|
||||
ise = lib.hasPrefix "enable";
|
||||
isp = lib.hasPrefix "package";
|
||||
cmp =
|
||||
lib.splitByAndCompare ise lib.compare
|
||||
(lib.splitByAndCompare isp lib.compare lib.compare);
|
||||
in
|
||||
lib.compareLists cmp a.loc b.loc < 0;
|
||||
|
||||
prefixesToStrip = map (p: "${toString p}/") ([../../..] ++ extraSources);
|
||||
prefixesToStrip = map (p: "${toString p}/") ([ ../../.. ] ++ extraSources);
|
||||
stripAnyPrefixes = lib.flip (lib.fold lib.removePrefix) prefixesToStrip;
|
||||
|
||||
###############################################################################
|
||||
|
|
@ -119,4 +112,4 @@
|
|||
})
|
||||
optionsList)));
|
||||
in
|
||||
pkgs.writeText "options.json" optionsJSON
|
||||
pkgs.writeText "options.json" optionsJSON
|
||||
|
|
|
|||
193
flake.nix
193
flake.nix
|
|
@ -11,57 +11,50 @@
|
|||
};
|
||||
};
|
||||
|
||||
outputs = inputs @ {self, ...}:
|
||||
(inputs.flake-utils.lib.eachDefaultSystem (
|
||||
system: let
|
||||
outputs = inputs @ { self, ... }:
|
||||
(inputs.flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
pkgs = import inputs.nixpkgs {
|
||||
inherit system;
|
||||
overlays = [self.overlays.default];
|
||||
overlays = [ self.overlays.default ];
|
||||
config.allowUnsupportedSystem = true;
|
||||
};
|
||||
|
||||
inherit (pkgs) lib;
|
||||
|
||||
kubenix = {
|
||||
lib = import ./lib {inherit lib pkgs;};
|
||||
lib = import ./lib { inherit lib pkgs; };
|
||||
evalModules = self.evalModules.${system};
|
||||
modules = self.nixosModules.kubenix;
|
||||
};
|
||||
|
||||
# evalModules with same interface as lib.evalModules and kubenix as
|
||||
# special argument
|
||||
evalModules = attrs @ {
|
||||
module ? null,
|
||||
modules ? [module],
|
||||
...
|
||||
}: let
|
||||
lib' = lib.extend (lib: _self: import ./lib/upstreamables.nix {inherit lib pkgs;});
|
||||
attrs' = builtins.removeAttrs attrs ["module"];
|
||||
in
|
||||
evalModules = attrs @ { module ? null, modules ? [ module ], ... }:
|
||||
let
|
||||
lib' = lib.extend (lib: _self: import ./lib/upstreamables.nix { inherit lib pkgs; });
|
||||
attrs' = builtins.removeAttrs attrs [ "module" ];
|
||||
in
|
||||
lib'.evalModules (lib.recursiveUpdate
|
||||
{
|
||||
modules =
|
||||
modules
|
||||
++ [
|
||||
{
|
||||
config._module.args = {
|
||||
inherit pkgs;
|
||||
name = "default";
|
||||
};
|
||||
}
|
||||
];
|
||||
modules = modules ++ [{
|
||||
config._module.args = {
|
||||
inherit pkgs;
|
||||
name = "default";
|
||||
};
|
||||
}];
|
||||
specialArgs = {
|
||||
inherit kubenix;
|
||||
inherit pkgs;
|
||||
};
|
||||
}
|
||||
attrs');
|
||||
in {
|
||||
in
|
||||
{
|
||||
inherit evalModules pkgs;
|
||||
|
||||
devShells.default = pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
# extra tools
|
||||
dive
|
||||
fd
|
||||
k9s
|
||||
|
|
@ -81,103 +74,93 @@
|
|||
'';
|
||||
};
|
||||
|
||||
formatter =
|
||||
(inputs.treefmt.lib.evalModule pkgs {
|
||||
projectRootFile = "flake.nix";
|
||||
programs = {
|
||||
alejandra.enable = true;
|
||||
black.enable = true;
|
||||
prettier.enable = true;
|
||||
shfmt.enable = true;
|
||||
};
|
||||
settings.global.excludes = [
|
||||
"docs/themes/*"
|
||||
"docs/layouts/*"
|
||||
"modules/generated/*"
|
||||
];
|
||||
})
|
||||
.config
|
||||
.build
|
||||
.wrapper;
|
||||
formatter = (inputs.treefmt.lib.evalModule pkgs {
|
||||
projectRootFile = "flake.nix";
|
||||
programs = {
|
||||
nixpkgs-fmt.enable = true;
|
||||
black.enable = true;
|
||||
prettier.enable = true;
|
||||
shfmt.enable = true;
|
||||
};
|
||||
settings.global.excludes = [
|
||||
"docs/themes/*"
|
||||
"docs/layouts/*"
|
||||
"modules/generated/*"
|
||||
];
|
||||
}).config.build.wrapper;
|
||||
|
||||
apps = {
|
||||
docs = {
|
||||
type = "app";
|
||||
program =
|
||||
(pkgs.writeShellScript "gen-docs" ''
|
||||
set -eo pipefail
|
||||
program = (pkgs.writeShellScript "gen-docs" ''
|
||||
set -eo pipefail
|
||||
|
||||
# generate json object of module options
|
||||
nix build '.#docs' -o ./docs/data/options.json
|
||||
# generate json object of module options
|
||||
nix build '.#docs' -o ./docs/data/options.json
|
||||
|
||||
# remove all old module pages
|
||||
rm ./docs/content/modules/[!_]?*.md || true
|
||||
# remove all old module pages
|
||||
rm ./docs/content/modules/[!_]?*.md || true
|
||||
|
||||
# create a page for each module in hugo
|
||||
for mod in ${builtins.toString (builtins.attrNames self.nixosModules.kubenix)}; do
|
||||
[[ $mod == "base" ]] && mod=kubenix
|
||||
[[ $mod == "k8s" ]] && mod=kubernetes
|
||||
[[ $mod == "submodule"* ]] && continue
|
||||
echo " {{< options >}}" > ./docs/content/modules/$mod.md
|
||||
done
|
||||
# create a page for each module in hugo
|
||||
for mod in ${builtins.toString (builtins.attrNames self.nixosModules.kubenix)}; do
|
||||
[[ $mod == "base" ]] && mod=kubenix
|
||||
[[ $mod == "k8s" ]] && mod=kubernetes
|
||||
[[ $mod == "submodule"* ]] && continue
|
||||
echo " {{< options >}}" > ./docs/content/modules/$mod.md
|
||||
done
|
||||
|
||||
# build the site
|
||||
cd docs && ${pkgs.hugo}/bin/hugo "$@"
|
||||
'')
|
||||
.outPath;
|
||||
# build the site
|
||||
cd docs && ${pkgs.hugo}/bin/hugo "$@"
|
||||
'').outPath;
|
||||
};
|
||||
|
||||
generate = {
|
||||
type = "app";
|
||||
program =
|
||||
(pkgs.writeShellScript "gen-modules" ''
|
||||
set -eo pipefail
|
||||
dir=./modules/generated
|
||||
program = (pkgs.writeShellScript "gen-modules" ''
|
||||
set -eo pipefail
|
||||
dir=./modules/generated
|
||||
|
||||
rm -rf $dir
|
||||
mkdir $dir
|
||||
nix build '.#generate-k8s'
|
||||
cp ./result/* $dir/
|
||||
rm -rf $dir
|
||||
mkdir $dir
|
||||
nix build '.#generate-k8s'
|
||||
cp ./result/* $dir/
|
||||
|
||||
rm result
|
||||
'')
|
||||
.outPath;
|
||||
rm result
|
||||
'').outPath;
|
||||
};
|
||||
};
|
||||
|
||||
packages =
|
||||
{
|
||||
inherit (pkgs) kubernetes kubectl;
|
||||
default = pkgs.callPackage ./pkgs/kubenix.nix {
|
||||
inherit (self.packages.${system});
|
||||
evalModules = self.evalModules.${system};
|
||||
};
|
||||
docs = import ./docs {
|
||||
inherit pkgs;
|
||||
options =
|
||||
(self.evalModules.${system} {
|
||||
modules = builtins.attrValues (builtins.removeAttrs
|
||||
# the submodules module currently doesn't evaluate:
|
||||
# error: No module found ‹name›/latest
|
||||
# not sure how important that documentation is a this time
|
||||
self.nixosModules.kubenix ["submodule" "submodules"]);
|
||||
})
|
||||
.options;
|
||||
};
|
||||
}
|
||||
// pkgs.lib.attrsets.mapAttrs' (name: value: pkgs.lib.attrsets.nameValuePair "generate-${name}" value)
|
||||
(builtins.removeAttrs (pkgs.callPackage ./pkgs/generators {}) ["override" "overrideDerivation"]);
|
||||
packages = {
|
||||
inherit (pkgs) kubernetes kubectl;
|
||||
default = pkgs.callPackage ./pkgs/kubenix.nix {
|
||||
inherit (self.packages.${system});
|
||||
evalModules = self.evalModules.${system};
|
||||
};
|
||||
docs = import ./docs {
|
||||
inherit pkgs;
|
||||
options = (self.evalModules.${system} {
|
||||
modules = builtins.attrValues (builtins.removeAttrs
|
||||
# the submodules module currently doesn't evaluate:
|
||||
# error: No module found ‹name›/latest
|
||||
# not sure how important that documentation is a this time
|
||||
self.nixosModules.kubenix [ "submodule" "submodules" ]);
|
||||
}).options;
|
||||
};
|
||||
}
|
||||
// pkgs.lib.attrsets.mapAttrs' (name: value: pkgs.lib.attrsets.nameValuePair "generate-${name}" value)
|
||||
(builtins.removeAttrs (pkgs.callPackage ./pkgs/generators { }) [ "override" "overrideDerivation" ]);
|
||||
|
||||
checks = let
|
||||
wasSuccess = suite:
|
||||
if suite.success
|
||||
then pkgs.runCommandNoCC "testing-suite-config-assertions-for-${suite.name}-succeeded" {} "echo success > $out"
|
||||
else pkgs.runCommandNoCC "testing-suite-config-assertions-for-${suite.name}-failed" {} "exit 1";
|
||||
examples = import ./docs/content/examples;
|
||||
mkK8STests = attrs:
|
||||
(import ./tests {inherit evalModules;})
|
||||
({registry = "docker.io/gatehub";} // attrs);
|
||||
in
|
||||
checks =
|
||||
let
|
||||
wasSuccess = suite:
|
||||
if suite.success
|
||||
then pkgs.runCommandNoCC "testing-suite-config-assertions-for-${suite.name}-succeeded" { } "echo success > $out"
|
||||
else pkgs.runCommandNoCC "testing-suite-config-assertions-for-${suite.name}-failed" { } "exit 1";
|
||||
examples = import ./docs/content/examples;
|
||||
mkK8STests = attrs:
|
||||
(import ./tests { inherit evalModules; })
|
||||
({ registry = "docker.io/gatehub"; } // attrs);
|
||||
in
|
||||
{
|
||||
# TODO: access "success" derivation with nice testing utils for nice output
|
||||
testing = wasSuccess examples.testing.config.testing;
|
||||
|
|
@ -185,7 +168,7 @@
|
|||
// builtins.listToAttrs (builtins.map
|
||||
(v: {
|
||||
name = "test-k8s-${builtins.replaceStrings ["."] ["_"] v}";
|
||||
value = wasSuccess (mkK8STests {k8sVersion = v;});
|
||||
value = wasSuccess (mkK8STests { k8sVersion = v; });
|
||||
})
|
||||
(import ./versions.nix).versions);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
}: {
|
||||
k8s = import ./k8s {inherit lib;};
|
||||
docker = import ./docker {inherit lib pkgs;};
|
||||
helm = import ./helm {inherit pkgs;};
|
||||
{ lib, pkgs }: {
|
||||
k8s = import ./k8s { inherit lib; };
|
||||
docker = import ./docker { inherit lib pkgs; };
|
||||
helm = import ./helm { inherit pkgs; };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
}:
|
||||
{ lib, pkgs }:
|
||||
with lib; {
|
||||
copyDockerImages = {
|
||||
images,
|
||||
dest,
|
||||
args ? "",
|
||||
}:
|
||||
copyDockerImages = { images, dest, args ? "" }:
|
||||
pkgs.writeScript "copy-docker-images.sh" (concatMapStrings
|
||||
(image: ''
|
||||
#!${pkgs.runtimeShell}
|
||||
|
|
|
|||
|
|
@ -1,46 +1,42 @@
|
|||
{
|
||||
runCommand,
|
||||
lib,
|
||||
kubernetes-helm,
|
||||
yq,
|
||||
}:
|
||||
{ runCommand, lib, kubernetes-helm, yq }:
|
||||
with lib;
|
||||
{
|
||||
# chart to template
|
||||
chart,
|
||||
# release name
|
||||
name,
|
||||
# namespace to install release into
|
||||
namespace ? null,
|
||||
# values to pass to chart
|
||||
values ? {},
|
||||
# kubernetes version to template chart for
|
||||
kubeVersion ? null,
|
||||
# whether to include CRD
|
||||
includeCRDs ? false,
|
||||
# whether to include hooks
|
||||
noHooks ? false,
|
||||
}: let
|
||||
valuesJsonFile = builtins.toFile "${name}-values.json" (builtins.toJSON values);
|
||||
# The `helm template` and YAML -> JSON steps are separate `runCommand` derivations for easier debuggability
|
||||
resourcesYaml = runCommand "${name}.yaml" {nativeBuildInputs = [kubernetes-helm];} ''
|
||||
helm template "${name}" \
|
||||
${optionalString (kubeVersion != null) "--kube-version ${kubeVersion}"} \
|
||||
${optionalString (namespace != null) "--namespace ${namespace}"} \
|
||||
${optionalString (values != {}) "-f ${valuesJsonFile}"} \
|
||||
${optionalString includeCRDs "--include-crds"} \
|
||||
${optionalString noHooks "--no-hooks"} \
|
||||
${chart} >$out
|
||||
'';
|
||||
in
|
||||
runCommand "${name}.json" {} ''
|
||||
# Remove null values
|
||||
${yq}/bin/yq -Scs 'walk(
|
||||
if type == "object" then
|
||||
with_entries(select(.value != null))
|
||||
elif type == "array" then
|
||||
map(select(. != null))
|
||||
else
|
||||
.
|
||||
end)' ${resourcesYaml} >$out
|
||||
''
|
||||
{
|
||||
# chart to template
|
||||
chart
|
||||
# release name
|
||||
, name
|
||||
# namespace to install release into
|
||||
, namespace ? null
|
||||
# values to pass to chart
|
||||
, values ? { }
|
||||
# kubernetes version to template chart for
|
||||
, kubeVersion ? null
|
||||
# whether to include CRD
|
||||
, includeCRDs ? false
|
||||
# whether to include hooks
|
||||
, noHooks ? false
|
||||
}:
|
||||
let
|
||||
valuesJsonFile = builtins.toFile "${name}-values.json" (builtins.toJSON values);
|
||||
# The `helm template` and YAML -> JSON steps are separate `runCommand` derivations for easier debuggability
|
||||
resourcesYaml = runCommand "${name}.yaml" { nativeBuildInputs = [ kubernetes-helm ]; } ''
|
||||
helm template "${name}" \
|
||||
${optionalString (kubeVersion != null) "--kube-version ${kubeVersion}"} \
|
||||
${optionalString (namespace != null) "--namespace ${namespace}"} \
|
||||
${optionalString (values != {}) "-f ${valuesJsonFile}"} \
|
||||
${optionalString includeCRDs "--include-crds"} \
|
||||
${optionalString noHooks "--no-hooks"} \
|
||||
${chart} >$out
|
||||
'';
|
||||
in
|
||||
runCommand "${name}.json" { } ''
|
||||
# Remove null values
|
||||
${yq}/bin/yq -Scs 'walk(
|
||||
if type == "object" then
|
||||
with_entries(select(.value != null))
|
||||
elif type == "array" then
|
||||
map(select(. != null))
|
||||
else
|
||||
.
|
||||
end)' ${resourcesYaml} >$out
|
||||
''
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
{pkgs}: {
|
||||
chart2json = pkgs.callPackage ./chart2json.nix {};
|
||||
fetch = pkgs.callPackage ./fetchhelm.nix {};
|
||||
{ pkgs }: {
|
||||
chart2json = pkgs.callPackage ./chart2json.nix { };
|
||||
fetch = pkgs.callPackage ./fetchhelm.nix { };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,80 +1,48 @@
|
|||
{
|
||||
stdenvNoCC,
|
||||
lib,
|
||||
kubernetes-helm,
|
||||
cacert,
|
||||
}: let
|
||||
cleanName = lib.replaceStrings ["/"] ["-"];
|
||||
{ stdenvNoCC, lib, kubernetes-helm, cacert }:
|
||||
let
|
||||
cleanName = lib.replaceStrings [ "/" ] [ "-" ];
|
||||
in
|
||||
{
|
||||
# name of the chart
|
||||
chart,
|
||||
# chart url to fetch from custom location
|
||||
chartUrl ? null,
|
||||
# version of the chart
|
||||
version ? null,
|
||||
# chart hash
|
||||
sha256,
|
||||
# whether to extract chart
|
||||
untar ? true,
|
||||
# use custom charts repo
|
||||
repo ? null,
|
||||
# pass --verify to helm chart
|
||||
verify ? false,
|
||||
# pass --devel to helm chart
|
||||
devel ? false,
|
||||
}:
|
||||
stdenvNoCC.mkDerivation {
|
||||
name = "${cleanName chart}-${
|
||||
if version == null
|
||||
then "dev"
|
||||
else version
|
||||
}";
|
||||
{
|
||||
# name of the chart
|
||||
chart
|
||||
, # chart url to fetch from custom location
|
||||
chartUrl ? null
|
||||
, # version of the chart
|
||||
version ? null
|
||||
, # chart hash
|
||||
sha256
|
||||
, # whether to extract chart
|
||||
untar ? true
|
||||
, # use custom charts repo
|
||||
repo ? null
|
||||
, # pass --verify to helm chart
|
||||
verify ? false
|
||||
, # pass --devel to helm chart
|
||||
devel ? false
|
||||
,
|
||||
}:
|
||||
stdenvNoCC.mkDerivation {
|
||||
name = "${cleanName chart}-${ if version == null then "dev" else version }";
|
||||
|
||||
buildCommand = ''
|
||||
export HOME="$PWD"
|
||||
echo "adding helm repo"
|
||||
${
|
||||
if repo == null
|
||||
then ""
|
||||
else "helm repo add repository ${repo}"
|
||||
}
|
||||
echo "fetching helm chart"
|
||||
helm fetch -d ./chart \
|
||||
${
|
||||
if untar
|
||||
then "--untar"
|
||||
else ""
|
||||
} \
|
||||
${
|
||||
if version == null
|
||||
then ""
|
||||
else "--version ${version}"
|
||||
} \
|
||||
${
|
||||
if devel
|
||||
then "--devel"
|
||||
else ""
|
||||
} \
|
||||
${
|
||||
if verify
|
||||
then "--verify"
|
||||
else ""
|
||||
} \
|
||||
${
|
||||
if chartUrl == null
|
||||
then
|
||||
(
|
||||
if repo == null
|
||||
then chart
|
||||
else "repository/${chart}"
|
||||
)
|
||||
else chartUrl
|
||||
}
|
||||
cp -r chart/*/ $out
|
||||
'';
|
||||
outputHashMode = "recursive";
|
||||
outputHashAlgo = "sha256";
|
||||
outputHash = sha256;
|
||||
nativeBuildInputs = [kubernetes-helm cacert];
|
||||
}
|
||||
buildCommand = ''
|
||||
export HOME="$PWD"
|
||||
echo "adding helm repo"
|
||||
${ if repo == null then "" else "helm repo add repository ${repo}" }
|
||||
echo "fetching helm chart"
|
||||
helm fetch -d ./chart \
|
||||
${ if untar then "--untar" else ""} \
|
||||
${ if version == null then "" else "--version ${version}" } \
|
||||
${ if devel then "--devel" else "" } \
|
||||
${ if verify then "--verify" else "" } \
|
||||
${ if chartUrl == null then (
|
||||
if repo == null
|
||||
then chart
|
||||
else "repository/${chart}"
|
||||
) else chartUrl}
|
||||
cp -r chart/*/ $out
|
||||
'';
|
||||
outputHashMode = "recursive";
|
||||
outputHashAlgo = "sha256";
|
||||
outputHash = sha256;
|
||||
nativeBuildInputs = [ kubernetes-helm cacert ];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
{pkgs ? import <nixpkgs> {}}: let
|
||||
fetchhelm = pkgs.callPackage ./fetchhelm.nix {};
|
||||
chart2json = pkgs.callPackage ./chart2json.nix {};
|
||||
in rec {
|
||||
{ pkgs ? import <nixpkgs> { } }:
|
||||
let
|
||||
fetchhelm = pkgs.callPackage ./fetchhelm.nix { };
|
||||
chart2json = pkgs.callPackage ./chart2json.nix { };
|
||||
in
|
||||
rec {
|
||||
postgresql-chart = fetchhelm {
|
||||
chart = "stable/postgresql";
|
||||
version = "0.18.1";
|
||||
|
|
|
|||
|
|
@ -1,42 +1,32 @@
|
|||
{lib}:
|
||||
{ lib }:
|
||||
with lib; rec {
|
||||
# TODO: refactor with mkOptionType
|
||||
mkSecretOption = {
|
||||
description ? "",
|
||||
default ? {},
|
||||
allowNull ? true,
|
||||
}:
|
||||
mkSecretOption = { description ? "", default ? { }, allowNull ? true }:
|
||||
mkOption {
|
||||
inherit description;
|
||||
type =
|
||||
(
|
||||
if allowNull
|
||||
then types.nullOr
|
||||
else id
|
||||
) (types.submodule {
|
||||
options = {
|
||||
name = mkOption ({
|
||||
description = "Name of the secret where secret is stored";
|
||||
type = types.str;
|
||||
default = default.name;
|
||||
}
|
||||
// (optionalAttrs (default ? "name") {
|
||||
default = default.name;
|
||||
}));
|
||||
type = (
|
||||
if allowNull
|
||||
then types.nullOr
|
||||
else id
|
||||
) (types.submodule {
|
||||
options = {
|
||||
name = mkOption ({
|
||||
description = "Name of the secret where secret is stored";
|
||||
type = types.str;
|
||||
default = default.name;
|
||||
} // (optionalAttrs (default ? "name") {
|
||||
default = default.name;
|
||||
}));
|
||||
|
||||
key = mkOption ({
|
||||
description = "Name of the key where secret is stored";
|
||||
type = types.str;
|
||||
}
|
||||
// (optionalAttrs (default ? "key") {
|
||||
default = default.key;
|
||||
}));
|
||||
};
|
||||
});
|
||||
default =
|
||||
if default == null
|
||||
then null
|
||||
else {};
|
||||
key = mkOption ({
|
||||
description = "Name of the key where secret is stored";
|
||||
type = types.str;
|
||||
} // (optionalAttrs (default ? "key") {
|
||||
default = default.key;
|
||||
}));
|
||||
};
|
||||
});
|
||||
default = if default == null then null else { };
|
||||
};
|
||||
|
||||
secretToEnv = value: {
|
||||
|
|
@ -46,10 +36,7 @@ with lib; rec {
|
|||
};
|
||||
|
||||
# Creates kubernetes list from a list of kubernetes objects
|
||||
mkList = {
|
||||
items,
|
||||
labels ? {},
|
||||
}: {
|
||||
mkList = { items, labels ? { } }: {
|
||||
kind = "List";
|
||||
apiVersion = "v1";
|
||||
|
||||
|
|
@ -57,27 +44,22 @@ with lib; rec {
|
|||
};
|
||||
|
||||
# Creates hashed kubernetes list from a list of kubernetes objects
|
||||
mkHashedList = {
|
||||
items,
|
||||
labels ? {},
|
||||
}: let
|
||||
hash = builtins.hashString "sha1" (builtins.toJSON items);
|
||||
mkHashedList = { items, labels ? { } }:
|
||||
let
|
||||
hash = builtins.hashString "sha1" (builtins.toJSON items);
|
||||
|
||||
labeledItems =
|
||||
map
|
||||
(item:
|
||||
recursiveUpdate item {
|
||||
metadata.labels."kubenix/hash" = hash;
|
||||
})
|
||||
items;
|
||||
in
|
||||
labeledItems = map
|
||||
(item:
|
||||
recursiveUpdate item {
|
||||
metadata.labels."kubenix/hash" = hash;
|
||||
})
|
||||
items;
|
||||
in
|
||||
mkList {
|
||||
items = labeledItems;
|
||||
labels =
|
||||
{
|
||||
"kubenix/hash" = hash;
|
||||
}
|
||||
// labels;
|
||||
labels = {
|
||||
"kubenix/hash" = hash;
|
||||
} // labels;
|
||||
};
|
||||
|
||||
inherit (lib) toBase64;
|
||||
|
|
|
|||
|
|
@ -1,30 +1,27 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
}:
|
||||
{ lib, pkgs }:
|
||||
with lib; let
|
||||
self = {
|
||||
importYAML = path:
|
||||
importJSON (pkgs.runCommand "yaml-to-json" {} ''
|
||||
importJSON (pkgs.runCommand "yaml-to-json" { } ''
|
||||
${pkgs.yq}/bin/yq -c . ${path} > $out
|
||||
'');
|
||||
|
||||
toYAML = config:
|
||||
builtins.readFile (pkgs.runCommand "to-yaml" {} ''
|
||||
builtins.readFile (pkgs.runCommand "to-yaml" { } ''
|
||||
${pkgs.yq}/bin/yq -y . ${pkgs.writeText "to-json" (builtins.toJSON config)} > $out
|
||||
'');
|
||||
|
||||
toMultiDocumentYaml = name: documents:
|
||||
pkgs.runCommand name {}
|
||||
(concatMapStringsSep "\necho --- >> $out\n"
|
||||
(
|
||||
d: "${pkgs.yq}/bin/yq -y . ${pkgs.writeText "to-json" (builtins.toJSON config)} >> $out"
|
||||
)
|
||||
documents);
|
||||
pkgs.runCommand name { }
|
||||
(concatMapStringsSep "\necho --- >> $out\n"
|
||||
(
|
||||
d: "${pkgs.yq}/bin/yq -y . ${pkgs.writeText "to-json" (builtins.toJSON config)} >> $out"
|
||||
)
|
||||
documents);
|
||||
|
||||
toBase64 = value:
|
||||
builtins.readFile
|
||||
(pkgs.runCommand "value-to-b64" {} "echo -n '${value}' | ${pkgs.coreutils}/bin/base64 -w0 > $out");
|
||||
(pkgs.runCommand "value-to-b64" { } "echo -n '${value}' | ${pkgs.coreutils}/bin/base64 -w0 > $out");
|
||||
|
||||
exp = base: exp: foldr (_value: acc: acc * base) 1 (range 1 exp);
|
||||
|
||||
|
|
@ -38,8 +35,7 @@ with lib; let
|
|||
i = 0;
|
||||
value = 0;
|
||||
}
|
||||
(stringToCharacters value))
|
||||
.value;
|
||||
(stringToCharacters value)).value;
|
||||
};
|
||||
in
|
||||
self
|
||||
self
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
{lib, ...}:
|
||||
{ lib, ... }:
|
||||
with lib; {
|
||||
options = {
|
||||
kubenix.project = mkOption {
|
||||
|
|
@ -10,7 +10,7 @@ with lib; {
|
|||
_m.features = mkOption {
|
||||
description = "List of features exposed by module";
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
_m.propagate = mkOption {
|
||||
|
|
@ -20,17 +20,17 @@ with lib; {
|
|||
features = mkOption {
|
||||
description = "List of features that submodule has to have to propagate module";
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
module = mkOption {
|
||||
description = "Module to propagate";
|
||||
type = types.unspecified;
|
||||
default = {};
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
}));
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,9 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
docker,
|
||||
...
|
||||
}:
|
||||
{ config, lib, pkgs, docker, ... }:
|
||||
with lib; let
|
||||
cfg = config.docker;
|
||||
in {
|
||||
imports = [./base.nix];
|
||||
in
|
||||
{
|
||||
imports = [ ./base.nix ];
|
||||
|
||||
options.docker = {
|
||||
registry.url = mkOption {
|
||||
|
|
@ -19,11 +14,7 @@ in {
|
|||
|
||||
images = mkOption {
|
||||
description = "Attribute set of docker images that should be published";
|
||||
type = types.attrsOf (types.submodule ({
|
||||
name,
|
||||
config,
|
||||
...
|
||||
}: {
|
||||
type = types.attrsOf (types.submodule ({ name, config, ... }: {
|
||||
options = {
|
||||
image = mkOption {
|
||||
description = "Docker image to publish";
|
||||
|
|
@ -65,13 +56,13 @@ in {
|
|||
};
|
||||
};
|
||||
}));
|
||||
default = {};
|
||||
default = { };
|
||||
};
|
||||
|
||||
export = mkOption {
|
||||
description = "List of images to export";
|
||||
type = types.listOf types.package;
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
copyScript = mkOption {
|
||||
|
|
@ -86,25 +77,22 @@ in {
|
|||
|
||||
config = {
|
||||
# define docker feature
|
||||
_m.features = ["docker"];
|
||||
_m.features = [ "docker" ];
|
||||
|
||||
# propagate docker options if docker feature is enabled
|
||||
_m.propagate = [
|
||||
{
|
||||
features = ["docker"];
|
||||
module = _: {
|
||||
# propagate registry options
|
||||
docker.registry = cfg.registry;
|
||||
};
|
||||
}
|
||||
];
|
||||
_m.propagate = [{
|
||||
features = [ "docker" ];
|
||||
module = _: {
|
||||
# propagate registry options
|
||||
docker.registry = cfg.registry;
|
||||
};
|
||||
}];
|
||||
|
||||
# pass docker library as param
|
||||
_module.args.docker = import ../lib/docker {inherit lib pkgs;};
|
||||
_module.args.docker = import ../lib/docker { inherit lib pkgs; };
|
||||
|
||||
# list of exported docker images
|
||||
docker.export =
|
||||
mapAttrsToList (_: i: i.image)
|
||||
docker.export = mapAttrsToList (_: i: i.image)
|
||||
(filterAttrs (_: i: i.registry != null) config.docker.images);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,6 @@
|
|||
# helm defines kubenix module with options for using helm charts
|
||||
# with kubenix
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
helm,
|
||||
...
|
||||
}:
|
||||
{ config, lib, pkgs, helm, ... }:
|
||||
with lib; let
|
||||
cfg = config.kubernetes.helm;
|
||||
|
||||
|
|
@ -16,29 +10,28 @@ with lib; let
|
|||
name = "recursive-attrs";
|
||||
description = "recursive attribute set";
|
||||
check = isAttrs;
|
||||
merge = _loc: foldl' (res: def: recursiveUpdate res def.value) {};
|
||||
merge = _loc: foldl' (res: def: recursiveUpdate res def.value) { };
|
||||
};
|
||||
|
||||
parseApiVersion = apiVersion: let
|
||||
splitted = splitString "/" apiVersion;
|
||||
in {
|
||||
group =
|
||||
if length splitted == 1
|
||||
then "core"
|
||||
else head splitted;
|
||||
version = last splitted;
|
||||
};
|
||||
in {
|
||||
imports = [./k8s.nix];
|
||||
parseApiVersion = apiVersion:
|
||||
let
|
||||
splitted = splitString "/" apiVersion;
|
||||
in
|
||||
{
|
||||
group =
|
||||
if length splitted == 1
|
||||
then "core"
|
||||
else head splitted;
|
||||
version = last splitted;
|
||||
};
|
||||
in
|
||||
{
|
||||
imports = [ ./k8s.nix ];
|
||||
|
||||
options.kubernetes.helm = {
|
||||
releases = mkOption {
|
||||
description = "Attribute set of helm releases";
|
||||
type = types.attrsOf (types.submodule ({
|
||||
config,
|
||||
name,
|
||||
...
|
||||
}: {
|
||||
type = types.attrsOf (types.submodule ({ config, name, ... }: {
|
||||
options = {
|
||||
name = mkOption {
|
||||
description = "Helm release name";
|
||||
|
|
@ -60,7 +53,7 @@ in {
|
|||
values = mkOption {
|
||||
description = "Values to pass to chart";
|
||||
type = recursiveAttrs;
|
||||
default = {};
|
||||
default = { };
|
||||
};
|
||||
|
||||
kubeVersion = mkOption {
|
||||
|
|
@ -72,7 +65,7 @@ in {
|
|||
overrides = mkOption {
|
||||
description = "Overrides to apply to all chart resources";
|
||||
type = types.listOf types.unspecified;
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
overrideNamespace = mkOption {
|
||||
|
|
@ -109,42 +102,40 @@ in {
|
|||
objects = mkOption {
|
||||
description = "Generated kubernetes objects";
|
||||
type = types.listOf types.attrs;
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
|
||||
config.overrides = mkIf (config.overrideNamespace && config.namespace != null) [
|
||||
{
|
||||
metadata.namespace = config.namespace;
|
||||
}
|
||||
];
|
||||
config.overrides = mkIf (config.overrideNamespace && config.namespace != null) [{
|
||||
metadata.namespace = config.namespace;
|
||||
}];
|
||||
|
||||
config.objects = importJSON (helm.chart2json {
|
||||
inherit (config) chart name namespace values kubeVersion includeCRDs noHooks;
|
||||
});
|
||||
}));
|
||||
default = {};
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
# expose helm helper methods as module argument
|
||||
_module.args.helm = import ../lib/helm {inherit pkgs;};
|
||||
_module.args.helm = import ../lib/helm { inherit pkgs; };
|
||||
|
||||
kubernetes.api.resources = mkMerge (flatten (mapAttrsToList
|
||||
(
|
||||
_: release:
|
||||
map
|
||||
(object: let
|
||||
(_: release: map
|
||||
(object:
|
||||
let
|
||||
apiVersion = parseApiVersion object.apiVersion;
|
||||
inherit (object.metadata) name;
|
||||
in {
|
||||
in
|
||||
{
|
||||
"${apiVersion.group}"."${apiVersion.version}".${object.kind}."${name}" = mkMerge ([
|
||||
object
|
||||
]
|
||||
++ release.overrides);
|
||||
object
|
||||
]
|
||||
++ release.overrides);
|
||||
})
|
||||
release.objects
|
||||
release.objects
|
||||
)
|
||||
cfg.releases));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,19 +1,13 @@
|
|||
{
|
||||
lib,
|
||||
definitions,
|
||||
}:
|
||||
{ lib, definitions }:
|
||||
with lib; {
|
||||
"istio_networking_v1alpha3_StringMatch" =
|
||||
recursiveUpdate
|
||||
(
|
||||
recursiveUpdate
|
||||
"istio_networking_v1alpha3_StringMatch" = recursiveUpdate
|
||||
(recursiveUpdate
|
||||
definitions."istio_networking_v1alpha3_StringMatch_Exact"
|
||||
definitions."istio_networking_v1alpha3_StringMatch_Prefix"
|
||||
)
|
||||
definitions."istio_networking_v1alpha3_StringMatch_Regex";
|
||||
|
||||
"istio_networking_v1alpha3_PortSelector" =
|
||||
recursiveUpdate
|
||||
"istio_networking_v1alpha3_PortSelector" = recursiveUpdate
|
||||
definitions."istio_networking_v1alpha3_PortSelector_Name"
|
||||
definitions."istio_networking_v1alpha3_PortSelector_Number";
|
||||
}
|
||||
|
|
|
|||
6628
modules/istio.nix
6628
modules/istio.nix
File diff suppressed because it is too large
Load diff
290
modules/k8s.nix
290
modules/k8s.nix
|
|
@ -1,12 +1,5 @@
|
|||
# K8S module defines kubernetes definitions for kubenix
|
||||
{
|
||||
options,
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
k8s,
|
||||
...
|
||||
}:
|
||||
{ options, config, lib, pkgs, k8s, ... }:
|
||||
with lib; let
|
||||
versions = (import ../versions.nix).versions;
|
||||
cfg = config.kubernetes;
|
||||
|
|
@ -15,12 +8,11 @@ with lib; let
|
|||
|
||||
getDefaults = resource: group: version: kind:
|
||||
catAttrs "default" (filter
|
||||
(
|
||||
default:
|
||||
(resource == null || default.resource == null || default.resource == resource)
|
||||
&& (default.group == null || default.group == group)
|
||||
&& (default.version == null || default.version == version)
|
||||
&& (default.kind == null || default.kind == kind)
|
||||
(default:
|
||||
(resource == null || default.resource == null || default.resource == resource)
|
||||
&& (default.group == null || default.group == group)
|
||||
&& (default.version == null || default.version == version)
|
||||
&& (default.kind == null || default.kind == kind)
|
||||
)
|
||||
cfg.api.defaults);
|
||||
|
||||
|
|
@ -31,7 +23,7 @@ with lib; let
|
|||
then map moduleToAttrs value
|
||||
else value;
|
||||
|
||||
apiOptions = {config, ...}: {
|
||||
apiOptions = { config, ... }: {
|
||||
options = {
|
||||
definitions = mkOption {
|
||||
description = "Attribute set of kubernetes definitions";
|
||||
|
|
@ -74,18 +66,17 @@ with lib; let
|
|||
default = mkOption {
|
||||
description = "Default to apply";
|
||||
type = types.unspecified;
|
||||
default = {};
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
}));
|
||||
default = [];
|
||||
default = [ ];
|
||||
apply = unique;
|
||||
};
|
||||
|
||||
types = mkOption {
|
||||
description = "List of registered kubernetes types";
|
||||
type =
|
||||
coerceListOfSubmodulesToAttrs
|
||||
type = coerceListOfSubmodulesToAttrs
|
||||
{
|
||||
options = {
|
||||
group = mkOption {
|
||||
|
|
@ -115,7 +106,7 @@ with lib; let
|
|||
};
|
||||
}
|
||||
gvkKeyFn;
|
||||
default = {};
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -133,20 +124,21 @@ with lib; let
|
|||
else -1)
|
||||
lst));
|
||||
|
||||
compareVersions = ver1: ver2: let
|
||||
getVersion = substring 1 10;
|
||||
splittedVer1 = builtins.splitVersion (getVersion ver1);
|
||||
splittedVer2 = builtins.splitVersion (getVersion ver2);
|
||||
compareVersions = ver1: ver2:
|
||||
let
|
||||
getVersion = substring 1 10;
|
||||
splittedVer1 = builtins.splitVersion (getVersion ver1);
|
||||
splittedVer2 = builtins.splitVersion (getVersion ver2);
|
||||
|
||||
v1 =
|
||||
if length splittedVer1 == 1
|
||||
then "${getVersion ver1}prod"
|
||||
else getVersion ver1;
|
||||
v2 =
|
||||
if length splittedVer2 == 1
|
||||
then "${getVersion ver2}prod"
|
||||
else getVersion ver2;
|
||||
in
|
||||
v1 =
|
||||
if length splittedVer1 == 1
|
||||
then "${getVersion ver1}prod"
|
||||
else getVersion ver1;
|
||||
v2 =
|
||||
if length splittedVer2 == 1
|
||||
then "${getVersion ver2}prod"
|
||||
else getVersion ver2;
|
||||
in
|
||||
builtins.compareVersions v1 v2;
|
||||
|
||||
customResourceTypesByAttrName = zipAttrs (mapAttrsToList
|
||||
|
|
@ -155,23 +147,20 @@ with lib; let
|
|||
})
|
||||
cfg.customTypes);
|
||||
|
||||
customResourceTypesByAttrNameSortByVersion =
|
||||
mapAttrs
|
||||
(
|
||||
_: resourceTypes:
|
||||
reverseList (sort
|
||||
(
|
||||
r1: r2:
|
||||
compareVersions r1.version r2.version > 0
|
||||
)
|
||||
resourceTypes)
|
||||
customResourceTypesByAttrNameSortByVersion = mapAttrs
|
||||
(_: resourceTypes:
|
||||
reverseList (sort
|
||||
(
|
||||
r1: r2:
|
||||
compareVersions r1.version r2.version > 0
|
||||
)
|
||||
resourceTypes)
|
||||
)
|
||||
customResourceTypesByAttrName;
|
||||
|
||||
latestCustomResourceTypes =
|
||||
mapAttrsToList (_: last) customResourceTypesByAttrNameSortByVersion;
|
||||
latestCustomResourceTypes = mapAttrsToList (_: last) customResourceTypesByAttrNameSortByVersion;
|
||||
|
||||
customResourceModuleForType = config: ct: {name, ...}: {
|
||||
customResourceModuleForType = config: ct: { name, ... }: {
|
||||
imports = getDefaults ct.name ct.group ct.version ct.kind;
|
||||
options = {
|
||||
apiVersion = mkOption {
|
||||
|
|
@ -192,7 +181,7 @@ with lib; let
|
|||
spec = mkOption {
|
||||
description = "Module spec";
|
||||
type = types.either types.attrs (types.submodule ct.module);
|
||||
default = {};
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -203,73 +192,74 @@ with lib; let
|
|||
};
|
||||
};
|
||||
|
||||
customResourceOptions =
|
||||
(mapAttrsToList
|
||||
(_: ct: {config, ...}: let
|
||||
customResourceOptions = (mapAttrsToList
|
||||
(_: ct: { config, ... }:
|
||||
let
|
||||
module = customResourceModuleForType config ct;
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.resources.${ct.group}.${ct.version}.${ct.kind} = mkOption {
|
||||
inherit (ct) description;
|
||||
type = types.attrsOf (types.submodule module);
|
||||
default = {};
|
||||
default = { };
|
||||
};
|
||||
})
|
||||
cfg.customTypes)
|
||||
++ (map
|
||||
(ct: {
|
||||
options,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
cfg.customTypes)
|
||||
++ (map
|
||||
(ct: { options, config, ... }:
|
||||
let
|
||||
module = customResourceModuleForType config ct;
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.resources.${ct.attrName} = mkOption {
|
||||
inherit (ct) description;
|
||||
type = types.attrsOf (types.submodule module);
|
||||
default = {};
|
||||
default = { };
|
||||
};
|
||||
|
||||
config.resources.${ct.group}.${ct.version}.${ct.kind} =
|
||||
mkAliasDefinitions options.resources.${ct.attrName};
|
||||
})
|
||||
latestCustomResourceTypes);
|
||||
latestCustomResourceTypes);
|
||||
|
||||
coerceListOfSubmodulesToAttrs = submodule: keyFn: let
|
||||
mergeValuesByFn = keyFn: values:
|
||||
listToAttrs (map
|
||||
(
|
||||
value:
|
||||
coerceListOfSubmodulesToAttrs = submodule: keyFn:
|
||||
let
|
||||
mergeValuesByFn = keyFn: values:
|
||||
listToAttrs (map
|
||||
(value:
|
||||
nameValuePair (toString (keyFn value)) value
|
||||
)
|
||||
values);
|
||||
)
|
||||
values);
|
||||
|
||||
# Either value of type `finalType` or `coercedType`, the latter is
|
||||
# converted to `finalType` using `coerceFunc`.
|
||||
coercedTo = coercedType: coerceFunc: finalType:
|
||||
mkOptionType rec {
|
||||
name = "coercedTo";
|
||||
description = "${finalType.description} or ${coercedType.description}";
|
||||
check = x: finalType.check x || coercedType.check x;
|
||||
merge = loc: defs: let
|
||||
coerceVal = val:
|
||||
if finalType.check val
|
||||
then val
|
||||
else let coerced = coerceFunc val; in assert finalType.check coerced; coerced;
|
||||
in
|
||||
finalType.merge loc (map (def: def // {value = coerceVal def.value;}) defs);
|
||||
inherit (finalType) getSubOptions;
|
||||
inherit (finalType) getSubModules;
|
||||
substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m);
|
||||
typeMerge = _t1: _t2: null;
|
||||
functor = (defaultFunctor name) // {wrapped = finalType;};
|
||||
};
|
||||
in
|
||||
# Either value of type `finalType` or `coercedType`, the latter is
|
||||
# converted to `finalType` using `coerceFunc`.
|
||||
coercedTo = coercedType: coerceFunc: finalType:
|
||||
mkOptionType rec {
|
||||
name = "coercedTo";
|
||||
description = "${finalType.description} or ${coercedType.description}";
|
||||
check = x: finalType.check x || coercedType.check x;
|
||||
merge = loc: defs:
|
||||
let
|
||||
coerceVal = val:
|
||||
if finalType.check val
|
||||
then val
|
||||
else let coerced = coerceFunc val; in assert finalType.check coerced; coerced;
|
||||
in
|
||||
finalType.merge loc (map (def: def // { value = coerceVal def.value; }) defs);
|
||||
inherit (finalType) getSubOptions;
|
||||
inherit (finalType) getSubModules;
|
||||
substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m);
|
||||
typeMerge = _t1: _t2: null;
|
||||
functor = (defaultFunctor name) // { wrapped = finalType; };
|
||||
};
|
||||
in
|
||||
coercedTo
|
||||
(types.listOf (types.submodule submodule))
|
||||
(mergeValuesByFn keyFn)
|
||||
(types.attrsOf (types.submodule submodule));
|
||||
in {
|
||||
imports = [./base.nix];
|
||||
(types.listOf (types.submodule submodule))
|
||||
(mergeValuesByFn keyFn)
|
||||
(types.attrsOf (types.submodule submodule));
|
||||
in
|
||||
{
|
||||
imports = [ ./base.nix ];
|
||||
|
||||
options.kubernetes = {
|
||||
kubeconfig = mkOption {
|
||||
|
|
@ -296,7 +286,7 @@ in {
|
|||
customResources = mkOption {
|
||||
description = "Setup custom resources";
|
||||
type = types.listOf types.attrs;
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
resourceOrder = mkOption {
|
||||
|
|
@ -310,25 +300,24 @@ in {
|
|||
|
||||
api = mkOption {
|
||||
type = types.submodule {
|
||||
imports =
|
||||
[
|
||||
./generated/v${cfg.version}.nix
|
||||
apiOptions
|
||||
]
|
||||
++ customResourceOptions;
|
||||
imports = [
|
||||
./generated/v${cfg.version}.nix
|
||||
apiOptions
|
||||
]
|
||||
++ customResourceOptions;
|
||||
};
|
||||
default = {};
|
||||
default = { };
|
||||
};
|
||||
|
||||
imports = mkOption {
|
||||
type = types.listOf (types.either types.package types.path);
|
||||
description = "List of resources to import";
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
resources = mkOption {
|
||||
description = "Alias for `config.kubernetes.api.resources` options";
|
||||
default = {};
|
||||
default = { };
|
||||
type = types.attrsOf types.attrs;
|
||||
};
|
||||
|
||||
|
|
@ -342,8 +331,7 @@ in {
|
|||
group = "helm.cattle.io";
|
||||
};
|
||||
};
|
||||
type =
|
||||
coerceListOfSubmodulesToAttrs
|
||||
type = coerceListOfSubmodulesToAttrs
|
||||
{
|
||||
options = {
|
||||
group = mkOption {
|
||||
|
|
@ -385,12 +373,12 @@ in {
|
|||
module = mkOption {
|
||||
description = "Custom type module";
|
||||
type = types.unspecified;
|
||||
default = {};
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
}
|
||||
gvkKeyFn;
|
||||
default = {};
|
||||
default = { };
|
||||
};
|
||||
|
||||
objects = mkOption {
|
||||
|
|
@ -398,16 +386,15 @@ in {
|
|||
type = types.listOf types.attrs;
|
||||
apply = items:
|
||||
sort
|
||||
(
|
||||
r1: r2:
|
||||
(r1: r2:
|
||||
if elem r1.kind cfg.resourceOrder && elem r2.kind cfg.resourceOrder
|
||||
then indexOf cfg.resourceOrder r1.kind < indexOf cfg.resourceOrder r2.kind
|
||||
else if elem r1.kind cfg.resourceOrder
|
||||
then true
|
||||
else false
|
||||
)
|
||||
(unique items);
|
||||
default = [];
|
||||
)
|
||||
(unique items);
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
generated = mkOption {
|
||||
|
|
@ -428,12 +415,12 @@ in {
|
|||
|
||||
config = {
|
||||
# features that module is defining
|
||||
_m.features = ["k8s"];
|
||||
_m.features = [ "k8s" ];
|
||||
|
||||
# module propagation options
|
||||
_m.propagate = [
|
||||
{
|
||||
features = ["k8s"];
|
||||
features = [ "k8s" ];
|
||||
module = _: {
|
||||
# propagate kubernetes version and namespace
|
||||
kubernetes.version = mkDefault cfg.version;
|
||||
|
|
@ -441,8 +428,8 @@ in {
|
|||
};
|
||||
}
|
||||
{
|
||||
features = ["k8s" "submodule"];
|
||||
module = {config, ...}: {
|
||||
features = [ "k8s" "submodule" ];
|
||||
module = { config, ... }: {
|
||||
# set module defaults
|
||||
kubernetes.api.defaults =
|
||||
(filter (default: default.propagate) cfg.api.defaults)
|
||||
|
|
@ -460,40 +447,37 @@ in {
|
|||
];
|
||||
|
||||
# expose k8s helper methods as module argument
|
||||
_module.args.k8s = import ../lib/k8s {inherit lib;};
|
||||
_module.args.k8s = import ../lib/k8s { inherit lib; };
|
||||
|
||||
kubernetes.api = mkMerge ([
|
||||
{
|
||||
# register custom types
|
||||
types =
|
||||
mapAttrsToList
|
||||
(_: cr: {
|
||||
inherit (cr) name group version kind attrName;
|
||||
})
|
||||
cfg.customTypes;
|
||||
{
|
||||
# register custom types
|
||||
types = mapAttrsToList
|
||||
(_: cr: {
|
||||
inherit (cr) name group version kind attrName;
|
||||
})
|
||||
cfg.customTypes;
|
||||
|
||||
defaults = [
|
||||
{
|
||||
default = {
|
||||
# set default kubernetes namespace to all resources
|
||||
metadata.namespace =
|
||||
mkIf (config.kubernetes.namespace != null)
|
||||
(mkDefault config.kubernetes.namespace);
|
||||
defaults = [{
|
||||
default = {
|
||||
# set default kubernetes namespace to all resources
|
||||
metadata.namespace = mkIf (config.kubernetes.namespace != null)
|
||||
(mkDefault config.kubernetes.namespace);
|
||||
|
||||
# set project name to all resources
|
||||
metadata.annotations = {
|
||||
"kubenix/project-name" = config.kubenix.project;
|
||||
"kubenix/k8s-version" = cfg.version;
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
]
|
||||
++
|
||||
# import of yaml files
|
||||
(map
|
||||
(i: let
|
||||
# set project name to all resources
|
||||
metadata.annotations = {
|
||||
"kubenix/project-name" = config.kubenix.project;
|
||||
"kubenix/k8s-version" = cfg.version;
|
||||
};
|
||||
};
|
||||
}];
|
||||
}
|
||||
]
|
||||
++
|
||||
# import of yaml files
|
||||
(map
|
||||
(i:
|
||||
let
|
||||
# load yaml file
|
||||
object = importYAML i;
|
||||
groupVersion = splitString "/" object.apiVersion;
|
||||
|
|
@ -504,15 +488,15 @@ in {
|
|||
then "core"
|
||||
else head groupVersion;
|
||||
inherit (object) kind;
|
||||
in {
|
||||
in
|
||||
{
|
||||
resources.${group}.${version}.${kind}.${name} = object;
|
||||
})
|
||||
cfg.imports));
|
||||
cfg.imports));
|
||||
|
||||
kubernetes.objects = flatten (mapAttrsToList
|
||||
(
|
||||
_: type:
|
||||
mapAttrsToList (_name: moduleToAttrs)
|
||||
(_: type:
|
||||
mapAttrsToList (_name: moduleToAttrs)
|
||||
cfg.api.resources.${type.group}.${type.version}.${type.kind}
|
||||
)
|
||||
cfg.api.types);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{ config, lib, ... }:
|
||||
with lib; {
|
||||
imports = [./base.nix];
|
||||
imports = [ ./base.nix ];
|
||||
|
||||
options.submodule = {
|
||||
name = mkOption {
|
||||
|
|
@ -27,24 +23,24 @@ with lib; {
|
|||
tags = mkOption {
|
||||
description = "List of submodule tags";
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
exports = mkOption {
|
||||
description = "Attribute set of functions to export";
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
default = { };
|
||||
};
|
||||
|
||||
passthru = mkOption {
|
||||
description = "Attribute set to passthru";
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
default = { };
|
||||
};
|
||||
|
||||
args._empty = mkOption {};
|
||||
args._empty = mkOption { };
|
||||
};
|
||||
|
||||
config._module.args.args = config.submodule.args;
|
||||
config._m.features = ["submodule"];
|
||||
config._m.features = [ "submodule" ];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,4 @@
|
|||
{
|
||||
config,
|
||||
options,
|
||||
kubenix,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{ config, options, kubenix, pkgs, lib, ... }:
|
||||
with lib; let
|
||||
cfg = config.submodules;
|
||||
parentConfig = config;
|
||||
|
|
@ -18,161 +11,139 @@ with lib; let
|
|||
else requiredVersion == version
|
||||
else true;
|
||||
|
||||
getDefaults = {
|
||||
name,
|
||||
version,
|
||||
tags,
|
||||
features,
|
||||
}:
|
||||
getDefaults = { name, version, tags, features }:
|
||||
catAttrs "default" (filter
|
||||
(
|
||||
submoduleDefault:
|
||||
(submoduleDefault.name == null || submoduleDefault.name == name)
|
||||
&& (matchesVersion submoduleDefault.version version)
|
||||
&& (
|
||||
(length submoduleDefault.tags == 0)
|
||||
|| (length (intersectLists submoduleDefault.tags tags)) > 0
|
||||
)
|
||||
&& (
|
||||
(length submoduleDefault.features == 0)
|
||||
|| (length (intersectLists submoduleDefault.features features)) > 0
|
||||
)
|
||||
(submoduleDefault:
|
||||
(submoduleDefault.name == null || submoduleDefault.name == name)
|
||||
&& (matchesVersion submoduleDefault.version version)
|
||||
&& (
|
||||
(length submoduleDefault.tags == 0)
|
||||
|| (length (intersectLists submoduleDefault.tags tags)) > 0
|
||||
)
|
||||
&& (
|
||||
(length submoduleDefault.features == 0)
|
||||
|| (length (intersectLists submoduleDefault.features features)) > 0
|
||||
)
|
||||
)
|
||||
config.submodules.defaults);
|
||||
|
||||
specialArgs =
|
||||
cfg.specialArgs
|
||||
// {
|
||||
parentConfig = config;
|
||||
};
|
||||
specialArgs = cfg.specialArgs // {
|
||||
parentConfig = config;
|
||||
};
|
||||
|
||||
findSubmodule = {
|
||||
name,
|
||||
version ? null,
|
||||
latest ? true,
|
||||
}: let
|
||||
matchingSubmodules =
|
||||
filter
|
||||
(
|
||||
el:
|
||||
findSubmodule = { name, version ? null, latest ? true }:
|
||||
let
|
||||
matchingSubmodules = filter
|
||||
(el:
|
||||
el.definition.name
|
||||
== name
|
||||
&& (matchesVersion version el.definition.version)
|
||||
)
|
||||
cfg.imports;
|
||||
)
|
||||
cfg.imports;
|
||||
|
||||
versionSortedSubmodules =
|
||||
sort
|
||||
(
|
||||
s1: s2:
|
||||
versionSortedSubmodules = sort
|
||||
(s1: s2:
|
||||
if builtins.compareVersions s1.definition.version s2.definition.version > 0
|
||||
then true
|
||||
else false
|
||||
)
|
||||
matchingSubmodules;
|
||||
)
|
||||
matchingSubmodules;
|
||||
|
||||
matchingModule =
|
||||
if length versionSortedSubmodules == 0
|
||||
then
|
||||
throw "No module found ${name}/${
|
||||
matchingModule =
|
||||
if length versionSortedSubmodules == 0
|
||||
then
|
||||
throw "No module found ${name}/${
|
||||
if version == null
|
||||
then "latest"
|
||||
else version
|
||||
}"
|
||||
else head versionSortedSubmodules;
|
||||
in
|
||||
else head versionSortedSubmodules;
|
||||
in
|
||||
matchingModule;
|
||||
|
||||
passthruConfig =
|
||||
mapAttrsToList
|
||||
passthruConfig = mapAttrsToList
|
||||
(name: _opt: {
|
||||
${name} = mkMerge (mapAttrsToList
|
||||
(
|
||||
_: inst:
|
||||
if inst.passthru.enable
|
||||
then inst.config.submodule.passthru.${name} or {}
|
||||
else {}
|
||||
(_: inst:
|
||||
if inst.passthru.enable
|
||||
then inst.config.submodule.passthru.${name} or { }
|
||||
else { }
|
||||
)
|
||||
config.submodules.instances);
|
||||
|
||||
_module.args = mkMerge (mapAttrsToList
|
||||
(
|
||||
_: inst:
|
||||
if inst.passthru.enable
|
||||
then inst.config.submodule.passthru._module.args or {}
|
||||
else {}
|
||||
(_: inst:
|
||||
if inst.passthru.enable
|
||||
then inst.config.submodule.passthru._module.args or { }
|
||||
else { }
|
||||
)
|
||||
config.submodules.instances);
|
||||
})
|
||||
(removeAttrs options ["_definedNames" "_module" "_m" "submodules"]);
|
||||
(removeAttrs options [ "_definedNames" "_module" "_m" "submodules" ]);
|
||||
|
||||
submoduleWithSpecialArgs = opts: specialArgs: let
|
||||
opts' = toList opts;
|
||||
inherit (lib.modules) evalModules;
|
||||
in
|
||||
submoduleWithSpecialArgs = opts: specialArgs:
|
||||
let
|
||||
opts' = toList opts;
|
||||
inherit (lib.modules) evalModules;
|
||||
in
|
||||
mkOptionType rec {
|
||||
name = "submodule";
|
||||
check = x: isAttrs x || isFunction x;
|
||||
merge = loc: defs: let
|
||||
coerce = def:
|
||||
if isFunction def
|
||||
then def
|
||||
else {config = def;};
|
||||
modules =
|
||||
opts'
|
||||
++ map (def: {
|
||||
_file = def.file;
|
||||
imports = [(coerce def.value)];
|
||||
})
|
||||
defs;
|
||||
in
|
||||
merge = loc: defs:
|
||||
let
|
||||
coerce = def:
|
||||
if isFunction def
|
||||
then def
|
||||
else { config = def; };
|
||||
modules = opts' ++ map
|
||||
(def: {
|
||||
_file = def.file;
|
||||
imports = [ (coerce def.value) ];
|
||||
})
|
||||
defs;
|
||||
in
|
||||
(evalModules {
|
||||
inherit modules specialArgs;
|
||||
prefix = loc;
|
||||
})
|
||||
.config;
|
||||
getSubOptions = prefix:
|
||||
(evalModules
|
||||
{
|
||||
modules = opts';
|
||||
inherit prefix specialArgs;
|
||||
# This is a work-around due to the fact that some sub-modules,
|
||||
# such as the one included in an attribute set, expects a "args"
|
||||
# attribute to be given to the sub-module. As the option
|
||||
# evaluation does not have any specific attribute name, we
|
||||
# provide a default one for the documentation.
|
||||
#
|
||||
# This is mandatory as some option declaration might use the
|
||||
# "name" attribute given as argument of the submodule and use it
|
||||
# as the default of option declarations.
|
||||
#
|
||||
# Using lookalike unicode single angle quotation marks because
|
||||
# of the docbook transformation the options receive. In all uses
|
||||
# > and < wouldn't be encoded correctly so the encoded values
|
||||
# would be used, and use of `<` and `>` would break the XML document.
|
||||
# It shouldn't cause an issue since this is cosmetic for the manual.
|
||||
args.name = "‹name›";
|
||||
})
|
||||
.options;
|
||||
}).config;
|
||||
getSubOptions = prefix: (evalModules {
|
||||
modules = opts';
|
||||
inherit prefix specialArgs;
|
||||
# This is a work-around due to the fact that some sub-modules,
|
||||
# such as the one included in an attribute set, expects a "args"
|
||||
# attribute to be given to the sub-module. As the option
|
||||
# evaluation does not have any specific attribute name, we
|
||||
# provide a default one for the documentation.
|
||||
#
|
||||
# This is mandatory as some option declaration might use the
|
||||
# "name" attribute given as argument of the submodule and use it
|
||||
# as the default of option declarations.
|
||||
#
|
||||
# Using lookalike unicode single angle quotation marks because
|
||||
# of the docbook transformation the options receive. In all uses
|
||||
# > and < wouldn't be encoded correctly so the encoded values
|
||||
# would be used, and use of `<` and `>` would break the XML document.
|
||||
# It shouldn't cause an issue since this is cosmetic for the manual.
|
||||
args.name = "‹name›";
|
||||
}).options;
|
||||
getSubModules = opts';
|
||||
substSubModules = m: submoduleWithSpecialArgs m specialArgs;
|
||||
functor =
|
||||
(defaultFunctor name)
|
||||
// {
|
||||
# Merging of submodules is done as part of mergeOptionDecls, as we have to annotate
|
||||
# each submodule with its location.
|
||||
payload = [];
|
||||
binOp = _lhs: _rhs: [];
|
||||
};
|
||||
functor = (defaultFunctor name) // {
|
||||
# Merging of submodules is done as part of mergeOptionDecls, as we have to annotate
|
||||
# each submodule with its location.
|
||||
payload = [ ];
|
||||
binOp = _lhs: _rhs: [ ];
|
||||
};
|
||||
};
|
||||
in {
|
||||
imports = [./base.nix];
|
||||
in
|
||||
{
|
||||
imports = [ ./base.nix ];
|
||||
|
||||
options = {
|
||||
submodules.specialArgs = mkOption {
|
||||
description = "Special args to pass to submodules. These arguments can be used for imports";
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
default = { };
|
||||
};
|
||||
|
||||
submodules.defaults = mkOption {
|
||||
|
|
@ -197,23 +168,23 @@ in {
|
|||
tags = mkOption {
|
||||
description = "List of tags to apply defaults for";
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
features = mkOption {
|
||||
description = "List of features that submodule has to have to apply defaults";
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
default = mkOption {
|
||||
description = "Default to apply to submodule instance";
|
||||
type = types.unspecified;
|
||||
default = {};
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
}));
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
submodules.propagate.enable = mkOption {
|
||||
|
|
@ -226,197 +197,184 @@ in {
|
|||
description = "List of submodule imports";
|
||||
type = types.listOf (
|
||||
types.coercedTo
|
||||
types.path
|
||||
(module: {inherit module;})
|
||||
(
|
||||
types.submodule ({
|
||||
name,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
evaledSubmodule' = evalModules {
|
||||
inherit specialArgs;
|
||||
modules =
|
||||
config.modules
|
||||
++ [./base.nix]
|
||||
++ [
|
||||
{
|
||||
types.path
|
||||
(module: { inherit module; })
|
||||
(
|
||||
types.submodule ({ name, config, ... }:
|
||||
let
|
||||
evaledSubmodule' = evalModules {
|
||||
inherit specialArgs;
|
||||
modules = config.modules
|
||||
++ [ ./base.nix ]
|
||||
++ [{
|
||||
_module.args.check = false;
|
||||
}
|
||||
];
|
||||
};
|
||||
}];
|
||||
};
|
||||
|
||||
evaledSubmodule =
|
||||
if (!(elem "submodule" evaledSubmodule'.config._m.features))
|
||||
then throw "no submodule defined"
|
||||
else evaledSubmodule';
|
||||
in {
|
||||
options = {
|
||||
module = mkOption {
|
||||
description = "Module defining submodule";
|
||||
type = types.unspecified;
|
||||
};
|
||||
evaledSubmodule =
|
||||
if (!(elem "submodule" evaledSubmodule'.config._m.features))
|
||||
then throw "no submodule defined"
|
||||
else evaledSubmodule';
|
||||
in
|
||||
{
|
||||
options = {
|
||||
module = mkOption {
|
||||
description = "Module defining submodule";
|
||||
type = types.unspecified;
|
||||
};
|
||||
|
||||
modules = mkOption {
|
||||
description = "List of modules defining submodule";
|
||||
type = types.listOf types.unspecified;
|
||||
default = [config.module];
|
||||
};
|
||||
modules = mkOption {
|
||||
description = "List of modules defining submodule";
|
||||
type = types.listOf types.unspecified;
|
||||
default = [ config.module ];
|
||||
};
|
||||
|
||||
features = mkOption {
|
||||
description = "List of features exposed by submodule";
|
||||
type = types.listOf types.str;
|
||||
};
|
||||
features = mkOption {
|
||||
description = "List of features exposed by submodule";
|
||||
type = types.listOf types.str;
|
||||
};
|
||||
|
||||
definition = mkOption {
|
||||
description = "Submodule definition";
|
||||
type = types.attrs;
|
||||
};
|
||||
definition = mkOption {
|
||||
description = "Submodule definition";
|
||||
type = types.attrs;
|
||||
};
|
||||
|
||||
exportAs = mkOption {
|
||||
description = "Name under which to register exports";
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
exportAs = mkOption {
|
||||
description = "Name under which to register exports";
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
definition = {
|
||||
inherit (evaledSubmodule.config.submodule) name description version tags exports;
|
||||
};
|
||||
config = {
|
||||
definition = {
|
||||
inherit (evaledSubmodule.config.submodule) name description version tags exports;
|
||||
};
|
||||
|
||||
inherit (evaledSubmodule.config._m) features;
|
||||
};
|
||||
})
|
||||
)
|
||||
inherit (evaledSubmodule.config._m) features;
|
||||
};
|
||||
})
|
||||
)
|
||||
);
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
submodules.instances = mkOption {
|
||||
description = "Attribute set of submodule instances";
|
||||
default = {};
|
||||
type = types.attrsOf (types.submodule ({
|
||||
name,
|
||||
config,
|
||||
options,
|
||||
...
|
||||
}: let
|
||||
# submodule associated with
|
||||
submodule = findSubmodule {
|
||||
name = config.submodule;
|
||||
inherit (config) version;
|
||||
};
|
||||
|
||||
# definition of a submodule
|
||||
submoduleDefinition = submodule.definition;
|
||||
|
||||
# submodule defaults
|
||||
defaults = getDefaults {
|
||||
inherit (submoduleDefinition) name;
|
||||
inherit (submoduleDefinition) version;
|
||||
inherit (submoduleDefinition) tags;
|
||||
inherit (submodule) features;
|
||||
};
|
||||
in {
|
||||
options = {
|
||||
name = mkOption {
|
||||
description = "Submodule instance name";
|
||||
type = types.str;
|
||||
default = name;
|
||||
default = { };
|
||||
type = types.attrsOf (types.submodule ({ name, config, options, ... }:
|
||||
let
|
||||
# submodule associated with
|
||||
submodule = findSubmodule {
|
||||
name = config.submodule;
|
||||
inherit (config) version;
|
||||
};
|
||||
|
||||
submodule = mkOption {
|
||||
description = "Name of the submodule to use";
|
||||
type = types.str;
|
||||
default = name;
|
||||
};
|
||||
# definition of a submodule
|
||||
submoduleDefinition = submodule.definition;
|
||||
|
||||
version = mkOption {
|
||||
description = ''
|
||||
Version of submodule to use, if version starts with "~" it is
|
||||
threated as regex pattern for example "~1.0.*"
|
||||
'';
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
# submodule defaults
|
||||
defaults = getDefaults {
|
||||
inherit (submoduleDefinition) name;
|
||||
inherit (submoduleDefinition) version;
|
||||
inherit (submoduleDefinition) tags;
|
||||
inherit (submodule) features;
|
||||
};
|
||||
in
|
||||
{
|
||||
options = {
|
||||
name = mkOption {
|
||||
description = "Submodule instance name";
|
||||
type = types.str;
|
||||
default = name;
|
||||
};
|
||||
|
||||
passthru.enable = mkOption {
|
||||
description = "Whether to passthru submodule resources";
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
submodule = mkOption {
|
||||
description = "Name of the submodule to use";
|
||||
type = types.str;
|
||||
default = name;
|
||||
};
|
||||
|
||||
config = mkOption {
|
||||
description = "Submodule instance ${config.name} for ${submoduleDefinition.name}:${submoduleDefinition.version} config";
|
||||
type =
|
||||
submoduleWithSpecialArgs
|
||||
({...}: {
|
||||
imports = submodule.modules ++ defaults ++ [./base.nix];
|
||||
_module.args.pkgs = pkgs;
|
||||
_module.args.name = config.name;
|
||||
_module.args.submodule = config;
|
||||
submodule.args = mkAliasDefinitions options.args;
|
||||
})
|
||||
specialArgs;
|
||||
default = {};
|
||||
};
|
||||
version = mkOption {
|
||||
description = ''
|
||||
Version of submodule to use, if version starts with "~" it is
|
||||
threated as regex pattern for example "~1.0.*"
|
||||
'';
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
|
||||
args = mkOption {
|
||||
description = "Submodule arguments (alias of config.submodule.args)";
|
||||
passthru.enable = mkOption {
|
||||
description = "Whether to passthru submodule resources";
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
|
||||
config = mkOption {
|
||||
description = "Submodule instance ${config.name} for ${submoduleDefinition.name}:${submoduleDefinition.version} config";
|
||||
type = submoduleWithSpecialArgs
|
||||
({ ... }: {
|
||||
imports = submodule.modules ++ defaults ++ [ ./base.nix ];
|
||||
_module.args.pkgs = pkgs;
|
||||
_module.args.name = config.name;
|
||||
_module.args.submodule = config;
|
||||
submodule.args = mkAliasDefinitions options.args;
|
||||
})
|
||||
specialArgs;
|
||||
default = { };
|
||||
};
|
||||
|
||||
args = mkOption {
|
||||
description = "Submodule arguments (alias of config.submodule.args)";
|
||||
};
|
||||
};
|
||||
};
|
||||
}));
|
||||
}));
|
||||
};
|
||||
default = {};
|
||||
default = { };
|
||||
};
|
||||
|
||||
config = mkMerge ([
|
||||
{
|
||||
# register exported functions as args
|
||||
_module.args = mkMerge (map
|
||||
(submodule: {
|
||||
${submodule.exportAs} = submodule.definition.exports;
|
||||
{
|
||||
# register exported functions as args
|
||||
_module.args = mkMerge (map
|
||||
(submodule: {
|
||||
${submodule.exportAs} = submodule.definition.exports;
|
||||
})
|
||||
(filter (submodule: submodule.exportAs != null) cfg.imports));
|
||||
|
||||
_m.features = [ "submodules" ];
|
||||
|
||||
submodules.specialArgs.kubenix = kubenix;
|
||||
|
||||
# passthru kubenix.project to submodules
|
||||
submodules.defaults = mkMerge [
|
||||
[{
|
||||
default = {
|
||||
kubenix.project = parentConfig.kubenix.project;
|
||||
};
|
||||
}]
|
||||
|
||||
(map
|
||||
(propagate: {
|
||||
inherit (propagate) features;
|
||||
default = propagate.module;
|
||||
})
|
||||
(filter (submodule: submodule.exportAs != null) cfg.imports));
|
||||
config._m.propagate)
|
||||
];
|
||||
}
|
||||
|
||||
_m.features = ["submodules"];
|
||||
|
||||
submodules.specialArgs.kubenix = kubenix;
|
||||
|
||||
# passthru kubenix.project to submodules
|
||||
submodules.defaults = mkMerge [
|
||||
[
|
||||
{
|
||||
default = {
|
||||
kubenix.project = parentConfig.kubenix.project;
|
||||
};
|
||||
}
|
||||
]
|
||||
|
||||
(map
|
||||
(propagate: {
|
||||
inherit (propagate) features;
|
||||
default = propagate.module;
|
||||
})
|
||||
config._m.propagate)
|
||||
];
|
||||
}
|
||||
|
||||
(mkIf cfg.propagate.enable {
|
||||
# if propagate is enabled and submodule has submodules included propagage defaults and imports
|
||||
submodules.defaults = [
|
||||
{
|
||||
features = ["submodules"];
|
||||
default = {
|
||||
submodules = {
|
||||
inherit (cfg) defaults;
|
||||
inherit (cfg) imports;
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
})
|
||||
]
|
||||
++ passthruConfig);
|
||||
(mkIf cfg.propagate.enable {
|
||||
# if propagate is enabled and submodule has submodules included propagage defaults and imports
|
||||
submodules.defaults = [{
|
||||
features = [ "submodules" ];
|
||||
default = {
|
||||
submodules = {
|
||||
inherit (cfg) defaults;
|
||||
inherit (cfg) imports;
|
||||
};
|
||||
};
|
||||
}];
|
||||
})
|
||||
]
|
||||
++ passthruConfig);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,9 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
kubenix,
|
||||
...
|
||||
}:
|
||||
{ config, pkgs, lib, kubenix, ... }:
|
||||
with lib; let
|
||||
cfg = config.testing;
|
||||
|
||||
testModule = {
|
||||
imports = [./evalTest.nix];
|
||||
imports = [ ./evalTest.nix ];
|
||||
|
||||
# passthru testing configuration
|
||||
config._module.args = {
|
||||
|
|
@ -18,9 +12,9 @@ with lib; let
|
|||
};
|
||||
};
|
||||
|
||||
isTestEnabled = test:
|
||||
(cfg.enabledTests == null || elem test.name cfg.enabledTests) && test.enable;
|
||||
in {
|
||||
isTestEnabled = test: (cfg.enabledTests == null || elem test.name cfg.enabledTests) && test.enable;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
./docker.nix
|
||||
./driver/kubetest.nix
|
||||
|
|
@ -48,23 +42,23 @@ in {
|
|||
features = mkOption {
|
||||
description = "List of features that test has to have to apply options";
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
options = mkOption {
|
||||
description = "Options to apply to test";
|
||||
type = types.unspecified;
|
||||
default = {};
|
||||
apply = default: {_file = "testing.common";} // default;
|
||||
default = { };
|
||||
apply = default: { _file = "testing.common"; } // default;
|
||||
};
|
||||
};
|
||||
}));
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
tests = mkOption {
|
||||
description = "List of test cases";
|
||||
default = [];
|
||||
default = [ ];
|
||||
type = types.listOf (types.coercedTo types.path
|
||||
(module: {
|
||||
inherit module;
|
||||
|
|
@ -88,7 +82,7 @@ in {
|
|||
args = mkOption {
|
||||
description = "Attribute set of extra args passed to tests";
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
default = { };
|
||||
};
|
||||
|
||||
success = mkOption {
|
||||
|
|
|
|||
|
|
@ -1,17 +1,13 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{ config, lib, pkgs, ... }:
|
||||
with lib;
|
||||
with import ../../lib/docker {inherit lib pkgs;}; let
|
||||
with import ../../lib/docker { inherit lib pkgs; }; let
|
||||
inherit (config) testing;
|
||||
|
||||
allImages = unique (flatten (map (t: t.evaled.config.docker.export or []) testing.tests));
|
||||
allImages = unique (flatten (map (t: t.evaled.config.docker.export or [ ]) testing.tests));
|
||||
|
||||
cfg = config.testing.docker;
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.testing.docker = {
|
||||
registryUrl = mkOption {
|
||||
description = "Docker registry url";
|
||||
|
|
@ -38,13 +34,11 @@ in {
|
|||
};
|
||||
};
|
||||
|
||||
config.testing.common = [
|
||||
{
|
||||
features = ["docker"];
|
||||
options = {
|
||||
_file = "testing.docker.registryUrl";
|
||||
docker.registry.url = cfg.registryUrl;
|
||||
};
|
||||
}
|
||||
];
|
||||
config.testing.common = [{
|
||||
features = [ "docker" ];
|
||||
options = {
|
||||
_file = "testing.docker.registryUrl";
|
||||
docker.registry.url = cfg.registryUrl;
|
||||
};
|
||||
}];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,15 @@
|
|||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{ lib, config, pkgs, ... }:
|
||||
with lib; let
|
||||
inherit (config) testing;
|
||||
cfg = testing.driver.kubetest;
|
||||
|
||||
kubetest = import ./kubetestdrv.nix {inherit pkgs;};
|
||||
kubetest = import ./kubetestdrv.nix { inherit pkgs; };
|
||||
|
||||
pythonEnv = pkgs.python38.withPackages (ps:
|
||||
with ps;
|
||||
[
|
||||
pytest
|
||||
kubetest
|
||||
kubernetes
|
||||
]
|
||||
++ cfg.extraPackages);
|
||||
pythonEnv = pkgs.python38.withPackages (ps: with ps; [
|
||||
pytest
|
||||
kubetest
|
||||
kubernetes
|
||||
] ++ cfg.extraPackages);
|
||||
|
||||
toTestScript = t:
|
||||
if isString t.script
|
||||
|
|
@ -28,26 +20,29 @@ with lib; let
|
|||
''
|
||||
else t.script;
|
||||
|
||||
tests = let
|
||||
# make sure tests are prefixed so that alphanumerical
|
||||
# sorting reproduces them in the same order as they
|
||||
# have been declared in the list.
|
||||
seive = t: t.script != null && t.enabled;
|
||||
allEligibleTests = filter seive testing.tests;
|
||||
listLengthPadding = builtins.length (
|
||||
lib.stringToCharacters (
|
||||
builtins.toString (
|
||||
builtins.length allEligibleTests
|
||||
tests =
|
||||
let
|
||||
# make sure tests are prefixed so that alphanumerical
|
||||
# sorting reproduces them in the same order as they
|
||||
# have been declared in the list.
|
||||
seive = t: t.script != null && t.enabled;
|
||||
allEligibleTests = filter seive testing.tests;
|
||||
listLengthPadding = builtins.length (
|
||||
lib.stringToCharacters (
|
||||
builtins.toString (
|
||||
builtins.length allEligibleTests
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
op = i: t: {
|
||||
path = toTestScript t;
|
||||
name = let
|
||||
prefix = lib.fixedWidthNumber listLengthPadding i;
|
||||
in "${prefix}_${t.name}_test.py";
|
||||
};
|
||||
in
|
||||
);
|
||||
op = i: t: {
|
||||
path = toTestScript t;
|
||||
name =
|
||||
let
|
||||
prefix = lib.fixedWidthNumber listLengthPadding i;
|
||||
in
|
||||
"${prefix}_${t.name}_test.py";
|
||||
};
|
||||
in
|
||||
pkgs.linkFarm "${testing.name}-tests" (
|
||||
lib.imap0 op allEligibleTests
|
||||
);
|
||||
|
|
@ -56,7 +51,8 @@ with lib; let
|
|||
#!/usr/bin/env bash
|
||||
${pythonEnv}/bin/pytest -p no:cacheprovider ${tests} $@
|
||||
'';
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.testing.driver.kubetest = {
|
||||
defaultHeader = mkOption {
|
||||
type = types.lines;
|
||||
|
|
@ -69,7 +65,7 @@ in {
|
|||
extraPackages = mkOption {
|
||||
type = types.listOf types.package;
|
||||
description = "Extra packages to pass to tests";
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
{pkgs ? import <nixpkgs> {}}:
|
||||
{ pkgs ? import <nixpkgs> { } }:
|
||||
with pkgs;
|
||||
with pkgs.python38Packages;
|
||||
with pkgs.python38;
|
||||
pkgs.python38Packages.buildPythonPackage rec {
|
||||
pname = "kubetest";
|
||||
version = "0.9.5";
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
sha256 = "sha256-TqDHMciAEXv4vMWLJY1YdtXsP4ho+INgdFB3xQQNoZU=";
|
||||
};
|
||||
propagatedBuildInputs = [pytest kubernetes];
|
||||
doCheck = false;
|
||||
}
|
||||
pkgs.python38Packages.buildPythonPackage rec {
|
||||
pname = "kubetest";
|
||||
version = "0.9.5";
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
sha256 = "sha256-TqDHMciAEXv4vMWLJY1YdtXsP4ho+INgdFB3xQQNoZU=";
|
||||
};
|
||||
propagatedBuildInputs = [ pytest kubernetes ];
|
||||
doCheck = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,4 @@
|
|||
{
|
||||
lib,
|
||||
config,
|
||||
testing,
|
||||
kubenix,
|
||||
...
|
||||
}:
|
||||
{ lib, config, testing, kubenix, ... }:
|
||||
with lib; let
|
||||
modules = [
|
||||
# testing module
|
||||
|
|
@ -29,13 +23,9 @@ with lib; let
|
|||
|
||||
# eval without checking
|
||||
evaled' = kubenix.evalModules {
|
||||
modules =
|
||||
modules
|
||||
++ [
|
||||
{
|
||||
_module.args.check = false;
|
||||
}
|
||||
];
|
||||
modules = modules ++ [{
|
||||
_module.args.check = false;
|
||||
}];
|
||||
};
|
||||
|
||||
# test configuration
|
||||
|
|
@ -45,13 +35,11 @@ with lib; let
|
|||
testFeatures = evaled'.config._m.features;
|
||||
|
||||
# common options that can be applied on this test
|
||||
commonOpts =
|
||||
filter
|
||||
(
|
||||
d:
|
||||
(intersectLists d.features testFeatures)
|
||||
== d.features
|
||||
|| (length d.features) == 0
|
||||
commonOpts = filter
|
||||
(d:
|
||||
(intersectLists d.features testFeatures)
|
||||
== d.features
|
||||
|| (length d.features) == 0
|
||||
)
|
||||
testing.common;
|
||||
|
||||
|
|
@ -59,17 +47,19 @@ with lib; let
|
|||
modulesWithCommonOptions = modules ++ (map (d: d.options) commonOpts);
|
||||
|
||||
# evaled test
|
||||
evaled = let
|
||||
evaled' = kubenix.evalModules {
|
||||
modules = modulesWithCommonOptions;
|
||||
};
|
||||
in
|
||||
evaled =
|
||||
let
|
||||
evaled' = kubenix.evalModules {
|
||||
modules = modulesWithCommonOptions;
|
||||
};
|
||||
in
|
||||
if testing.doThrowError
|
||||
then evaled'
|
||||
else if (builtins.tryEval evaled'.config.test.assertions).success
|
||||
then evaled'
|
||||
else null;
|
||||
in {
|
||||
in
|
||||
{
|
||||
options = {
|
||||
module = mkOption {
|
||||
description = "Module defining kubenix test";
|
||||
|
|
@ -112,7 +102,7 @@ in {
|
|||
description = "Test result";
|
||||
type = types.unspecified;
|
||||
internal = true;
|
||||
default = [];
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
script = mkOption {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,4 @@
|
|||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{ lib, config, pkgs, ... }:
|
||||
with lib; let
|
||||
inherit (config) testing;
|
||||
|
||||
|
|
@ -34,7 +29,8 @@ with lib; let
|
|||
echo "--> running tests"
|
||||
${testing.testScript} --kube-config=$KUBECONFIG
|
||||
'';
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.testing.runtime.local = {
|
||||
script = mkOption {
|
||||
type = types.package;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,5 @@
|
|||
# nixos-k8s implements nixos kubernetes testing runtime
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{ config, pkgs, lib, ... }:
|
||||
with lib; let
|
||||
inherit (config) testing;
|
||||
# kubeconfig = "/etc/${config.services.kubernetes.pki.etcClusterAdminKubeconfig}";
|
||||
|
|
@ -12,15 +7,15 @@ with lib; let
|
|||
kubecerts = "/var/lib/kubernetes/secrets";
|
||||
|
||||
# how we differ from the standard configuration of mkKubernetesBaseTest
|
||||
extraConfiguration = {config, ...}: {
|
||||
extraConfiguration = { config, ... }: {
|
||||
virtualisation = {
|
||||
memorySize = 2048;
|
||||
};
|
||||
|
||||
networking = {
|
||||
nameservers = ["10.0.0.254"];
|
||||
nameservers = [ "10.0.0.254" ];
|
||||
firewall = {
|
||||
trustedInterfaces = ["docker0" "cni0"];
|
||||
trustedInterfaces = [ "docker0" "cni0" ];
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -29,26 +24,22 @@ with lib; let
|
|||
kubelet = {
|
||||
seedDockerImages = testing.docker.images;
|
||||
networkPlugin = "cni";
|
||||
cni.config = [
|
||||
{
|
||||
name = "mynet";
|
||||
type = "bridge";
|
||||
bridge = "cni0";
|
||||
addIf = true;
|
||||
ipMasq = true;
|
||||
isGateway = true;
|
||||
ipam = {
|
||||
type = "host-local";
|
||||
subnet = "10.1.0.0/16";
|
||||
gateway = "10.1.0.1";
|
||||
routes = [
|
||||
{
|
||||
dst = "0.0.0.0/0";
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
];
|
||||
cni.config = [{
|
||||
name = "mynet";
|
||||
type = "bridge";
|
||||
bridge = "cni0";
|
||||
addIf = true;
|
||||
ipMasq = true;
|
||||
isGateway = true;
|
||||
ipam = {
|
||||
type = "host-local";
|
||||
subnet = "10.1.0.0/16";
|
||||
gateway = "10.1.0.1";
|
||||
routes = [{
|
||||
dst = "0.0.0.0/0";
|
||||
}];
|
||||
};
|
||||
}];
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -58,8 +49,8 @@ with lib; let
|
|||
services.copy-certs = {
|
||||
description = "Share k8s certificates with host";
|
||||
script = "cp -rf ${kubecerts} /tmp/xchg/; cp -f ${kubeconfig} /tmp/xchg/;";
|
||||
after = ["kubernetes.target"];
|
||||
wantedBy = ["multi-user.target"];
|
||||
after = [ "kubernetes.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
|
|
@ -72,16 +63,18 @@ with lib; let
|
|||
machine1.succeed("${testing.testScript} --kube-config=${kubeconfig}")
|
||||
'';
|
||||
|
||||
test = with import "${pkgs.path}/nixos/tests/kubernetes/base.nix" {
|
||||
inherit pkgs;
|
||||
inherit (pkgs) system;
|
||||
};
|
||||
test = with import "${pkgs.path}/nixos/tests/kubernetes/base.nix"
|
||||
{
|
||||
inherit pkgs;
|
||||
inherit (pkgs) system;
|
||||
};
|
||||
mkKubernetesSingleNodeTest {
|
||||
inherit extraConfiguration;
|
||||
inherit (config.testing) name;
|
||||
test = script;
|
||||
};
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.testing.runtime.nixos-k8s = {
|
||||
driver = mkOption {
|
||||
description = "Test driver";
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{ lib, config, ... }:
|
||||
with lib; {
|
||||
options.test = {
|
||||
name = mkOption {
|
||||
|
|
@ -36,13 +32,11 @@ with lib; {
|
|||
};
|
||||
};
|
||||
});
|
||||
default = [];
|
||||
example = [
|
||||
{
|
||||
assertion = false;
|
||||
message = "you can't enable this for some reason";
|
||||
}
|
||||
];
|
||||
default = [ ];
|
||||
example = [{
|
||||
assertion = false;
|
||||
message = "you can't enable this for some reason";
|
||||
}];
|
||||
description = ''
|
||||
This option allows modules to express conditions that must
|
||||
hold for the evaluation of the system configuration to
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
{
|
||||
stdenv,
|
||||
kubernetes,
|
||||
installShellFiles,
|
||||
{ stdenv
|
||||
, kubernetes
|
||||
, installShellFiles
|
||||
}:
|
||||
stdenv.mkDerivation {
|
||||
name = "kubectl-${kubernetes.version}";
|
||||
|
|
@ -10,9 +9,9 @@ stdenv.mkDerivation {
|
|||
# split out (see homepage)
|
||||
dontUnpack = true;
|
||||
|
||||
nativeBuildInputs = [installShellFiles];
|
||||
nativeBuildInputs = [ installShellFiles ];
|
||||
|
||||
outputs = ["out" "man"];
|
||||
outputs = [ "out" "man" ];
|
||||
|
||||
installPhase = ''
|
||||
install -D ${kubernetes}/bin/kubectl -t $out/bin
|
||||
|
|
|
|||
|
|
@ -1,21 +1,20 @@
|
|||
{
|
||||
stdenv,
|
||||
lib,
|
||||
fetchFromGitHub,
|
||||
removeReferencesTo,
|
||||
which,
|
||||
go,
|
||||
makeWrapper,
|
||||
rsync,
|
||||
installShellFiles,
|
||||
components ? [
|
||||
{ stdenv
|
||||
, lib
|
||||
, fetchFromGitHub
|
||||
, removeReferencesTo
|
||||
, which
|
||||
, go
|
||||
, makeWrapper
|
||||
, rsync
|
||||
, installShellFiles
|
||||
, components ? [
|
||||
"cmd/kubelet"
|
||||
"cmd/kube-apiserver"
|
||||
"cmd/kube-controller-manager"
|
||||
"cmd/kube-proxy"
|
||||
"cmd/kube-scheduler"
|
||||
"test/e2e/e2e.test"
|
||||
],
|
||||
]
|
||||
}:
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "kubernetes";
|
||||
|
|
@ -28,11 +27,11 @@ stdenv.mkDerivation rec {
|
|||
hash = "sha256-r9Clwr+87Ns4VXUW9F6cgks+LknY39ngbQgZ5UMZ0Vo=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [removeReferencesTo makeWrapper which go rsync installShellFiles];
|
||||
nativeBuildInputs = [ removeReferencesTo makeWrapper which go rsync installShellFiles ];
|
||||
|
||||
outputs = ["out" "man" "pause"];
|
||||
outputs = [ "out" "man" "pause" ];
|
||||
|
||||
patches = [./fixup-addonmanager-lib-path.patch];
|
||||
patches = [ ./fixup-addonmanager-lib-path.patch ];
|
||||
|
||||
postPatch = ''
|
||||
# go env breaks the sandbox
|
||||
|
|
@ -48,10 +47,10 @@ stdenv.mkDerivation rec {
|
|||
'';
|
||||
|
||||
WHAT = lib.concatStringsSep " " ([
|
||||
"cmd/kubeadm"
|
||||
"cmd/kubectl"
|
||||
]
|
||||
++ components);
|
||||
"cmd/kubeadm"
|
||||
"cmd/kubectl"
|
||||
]
|
||||
++ components);
|
||||
|
||||
postBuild = ''
|
||||
./hack/update-generated-docs.sh
|
||||
|
|
@ -84,7 +83,7 @@ stdenv.mkDerivation rec {
|
|||
description = "Production-Grade Container Scheduling and Management";
|
||||
license = licenses.asl20;
|
||||
homepage = "https://kubernetes.io";
|
||||
maintainers = with maintainers; [johanot offline saschagrunert];
|
||||
maintainers = with maintainers; [ johanot offline saschagrunert ];
|
||||
platforms = platforms.unix;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,45 +1,36 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
}: let
|
||||
{ pkgs, lib }:
|
||||
let
|
||||
generateIstio = import ./istio {
|
||||
inherit
|
||||
pkgs
|
||||
lib
|
||||
;
|
||||
inherit pkgs lib;
|
||||
};
|
||||
|
||||
generateK8S = name: spec:
|
||||
import ./k8s {
|
||||
inherit
|
||||
name
|
||||
pkgs
|
||||
lib
|
||||
spec
|
||||
;
|
||||
inherit name pkgs lib spec;
|
||||
};
|
||||
in {
|
||||
istio = pkgs.linkFarm "istio-generated" [
|
||||
{
|
||||
name = "latest.nix";
|
||||
path = generateIstio;
|
||||
}
|
||||
];
|
||||
in
|
||||
{
|
||||
istio = pkgs.linkFarm "istio-generated" [{
|
||||
name = "latest.nix";
|
||||
path = generateIstio;
|
||||
}];
|
||||
|
||||
k8s = pkgs.linkFarm "k8s-generated" (
|
||||
builtins.attrValues (
|
||||
builtins.mapAttrs (
|
||||
version: sha: let
|
||||
short = builtins.concatStringsSep "." (lib.lists.sublist 0 2 (builtins.splitVersion version));
|
||||
in {
|
||||
name = "v${short}.nix";
|
||||
path = generateK8S "v${short}" (builtins.fetchurl {
|
||||
url = "https://github.com/kubernetes/kubernetes/raw/v${version}/api/openapi-spec/swagger.json";
|
||||
sha256 = sha;
|
||||
});
|
||||
}
|
||||
)
|
||||
(import ../../versions.nix).full
|
||||
builtins.mapAttrs
|
||||
(version: sha:
|
||||
let
|
||||
short = builtins.concatStringsSep "." (lib.lists.sublist 0 2 (builtins.splitVersion version));
|
||||
in
|
||||
{
|
||||
name = "v${short}.nix";
|
||||
path = generateK8S "v${short}" (builtins.fetchurl {
|
||||
url = "https://github.com/kubernetes/kubernetes/raw/v${version}/api/openapi-spec/swagger.json";
|
||||
sha256 = sha;
|
||||
});
|
||||
}
|
||||
)
|
||||
(import ../../versions.nix).full
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
{
|
||||
pkgs ? import <nixpkgs> {},
|
||||
lib ? pkgs.lib,
|
||||
spec ? ./istio-schema.json,
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, lib ? pkgs.lib
|
||||
, spec ? ./istio-schema.json
|
||||
}:
|
||||
with lib; let
|
||||
gen = rec {
|
||||
|
|
@ -20,14 +19,9 @@ with lib; let
|
|||
then "null"
|
||||
else builtins.toString value;
|
||||
|
||||
removeEmptyLines = str: concatStringsSep "\n" (filter (l: builtins.match "[[:space:]]*" l != []) (splitString "\n" str));
|
||||
removeEmptyLines = str: concatStringsSep "\n" (filter (l: builtins.match "[[:space:]]*" l != [ ]) (splitString "\n" str));
|
||||
|
||||
mkOption = {
|
||||
description ? null,
|
||||
type ? null,
|
||||
default ? null,
|
||||
apply ? null,
|
||||
}:
|
||||
mkOption = { description ? null, type ? null, default ? null, apply ? null }:
|
||||
removeEmptyLines '' mkOption {
|
||||
${optionalString (description != null) "description = ${builtins.toJSON description};"}
|
||||
${optionalString (type != null) ''type = ${type};''}
|
||||
|
|
@ -53,7 +47,7 @@ with lib; let
|
|||
|
||||
hasTypeMapping = def:
|
||||
hasAttr "type" def
|
||||
&& elem def.type ["string" "integer" "boolean"];
|
||||
&& elem def.type [ "string" "integer" "boolean" ];
|
||||
|
||||
mergeValuesByKey = mergeKey: ''(mergeValuesByKey "${mergeKey}")'';
|
||||
|
||||
|
|
@ -84,157 +78,152 @@ with lib; let
|
|||
refDefinition = attr: head (tail (tail (splitString "/" attr."$ref")));
|
||||
};
|
||||
|
||||
fixJSON = replaceStrings ["\\u"] ["u"];
|
||||
fixJSON = replaceStrings [ "\\u" ] [ "u" ];
|
||||
|
||||
fetchSpecs = path: builtins.fromJSON (fixJSON (builtins.readFile path));
|
||||
|
||||
genDefinitions = swagger:
|
||||
with gen; (mapAttrs
|
||||
(
|
||||
_name: definition:
|
||||
# if $ref is in definition it means it's an alias of other definition
|
||||
if hasAttr "$ref" definition
|
||||
then definitions."${refDefinition definition}"
|
||||
else if !(hasAttr "properties" definition)
|
||||
then {
|
||||
type = mapType definition;
|
||||
}
|
||||
else {
|
||||
options =
|
||||
mapAttrs
|
||||
(
|
||||
propName: property: let
|
||||
isRequired = elem propName (definition.required or []);
|
||||
requiredOrNot = type:
|
||||
if isRequired
|
||||
then type
|
||||
else types.nullOr type;
|
||||
optionProperties =
|
||||
# if $ref is in property it references other definition,
|
||||
# but if other definition does not have properties, then just take it's type
|
||||
if hasAttr "$ref" property
|
||||
then
|
||||
if hasTypeMapping swagger.definitions.${refDefinition property}
|
||||
then {
|
||||
type = requiredOrNot (mapType swagger.definitions.${refDefinition property});
|
||||
}
|
||||
else {
|
||||
type = requiredOrNot (submoduleOf definitions (refDefinition property));
|
||||
}
|
||||
else if !(hasAttr "type" property)
|
||||
genDefinitions = swagger: with gen; (mapAttrs
|
||||
(_name: definition:
|
||||
# if $ref is in definition it means it's an alias of other definition
|
||||
if hasAttr "$ref" definition
|
||||
then definitions."${refDefinition definition}"
|
||||
else if !(hasAttr "properties" definition)
|
||||
then {
|
||||
type = mapType definition;
|
||||
}
|
||||
else {
|
||||
options = mapAttrs
|
||||
(propName: property:
|
||||
let
|
||||
isRequired = elem propName (definition.required or [ ]);
|
||||
requiredOrNot = type:
|
||||
if isRequired
|
||||
then type
|
||||
else types.nullOr type;
|
||||
optionProperties =
|
||||
# if $ref is in property it references other definition,
|
||||
# but if other definition does not have properties, then just take it's type
|
||||
if hasAttr "$ref" property
|
||||
then
|
||||
if hasTypeMapping swagger.definitions.${refDefinition property}
|
||||
then {
|
||||
type = requiredOrNot (mapType swagger.definitions.${refDefinition property});
|
||||
}
|
||||
else {
|
||||
type = requiredOrNot (submoduleOf definitions (refDefinition property));
|
||||
}
|
||||
else if !(hasAttr "type" property)
|
||||
then {
|
||||
type = types.unspecified;
|
||||
}
|
||||
# if property has an array type
|
||||
else if property.type == "array"
|
||||
then
|
||||
# if reference is in items it can reference other type of another
|
||||
# definition
|
||||
if hasAttr "$ref" property.items
|
||||
then
|
||||
# if it is a reference to simple type
|
||||
if hasTypeMapping swagger.definitions.${refDefinition property.items}
|
||||
then {
|
||||
type = types.unspecified;
|
||||
type = requiredOrNot (types.listOf (mapType swagger.definitions.${refDefinition property.items}.type));
|
||||
}
|
||||
# if property has an array type
|
||||
else if property.type == "array"
|
||||
then
|
||||
# if reference is in items it can reference other type of another
|
||||
# definition
|
||||
if hasAttr "$ref" property.items
|
||||
# if a reference is to complex type
|
||||
else
|
||||
# if x-kubernetes-patch-merge-key is set then make it an
|
||||
# attribute set of submodules
|
||||
if hasAttr "x-kubernetes-patch-merge-key" property
|
||||
then
|
||||
# if it is a reference to simple type
|
||||
if hasTypeMapping swagger.definitions.${refDefinition property.items}
|
||||
then {
|
||||
type = requiredOrNot (types.listOf (mapType swagger.definitions.${refDefinition property.items}.type));
|
||||
let
|
||||
mergeKey = property."x-kubernetes-patch-merge-key";
|
||||
in
|
||||
{
|
||||
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey);
|
||||
apply = attrsToList;
|
||||
}
|
||||
# if a reference is to complex type
|
||||
else
|
||||
# if x-kubernetes-patch-merge-key is set then make it an
|
||||
# attribute set of submodules
|
||||
if hasAttr "x-kubernetes-patch-merge-key" property
|
||||
then let
|
||||
mergeKey = property."x-kubernetes-patch-merge-key";
|
||||
in {
|
||||
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey);
|
||||
apply = attrsToList;
|
||||
}
|
||||
# in other case it's a simple list
|
||||
else {
|
||||
type = requiredOrNot (types.listOf (submoduleOf definitions (refDefinition property.items)));
|
||||
}
|
||||
# in other case it only references a simple type
|
||||
# in other case it's a simple list
|
||||
else {
|
||||
type = requiredOrNot (types.listOf (mapType property.items));
|
||||
type = requiredOrNot (types.listOf (submoduleOf definitions (refDefinition property.items)));
|
||||
}
|
||||
else if property.type == "object" && hasAttr "additionalProperties" property
|
||||
then
|
||||
# if it is a reference to simple type
|
||||
if
|
||||
(
|
||||
hasAttr "$ref" property.additionalProperties
|
||||
&& hasTypeMapping swagger.definitions.${refDefinition property.additionalProperties}
|
||||
)
|
||||
then {
|
||||
type = requiredOrNot (types.attrsOf (mapType swagger.definitions.${refDefinition property.additionalProperties}));
|
||||
}
|
||||
else if hasAttr "$ref" property.additionalProperties
|
||||
then {
|
||||
type = requiredOrNot types.attrs;
|
||||
}
|
||||
# if is an array
|
||||
else if property.additionalProperties.type == "array"
|
||||
then {
|
||||
type = requiredOrNot (types.loaOf (mapType property.additionalProperties.items));
|
||||
}
|
||||
else {
|
||||
type = requiredOrNot (types.attrsOf (mapType property.additionalProperties));
|
||||
}
|
||||
# just a simple property
|
||||
else {
|
||||
type = requiredOrNot (mapType property);
|
||||
};
|
||||
in
|
||||
mkOption ({
|
||||
description = property.description or "";
|
||||
}
|
||||
// optionProperties)
|
||||
# in other case it only references a simple type
|
||||
else {
|
||||
type = requiredOrNot (types.listOf (mapType property.items));
|
||||
}
|
||||
else if property.type == "object" && hasAttr "additionalProperties" property
|
||||
then
|
||||
# if it is a reference to simple type
|
||||
if
|
||||
(
|
||||
hasAttr "$ref" property.additionalProperties
|
||||
&& hasTypeMapping swagger.definitions.${refDefinition property.additionalProperties}
|
||||
)
|
||||
then {
|
||||
type = requiredOrNot (types.attrsOf (mapType swagger.definitions.${refDefinition property.additionalProperties}));
|
||||
}
|
||||
else if hasAttr "$ref" property.additionalProperties
|
||||
then {
|
||||
type = requiredOrNot types.attrs;
|
||||
}
|
||||
# if is an array
|
||||
else if property.additionalProperties.type == "array"
|
||||
then {
|
||||
type = requiredOrNot (types.loaOf (mapType property.additionalProperties.items));
|
||||
}
|
||||
else {
|
||||
type = requiredOrNot (types.attrsOf (mapType property.additionalProperties));
|
||||
}
|
||||
# just a simple property
|
||||
else {
|
||||
type = requiredOrNot (mapType property);
|
||||
};
|
||||
in
|
||||
mkOption ({
|
||||
description = property.description or "";
|
||||
}
|
||||
// optionProperties)
|
||||
)
|
||||
definition.properties;
|
||||
config =
|
||||
let
|
||||
optionalProps = filterAttrs
|
||||
(propName: _property:
|
||||
!(elem propName (definition.required or [ ]))
|
||||
)
|
||||
definition.properties;
|
||||
config = let
|
||||
optionalProps =
|
||||
filterAttrs
|
||||
(
|
||||
propName: _property:
|
||||
!(elem propName (definition.required or []))
|
||||
)
|
||||
definition.properties;
|
||||
in
|
||||
mapAttrs (_name: _property: mkOverride 1002 null) optionalProps;
|
||||
}
|
||||
)
|
||||
swagger.definitions);
|
||||
in
|
||||
mapAttrs (_name: _property: mkOverride 1002 null) optionalProps;
|
||||
}
|
||||
)
|
||||
swagger.definitions);
|
||||
|
||||
genResources = swagger:
|
||||
(mapAttrsToList
|
||||
(_name: property: rec {
|
||||
splittedType = splitString "." (removePrefix "me.snowdrop.istio.api." property.javaType);
|
||||
group = (concatStringsSep "." (take ((length splittedType) - 2) splittedType)) + ".istio.io";
|
||||
kind = removeSuffix "Spec" (last splittedType);
|
||||
version = last (take ((length splittedType) - 1) splittedType);
|
||||
ref = removePrefix "#/definitions/" property."$ref";
|
||||
})
|
||||
(filterAttrs
|
||||
(
|
||||
_name: property:
|
||||
(hasPrefix "me.snowdrop.istio.api" property.javaType)
|
||||
&& hasSuffix "Spec" property.javaType
|
||||
)
|
||||
swagger.properties))
|
||||
++ (mapAttrsToList
|
||||
(_name: property: rec {
|
||||
splittedType = splitString "." (removePrefix "me.snowdrop.istio.mixer." property.javaType);
|
||||
group = "config.istio.io";
|
||||
version = "v1alpha2";
|
||||
kind = head (tail splittedType);
|
||||
ref = removePrefix "#/definitions/" property."$ref";
|
||||
})
|
||||
(filterAttrs
|
||||
(
|
||||
_name: property:
|
||||
(hasPrefix "me.snowdrop.istio.mixer" property.javaType)
|
||||
&& hasSuffix "Spec" property.javaType
|
||||
)
|
||||
swagger.properties));
|
||||
genResources = swagger: (mapAttrsToList
|
||||
(_name: property: rec {
|
||||
splittedType = splitString "." (removePrefix "me.snowdrop.istio.api." property.javaType);
|
||||
group = (concatStringsSep "." (take ((length splittedType) - 2) splittedType)) + ".istio.io";
|
||||
kind = removeSuffix "Spec" (last splittedType);
|
||||
version = last (take ((length splittedType) - 1) splittedType);
|
||||
ref = removePrefix "#/definitions/" property."$ref";
|
||||
})
|
||||
(filterAttrs
|
||||
(_name: property:
|
||||
(hasPrefix "me.snowdrop.istio.api" property.javaType)
|
||||
&& hasSuffix "Spec" property.javaType
|
||||
)
|
||||
swagger.properties))
|
||||
++ (mapAttrsToList
|
||||
(_name: property: rec {
|
||||
splittedType = splitString "." (removePrefix "me.snowdrop.istio.mixer." property.javaType);
|
||||
group = "config.istio.io";
|
||||
version = "v1alpha2";
|
||||
kind = head (tail splittedType);
|
||||
ref = removePrefix "#/definitions/" property."$ref";
|
||||
})
|
||||
(filterAttrs
|
||||
(_name: property:
|
||||
(hasPrefix "me.snowdrop.istio.mixer" property.javaType)
|
||||
&& hasSuffix "Spec" property.javaType
|
||||
)
|
||||
swagger.properties));
|
||||
|
||||
swagger = fetchSpecs spec;
|
||||
|
||||
|
|
@ -367,14 +356,14 @@ with lib; let
|
|||
}
|
||||
'';
|
||||
in
|
||||
pkgs.runCommand "istio-gen.nix"
|
||||
{
|
||||
buildInputs = [pkgs.nixpkgs-fmt];
|
||||
} ''
|
||||
cat << 'GENERATED' > ./raw
|
||||
"${generated}"
|
||||
GENERATED
|
||||
pkgs.runCommand "istio-gen.nix"
|
||||
{
|
||||
buildInputs = [ pkgs.nixpkgs-fmt ];
|
||||
} ''
|
||||
cat << 'GENERATED' > ./raw
|
||||
"${generated}"
|
||||
GENERATED
|
||||
|
||||
nixpkgs-fmt ./raw
|
||||
cp ./raw $out
|
||||
''
|
||||
nixpkgs-fmt ./raw
|
||||
cp ./raw $out
|
||||
''
|
||||
|
|
|
|||
|
|
@ -1,9 +1,4 @@
|
|||
{
|
||||
name,
|
||||
pkgs,
|
||||
lib,
|
||||
spec,
|
||||
}:
|
||||
{ name, pkgs, lib, spec }:
|
||||
with lib; let
|
||||
gen = rec {
|
||||
mkMerge = values: ''mkMerge [${concatMapStrings
|
||||
|
|
@ -21,14 +16,9 @@ with lib; let
|
|||
then "null"
|
||||
else builtins.toString value;
|
||||
|
||||
removeEmptyLines = str: concatStringsSep "\n" (filter (l: builtins.match "[[:space:]]*" l != []) (splitString "\n" str));
|
||||
removeEmptyLines = str: concatStringsSep "\n" (filter (l: builtins.match "[[:space:]]*" l != [ ]) (splitString "\n" str));
|
||||
|
||||
mkOption = {
|
||||
description ? null,
|
||||
type ? null,
|
||||
default ? null,
|
||||
apply ? null,
|
||||
}:
|
||||
mkOption = { description ? null, type ? null, default ? null, apply ? null }:
|
||||
removeEmptyLines '' mkOption {
|
||||
${optionalString (description != null) "description = ${builtins.toJSON description};"}
|
||||
${optionalString (type != null) ''type = ${type};''}
|
||||
|
|
@ -52,9 +42,7 @@ with lib; let
|
|||
loaOf = type: "(types.loaOf ${type})";
|
||||
};
|
||||
|
||||
hasTypeMapping = def:
|
||||
hasAttr "type" def
|
||||
&& elem def.type ["string" "integer" "boolean"];
|
||||
hasTypeMapping = def: hasAttr "type" def && elem def.type [ "string" "integer" "boolean" ];
|
||||
|
||||
mergeValuesByKey = mergeKey: ''(mergeValuesByKey "${mergeKey}")'';
|
||||
|
||||
|
|
@ -87,43 +75,42 @@ with lib; let
|
|||
|
||||
refType = attr: head (tail (tail (splitString "/" attr."$ref")));
|
||||
|
||||
compareVersions = ver1: ver2: let
|
||||
getVersion = substring 1 10;
|
||||
splitVersion = v: builtins.splitVersion (getVersion v);
|
||||
isAlpha = v: elem "alpha" (splitVersion v);
|
||||
patchVersion = v:
|
||||
if isAlpha v
|
||||
then ""
|
||||
else if length (splitVersion v) == 1
|
||||
then "${getVersion v}prod"
|
||||
else getVersion v;
|
||||
compareVersions = ver1: ver2:
|
||||
let
|
||||
getVersion = substring 1 10;
|
||||
splitVersion = v: builtins.splitVersion (getVersion v);
|
||||
isAlpha = v: elem "alpha" (splitVersion v);
|
||||
patchVersion = v:
|
||||
if isAlpha v
|
||||
then ""
|
||||
else if length (splitVersion v) == 1
|
||||
then "${getVersion v}prod"
|
||||
else getVersion v;
|
||||
|
||||
v1 = patchVersion ver1;
|
||||
v2 = patchVersion ver2;
|
||||
in
|
||||
v1 = patchVersion ver1;
|
||||
v2 = patchVersion ver2;
|
||||
in
|
||||
builtins.compareVersions v1 v2;
|
||||
|
||||
fixJSON = replaceStrings ["\\u"] ["u"];
|
||||
fixJSON = replaceStrings [ "\\u" ] [ "u" ];
|
||||
|
||||
fetchSpecs = path: builtins.fromJSON (fixJSON (builtins.readFile path));
|
||||
|
||||
genDefinitions = swagger:
|
||||
with gen;
|
||||
mapAttrs
|
||||
(
|
||||
_name: definition:
|
||||
# if $ref is in definition it means it's an alias of other definition
|
||||
if hasAttr "$ref" definition
|
||||
then definitions."${refDefinition definition}"
|
||||
else if !(hasAttr "properties" definition)
|
||||
then {}
|
||||
# in other case it's an actual definition
|
||||
else {
|
||||
options =
|
||||
mapAttrs
|
||||
(
|
||||
propName: property: let
|
||||
isRequired = elem propName (definition.required or []);
|
||||
genDefinitions = swagger: with gen; mapAttrs
|
||||
(_name: definition:
|
||||
# if $ref is in definition it means it's an alias of other definition
|
||||
if hasAttr "$ref" definition
|
||||
then definitions."${refDefinition definition}"
|
||||
else if !(hasAttr "properties" definition)
|
||||
then { }
|
||||
# in other case it's an actual definition
|
||||
else {
|
||||
options =
|
||||
mapAttrs
|
||||
(
|
||||
propName: property:
|
||||
let
|
||||
isRequired = elem propName (definition.required or [ ]);
|
||||
requiredOrNot = type:
|
||||
if isRequired
|
||||
then type
|
||||
|
|
@ -146,43 +133,47 @@ with lib; let
|
|||
# if property has an array type
|
||||
else if property.type == "array"
|
||||
then
|
||||
# if reference is in items it can reference other type of another
|
||||
# definition
|
||||
# if reference is in items it can reference other type of another
|
||||
# definition
|
||||
if hasAttr "$ref" property.items
|
||||
then
|
||||
# if it is a reference to simple type
|
||||
# if it is a reference to simple type
|
||||
if hasTypeMapping swagger.definitions.${refDefinition property.items}
|
||||
then {
|
||||
type = requiredOrNot (types.listOf (mapType swagger.definitions.${refDefinition property.items}.type));
|
||||
}
|
||||
# if a reference is to complex type
|
||||
else
|
||||
# make it an attribute set of submodules if only x-kubernetes-patch-merge-key is present, or
|
||||
# x-kubernetes-patch-merge-key == x-kubernetes-list-map-keys.
|
||||
if (hasAttr "x-kubernetes-patch-merge-key" property) && (!(hasAttr "x-kubernetes-list-map-keys" property) || (property."x-kubernetes-list-map-keys" == [property."x-kubernetes-patch-merge-key"]))
|
||||
then let
|
||||
mergeKey = property."x-kubernetes-patch-merge-key";
|
||||
in {
|
||||
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey []);
|
||||
apply = attrsToList;
|
||||
}
|
||||
# make it an attribute set of submodules if only x-kubernetes-patch-merge-key is present, or
|
||||
# x-kubernetes-patch-merge-key == x-kubernetes-list-map-keys.
|
||||
if (hasAttr "x-kubernetes-patch-merge-key" property) && (!(hasAttr "x-kubernetes-list-map-keys" property) || (property."x-kubernetes-list-map-keys" == [ property."x-kubernetes-patch-merge-key" ]))
|
||||
then
|
||||
let
|
||||
mergeKey = property."x-kubernetes-patch-merge-key";
|
||||
in
|
||||
{
|
||||
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey [ ]);
|
||||
apply = attrsToList;
|
||||
}
|
||||
# in other case it's a simple list
|
||||
else
|
||||
# make it an attribute set of submodules if only x-kubernetes-patch-merge-key is present, or
|
||||
# x-kubernetes-patch-merge-key == x-kubernetes-list-map-keys.
|
||||
# make it an attribute set of submodules if only x-kubernetes-patch-merge-key is present, or
|
||||
# x-kubernetes-patch-merge-key == x-kubernetes-list-map-keys.
|
||||
if
|
||||
hasAttr "properties" swagger.definitions.${refDefinition property.items}
|
||||
&& hasAttr "name" swagger.definitions.${refDefinition property.items}.properties
|
||||
then let
|
||||
mergeKey = "name";
|
||||
in {
|
||||
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey (
|
||||
if hasAttr "x-kubernetes-list-map-keys" property
|
||||
then property."x-kubernetes-list-map-keys"
|
||||
else []
|
||||
));
|
||||
apply = attrsToList;
|
||||
}
|
||||
then
|
||||
let
|
||||
mergeKey = "name";
|
||||
in
|
||||
{
|
||||
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey (
|
||||
if hasAttr "x-kubernetes-list-map-keys" property
|
||||
then property."x-kubernetes-list-map-keys"
|
||||
else [ ]
|
||||
));
|
||||
apply = attrsToList;
|
||||
}
|
||||
else {
|
||||
type =
|
||||
if (refDefinition property.items) == _name
|
||||
|
|
@ -195,7 +186,7 @@ with lib; let
|
|||
}
|
||||
else if property.type == "object" && hasAttr "additionalProperties" property
|
||||
then
|
||||
# if it is a reference to simple type
|
||||
# if it is a reference to simple type
|
||||
if
|
||||
(
|
||||
hasAttr "$ref" property.additionalProperties
|
||||
|
|
@ -221,63 +212,60 @@ with lib; let
|
|||
type = requiredOrNot (mapType property);
|
||||
};
|
||||
in
|
||||
mkOption ({
|
||||
description = property.description or "";
|
||||
}
|
||||
// optionProperties)
|
||||
)
|
||||
definition.properties;
|
||||
config = let
|
||||
optionalProps =
|
||||
filterAttrs
|
||||
mkOption ({
|
||||
description = property.description or "";
|
||||
}
|
||||
// optionProperties)
|
||||
)
|
||||
definition.properties;
|
||||
config =
|
||||
let
|
||||
optionalProps =
|
||||
filterAttrs
|
||||
(
|
||||
propName: _property:
|
||||
!(elem propName (definition.required or []))
|
||||
!(elem propName (definition.required or [ ]))
|
||||
)
|
||||
definition.properties;
|
||||
in
|
||||
mapAttrs (_name: _property: mkOverride 1002 null) optionalProps;
|
||||
}
|
||||
)
|
||||
swagger.definitions;
|
||||
in
|
||||
mapAttrs (_name: _property: mkOverride 1002 null) optionalProps;
|
||||
}
|
||||
)
|
||||
swagger.definitions;
|
||||
|
||||
mapCharPairs = f: s1: s2:
|
||||
concatStrings (imap0
|
||||
(
|
||||
i: c1:
|
||||
f i c1 (
|
||||
if i >= stringLength s2
|
||||
then ""
|
||||
else elemAt (stringToCharacters s2) i
|
||||
)
|
||||
mapCharPairs = f: s1: s2: concatStrings (imap0
|
||||
(i: c1:
|
||||
f i c1 (
|
||||
if i >= stringLength s2
|
||||
then ""
|
||||
else elemAt (stringToCharacters s2) i
|
||||
)
|
||||
(stringToCharacters s1));
|
||||
)
|
||||
(stringToCharacters s1));
|
||||
|
||||
getAttrName = resource: kind:
|
||||
mapCharPairs
|
||||
(
|
||||
i: c1: c2:
|
||||
if hasPrefix "API" kind && i == 0
|
||||
then "A"
|
||||
else if i == 0
|
||||
then c1
|
||||
else if c2 == "" || (toLower c2) != c1
|
||||
then c1
|
||||
else c2
|
||||
getAttrName = resource: kind: mapCharPairs
|
||||
(i: c1: c2:
|
||||
if hasPrefix "API" kind && i == 0
|
||||
then "A"
|
||||
else if i == 0
|
||||
then c1
|
||||
else if c2 == "" || (toLower c2) != c1
|
||||
then c1
|
||||
else c2
|
||||
)
|
||||
resource
|
||||
kind;
|
||||
|
||||
genResourceTypes = swagger:
|
||||
mapAttrs'
|
||||
(name: path: let
|
||||
ref = refType (head path.post.parameters).schema;
|
||||
group' = path.post."x-kubernetes-group-version-kind".group;
|
||||
version' = path.post."x-kubernetes-group-version-kind".version;
|
||||
kind' = path.post."x-kubernetes-group-version-kind".kind;
|
||||
name' = last (splitString "/" name);
|
||||
attrName = getAttrName name' kind';
|
||||
in
|
||||
genResourceTypes = swagger: mapAttrs'
|
||||
(name: path:
|
||||
let
|
||||
ref = refType (head path.post.parameters).schema;
|
||||
group' = path.post."x-kubernetes-group-version-kind".group;
|
||||
version' = path.post."x-kubernetes-group-version-kind".version;
|
||||
kind' = path.post."x-kubernetes-group-version-kind".kind;
|
||||
name' = last (splitString "/" name);
|
||||
attrName = getAttrName name' kind';
|
||||
in
|
||||
nameValuePair ref {
|
||||
inherit ref attrName;
|
||||
|
||||
|
|
@ -309,37 +297,34 @@ with lib; let
|
|||
})
|
||||
resourceTypes);
|
||||
|
||||
resourcesTypesByKindSortByVersion =
|
||||
mapAttrs
|
||||
(
|
||||
_kind: resourceTypes:
|
||||
reverseList (sort
|
||||
(
|
||||
r1: r2:
|
||||
compareVersions r1.version r2.version > 0
|
||||
)
|
||||
resourceTypes)
|
||||
resourcesTypesByKindSortByVersion = mapAttrs
|
||||
(_kind: resourceTypes:
|
||||
reverseList (sort
|
||||
(
|
||||
r1: r2:
|
||||
compareVersions r1.version r2.version > 0
|
||||
)
|
||||
resourceTypes)
|
||||
)
|
||||
resourceTypesByKind;
|
||||
|
||||
latestResourceTypesByKind =
|
||||
mapAttrs (_kind: last) resourcesTypesByKindSortByVersion;
|
||||
latestResourceTypesByKind = mapAttrs (_kind: last) resourcesTypesByKindSortByVersion;
|
||||
|
||||
genResourceOptions = resource:
|
||||
with gen; let
|
||||
submoduleForDefinition' = definition:
|
||||
submoduleForDefinition
|
||||
definition.ref
|
||||
definition.name
|
||||
definition.kind
|
||||
definition.group
|
||||
definition.version;
|
||||
definition.ref
|
||||
definition.name
|
||||
definition.kind
|
||||
definition.group
|
||||
definition.version;
|
||||
in
|
||||
mkOption {
|
||||
inherit (resource) description;
|
||||
type = types.attrsOf (submoduleForDefinition' resource);
|
||||
default = {};
|
||||
};
|
||||
mkOption {
|
||||
inherit (resource) description;
|
||||
type = types.attrsOf (submoduleForDefinition' resource);
|
||||
default = { };
|
||||
};
|
||||
|
||||
generated = ''
|
||||
# This file was generated with kubenix k8s generator, do not edit
|
||||
|
|
@ -530,14 +515,14 @@ with lib; let
|
|||
}
|
||||
'';
|
||||
in
|
||||
pkgs.runCommand "k8s-${name}-gen.nix"
|
||||
{
|
||||
buildInputs = [pkgs.nixpkgs-fmt];
|
||||
} ''
|
||||
cat << 'GENERATED' > ./raw
|
||||
${generated}
|
||||
GENERATED
|
||||
pkgs.runCommand "k8s-${name}-gen.nix"
|
||||
{
|
||||
buildInputs = [ pkgs.nixpkgs-fmt ];
|
||||
} ''
|
||||
cat << 'GENERATED' > ./raw
|
||||
${generated}
|
||||
GENERATED
|
||||
|
||||
nixpkgs-fmt ./raw
|
||||
cp ./raw $out
|
||||
''
|
||||
nixpkgs-fmt ./raw
|
||||
cp ./raw $out
|
||||
''
|
||||
|
|
|
|||
158
pkgs/kubenix.nix
158
pkgs/kubenix.nix
|
|
@ -1,99 +1,95 @@
|
|||
{
|
||||
kubectl,
|
||||
vals,
|
||||
colordiff,
|
||||
evalModules,
|
||||
runCommand,
|
||||
writeShellScript,
|
||||
module ? {},
|
||||
specialArgs ? {},
|
||||
}: let
|
||||
kubernetes =
|
||||
(evalModules {
|
||||
inherit module specialArgs;
|
||||
})
|
||||
.config
|
||||
.kubernetes
|
||||
or {};
|
||||
{ kubectl
|
||||
, vals
|
||||
, colordiff
|
||||
, evalModules
|
||||
, runCommand
|
||||
, writeShellScript
|
||||
, module ? { }
|
||||
, specialArgs ? { }
|
||||
}:
|
||||
let
|
||||
kubernetes = (evalModules {
|
||||
inherit module specialArgs;
|
||||
}).config.kubernetes or { };
|
||||
in
|
||||
runCommand "kubenix"
|
||||
{
|
||||
kubeconfig = kubernetes.kubeconfig or "";
|
||||
result = kubernetes.result or "";
|
||||
runCommand "kubenix"
|
||||
{
|
||||
kubeconfig = kubernetes.kubeconfig or "";
|
||||
result = kubernetes.result or "";
|
||||
|
||||
# kubectl does some parsing which removes the -I flag so
|
||||
# as workaround, we write to a script and call that
|
||||
# https://github.com/kubernetes/kubernetes/pull/108199#issuecomment-1058405404
|
||||
diff = writeShellScript "kubenix-diff" ''
|
||||
${colordiff}/bin/colordiff --nobanner -N -u -I ' kubenix/hash: ' -I ' generation: ' $@
|
||||
'';
|
||||
} ''
|
||||
set -euo pipefail
|
||||
mkdir -p $out/bin
|
||||
# kubectl does some parsing which removes the -I flag so
|
||||
# as workaround, we write to a script and call that
|
||||
# https://github.com/kubernetes/kubernetes/pull/108199#issuecomment-1058405404
|
||||
diff = writeShellScript "kubenix-diff" ''
|
||||
${colordiff}/bin/colordiff --nobanner -N -u -I ' kubenix/hash: ' -I ' generation: ' $@
|
||||
'';
|
||||
} ''
|
||||
set -euo pipefail
|
||||
mkdir -p $out/bin
|
||||
|
||||
# write the manifests for use with `nix build`
|
||||
ln -s $result $out/manifest.json
|
||||
# write the manifests for use with `nix build`
|
||||
ln -s $result $out/manifest.json
|
||||
|
||||
# create a script for `nix run`
|
||||
cat <<EOF> $out/bin/kubenix
|
||||
set -uo pipefail
|
||||
# create a script for `nix run`
|
||||
cat <<EOF> $out/bin/kubenix
|
||||
set -uo pipefail
|
||||
|
||||
export KUBECONFIG=$kubeconfig
|
||||
export KUBECTL_EXTERNAL_DIFF=$diff
|
||||
export KUBECONFIG=$kubeconfig
|
||||
export KUBECTL_EXTERNAL_DIFF=$diff
|
||||
|
||||
function _help() {
|
||||
echo "
|
||||
kubenix - Kubernetes management with Nix
|
||||
function _help() {
|
||||
echo "
|
||||
kubenix - Kubernetes management with Nix
|
||||
|
||||
commands:
|
||||
"" - run diff, prompt for confirmation, then apply
|
||||
apply - create resources in target cluster
|
||||
diff - show a diff between configured and live resources
|
||||
render - print resource manifests to stdout
|
||||
commands:
|
||||
"" - run diff, prompt for confirmation, then apply
|
||||
apply - create resources in target cluster
|
||||
diff - show a diff between configured and live resources
|
||||
render - print resource manifests to stdout
|
||||
|
||||
options:
|
||||
-h --help - show this menu
|
||||
"
|
||||
}
|
||||
options:
|
||||
-h --help - show this menu
|
||||
"
|
||||
}
|
||||
|
||||
function _kubectl() {
|
||||
${vals}/bin/vals eval -fail-on-missing-key-in-map < $result | ${kubectl}/bin/kubectl \$@
|
||||
}
|
||||
function _kubectl() {
|
||||
${vals}/bin/vals eval -fail-on-missing-key-in-map < $result | ${kubectl}/bin/kubectl \$@
|
||||
}
|
||||
|
||||
# if no args given, add empty string
|
||||
[ \$# -eq 0 ] && set -- ""
|
||||
# if no args given, add empty string
|
||||
[ \$# -eq 0 ] && set -- ""
|
||||
|
||||
# parse arguments
|
||||
while test \$# -gt 0; do
|
||||
case "\$1" in
|
||||
# parse arguments
|
||||
while test \$# -gt 0; do
|
||||
case "\$1" in
|
||||
|
||||
-h|--help)
|
||||
_help
|
||||
exit 0;;
|
||||
-h|--help)
|
||||
_help
|
||||
exit 0;;
|
||||
|
||||
"")
|
||||
_kubectl diff -f - --prune
|
||||
if [[ "\$?" -eq 1 ]]; then
|
||||
read -p 'apply? [y/N]: ' response
|
||||
[[ \$response == "y" ]] && _kubectl apply -f - --prune --all
|
||||
fi
|
||||
shift;;
|
||||
"")
|
||||
_kubectl diff -f - --prune
|
||||
if [[ "\$?" -eq 1 ]]; then
|
||||
read -p 'apply? [y/N]: ' response
|
||||
[[ \$response == "y" ]] && _kubectl apply -f - --prune --all
|
||||
fi
|
||||
shift;;
|
||||
|
||||
render)
|
||||
${vals}/bin/vals eval < $result
|
||||
shift;;
|
||||
render)
|
||||
${vals}/bin/vals eval < $result
|
||||
shift;;
|
||||
|
||||
apply|diff)
|
||||
_kubectl \$@ -f - --prune
|
||||
shift;;
|
||||
apply|diff)
|
||||
_kubectl \$@ -f - --prune
|
||||
shift;;
|
||||
|
||||
*)
|
||||
_kubectl \$@
|
||||
shift;;
|
||||
*)
|
||||
_kubectl \$@
|
||||
shift;;
|
||||
|
||||
esac
|
||||
done
|
||||
esac
|
||||
done
|
||||
|
||||
EOF
|
||||
chmod +x $out/bin/kubenix
|
||||
''
|
||||
EOF
|
||||
chmod +x $out/bin/kubenix
|
||||
''
|
||||
|
|
|
|||
|
|
@ -1,20 +1,15 @@
|
|||
{
|
||||
system ? builtins.currentSystem,
|
||||
evalModules ? (import ../. {}).evalModules.${system},
|
||||
}: {
|
||||
k8sVersion ? "1.23",
|
||||
registry ? throw "Registry url not defined",
|
||||
doThrowError ? true, # whether any testing error should throw an error
|
||||
enabledTests ? null,
|
||||
}: let
|
||||
{ system ? builtins.currentSystem, evalModules ? (import ../. { }).evalModules.${system} }:
|
||||
{ k8sVersion ? "1.23"
|
||||
, registry ? throw "Registry url not defined"
|
||||
, doThrowError ? true
|
||||
# whether any testing error should throw an error
|
||||
, enabledTests ? null
|
||||
}:
|
||||
let
|
||||
inherit
|
||||
((evalModules {
|
||||
module = {
|
||||
kubenix,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
imports = [kubenix.modules.testing];
|
||||
module = { kubenix, pkgs, ... }: {
|
||||
imports = [ kubenix.modules.testing ];
|
||||
|
||||
testing = {
|
||||
inherit doThrowError enabledTests;
|
||||
|
|
@ -38,21 +33,19 @@
|
|||
./submodules/passthru.nix
|
||||
];
|
||||
|
||||
args = {images = pkgs.callPackage ./images.nix {};};
|
||||
args = { images = pkgs.callPackage ./images.nix { }; };
|
||||
docker.registryUrl = registry;
|
||||
|
||||
common = [
|
||||
{
|
||||
features = ["k8s"];
|
||||
options = {
|
||||
kubernetes.version = k8sVersion;
|
||||
};
|
||||
}
|
||||
];
|
||||
common = [{
|
||||
features = [ "k8s" ];
|
||||
options = {
|
||||
kubernetes.version = k8sVersion;
|
||||
};
|
||||
}];
|
||||
};
|
||||
};
|
||||
}))
|
||||
config
|
||||
;
|
||||
in
|
||||
config.testing // {recurseForDerivations = true;}
|
||||
config.testing // { recurseForDerivations = true; }
|
||||
|
|
|
|||
|
|
@ -1,11 +1,4 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
kubenix,
|
||||
helm,
|
||||
...
|
||||
}:
|
||||
{ config, lib, pkgs, kubenix, helm, ... }:
|
||||
with lib;
|
||||
with kubenix.lib;
|
||||
with pkgs.dockerTools; let
|
||||
|
|
@ -35,8 +28,9 @@ with pkgs.dockerTools; let
|
|||
finalImageName = "docker.io/bitnami/bitnami-shell";
|
||||
finalImageTag = "10";
|
||||
};
|
||||
in {
|
||||
imports = [kubenix.modules.test kubenix.modules.helm kubenix.modules.k8s kubenix.modules.docker];
|
||||
in
|
||||
{
|
||||
imports = [ kubenix.modules.test kubenix.modules.helm kubenix.modules.k8s kubenix.modules.docker ];
|
||||
|
||||
docker.images = {
|
||||
postgresql.image = postgresql;
|
||||
|
|
|
|||
|
|
@ -1,44 +1,40 @@
|
|||
{
|
||||
pkgs,
|
||||
dockerTools,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{ pkgs, dockerTools, lib, ... }:
|
||||
with lib; {
|
||||
curl = dockerTools.buildLayeredImage {
|
||||
name = "curl";
|
||||
tag = "latest";
|
||||
config.Cmd = ["${pkgs.bash}" "-c" "sleep infinity"];
|
||||
contents = [pkgs.bash pkgs.curl pkgs.cacert];
|
||||
config.Cmd = [ "${pkgs.bash}" "-c" "sleep infinity" ];
|
||||
contents = [ pkgs.bash pkgs.curl pkgs.cacert ];
|
||||
};
|
||||
|
||||
nginx = let
|
||||
nginxPort = "80";
|
||||
nginxConf = pkgs.writeText "nginx.conf" ''
|
||||
user nginx nginx;
|
||||
daemon off;
|
||||
error_log /dev/stdout info;
|
||||
pid /dev/null;
|
||||
events {}
|
||||
http {
|
||||
access_log /dev/stdout;
|
||||
server {
|
||||
listen ${nginxPort};
|
||||
index index.html;
|
||||
location / {
|
||||
root ${nginxWebRoot};
|
||||
nginx =
|
||||
let
|
||||
nginxPort = "80";
|
||||
nginxConf = pkgs.writeText "nginx.conf" ''
|
||||
user nginx nginx;
|
||||
daemon off;
|
||||
error_log /dev/stdout info;
|
||||
pid /dev/null;
|
||||
events {}
|
||||
http {
|
||||
access_log /dev/stdout;
|
||||
server {
|
||||
listen ${nginxPort};
|
||||
index index.html;
|
||||
location / {
|
||||
root ${nginxWebRoot};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'';
|
||||
nginxWebRoot = pkgs.writeTextDir "index.html" ''
|
||||
<html><body><h1>Hello from NGINX</h1></body></html>
|
||||
'';
|
||||
in
|
||||
'';
|
||||
nginxWebRoot = pkgs.writeTextDir "index.html" ''
|
||||
<html><body><h1>Hello from NGINX</h1></body></html>
|
||||
'';
|
||||
in
|
||||
dockerTools.buildLayeredImage {
|
||||
name = "xtruder/nginx";
|
||||
tag = "latest";
|
||||
contents = [pkgs.nginx];
|
||||
contents = [ pkgs.nginx ];
|
||||
extraCommands = ''
|
||||
mkdir -p etc
|
||||
chmod u+w etc
|
||||
|
|
@ -50,9 +46,9 @@ with lib; {
|
|||
echo "nginx:x:1000:nginx" > etc/group
|
||||
'';
|
||||
config = {
|
||||
Cmd = ["nginx" "-c" nginxConf];
|
||||
Cmd = [ "nginx" "-c" nginxConf ];
|
||||
ExposedPorts = {
|
||||
"${nginxPort}/tcp" = {};
|
||||
"${nginxPort}/tcp" = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{kubenix, ...}: {
|
||||
imports = with kubenix.modules; [test k8s istio];
|
||||
{ kubenix, ... }: {
|
||||
imports = with kubenix.modules; [ test k8s istio ];
|
||||
|
||||
test = {
|
||||
name = "istio-bookinfo";
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
name = "http";
|
||||
protocol = "HTTP";
|
||||
};
|
||||
hosts = ["*"];
|
||||
hosts = [ "*" ];
|
||||
}
|
||||
];
|
||||
};
|
||||
|
|
@ -25,8 +25,8 @@
|
|||
|
||||
VirtualService.bookinfo = {
|
||||
spec = {
|
||||
hosts = ["*"];
|
||||
gateways = ["bookinfo-gateway"];
|
||||
hosts = [ "*" ];
|
||||
gateways = [ "bookinfo-gateway" ];
|
||||
http = [
|
||||
{
|
||||
match = [
|
||||
|
|
|
|||
|
|
@ -1,24 +1,18 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
kubenix,
|
||||
...
|
||||
}:
|
||||
{ config, lib, kubenix, ... }:
|
||||
with lib; let
|
||||
latestCrontab = config.kubernetes.api.resources.cronTabs.latest;
|
||||
in {
|
||||
imports = with kubenix.modules; [test k8s];
|
||||
in
|
||||
{
|
||||
imports = with kubenix.modules; [ test k8s ];
|
||||
|
||||
test = {
|
||||
name = "k8s-crd";
|
||||
description = "Simple test tesing CRD";
|
||||
enable = builtins.compareVersions config.kubernetes.version "1.8" >= 0;
|
||||
assertions = [
|
||||
{
|
||||
message = "Custom resource should have correct version set";
|
||||
assertion = latestCrontab.apiVersion == "stable.example.com/v2";
|
||||
}
|
||||
];
|
||||
assertions = [{
|
||||
message = "Custom resource should have correct version set";
|
||||
assertion = latestCrontab.apiVersion == "stable.example.com/v2";
|
||||
}];
|
||||
script = ''
|
||||
@pytest.mark.applymanifest('${config.kubernetes.resultYAML}')
|
||||
def test_testing_module(kube):
|
||||
|
|
|
|||
|
|
@ -1,14 +1,10 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
kubenix,
|
||||
...
|
||||
}:
|
||||
{ config, lib, kubenix, ... }:
|
||||
with lib; let
|
||||
inherit (config.kubernetes.api.resources.pods) pod1;
|
||||
inherit (config.kubernetes.api.resources.pods) pod2;
|
||||
in {
|
||||
imports = with kubenix.modules; [test k8s];
|
||||
in
|
||||
{
|
||||
imports = with kubenix.modules; [ test k8s ];
|
||||
|
||||
test = {
|
||||
name = "k8s-defaults";
|
||||
|
|
@ -29,7 +25,7 @@ in {
|
|||
];
|
||||
};
|
||||
|
||||
kubernetes.resources.pods.pod1 = {};
|
||||
kubernetes.resources.pods.pod1 = { };
|
||||
|
||||
kubernetes.resources.pods.pod2 = {
|
||||
metadata.labels.custom-label = "value";
|
||||
|
|
@ -48,7 +44,7 @@ in {
|
|||
}
|
||||
{
|
||||
resource = "pods";
|
||||
default = {config, ...}: {
|
||||
default = { config, ... }: {
|
||||
config.metadata.annotations = mkIf (config.metadata.labels ? "custom-label") {
|
||||
conditional-annotation = "value";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,11 +1,4 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
kubenix,
|
||||
images,
|
||||
test,
|
||||
...
|
||||
}:
|
||||
{ config, lib, kubenix, images, test, ... }:
|
||||
with lib; let
|
||||
cfg = config.kubernetes.api.resources.deployments.nginx;
|
||||
image = images.nginx;
|
||||
|
|
@ -17,17 +10,16 @@ with lib; let
|
|||
inherit (config.kubernetes) namespace;
|
||||
name = "curl";
|
||||
};
|
||||
spec.containers = [
|
||||
{
|
||||
name = "curl";
|
||||
image = config.docker.images.curl.path;
|
||||
args = ["curl" "--retry" "20" "--retry-connrefused" "http://nginx"];
|
||||
}
|
||||
];
|
||||
spec.containers = [{
|
||||
name = "curl";
|
||||
image = config.docker.images.curl.path;
|
||||
args = [ "curl" "--retry" "20" "--retry-connrefused" "http://nginx" ];
|
||||
}];
|
||||
spec.restartPolicy = "Never";
|
||||
});
|
||||
in {
|
||||
imports = [kubenix.modules.test kubenix.modules.k8s kubenix.modules.docker];
|
||||
in
|
||||
{
|
||||
imports = [ kubenix.modules.test kubenix.modules.k8s kubenix.modules.docker ];
|
||||
|
||||
test = {
|
||||
name = "k8s-deployment";
|
||||
|
|
|
|||
|
|
@ -1,14 +1,10 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
kubenix,
|
||||
...
|
||||
}:
|
||||
{ config, lib, kubenix, ... }:
|
||||
with lib; let
|
||||
pod = config.kubernetes.api.resources.core.v1.Pod.test;
|
||||
deployment = config.kubernetes.api.resources.apps.v1.Deployment.nginx-deployment;
|
||||
in {
|
||||
imports = with kubenix.modules; [test k8s];
|
||||
in
|
||||
{
|
||||
imports = with kubenix.modules; [ test k8s ];
|
||||
|
||||
test = {
|
||||
name = "k8s-imports";
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
kubenix,
|
||||
...
|
||||
}:
|
||||
{ config, lib, kubenix, ... }:
|
||||
with lib; {
|
||||
imports = with kubenix.modules; [test k8s];
|
||||
imports = with kubenix.modules; [ test k8s ];
|
||||
|
||||
test = {
|
||||
name = "k8s-order";
|
||||
|
|
@ -39,7 +34,7 @@ with lib; {
|
|||
plural = "crontabs";
|
||||
singular = "crontab";
|
||||
kind = "CronTab";
|
||||
shortNames = ["ct"];
|
||||
shortNames = [ "ct" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -62,7 +57,7 @@ with lib; {
|
|||
}
|
||||
];
|
||||
|
||||
kubernetes.resources.namespaces.test = {};
|
||||
kubernetes.resources.namespaces.test = { };
|
||||
|
||||
kubernetes.resources."stable.example.com"."v1".CronTab.crontab.spec.schedule = "* * * * *";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
{
|
||||
config,
|
||||
kubenix,
|
||||
...
|
||||
}: let
|
||||
{ config, kubenix, ... }:
|
||||
let
|
||||
cfg = config.kubernetes.api.resources.pods.nginx;
|
||||
in {
|
||||
imports = [kubenix.modules.test kubenix.modules.k8s];
|
||||
in
|
||||
{
|
||||
imports = [ kubenix.modules.test kubenix.modules.k8s ];
|
||||
|
||||
test = {
|
||||
name = "k8s-simple";
|
||||
|
|
@ -22,5 +20,5 @@ in {
|
|||
];
|
||||
};
|
||||
|
||||
kubernetes.resources.pods.nginx = {};
|
||||
kubernetes.resources.pods.nginx = { };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
{
|
||||
name,
|
||||
config,
|
||||
lib,
|
||||
kubenix,
|
||||
images,
|
||||
...
|
||||
}:
|
||||
{ name, config, lib, kubenix, images, ... }:
|
||||
with lib; {
|
||||
imports = with kubenix.modules; [test submodules k8s docker];
|
||||
imports = with kubenix.modules; [ test submodules k8s docker ];
|
||||
|
||||
test = {
|
||||
name = "k8s-submodule";
|
||||
|
|
@ -26,41 +19,33 @@ with lib; {
|
|||
|
||||
kubernetes.namespace = "test-namespace";
|
||||
|
||||
submodules.imports = [
|
||||
{
|
||||
module = {
|
||||
name,
|
||||
config,
|
||||
...
|
||||
}: {
|
||||
imports = with kubenix.modules; [submodule k8s docker];
|
||||
submodules.imports = [{
|
||||
module = { name, config, ... }: {
|
||||
imports = with kubenix.modules; [ submodule k8s docker ];
|
||||
|
||||
config = {
|
||||
submodule = {
|
||||
name = "test-submodule";
|
||||
passthru = {
|
||||
kubernetes.objects = config.kubernetes.objects;
|
||||
docker.images = config.docker.images;
|
||||
};
|
||||
config = {
|
||||
submodule = {
|
||||
name = "test-submodule";
|
||||
passthru = {
|
||||
kubernetes.objects = config.kubernetes.objects;
|
||||
docker.images = config.docker.images;
|
||||
};
|
||||
|
||||
kubernetes.resources.pods.nginx = {
|
||||
metadata.name = name;
|
||||
spec.containers.nginx.image = config.docker.images.nginx.path;
|
||||
};
|
||||
|
||||
docker.images.nginx.image = images.nginx;
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
kubernetes.api.defaults = [
|
||||
{
|
||||
propagate = true;
|
||||
default.metadata.labels.my-label = "my-value";
|
||||
}
|
||||
];
|
||||
kubernetes.resources.pods.nginx = {
|
||||
metadata.name = name;
|
||||
spec.containers.nginx.image = config.docker.images.nginx.path;
|
||||
};
|
||||
|
||||
docker.images.nginx.image = images.nginx;
|
||||
};
|
||||
};
|
||||
}];
|
||||
|
||||
kubernetes.api.defaults = [{
|
||||
propagate = true;
|
||||
default.metadata.labels.my-label = "my-value";
|
||||
}];
|
||||
|
||||
submodules.instances.passthru = {
|
||||
submodule = "test-submodule";
|
||||
|
|
|
|||
|
|
@ -1,10 +1,4 @@
|
|||
{
|
||||
name,
|
||||
config,
|
||||
lib,
|
||||
kubenix,
|
||||
...
|
||||
}:
|
||||
{ name, config, lib, kubenix, ... }:
|
||||
with lib; let
|
||||
inherit (config.submodules.instances) instance1;
|
||||
inherit (config.submodules.instances) instance2;
|
||||
|
|
@ -13,8 +7,8 @@ with lib; let
|
|||
inherit (config.submodules.instances) instance5;
|
||||
inherit (config.submodules.instances) versioned-submodule;
|
||||
|
||||
submodule = {...}: {
|
||||
imports = [kubenix.modules.submodule];
|
||||
submodule = { ... }: {
|
||||
imports = [ kubenix.modules.submodule ];
|
||||
|
||||
options.submodule.args = {
|
||||
value = mkOption {
|
||||
|
|
@ -28,8 +22,9 @@ with lib; let
|
|||
};
|
||||
};
|
||||
};
|
||||
in {
|
||||
imports = with kubenix.modules; [test submodules];
|
||||
in
|
||||
{
|
||||
imports = with kubenix.modules; [ test submodules ];
|
||||
|
||||
test = {
|
||||
name = "submodules-defaults";
|
||||
|
|
@ -80,7 +75,7 @@ in {
|
|||
{
|
||||
submodule = {
|
||||
name = "submodule1";
|
||||
tags = ["tag1"];
|
||||
tags = [ "tag1" ];
|
||||
};
|
||||
}
|
||||
];
|
||||
|
|
@ -91,7 +86,7 @@ in {
|
|||
{
|
||||
submodule = {
|
||||
name = "submodule2";
|
||||
tags = ["tag2"];
|
||||
tags = [ "tag2" ];
|
||||
};
|
||||
}
|
||||
];
|
||||
|
|
@ -102,7 +97,7 @@ in {
|
|||
{
|
||||
submodule = {
|
||||
name = "submodule3";
|
||||
tags = ["tag2"];
|
||||
tags = [ "tag2" ];
|
||||
};
|
||||
}
|
||||
];
|
||||
|
|
@ -146,11 +141,11 @@ in {
|
|||
default.submodule.args.defaultValue = mkDefault "value";
|
||||
}
|
||||
{
|
||||
tags = ["tag1"];
|
||||
tags = [ "tag1" ];
|
||||
default.submodule.args.value = mkDefault "value1";
|
||||
}
|
||||
{
|
||||
tags = ["tag2"];
|
||||
tags = [ "tag2" ];
|
||||
default.submodule.args.value = mkDefault "value2";
|
||||
}
|
||||
{
|
||||
|
|
@ -158,7 +153,7 @@ in {
|
|||
default.submodule.args.value = mkDefault "value4";
|
||||
}
|
||||
{
|
||||
default = {config, ...}: {
|
||||
default = { config, ... }: {
|
||||
submodule.args.defaultValue = mkIf (config.submodule.args.value == "custom-value") "my-custom-value";
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,7 @@
|
|||
{
|
||||
name,
|
||||
config,
|
||||
lib,
|
||||
kubenix,
|
||||
subm-lib,
|
||||
...
|
||||
}:
|
||||
{ name, config, lib, kubenix, subm-lib, ... }:
|
||||
with lib; let
|
||||
submodule = {
|
||||
imports = [kubenix.modules.submodule];
|
||||
imports = [ kubenix.modules.submodule ];
|
||||
|
||||
config.submodule = {
|
||||
name = "subm";
|
||||
|
|
@ -17,8 +10,9 @@ with lib; let
|
|||
};
|
||||
};
|
||||
};
|
||||
in {
|
||||
imports = with kubenix.modules; [test submodules];
|
||||
in
|
||||
{
|
||||
imports = with kubenix.modules; [ test submodules ];
|
||||
|
||||
test = {
|
||||
name = "submodules-exports";
|
||||
|
|
@ -33,7 +27,7 @@ in {
|
|||
|
||||
submodules.imports = [
|
||||
{
|
||||
modules = [submodule];
|
||||
modules = [ submodule ];
|
||||
exportAs = "subm-lib";
|
||||
}
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,27 +1,22 @@
|
|||
{
|
||||
name,
|
||||
config,
|
||||
lib,
|
||||
kubenix,
|
||||
...
|
||||
}:
|
||||
{ name, config, lib, kubenix, ... }:
|
||||
with lib; let
|
||||
submodule = {name, ...}: {
|
||||
imports = [kubenix.modules.submodule];
|
||||
submodule = { name, ... }: {
|
||||
imports = [ kubenix.modules.submodule ];
|
||||
|
||||
config.submodule = {
|
||||
name = "subm";
|
||||
passthru.global.${name} = "true";
|
||||
};
|
||||
};
|
||||
in {
|
||||
imports = with kubenix.modules; [test submodules];
|
||||
in
|
||||
{
|
||||
imports = with kubenix.modules; [ test submodules ];
|
||||
|
||||
options = {
|
||||
global = mkOption {
|
||||
description = "Global value";
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -45,11 +40,9 @@ in {
|
|||
];
|
||||
};
|
||||
|
||||
submodules.imports = [
|
||||
{
|
||||
modules = [submodule];
|
||||
}
|
||||
];
|
||||
submodules.imports = [{
|
||||
modules = [ submodule ];
|
||||
}];
|
||||
|
||||
submodules.instances.inst1 = {
|
||||
submodule = "subm";
|
||||
|
|
|
|||
|
|
@ -1,15 +1,10 @@
|
|||
{
|
||||
name,
|
||||
config,
|
||||
lib,
|
||||
kubenix,
|
||||
...
|
||||
}:
|
||||
{ name, config, lib, kubenix, ... }:
|
||||
with lib; let
|
||||
cfg = config.submodules.instances.instance;
|
||||
inherit (cfg.config.submodule) args;
|
||||
in {
|
||||
imports = with kubenix.modules; [test submodules];
|
||||
in
|
||||
{
|
||||
imports = with kubenix.modules; [ test submodules ];
|
||||
|
||||
test = {
|
||||
name = "submodules-simple";
|
||||
|
|
@ -45,8 +40,8 @@ in {
|
|||
submodules.propagate.enable = true;
|
||||
submodules.imports = [
|
||||
{
|
||||
module = {submodule, ...}: {
|
||||
imports = [kubenix.modules.submodule];
|
||||
module = { submodule, ... }: {
|
||||
imports = [ kubenix.modules.submodule ];
|
||||
|
||||
options.submodule.args = {
|
||||
name = mkOption {
|
||||
|
|
@ -62,7 +57,7 @@ in {
|
|||
|
||||
config = {
|
||||
submodule.name = "submodule";
|
||||
submodule.tags = ["tag"];
|
||||
submodule.tags = [ "tag" ];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,11 @@
|
|||
{
|
||||
name,
|
||||
config,
|
||||
lib,
|
||||
kubenix,
|
||||
...
|
||||
}:
|
||||
{ name, config, lib, kubenix, ... }:
|
||||
with lib; let
|
||||
inst-exact = config.submodules.instances.inst-exact.config;
|
||||
inst-regex = config.submodules.instances.inst-regex.config;
|
||||
inst-latest = config.submodules.instances.inst-latest.config;
|
||||
|
||||
submodule = {
|
||||
imports = [kubenix.modules.submodule];
|
||||
imports = [ kubenix.modules.submodule ];
|
||||
|
||||
options.version = mkOption {
|
||||
type = types.str;
|
||||
|
|
@ -20,8 +14,9 @@ with lib; let
|
|||
|
||||
config.submodule.name = "subm";
|
||||
};
|
||||
in {
|
||||
imports = with kubenix.modules; [test submodules];
|
||||
in
|
||||
{
|
||||
imports = with kubenix.modules; [ test submodules ];
|
||||
|
||||
test = {
|
||||
name = "submodules-versioning";
|
||||
|
|
|
|||
18
versions.nix
18
versions.nix
|
|
@ -12,19 +12,17 @@ let
|
|||
"1.26.5" = "sha256:1dyqvggyvqw3z9sml2x06v1l9kynqcs8bkfrkx8jy81gkvg7qxdi";
|
||||
"1.27.2" = "sha256:1yqcds6lvpnvc5dsv9pnvp5qb3kc5y6cdgx827szljdlwf51wd15";
|
||||
};
|
||||
in {
|
||||
in
|
||||
{
|
||||
inherit full;
|
||||
# sorted list of major.minor version numbers
|
||||
# NOTE: avoiding pulling in lib here (not for any good reason)
|
||||
versions =
|
||||
map (v: let
|
||||
arr = builtins.splitVersion v;
|
||||
in (
|
||||
builtins.concatStringsSep "."
|
||||
[
|
||||
(builtins.elemAt arr 0)
|
||||
(builtins.elemAt arr 1)
|
||||
versions = with builtins; map
|
||||
(v: (
|
||||
concatStringsSep "." [
|
||||
(elemAt (splitVersion v) 0)
|
||||
(elemAt (splitVersion v) 1)
|
||||
]
|
||||
))
|
||||
(builtins.attrNames full);
|
||||
(attrNames full);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue