mirror of
https://github.com/TECHNOFAB11/kubenix.git
synced 2025-12-12 16:10:05 +01:00
fmt
This commit is contained in:
parent
a0ce293db8
commit
60592d3096
55 changed files with 23668 additions and 30925 deletions
|
|
@ -1,9 +1,9 @@
|
||||||
{ system ? builtins.currentSystem }:
|
{system ? builtins.currentSystem}: let
|
||||||
let
|
|
||||||
in
|
in
|
||||||
(
|
(
|
||||||
(import ./compat.nix).flake-compat {
|
(import ./compat.nix).flake-compat {
|
||||||
src = ./.;
|
src = ./.;
|
||||||
inherit system;
|
inherit system;
|
||||||
}
|
}
|
||||||
).defaultNix
|
)
|
||||||
|
.defaultNix
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
{ system ? builtins.currentSystem
|
|
||||||
, evalModules ? (import ../. { }).evalModules.${system}
|
|
||||||
}:
|
|
||||||
|
|
||||||
{ registry ? "docker.io/gatehub" }:
|
|
||||||
|
|
||||||
{
|
{
|
||||||
nginx-deployment = import ./nginx-deployment { inherit evalModules registry; };
|
system ? builtins.currentSystem,
|
||||||
|
evalModules ? (import ../. {}).evalModules.${system},
|
||||||
|
}: {registry ? "docker.io/gatehub"}: {
|
||||||
|
nginx-deployment = import ./nginx-deployment {inherit evalModules registry;};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
{ evalModules, registry }:
|
{
|
||||||
|
evalModules,
|
||||||
let
|
registry,
|
||||||
|
}: let
|
||||||
# evaluated configuration
|
# evaluated configuration
|
||||||
config = (evalModules {
|
config =
|
||||||
module =
|
(evalModules {
|
||||||
{ kubenix, ... }: {
|
module = {kubenix, ...}: {
|
||||||
imports = [
|
imports = [
|
||||||
kubenix.modules.testing
|
kubenix.modules.testing
|
||||||
./module.nix
|
./module.nix
|
||||||
|
|
@ -16,12 +17,12 @@ let
|
||||||
kubernetes.version = "1.21";
|
kubernetes.version = "1.21";
|
||||||
|
|
||||||
testing = {
|
testing = {
|
||||||
tests = [ ./test.nix ];
|
tests = [./test.nix];
|
||||||
docker.registryUrl = "";
|
docker.registryUrl = "";
|
||||||
# testing commonalities for tests that exhibit the respective feature
|
# testing commonalities for tests that exhibit the respective feature
|
||||||
common = [
|
common = [
|
||||||
{
|
{
|
||||||
features = [ "k8s" ];
|
features = ["k8s"];
|
||||||
options = {
|
options = {
|
||||||
kubernetes.version = "1.20";
|
kubernetes.version = "1.20";
|
||||||
};
|
};
|
||||||
|
|
@ -29,10 +30,9 @@ let
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}).config;
|
})
|
||||||
|
.config;
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
inherit config;
|
inherit config;
|
||||||
|
|
||||||
# config checks
|
# config checks
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
{ dockerTools, nginx }:
|
{
|
||||||
|
dockerTools,
|
||||||
|
nginx,
|
||||||
|
}:
|
||||||
dockerTools.buildLayeredImage {
|
dockerTools.buildLayeredImage {
|
||||||
name = "nginx";
|
name = "nginx";
|
||||||
contents = [ nginx ];
|
contents = [nginx];
|
||||||
extraCommands = ''
|
extraCommands = ''
|
||||||
mkdir -p etc
|
mkdir -p etc
|
||||||
chmod u+w etc
|
chmod u+w etc
|
||||||
|
|
@ -10,9 +12,9 @@ dockerTools.buildLayeredImage {
|
||||||
echo "nginx:x:1000:nginx" > etc/group
|
echo "nginx:x:1000:nginx" > etc/group
|
||||||
'';
|
'';
|
||||||
config = {
|
config = {
|
||||||
Cmd = [ "nginx" "-c" "/etc/nginx/nginx.conf" ];
|
Cmd = ["nginx" "-c" "/etc/nginx/nginx.conf"];
|
||||||
ExposedPorts = {
|
ExposedPorts = {
|
||||||
"80/tcp" = { };
|
"80/tcp" = {};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
{ config, lib, pkgs, kubenix, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
let
|
|
||||||
nginx = pkgs.callPackage ./image.nix { };
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
imports = with kubenix.modules; [ k8s docker ];
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
kubenix,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
|
nginx = pkgs.callPackage ./image.nix {};
|
||||||
|
in {
|
||||||
|
imports = with kubenix.modules; [k8s docker];
|
||||||
|
|
||||||
docker.images.nginx.image = nginx;
|
docker.images.nginx.image = nginx;
|
||||||
|
|
||||||
|
|
@ -54,10 +57,12 @@ in
|
||||||
|
|
||||||
kubernetes.resources.services.nginx = {
|
kubernetes.resources.services.nginx = {
|
||||||
spec = {
|
spec = {
|
||||||
ports = [{
|
ports = [
|
||||||
|
{
|
||||||
name = "http";
|
name = "http";
|
||||||
port = 80;
|
port = 80;
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
selector.app = "nginx";
|
selector.app = "nginx";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,13 @@
|
||||||
{ config, lib, pkgs, kubenix, test, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [ kubenix.modules.test ./module.nix ];
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
kubenix,
|
||||||
|
test,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; {
|
||||||
|
imports = [kubenix.modules.test ./module.nix];
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
name = "nginx-deployment";
|
name = "nginx-deployment";
|
||||||
|
|
|
||||||
73
flake.nix
73
flake.nix
|
|
@ -7,55 +7,59 @@
|
||||||
devshell-flake.url = "github:numtide/devshell";
|
devshell-flake.url = "github:numtide/devshell";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, nixpkgs, flake-utils, devshell-flake }:
|
outputs = {
|
||||||
|
self,
|
||||||
(flake-utils.lib.eachDefaultSystem (system:
|
nixpkgs,
|
||||||
let
|
flake-utils,
|
||||||
|
devshell-flake,
|
||||||
|
}:
|
||||||
|
(flake-utils.lib.eachDefaultSystem (
|
||||||
|
system: let
|
||||||
pkgs = import nixpkgs {
|
pkgs = import nixpkgs {
|
||||||
inherit system;
|
inherit system;
|
||||||
overlays = [
|
overlays = [
|
||||||
self.overlay
|
self.overlay
|
||||||
devshell-flake.overlay
|
devshell-flake.overlay
|
||||||
];
|
];
|
||||||
config = { allowUnsupportedSystem = true; };
|
config = {allowUnsupportedSystem = true;};
|
||||||
};
|
};
|
||||||
|
|
||||||
lib = pkgs.lib;
|
lib = pkgs.lib;
|
||||||
|
|
||||||
kubenix = {
|
kubenix = {
|
||||||
lib = import ./lib { inherit lib pkgs; };
|
lib = import ./lib {inherit lib pkgs;};
|
||||||
evalModules = self.evalModules.${system};
|
evalModules = self.evalModules.${system};
|
||||||
modules = self.modules;
|
modules = self.modules;
|
||||||
};
|
};
|
||||||
|
|
||||||
# evalModules with same interface as lib.evalModules and kubenix as
|
# evalModules with same interface as lib.evalModules and kubenix as
|
||||||
# special argument
|
# special argument
|
||||||
evalModules = attrs@{ module ? null, modules ? [ module ], ... }:
|
evalModules = attrs @ {
|
||||||
let
|
module ? null,
|
||||||
lib' = lib.extend (lib: self: import ./lib/upstreamables.nix { inherit lib pkgs; });
|
modules ? [module],
|
||||||
attrs' = builtins.removeAttrs attrs [ "module" ];
|
...
|
||||||
|
}: let
|
||||||
|
lib' = lib.extend (lib: self: import ./lib/upstreamables.nix {inherit lib pkgs;});
|
||||||
|
attrs' = builtins.removeAttrs attrs ["module"];
|
||||||
in
|
in
|
||||||
lib'.evalModules (lib.recursiveUpdate
|
lib'.evalModules (lib.recursiveUpdate
|
||||||
{
|
{
|
||||||
inherit modules;
|
inherit modules;
|
||||||
specialArgs = { inherit kubenix; };
|
specialArgs = {inherit kubenix;};
|
||||||
args = {
|
args = {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
name = "default";
|
name = "default";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
attrs');
|
attrs');
|
||||||
|
in {
|
||||||
in
|
|
||||||
{
|
|
||||||
|
|
||||||
inherit evalModules;
|
inherit evalModules;
|
||||||
|
|
||||||
jobs = import ./jobs { inherit pkgs; };
|
jobs = import ./jobs {inherit pkgs;};
|
||||||
|
|
||||||
devShell = with pkgs; devshell.mkShell
|
devShell = with pkgs;
|
||||||
{ imports = [ (devshell.importTOML ./devshell.toml) ]; };
|
devshell.mkShell
|
||||||
|
{imports = [(devshell.importTOML ./devshell.toml)];};
|
||||||
|
|
||||||
packages = flake-utils.lib.flattenTree {
|
packages = flake-utils.lib.flattenTree {
|
||||||
inherit (pkgs) kubernetes kubectl;
|
inherit (pkgs) kubernetes kubectl;
|
||||||
|
|
@ -66,31 +70,30 @@
|
||||||
if suite.success == true
|
if suite.success == true
|
||||||
then pkgs.runCommandNoCC "testing-suite-config-assertions-for-${suite.name}-succeeded" {} "echo success > $out"
|
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";
|
else pkgs.runCommandNoCC "testing-suite-config-assertions-for-${suite.name}-failed" {} "exit 1";
|
||||||
mkExamples = attrs: (import ./examples { inherit evalModules; })
|
mkExamples = attrs:
|
||||||
({ registry = "docker.io/gatehub"; } // attrs);
|
(import ./examples {inherit evalModules;})
|
||||||
mkK8STests = attrs: (import ./tests { inherit evalModules; })
|
({registry = "docker.io/gatehub";} // attrs);
|
||||||
({ registry = "docker.io/gatehub"; } // attrs);
|
mkK8STests = attrs:
|
||||||
|
(import ./tests {inherit evalModules;})
|
||||||
|
({registry = "docker.io/gatehub";} // attrs);
|
||||||
in {
|
in {
|
||||||
# TODO: access "success" derivation with nice testing utils for nice output
|
# TODO: access "success" derivation with nice testing utils for nice output
|
||||||
nginx-example = wasSuccess (mkExamples { }).nginx-deployment.config.testing;
|
nginx-example = wasSuccess (mkExamples {}).nginx-deployment.config.testing;
|
||||||
tests-k8s-1_19 = wasSuccess (mkK8STests { k8sVersion = "1.19"; });
|
tests-k8s-1_19 = wasSuccess (mkK8STests {k8sVersion = "1.19";});
|
||||||
tests-k8s-1_20 = wasSuccess (mkK8STests { k8sVersion = "1.20"; });
|
tests-k8s-1_20 = wasSuccess (mkK8STests {k8sVersion = "1.20";});
|
||||||
tests-k8s-1_21 = wasSuccess (mkK8STests { k8sVersion = "1.21"; });
|
tests-k8s-1_21 = wasSuccess (mkK8STests {k8sVersion = "1.21";});
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
|
// {
|
||||||
//
|
|
||||||
|
|
||||||
{
|
|
||||||
modules = import ./modules;
|
modules = import ./modules;
|
||||||
overlay = final: prev: {
|
overlay = final: prev: {
|
||||||
kubenix.evalModules = self.evalModules.${prev.system};
|
kubenix.evalModules = self.evalModules.${prev.system};
|
||||||
# up to date versions of their nixpkgs equivalents
|
# up to date versions of their nixpkgs equivalents
|
||||||
kubernetes = prev.callPackage ./pkgs/applications/networking/cluster/kubernetes
|
kubernetes =
|
||||||
{ };
|
prev.callPackage ./pkgs/applications/networking/cluster/kubernetes
|
||||||
kubectl = prev.callPackage ./pkgs/applications/networking/cluster/kubectl { };
|
{};
|
||||||
|
kubectl = prev.callPackage ./pkgs/applications/networking/cluster/kubectl {};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
{ pkgs }:
|
{pkgs}: {
|
||||||
{
|
generators = pkgs.callPackage ./generators {};
|
||||||
generators = pkgs.callPackage ./generators { };
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
{ pkgs, lib }:
|
{
|
||||||
let
|
pkgs,
|
||||||
|
lib,
|
||||||
|
}: let
|
||||||
generateIstio = import ./istio {
|
generateIstio = import ./istio {
|
||||||
inherit
|
inherit
|
||||||
pkgs
|
pkgs
|
||||||
|
|
@ -8,7 +9,8 @@ let
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
|
|
||||||
generateK8S = name: spec: import ./k8s {
|
generateK8S = name: spec:
|
||||||
|
import ./k8s {
|
||||||
inherit
|
inherit
|
||||||
name
|
name
|
||||||
pkgs
|
pkgs
|
||||||
|
|
@ -16,14 +18,13 @@ let
|
||||||
spec
|
spec
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
|
in {
|
||||||
in
|
istio = pkgs.linkFarm "istio-generated" [
|
||||||
{
|
{
|
||||||
|
|
||||||
istio = pkgs.linkFarm "istio-generated" [{
|
|
||||||
name = "latest.nix";
|
name = "latest.nix";
|
||||||
path = generateIstio;
|
path = generateIstio;
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
|
||||||
k8s = pkgs.linkFarm "k8s-generated" [
|
k8s = pkgs.linkFarm "k8s-generated" [
|
||||||
{
|
{
|
||||||
|
|
@ -50,5 +51,4 @@ in
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
{ pkgs ? import <nixpkgs> { }, lib ? pkgs.lib, spec ? ./istio-schema.json }:
|
{
|
||||||
|
pkgs ? import <nixpkgs> {},
|
||||||
with lib;
|
lib ? pkgs.lib,
|
||||||
let
|
spec ? ./istio-schema.json,
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
gen = rec {
|
gen = rec {
|
||||||
mkMerge = values: ''mkMerge [${concatMapStrings
|
mkMerge = values: ''mkMerge [${concatMapStrings
|
||||||
(value: "
|
(value: "
|
||||||
${value}
|
${value}
|
||||||
")
|
")
|
||||||
values}]'';
|
values}]'';
|
||||||
|
|
||||||
toNixString = value:
|
toNixString = value:
|
||||||
if isAttrs value || isList value
|
if isAttrs value || isList value
|
||||||
|
|
@ -20,12 +22,13 @@ values}]'';
|
||||||
|
|
||||||
removeEmptyLines = str: concatStringsSep "\n" (filter (l: (builtins.match "( |)+" l) == null) (splitString "\n" str));
|
removeEmptyLines = str: concatStringsSep "\n" (filter (l: (builtins.match "( |)+" l) == null) (splitString "\n" str));
|
||||||
|
|
||||||
mkOption =
|
mkOption = {
|
||||||
{ description ? null
|
description ? null,
|
||||||
, type ? null
|
type ? null,
|
||||||
, default ? null
|
default ? null,
|
||||||
, apply ? null
|
apply ? null,
|
||||||
}: removeEmptyLines ''mkOption {
|
}:
|
||||||
|
removeEmptyLines '' mkOption {
|
||||||
${optionalString (description != null) "description = ${builtins.toJSON description};"}
|
${optionalString (description != null) "description = ${builtins.toJSON description};"}
|
||||||
${optionalString (type != null) ''type = ${type};''}
|
${optionalString (type != null) ''type = ${type};''}
|
||||||
${optionalString (default != null) ''default = ${toNixString default};''}
|
${optionalString (default != null) ''default = ${toNixString default};''}
|
||||||
|
|
@ -43,140 +46,139 @@ values}]'';
|
||||||
nullOr = val: "(types.nullOr ${val})";
|
nullOr = val: "(types.nullOr ${val})";
|
||||||
attrsOf = val: "(types.attrsOf ${val})";
|
attrsOf = val: "(types.attrsOf ${val})";
|
||||||
listOf = val: "(types.listOf ${val})";
|
listOf = val: "(types.listOf ${val})";
|
||||||
coercedTo = coercedType: coerceFunc: finalType:
|
coercedTo = coercedType: coerceFunc: finalType: "(types.coercedTo ${coercedType} ${coerceFunc} ${finalType})";
|
||||||
"(types.coercedTo ${coercedType} ${coerceFunc} ${finalType})";
|
|
||||||
either = val1: val2: "(types.either ${val1} ${val2})";
|
either = val1: val2: "(types.either ${val1} ${val2})";
|
||||||
loaOf = type: "(types.loaOf ${type})";
|
loaOf = type: "(types.loaOf ${type})";
|
||||||
};
|
};
|
||||||
|
|
||||||
hasTypeMapping = def:
|
hasTypeMapping = def:
|
||||||
hasAttr "type" def &&
|
hasAttr "type" def
|
||||||
elem def.type [ "string" "integer" "boolean" ];
|
&& elem def.type ["string" "integer" "boolean"];
|
||||||
|
|
||||||
mergeValuesByKey = mergeKey: ''(mergeValuesByKey "${mergeKey}")'';
|
mergeValuesByKey = mergeKey: ''(mergeValuesByKey "${mergeKey}")'';
|
||||||
|
|
||||||
mapType = def:
|
mapType = def:
|
||||||
if def.type == "string" then
|
if def.type == "string"
|
||||||
|
then
|
||||||
if hasAttr "format" def && def.format == "int-or-string"
|
if hasAttr "format" def && def.format == "int-or-string"
|
||||||
then types.either types.int types.str
|
then types.either types.int types.str
|
||||||
else types.str
|
else types.str
|
||||||
else if def.type == "integer" then types.int
|
else if def.type == "integer"
|
||||||
else if def.type == "number" then types.int
|
then types.int
|
||||||
else if def.type == "boolean" then types.bool
|
else if def.type == "number"
|
||||||
else if def.type == "object" then types.attrs
|
then types.int
|
||||||
|
else if def.type == "boolean"
|
||||||
|
then types.bool
|
||||||
|
else if def.type == "object"
|
||||||
|
then types.attrs
|
||||||
else throw "type ${def.type} not supported";
|
else throw "type ${def.type} not supported";
|
||||||
|
|
||||||
submoduleOf = definitions: ref: ''(submoduleOf "${ref}")'';
|
submoduleOf = definitions: ref: ''(submoduleOf "${ref}")'';
|
||||||
|
|
||||||
submoduleForDefinition = ref: name: kind: group: version:
|
submoduleForDefinition = ref: name: kind: group: version: ''(submoduleForDefinition "${ref}" "${name}" "${kind}" "${group}" "${version}")'';
|
||||||
''(submoduleForDefinition "${ref}" "${name}" "${kind}" "${group}" "${version}")'';
|
|
||||||
|
|
||||||
coerceAttrsOfSubmodulesToListByKey = ref: mergeKey:
|
coerceAttrsOfSubmodulesToListByKey = ref: mergeKey: ''(coerceAttrsOfSubmodulesToListByKey "${ref}" "${mergeKey}")'';
|
||||||
''(coerceAttrsOfSubmodulesToListByKey "${ref}" "${mergeKey}")'';
|
|
||||||
|
|
||||||
attrsToList = "values: if values != null then mapAttrsToList (n: v: v) values else values";
|
attrsToList = "values: if values != null then mapAttrsToList (n: v: v) values else values";
|
||||||
|
|
||||||
refDefinition = attr: head (tail (tail (splitString "/" attr."$ref")));
|
refDefinition = attr: head (tail (tail (splitString "/" attr."$ref")));
|
||||||
};
|
};
|
||||||
|
|
||||||
fixJSON = content: replaceStrings [ "\\u" ] [ "u" ] content;
|
fixJSON = content: replaceStrings ["\\u"] ["u"] content;
|
||||||
|
|
||||||
fetchSpecs = path: builtins.fromJSON (fixJSON (builtins.readFile path));
|
fetchSpecs = path: builtins.fromJSON (fixJSON (builtins.readFile path));
|
||||||
|
|
||||||
genDefinitions = swagger: with gen; (mapAttrs
|
genDefinitions = swagger:
|
||||||
(name: definition:
|
with gen; (mapAttrs
|
||||||
|
(
|
||||||
|
name: definition:
|
||||||
# if $ref is in definition it means it's an alias of other definition
|
# if $ref is in definition it means it's an alias of other definition
|
||||||
if hasAttr "$ref" definition
|
if hasAttr "$ref" definition
|
||||||
then definitions."${refDefinition definition}"
|
then definitions."${refDefinition definition}"
|
||||||
|
|
||||||
else if !(hasAttr "properties" definition)
|
else if !(hasAttr "properties" definition)
|
||||||
then {
|
then {
|
||||||
type = mapType definition;
|
type = mapType definition;
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
options = mapAttrs
|
options =
|
||||||
(propName: property:
|
mapAttrs
|
||||||
let
|
(
|
||||||
isRequired = elem propName (definition.required or [ ]);
|
propName: property: let
|
||||||
requiredOrNot = type: if isRequired then type else types.nullOr type;
|
isRequired = elem propName (definition.required or []);
|
||||||
|
requiredOrNot = type:
|
||||||
|
if isRequired
|
||||||
|
then type
|
||||||
|
else types.nullOr type;
|
||||||
optionProperties =
|
optionProperties =
|
||||||
# if $ref is in property it references other definition,
|
# if $ref is in property it references other definition,
|
||||||
# but if other definition does not have properties, then just take it's type
|
# but if other definition does not have properties, then just take it's type
|
||||||
if hasAttr "$ref" property then
|
if hasAttr "$ref" property
|
||||||
if hasTypeMapping swagger.definitions.${refDefinition property} then {
|
then
|
||||||
|
if hasTypeMapping swagger.definitions.${refDefinition property}
|
||||||
|
then {
|
||||||
type = requiredOrNot (mapType swagger.definitions.${refDefinition property});
|
type = requiredOrNot (mapType swagger.definitions.${refDefinition property});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
type = requiredOrNot (submoduleOf definitions (refDefinition property));
|
type = requiredOrNot (submoduleOf definitions (refDefinition property));
|
||||||
}
|
}
|
||||||
|
else if !(hasAttr "type" property)
|
||||||
else if !(hasAttr "type" property) then {
|
then {
|
||||||
type = types.unspecified;
|
type = types.unspecified;
|
||||||
}
|
}
|
||||||
|
|
||||||
# if property has an array type
|
# if property has an array type
|
||||||
else if property.type == "array" then
|
else if property.type == "array"
|
||||||
|
then
|
||||||
# if reference is in items it can reference other type of another
|
# if reference is in items it can reference other type of another
|
||||||
# definition
|
# definition
|
||||||
if hasAttr "$ref" property.items then
|
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}
|
if hasTypeMapping swagger.definitions.${refDefinition property.items}
|
||||||
then {
|
then {
|
||||||
type = requiredOrNot (types.listOf (mapType swagger.definitions.${refDefinition property.items}.type));
|
type = requiredOrNot (types.listOf (mapType swagger.definitions.${refDefinition property.items}.type));
|
||||||
}
|
}
|
||||||
|
|
||||||
# if a reference is to complex type
|
# if a reference is to complex type
|
||||||
else
|
else
|
||||||
# if x-kubernetes-patch-merge-key is set then make it an
|
# if x-kubernetes-patch-merge-key is set then make it an
|
||||||
# attribute set of submodules
|
# attribute set of submodules
|
||||||
if hasAttr "x-kubernetes-patch-merge-key" property
|
if hasAttr "x-kubernetes-patch-merge-key" property
|
||||||
then
|
then let
|
||||||
let
|
|
||||||
mergeKey = property."x-kubernetes-patch-merge-key";
|
mergeKey = property."x-kubernetes-patch-merge-key";
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey);
|
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey);
|
||||||
apply = attrsToList;
|
apply = attrsToList;
|
||||||
}
|
}
|
||||||
|
|
||||||
# in other case it's a simple list
|
# in other case it's a simple list
|
||||||
else {
|
else {
|
||||||
type = requiredOrNot (types.listOf (submoduleOf definitions (refDefinition property.items)));
|
type = requiredOrNot (types.listOf (submoduleOf definitions (refDefinition property.items)));
|
||||||
}
|
}
|
||||||
|
|
||||||
# in other case it only references a simple type
|
# in other case it only references a simple type
|
||||||
else {
|
else {
|
||||||
type = requiredOrNot (types.listOf (mapType property.items));
|
type = requiredOrNot (types.listOf (mapType property.items));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if property.type == "object" && hasAttr "additionalProperties" property
|
else if property.type == "object" && hasAttr "additionalProperties" property
|
||||||
then
|
then
|
||||||
# if it is a reference to simple type
|
# if it is a reference to simple type
|
||||||
if (
|
if
|
||||||
hasAttr "$ref" property.additionalProperties &&
|
(
|
||||||
hasTypeMapping swagger.definitions.${refDefinition property.additionalProperties}
|
hasAttr "$ref" property.additionalProperties
|
||||||
) then {
|
&& hasTypeMapping swagger.definitions.${refDefinition property.additionalProperties}
|
||||||
|
)
|
||||||
|
then {
|
||||||
type = requiredOrNot (types.attrsOf (mapType swagger.definitions.${refDefinition property.additionalProperties}));
|
type = requiredOrNot (types.attrsOf (mapType swagger.definitions.${refDefinition property.additionalProperties}));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if hasAttr "$ref" property.additionalProperties
|
else if hasAttr "$ref" property.additionalProperties
|
||||||
then {
|
then {
|
||||||
type = requiredOrNot types.attrs;
|
type = requiredOrNot types.attrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
# if is an array
|
# if is an array
|
||||||
else if property.additionalProperties.type == "array"
|
else if property.additionalProperties.type == "array"
|
||||||
then {
|
then {
|
||||||
type = requiredOrNot (types.loaOf (mapType property.additionalProperties.items));
|
type = requiredOrNot (types.loaOf (mapType property.additionalProperties.items));
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
type = requiredOrNot (types.attrsOf (mapType property.additionalProperties));
|
type = requiredOrNot (types.attrsOf (mapType property.additionalProperties));
|
||||||
}
|
}
|
||||||
|
|
||||||
# just a simple property
|
# just a simple property
|
||||||
else {
|
else {
|
||||||
type = requiredOrNot (mapType property);
|
type = requiredOrNot (mapType property);
|
||||||
|
|
@ -184,14 +186,16 @@ values}]'';
|
||||||
in
|
in
|
||||||
mkOption ({
|
mkOption ({
|
||||||
description = property.description or "";
|
description = property.description or "";
|
||||||
} // optionProperties)
|
}
|
||||||
|
// optionProperties)
|
||||||
)
|
)
|
||||||
definition.properties;
|
definition.properties;
|
||||||
config =
|
config = let
|
||||||
let
|
optionalProps =
|
||||||
optionalProps = filterAttrs
|
filterAttrs
|
||||||
(propName: property:
|
(
|
||||||
!(elem propName (definition.required or [ ]))
|
propName: property:
|
||||||
|
!(elem propName (definition.required or []))
|
||||||
)
|
)
|
||||||
definition.properties;
|
definition.properties;
|
||||||
in
|
in
|
||||||
|
|
@ -200,7 +204,8 @@ values}]'';
|
||||||
)
|
)
|
||||||
swagger.definitions);
|
swagger.definitions);
|
||||||
|
|
||||||
genResources = swagger: (mapAttrsToList
|
genResources = swagger:
|
||||||
|
(mapAttrsToList
|
||||||
(name: property: rec {
|
(name: property: rec {
|
||||||
splittedType = splitString "." (removePrefix "me.snowdrop.istio.api." property.javaType);
|
splittedType = splitString "." (removePrefix "me.snowdrop.istio.api." property.javaType);
|
||||||
group = (concatStringsSep "." (take ((length splittedType) - 2) splittedType)) + ".istio.io";
|
group = (concatStringsSep "." (take ((length splittedType) - 2) splittedType)) + ".istio.io";
|
||||||
|
|
@ -209,11 +214,13 @@ values}]'';
|
||||||
ref = removePrefix "#/definitions/" property."$ref";
|
ref = removePrefix "#/definitions/" property."$ref";
|
||||||
})
|
})
|
||||||
(filterAttrs
|
(filterAttrs
|
||||||
(name: property:
|
(
|
||||||
(hasPrefix "me.snowdrop.istio.api" property.javaType) &&
|
name: property:
|
||||||
hasSuffix "Spec" property.javaType
|
(hasPrefix "me.snowdrop.istio.api" property.javaType)
|
||||||
|
&& hasSuffix "Spec" property.javaType
|
||||||
)
|
)
|
||||||
swagger.properties)) ++ (mapAttrsToList
|
swagger.properties))
|
||||||
|
++ (mapAttrsToList
|
||||||
(name: property: rec {
|
(name: property: rec {
|
||||||
splittedType = splitString "." (removePrefix "me.snowdrop.istio.mixer." property.javaType);
|
splittedType = splitString "." (removePrefix "me.snowdrop.istio.mixer." property.javaType);
|
||||||
group = "config.istio.io";
|
group = "config.istio.io";
|
||||||
|
|
@ -222,9 +229,10 @@ values}]'';
|
||||||
ref = removePrefix "#/definitions/" property."$ref";
|
ref = removePrefix "#/definitions/" property."$ref";
|
||||||
})
|
})
|
||||||
(filterAttrs
|
(filterAttrs
|
||||||
(name: property:
|
(
|
||||||
(hasPrefix "me.snowdrop.istio.mixer" property.javaType) &&
|
name: property:
|
||||||
hasSuffix "Spec" property.javaType
|
(hasPrefix "me.snowdrop.istio.mixer" property.javaType)
|
||||||
|
&& hasSuffix "Spec" property.javaType
|
||||||
)
|
)
|
||||||
swagger.properties));
|
swagger.properties));
|
||||||
|
|
||||||
|
|
@ -330,21 +338,24 @@ values}]'';
|
||||||
"${name}" = {${optionalString (hasAttr "options" value) "
|
"${name}" = {${optionalString (hasAttr "options" value) "
|
||||||
options = {${concatStrings (mapAttrsToList (name: value: ''
|
options = {${concatStrings (mapAttrsToList (name: value: ''
|
||||||
"${name}" = ${value};
|
"${name}" = ${value};
|
||||||
'') value.options)}};
|
'')
|
||||||
|
value.options)}};
|
||||||
"}
|
"}
|
||||||
|
|
||||||
${optionalString (hasAttr "config" value) ''
|
${optionalString (hasAttr "config" value) ''
|
||||||
config = {${concatStrings (mapAttrsToList (name: value: ''
|
config = {${concatStrings (mapAttrsToList (name: value: ''
|
||||||
"${name}" = ${value};
|
"${name}" = ${value};
|
||||||
'') value.config)}};
|
'')
|
||||||
|
value.config)}};
|
||||||
''}
|
''}
|
||||||
};
|
};
|
||||||
'') definitions)}
|
'')
|
||||||
|
definitions)}
|
||||||
} // (import ./overrides.nix {inheirt definitions lib;}));
|
} // (import ./overrides.nix {inheirt definitions lib;}));
|
||||||
in {
|
in {
|
||||||
kubernetes.customResources = [
|
kubernetes.customResources = [
|
||||||
${concatMapStrings
|
${concatMapStrings
|
||||||
(resource: ''{
|
(resource: '' {
|
||||||
group = "${resource.group}";
|
group = "${resource.group}";
|
||||||
version = "${resource.version}";
|
version = "${resource.version}";
|
||||||
kind = "${resource.kind}";
|
kind = "${resource.kind}";
|
||||||
|
|
@ -354,16 +365,16 @@ values}]'';
|
||||||
(genResources swagger)}
|
(genResources swagger)}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
in
|
in
|
||||||
pkgs.runCommand "istio-gen.nix"
|
pkgs.runCommand "istio-gen.nix"
|
||||||
{
|
{
|
||||||
buildInputs = [ pkgs.nixpkgs-fmt ];
|
buildInputs = [pkgs.nixpkgs-fmt];
|
||||||
} ''
|
} ''
|
||||||
cat << 'GENERATED' > ./raw
|
cat << 'GENERATED' > ./raw
|
||||||
"${generated}"
|
"${generated}"
|
||||||
GENERATED
|
GENERATED
|
||||||
|
|
||||||
nixpkgs-fmt ./raw
|
nixpkgs-fmt ./raw
|
||||||
cp ./raw $out
|
cp ./raw $out
|
||||||
''
|
''
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,16 @@
|
||||||
{ name
|
{
|
||||||
, pkgs
|
name,
|
||||||
, lib
|
pkgs,
|
||||||
, spec
|
lib,
|
||||||
|
spec,
|
||||||
}:
|
}:
|
||||||
|
with lib; let
|
||||||
with lib;
|
|
||||||
let
|
|
||||||
gen = rec {
|
gen = rec {
|
||||||
mkMerge = values: ''mkMerge [${concatMapStrings
|
mkMerge = values: ''mkMerge [${concatMapStrings
|
||||||
(value: "
|
(value: "
|
||||||
${value}
|
${value}
|
||||||
")
|
")
|
||||||
values}]'';
|
values}]'';
|
||||||
|
|
||||||
toNixString = value:
|
toNixString = value:
|
||||||
if isAttrs value || isList value
|
if isAttrs value || isList value
|
||||||
|
|
@ -24,12 +23,13 @@ values}]'';
|
||||||
|
|
||||||
removeEmptyLines = str: concatStringsSep "\n" (filter (l: (builtins.match "( |)+" l) == null) (splitString "\n" str));
|
removeEmptyLines = str: concatStringsSep "\n" (filter (l: (builtins.match "( |)+" l) == null) (splitString "\n" str));
|
||||||
|
|
||||||
mkOption =
|
mkOption = {
|
||||||
{ description ? null
|
description ? null,
|
||||||
, type ? null
|
type ? null,
|
||||||
, default ? null
|
default ? null,
|
||||||
, apply ? null
|
apply ? null,
|
||||||
}: removeEmptyLines ''mkOption {
|
}:
|
||||||
|
removeEmptyLines '' mkOption {
|
||||||
${optionalString (description != null) "description = ${builtins.toJSON description};"}
|
${optionalString (description != null) "description = ${builtins.toJSON description};"}
|
||||||
${optionalString (type != null) ''type = ${type};''}
|
${optionalString (type != null) ''type = ${type};''}
|
||||||
${optionalString (default != null) ''default = ${toNixString default};''}
|
${optionalString (default != null) ''default = ${toNixString default};''}
|
||||||
|
|
@ -47,36 +47,38 @@ values}]'';
|
||||||
nullOr = val: "(types.nullOr ${val})";
|
nullOr = val: "(types.nullOr ${val})";
|
||||||
attrsOf = val: "(types.attrsOf ${val})";
|
attrsOf = val: "(types.attrsOf ${val})";
|
||||||
listOf = val: "(types.listOf ${val})";
|
listOf = val: "(types.listOf ${val})";
|
||||||
coercedTo = coercedType: coerceFunc: finalType:
|
coercedTo = coercedType: coerceFunc: finalType: "(types.coercedTo ${coercedType} ${coerceFunc} ${finalType})";
|
||||||
"(types.coercedTo ${coercedType} ${coerceFunc} ${finalType})";
|
|
||||||
either = val1: val2: "(types.either ${val1} ${val2})";
|
either = val1: val2: "(types.either ${val1} ${val2})";
|
||||||
loaOf = type: "(types.loaOf ${type})";
|
loaOf = type: "(types.loaOf ${type})";
|
||||||
};
|
};
|
||||||
|
|
||||||
hasTypeMapping = def:
|
hasTypeMapping = def:
|
||||||
hasAttr "type" def &&
|
hasAttr "type" def
|
||||||
elem def.type [ "string" "integer" "boolean" ];
|
&& elem def.type ["string" "integer" "boolean"];
|
||||||
|
|
||||||
mergeValuesByKey = mergeKey: ''(mergeValuesByKey "${mergeKey}")'';
|
mergeValuesByKey = mergeKey: ''(mergeValuesByKey "${mergeKey}")'';
|
||||||
|
|
||||||
mapType = def:
|
mapType = def:
|
||||||
if def.type == "string" then
|
if def.type == "string"
|
||||||
|
then
|
||||||
if hasAttr "format" def && def.format == "int-or-string"
|
if hasAttr "format" def && def.format == "int-or-string"
|
||||||
then types.either types.int types.str
|
then types.either types.int types.str
|
||||||
else types.str
|
else types.str
|
||||||
else if def.type == "integer" then types.int
|
else if def.type == "integer"
|
||||||
else if def.type == "number" then types.int
|
then types.int
|
||||||
else if def.type == "boolean" then types.bool
|
else if def.type == "number"
|
||||||
else if def.type == "object" then types.attrs
|
then types.int
|
||||||
|
else if def.type == "boolean"
|
||||||
|
then types.bool
|
||||||
|
else if def.type == "object"
|
||||||
|
then types.attrs
|
||||||
else throw "type ${def.type} not supported";
|
else throw "type ${def.type} not supported";
|
||||||
|
|
||||||
submoduleOf = definitions: ref: ''(submoduleOf "${ref}")'';
|
submoduleOf = definitions: ref: ''(submoduleOf "${ref}")'';
|
||||||
|
|
||||||
submoduleForDefinition = ref: name: kind: group: version:
|
submoduleForDefinition = ref: name: kind: group: version: ''(submoduleForDefinition "${ref}" "${name}" "${kind}" "${group}" "${version}")'';
|
||||||
''(submoduleForDefinition "${ref}" "${name}" "${kind}" "${group}" "${version}")'';
|
|
||||||
|
|
||||||
coerceAttrsOfSubmodulesToListByKey = ref: mergeKey:
|
coerceAttrsOfSubmodulesToListByKey = ref: mergeKey: ''(coerceAttrsOfSubmodulesToListByKey "${ref}" "${mergeKey}")'';
|
||||||
''(coerceAttrsOfSubmodulesToListByKey "${ref}" "${mergeKey}")'';
|
|
||||||
|
|
||||||
attrsToList = "values: if values != null then mapAttrsToList (n: v: v) values else values";
|
attrsToList = "values: if values != null then mapAttrsToList (n: v: v) values else values";
|
||||||
|
|
||||||
|
|
@ -85,14 +87,15 @@ values}]'';
|
||||||
|
|
||||||
refType = attr: head (tail (tail (splitString "/" attr."$ref")));
|
refType = attr: head (tail (tail (splitString "/" attr."$ref")));
|
||||||
|
|
||||||
compareVersions = ver1: ver2:
|
compareVersions = ver1: ver2: let
|
||||||
let
|
|
||||||
getVersion = v: substring 1 10 v;
|
getVersion = v: substring 1 10 v;
|
||||||
splitVersion = v: builtins.splitVersion (getVersion v);
|
splitVersion = v: builtins.splitVersion (getVersion v);
|
||||||
isAlpha = v: elem "alpha" (splitVersion v);
|
isAlpha = v: elem "alpha" (splitVersion v);
|
||||||
patchVersion = v:
|
patchVersion = v:
|
||||||
if isAlpha v then ""
|
if isAlpha v
|
||||||
else if length (splitVersion v) == 1 then "${getVersion v}prod"
|
then ""
|
||||||
|
else if length (splitVersion v) == 1
|
||||||
|
then "${getVersion v}prod"
|
||||||
else getVersion v;
|
else getVersion v;
|
||||||
|
|
||||||
v1 = patchVersion ver1;
|
v1 = patchVersion ver1;
|
||||||
|
|
@ -100,100 +103,97 @@ values}]'';
|
||||||
in
|
in
|
||||||
builtins.compareVersions v1 v2;
|
builtins.compareVersions v1 v2;
|
||||||
|
|
||||||
fixJSON = content: replaceStrings [ "\\u" ] [ "u" ] content;
|
fixJSON = content: replaceStrings ["\\u"] ["u"] content;
|
||||||
|
|
||||||
fetchSpecs = path: builtins.fromJSON (fixJSON (builtins.readFile path));
|
fetchSpecs = path: builtins.fromJSON (fixJSON (builtins.readFile path));
|
||||||
|
|
||||||
genDefinitions = swagger: with gen; mapAttrs
|
genDefinitions = swagger:
|
||||||
(name: definition:
|
with gen;
|
||||||
|
mapAttrs
|
||||||
|
(
|
||||||
|
name: definition:
|
||||||
# if $ref is in definition it means it's an alias of other definition
|
# if $ref is in definition it means it's an alias of other definition
|
||||||
if hasAttr "$ref" definition
|
if hasAttr "$ref" definition
|
||||||
then definitions."${refDefinition definition}"
|
then definitions."${refDefinition definition}"
|
||||||
|
|
||||||
else if !(hasAttr "properties" definition)
|
else if !(hasAttr "properties" definition)
|
||||||
then { }
|
then {}
|
||||||
|
|
||||||
# in other case it's an actual definition
|
# in other case it's an actual definition
|
||||||
else {
|
else {
|
||||||
options = mapAttrs
|
options =
|
||||||
(propName: property:
|
mapAttrs
|
||||||
let
|
(
|
||||||
isRequired = elem propName (definition.required or [ ]);
|
propName: property: let
|
||||||
requiredOrNot = type: if isRequired then type else types.nullOr type;
|
isRequired = elem propName (definition.required or []);
|
||||||
|
requiredOrNot = type:
|
||||||
|
if isRequired
|
||||||
|
then type
|
||||||
|
else types.nullOr type;
|
||||||
optionProperties =
|
optionProperties =
|
||||||
|
|
||||||
# if $ref is in property it references other definition,
|
# if $ref is in property it references other definition,
|
||||||
# but if other definition does not have properties, then just take it's type
|
# but if other definition does not have properties, then just take it's type
|
||||||
if hasAttr "$ref" property then
|
if hasAttr "$ref" property
|
||||||
if hasTypeMapping swagger.definitions.${refDefinition property} then {
|
then
|
||||||
|
if hasTypeMapping swagger.definitions.${refDefinition property}
|
||||||
|
then {
|
||||||
type = requiredOrNot (mapType swagger.definitions.${refDefinition property});
|
type = requiredOrNot (mapType swagger.definitions.${refDefinition property});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
type = requiredOrNot (submoduleOf definitions (refDefinition property));
|
type = requiredOrNot (submoduleOf definitions (refDefinition property));
|
||||||
}
|
}
|
||||||
|
|
||||||
# if property has an array type
|
# if property has an array type
|
||||||
else if property.type == "array" then
|
else if property.type == "array"
|
||||||
|
then
|
||||||
# if reference is in items it can reference other type of another
|
# if reference is in items it can reference other type of another
|
||||||
# definition
|
# definition
|
||||||
if hasAttr "$ref" property.items then
|
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}
|
if hasTypeMapping swagger.definitions.${refDefinition property.items}
|
||||||
then {
|
then {
|
||||||
type = requiredOrNot (types.listOf (mapType swagger.definitions.${refDefinition property.items}.type));
|
type = requiredOrNot (types.listOf (mapType swagger.definitions.${refDefinition property.items}.type));
|
||||||
}
|
}
|
||||||
|
|
||||||
# if a reference is to complex type
|
# if a reference is to complex type
|
||||||
else
|
else
|
||||||
# if x-kubernetes-patch-merge-key is set then make it an
|
# if x-kubernetes-patch-merge-key is set then make it an
|
||||||
# attribute set of submodules
|
# attribute set of submodules
|
||||||
if hasAttr "x-kubernetes-patch-merge-key" property
|
if hasAttr "x-kubernetes-patch-merge-key" property
|
||||||
then
|
then let
|
||||||
let
|
|
||||||
mergeKey = property."x-kubernetes-patch-merge-key";
|
mergeKey = property."x-kubernetes-patch-merge-key";
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey);
|
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey);
|
||||||
apply = attrsToList;
|
apply = attrsToList;
|
||||||
}
|
}
|
||||||
|
|
||||||
# in other case it's a simple list
|
# in other case it's a simple list
|
||||||
else {
|
else {
|
||||||
type = requiredOrNot (types.listOf (submoduleOf definitions (refDefinition property.items)));
|
type = requiredOrNot (types.listOf (submoduleOf definitions (refDefinition property.items)));
|
||||||
}
|
}
|
||||||
|
|
||||||
# in other case it only references a simple type
|
# in other case it only references a simple type
|
||||||
else {
|
else {
|
||||||
type = requiredOrNot (types.listOf (mapType property.items));
|
type = requiredOrNot (types.listOf (mapType property.items));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if property.type == "object" && hasAttr "additionalProperties" property
|
else if property.type == "object" && hasAttr "additionalProperties" property
|
||||||
then
|
then
|
||||||
# if it is a reference to simple type
|
# if it is a reference to simple type
|
||||||
if (
|
if
|
||||||
hasAttr "$ref" property.additionalProperties &&
|
(
|
||||||
hasTypeMapping swagger.definitions.${refDefinition property.additionalProperties}
|
hasAttr "$ref" property.additionalProperties
|
||||||
) then {
|
&& hasTypeMapping swagger.definitions.${refDefinition property.additionalProperties}
|
||||||
|
)
|
||||||
|
then {
|
||||||
type = requiredOrNot (types.attrsOf (mapType swagger.definitions.${refDefinition property.additionalProperties}));
|
type = requiredOrNot (types.attrsOf (mapType swagger.definitions.${refDefinition property.additionalProperties}));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if hasAttr "$ref" property.additionalProperties
|
else if hasAttr "$ref" property.additionalProperties
|
||||||
then {
|
then {
|
||||||
type = requiredOrNot types.attrs;
|
type = requiredOrNot types.attrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
# if is an array
|
# if is an array
|
||||||
else if property.additionalProperties.type == "array"
|
else if property.additionalProperties.type == "array"
|
||||||
then {
|
then {
|
||||||
type = requiredOrNot (types.loaOf (mapType property.additionalProperties.items));
|
type = requiredOrNot (types.loaOf (mapType property.additionalProperties.items));
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
type = requiredOrNot (types.attrsOf (mapType property.additionalProperties));
|
type = requiredOrNot (types.attrsOf (mapType property.additionalProperties));
|
||||||
}
|
}
|
||||||
|
|
||||||
# just a simple property
|
# just a simple property
|
||||||
else {
|
else {
|
||||||
type = requiredOrNot (mapType property);
|
type = requiredOrNot (mapType property);
|
||||||
|
|
@ -201,14 +201,16 @@ values}]'';
|
||||||
in
|
in
|
||||||
mkOption ({
|
mkOption ({
|
||||||
description = property.description or "";
|
description = property.description or "";
|
||||||
} // optionProperties)
|
}
|
||||||
|
// optionProperties)
|
||||||
)
|
)
|
||||||
definition.properties;
|
definition.properties;
|
||||||
config =
|
config = let
|
||||||
let
|
optionalProps =
|
||||||
optionalProps = filterAttrs
|
filterAttrs
|
||||||
(propName: property:
|
(
|
||||||
!(elem propName (definition.required or [ ]))
|
propName: property:
|
||||||
|
!(elem propName (definition.required or []))
|
||||||
)
|
)
|
||||||
definition.properties;
|
definition.properties;
|
||||||
in
|
in
|
||||||
|
|
@ -217,26 +219,36 @@ values}]'';
|
||||||
)
|
)
|
||||||
swagger.definitions;
|
swagger.definitions;
|
||||||
|
|
||||||
mapCharPairs = f: s1: s2: concatStrings (imap0
|
mapCharPairs = f: s1: s2:
|
||||||
(i: c1:
|
concatStrings (imap0
|
||||||
f i c1 (if i >= stringLength s2 then "" else elemAt (stringToCharacters s2) i)
|
(
|
||||||
|
i: c1:
|
||||||
|
f i c1 (
|
||||||
|
if i >= stringLength s2
|
||||||
|
then ""
|
||||||
|
else elemAt (stringToCharacters s2) i
|
||||||
|
)
|
||||||
)
|
)
|
||||||
(stringToCharacters s1));
|
(stringToCharacters s1));
|
||||||
|
|
||||||
getAttrName = resource: kind:
|
getAttrName = resource: kind:
|
||||||
mapCharPairs
|
mapCharPairs
|
||||||
(i: c1: c2:
|
(
|
||||||
if hasPrefix "API" kind && i == 0 then "A"
|
i: c1: c2:
|
||||||
else if i == 0 then c1
|
if hasPrefix "API" kind && i == 0
|
||||||
else if c2 == "" || (toLower c2) != c1 then c1
|
then "A"
|
||||||
|
else if i == 0
|
||||||
|
then c1
|
||||||
|
else if c2 == "" || (toLower c2) != c1
|
||||||
|
then c1
|
||||||
else c2
|
else c2
|
||||||
)
|
)
|
||||||
resource
|
resource
|
||||||
kind;
|
kind;
|
||||||
|
|
||||||
genResourceTypes = swagger: mapAttrs'
|
genResourceTypes = swagger:
|
||||||
(name: path:
|
mapAttrs'
|
||||||
let
|
(name: path: let
|
||||||
ref = refType (head path.post.parameters).schema;
|
ref = refType (head path.post.parameters).schema;
|
||||||
group' = path.post."x-kubernetes-group-version-kind".group;
|
group' = path.post."x-kubernetes-group-version-kind".group;
|
||||||
version' = path.post."x-kubernetes-group-version-kind".version;
|
version' = path.post."x-kubernetes-group-version-kind".version;
|
||||||
|
|
@ -248,16 +260,20 @@ values}]'';
|
||||||
inherit ref attrName;
|
inherit ref attrName;
|
||||||
|
|
||||||
name = name';
|
name = name';
|
||||||
group = if group' == "" then "core" else group';
|
group =
|
||||||
|
if group' == ""
|
||||||
|
then "core"
|
||||||
|
else group';
|
||||||
version = version';
|
version = version';
|
||||||
kind = kind';
|
kind = kind';
|
||||||
description = swagger.definitions.${ref}.description;
|
description = swagger.definitions.${ref}.description;
|
||||||
defintion = refDefinition (head path.post.parameters).schema;
|
defintion = refDefinition (head path.post.parameters).schema;
|
||||||
})
|
})
|
||||||
(filterAttrs
|
(filterAttrs
|
||||||
(name: path:
|
(
|
||||||
hasAttr "post" path &&
|
name: path:
|
||||||
path.post."x-kubernetes-action" == "post"
|
hasAttr "post" path
|
||||||
|
&& path.post."x-kubernetes-action" == "post"
|
||||||
)
|
)
|
||||||
swagger.paths);
|
swagger.paths);
|
||||||
|
|
||||||
|
|
@ -271,10 +287,13 @@ values}]'';
|
||||||
})
|
})
|
||||||
resourceTypes);
|
resourceTypes);
|
||||||
|
|
||||||
resourcesTypesByKindSortByVersion = mapAttrs
|
resourcesTypesByKindSortByVersion =
|
||||||
(kind: resourceTypes:
|
mapAttrs
|
||||||
|
(
|
||||||
|
kind: resourceTypes:
|
||||||
reverseList (sort
|
reverseList (sort
|
||||||
(r1: r2:
|
(
|
||||||
|
r1: r2:
|
||||||
compareVersions r1.version r2.version > 0
|
compareVersions r1.version r2.version > 0
|
||||||
)
|
)
|
||||||
resourceTypes)
|
resourceTypes)
|
||||||
|
|
@ -284,9 +303,9 @@ values}]'';
|
||||||
latestResourceTypesByKind =
|
latestResourceTypesByKind =
|
||||||
mapAttrs (kind: resources: last resources) resourcesTypesByKindSortByVersion;
|
mapAttrs (kind: resources: last resources) resourcesTypesByKindSortByVersion;
|
||||||
|
|
||||||
genResourceOptions = resource: with gen; let
|
genResourceOptions = resource:
|
||||||
submoduleForDefinition' = definition:
|
with gen; let
|
||||||
let
|
submoduleForDefinition' = definition: let
|
||||||
in
|
in
|
||||||
submoduleForDefinition
|
submoduleForDefinition
|
||||||
definition.ref
|
definition.ref
|
||||||
|
|
@ -298,7 +317,7 @@ values}]'';
|
||||||
mkOption {
|
mkOption {
|
||||||
description = resource.description;
|
description = resource.description;
|
||||||
type = types.attrsOf (submoduleForDefinition' resource);
|
type = types.attrsOf (submoduleForDefinition' resource);
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
generated = ''
|
generated = ''
|
||||||
|
|
@ -405,16 +424,19 @@ values}]'';
|
||||||
${optionalString (hasAttr "options" value) "
|
${optionalString (hasAttr "options" value) "
|
||||||
options = {${concatStrings (mapAttrsToList (name: value: ''
|
options = {${concatStrings (mapAttrsToList (name: value: ''
|
||||||
"${name}" = ${value};
|
"${name}" = ${value};
|
||||||
'') value.options)}};
|
'')
|
||||||
|
value.options)}};
|
||||||
"}
|
"}
|
||||||
|
|
||||||
${optionalString (hasAttr "config" value) ''
|
${optionalString (hasAttr "config" value) ''
|
||||||
config = {${concatStrings (mapAttrsToList (name: value: ''
|
config = {${concatStrings (mapAttrsToList (name: value: ''
|
||||||
"${name}" = ${value};
|
"${name}" = ${value};
|
||||||
'') value.config)}};
|
'')
|
||||||
|
value.config)}};
|
||||||
''}
|
''}
|
||||||
};
|
};
|
||||||
'') definitions)}
|
'')
|
||||||
|
definitions)}
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
# all resource versions
|
# all resource versions
|
||||||
|
|
@ -422,11 +444,13 @@ values}]'';
|
||||||
resources = {
|
resources = {
|
||||||
${concatStrings (mapAttrsToList (_: rt: ''
|
${concatStrings (mapAttrsToList (_: rt: ''
|
||||||
"${rt.group}"."${rt.version}"."${rt.kind}" = ${genResourceOptions rt};
|
"${rt.group}"."${rt.version}"."${rt.kind}" = ${genResourceOptions rt};
|
||||||
'') resourceTypes)}
|
'')
|
||||||
|
resourceTypes)}
|
||||||
} // {
|
} // {
|
||||||
${concatStrings (mapAttrsToList (_: rt: ''
|
${concatStrings (mapAttrsToList (_: rt: ''
|
||||||
"${rt.attrName}" = ${genResourceOptions rt};
|
"${rt.attrName}" = ${genResourceOptions rt};
|
||||||
'') latestResourceTypesByKind)}
|
'')
|
||||||
|
latestResourceTypesByKind)}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -435,32 +459,34 @@ values}]'';
|
||||||
inherit definitions;
|
inherit definitions;
|
||||||
|
|
||||||
# register resource types
|
# register resource types
|
||||||
types = [${concatStrings (mapAttrsToList (_: rt: ''{
|
types = [${concatStrings (mapAttrsToList (_: rt: '' {
|
||||||
name = "${rt.name}";
|
name = "${rt.name}";
|
||||||
group = "${rt.group}";
|
group = "${rt.group}";
|
||||||
version = "${rt.version}";
|
version = "${rt.version}";
|
||||||
kind = "${rt.kind}";
|
kind = "${rt.kind}";
|
||||||
attrName = "${rt.attrName}";
|
attrName = "${rt.attrName}";
|
||||||
}'') resourceTypes)}];
|
}'')
|
||||||
|
resourceTypes)}];
|
||||||
|
|
||||||
resources = {
|
resources = {
|
||||||
${concatStrings (mapAttrsToList (_: rt: ''
|
${concatStrings (mapAttrsToList (_: rt: ''
|
||||||
"${rt.group}"."${rt.version}"."${rt.kind}" =
|
"${rt.group}"."${rt.version}"."${rt.kind}" =
|
||||||
mkAliasDefinitions options.resources."${rt.attrName}";
|
mkAliasDefinitions options.resources."${rt.attrName}";
|
||||||
'') latestResourceTypesByKind)}
|
'')
|
||||||
|
latestResourceTypesByKind)}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
in
|
in
|
||||||
pkgs.runCommand "k8s-${name}-gen.nix"
|
pkgs.runCommand "k8s-${name}-gen.nix"
|
||||||
{
|
{
|
||||||
buildInputs = [ pkgs.nixpkgs-fmt ];
|
buildInputs = [pkgs.nixpkgs-fmt];
|
||||||
} ''
|
} ''
|
||||||
cat << 'GENERATED' > ./raw
|
cat << 'GENERATED' > ./raw
|
||||||
"${generated}"
|
"${generated}"
|
||||||
GENERATED
|
GENERATED
|
||||||
|
|
||||||
nixpkgs-fmt ./raw
|
nixpkgs-fmt ./raw
|
||||||
cp ./raw $out
|
cp ./raw $out
|
||||||
''
|
''
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{ lib, pkgs }:
|
|
||||||
|
|
||||||
{
|
{
|
||||||
k8s = import ./k8s { inherit lib; };
|
lib,
|
||||||
docker = import ./docker { inherit lib pkgs; };
|
pkgs,
|
||||||
helm = import ./helm { inherit pkgs; };
|
}: {
|
||||||
|
k8s = import ./k8s {inherit lib;};
|
||||||
|
docker = import ./docker {inherit lib pkgs;};
|
||||||
|
helm = import ./helm {inherit pkgs;};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,13 @@
|
||||||
{ lib, pkgs }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
copyDockerImages = { images, dest, args ? "" }:
|
lib,
|
||||||
|
pkgs,
|
||||||
|
}:
|
||||||
|
with lib; {
|
||||||
|
copyDockerImages = {
|
||||||
|
images,
|
||||||
|
dest,
|
||||||
|
args ? "",
|
||||||
|
}:
|
||||||
pkgs.writeScript "copy-docker-images.sh" (concatMapStrings
|
pkgs.writeScript "copy-docker-images.sh" (concatMapStrings
|
||||||
(image: ''
|
(image: ''
|
||||||
#!${pkgs.runtimeShell}
|
#!${pkgs.runtimeShell}
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,34 @@
|
||||||
{ stdenvNoCC, lib, kubernetes-helm, gawk, remarshal, jq }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
# chart to template
|
stdenvNoCC,
|
||||||
chart
|
lib,
|
||||||
|
kubernetes-helm,
|
||||||
# release name
|
gawk,
|
||||||
, name
|
remarshal,
|
||||||
|
jq,
|
||||||
# namespace to install release into
|
|
||||||
, namespace ? null
|
|
||||||
|
|
||||||
# values to pass to chart
|
|
||||||
, values ? { }
|
|
||||||
|
|
||||||
# kubernetes version to template chart for
|
|
||||||
, kubeVersion ? null
|
|
||||||
}:
|
}:
|
||||||
let
|
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,
|
||||||
|
}: let
|
||||||
valuesJsonFile = builtins.toFile "${name}-values.json" (builtins.toJSON values);
|
valuesJsonFile = builtins.toFile "${name}-values.json" (builtins.toJSON values);
|
||||||
in
|
in
|
||||||
stdenvNoCC.mkDerivation {
|
stdenvNoCC.mkDerivation {
|
||||||
name = "${name}.json";
|
name = "${name}.json";
|
||||||
buildCommand = ''
|
buildCommand = ''
|
||||||
# template helm file and write resources to yaml
|
# template helm file and write resources to yaml
|
||||||
helm template "${name}" \
|
helm template "${name}" \
|
||||||
${optionalString (kubeVersion != null) "--api-versions ${kubeVersion}"} \
|
${optionalString (kubeVersion != null) "--api-versions ${kubeVersion}"} \
|
||||||
${optionalString (namespace != null) "--namespace ${namespace}"} \
|
${optionalString (namespace != null) "--namespace ${namespace}"} \
|
||||||
${optionalString (values != { }) "-f ${valuesJsonFile}"} \
|
${optionalString (values != {}) "-f ${valuesJsonFile}"} \
|
||||||
${chart} >resources.yaml
|
${chart} >resources.yaml
|
||||||
|
|
||||||
# split multy yaml file into multiple files
|
# split multy yaml file into multiple files
|
||||||
|
|
@ -50,5 +50,5 @@ stdenvNoCC.mkDerivation {
|
||||||
.
|
.
|
||||||
end)' > $out
|
end)' > $out
|
||||||
'';
|
'';
|
||||||
nativeBuildInputs = [ kubernetes-helm gawk remarshal jq ];
|
nativeBuildInputs = [kubernetes-helm gawk remarshal jq];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
{ pkgs }:
|
{pkgs}: {
|
||||||
|
chart2json = pkgs.callPackage ./chart2json.nix {};
|
||||||
{
|
fetch = pkgs.callPackage ./fetchhelm.nix {};
|
||||||
chart2json = pkgs.callPackage ./chart2json.nix { };
|
|
||||||
fetch = pkgs.callPackage ./fetchhelm.nix { };
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,50 +1,80 @@
|
||||||
{ stdenvNoCC, lib, kubernetes-helm, cacert }:
|
|
||||||
let
|
|
||||||
cleanName = name: lib.replaceStrings [ "/" ] [ "-" ] name;
|
|
||||||
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
|
stdenvNoCC,
|
||||||
|
lib,
|
||||||
|
kubernetes-helm,
|
||||||
|
cacert,
|
||||||
|
}: let
|
||||||
|
cleanName = name: lib.replaceStrings ["/"] ["-"] name;
|
||||||
|
in
|
||||||
|
{
|
||||||
# name of the chart
|
# name of the chart
|
||||||
chart
|
chart,
|
||||||
|
|
||||||
# chart url to fetch from custom location
|
# chart url to fetch from custom location
|
||||||
, chartUrl ? null
|
chartUrl ? null,
|
||||||
|
|
||||||
# version of the chart
|
# version of the chart
|
||||||
, version ? null
|
version ? null,
|
||||||
|
|
||||||
# chart hash
|
# chart hash
|
||||||
, sha256
|
sha256,
|
||||||
|
|
||||||
# whether to extract chart
|
# whether to extract chart
|
||||||
, untar ? true
|
untar ? true,
|
||||||
|
|
||||||
# use custom charts repo
|
# use custom charts repo
|
||||||
, repo ? null
|
repo ? null,
|
||||||
|
|
||||||
# pass --verify to helm chart
|
# pass --verify to helm chart
|
||||||
, verify ? false
|
verify ? false,
|
||||||
|
|
||||||
# pass --devel to helm chart
|
# pass --devel to helm chart
|
||||||
, devel ? false
|
devel ? false,
|
||||||
}: stdenvNoCC.mkDerivation {
|
}:
|
||||||
name = "${cleanName chart}-${if version == null then "dev" else version}";
|
stdenvNoCC.mkDerivation {
|
||||||
|
name = "${cleanName chart}-${
|
||||||
|
if version == null
|
||||||
|
then "dev"
|
||||||
|
else version
|
||||||
|
}";
|
||||||
|
|
||||||
buildCommand = ''
|
buildCommand = ''
|
||||||
export HOME="$PWD"
|
export HOME="$PWD"
|
||||||
echo "adding helm repo"
|
echo "adding helm repo"
|
||||||
${if repo == null then "" else "helm repo add repository ${repo}"}
|
${
|
||||||
|
if repo == null
|
||||||
|
then ""
|
||||||
|
else "helm repo add repository ${repo}"
|
||||||
|
}
|
||||||
echo "fetching helm chart"
|
echo "fetching helm chart"
|
||||||
helm fetch -d ./chart \
|
helm fetch -d ./chart \
|
||||||
${if untar then "--untar" else ""} \
|
${
|
||||||
${if version == null then "" else "--version ${version}"} \
|
if untar
|
||||||
${if devel then "--devel" else ""} \
|
then "--untar"
|
||||||
${if verify then "--verify" else ""} \
|
else ""
|
||||||
${if chartUrl == null then (if repo == null then chart else "repository/${chart}") else chartUrl}
|
} \
|
||||||
|
${
|
||||||
|
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
|
cp -r chart/*/ $out
|
||||||
'';
|
'';
|
||||||
outputHashMode = "recursive";
|
outputHashMode = "recursive";
|
||||||
outputHashAlgo = "sha256";
|
outputHashAlgo = "sha256";
|
||||||
outputHash = sha256;
|
outputHash = sha256;
|
||||||
nativeBuildInputs = [ kubernetes-helm cacert ];
|
nativeBuildInputs = [kubernetes-helm cacert];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
{ pkgs ? import <nixpkgs> { } }:
|
{pkgs ? import <nixpkgs> {}}: let
|
||||||
let
|
fetchhelm = pkgs.callPackage ./fetchhelm.nix {};
|
||||||
fetchhelm = pkgs.callPackage ./fetchhelm.nix { };
|
chart2json = pkgs.callPackage ./chart2json.nix {};
|
||||||
chart2json = pkgs.callPackage ./chart2json.nix { };
|
in rec {
|
||||||
in
|
|
||||||
rec {
|
|
||||||
postgresql-chart = fetchhelm {
|
postgresql-chart = fetchhelm {
|
||||||
chart = "stable/postgresql";
|
chart = "stable/postgresql";
|
||||||
version = "0.18.1";
|
version = "0.18.1";
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,42 @@
|
||||||
{ lib }:
|
{lib}:
|
||||||
|
with lib; rec {
|
||||||
with lib;
|
|
||||||
|
|
||||||
rec {
|
|
||||||
# TODO: refactor with mkOptionType
|
# TODO: refactor with mkOptionType
|
||||||
mkSecretOption = { description ? "", default ? { }, allowNull ? true }: mkOption {
|
mkSecretOption = {
|
||||||
|
description ? "",
|
||||||
|
default ? {},
|
||||||
|
allowNull ? true,
|
||||||
|
}:
|
||||||
|
mkOption {
|
||||||
inherit description;
|
inherit description;
|
||||||
type = (if allowNull then types.nullOr else id) (types.submodule {
|
type =
|
||||||
|
(
|
||||||
|
if allowNull
|
||||||
|
then types.nullOr
|
||||||
|
else id
|
||||||
|
) (types.submodule {
|
||||||
options = {
|
options = {
|
||||||
name = mkOption ({
|
name = mkOption ({
|
||||||
description = "Name of the secret where secret is stored";
|
description = "Name of the secret where secret is stored";
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = default.name;
|
default = default.name;
|
||||||
} // (optionalAttrs (default ? "name") {
|
}
|
||||||
|
// (optionalAttrs (default ? "name") {
|
||||||
default = default.name;
|
default = default.name;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
key = mkOption ({
|
key = mkOption ({
|
||||||
description = "Name of the key where secret is stored";
|
description = "Name of the key where secret is stored";
|
||||||
type = types.str;
|
type = types.str;
|
||||||
} // (optionalAttrs (default ? "key") {
|
}
|
||||||
|
// (optionalAttrs (default ? "key") {
|
||||||
default = default.key;
|
default = default.key;
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
default = if default == null then null else { };
|
default =
|
||||||
|
if default == null
|
||||||
|
then null
|
||||||
|
else {};
|
||||||
};
|
};
|
||||||
|
|
||||||
secretToEnv = value: {
|
secretToEnv = value: {
|
||||||
|
|
@ -34,7 +46,10 @@ rec {
|
||||||
};
|
};
|
||||||
|
|
||||||
# Creates kubernetes list from a list of kubernetes objects
|
# Creates kubernetes list from a list of kubernetes objects
|
||||||
mkList = { items, labels ? { } }: {
|
mkList = {
|
||||||
|
items,
|
||||||
|
labels ? {},
|
||||||
|
}: {
|
||||||
kind = "List";
|
kind = "List";
|
||||||
apiVersion = "v1";
|
apiVersion = "v1";
|
||||||
|
|
||||||
|
|
@ -42,22 +57,27 @@ rec {
|
||||||
};
|
};
|
||||||
|
|
||||||
# Creates hashed kubernetes list from a list of kubernetes objects
|
# Creates hashed kubernetes list from a list of kubernetes objects
|
||||||
mkHashedList = { items, labels ? { } }:
|
mkHashedList = {
|
||||||
let
|
items,
|
||||||
|
labels ? {},
|
||||||
|
}: let
|
||||||
hash = builtins.hashString "sha1" (builtins.toJSON items);
|
hash = builtins.hashString "sha1" (builtins.toJSON items);
|
||||||
|
|
||||||
labeledItems = map
|
labeledItems =
|
||||||
(item: recursiveUpdate item {
|
map
|
||||||
|
(item:
|
||||||
|
recursiveUpdate item {
|
||||||
metadata.labels."kubenix/hash" = hash;
|
metadata.labels."kubenix/hash" = hash;
|
||||||
})
|
})
|
||||||
items;
|
items;
|
||||||
|
|
||||||
in
|
in
|
||||||
mkList {
|
mkList {
|
||||||
items = labeledItems;
|
items = labeledItems;
|
||||||
labels = {
|
labels =
|
||||||
|
{
|
||||||
"kubenix/hash" = hash;
|
"kubenix/hash" = hash;
|
||||||
} // labels;
|
}
|
||||||
|
// labels;
|
||||||
};
|
};
|
||||||
|
|
||||||
toBase64 = lib.toBase64;
|
toBase64 = lib.toBase64;
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,45 @@
|
||||||
{ lib, pkgs }:
|
{
|
||||||
|
lib,
|
||||||
with lib;
|
pkgs,
|
||||||
|
}:
|
||||||
let self = {
|
with lib; let
|
||||||
|
self = {
|
||||||
importYAML = path: importJSON (pkgs.runCommand "yaml-to-json" { } ''
|
importYAML = path:
|
||||||
|
importJSON (pkgs.runCommand "yaml-to-json" {} ''
|
||||||
${pkgs.remarshal}/bin/remarshal -i ${path} -if yaml -of json > $out
|
${pkgs.remarshal}/bin/remarshal -i ${path} -if yaml -of json > $out
|
||||||
'');
|
'');
|
||||||
|
|
||||||
toYAML = config: builtins.readFile (pkgs.runCommand "to-yaml" { } ''
|
toYAML = config:
|
||||||
|
builtins.readFile (pkgs.runCommand "to-yaml" {} ''
|
||||||
${pkgs.remarshal}/bin/remarshal -i ${pkgs.writeText "to-json" (builtins.toJSON config)} -if json -of yaml > $out
|
${pkgs.remarshal}/bin/remarshal -i ${pkgs.writeText "to-json" (builtins.toJSON config)} -if json -of yaml > $out
|
||||||
'');
|
'');
|
||||||
|
|
||||||
toMultiDocumentYaml = name: documents: pkgs.runCommand name { }
|
toMultiDocumentYaml = name: documents:
|
||||||
|
pkgs.runCommand name {}
|
||||||
(concatMapStringsSep "\necho --- >> $out\n"
|
(concatMapStringsSep "\necho --- >> $out\n"
|
||||||
(d:
|
(
|
||||||
"${pkgs.remarshal}/bin/remarshal -i ${builtins.toFile "doc" (builtins.toJSON d)} -if json -of yaml >> $out"
|
d: "${pkgs.remarshal}/bin/remarshal -i ${builtins.toFile "doc" (builtins.toJSON d)} -if json -of yaml >> $out"
|
||||||
)
|
)
|
||||||
documents);
|
documents);
|
||||||
|
|
||||||
toBase64 = value:
|
toBase64 = value:
|
||||||
builtins.readFile
|
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);
|
exp = base: exp: foldr (value: acc: acc * base) 1 (range 1 exp);
|
||||||
|
|
||||||
octalToDecimal = value: (foldr
|
octalToDecimal = value:
|
||||||
|
(foldr
|
||||||
(char: acc: {
|
(char: acc: {
|
||||||
i = acc.i + 1;
|
i = acc.i + 1;
|
||||||
value = acc.value + (toInt char) * (self.exp 8 acc.i);
|
value = acc.value + (toInt char) * (self.exp 8 acc.i);
|
||||||
})
|
})
|
||||||
{ i = 0; value = 0; }
|
{
|
||||||
(stringToCharacters value)).value;
|
i = 0;
|
||||||
};
|
value = 0;
|
||||||
in self
|
}
|
||||||
|
(stringToCharacters value))
|
||||||
|
.value;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
self
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
{ config, lib, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; {
|
||||||
options = {
|
options = {
|
||||||
kubenix.project = mkOption {
|
kubenix.project = mkOption {
|
||||||
description = "Name of the project";
|
description = "Name of the project";
|
||||||
|
|
@ -13,27 +14,27 @@ with lib;
|
||||||
_m.features = mkOption {
|
_m.features = mkOption {
|
||||||
description = "List of features exposed by module";
|
description = "List of features exposed by module";
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [ ];
|
default = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
_m.propagate = mkOption {
|
_m.propagate = mkOption {
|
||||||
description = "Module propagation options";
|
description = "Module propagation options";
|
||||||
type = types.listOf (types.submodule ({ config, ... }: {
|
type = types.listOf (types.submodule ({config, ...}: {
|
||||||
options = {
|
options = {
|
||||||
features = mkOption {
|
features = mkOption {
|
||||||
description = "List of features that submodule has to have to propagate module";
|
description = "List of features that submodule has to have to propagate module";
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [ ];
|
default = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
module = mkOption {
|
module = mkOption {
|
||||||
description = "Module to propagate";
|
description = "Module to propagate";
|
||||||
type = types.unspecified;
|
type = types.unspecified;
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
default = [ ];
|
default = [];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
{ config, lib, pkgs, docker, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
let
|
|
||||||
cfg = config.docker;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
imports = [ ./base.nix ];
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
docker,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
|
cfg = config.docker;
|
||||||
|
in {
|
||||||
|
imports = [./base.nix];
|
||||||
|
|
||||||
options.docker = {
|
options.docker = {
|
||||||
registry.url = mkOption {
|
registry.url = mkOption {
|
||||||
|
|
@ -16,7 +19,11 @@ in
|
||||||
|
|
||||||
images = mkOption {
|
images = mkOption {
|
||||||
description = "Attribute set of docker images that should be published";
|
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 = {
|
options = {
|
||||||
image = mkOption {
|
image = mkOption {
|
||||||
description = "Docker image to publish";
|
description = "Docker image to publish";
|
||||||
|
|
@ -52,13 +59,13 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
export = mkOption {
|
export = mkOption {
|
||||||
description = "List of images to export";
|
description = "List of images to export";
|
||||||
type = types.listOf types.package;
|
type = types.listOf types.package;
|
||||||
default = [ ];
|
default = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
copyScript = mkOption {
|
copyScript = mkOption {
|
||||||
|
|
@ -73,22 +80,29 @@ in
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
# define docker feature
|
# define docker feature
|
||||||
_m.features = [ "docker" ];
|
_m.features = ["docker"];
|
||||||
|
|
||||||
# propagate docker options if docker feature is enabled
|
# propagate docker options if docker feature is enabled
|
||||||
_m.propagate = [{
|
_m.propagate = [
|
||||||
features = [ "docker" ];
|
{
|
||||||
module = { config, name, ... }: {
|
features = ["docker"];
|
||||||
|
module = {
|
||||||
|
config,
|
||||||
|
name,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
# propagate registry options
|
# propagate registry options
|
||||||
docker.registry = cfg.registry;
|
docker.registry = cfg.registry;
|
||||||
};
|
};
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
|
||||||
# pass docker library as param
|
# 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
|
# 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);
|
(filterAttrs (_: i: i.registry != null) config.docker.images);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,10 +1,13 @@
|
||||||
# helm defines kubenix module with options for using helm charts
|
# helm defines kubenix module with options for using helm charts
|
||||||
# with kubenix
|
# with kubenix
|
||||||
|
{
|
||||||
{ config, lib, pkgs, helm, ... }:
|
config,
|
||||||
|
lib,
|
||||||
with lib;
|
pkgs,
|
||||||
let
|
helm,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
cfg = config.kubernetes.helm;
|
cfg = config.kubernetes.helm;
|
||||||
|
|
||||||
globalConfig = config;
|
globalConfig = config;
|
||||||
|
|
@ -13,26 +16,29 @@ let
|
||||||
name = "recursive-attrs";
|
name = "recursive-attrs";
|
||||||
description = "recursive attribute set";
|
description = "recursive attribute set";
|
||||||
check = isAttrs;
|
check = isAttrs;
|
||||||
merge = loc: foldl' (res: def: recursiveUpdate res def.value) { };
|
merge = loc: foldl' (res: def: recursiveUpdate res def.value) {};
|
||||||
};
|
};
|
||||||
|
|
||||||
parseApiVersion = apiVersion:
|
parseApiVersion = apiVersion: let
|
||||||
let
|
|
||||||
splitted = splitString "/" apiVersion;
|
splitted = splitString "/" apiVersion;
|
||||||
in
|
in {
|
||||||
{
|
group =
|
||||||
group = if length splitted == 1 then "core" else head splitted;
|
if length splitted == 1
|
||||||
|
then "core"
|
||||||
|
else head splitted;
|
||||||
version = last splitted;
|
version = last splitted;
|
||||||
};
|
};
|
||||||
|
in {
|
||||||
in
|
imports = [./k8s.nix];
|
||||||
{
|
|
||||||
imports = [ ./k8s.nix ];
|
|
||||||
|
|
||||||
options.kubernetes.helm = {
|
options.kubernetes.helm = {
|
||||||
instances = mkOption {
|
instances = mkOption {
|
||||||
description = "Attribute set of helm instances";
|
description = "Attribute set of helm instances";
|
||||||
type = types.attrsOf (types.submodule ({ config, name, ... }: {
|
type = types.attrsOf (types.submodule ({
|
||||||
|
config,
|
||||||
|
name,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
options = {
|
options = {
|
||||||
name = mkOption {
|
name = mkOption {
|
||||||
description = "Helm release name";
|
description = "Helm release name";
|
||||||
|
|
@ -54,7 +60,7 @@ in
|
||||||
values = mkOption {
|
values = mkOption {
|
||||||
description = "Values to pass to chart";
|
description = "Values to pass to chart";
|
||||||
type = recursiveAttrs;
|
type = recursiveAttrs;
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
kubeVersion = mkOption {
|
kubeVersion = mkOption {
|
||||||
|
|
@ -66,7 +72,7 @@ in
|
||||||
overrides = mkOption {
|
overrides = mkOption {
|
||||||
description = "Overrides to apply to all chart resources";
|
description = "Overrides to apply to all chart resources";
|
||||||
type = types.listOf types.unspecified;
|
type = types.listOf types.unspecified;
|
||||||
default = [ ];
|
default = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
overrideNamespace = mkOption {
|
overrideNamespace = mkOption {
|
||||||
|
|
@ -78,38 +84,40 @@ in
|
||||||
objects = mkOption {
|
objects = mkOption {
|
||||||
description = "Generated kubernetes objects";
|
description = "Generated kubernetes objects";
|
||||||
type = types.listOf types.attrs;
|
type = types.listOf types.attrs;
|
||||||
default = [ ];
|
default = [];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config.overrides = mkIf (config.overrideNamespace && config.namespace != null) [{
|
config.overrides = mkIf (config.overrideNamespace && config.namespace != null) [
|
||||||
|
{
|
||||||
metadata.namespace = config.namespace;
|
metadata.namespace = config.namespace;
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
|
||||||
config.objects = importJSON (helm.chart2json {
|
config.objects = importJSON (helm.chart2json {
|
||||||
inherit (config) chart name namespace values kubeVersion;
|
inherit (config) chart name namespace values kubeVersion;
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
# expose helm helper methods as module argument
|
# 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
|
kubernetes.api.resources = mkMerge (flatten (mapAttrsToList
|
||||||
(_: instance:
|
(
|
||||||
|
_: instance:
|
||||||
map
|
map
|
||||||
(object:
|
(object: let
|
||||||
let
|
|
||||||
apiVersion = parseApiVersion object.apiVersion;
|
apiVersion = parseApiVersion object.apiVersion;
|
||||||
name = object.metadata.name;
|
name = object.metadata.name;
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
"${apiVersion.group}"."${apiVersion.version}".${object.kind}."${name}" = mkMerge ([
|
"${apiVersion.group}"."${apiVersion.version}".${object.kind}."${name}" = mkMerge ([
|
||||||
object
|
object
|
||||||
] ++ instance.overrides);
|
]
|
||||||
|
++ instance.overrides);
|
||||||
})
|
})
|
||||||
instance.objects
|
instance.objects
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,19 @@
|
||||||
{ lib, definitions }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
"istio_networking_v1alpha3_StringMatch" = recursiveUpdate
|
lib,
|
||||||
(recursiveUpdate
|
definitions,
|
||||||
|
}:
|
||||||
|
with lib; {
|
||||||
|
"istio_networking_v1alpha3_StringMatch" =
|
||||||
|
recursiveUpdate
|
||||||
|
(
|
||||||
|
recursiveUpdate
|
||||||
definitions."istio_networking_v1alpha3_StringMatch_Exact"
|
definitions."istio_networking_v1alpha3_StringMatch_Exact"
|
||||||
definitions."istio_networking_v1alpha3_StringMatch_Prefix"
|
definitions."istio_networking_v1alpha3_StringMatch_Prefix"
|
||||||
)
|
)
|
||||||
definitions."istio_networking_v1alpha3_StringMatch_Regex";
|
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_Name"
|
||||||
definitions."istio_networking_v1alpha3_PortSelector_Number";
|
definitions."istio_networking_v1alpha3_PortSelector_Number";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1011
modules/istio.nix
1011
modules/istio.nix
File diff suppressed because it is too large
Load diff
213
modules/k8s.nix
213
modules/k8s.nix
|
|
@ -1,33 +1,36 @@
|
||||||
# K8S module defines kubernetes definitions for kubenix
|
# K8S module defines kubernetes definitions for kubenix
|
||||||
|
{
|
||||||
{ options, config, lib, pkgs, k8s, ... }:
|
options,
|
||||||
|
config,
|
||||||
with lib;
|
lib,
|
||||||
let
|
pkgs,
|
||||||
|
k8s,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
cfg = config.kubernetes;
|
cfg = config.kubernetes;
|
||||||
|
|
||||||
gvkKeyFn = type: "${type.group}/${type.version}/${type.kind}";
|
gvkKeyFn = type: "${type.group}/${type.version}/${type.kind}";
|
||||||
|
|
||||||
getDefaults = resource: group: version: kind:
|
getDefaults = resource: group: version: kind:
|
||||||
catAttrs "default" (filter
|
catAttrs "default" (filter
|
||||||
(default:
|
(
|
||||||
(resource == null || default.resource == null || default.resource == resource) &&
|
default:
|
||||||
(default.group == null || default.group == group) &&
|
(resource == null || default.resource == null || default.resource == resource)
|
||||||
(default.version == null || default.version == version) &&
|
&& (default.group == null || default.group == group)
|
||||||
(default.kind == null || default.kind == kind)
|
&& (default.version == null || default.version == version)
|
||||||
|
&& (default.kind == null || default.kind == kind)
|
||||||
)
|
)
|
||||||
cfg.api.defaults);
|
cfg.api.defaults);
|
||||||
|
|
||||||
moduleToAttrs = value:
|
moduleToAttrs = value:
|
||||||
if isAttrs value
|
if isAttrs value
|
||||||
then mapAttrs (n: v: moduleToAttrs v) (filterAttrs (n: v: v != null && !(hasPrefix "_" n)) value)
|
then mapAttrs (n: v: moduleToAttrs v) (filterAttrs (n: v: v != null && !(hasPrefix "_" n)) value)
|
||||||
|
|
||||||
else if isList value
|
else if isList value
|
||||||
then map (v: moduleToAttrs v) value
|
then map (v: moduleToAttrs v) value
|
||||||
|
|
||||||
else value;
|
else value;
|
||||||
|
|
||||||
apiOptions = { config, ... }: {
|
apiOptions = {config, ...}: {
|
||||||
options = {
|
options = {
|
||||||
definitions = mkOption {
|
definitions = mkOption {
|
||||||
description = "Attribute set of kubernetes definitions";
|
description = "Attribute set of kubernetes definitions";
|
||||||
|
|
@ -35,7 +38,7 @@ let
|
||||||
|
|
||||||
defaults = mkOption {
|
defaults = mkOption {
|
||||||
description = "Kubernetes defaults to apply to resources";
|
description = "Kubernetes defaults to apply to resources";
|
||||||
type = types.listOf (types.submodule ({ config, ... }: {
|
type = types.listOf (types.submodule ({config, ...}: {
|
||||||
options = {
|
options = {
|
||||||
group = mkOption {
|
group = mkOption {
|
||||||
description = "Group to apply default to (all by default)";
|
description = "Group to apply default to (all by default)";
|
||||||
|
|
@ -70,17 +73,18 @@ let
|
||||||
default = mkOption {
|
default = mkOption {
|
||||||
description = "Default to apply";
|
description = "Default to apply";
|
||||||
type = types.unspecified;
|
type = types.unspecified;
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
default = [ ];
|
default = [];
|
||||||
apply = unique;
|
apply = unique;
|
||||||
};
|
};
|
||||||
|
|
||||||
types = mkOption {
|
types = mkOption {
|
||||||
description = "List of registered kubernetes types";
|
description = "List of registered kubernetes types";
|
||||||
type = coerceListOfSubmodulesToAttrs
|
type =
|
||||||
|
coerceListOfSubmodulesToAttrs
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
group = mkOption {
|
group = mkOption {
|
||||||
|
|
@ -110,7 +114,7 @@ let
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
gvkKeyFn;
|
gvkKeyFn;
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -121,16 +125,25 @@ let
|
||||||
};
|
};
|
||||||
|
|
||||||
indexOf = lst: value:
|
indexOf = lst: value:
|
||||||
head (filter (v: v != -1) (imap0 (i: v: if v == value then i else -1) lst));
|
head (filter (v: v != -1) (imap0 (i: v:
|
||||||
|
if v == value
|
||||||
|
then i
|
||||||
|
else -1)
|
||||||
|
lst));
|
||||||
|
|
||||||
compareVersions = ver1: ver2:
|
compareVersions = ver1: ver2: let
|
||||||
let
|
|
||||||
getVersion = v: substring 1 10 v;
|
getVersion = v: substring 1 10 v;
|
||||||
splittedVer1 = builtins.splitVersion (getVersion ver1);
|
splittedVer1 = builtins.splitVersion (getVersion ver1);
|
||||||
splittedVer2 = builtins.splitVersion (getVersion ver2);
|
splittedVer2 = builtins.splitVersion (getVersion ver2);
|
||||||
|
|
||||||
v1 = if length splittedVer1 == 1 then "${getVersion ver1}prod" else getVersion ver1;
|
v1 =
|
||||||
v2 = if length splittedVer2 == 1 then "${getVersion ver2}prod" else getVersion ver2;
|
if length splittedVer1 == 1
|
||||||
|
then "${getVersion ver1}prod"
|
||||||
|
else getVersion ver1;
|
||||||
|
v2 =
|
||||||
|
if length splittedVer2 == 1
|
||||||
|
then "${getVersion ver2}prod"
|
||||||
|
else getVersion ver2;
|
||||||
in
|
in
|
||||||
builtins.compareVersions v1 v2;
|
builtins.compareVersions v1 v2;
|
||||||
|
|
||||||
|
|
@ -140,10 +153,13 @@ let
|
||||||
})
|
})
|
||||||
cfg.customTypes);
|
cfg.customTypes);
|
||||||
|
|
||||||
customResourceTypesByAttrNameSortByVersion = mapAttrs
|
customResourceTypesByAttrNameSortByVersion =
|
||||||
(_: resourceTypes:
|
mapAttrs
|
||||||
|
(
|
||||||
|
_: resourceTypes:
|
||||||
reverseList (sort
|
reverseList (sort
|
||||||
(r1: r2:
|
(
|
||||||
|
r1: r2:
|
||||||
compareVersions r1.version r2.version > 0
|
compareVersions r1.version r2.version > 0
|
||||||
)
|
)
|
||||||
resourceTypes)
|
resourceTypes)
|
||||||
|
|
@ -153,7 +169,7 @@ let
|
||||||
latestCustomResourceTypes =
|
latestCustomResourceTypes =
|
||||||
mapAttrsToList (_: resources: last resources) customResourceTypesByAttrNameSortByVersion;
|
mapAttrsToList (_: resources: last resources) customResourceTypesByAttrNameSortByVersion;
|
||||||
|
|
||||||
customResourceModuleForType = config: ct: { name, ... }: {
|
customResourceModuleForType = config: ct: {name, ...}: {
|
||||||
imports = getDefaults ct.name ct.group ct.version ct.kind;
|
imports = getDefaults ct.name ct.group ct.version ct.kind;
|
||||||
options = {
|
options = {
|
||||||
apiVersion = mkOption {
|
apiVersion = mkOption {
|
||||||
|
|
@ -174,7 +190,7 @@ let
|
||||||
spec = mkOption {
|
spec = mkOption {
|
||||||
description = "Module spec";
|
description = "Module spec";
|
||||||
type = types.either types.attrs (types.submodule ct.module);
|
type = types.either types.attrs (types.submodule ct.module);
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -185,28 +201,30 @@ let
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
customResourceOptions = (mapAttrsToList
|
customResourceOptions =
|
||||||
(_: ct: { config, ... }:
|
(mapAttrsToList
|
||||||
let
|
(_: ct: {config, ...}: let
|
||||||
module = customResourceModuleForType config ct;
|
module = customResourceModuleForType config ct;
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
options.resources.${ct.group}.${ct.version}.${ct.kind} = mkOption {
|
options.resources.${ct.group}.${ct.version}.${ct.kind} = mkOption {
|
||||||
description = ct.description;
|
description = ct.description;
|
||||||
type = types.attrsOf (types.submodule module);
|
type = types.attrsOf (types.submodule module);
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
cfg.customTypes) ++ (map
|
cfg.customTypes)
|
||||||
(ct: { options, config, ... }:
|
++ (map
|
||||||
let
|
(ct: {
|
||||||
|
options,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
module = customResourceModuleForType config ct;
|
module = customResourceModuleForType config ct;
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
options.resources.${ct.attrName} = mkOption {
|
options.resources.${ct.attrName} = mkOption {
|
||||||
description = ct.description;
|
description = ct.description;
|
||||||
type = types.attrsOf (types.submodule module);
|
type = types.attrsOf (types.submodule module);
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
config.resources.${ct.group}.${ct.version}.${ct.kind} =
|
config.resources.${ct.group}.${ct.version}.${ct.kind} =
|
||||||
|
|
@ -214,11 +232,11 @@ let
|
||||||
})
|
})
|
||||||
latestCustomResourceTypes);
|
latestCustomResourceTypes);
|
||||||
|
|
||||||
coerceListOfSubmodulesToAttrs = submodule: keyFn:
|
coerceListOfSubmodulesToAttrs = submodule: keyFn: let
|
||||||
let
|
|
||||||
mergeValuesByFn = keyFn: values:
|
mergeValuesByFn = keyFn: values:
|
||||||
listToAttrs (map
|
listToAttrs (map
|
||||||
(value:
|
(
|
||||||
|
value:
|
||||||
nameValuePair (toString (keyFn value)) value
|
nameValuePair (toString (keyFn value)) value
|
||||||
)
|
)
|
||||||
values);
|
values);
|
||||||
|
|
@ -230,36 +248,31 @@ let
|
||||||
name = "coercedTo";
|
name = "coercedTo";
|
||||||
description = "${finalType.description} or ${coercedType.description}";
|
description = "${finalType.description} or ${coercedType.description}";
|
||||||
check = x: finalType.check x || coercedType.check x;
|
check = x: finalType.check x || coercedType.check x;
|
||||||
merge = loc: defs:
|
merge = loc: defs: let
|
||||||
let
|
|
||||||
coerceVal = val:
|
coerceVal = val:
|
||||||
if finalType.check val then
|
if finalType.check val
|
||||||
val
|
then val
|
||||||
else
|
else let coerced = coerceFunc val; in assert finalType.check coerced; coerced;
|
||||||
let coerced = coerceFunc val; in assert finalType.check coerced; coerced;
|
|
||||||
|
|
||||||
in
|
in
|
||||||
finalType.merge loc (map (def: def // { value = coerceVal def.value; }) defs);
|
finalType.merge loc (map (def: def // {value = coerceVal def.value;}) defs);
|
||||||
getSubOptions = finalType.getSubOptions;
|
getSubOptions = finalType.getSubOptions;
|
||||||
getSubModules = finalType.getSubModules;
|
getSubModules = finalType.getSubModules;
|
||||||
substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m);
|
substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m);
|
||||||
typeMerge = t1: t2: null;
|
typeMerge = t1: t2: null;
|
||||||
functor = (defaultFunctor name) // { wrapped = finalType; };
|
functor = (defaultFunctor name) // {wrapped = finalType;};
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
coercedTo
|
coercedTo
|
||||||
(types.listOf (types.submodule submodule))
|
(types.listOf (types.submodule submodule))
|
||||||
(mergeValuesByFn keyFn)
|
(mergeValuesByFn keyFn)
|
||||||
(types.attrsOf (types.submodule submodule));
|
(types.attrsOf (types.submodule submodule));
|
||||||
|
in {
|
||||||
in
|
imports = [./base.nix];
|
||||||
{
|
|
||||||
imports = [ ./base.nix ];
|
|
||||||
|
|
||||||
options.kubernetes = {
|
options.kubernetes = {
|
||||||
version = mkOption {
|
version = mkOption {
|
||||||
description = "Kubernetes version to use";
|
description = "Kubernetes version to use";
|
||||||
type = types.enum [ "1.19" "1.20" "1.21" ];
|
type = types.enum ["1.19" "1.20" "1.21"];
|
||||||
default = "1.21";
|
default = "1.21";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -280,29 +293,32 @@ in
|
||||||
|
|
||||||
api = mkOption {
|
api = mkOption {
|
||||||
type = types.submodule {
|
type = types.submodule {
|
||||||
imports = [
|
imports =
|
||||||
|
[
|
||||||
(./generated + ''/v'' + cfg.version + ".nix")
|
(./generated + ''/v'' + cfg.version + ".nix")
|
||||||
apiOptions
|
apiOptions
|
||||||
] ++ customResourceOptions;
|
]
|
||||||
|
++ customResourceOptions;
|
||||||
};
|
};
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
imports = mkOption {
|
imports = mkOption {
|
||||||
type = types.listOf (types.either types.package types.path);
|
type = types.listOf (types.either types.package types.path);
|
||||||
description = "List of resources to import";
|
description = "List of resources to import";
|
||||||
default = [ ];
|
default = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
resources = mkOption {
|
resources = mkOption {
|
||||||
description = "Alias for `config.kubernetes.api.resources` options";
|
description = "Alias for `config.kubernetes.api.resources` options";
|
||||||
default = { };
|
default = {};
|
||||||
type = types.attrsOf types.attrs;
|
type = types.attrsOf types.attrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
customTypes = mkOption {
|
customTypes = mkOption {
|
||||||
description = "List of custom resource types to make API for";
|
description = "List of custom resource types to make API for";
|
||||||
type = coerceListOfSubmodulesToAttrs
|
type =
|
||||||
|
coerceListOfSubmodulesToAttrs
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
group = mkOption {
|
group = mkOption {
|
||||||
|
|
@ -340,25 +356,29 @@ in
|
||||||
module = mkOption {
|
module = mkOption {
|
||||||
description = "Custom type module";
|
description = "Custom type module";
|
||||||
type = types.unspecified;
|
type = types.unspecified;
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
gvkKeyFn;
|
gvkKeyFn;
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
objects = mkOption {
|
objects = mkOption {
|
||||||
description = "List of generated kubernetes objects";
|
description = "List of generated kubernetes objects";
|
||||||
type = types.listOf types.attrs;
|
type = types.listOf types.attrs;
|
||||||
apply = items: sort
|
apply = items:
|
||||||
(r1: r2:
|
sort
|
||||||
|
(
|
||||||
|
r1: r2:
|
||||||
if elem r1.kind cfg.resourceOrder && elem r2.kind cfg.resourceOrder
|
if elem r1.kind cfg.resourceOrder && elem r2.kind cfg.resourceOrder
|
||||||
then indexOf cfg.resourceOrder r1.kind < indexOf cfg.resourceOrder r2.kind
|
then indexOf cfg.resourceOrder r1.kind < indexOf cfg.resourceOrder r2.kind
|
||||||
else if elem r1.kind cfg.resourceOrder then true else false
|
else if elem r1.kind cfg.resourceOrder
|
||||||
|
then true
|
||||||
|
else false
|
||||||
)
|
)
|
||||||
(unique items);
|
(unique items);
|
||||||
default = [ ];
|
default = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
generated = mkOption {
|
generated = mkOption {
|
||||||
|
|
@ -379,26 +399,26 @@ in
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
# features that module is defining
|
# features that module is defining
|
||||||
_m.features = [ "k8s" ];
|
_m.features = ["k8s"];
|
||||||
|
|
||||||
# module propagation options
|
# module propagation options
|
||||||
_m.propagate = [{
|
_m.propagate = [
|
||||||
features = [ "k8s" ];
|
{
|
||||||
module = { config, ... }: {
|
features = ["k8s"];
|
||||||
|
module = {config, ...}: {
|
||||||
# propagate kubernetes version and namespace
|
# propagate kubernetes version and namespace
|
||||||
kubernetes.version = mkDefault cfg.version;
|
kubernetes.version = mkDefault cfg.version;
|
||||||
kubernetes.namespace = mkDefault cfg.namespace;
|
kubernetes.namespace = mkDefault cfg.namespace;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
features = [ "k8s" "submodule" ];
|
features = ["k8s" "submodule"];
|
||||||
module = { config, ... }: {
|
module = {config, ...}: {
|
||||||
# set module defaults
|
# set module defaults
|
||||||
kubernetes.api.defaults = (
|
kubernetes.api.defaults = (
|
||||||
# propagate defaults if default propagation is enabled
|
# propagate defaults if default propagation is enabled
|
||||||
(filter (default: default.propagate) cfg.api.defaults) ++
|
(filter (default: default.propagate) cfg.api.defaults)
|
||||||
|
++ [
|
||||||
[
|
|
||||||
# set module name and version for all kuberentes resources
|
# set module name and version for all kuberentes resources
|
||||||
{
|
{
|
||||||
default.metadata.labels = {
|
default.metadata.labels = {
|
||||||
|
|
@ -409,23 +429,28 @@ in
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
|
||||||
# expose k8s helper methods as module argument
|
# 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 ([{
|
kubernetes.api = mkMerge ([
|
||||||
|
{
|
||||||
# register custom types
|
# register custom types
|
||||||
types = mapAttrsToList
|
types =
|
||||||
|
mapAttrsToList
|
||||||
(_: cr: {
|
(_: cr: {
|
||||||
inherit (cr) name group version kind attrName;
|
inherit (cr) name group version kind attrName;
|
||||||
})
|
})
|
||||||
cfg.customTypes;
|
cfg.customTypes;
|
||||||
|
|
||||||
defaults = [{
|
defaults = [
|
||||||
|
{
|
||||||
default = {
|
default = {
|
||||||
# set default kubernetes namespace to all resources
|
# set default kubernetes namespace to all resources
|
||||||
metadata.namespace = mkIf (config.kubernetes.namespace != null)
|
metadata.namespace =
|
||||||
|
mkIf (config.kubernetes.namespace != null)
|
||||||
(mkDefault config.kubernetes.namespace);
|
(mkDefault config.kubernetes.namespace);
|
||||||
|
|
||||||
# set project name to all resources
|
# set project name to all resources
|
||||||
|
|
@ -434,13 +459,14 @@ in
|
||||||
"kubenix/k8s-version" = cfg.version;
|
"kubenix/k8s-version" = cfg.version;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}];
|
}
|
||||||
}] ++
|
];
|
||||||
|
}
|
||||||
|
]
|
||||||
|
++
|
||||||
# import of yaml files
|
# import of yaml files
|
||||||
(map
|
(map
|
||||||
(i:
|
(i: let
|
||||||
let
|
|
||||||
# load yaml file
|
# load yaml file
|
||||||
object = importYAML i;
|
object = importYAML i;
|
||||||
groupVersion = splitString "/" object.apiVersion;
|
groupVersion = splitString "/" object.apiVersion;
|
||||||
|
|
@ -448,16 +474,17 @@ in
|
||||||
version = last groupVersion;
|
version = last groupVersion;
|
||||||
group =
|
group =
|
||||||
if version == (head groupVersion)
|
if version == (head groupVersion)
|
||||||
then "core" else head groupVersion;
|
then "core"
|
||||||
|
else head groupVersion;
|
||||||
kind = object.kind;
|
kind = object.kind;
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
resources.${group}.${version}.${kind}.${name} = object;
|
resources.${group}.${version}.${kind}.${name} = object;
|
||||||
})
|
})
|
||||||
cfg.imports));
|
cfg.imports));
|
||||||
|
|
||||||
kubernetes.objects = flatten (mapAttrsToList
|
kubernetes.objects = flatten (mapAttrsToList
|
||||||
(_: type:
|
(
|
||||||
|
_: type:
|
||||||
mapAttrsToList (name: resource: moduleToAttrs resource)
|
mapAttrsToList (name: resource: moduleToAttrs resource)
|
||||||
cfg.api.resources.${type.group}.${type.version}.${type.kind}
|
cfg.api.resources.${type.group}.${type.version}.${type.kind}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
{ config, lib, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
{
|
{
|
||||||
imports = [ ./base.nix ];
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; {
|
||||||
|
imports = [./base.nix];
|
||||||
|
|
||||||
options.submodule = {
|
options.submodule = {
|
||||||
name = mkOption {
|
name = mkOption {
|
||||||
|
|
@ -25,24 +27,24 @@ with lib;
|
||||||
tags = mkOption {
|
tags = mkOption {
|
||||||
description = "List of submodule tags";
|
description = "List of submodule tags";
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [ ];
|
default = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
exports = mkOption {
|
exports = mkOption {
|
||||||
description = "Attribute set of functions to export";
|
description = "Attribute set of functions to export";
|
||||||
type = types.attrs;
|
type = types.attrs;
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
passthru = mkOption {
|
passthru = mkOption {
|
||||||
description = "Attribute set to passthru";
|
description = "Attribute set to passthru";
|
||||||
type = types.attrs;
|
type = types.attrs;
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
args._empty = mkOption { };
|
args._empty = mkOption {};
|
||||||
};
|
};
|
||||||
|
|
||||||
config._module.args.args = config.submodule.args;
|
config._module.args.args = config.submodule.args;
|
||||||
config._m.features = [ "submodule" ];
|
config._m.features = ["submodule"];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,100 +1,141 @@
|
||||||
{ config, options, kubenix, pkgs, lib, ... }:
|
{
|
||||||
|
config,
|
||||||
with lib;
|
options,
|
||||||
let
|
kubenix,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
cfg = config.submodules;
|
cfg = config.submodules;
|
||||||
parentConfig = config;
|
parentConfig = config;
|
||||||
|
|
||||||
matchesVersion = requiredVersion: version:
|
matchesVersion = requiredVersion: version:
|
||||||
if requiredVersion != null then
|
if requiredVersion != null
|
||||||
|
then
|
||||||
if hasPrefix "~" requiredVersion
|
if hasPrefix "~" requiredVersion
|
||||||
then (builtins.match (removePrefix "~" requiredVersion) version) != null
|
then (builtins.match (removePrefix "~" requiredVersion) version) != null
|
||||||
else requiredVersion == version
|
else requiredVersion == version
|
||||||
else true;
|
else true;
|
||||||
|
|
||||||
getDefaults = { name, version, tags, features }:
|
getDefaults = {
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
tags,
|
||||||
|
features,
|
||||||
|
}:
|
||||||
catAttrs "default" (filter
|
catAttrs "default" (filter
|
||||||
(submoduleDefault:
|
|
||||||
(submoduleDefault.name == null || submoduleDefault.name == name) &&
|
|
||||||
(matchesVersion submoduleDefault.version version) &&
|
|
||||||
(
|
(
|
||||||
(length submoduleDefault.tags == 0) ||
|
submoduleDefault:
|
||||||
(length (intersectLists submoduleDefault.tags tags)) > 0
|
(submoduleDefault.name == null || submoduleDefault.name == name)
|
||||||
) &&
|
&& (matchesVersion submoduleDefault.version version)
|
||||||
(
|
&& (
|
||||||
(length submoduleDefault.features == 0) ||
|
(length submoduleDefault.tags == 0)
|
||||||
(length (intersectLists submoduleDefault.features features)) > 0
|
|| (length (intersectLists submoduleDefault.tags tags)) > 0
|
||||||
|
)
|
||||||
|
&& (
|
||||||
|
(length submoduleDefault.features == 0)
|
||||||
|
|| (length (intersectLists submoduleDefault.features features)) > 0
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
config.submodules.defaults);
|
config.submodules.defaults);
|
||||||
|
|
||||||
specialArgs = cfg.specialArgs // {
|
specialArgs =
|
||||||
|
cfg.specialArgs
|
||||||
|
// {
|
||||||
parentConfig = config;
|
parentConfig = config;
|
||||||
};
|
};
|
||||||
|
|
||||||
findSubmodule = { name, version ? null, latest ? true }:
|
findSubmodule = {
|
||||||
let
|
name,
|
||||||
matchingSubmodules = filter
|
version ? null,
|
||||||
(el:
|
latest ? true,
|
||||||
el.definition.name == name &&
|
}: let
|
||||||
(matchesVersion version el.definition.version)
|
matchingSubmodules =
|
||||||
|
filter
|
||||||
|
(
|
||||||
|
el:
|
||||||
|
el.definition.name
|
||||||
|
== name
|
||||||
|
&& (matchesVersion version el.definition.version)
|
||||||
)
|
)
|
||||||
cfg.imports;
|
cfg.imports;
|
||||||
|
|
||||||
versionSortedSubmodules = sort
|
versionSortedSubmodules =
|
||||||
(s1: s2:
|
sort
|
||||||
|
(
|
||||||
|
s1: s2:
|
||||||
if builtins.compareVersions s1.definition.version s2.definition.version > 0
|
if builtins.compareVersions s1.definition.version s2.definition.version > 0
|
||||||
then true else false
|
then true
|
||||||
|
else false
|
||||||
)
|
)
|
||||||
matchingSubmodules;
|
matchingSubmodules;
|
||||||
|
|
||||||
matchingModule =
|
matchingModule =
|
||||||
if length versionSortedSubmodules == 0
|
if length versionSortedSubmodules == 0
|
||||||
then throw "No module found ${name}/${if version == null then "latest" else version}"
|
then
|
||||||
|
throw "No module found ${name}/${
|
||||||
|
if version == null
|
||||||
|
then "latest"
|
||||||
|
else version
|
||||||
|
}"
|
||||||
else head versionSortedSubmodules;
|
else head versionSortedSubmodules;
|
||||||
in
|
in
|
||||||
matchingModule;
|
matchingModule;
|
||||||
|
|
||||||
passthruConfig = mapAttrsToList
|
passthruConfig =
|
||||||
|
mapAttrsToList
|
||||||
(name: opt: {
|
(name: opt: {
|
||||||
${name} = mkMerge (mapAttrsToList
|
${name} = mkMerge (mapAttrsToList
|
||||||
(_: inst:
|
(
|
||||||
|
_: inst:
|
||||||
if inst.passthru.enable
|
if inst.passthru.enable
|
||||||
then inst.config.submodule.passthru.${name} or { }
|
then inst.config.submodule.passthru.${name} or {}
|
||||||
else { }
|
else {}
|
||||||
)
|
)
|
||||||
config.submodules.instances);
|
config.submodules.instances);
|
||||||
|
|
||||||
_module.args = mkMerge (mapAttrsToList
|
_module.args = mkMerge (mapAttrsToList
|
||||||
(_: inst:
|
(
|
||||||
|
_: inst:
|
||||||
if inst.passthru.enable
|
if inst.passthru.enable
|
||||||
then inst.config.submodule.passthru._module.args or { }
|
then inst.config.submodule.passthru._module.args or {}
|
||||||
else { }
|
else {}
|
||||||
)
|
)
|
||||||
config.submodules.instances);
|
config.submodules.instances);
|
||||||
})
|
})
|
||||||
(removeAttrs options [ "_definedNames" "_module" "_m" "submodules" ]);
|
(removeAttrs options ["_definedNames" "_module" "_m" "submodules"]);
|
||||||
|
|
||||||
submoduleWithSpecialArgs = opts: specialArgs:
|
submoduleWithSpecialArgs = opts: specialArgs: let
|
||||||
let
|
|
||||||
opts' = toList opts;
|
opts' = toList opts;
|
||||||
inherit (lib.modules) evalModules;
|
inherit (lib.modules) evalModules;
|
||||||
in
|
in
|
||||||
mkOptionType rec {
|
mkOptionType rec {
|
||||||
name = "submodule";
|
name = "submodule";
|
||||||
check = x: isAttrs x || isFunction x;
|
check = x: isAttrs x || isFunction x;
|
||||||
merge = loc: defs:
|
merge = loc: defs: let
|
||||||
let
|
coerce = def:
|
||||||
coerce = def: if isFunction def then def else { config = def; };
|
if isFunction def
|
||||||
modules = opts' ++ map (def: { _file = def.file; imports = [ (coerce def.value) ]; }) defs;
|
then def
|
||||||
|
else {config = def;};
|
||||||
|
modules =
|
||||||
|
opts'
|
||||||
|
++ map (def: {
|
||||||
|
_file = def.file;
|
||||||
|
imports = [(coerce def.value)];
|
||||||
|
})
|
||||||
|
defs;
|
||||||
in
|
in
|
||||||
(evalModules {
|
(evalModules {
|
||||||
inherit modules specialArgs;
|
inherit modules specialArgs;
|
||||||
prefix = loc;
|
prefix = loc;
|
||||||
}).config;
|
})
|
||||||
getSubOptions = prefix: (evalModules
|
.config;
|
||||||
|
getSubOptions = prefix:
|
||||||
|
(evalModules
|
||||||
{
|
{
|
||||||
modules = opts'; inherit prefix specialArgs;
|
modules = opts';
|
||||||
|
inherit prefix specialArgs;
|
||||||
# This is a work-around due to the fact that some sub-modules,
|
# 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"
|
# such as the one included in an attribute set, expects a "args"
|
||||||
# attribute to be given to the sub-module. As the option
|
# attribute to be given to the sub-module. As the option
|
||||||
|
|
@ -111,30 +152,32 @@ let
|
||||||
# would be used, and use of `<` and `>` would break the XML document.
|
# 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.
|
# It shouldn't cause an issue since this is cosmetic for the manual.
|
||||||
args.name = "‹name›";
|
args.name = "‹name›";
|
||||||
}).options;
|
})
|
||||||
|
.options;
|
||||||
getSubModules = opts';
|
getSubModules = opts';
|
||||||
substSubModules = m: submoduleWithSpecialArgs m specialArgs;
|
substSubModules = m: submoduleWithSpecialArgs m specialArgs;
|
||||||
functor = (defaultFunctor name) // {
|
functor =
|
||||||
|
(defaultFunctor name)
|
||||||
|
// {
|
||||||
# Merging of submodules is done as part of mergeOptionDecls, as we have to annotate
|
# Merging of submodules is done as part of mergeOptionDecls, as we have to annotate
|
||||||
# each submodule with its location.
|
# each submodule with its location.
|
||||||
payload = [ ];
|
payload = [];
|
||||||
binOp = lhs: rhs: [ ];
|
binOp = lhs: rhs: [];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in
|
in {
|
||||||
{
|
imports = [./base.nix];
|
||||||
imports = [ ./base.nix ];
|
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
submodules.specialArgs = mkOption {
|
submodules.specialArgs = mkOption {
|
||||||
description = "Special args to pass to submodules. These arguments can be used for imports";
|
description = "Special args to pass to submodules. These arguments can be used for imports";
|
||||||
type = types.attrs;
|
type = types.attrs;
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
submodules.defaults = mkOption {
|
submodules.defaults = mkOption {
|
||||||
description = "List of defaults to apply to submodule instances";
|
description = "List of defaults to apply to submodule instances";
|
||||||
type = types.listOf (types.submodule ({ config, ... }: {
|
type = types.listOf (types.submodule ({config, ...}: {
|
||||||
options = {
|
options = {
|
||||||
name = mkOption {
|
name = mkOption {
|
||||||
description = "Name of the submodule to apply defaults for";
|
description = "Name of the submodule to apply defaults for";
|
||||||
|
|
@ -154,23 +197,23 @@ in
|
||||||
tags = mkOption {
|
tags = mkOption {
|
||||||
description = "List of tags to apply defaults for";
|
description = "List of tags to apply defaults for";
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [ ];
|
default = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
features = mkOption {
|
features = mkOption {
|
||||||
description = "List of features that submodule has to have to apply defaults";
|
description = "List of features that submodule has to have to apply defaults";
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [ ];
|
default = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
default = mkOption {
|
default = mkOption {
|
||||||
description = "Default to apply to submodule instance";
|
description = "Default to apply to submodule instance";
|
||||||
type = types.unspecified;
|
type = types.unspecified;
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
default = [ ];
|
default = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
submodules.propagate.enable = mkOption {
|
submodules.propagate.enable = mkOption {
|
||||||
|
|
@ -184,12 +227,16 @@ in
|
||||||
type = types.listOf (
|
type = types.listOf (
|
||||||
types.coercedTo
|
types.coercedTo
|
||||||
types.path
|
types.path
|
||||||
(module: { inherit module; })
|
(module: {inherit module;})
|
||||||
(types.submodule ({ name, config, ... }:
|
(
|
||||||
let
|
types.submodule ({
|
||||||
|
name,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
evaledSubmodule' = evalModules {
|
evaledSubmodule' = evalModules {
|
||||||
inherit specialArgs;
|
inherit specialArgs;
|
||||||
modules = config.modules ++ [ ./base.nix ];
|
modules = config.modules ++ [./base.nix];
|
||||||
check = false;
|
check = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -197,8 +244,7 @@ in
|
||||||
if (!(elem "submodule" evaledSubmodule'.config._m.features))
|
if (!(elem "submodule" evaledSubmodule'.config._m.features))
|
||||||
then throw "no submodule defined"
|
then throw "no submodule defined"
|
||||||
else evaledSubmodule';
|
else evaledSubmodule';
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
options = {
|
options = {
|
||||||
module = mkOption {
|
module = mkOption {
|
||||||
description = "Module defining submodule";
|
description = "Module defining submodule";
|
||||||
|
|
@ -208,7 +254,7 @@ in
|
||||||
modules = mkOption {
|
modules = mkOption {
|
||||||
description = "List of modules defining submodule";
|
description = "List of modules defining submodule";
|
||||||
type = types.listOf types.unspecified;
|
type = types.listOf types.unspecified;
|
||||||
default = [ config.module ];
|
default = [config.module];
|
||||||
};
|
};
|
||||||
|
|
||||||
features = mkOption {
|
features = mkOption {
|
||||||
|
|
@ -238,14 +284,18 @@ in
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
default = [ ];
|
default = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
submodules.instances = mkOption {
|
submodules.instances = mkOption {
|
||||||
description = "Attribute set of submodule instances";
|
description = "Attribute set of submodule instances";
|
||||||
default = { };
|
default = {};
|
||||||
type = types.attrsOf (types.submodule ({ name, config, options, ... }:
|
type = types.attrsOf (types.submodule ({
|
||||||
let
|
name,
|
||||||
|
config,
|
||||||
|
options,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
# submodule associated with
|
# submodule associated with
|
||||||
submodule = findSubmodule {
|
submodule = findSubmodule {
|
||||||
name = config.submodule;
|
name = config.submodule;
|
||||||
|
|
@ -262,8 +312,7 @@ in
|
||||||
tags = submoduleDefinition.tags;
|
tags = submoduleDefinition.tags;
|
||||||
features = submodule.features;
|
features = submodule.features;
|
||||||
};
|
};
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
options = {
|
options = {
|
||||||
name = mkOption {
|
name = mkOption {
|
||||||
description = "Submodule instance name";
|
description = "Submodule instance name";
|
||||||
|
|
@ -294,16 +343,17 @@ in
|
||||||
|
|
||||||
config = mkOption {
|
config = mkOption {
|
||||||
description = "Submodule instance ${config.name} for ${submoduleDefinition.name}:${submoduleDefinition.version} config";
|
description = "Submodule instance ${config.name} for ${submoduleDefinition.name}:${submoduleDefinition.version} config";
|
||||||
type = submoduleWithSpecialArgs
|
type =
|
||||||
({ ... }: {
|
submoduleWithSpecialArgs
|
||||||
imports = submodule.modules ++ defaults ++ [ ./base.nix ];
|
({...}: {
|
||||||
|
imports = submodule.modules ++ defaults ++ [./base.nix];
|
||||||
_module.args.pkgs = pkgs;
|
_module.args.pkgs = pkgs;
|
||||||
_module.args.name = config.name;
|
_module.args.name = config.name;
|
||||||
_module.args.submodule = config;
|
_module.args.submodule = config;
|
||||||
submodule.args = mkAliasDefinitions options.args;
|
submodule.args = mkAliasDefinitions options.args;
|
||||||
})
|
})
|
||||||
specialArgs;
|
specialArgs;
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
args = mkOption {
|
args = mkOption {
|
||||||
|
|
@ -312,7 +362,7 @@ in
|
||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkMerge ([
|
config = mkMerge ([
|
||||||
|
|
@ -324,17 +374,19 @@ in
|
||||||
})
|
})
|
||||||
(filter (submodule: submodule.exportAs != null) cfg.imports));
|
(filter (submodule: submodule.exportAs != null) cfg.imports));
|
||||||
|
|
||||||
_m.features = [ "submodules" ];
|
_m.features = ["submodules"];
|
||||||
|
|
||||||
submodules.specialArgs.kubenix = kubenix;
|
submodules.specialArgs.kubenix = kubenix;
|
||||||
|
|
||||||
# passthru kubenix.project to submodules
|
# passthru kubenix.project to submodules
|
||||||
submodules.defaults = mkMerge [
|
submodules.defaults = mkMerge [
|
||||||
[{
|
[
|
||||||
|
{
|
||||||
default = {
|
default = {
|
||||||
kubenix.project = parentConfig.kubenix.project;
|
kubenix.project = parentConfig.kubenix.project;
|
||||||
};
|
};
|
||||||
}]
|
}
|
||||||
|
]
|
||||||
|
|
||||||
(map
|
(map
|
||||||
(propagate: {
|
(propagate: {
|
||||||
|
|
@ -347,15 +399,18 @@ in
|
||||||
|
|
||||||
(mkIf cfg.propagate.enable {
|
(mkIf cfg.propagate.enable {
|
||||||
# if propagate is enabled and submodule has submodules included propagage defaults and imports
|
# if propagate is enabled and submodule has submodules included propagage defaults and imports
|
||||||
submodules.defaults = [{
|
submodules.defaults = [
|
||||||
features = [ "submodules" ];
|
{
|
||||||
|
features = ["submodules"];
|
||||||
default = {
|
default = {
|
||||||
submodules = {
|
submodules = {
|
||||||
defaults = cfg.defaults;
|
defaults = cfg.defaults;
|
||||||
imports = cfg.imports;
|
imports = cfg.imports;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
})
|
})
|
||||||
] ++ passthruConfig);
|
]
|
||||||
|
++ passthruConfig);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
{ config, pkgs, lib, kubenix, ... }:
|
{
|
||||||
|
config,
|
||||||
with lib;
|
pkgs,
|
||||||
let
|
lib,
|
||||||
|
kubenix,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
cfg = config.testing;
|
cfg = config.testing;
|
||||||
|
|
||||||
testModule = {
|
testModule = {
|
||||||
imports = [ ./evalTest.nix ];
|
imports = [./evalTest.nix];
|
||||||
|
|
||||||
# passthru testing configuration
|
# passthru testing configuration
|
||||||
config._module.args = {
|
config._module.args = {
|
||||||
|
|
@ -16,9 +20,7 @@ let
|
||||||
|
|
||||||
isTestEnabled = test:
|
isTestEnabled = test:
|
||||||
(cfg.enabledTests == null || elem test.name cfg.enabledTests) && test.enable;
|
(cfg.enabledTests == null || elem test.name cfg.enabledTests) && test.enable;
|
||||||
|
in {
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = [
|
imports = [
|
||||||
./docker.nix
|
./docker.nix
|
||||||
./driver/kubetest.nix
|
./driver/kubetest.nix
|
||||||
|
|
@ -41,28 +43,28 @@ in
|
||||||
|
|
||||||
common = mkOption {
|
common = mkOption {
|
||||||
description = "List of common options to apply to tests";
|
description = "List of common options to apply to tests";
|
||||||
type = types.listOf (types.submodule ({ config, ... }: {
|
type = types.listOf (types.submodule ({config, ...}: {
|
||||||
options = {
|
options = {
|
||||||
features = mkOption {
|
features = mkOption {
|
||||||
description = "List of features that test has to have to apply options";
|
description = "List of features that test has to have to apply options";
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [ ];
|
default = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
options = mkOption {
|
options = mkOption {
|
||||||
description = "Options to apply to test";
|
description = "Options to apply to test";
|
||||||
type = types.unspecified;
|
type = types.unspecified;
|
||||||
default = { };
|
default = {};
|
||||||
apply = default: { _file = "testing.common"; } // default;
|
apply = default: {_file = "testing.common";} // default;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
default = [ ];
|
default = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
tests = mkOption {
|
tests = mkOption {
|
||||||
description = "List of test cases";
|
description = "List of test cases";
|
||||||
default = [ ];
|
default = [];
|
||||||
type = types.listOf (types.coercedTo types.path
|
type = types.listOf (types.coercedTo types.path
|
||||||
(module: {
|
(module: {
|
||||||
inherit module;
|
inherit module;
|
||||||
|
|
@ -86,7 +88,7 @@ in
|
||||||
args = mkOption {
|
args = mkOption {
|
||||||
description = "Attribute set of extra args passed to tests";
|
description = "Attribute set of extra args passed to tests";
|
||||||
type = types.attrs;
|
type = types.attrs;
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
success = mkOption {
|
success = mkOption {
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,17 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
with lib;
|
with lib;
|
||||||
with import ../../lib/docker { inherit lib pkgs; };
|
with import ../../lib/docker {inherit lib pkgs;}; let
|
||||||
let
|
|
||||||
testing = config.testing;
|
testing = 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;
|
cfg = config.testing.docker;
|
||||||
|
in {
|
||||||
in
|
|
||||||
{
|
|
||||||
options.testing.docker = {
|
options.testing.docker = {
|
||||||
registryUrl = mkOption {
|
registryUrl = mkOption {
|
||||||
description = "Docker registry url";
|
description = "Docker registry url";
|
||||||
|
|
@ -37,11 +38,13 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config.testing.common = [{
|
config.testing.common = [
|
||||||
features = [ "docker" ];
|
{
|
||||||
|
features = ["docker"];
|
||||||
options = {
|
options = {
|
||||||
_file = "testing.docker.registryUrl";
|
_file = "testing.docker.registryUrl";
|
||||||
docker.registry.url = cfg.registryUrl;
|
docker.registry.url = cfg.registryUrl;
|
||||||
};
|
};
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
{ pkgs ? import <nixpkgs> { } }:
|
{pkgs ? import <nixpkgs> {}}:
|
||||||
with pkgs;
|
with pkgs;
|
||||||
with pkgs.python38Packages;
|
with pkgs.python38Packages;
|
||||||
|
|
||||||
with pkgs.python38;
|
with pkgs.python38;
|
||||||
pkgs.python38Packages.buildPythonPackage rec {
|
pkgs.python38Packages.buildPythonPackage rec {
|
||||||
pname = "kubetest";
|
pname = "kubetest";
|
||||||
version = "0.9.5";
|
version = "0.9.5";
|
||||||
src = fetchPypi {
|
src = fetchPypi {
|
||||||
inherit pname version;
|
inherit pname version;
|
||||||
sha256 = "sha256-TqDHMciAEXv4vMWLJY1YdtXsP4ho+INgdFB3xQQNoZU=";
|
sha256 = "sha256-TqDHMciAEXv4vMWLJY1YdtXsP4ho+INgdFB3xQQNoZU=";
|
||||||
};
|
};
|
||||||
propagatedBuildInputs = [ pytest kubernetes ];
|
propagatedBuildInputs = [pytest kubernetes];
|
||||||
doCheck = false;
|
doCheck = false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
{ lib, config, testing, kubenix, ... }:
|
{
|
||||||
|
lib,
|
||||||
with lib;
|
config,
|
||||||
let
|
testing,
|
||||||
|
kubenix,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
modules = [
|
modules = [
|
||||||
# testing module
|
# testing module
|
||||||
config.module
|
config.module
|
||||||
|
|
@ -13,10 +17,12 @@ let
|
||||||
{
|
{
|
||||||
config = {
|
config = {
|
||||||
kubenix.project = mkDefault config.name;
|
kubenix.project = mkDefault config.name;
|
||||||
_module.args = {
|
_module.args =
|
||||||
|
{
|
||||||
inherit kubenix;
|
inherit kubenix;
|
||||||
test = evaled.config;
|
test = evaled.config;
|
||||||
} // testing.args;
|
}
|
||||||
|
// testing.args;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
@ -36,9 +42,11 @@ let
|
||||||
# common options that can be applied on this test
|
# common options that can be applied on this test
|
||||||
commonOpts =
|
commonOpts =
|
||||||
filter
|
filter
|
||||||
(d:
|
(
|
||||||
(intersectLists d.features testFeatures) == d.features ||
|
d:
|
||||||
(length d.features) == 0
|
(intersectLists d.features testFeatures)
|
||||||
|
== d.features
|
||||||
|
|| (length d.features) == 0
|
||||||
)
|
)
|
||||||
testing.common;
|
testing.common;
|
||||||
|
|
||||||
|
|
@ -46,18 +54,17 @@ let
|
||||||
modulesWithCommonOptions = modules ++ (map (d: d.options) commonOpts);
|
modulesWithCommonOptions = modules ++ (map (d: d.options) commonOpts);
|
||||||
|
|
||||||
# evaled test
|
# evaled test
|
||||||
evaled =
|
evaled = let
|
||||||
let
|
|
||||||
evaled' = kubenix.evalModules {
|
evaled' = kubenix.evalModules {
|
||||||
modules = modulesWithCommonOptions;
|
modules = modulesWithCommonOptions;
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
if testing.doThrowError then evaled'
|
if testing.doThrowError
|
||||||
|
then evaled'
|
||||||
else if (builtins.tryEval evaled'.config.test.assertions).success
|
else if (builtins.tryEval evaled'.config.test.assertions).success
|
||||||
then evaled' else null;
|
then evaled'
|
||||||
|
else null;
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
options = {
|
options = {
|
||||||
module = mkOption {
|
module = mkOption {
|
||||||
description = "Module defining kubenix test";
|
description = "Module defining kubenix test";
|
||||||
|
|
@ -100,7 +107,7 @@ in
|
||||||
description = "Test result";
|
description = "Test result";
|
||||||
type = types.unspecified;
|
type = types.unspecified;
|
||||||
internal = true;
|
internal = true;
|
||||||
default = [ ];
|
default = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
script = mkOption {
|
script = mkOption {
|
||||||
|
|
@ -108,7 +115,6 @@ in
|
||||||
type = types.nullOr (types.either types.lines types.path);
|
type = types.nullOr (types.either types.lines types.path);
|
||||||
internal = true;
|
internal = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkMerge [
|
config = mkMerge [
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
{ lib, config, pkgs, ... }:
|
{
|
||||||
|
lib,
|
||||||
with lib;
|
config,
|
||||||
let
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
testing = config.testing;
|
testing = config.testing;
|
||||||
|
|
||||||
script = pkgs.writeScript "run-local-k8s-tests-${testing.name}.sh" ''
|
script = pkgs.writeScript "run-local-k8s-tests-${testing.name}.sh" ''
|
||||||
|
|
@ -31,8 +34,7 @@ let
|
||||||
echo "--> running tests"
|
echo "--> running tests"
|
||||||
${testing.testScript} --kube-config=$KUBECONFIG
|
${testing.testScript} --kube-config=$KUBECONFIG
|
||||||
'';
|
'';
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
options.testing.runtime.local = {
|
options.testing.runtime.local = {
|
||||||
script = mkOption {
|
script = mkOption {
|
||||||
type = types.package;
|
type = types.package;
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,32 @@
|
||||||
# nixos-k8s implements nixos kubernetes testing runtime
|
# nixos-k8s implements nixos kubernetes testing runtime
|
||||||
|
{
|
||||||
{ config
|
config,
|
||||||
, pkgs
|
pkgs,
|
||||||
, lib
|
lib,
|
||||||
, ...
|
...
|
||||||
}:
|
}:
|
||||||
|
with lib; let
|
||||||
with lib;
|
|
||||||
let
|
|
||||||
testing = config.testing;
|
testing = config.testing;
|
||||||
# kubeconfig = "/etc/${config.services.kubernetes.pki.etcClusterAdminKubeconfig}";
|
# kubeconfig = "/etc/${config.services.kubernetes.pki.etcClusterAdminKubeconfig}";
|
||||||
kubeconfig = "/etc/kubernetes/cluster-admin.kubeconfig";
|
kubeconfig = "/etc/kubernetes/cluster-admin.kubeconfig";
|
||||||
kubecerts = "/var/lib/kubernetes/secrets";
|
kubecerts = "/var/lib/kubernetes/secrets";
|
||||||
|
|
||||||
# how we differ from the standard configuration of mkKubernetesBaseTest
|
# how we differ from the standard configuration of mkKubernetesBaseTest
|
||||||
extraConfiguration = { config, pkgs, lib, nodes, ... }: {
|
extraConfiguration = {
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
nodes,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
virtualisation = {
|
virtualisation = {
|
||||||
memorySize = 2048;
|
memorySize = 2048;
|
||||||
};
|
};
|
||||||
|
|
||||||
networking = {
|
networking = {
|
||||||
nameservers = [ "10.0.0.254" ];
|
nameservers = ["10.0.0.254"];
|
||||||
firewall = {
|
firewall = {
|
||||||
trustedInterfaces = [ "docker0" "cni0" ];
|
trustedInterfaces = ["docker0" "cni0"];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -32,7 +35,8 @@ let
|
||||||
kubelet = {
|
kubelet = {
|
||||||
seedDockerImages = testing.docker.images;
|
seedDockerImages = testing.docker.images;
|
||||||
networkPlugin = "cni";
|
networkPlugin = "cni";
|
||||||
cni.config = [{
|
cni.config = [
|
||||||
|
{
|
||||||
name = "mynet";
|
name = "mynet";
|
||||||
type = "bridge";
|
type = "bridge";
|
||||||
bridge = "cni0";
|
bridge = "cni0";
|
||||||
|
|
@ -43,11 +47,14 @@ let
|
||||||
type = "host-local";
|
type = "host-local";
|
||||||
subnet = "10.1.0.0/16";
|
subnet = "10.1.0.0/16";
|
||||||
gateway = "10.1.0.1";
|
gateway = "10.1.0.1";
|
||||||
routes = [{
|
routes = [
|
||||||
|
{
|
||||||
dst = "0.0.0.0/0";
|
dst = "0.0.0.0/0";
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -57,32 +64,30 @@ let
|
||||||
services.copy-certs = {
|
services.copy-certs = {
|
||||||
description = "Share k8s certificates with host";
|
description = "Share k8s certificates with host";
|
||||||
script = "cp -rf ${kubecerts} /tmp/xchg/; cp -f ${kubeconfig} /tmp/xchg/;";
|
script = "cp -rf ${kubecerts} /tmp/xchg/; cp -f ${kubeconfig} /tmp/xchg/;";
|
||||||
after = [ "kubernetes.target" ];
|
after = ["kubernetes.target"];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = ["multi-user.target"];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
RemainAfterExit = true;
|
RemainAfterExit = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
script = ''
|
script = ''
|
||||||
machine1.succeed("${testing.testScript} --kube-config=${kubeconfig}")
|
machine1.succeed("${testing.testScript} --kube-config=${kubeconfig}")
|
||||||
'';
|
'';
|
||||||
|
|
||||||
test =
|
test = with import "${pkgs.path}/nixos/tests/kubernetes/base.nix" {
|
||||||
with import "${pkgs.path}/nixos/tests/kubernetes/base.nix" { inherit pkgs; inherit (pkgs) system; };
|
inherit pkgs;
|
||||||
|
inherit (pkgs) system;
|
||||||
|
};
|
||||||
mkKubernetesSingleNodeTest {
|
mkKubernetesSingleNodeTest {
|
||||||
inherit extraConfiguration;
|
inherit extraConfiguration;
|
||||||
inherit (config.testing) name;
|
inherit (config.testing) name;
|
||||||
test = script;
|
test = script;
|
||||||
};
|
};
|
||||||
|
in {
|
||||||
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.testing.runtime.nixos-k8s = {
|
options.testing.runtime.nixos-k8s = {
|
||||||
driver = mkOption {
|
driver = mkOption {
|
||||||
description = "Test driver";
|
description = "Test driver";
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
{ lib, config, pkgs, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
let
|
|
||||||
cfg = config.test;
|
|
||||||
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
|
cfg = config.test;
|
||||||
|
in {
|
||||||
options.test = {
|
options.test = {
|
||||||
name = mkOption {
|
name = mkOption {
|
||||||
description = "Test name";
|
description = "Test name";
|
||||||
|
|
@ -38,8 +39,13 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
default = [ ];
|
default = [];
|
||||||
example = [{ assertion = false; message = "you can't enable this for some reason"; }];
|
example = [
|
||||||
|
{
|
||||||
|
assertion = false;
|
||||||
|
message = "you can't enable this for some reason";
|
||||||
|
}
|
||||||
|
];
|
||||||
description = ''
|
description = ''
|
||||||
This option allows modules to express conditions that must
|
This option allows modules to express conditions that must
|
||||||
hold for the evaluation of the system configuration to
|
hold for the evaluation of the system configuration to
|
||||||
|
|
@ -52,6 +58,5 @@ in
|
||||||
type = types.nullOr (types.either types.lines types.path);
|
type = types.nullOr (types.either types.lines types.path);
|
||||||
default = null;
|
default = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
{ stdenv, kubernetes, installShellFiles }:
|
{
|
||||||
|
stdenv,
|
||||||
|
kubernetes,
|
||||||
|
installShellFiles,
|
||||||
|
}:
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
name = "kubectl-${kubernetes.version}";
|
name = "kubectl-${kubernetes.version}";
|
||||||
|
|
||||||
|
|
@ -7,9 +10,9 @@ stdenv.mkDerivation {
|
||||||
# split out (see homepage)
|
# split out (see homepage)
|
||||||
dontUnpack = true;
|
dontUnpack = true;
|
||||||
|
|
||||||
nativeBuildInputs = [ installShellFiles ];
|
nativeBuildInputs = [installShellFiles];
|
||||||
|
|
||||||
outputs = [ "out" "man" ];
|
outputs = ["out" "man"];
|
||||||
|
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
install -D ${kubernetes}/bin/kubectl -t $out/bin
|
install -D ${kubernetes}/bin/kubectl -t $out/bin
|
||||||
|
|
@ -22,7 +25,9 @@ stdenv.mkDerivation {
|
||||||
done
|
done
|
||||||
'';
|
'';
|
||||||
|
|
||||||
meta = kubernetes.meta // {
|
meta =
|
||||||
|
kubernetes.meta
|
||||||
|
// {
|
||||||
description = "Kubernetes CLI";
|
description = "Kubernetes CLI";
|
||||||
homepage = "https://github.com/kubernetes/kubectl";
|
homepage = "https://github.com/kubernetes/kubectl";
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,22 @@
|
||||||
{ stdenv
|
{
|
||||||
, lib
|
stdenv,
|
||||||
, fetchFromGitHub
|
lib,
|
||||||
, removeReferencesTo
|
fetchFromGitHub,
|
||||||
, which
|
removeReferencesTo,
|
||||||
, go
|
which,
|
||||||
, makeWrapper
|
go,
|
||||||
, rsync
|
makeWrapper,
|
||||||
, installShellFiles
|
rsync,
|
||||||
|
installShellFiles,
|
||||||
, components ? [
|
components ? [
|
||||||
"cmd/kubelet"
|
"cmd/kubelet"
|
||||||
"cmd/kube-apiserver"
|
"cmd/kube-apiserver"
|
||||||
"cmd/kube-controller-manager"
|
"cmd/kube-controller-manager"
|
||||||
"cmd/kube-proxy"
|
"cmd/kube-proxy"
|
||||||
"cmd/kube-scheduler"
|
"cmd/kube-scheduler"
|
||||||
"test/e2e/e2e.test"
|
"test/e2e/e2e.test"
|
||||||
]
|
],
|
||||||
}:
|
}:
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "kubernetes";
|
pname = "kubernetes";
|
||||||
version = "1.20.4";
|
version = "1.20.4";
|
||||||
|
|
@ -29,11 +28,11 @@ stdenv.mkDerivation rec {
|
||||||
hash = "sha256-r9Clwr+87Ns4VXUW9F6cgks+LknY39ngbQgZ5UMZ0Vo=";
|
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 = ''
|
postPatch = ''
|
||||||
# go env breaks the sandbox
|
# go env breaks the sandbox
|
||||||
|
|
@ -51,7 +50,8 @@ stdenv.mkDerivation rec {
|
||||||
WHAT = lib.concatStringsSep " " ([
|
WHAT = lib.concatStringsSep " " ([
|
||||||
"cmd/kubeadm"
|
"cmd/kubeadm"
|
||||||
"cmd/kubectl"
|
"cmd/kubectl"
|
||||||
] ++ components);
|
]
|
||||||
|
++ components);
|
||||||
|
|
||||||
postBuild = ''
|
postBuild = ''
|
||||||
./hack/update-generated-docs.sh
|
./hack/update-generated-docs.sh
|
||||||
|
|
@ -84,7 +84,7 @@ stdenv.mkDerivation rec {
|
||||||
description = "Production-Grade Container Scheduling and Management";
|
description = "Production-Grade Container Scheduling and Management";
|
||||||
license = licenses.asl20;
|
license = licenses.asl20;
|
||||||
homepage = "https://kubernetes.io";
|
homepage = "https://kubernetes.io";
|
||||||
maintainers = with maintainers; [ johanot offline saschagrunert ];
|
maintainers = with maintainers; [johanot offline saschagrunert];
|
||||||
platforms = platforms.unix;
|
platforms = platforms.unix;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
{ system ? builtins.currentSystem }:
|
{system ? builtins.currentSystem}: let
|
||||||
let
|
|
||||||
in
|
in
|
||||||
(
|
(
|
||||||
(import ./compat.nix).flake-compat {
|
(import ./compat.nix).flake-compat {
|
||||||
src = ./.;
|
src = ./.;
|
||||||
inherit system;
|
inherit system;
|
||||||
}
|
}
|
||||||
).shellNix
|
)
|
||||||
|
.shellNix
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
{ system ? builtins.currentSystem
|
{
|
||||||
, evalModules ? (import ../. { }).evalModules.${system}
|
system ? builtins.currentSystem,
|
||||||
}:
|
evalModules ? (import ../. {}).evalModules.${system},
|
||||||
|
}: {
|
||||||
{ k8sVersion ? "1.21"
|
k8sVersion ? "1.21",
|
||||||
, registry ? throw "Registry url not defined"
|
registry ? throw "Registry url not defined",
|
||||||
, doThrowError ? true # whether any testing error should throw an error
|
doThrowError ? true, # whether any testing error should throw an error
|
||||||
, enabledTests ? null
|
enabledTests ? null,
|
||||||
}:
|
}: let
|
||||||
|
config =
|
||||||
let
|
(evalModules {
|
||||||
config = (evalModules {
|
module = {
|
||||||
|
kubenix,
|
||||||
module =
|
pkgs,
|
||||||
{ kubenix, pkgs, ... }: {
|
...
|
||||||
|
}: {
|
||||||
imports = [ kubenix.modules.testing ];
|
imports = [kubenix.modules.testing];
|
||||||
|
|
||||||
testing = {
|
testing = {
|
||||||
inherit doThrowError enabledTests;
|
inherit doThrowError enabledTests;
|
||||||
|
|
@ -36,21 +36,20 @@ let
|
||||||
./submodules/passthru.nix
|
./submodules/passthru.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
args = { images = pkgs.callPackage ./images.nix { }; };
|
args = {images = pkgs.callPackage ./images.nix {};};
|
||||||
docker.registryUrl = registry;
|
docker.registryUrl = registry;
|
||||||
|
|
||||||
common = [
|
common = [
|
||||||
{
|
{
|
||||||
features = [ "k8s" ];
|
features = ["k8s"];
|
||||||
options = {
|
options = {
|
||||||
kubernetes.version = k8sVersion;
|
kubernetes.version = k8sVersion;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
})
|
||||||
}).config;
|
.config;
|
||||||
in
|
in
|
||||||
config.testing // { recurseForDerivations = true; }
|
config.testing // {recurseForDerivations = true;}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,18 @@
|
||||||
{ pkgs, dockerTools, lib, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
|
pkgs,
|
||||||
|
dockerTools,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; {
|
||||||
curl = dockerTools.buildLayeredImage {
|
curl = dockerTools.buildLayeredImage {
|
||||||
name = "curl";
|
name = "curl";
|
||||||
tag = "latest";
|
tag = "latest";
|
||||||
config.Cmd = [ "${pkgs.bash}" "-c" "sleep infinity" ];
|
config.Cmd = ["${pkgs.bash}" "-c" "sleep infinity"];
|
||||||
contents = [ pkgs.bash pkgs.curl pkgs.cacert ];
|
contents = [pkgs.bash pkgs.curl pkgs.cacert];
|
||||||
};
|
};
|
||||||
|
|
||||||
nginx =
|
nginx = let
|
||||||
let
|
|
||||||
nginxPort = "80";
|
nginxPort = "80";
|
||||||
nginxConf = pkgs.writeText "nginx.conf" ''
|
nginxConf = pkgs.writeText "nginx.conf" ''
|
||||||
user nginx nginx;
|
user nginx nginx;
|
||||||
|
|
@ -37,7 +38,7 @@ with lib;
|
||||||
dockerTools.buildLayeredImage {
|
dockerTools.buildLayeredImage {
|
||||||
name = "xtruder/nginx";
|
name = "xtruder/nginx";
|
||||||
tag = "latest";
|
tag = "latest";
|
||||||
contents = [ pkgs.nginx ];
|
contents = [pkgs.nginx];
|
||||||
extraCommands = ''
|
extraCommands = ''
|
||||||
mkdir -p etc
|
mkdir -p etc
|
||||||
chmod u+w etc
|
chmod u+w etc
|
||||||
|
|
@ -49,9 +50,9 @@ with lib;
|
||||||
echo "nginx:x:1000:nginx" > etc/group
|
echo "nginx:x:1000:nginx" > etc/group
|
||||||
'';
|
'';
|
||||||
config = {
|
config = {
|
||||||
Cmd = [ "nginx" "-c" nginxConf ];
|
Cmd = ["nginx" "-c" nginxConf];
|
||||||
ExposedPorts = {
|
ExposedPorts = {
|
||||||
"${nginxPort}/tcp" = { };
|
"${nginxPort}/tcp" = {};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
{ config, kubenix, ... }:
|
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = with kubenix.modules; [ test k8s istio ];
|
config,
|
||||||
|
kubenix,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
imports = with kubenix.modules; [test k8s istio];
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
name = "istio-bookinfo";
|
name = "istio-bookinfo";
|
||||||
|
|
@ -12,23 +14,27 @@
|
||||||
Gateway."bookinfo-gateway" = {
|
Gateway."bookinfo-gateway" = {
|
||||||
spec = {
|
spec = {
|
||||||
selector.istio = "ingressgateway";
|
selector.istio = "ingressgateway";
|
||||||
servers = [{
|
servers = [
|
||||||
|
{
|
||||||
port = {
|
port = {
|
||||||
number = 80;
|
number = 80;
|
||||||
name = "http";
|
name = "http";
|
||||||
protocol = "HTTP";
|
protocol = "HTTP";
|
||||||
};
|
};
|
||||||
hosts = [ "*" ];
|
hosts = ["*"];
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
VirtualService.bookinfo = {
|
VirtualService.bookinfo = {
|
||||||
spec = {
|
spec = {
|
||||||
hosts = [ "*" ];
|
hosts = ["*"];
|
||||||
gateways = [ "bookinfo-gateway" ];
|
gateways = ["bookinfo-gateway"];
|
||||||
http = [{
|
http = [
|
||||||
match = [{
|
{
|
||||||
|
match = [
|
||||||
|
{
|
||||||
uri.exact = "/productpage";
|
uri.exact = "/productpage";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
|
@ -39,31 +45,38 @@
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
uri.prefix = "/api/v1/products";
|
uri.prefix = "/api/v1/products";
|
||||||
}];
|
}
|
||||||
route = [{
|
];
|
||||||
|
route = [
|
||||||
|
{
|
||||||
destination = {
|
destination = {
|
||||||
host = "productpage";
|
host = "productpage";
|
||||||
port.number = 9080;
|
port.number = 9080;
|
||||||
};
|
};
|
||||||
}];
|
}
|
||||||
}];
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
DestinationRule.productpage = {
|
DestinationRule.productpage = {
|
||||||
spec = {
|
spec = {
|
||||||
host = "productpage";
|
host = "productpage";
|
||||||
subsets = [{
|
subsets = [
|
||||||
|
{
|
||||||
name = "v1";
|
name = "v1";
|
||||||
labels.version = "v1";
|
labels.version = "v1";
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
DestinationRule.reviews = {
|
DestinationRule.reviews = {
|
||||||
spec = {
|
spec = {
|
||||||
host = "reviews";
|
host = "reviews";
|
||||||
subsets = [{
|
subsets = [
|
||||||
|
{
|
||||||
name = "v1";
|
name = "v1";
|
||||||
labels.version = "v1";
|
labels.version = "v1";
|
||||||
}
|
}
|
||||||
|
|
@ -74,14 +87,16 @@
|
||||||
{
|
{
|
||||||
name = "v3";
|
name = "v3";
|
||||||
labels.version = "v3";
|
labels.version = "v3";
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
DestinationRule.ratings = {
|
DestinationRule.ratings = {
|
||||||
spec = {
|
spec = {
|
||||||
host = "ratings";
|
host = "ratings";
|
||||||
subsets = [{
|
subsets = [
|
||||||
|
{
|
||||||
name = "v1";
|
name = "v1";
|
||||||
labels.version = "v1";
|
labels.version = "v1";
|
||||||
}
|
}
|
||||||
|
|
@ -96,21 +111,24 @@
|
||||||
{
|
{
|
||||||
name = "v2-mysql-vm";
|
name = "v2-mysql-vm";
|
||||||
labels.version = "v2-mysql-vm";
|
labels.version = "v2-mysql-vm";
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
DestinationRule.details = {
|
DestinationRule.details = {
|
||||||
spec = {
|
spec = {
|
||||||
host = "details";
|
host = "details";
|
||||||
subsets = [{
|
subsets = [
|
||||||
|
{
|
||||||
name = "v1";
|
name = "v1";
|
||||||
labels.version = "v1";
|
labels.version = "v1";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
name = "v2";
|
name = "v2";
|
||||||
labels.version = "v2";
|
labels.version = "v2";
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,25 @@
|
||||||
{ config, lib, kubenix, pkgs, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
let
|
|
||||||
latestCrontab = config.kubernetes.api.resources.cronTabs.latest;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
imports = with kubenix.modules; [ test k8s ];
|
config,
|
||||||
|
lib,
|
||||||
|
kubenix,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
|
latestCrontab = config.kubernetes.api.resources.cronTabs.latest;
|
||||||
|
in {
|
||||||
|
imports = with kubenix.modules; [test k8s];
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
name = "k8s-crd";
|
name = "k8s-crd";
|
||||||
description = "Simple test tesing CRD";
|
description = "Simple test tesing CRD";
|
||||||
enable = builtins.compareVersions config.kubernetes.version "1.8" >= 0;
|
enable = builtins.compareVersions config.kubernetes.version "1.8" >= 0;
|
||||||
assertions = [{
|
assertions = [
|
||||||
|
{
|
||||||
message = "Custom resource should have correct version set";
|
message = "Custom resource should have correct version set";
|
||||||
assertion = latestCrontab.apiVersion == "stable.example.com/v2";
|
assertion = latestCrontab.apiVersion == "stable.example.com/v2";
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
script = ''
|
script = ''
|
||||||
@pytest.mark.applymanifest('${config.kubernetes.resultYAML}')
|
@pytest.mark.applymanifest('${config.kubernetes.resultYAML}')
|
||||||
def test_testing_module(kube):
|
def test_testing_module(kube):
|
||||||
|
|
@ -50,7 +55,6 @@ in
|
||||||
type = types.str;
|
type = types.str;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
group = "stable.example.com";
|
group = "stable.example.com";
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,20 @@
|
||||||
{ config, lib, kubenix, ... }:
|
{
|
||||||
|
config,
|
||||||
with lib;
|
lib,
|
||||||
let
|
kubenix,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
pod1 = config.kubernetes.api.resources.pods.pod1;
|
pod1 = config.kubernetes.api.resources.pods.pod1;
|
||||||
pod2 = config.kubernetes.api.resources.pods.pod2;
|
pod2 = config.kubernetes.api.resources.pods.pod2;
|
||||||
in
|
in {
|
||||||
{
|
imports = with kubenix.modules; [test k8s];
|
||||||
imports = with kubenix.modules; [ test k8s ];
|
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
name = "k8s-defaults";
|
name = "k8s-defaults";
|
||||||
description = "Simple k8s testing wheter name, apiVersion and kind are preset";
|
description = "Simple k8s testing wheter name, apiVersion and kind are preset";
|
||||||
assertions = [{
|
assertions = [
|
||||||
|
{
|
||||||
message = "Should have label set with resource";
|
message = "Should have label set with resource";
|
||||||
assertion = pod1.metadata.labels.resource-label == "value";
|
assertion = pod1.metadata.labels.resource-label == "value";
|
||||||
}
|
}
|
||||||
|
|
@ -22,16 +25,18 @@ in
|
||||||
{
|
{
|
||||||
message = "Should have conditional annotation set";
|
message = "Should have conditional annotation set";
|
||||||
assertion = pod2.metadata.annotations.conditional-annotation == "value";
|
assertion = pod2.metadata.annotations.conditional-annotation == "value";
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
kubernetes.resources.pods.pod1 = { };
|
kubernetes.resources.pods.pod1 = {};
|
||||||
|
|
||||||
kubernetes.resources.pods.pod2 = {
|
kubernetes.resources.pods.pod2 = {
|
||||||
metadata.labels.custom-label = "value";
|
metadata.labels.custom-label = "value";
|
||||||
};
|
};
|
||||||
|
|
||||||
kubernetes.api.defaults = [{
|
kubernetes.api.defaults = [
|
||||||
|
{
|
||||||
resource = "pods";
|
resource = "pods";
|
||||||
default.metadata.labels.resource-label = "value";
|
default.metadata.labels.resource-label = "value";
|
||||||
}
|
}
|
||||||
|
|
@ -43,10 +48,11 @@ in
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
resource = "pods";
|
resource = "pods";
|
||||||
default = { config, ... }: {
|
default = {config, ...}: {
|
||||||
config.metadata.annotations = mkIf (config.metadata.labels ? "custom-label") {
|
config.metadata.annotations = mkIf (config.metadata.labels ? "custom-label") {
|
||||||
conditional-annotation = "value";
|
conditional-annotation = "value";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,13 @@
|
||||||
{ config, lib, pkgs, kubenix, images, test, ... }:
|
{
|
||||||
|
config,
|
||||||
with lib;
|
lib,
|
||||||
let
|
pkgs,
|
||||||
|
kubenix,
|
||||||
|
images,
|
||||||
|
test,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
cfg = config.kubernetes.api.resources.deployments.nginx;
|
cfg = config.kubernetes.api.resources.deployments.nginx;
|
||||||
image = images.nginx;
|
image = images.nginx;
|
||||||
|
|
||||||
|
|
@ -12,22 +18,23 @@ let
|
||||||
namespace = config.kubernetes.namespace;
|
namespace = config.kubernetes.namespace;
|
||||||
name = "curl";
|
name = "curl";
|
||||||
};
|
};
|
||||||
spec.containers = [{
|
spec.containers = [
|
||||||
|
{
|
||||||
name = "curl";
|
name = "curl";
|
||||||
image = config.docker.images.curl.path;
|
image = config.docker.images.curl.path;
|
||||||
args = [ "curl" "--retry" "20" "--retry-connrefused" "http://nginx" ];
|
args = ["curl" "--retry" "20" "--retry-connrefused" "http://nginx"];
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
spec.restartPolicy = "Never";
|
spec.restartPolicy = "Never";
|
||||||
});
|
});
|
||||||
|
in {
|
||||||
in
|
imports = [kubenix.modules.test kubenix.modules.k8s kubenix.modules.docker];
|
||||||
{
|
|
||||||
imports = [ kubenix.modules.test kubenix.modules.k8s kubenix.modules.docker ];
|
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
name = "k8s-deployment";
|
name = "k8s-deployment";
|
||||||
description = "Simple k8s testing a simple deployment";
|
description = "Simple k8s testing a simple deployment";
|
||||||
assertions = [{
|
assertions = [
|
||||||
|
{
|
||||||
message = "should have correct apiVersion and kind set";
|
message = "should have correct apiVersion and kind set";
|
||||||
assertion =
|
assertion =
|
||||||
if ((builtins.compareVersions config.kubernetes.version "1.7") <= 0)
|
if ((builtins.compareVersions config.kubernetes.version "1.7") <= 0)
|
||||||
|
|
@ -43,7 +50,8 @@ in
|
||||||
{
|
{
|
||||||
message = "should have replicas set";
|
message = "should have replicas set";
|
||||||
assertion = cfg.spec.replicas == 3;
|
assertion = cfg.spec.replicas == 3;
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
script = ''
|
script = ''
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
|
@ -97,10 +105,12 @@ in
|
||||||
|
|
||||||
kubernetes.resources.services.nginx = {
|
kubernetes.resources.services.nginx = {
|
||||||
spec = {
|
spec = {
|
||||||
ports = [{
|
ports = [
|
||||||
|
{
|
||||||
name = "http";
|
name = "http";
|
||||||
port = 80;
|
port = 80;
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
selector.app = "nginx";
|
selector.app = "nginx";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,29 @@
|
||||||
{ config, lib, kubenix, ... }:
|
{
|
||||||
|
config,
|
||||||
with lib;
|
lib,
|
||||||
let
|
kubenix,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
pod = config.kubernetes.api.resources.core.v1.Pod.test;
|
pod = config.kubernetes.api.resources.core.v1.Pod.test;
|
||||||
deployment = config.kubernetes.api.resources.apps.v1.Deployment.nginx-deployment;
|
deployment = config.kubernetes.api.resources.apps.v1.Deployment.nginx-deployment;
|
||||||
in
|
in {
|
||||||
{
|
imports = with kubenix.modules; [test k8s];
|
||||||
imports = with kubenix.modules; [ test k8s ];
|
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
name = "k8s-imports";
|
name = "k8s-imports";
|
||||||
description = "Simple k8s testing imports";
|
description = "Simple k8s testing imports";
|
||||||
enable = builtins.compareVersions config.kubernetes.version "1.10" >= 0;
|
enable = builtins.compareVersions config.kubernetes.version "1.10" >= 0;
|
||||||
assertions = [{
|
assertions = [
|
||||||
|
{
|
||||||
message = "Pod should have name set";
|
message = "Pod should have name set";
|
||||||
assertion = pod.metadata.name == "test";
|
assertion = pod.metadata.name == "test";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
message = "Deployment should have name set";
|
message = "Deployment should have name set";
|
||||||
assertion = deployment.metadata.name == "nginx-deployment";
|
assertion = deployment.metadata.name == "nginx-deployment";
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
kubernetes.imports = [
|
kubernetes.imports = [
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,28 @@
|
||||||
{ config, lib, kubenix, pkgs, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
let
|
|
||||||
cfg = config.kubernetes.api.resources.customResourceDefinitions.crontabs;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
imports = with kubenix.modules; [ test k8s ];
|
config,
|
||||||
|
lib,
|
||||||
|
kubenix,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
|
cfg = config.kubernetes.api.resources.customResourceDefinitions.crontabs;
|
||||||
|
in {
|
||||||
|
imports = with kubenix.modules; [test k8s];
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
name = "k8s-order";
|
name = "k8s-order";
|
||||||
description = "test tesing k8s resource order";
|
description = "test tesing k8s resource order";
|
||||||
assertions = [{
|
assertions = [
|
||||||
|
{
|
||||||
message = "should have correct order of resources";
|
message = "should have correct order of resources";
|
||||||
assertion =
|
assertion =
|
||||||
(elemAt config.kubernetes.objects 0).kind == "CustomResourceDefinition" &&
|
(elemAt config.kubernetes.objects 0).kind
|
||||||
(elemAt config.kubernetes.objects 1).kind == "Namespace" &&
|
== "CustomResourceDefinition"
|
||||||
(elemAt config.kubernetes.objects 2).kind == "CronTab";
|
&& (elemAt config.kubernetes.objects 1).kind == "Namespace"
|
||||||
}];
|
&& (elemAt config.kubernetes.objects 2).kind == "CronTab";
|
||||||
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
kubernetes.resources.customResourceDefinitions.crontabs = {
|
kubernetes.resources.customResourceDefinitions.crontabs = {
|
||||||
|
|
@ -24,22 +30,25 @@ in
|
||||||
metadata.name = "crontabs.stable.example.com";
|
metadata.name = "crontabs.stable.example.com";
|
||||||
spec = {
|
spec = {
|
||||||
group = "stable.example.com";
|
group = "stable.example.com";
|
||||||
versions = [{
|
versions = [
|
||||||
|
{
|
||||||
name = "v1";
|
name = "v1";
|
||||||
served = true;
|
served = true;
|
||||||
schema = true;
|
schema = true;
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
scope = "Namespaced";
|
scope = "Namespaced";
|
||||||
names = {
|
names = {
|
||||||
plural = "crontabs";
|
plural = "crontabs";
|
||||||
singular = "crontab";
|
singular = "crontab";
|
||||||
kind = "CronTab";
|
kind = "CronTab";
|
||||||
shortNames = [ "ct" ];
|
shortNames = ["ct"];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
kubernetes.customTypes = [{
|
kubernetes.customTypes = [
|
||||||
|
{
|
||||||
name = "crontabs";
|
name = "crontabs";
|
||||||
description = "CronTabs resources";
|
description = "CronTabs resources";
|
||||||
|
|
||||||
|
|
@ -53,9 +62,10 @@ in
|
||||||
type = types.str;
|
type = types.str;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
|
||||||
kubernetes.resources.namespaces.test = { };
|
kubernetes.resources.namespaces.test = {};
|
||||||
|
|
||||||
kubernetes.resources."stable.example.com"."v1".CronTab.crontab.spec.schedule = "* * * * *";
|
kubernetes.resources."stable.example.com"."v1".CronTab.crontab.spec.schedule = "* * * * *";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,26 @@
|
||||||
{ config, kubenix, ... }:
|
|
||||||
let
|
|
||||||
cfg = config.kubernetes.api.resources.pods.nginx;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
imports = [ kubenix.modules.test kubenix.modules.k8s ];
|
config,
|
||||||
|
kubenix,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
cfg = config.kubernetes.api.resources.pods.nginx;
|
||||||
|
in {
|
||||||
|
imports = [kubenix.modules.test kubenix.modules.k8s];
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
name = "k8s-simple";
|
name = "k8s-simple";
|
||||||
description = "Simple k8s testing wheter name, apiVersion and kind are preset";
|
description = "Simple k8s testing wheter name, apiVersion and kind are preset";
|
||||||
assertions = [{
|
assertions = [
|
||||||
|
{
|
||||||
message = "should have apiVersion and kind set";
|
message = "should have apiVersion and kind set";
|
||||||
assertion = cfg.apiVersion == "v1" && cfg.kind == "Pod";
|
assertion = cfg.apiVersion == "v1" && cfg.kind == "Pod";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
message = "should have name set";
|
message = "should have name set";
|
||||||
assertion = cfg.metadata.name == "nginx";
|
assertion = cfg.metadata.name == "nginx";
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
kubernetes.resources.pods.nginx = { };
|
kubernetes.resources.pods.nginx = {};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,41 @@
|
||||||
{ name, config, lib, kubenix, images, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
let
|
|
||||||
cfg = config.submodules.instances.passthru;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
imports = with kubenix.modules; [ test submodules k8s docker ];
|
name,
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
kubenix,
|
||||||
|
images,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
|
cfg = config.submodules.instances.passthru;
|
||||||
|
in {
|
||||||
|
imports = with kubenix.modules; [test submodules k8s docker];
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
name = "k8s-submodule";
|
name = "k8s-submodule";
|
||||||
description = "Simple k8s submodule test";
|
description = "Simple k8s submodule test";
|
||||||
assertions = [{
|
assertions = [
|
||||||
|
{
|
||||||
message = "Submodule has correct name set";
|
message = "Submodule has correct name set";
|
||||||
assertion = (head config.kubernetes.objects).metadata.name == "passthru";
|
assertion = (head config.kubernetes.objects).metadata.name == "passthru";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
message = "Should expose docker image";
|
message = "Should expose docker image";
|
||||||
assertion = (head config.docker.export).imageName == "xtruder/nginx";
|
assertion = (head config.docker.export).imageName == "xtruder/nginx";
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
kubernetes.namespace = "test-namespace";
|
kubernetes.namespace = "test-namespace";
|
||||||
|
|
||||||
submodules.imports = [{
|
submodules.imports = [
|
||||||
module = { name, config, ... }: {
|
{
|
||||||
imports = with kubenix.modules; [ submodule k8s docker ];
|
module = {
|
||||||
|
name,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
imports = with kubenix.modules; [submodule k8s docker];
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
submodule = {
|
submodule = {
|
||||||
|
|
@ -43,12 +54,15 @@ in
|
||||||
docker.images.nginx.image = images.nginx;
|
docker.images.nginx.image = images.nginx;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
|
||||||
kubernetes.api.defaults = [{
|
kubernetes.api.defaults = [
|
||||||
|
{
|
||||||
propagate = true;
|
propagate = true;
|
||||||
default.metadata.labels.my-label = "my-value";
|
default.metadata.labels.my-label = "my-value";
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
|
||||||
submodules.instances.passthru = {
|
submodules.instances.passthru = {
|
||||||
submodule = "test-submodule";
|
submodule = "test-submodule";
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
{ name, config, lib, kubenix, ... }:
|
{
|
||||||
|
name,
|
||||||
with lib;
|
config,
|
||||||
let
|
lib,
|
||||||
|
kubenix,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
instance1 = config.submodules.instances.instance1;
|
instance1 = config.submodules.instances.instance1;
|
||||||
instance2 = config.submodules.instances.instance2;
|
instance2 = config.submodules.instances.instance2;
|
||||||
instance3 = config.submodules.instances.instance3;
|
instance3 = config.submodules.instances.instance3;
|
||||||
|
|
@ -9,8 +13,8 @@ let
|
||||||
instance5 = config.submodules.instances.instance5;
|
instance5 = config.submodules.instances.instance5;
|
||||||
versioned-submodule = config.submodules.instances.versioned-submodule;
|
versioned-submodule = config.submodules.instances.versioned-submodule;
|
||||||
|
|
||||||
submodule = { name, ... }: {
|
submodule = {name, ...}: {
|
||||||
imports = [ kubenix.modules.submodule ];
|
imports = [kubenix.modules.submodule];
|
||||||
|
|
||||||
options.submodule.args = {
|
options.submodule.args = {
|
||||||
value = mkOption {
|
value = mkOption {
|
||||||
|
|
@ -24,14 +28,14 @@ let
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in
|
in {
|
||||||
{
|
imports = with kubenix.modules; [test submodules];
|
||||||
imports = with kubenix.modules; [ test submodules ];
|
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
name = "submodules-defaults";
|
name = "submodules-defaults";
|
||||||
description = "Simple submodule test";
|
description = "Simple submodule test";
|
||||||
assertions = [{
|
assertions = [
|
||||||
|
{
|
||||||
message = "should apply defaults by tag1";
|
message = "should apply defaults by tag1";
|
||||||
assertion = instance1.config.submodule.args.value == "value1";
|
assertion = instance1.config.submodule.args.value == "value1";
|
||||||
}
|
}
|
||||||
|
|
@ -46,8 +50,9 @@ in
|
||||||
{
|
{
|
||||||
message = "should apply defaults to all";
|
message = "should apply defaults to all";
|
||||||
assertion =
|
assertion =
|
||||||
instance1.config.submodule.args.defaultValue == "value" &&
|
instance1.config.submodule.args.defaultValue
|
||||||
instance2.config.submodule.args.defaultValue == "value";
|
== "value"
|
||||||
|
&& instance2.config.submodule.args.defaultValue == "value";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
message = "instance1 and instance3 should have value of default-value";
|
message = "instance1 and instance3 should have value of default-value";
|
||||||
|
|
@ -64,16 +69,18 @@ in
|
||||||
{
|
{
|
||||||
message = "should apply defaults to versioned submodule";
|
message = "should apply defaults to versioned submodule";
|
||||||
assertion = versioned-submodule.config.submodule.args.defaultValue == "versioned-submodule";
|
assertion = versioned-submodule.config.submodule.args.defaultValue == "versioned-submodule";
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
submodules.imports = [{
|
submodules.imports = [
|
||||||
|
{
|
||||||
modules = [
|
modules = [
|
||||||
submodule
|
submodule
|
||||||
{
|
{
|
||||||
submodule = {
|
submodule = {
|
||||||
name = "submodule1";
|
name = "submodule1";
|
||||||
tags = [ "tag1" ];
|
tags = ["tag1"];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
@ -84,7 +91,7 @@ in
|
||||||
{
|
{
|
||||||
submodule = {
|
submodule = {
|
||||||
name = "submodule2";
|
name = "submodule2";
|
||||||
tags = [ "tag2" ];
|
tags = ["tag2"];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
@ -95,7 +102,7 @@ in
|
||||||
{
|
{
|
||||||
submodule = {
|
submodule = {
|
||||||
name = "submodule3";
|
name = "submodule3";
|
||||||
tags = [ "tag2" ];
|
tags = ["tag2"];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
@ -131,17 +138,19 @@ in
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
|
||||||
submodules.defaults = [{
|
submodules.defaults = [
|
||||||
|
{
|
||||||
default.submodule.args.defaultValue = mkDefault "value";
|
default.submodule.args.defaultValue = mkDefault "value";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
tags = [ "tag1" ];
|
tags = ["tag1"];
|
||||||
default.submodule.args.value = mkDefault "value1";
|
default.submodule.args.value = mkDefault "value1";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
tags = [ "tag2" ];
|
tags = ["tag2"];
|
||||||
default.submodule.args.value = mkDefault "value2";
|
default.submodule.args.value = mkDefault "value2";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
|
@ -149,7 +158,7 @@ in
|
||||||
default.submodule.args.value = mkDefault "value4";
|
default.submodule.args.value = mkDefault "value4";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
default = { config, ... }: {
|
default = {config, ...}: {
|
||||||
submodule.args.defaultValue = mkIf (config.submodule.args.value == "custom-value") "my-custom-value";
|
submodule.args.defaultValue = mkIf (config.submodule.args.value == "custom-value") "my-custom-value";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -157,7 +166,8 @@ in
|
||||||
name = "versioned-submodule";
|
name = "versioned-submodule";
|
||||||
version = "2.0.0";
|
version = "2.0.0";
|
||||||
default.submodule.args.value = mkDefault "versioned";
|
default.submodule.args.value = mkDefault "versioned";
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
|
||||||
submodules.instances.instance1.submodule = "submodule1";
|
submodules.instances.instance1.submodule = "submodule1";
|
||||||
submodules.instances.instance2.submodule = "submodule2";
|
submodules.instances.instance2.submodule = "submodule2";
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,14 @@
|
||||||
{ name, config, lib, kubenix, subm-lib, ... }:
|
{
|
||||||
|
name,
|
||||||
with lib;
|
config,
|
||||||
let
|
lib,
|
||||||
|
kubenix,
|
||||||
|
subm-lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
submodule = {
|
submodule = {
|
||||||
imports = [ kubenix.modules.submodule ];
|
imports = [kubenix.modules.submodule];
|
||||||
|
|
||||||
config.submodule = {
|
config.submodule = {
|
||||||
name = "subm";
|
name = "subm";
|
||||||
|
|
@ -12,21 +17,24 @@ let
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in
|
in {
|
||||||
{
|
imports = with kubenix.modules; [test submodules];
|
||||||
imports = with kubenix.modules; [ test submodules ];
|
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
name = "submodules-exports";
|
name = "submodules-exports";
|
||||||
description = "Submodules exports test";
|
description = "Submodules exports test";
|
||||||
assertions = [{
|
assertions = [
|
||||||
|
{
|
||||||
message = "should have library exported";
|
message = "should have library exported";
|
||||||
assertion = subm-lib.id 1 == 1;
|
assertion = subm-lib.id 1 == 1;
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
submodules.imports = [{
|
submodules.imports = [
|
||||||
modules = [ submodule ];
|
{
|
||||||
|
modules = [submodule];
|
||||||
exportAs = "subm-lib";
|
exportAs = "subm-lib";
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,27 @@
|
||||||
{ name, config, lib, kubenix, ... }:
|
{
|
||||||
|
name,
|
||||||
with lib;
|
config,
|
||||||
let
|
lib,
|
||||||
submodule = { name, ... }: {
|
kubenix,
|
||||||
imports = [ kubenix.modules.submodule ];
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
|
submodule = {name, ...}: {
|
||||||
|
imports = [kubenix.modules.submodule];
|
||||||
|
|
||||||
config.submodule = {
|
config.submodule = {
|
||||||
name = "subm";
|
name = "subm";
|
||||||
passthru.global.${name} = "true";
|
passthru.global.${name} = "true";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in
|
in {
|
||||||
{
|
imports = with kubenix.modules; [test submodules];
|
||||||
imports = with kubenix.modules; [ test submodules ];
|
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
global = mkOption {
|
global = mkOption {
|
||||||
description = "Global value";
|
description = "Global value";
|
||||||
type = types.attrs;
|
type = types.attrs;
|
||||||
default = { };
|
default = {};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -26,7 +29,8 @@ in
|
||||||
test = {
|
test = {
|
||||||
name = "submodules-passthru";
|
name = "submodules-passthru";
|
||||||
description = "Submodules passthru test";
|
description = "Submodules passthru test";
|
||||||
assertions = [{
|
assertions = [
|
||||||
|
{
|
||||||
message = "should passthru values if passthru enabled";
|
message = "should passthru values if passthru enabled";
|
||||||
assertion = hasAttr "inst1" config.global && config.global.inst1 == "true";
|
assertion = hasAttr "inst1" config.global && config.global.inst1 == "true";
|
||||||
}
|
}
|
||||||
|
|
@ -37,12 +41,15 @@ in
|
||||||
{
|
{
|
||||||
message = "should passthru by default";
|
message = "should passthru by default";
|
||||||
assertion = hasAttr "inst3" config.global && config.global.inst3 == "true";
|
assertion = hasAttr "inst3" config.global && config.global.inst3 == "true";
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
submodules.imports = [{
|
submodules.imports = [
|
||||||
modules = [ submodule ];
|
{
|
||||||
}];
|
modules = [submodule];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
submodules.instances.inst1 = {
|
submodules.instances.inst1 = {
|
||||||
submodule = "subm";
|
submodule = "subm";
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,21 @@
|
||||||
{ name, config, lib, kubenix, ... }:
|
{
|
||||||
|
name,
|
||||||
with lib;
|
config,
|
||||||
let
|
lib,
|
||||||
|
kubenix,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
cfg = config.submodules.instances.instance;
|
cfg = config.submodules.instances.instance;
|
||||||
args = cfg.config.submodule.args;
|
args = cfg.config.submodule.args;
|
||||||
in
|
in {
|
||||||
{
|
imports = with kubenix.modules; [test submodules];
|
||||||
imports = with kubenix.modules; [ test submodules ];
|
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
name = "submodules-simple";
|
name = "submodules-simple";
|
||||||
description = "Simple k8s submodule test";
|
description = "Simple k8s submodule test";
|
||||||
assertions = [{
|
assertions = [
|
||||||
|
{
|
||||||
message = "Submodule name is set";
|
message = "Submodule name is set";
|
||||||
assertion = cfg.name == "instance";
|
assertion = cfg.name == "instance";
|
||||||
}
|
}
|
||||||
|
|
@ -34,13 +38,15 @@ in
|
||||||
{
|
{
|
||||||
message = "should have tag set";
|
message = "should have tag set";
|
||||||
assertion = elem "tag" (cfg.config.submodule.tags);
|
assertion = elem "tag" (cfg.config.submodule.tags);
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
submodules.propagate.enable = true;
|
submodules.propagate.enable = true;
|
||||||
submodules.imports = [{
|
submodules.imports = [
|
||||||
module = { submodule, ... }: {
|
{
|
||||||
imports = [ kubenix.modules.submodule ];
|
module = {submodule, ...}: {
|
||||||
|
imports = [kubenix.modules.submodule];
|
||||||
|
|
||||||
options.submodule.args = {
|
options.submodule.args = {
|
||||||
name = mkOption {
|
name = mkOption {
|
||||||
|
|
@ -56,10 +62,11 @@ in
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
submodule.name = "submodule";
|
submodule.name = "submodule";
|
||||||
submodule.tags = [ "tag" ];
|
submodule.tags = ["tag"];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
|
||||||
submodules.instances.instance = {
|
submodules.instances.instance = {
|
||||||
submodule = "submodule";
|
submodule = "submodule";
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,17 @@
|
||||||
{ name, config, lib, kubenix, ... }:
|
{
|
||||||
|
name,
|
||||||
with lib;
|
config,
|
||||||
let
|
lib,
|
||||||
|
kubenix,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
inst-exact = config.submodules.instances.inst-exact.config;
|
inst-exact = config.submodules.instances.inst-exact.config;
|
||||||
inst-regex = config.submodules.instances.inst-regex.config;
|
inst-regex = config.submodules.instances.inst-regex.config;
|
||||||
inst-latest = config.submodules.instances.inst-latest.config;
|
inst-latest = config.submodules.instances.inst-latest.config;
|
||||||
|
|
||||||
submodule = {
|
submodule = {
|
||||||
imports = [ kubenix.modules.submodule ];
|
imports = [kubenix.modules.submodule];
|
||||||
|
|
||||||
options.version = mkOption {
|
options.version = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
|
|
@ -16,14 +20,14 @@ let
|
||||||
|
|
||||||
config.submodule.name = "subm";
|
config.submodule.name = "subm";
|
||||||
};
|
};
|
||||||
in
|
in {
|
||||||
{
|
imports = with kubenix.modules; [test submodules];
|
||||||
imports = with kubenix.modules; [ test submodules ];
|
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
name = "submodules-versioning";
|
name = "submodules-versioning";
|
||||||
description = "Submodules versioning test";
|
description = "Submodules versioning test";
|
||||||
assertions = [{
|
assertions = [
|
||||||
|
{
|
||||||
message = "should select exact version";
|
message = "should select exact version";
|
||||||
assertion = inst-exact.version == "1.1.0";
|
assertion = inst-exact.version == "1.1.0";
|
||||||
}
|
}
|
||||||
|
|
@ -34,37 +38,48 @@ in
|
||||||
{
|
{
|
||||||
message = "should select latest version";
|
message = "should select latest version";
|
||||||
assertion = inst-latest.version == "1.2.1";
|
assertion = inst-latest.version == "1.2.1";
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
submodules.imports = [{
|
submodules.imports = [
|
||||||
modules = [{
|
{
|
||||||
|
modules = [
|
||||||
|
{
|
||||||
config.submodule.version = "1.0.0";
|
config.submodule.version = "1.0.0";
|
||||||
config.version = "1.0.0";
|
config.version = "1.0.0";
|
||||||
}
|
}
|
||||||
submodule];
|
submodule
|
||||||
|
];
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
modules = [{
|
modules = [
|
||||||
|
{
|
||||||
config.submodule.version = "1.1.0";
|
config.submodule.version = "1.1.0";
|
||||||
config.version = "1.1.0";
|
config.version = "1.1.0";
|
||||||
}
|
}
|
||||||
submodule];
|
submodule
|
||||||
|
];
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
modules = [{
|
modules = [
|
||||||
|
{
|
||||||
config.submodule.version = "1.2.0";
|
config.submodule.version = "1.2.0";
|
||||||
config.version = "1.2.0";
|
config.version = "1.2.0";
|
||||||
}
|
}
|
||||||
submodule];
|
submodule
|
||||||
|
];
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
modules = [{
|
modules = [
|
||||||
|
{
|
||||||
config.submodule.version = "1.2.1";
|
config.submodule.version = "1.2.1";
|
||||||
config.version = "1.2.1";
|
config.version = "1.2.1";
|
||||||
}
|
}
|
||||||
submodule];
|
submodule
|
||||||
}];
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
submodules.instances.inst-exact = {
|
submodules.instances.inst-exact = {
|
||||||
submodule = "subm";
|
submodule = "subm";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue