mirror of
https://github.com/TECHNOFAB11/kubenix.git
synced 2025-12-12 16:10:05 +01:00
fmt
This commit is contained in:
parent
c3fa598922
commit
db6d83c61e
53 changed files with 1916 additions and 1599 deletions
5
ci.nix
5
ci.nix
|
|
@ -1,6 +1,6 @@
|
||||||
let
|
let
|
||||||
nixpkgsSrc = builtins.fetchTarball "https://github.com/NixOS/nixpkgs/archive/master.tar.gz";
|
nixpkgsSrc = builtins.fetchTarball "https://github.com/NixOS/nixpkgs/archive/master.tar.gz";
|
||||||
pkgs = import nixpkgsSrc {};
|
pkgs = import nixpkgsSrc { };
|
||||||
|
|
||||||
lib = pkgs.lib;
|
lib = pkgs.lib;
|
||||||
|
|
||||||
|
|
@ -8,4 +8,5 @@ let
|
||||||
inherit pkgs lib;
|
inherit pkgs lib;
|
||||||
nixosPath = "${nixpkgsSrc}/nixos";
|
nixosPath = "${nixpkgsSrc}/nixos";
|
||||||
};
|
};
|
||||||
in pkgs.recurseIntoAttrs release
|
in
|
||||||
|
pkgs.recurseIntoAttrs release
|
||||||
|
|
|
||||||
71
default.nix
71
default.nix
|
|
@ -7,7 +7,6 @@ in
|
||||||
}:
|
}:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
kubenixLib = import ./lib { inherit lib pkgs; };
|
kubenixLib = import ./lib { inherit lib pkgs; };
|
||||||
lib' = lib.extend (lib: self: import ./lib/extra.nix { inherit lib pkgs; });
|
lib' = lib.extend (lib: self: import ./lib/extra.nix { inherit lib pkgs; });
|
||||||
|
|
@ -18,46 +17,54 @@ let
|
||||||
|
|
||||||
# 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 = {
|
evalModules =
|
||||||
module ? null,
|
{ module ? null
|
||||||
modules ? [module],
|
, modules ? [ module ]
|
||||||
specialArgs ? defaultSpecialArgs, ...
|
, specialArgs ? defaultSpecialArgs
|
||||||
}@attrs: let
|
, ...
|
||||||
attrs' = filterAttrs (n: _: n != "module") attrs;
|
}@attrs:
|
||||||
in lib'.evalModules (recursiveUpdate {
|
let
|
||||||
inherit specialArgs modules;
|
attrs' = filterAttrs (n: _: n != "module") attrs;
|
||||||
args = {
|
in
|
||||||
inherit pkgs;
|
lib'.evalModules (recursiveUpdate
|
||||||
name = "default";
|
{
|
||||||
};
|
inherit specialArgs modules;
|
||||||
} attrs');
|
args = {
|
||||||
|
inherit pkgs;
|
||||||
|
name = "default";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
attrs');
|
||||||
|
|
||||||
modules = import ./modules;
|
modules = import ./modules;
|
||||||
|
|
||||||
# legacy support for buildResources
|
# legacy support for buildResources
|
||||||
buildResources = {
|
buildResources =
|
||||||
configuration ? {},
|
{ configuration ? { }
|
||||||
writeJSON ? true,
|
, writeJSON ? true
|
||||||
writeHash ? true
|
, writeHash ? true
|
||||||
}: let
|
}:
|
||||||
evaled = evalModules {
|
let
|
||||||
modules = [
|
evaled = evalModules {
|
||||||
configuration
|
modules = [
|
||||||
modules.legacy
|
configuration
|
||||||
];
|
modules.legacy
|
||||||
};
|
];
|
||||||
|
};
|
||||||
|
|
||||||
generated = evaled.config.kubernetes.generated;
|
generated = evaled.config.kubernetes.generated;
|
||||||
|
|
||||||
result =
|
result =
|
||||||
if writeJSON
|
if writeJSON
|
||||||
then pkgs.writeText "resources.json" (builtins.toJSON generated)
|
then pkgs.writeText "resources.json" (builtins.toJSON generated)
|
||||||
else generated;
|
else generated;
|
||||||
in result;
|
in
|
||||||
|
result;
|
||||||
|
|
||||||
kubenix = {
|
kubenix = {
|
||||||
inherit evalModules buildResources modules;
|
inherit evalModules buildResources modules;
|
||||||
|
|
||||||
lib = kubenixLib;
|
lib = kubenixLib;
|
||||||
};
|
};
|
||||||
in kubenix
|
in
|
||||||
|
kubenix
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{ kubenix ? import ./.. {} }:
|
{ kubenix ? import ./.. { } }:
|
||||||
|
|
||||||
{
|
{
|
||||||
nginx-deployment = import ./nginx-deployment { inherit kubenix; };
|
nginx-deployment = import ./nginx-deployment { inherit kubenix; };
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{ kubenix ? import ../.. {}, registry ? "docker.io/gatehub" }:
|
{ kubenix ? import ../.. { }, registry ? "docker.io/gatehub" }:
|
||||||
|
|
||||||
with kubenix.lib;
|
with kubenix.lib;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,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,10 +1,10 @@
|
||||||
{ config, lib, pkgs, kubenix, ... }:
|
{ config, lib, pkgs, kubenix, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
nginx = pkgs.callPackage ./image.nix { };
|
nginx = pkgs.callPackage ./image.nix { };
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
imports = with kubenix.modules; [ k8s docker ];
|
imports = with kubenix.modules; [ k8s docker ];
|
||||||
|
|
||||||
docker.images.nginx.image = nginx;
|
docker.images.nginx.image = nginx;
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
{ pkgs ? import <nixpkgs> {}, lib ? pkgs.lib, spec ? ./istio-schema.json }:
|
{ pkgs ? import <nixpkgs> { }, lib ? pkgs.lib, spec ? ./istio-schema.json }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
gen = rec {
|
gen = rec {
|
||||||
mkMerge = values: ''mkMerge [${concatMapStrings (value: "
|
mkMerge = values: ''mkMerge [${concatMapStrings
|
||||||
|
(value: "
|
||||||
${value}
|
${value}
|
||||||
") values}]'';
|
")
|
||||||
|
values}]'';
|
||||||
|
|
||||||
toNixString = value: if isAttrs value || isList value
|
toNixString = value:
|
||||||
|
if isAttrs value || isList value
|
||||||
then builtins.toJSON value
|
then builtins.toJSON value
|
||||||
else if isString value
|
else if isString value
|
||||||
then ''"${value}"''
|
then ''"${value}"''
|
||||||
|
|
@ -18,19 +20,19 @@ let
|
||||||
|
|
||||||
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};''}
|
||||||
${optionalString (apply != null) ''apply = ${apply};''}
|
${optionalString (apply != null) ''apply = ${apply};''}
|
||||||
}'';
|
}'';
|
||||||
|
|
||||||
mkOverride = priority: value: "mkOverride ${toString priority} ${toNixString value}";
|
mkOverride = priority: value: "mkOverride ${toString priority} ${toNixString value}";
|
||||||
|
|
||||||
types = {
|
types = {
|
||||||
unspecified = "types.unspecified";
|
unspecified = "types.unspecified";
|
||||||
|
|
@ -49,7 +51,7 @@ let
|
||||||
|
|
||||||
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}")'';
|
||||||
|
|
||||||
|
|
@ -77,256 +79,282 @@ let
|
||||||
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 (name: definition:
|
genDefinitions = swagger: with gen; (mapAttrs
|
||||||
# if $ref is in definition it means it's an alias of other definition
|
(name: definition:
|
||||||
if hasAttr "$ref" definition
|
# if $ref is in definition it means it's an alias of other definition
|
||||||
then definitions."${refDefinition definition}"
|
if hasAttr "$ref" 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 (propName: property:
|
options = mapAttrs
|
||||||
let
|
(propName: property:
|
||||||
isRequired = elem propName (definition.required or []);
|
let
|
||||||
requiredOrNot = type: if isRequired then type else types.nullOr type;
|
isRequired = elem propName (definition.required or [ ]);
|
||||||
optionProperties =
|
requiredOrNot = type: if isRequired then type else types.nullOr type;
|
||||||
# if $ref is in property it references other definition,
|
optionProperties =
|
||||||
# but if other definition does not have properties, then just take it's type
|
# if $ref is in property it references other definition,
|
||||||
if hasAttr "$ref" property then
|
# but if other definition does not have properties, then just take it's type
|
||||||
if hasTypeMapping swagger.definitions.${refDefinition property} then {
|
if hasAttr "$ref" property then
|
||||||
type = requiredOrNot (mapType swagger.definitions.${refDefinition property});
|
if hasTypeMapping swagger.definitions.${refDefinition property} then {
|
||||||
}
|
type = requiredOrNot (mapType swagger.definitions.${refDefinition property});
|
||||||
else {
|
}
|
||||||
type = requiredOrNot (submoduleOf definitions (refDefinition property));
|
else {
|
||||||
}
|
type = requiredOrNot (submoduleOf definitions (refDefinition property));
|
||||||
|
}
|
||||||
|
|
||||||
else if !(hasAttr "type" property) then {
|
else if !(hasAttr "type" property) then {
|
||||||
type = types.unspecified;
|
type = types.unspecified;
|
||||||
}
|
|
||||||
|
|
||||||
# if property has an array type
|
|
||||||
else if property.type == "array" then
|
|
||||||
|
|
||||||
# if reference is in items it can reference other type of another
|
|
||||||
# definition
|
|
||||||
if hasAttr "$ref" property.items then
|
|
||||||
|
|
||||||
# if it is a reference to simple type
|
|
||||||
if hasTypeMapping swagger.definitions.${refDefinition property.items}
|
|
||||||
then {
|
|
||||||
type = requiredOrNot (types.listOf (mapType swagger.definitions.${refDefinition property.items}.type));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# if a reference is to complex type
|
# if property has an array type
|
||||||
else
|
else if property.type == "array" then
|
||||||
# if x-kubernetes-patch-merge-key is set then make it an
|
|
||||||
# attribute set of submodules
|
|
||||||
if hasAttr "x-kubernetes-patch-merge-key" property
|
|
||||||
then let
|
|
||||||
mergeKey = property."x-kubernetes-patch-merge-key";
|
|
||||||
in {
|
|
||||||
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey);
|
|
||||||
apply = attrsToList;
|
|
||||||
}
|
|
||||||
|
|
||||||
# in other case it's a simple list
|
# if reference is in items it can reference other type of another
|
||||||
|
# definition
|
||||||
|
if hasAttr "$ref" property.items then
|
||||||
|
|
||||||
|
# if it is a reference to simple type
|
||||||
|
if hasTypeMapping swagger.definitions.${refDefinition property.items}
|
||||||
|
then {
|
||||||
|
type = requiredOrNot (types.listOf (mapType swagger.definitions.${refDefinition property.items}.type));
|
||||||
|
}
|
||||||
|
|
||||||
|
# if a reference is to complex type
|
||||||
|
else
|
||||||
|
# if x-kubernetes-patch-merge-key is set then make it an
|
||||||
|
# attribute set of submodules
|
||||||
|
if hasAttr "x-kubernetes-patch-merge-key" property
|
||||||
|
then
|
||||||
|
let
|
||||||
|
mergeKey = property."x-kubernetes-patch-merge-key";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey);
|
||||||
|
apply = attrsToList;
|
||||||
|
}
|
||||||
|
|
||||||
|
# in other case it's a simple list
|
||||||
|
else {
|
||||||
|
type = requiredOrNot (types.listOf (submoduleOf definitions (refDefinition property.items)));
|
||||||
|
}
|
||||||
|
|
||||||
|
# in other case it only references a simple type
|
||||||
else {
|
else {
|
||||||
type = requiredOrNot (types.listOf (submoduleOf definitions (refDefinition property.items)));
|
type = requiredOrNot (types.listOf (mapType property.items));
|
||||||
}
|
}
|
||||||
|
|
||||||
# in other case it only references a simple type
|
else if property.type == "object" && hasAttr "additionalProperties" property
|
||||||
else {
|
then
|
||||||
type = requiredOrNot (types.listOf (mapType property.items));
|
# if it is a reference to simple type
|
||||||
}
|
if (
|
||||||
|
hasAttr "$ref" property.additionalProperties &&
|
||||||
|
hasTypeMapping swagger.definitions.${refDefinition property.additionalProperties}
|
||||||
|
) then {
|
||||||
|
type = requiredOrNot (types.attrsOf (mapType swagger.definitions.${refDefinition property.additionalProperties}));
|
||||||
|
}
|
||||||
|
|
||||||
else if property.type == "object" && hasAttr "additionalProperties" property
|
else if hasAttr "$ref" property.additionalProperties
|
||||||
then
|
then {
|
||||||
# if it is a reference to simple type
|
type = requiredOrNot types.attrs;
|
||||||
if (
|
}
|
||||||
hasAttr "$ref" property.additionalProperties &&
|
|
||||||
hasTypeMapping swagger.definitions.${refDefinition property.additionalProperties}
|
|
||||||
) then {
|
|
||||||
type = requiredOrNot (types.attrsOf (mapType swagger.definitions.${refDefinition property.additionalProperties}));
|
|
||||||
}
|
|
||||||
|
|
||||||
else if hasAttr "$ref" property.additionalProperties
|
# if is an array
|
||||||
then {
|
else if property.additionalProperties.type == "array"
|
||||||
type = requiredOrNot types.attrs;
|
then {
|
||||||
}
|
type = requiredOrNot (types.loaOf (mapType property.additionalProperties.items));
|
||||||
|
}
|
||||||
|
|
||||||
# if is an array
|
else {
|
||||||
else if property.additionalProperties.type == "array"
|
type = requiredOrNot (types.attrsOf (mapType property.additionalProperties));
|
||||||
then {
|
}
|
||||||
type = requiredOrNot (types.loaOf (mapType property.additionalProperties.items));
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
# just a simple property
|
||||||
type = requiredOrNot (types.attrsOf (mapType property.additionalProperties));
|
else {
|
||||||
}
|
type = requiredOrNot (mapType property);
|
||||||
|
};
|
||||||
|
in
|
||||||
|
mkOption ({
|
||||||
|
description = property.description or "";
|
||||||
|
} // optionProperties)
|
||||||
|
)
|
||||||
|
definition.properties;
|
||||||
|
config =
|
||||||
|
let
|
||||||
|
optionalProps = filterAttrs
|
||||||
|
(propName: property:
|
||||||
|
!(elem propName (definition.required or [ ]))
|
||||||
|
)
|
||||||
|
definition.properties;
|
||||||
|
in
|
||||||
|
mapAttrs (name: property: mkOverride 1002 null) optionalProps;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
swagger.definitions);
|
||||||
|
|
||||||
# just a simple property
|
genResources = swagger: (mapAttrsToList
|
||||||
else {
|
(name: property: rec {
|
||||||
type = requiredOrNot (mapType property);
|
splittedType = splitString "." (removePrefix "me.snowdrop.istio.api." property.javaType);
|
||||||
};
|
group = (concatStringsSep "." (take ((length splittedType) - 2) splittedType)) + ".istio.io";
|
||||||
in mkOption ({
|
kind = removeSuffix "Spec" (last splittedType);
|
||||||
description = property.description or "";
|
version = last (take ((length splittedType) - 1) splittedType);
|
||||||
} // optionProperties)
|
ref = removePrefix "#/definitions/" property."$ref";
|
||||||
) definition.properties;
|
})
|
||||||
config =
|
(filterAttrs
|
||||||
let
|
(name: property:
|
||||||
optionalProps = filterAttrs (propName: property:
|
(hasPrefix "me.snowdrop.istio.api" property.javaType) &&
|
||||||
!(elem propName (definition.required or []))
|
hasSuffix "Spec" property.javaType
|
||||||
) definition.properties;
|
)
|
||||||
in mapAttrs (name: property: mkOverride 1002 null) optionalProps;
|
swagger.properties)) ++ (mapAttrsToList
|
||||||
}
|
(name: property: rec {
|
||||||
) swagger.definitions);
|
splittedType = splitString "." (removePrefix "me.snowdrop.istio.mixer." property.javaType);
|
||||||
|
group = "config.istio.io";
|
||||||
genResources = swagger: (mapAttrsToList (name: property: rec {
|
version = "v1alpha2";
|
||||||
splittedType = splitString "." (removePrefix "me.snowdrop.istio.api." property.javaType);
|
kind = head (tail splittedType);
|
||||||
group = (concatStringsSep "." (take ((length splittedType) - 2) splittedType)) + ".istio.io";
|
ref = removePrefix "#/definitions/" property."$ref";
|
||||||
kind = removeSuffix "Spec" (last splittedType);
|
})
|
||||||
version = last (take ((length splittedType) - 1) splittedType);
|
(filterAttrs
|
||||||
ref = removePrefix "#/definitions/" property."$ref";
|
(name: property:
|
||||||
})
|
(hasPrefix "me.snowdrop.istio.mixer" property.javaType) &&
|
||||||
(filterAttrs (name: property:
|
hasSuffix "Spec" property.javaType
|
||||||
(hasPrefix "me.snowdrop.istio.api" property.javaType) &&
|
)
|
||||||
hasSuffix "Spec" property.javaType
|
swagger.properties));
|
||||||
) swagger.properties)) ++ (mapAttrsToList (name: property: rec {
|
|
||||||
splittedType = splitString "." (removePrefix "me.snowdrop.istio.mixer." property.javaType);
|
|
||||||
group = "config.istio.io";
|
|
||||||
version = "v1alpha2";
|
|
||||||
kind = head (tail splittedType);
|
|
||||||
ref = removePrefix "#/definitions/" property."$ref";
|
|
||||||
}) (filterAttrs (name: property:
|
|
||||||
(hasPrefix "me.snowdrop.istio.mixer" property.javaType) &&
|
|
||||||
hasSuffix "Spec" property.javaType
|
|
||||||
) swagger.properties));
|
|
||||||
|
|
||||||
swagger = fetchSpecs spec;
|
swagger = fetchSpecs spec;
|
||||||
|
|
||||||
definitions = genDefinitions swagger;
|
definitions = genDefinitions swagger;
|
||||||
in pkgs.writeText "gen.nix"
|
in
|
||||||
"# This file was generated with kubenix k8s generator, do not edit
|
pkgs.writeText "gen.nix" ''
|
||||||
{lib, config, ... }:
|
# This file was generated with kubenix k8s generator, do not edit
|
||||||
|
{lib, config, ... }:
|
||||||
with lib;
|
|
||||||
|
with lib;
|
||||||
let
|
|
||||||
types = lib.types // rec {
|
let
|
||||||
str = mkOptionType {
|
types = lib.types // rec {
|
||||||
name = \"str\";
|
str = mkOptionType {
|
||||||
description = \"string\";
|
name = \"str\";
|
||||||
check = isString;
|
description = \"string\";
|
||||||
merge = mergeEqualOption;
|
check = isString;
|
||||||
|
merge = mergeEqualOption;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Either value of type `finalType` or `coercedType`, the latter is
|
||||||
|
# converted to `finalType` using `coerceFunc`.
|
||||||
|
coercedTo = coercedType: coerceFunc: finalType:
|
||||||
|
mkOptionType rec {
|
||||||
|
name = \"coercedTo\";
|
||||||
|
description = \"\${finalType.description} or \${coercedType.description}\";
|
||||||
|
check = x: finalType.check x || coercedType.check x;
|
||||||
|
merge = loc: defs:
|
||||||
|
let
|
||||||
|
coerceVal = val:
|
||||||
|
if finalType.check val then val
|
||||||
|
else let
|
||||||
|
coerced = coerceFunc val;
|
||||||
|
in assert finalType.check coerced; coerced;
|
||||||
|
|
||||||
|
in finalType.merge loc (map (def: def // { value = coerceVal def.value; }) defs);
|
||||||
|
getSubOptions = finalType.getSubOptions;
|
||||||
|
getSubModules = finalType.getSubModules;
|
||||||
|
substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m);
|
||||||
|
typeMerge = t1: t2: null;
|
||||||
|
functor = (defaultFunctor name) // { wrapped = finalType; };
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Either value of type `finalType` or `coercedType`, the latter is
|
mkOptionDefault = mkOverride 1001;
|
||||||
# converted to `finalType` using `coerceFunc`.
|
|
||||||
coercedTo = coercedType: coerceFunc: finalType:
|
extraOptions = {
|
||||||
mkOptionType rec {
|
kubenix = {};
|
||||||
name = \"coercedTo\";
|
|
||||||
description = \"\${finalType.description} or \${coercedType.description}\";
|
|
||||||
check = x: finalType.check x || coercedType.check x;
|
|
||||||
merge = loc: defs:
|
|
||||||
let
|
|
||||||
coerceVal = val:
|
|
||||||
if finalType.check val then val
|
|
||||||
else let
|
|
||||||
coerced = coerceFunc val;
|
|
||||||
in assert finalType.check coerced; coerced;
|
|
||||||
|
|
||||||
in finalType.merge loc (map (def: def // { value = coerceVal def.value; }) defs);
|
|
||||||
getSubOptions = finalType.getSubOptions;
|
|
||||||
getSubModules = finalType.getSubModules;
|
|
||||||
substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m);
|
|
||||||
typeMerge = t1: t2: null;
|
|
||||||
functor = (defaultFunctor name) // { wrapped = finalType; };
|
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
mergeValuesByKey = mergeKey: values:
|
||||||
mkOptionDefault = mkOverride 1001;
|
listToAttrs (map
|
||||||
|
(value: nameValuePair (
|
||||||
extraOptions = {
|
if isAttrs value.\${mergeKey}
|
||||||
kubenix = {};
|
then toString value.\${mergeKey}.content
|
||||||
};
|
else (toString value.\${mergeKey})
|
||||||
|
) value)
|
||||||
mergeValuesByKey = mergeKey: values:
|
values);
|
||||||
listToAttrs (map
|
|
||||||
(value: nameValuePair (
|
submoduleOf = ref: types.submodule ({name, ...}: {
|
||||||
if isAttrs value.\${mergeKey}
|
options = definitions.\"\${ref}\".options;
|
||||||
then toString value.\${mergeKey}.content
|
config = definitions.\"\${ref}\".config;
|
||||||
else (toString value.\${mergeKey})
|
|
||||||
) value)
|
|
||||||
values);
|
|
||||||
|
|
||||||
submoduleOf = ref: types.submodule ({name, ...}: {
|
|
||||||
options = definitions.\"\${ref}\".options;
|
|
||||||
config = definitions.\"\${ref}\".config;
|
|
||||||
});
|
|
||||||
|
|
||||||
submoduleWithMergeOf = ref: mergeKey: types.submodule ({name, ...}: let
|
|
||||||
convertName = name:
|
|
||||||
if definitions.\"\${ref}\".options.\${mergeKey}.type == types.int
|
|
||||||
then toInt name
|
|
||||||
else name;
|
|
||||||
in {
|
|
||||||
options = definitions.\"\${ref}\".options;
|
|
||||||
config = definitions.\"\${ref}\".config // {
|
|
||||||
\${mergeKey} = mkOverride 1002 (convertName name);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
submoduleForDefinition = ref: resource: kind: group: version:
|
|
||||||
types.submodule ({name, ...}: {
|
|
||||||
options = definitions.\"\${ref}\".options // extraOptions;
|
|
||||||
config = mkMerge ([
|
|
||||||
definitions.\"\${ref}\".config
|
|
||||||
{
|
|
||||||
kind = mkOptionDefault kind;
|
|
||||||
apiVersion = mkOptionDefault version;
|
|
||||||
|
|
||||||
# metdata.name cannot use option default, due deep config
|
|
||||||
metadata.name = mkOptionDefault name;
|
|
||||||
}
|
|
||||||
] ++ (config.defaults.\${resource} or [])
|
|
||||||
++ (config.defaults.all or []));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
coerceAttrsOfSubmodulesToListByKey = ref: mergeKey: (types.coercedTo
|
submoduleWithMergeOf = ref: mergeKey: types.submodule ({name, ...}: let
|
||||||
(types.listOf (submoduleOf ref))
|
convertName = name:
|
||||||
(mergeValuesByKey mergeKey)
|
if definitions.\"\${ref}\".options.\${mergeKey}.type == types.int
|
||||||
(types.attrsOf (submoduleWithMergeOf ref mergeKey))
|
then toInt name
|
||||||
);
|
else name;
|
||||||
|
in {
|
||||||
definitions = {
|
options = definitions.\"\${ref}\".options;
|
||||||
${concatStrings (mapAttrsToList (name: value: "
|
config = definitions.\"\${ref}\".config // {
|
||||||
\"${name}\" = {${optionalString (hasAttr "options" value) "
|
\${mergeKey} = mkOverride 1002 (convertName name);
|
||||||
options = {${concatStrings (mapAttrsToList (name: value: "
|
};
|
||||||
\"${name}\" = ${value};
|
});
|
||||||
") value.options)}};
|
|
||||||
"}${optionalString (hasAttr "config" value) "
|
submoduleForDefinition = ref: resource: kind: group: version:
|
||||||
config = {${concatStrings (mapAttrsToList (name: value: "
|
types.submodule ({name, ...}: {
|
||||||
\"${name}\" = ${value};
|
options = definitions.\"\${ref}\".options // extraOptions;
|
||||||
") value.config)}};
|
config = mkMerge ([
|
||||||
"}};
|
definitions.\"\${ref}\".config
|
||||||
") definitions)}
|
{
|
||||||
} // (import ./overrides.nix {inheirt definitions lib;}));
|
kind = mkOptionDefault kind;
|
||||||
in {
|
apiVersion = mkOptionDefault version;
|
||||||
kubernetes.customResources = [
|
|
||||||
${concatMapStrings (resource: ''{
|
# metdata.name cannot use option default, due deep config
|
||||||
group = "${resource.group}";
|
metadata.name = mkOptionDefault name;
|
||||||
version = "${resource.version}";
|
}
|
||||||
kind = "${resource.kind}";
|
] ++ (config.defaults.\${resource} or [])
|
||||||
description = "";
|
++ (config.defaults.all or []));
|
||||||
module = definitions."${resource.ref}";
|
});
|
||||||
}'') (genResources swagger)}
|
|
||||||
];
|
coerceAttrsOfSubmodulesToListByKey = ref: mergeKey: (types.coercedTo
|
||||||
}
|
(types.listOf (submoduleOf ref))
|
||||||
"
|
(mergeValuesByKey mergeKey)
|
||||||
|
(types.attrsOf (submoduleWithMergeOf ref mergeKey))
|
||||||
|
);
|
||||||
|
|
||||||
|
definitions = {
|
||||||
|
${concatStrings (mapAttrsToList
|
||||||
|
(name: value: "
|
||||||
|
\"${name}\" = {${optionalString (hasAttr "options" value) "
|
||||||
|
options = {${concatStrings (mapAttrsToList
|
||||||
|
(name: value: "
|
||||||
|
\"${name}\" = ${value};
|
||||||
|
")
|
||||||
|
value.options)}};
|
||||||
|
"}${optionalString (hasAttr "config" value) "
|
||||||
|
config = {${concatStrings (mapAttrsToList
|
||||||
|
(name: value: "
|
||||||
|
\"${name}\" = ${value};
|
||||||
|
")
|
||||||
|
value.config)}};
|
||||||
|
"}};
|
||||||
|
")
|
||||||
|
definitions)}
|
||||||
|
} // (import ./overrides.nix {inheirt definitions lib;}));
|
||||||
|
in {
|
||||||
|
kubernetes.customResources = [
|
||||||
|
${concatMapStrings
|
||||||
|
(resource: ''{
|
||||||
|
group = "${resource.group}";
|
||||||
|
version = "${resource.version}";
|
||||||
|
kind = "${resource.kind}";
|
||||||
|
description = "";
|
||||||
|
module = definitions."${resource.ref}";
|
||||||
|
}'')
|
||||||
|
(genResources swagger)}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
''
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,21 @@
|
||||||
{ name ? "k8s"
|
{ name ? "k8s"
|
||||||
, pkgs ? import <nixpkgs> {}
|
, pkgs ? import <nixpkgs> { }
|
||||||
, lib ? pkgs.lib
|
, lib ? pkgs.lib
|
||||||
, spec ? ./specs/1.21/swagger.json
|
, spec ? ./specs/1.21/swagger.json
|
||||||
, ... }:
|
, ...
|
||||||
|
}:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
gen = rec {
|
gen = rec {
|
||||||
mkMerge = values: ''mkMerge [${concatMapStrings (value: "
|
mkMerge = values: ''mkMerge [${concatMapStrings
|
||||||
|
(value: "
|
||||||
${value}
|
${value}
|
||||||
") values}]'';
|
")
|
||||||
|
values}]'';
|
||||||
|
|
||||||
toNixString = value: if isAttrs value || isList value
|
toNixString = value:
|
||||||
|
if isAttrs value || isList value
|
||||||
then builtins.toJSON value
|
then builtins.toJSON value
|
||||||
else if isString value
|
else if isString value
|
||||||
then ''"${value}"''
|
then ''"${value}"''
|
||||||
|
|
@ -22,19 +25,19 @@ let
|
||||||
|
|
||||||
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};''}
|
||||||
${optionalString (apply != null) ''apply = ${apply};''}
|
${optionalString (apply != null) ''apply = ${apply};''}
|
||||||
}'';
|
}'';
|
||||||
|
|
||||||
mkOverride = priority: value: "mkOverride ${toString priority} ${toNixString value}";
|
mkOverride = priority: value: "mkOverride ${toString priority} ${toNixString value}";
|
||||||
|
|
||||||
types = {
|
types = {
|
||||||
unspecified = "types.unspecified";
|
unspecified = "types.unspecified";
|
||||||
|
|
@ -53,7 +56,7 @@ let
|
||||||
|
|
||||||
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}")'';
|
||||||
|
|
||||||
|
|
@ -83,185 +86,220 @@ let
|
||||||
|
|
||||||
refType = attr: head (tail (tail (splitString "/" attr."$ref")));
|
refType = attr: head (tail (tail (splitString "/" attr."$ref")));
|
||||||
|
|
||||||
compareVersions = ver1: ver2: let
|
compareVersions = ver1: ver2:
|
||||||
getVersion = v: substring 1 10 v;
|
let
|
||||||
splitVersion = v: builtins.splitVersion (getVersion v);
|
getVersion = v: substring 1 10 v;
|
||||||
isAlpha = v: elem "alpha" (splitVersion v);
|
splitVersion = v: builtins.splitVersion (getVersion v);
|
||||||
patchVersion = v:
|
isAlpha = v: elem "alpha" (splitVersion v);
|
||||||
if isAlpha v then ""
|
patchVersion = v:
|
||||||
else if length (splitVersion v) == 1 then "${getVersion v}prod"
|
if isAlpha v then ""
|
||||||
else getVersion v;
|
else if length (splitVersion v) == 1 then "${getVersion v}prod"
|
||||||
|
else getVersion v;
|
||||||
|
|
||||||
v1 = patchVersion ver1;
|
v1 = patchVersion ver1;
|
||||||
v2 = patchVersion ver2;
|
v2 = patchVersion ver2;
|
||||||
in builtins.compareVersions v1 v2;
|
in
|
||||||
|
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 (name: definition:
|
genDefinitions = swagger: with gen; mapAttrs
|
||||||
# if $ref is in definition it means it's an alias of other definition
|
(name: definition:
|
||||||
if hasAttr "$ref" definition
|
# if $ref is in definition it means it's an alias of other definition
|
||||||
then definitions."${refDefinition definition}"
|
if hasAttr "$ref" 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 (propName: property:
|
options = mapAttrs
|
||||||
let
|
(propName: property:
|
||||||
isRequired = elem propName (definition.required or []);
|
let
|
||||||
requiredOrNot = type: if isRequired then type else types.nullOr type;
|
isRequired = elem propName (definition.required or [ ]);
|
||||||
optionProperties =
|
requiredOrNot = type: if isRequired then type else types.nullOr type;
|
||||||
|
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 then
|
||||||
if hasTypeMapping swagger.definitions.${refDefinition property} then {
|
if hasTypeMapping swagger.definitions.${refDefinition property} then {
|
||||||
type = requiredOrNot (mapType swagger.definitions.${refDefinition property});
|
type = requiredOrNot (mapType swagger.definitions.${refDefinition property});
|
||||||
}
|
|
||||||
else {
|
|
||||||
type = requiredOrNot (submoduleOf definitions (refDefinition property));
|
|
||||||
}
|
|
||||||
|
|
||||||
# if property has an array type
|
|
||||||
else if property.type == "array" then
|
|
||||||
|
|
||||||
# if reference is in items it can reference other type of another
|
|
||||||
# definition
|
|
||||||
if hasAttr "$ref" property.items then
|
|
||||||
|
|
||||||
# if it is a reference to simple type
|
|
||||||
if hasTypeMapping swagger.definitions.${refDefinition property.items}
|
|
||||||
then {
|
|
||||||
type = requiredOrNot (types.listOf (mapType swagger.definitions.${refDefinition property.items}.type));
|
|
||||||
}
|
|
||||||
|
|
||||||
# if a reference is to complex type
|
|
||||||
else
|
|
||||||
# if x-kubernetes-patch-merge-key is set then make it an
|
|
||||||
# attribute set of submodules
|
|
||||||
if hasAttr "x-kubernetes-patch-merge-key" property
|
|
||||||
then let
|
|
||||||
mergeKey = property."x-kubernetes-patch-merge-key";
|
|
||||||
in {
|
|
||||||
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey);
|
|
||||||
apply = attrsToList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# in other case it's a simple list
|
|
||||||
else {
|
else {
|
||||||
type = requiredOrNot (types.listOf (submoduleOf definitions (refDefinition property.items)));
|
type = requiredOrNot (submoduleOf definitions (refDefinition property));
|
||||||
}
|
}
|
||||||
|
|
||||||
# in other case it only references a simple type
|
# if property has an array type
|
||||||
else {
|
else if property.type == "array" then
|
||||||
type = requiredOrNot (types.listOf (mapType property.items));
|
|
||||||
}
|
|
||||||
|
|
||||||
else if property.type == "object" && hasAttr "additionalProperties" property
|
# if reference is in items it can reference other type of another
|
||||||
then
|
# definition
|
||||||
# if it is a reference to simple type
|
if hasAttr "$ref" property.items then
|
||||||
if (
|
|
||||||
hasAttr "$ref" property.additionalProperties &&
|
|
||||||
hasTypeMapping swagger.definitions.${refDefinition property.additionalProperties}
|
|
||||||
) then {
|
|
||||||
type = requiredOrNot (types.attrsOf (mapType swagger.definitions.${refDefinition property.additionalProperties}));
|
|
||||||
}
|
|
||||||
|
|
||||||
else if hasAttr "$ref" property.additionalProperties
|
# if it is a reference to simple type
|
||||||
then {
|
if hasTypeMapping swagger.definitions.${refDefinition property.items}
|
||||||
type = requiredOrNot types.attrs;
|
then {
|
||||||
}
|
type = requiredOrNot (types.listOf (mapType swagger.definitions.${refDefinition property.items}.type));
|
||||||
|
}
|
||||||
|
|
||||||
# if is an array
|
# if a reference is to complex type
|
||||||
else if property.additionalProperties.type == "array"
|
else
|
||||||
then {
|
# if x-kubernetes-patch-merge-key is set then make it an
|
||||||
type = requiredOrNot (types.loaOf (mapType property.additionalProperties.items));
|
# attribute set of submodules
|
||||||
}
|
if hasAttr "x-kubernetes-patch-merge-key" property
|
||||||
|
then
|
||||||
|
let
|
||||||
|
mergeKey = property."x-kubernetes-patch-merge-key";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey);
|
||||||
|
apply = attrsToList;
|
||||||
|
}
|
||||||
|
|
||||||
else {
|
# in other case it's a simple list
|
||||||
type = requiredOrNot (types.attrsOf (mapType property.additionalProperties));
|
else {
|
||||||
}
|
type = requiredOrNot (types.listOf (submoduleOf definitions (refDefinition property.items)));
|
||||||
|
}
|
||||||
|
|
||||||
# just a simple property
|
# in other case it only references a simple type
|
||||||
else {
|
else {
|
||||||
type = requiredOrNot (mapType property);
|
type = requiredOrNot (types.listOf (mapType property.items));
|
||||||
};
|
}
|
||||||
in mkOption ({
|
|
||||||
description = property.description or "";
|
|
||||||
} // optionProperties)
|
|
||||||
) definition.properties;
|
|
||||||
config =
|
|
||||||
let
|
|
||||||
optionalProps = filterAttrs (propName: property:
|
|
||||||
!(elem propName (definition.required or []))
|
|
||||||
) definition.properties;
|
|
||||||
in mapAttrs (name: property: mkOverride 1002 null) optionalProps;
|
|
||||||
}
|
|
||||||
) swagger.definitions;
|
|
||||||
|
|
||||||
mapCharPairs = f: s1: s2: concatStrings (imap0 (i: c1:
|
else if property.type == "object" && hasAttr "additionalProperties" property
|
||||||
f i c1 (if i >= stringLength s2 then "" else elemAt (stringToCharacters s2) i)
|
then
|
||||||
) (stringToCharacters s1));
|
# if it is a reference to simple type
|
||||||
|
if (
|
||||||
|
hasAttr "$ref" property.additionalProperties &&
|
||||||
|
hasTypeMapping swagger.definitions.${refDefinition property.additionalProperties}
|
||||||
|
) then {
|
||||||
|
type = requiredOrNot (types.attrsOf (mapType swagger.definitions.${refDefinition property.additionalProperties}));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if hasAttr "$ref" property.additionalProperties
|
||||||
|
then {
|
||||||
|
type = requiredOrNot types.attrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
# if is an array
|
||||||
|
else if property.additionalProperties.type == "array"
|
||||||
|
then {
|
||||||
|
type = requiredOrNot (types.loaOf (mapType property.additionalProperties.items));
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
type = requiredOrNot (types.attrsOf (mapType property.additionalProperties));
|
||||||
|
}
|
||||||
|
|
||||||
|
# just a simple property
|
||||||
|
else {
|
||||||
|
type = requiredOrNot (mapType property);
|
||||||
|
};
|
||||||
|
in
|
||||||
|
mkOption ({
|
||||||
|
description = property.description or "";
|
||||||
|
} // optionProperties)
|
||||||
|
)
|
||||||
|
definition.properties;
|
||||||
|
config =
|
||||||
|
let
|
||||||
|
optionalProps = filterAttrs
|
||||||
|
(propName: property:
|
||||||
|
!(elem propName (definition.required or [ ]))
|
||||||
|
)
|
||||||
|
definition.properties;
|
||||||
|
in
|
||||||
|
mapAttrs (name: property: mkOverride 1002 null) optionalProps;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
swagger.definitions;
|
||||||
|
|
||||||
|
mapCharPairs = f: s1: s2: concatStrings (imap0
|
||||||
|
(i: c1:
|
||||||
|
f i c1 (if i >= stringLength s2 then "" else elemAt (stringToCharacters s2) i)
|
||||||
|
)
|
||||||
|
(stringToCharacters s1));
|
||||||
|
|
||||||
getAttrName = resource: kind:
|
getAttrName = resource: kind:
|
||||||
mapCharPairs (i: c1: c2:
|
mapCharPairs
|
||||||
if hasPrefix "API" kind && i == 0 then "A"
|
(i: c1: c2:
|
||||||
else if i == 0 then c1
|
if hasPrefix "API" kind && i == 0 then "A"
|
||||||
else if c2 == "" || (toLower c2) != c1 then c1
|
else if i == 0 then c1
|
||||||
else c2
|
else if c2 == "" || (toLower c2) != c1 then c1
|
||||||
) resource kind;
|
else c2
|
||||||
|
)
|
||||||
|
resource
|
||||||
|
kind;
|
||||||
|
|
||||||
genResourceTypes = swagger: mapAttrs' (name: path: let
|
genResourceTypes = swagger: mapAttrs'
|
||||||
ref = refType (head path.post.parameters).schema;
|
(name: path:
|
||||||
group' = path.post."x-kubernetes-group-version-kind".group;
|
let
|
||||||
version' = path.post."x-kubernetes-group-version-kind".version;
|
ref = refType (head path.post.parameters).schema;
|
||||||
kind' = path.post."x-kubernetes-group-version-kind".kind;
|
group' = path.post."x-kubernetes-group-version-kind".group;
|
||||||
name' = last (splitString "/" name);
|
version' = path.post."x-kubernetes-group-version-kind".version;
|
||||||
attrName = getAttrName name' kind';
|
kind' = path.post."x-kubernetes-group-version-kind".kind;
|
||||||
in nameValuePair ref {
|
name' = last (splitString "/" name);
|
||||||
inherit ref attrName;
|
attrName = getAttrName name' kind';
|
||||||
|
in
|
||||||
|
nameValuePair ref {
|
||||||
|
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 (name: path:
|
(filterAttrs
|
||||||
hasAttr "post" path &&
|
(name: path:
|
||||||
path.post."x-kubernetes-action" == "post"
|
hasAttr "post" path &&
|
||||||
) swagger.paths);
|
path.post."x-kubernetes-action" == "post"
|
||||||
|
)
|
||||||
|
swagger.paths);
|
||||||
|
|
||||||
swagger = fetchSpecs spec;
|
swagger = fetchSpecs spec;
|
||||||
definitions = genDefinitions swagger;
|
definitions = genDefinitions swagger;
|
||||||
resourceTypes = genResourceTypes swagger;
|
resourceTypes = genResourceTypes swagger;
|
||||||
|
|
||||||
resourceTypesByKind = zipAttrs (mapAttrsToList (name: resourceType: {
|
resourceTypesByKind = zipAttrs (mapAttrsToList
|
||||||
${resourceType.kind} = resourceType;
|
(name: resourceType: {
|
||||||
}) resourceTypes);
|
${resourceType.kind} = resourceType;
|
||||||
|
})
|
||||||
|
resourceTypes);
|
||||||
|
|
||||||
resourcesTypesByKindSortByVersion = mapAttrs (kind: resourceTypes:
|
resourcesTypesByKindSortByVersion = mapAttrs
|
||||||
reverseList (sort (r1: r2:
|
(kind: resourceTypes:
|
||||||
compareVersions r1.version r2.version > 0
|
reverseList (sort
|
||||||
) resourceTypes)
|
(r1: r2:
|
||||||
) resourceTypesByKind;
|
compareVersions r1.version r2.version > 0
|
||||||
|
)
|
||||||
|
resourceTypes)
|
||||||
|
)
|
||||||
|
resourceTypesByKind;
|
||||||
|
|
||||||
latestResourceTypesByKind =
|
latestResourceTypesByKind =
|
||||||
mapAttrs (kind: resources: last resources) resourcesTypesByKindSortByVersion;
|
mapAttrs (kind: resources: last resources) resourcesTypesByKindSortByVersion;
|
||||||
|
|
||||||
genResourceOptions = resource: with gen; let
|
genResourceOptions = resource: with gen; let
|
||||||
submoduleForDefinition' = definition: let
|
submoduleForDefinition' = definition:
|
||||||
in submoduleForDefinition
|
let
|
||||||
definition.ref definition.name definition.kind definition.group definition.version;
|
in
|
||||||
in mkOption {
|
submoduleForDefinition
|
||||||
|
definition.ref
|
||||||
|
definition.name
|
||||||
|
definition.kind
|
||||||
|
definition.group
|
||||||
|
definition.version;
|
||||||
|
in
|
||||||
|
mkOption {
|
||||||
description = resource.description;
|
description = resource.description;
|
||||||
type = types.attrsOf (submoduleForDefinition' resource);
|
type = types.attrsOf (submoduleForDefinition' resource);
|
||||||
default = {};
|
default = { };
|
||||||
};
|
};
|
||||||
|
|
||||||
generated = ''
|
generated = ''
|
||||||
|
|
@ -415,7 +453,9 @@ let
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
in pkgs.runCommand "k8s-${name}-gen.nix" {
|
in
|
||||||
|
pkgs.runCommand "k8s-${name}-gen.nix"
|
||||||
|
{
|
||||||
buildInputs = [ pkgs.haskellPackages.nixfmt ];
|
buildInputs = [ pkgs.haskellPackages.nixfmt ];
|
||||||
} ''
|
} ''
|
||||||
cp ${builtins.toFile "k8s-${name}-gen-raw.nix" generated} $out
|
cp ${builtins.toFile "k8s-${name}-gen-raw.nix" generated} $out
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,15 @@
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
{
|
{
|
||||||
copyDockerImages = { images, dest, args ? "" }:
|
copyDockerImages = { images, dest, args ? "" }:
|
||||||
pkgs.writeScript "copy-docker-images.sh" (concatMapStrings (image: ''
|
pkgs.writeScript "copy-docker-images.sh" (concatMapStrings
|
||||||
#!${pkgs.runtimeShell}
|
(image: ''
|
||||||
|
#!${pkgs.runtimeShell}
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
echo "copying '${image.imageName}:${image.imageTag}' to '${dest}/${image.imageName}:${image.imageTag}'"
|
echo "copying '${image.imageName}:${image.imageTag}' to '${dest}/${image.imageName}:${image.imageTag}'"
|
||||||
${pkgs.skopeo}/bin/skopeo copy ${args} $@ docker-archive:${image} ${dest}/${image.imageName}:${image.imageTag}
|
${pkgs.skopeo}/bin/skopeo copy ${args} $@ docker-archive:${image} ${dest}/${image.imageName}:${image.imageTag}
|
||||||
'') images);
|
'')
|
||||||
|
images);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,31 +21,39 @@ rec {
|
||||||
|
|
||||||
else mkOverride priority value;
|
else mkOverride priority value;
|
||||||
|
|
||||||
loadYAML = path: importJSON (pkgs.runCommand "yaml-to-json" {
|
loadYAML = 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"
|
||||||
buildInputs = [pkgs.remarshal];
|
{
|
||||||
} ''
|
buildInputs = [ pkgs.remarshal ];
|
||||||
|
} ''
|
||||||
remarshal -i ${pkgs.writeText "to-json" (builtins.toJSON config)} -if json -of yaml > $out
|
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
|
||||||
buildInputs = [ pkgs.remarshal ];
|
{
|
||||||
} (concatMapStringsSep "\necho --- >> $out\n" (d:
|
buildInputs = [ pkgs.remarshal ];
|
||||||
"remarshal -i ${builtins.toFile "doc" (builtins.toJSON d)} -if json -of yaml >> $out"
|
}
|
||||||
) documents);
|
(concatMapStringsSep "\necho --- >> $out\n"
|
||||||
|
(d:
|
||||||
|
"remarshal -i ${builtins.toFile "doc" (builtins.toJSON d)} -if json -of yaml >> $out"
|
||||||
|
)
|
||||||
|
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 (char: acc: {
|
octalToDecimal = value: (foldr
|
||||||
i = acc.i + 1;
|
(char: acc: {
|
||||||
value = acc.value + (toInt char) * (exp 8 acc.i);
|
i = acc.i + 1;
|
||||||
}) {i = 0; value = 0;} (stringToCharacters value)).value;
|
value = acc.value + (toInt char) * (exp 8 acc.i);
|
||||||
|
})
|
||||||
|
{ i = 0; value = 0; }
|
||||||
|
(stringToCharacters value)).value;
|
||||||
|
|
||||||
submoduleWithSpecialArgs = opts: specialArgs:
|
submoduleWithSpecialArgs = opts: specialArgs:
|
||||||
let
|
let
|
||||||
|
|
@ -58,13 +66,15 @@ rec {
|
||||||
merge = loc: defs:
|
merge = loc: defs:
|
||||||
let
|
let
|
||||||
coerce = def: if isFunction def then def else { config = def; };
|
coerce = def: if isFunction def then def else { config = def; };
|
||||||
modules = opts' ++ map (def: { _file = def.file; imports = [(coerce def.value)]; }) defs;
|
modules = opts' ++ map (def: { _file = def.file; imports = [ (coerce def.value) ]; }) defs;
|
||||||
in (evalModules {
|
in
|
||||||
|
(evalModules {
|
||||||
inherit modules specialArgs;
|
inherit modules specialArgs;
|
||||||
prefix = loc;
|
prefix = loc;
|
||||||
}).config;
|
}).config;
|
||||||
getSubOptions = prefix: (evalModules
|
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
|
||||||
|
|
@ -87,16 +97,19 @@ rec {
|
||||||
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: [ ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
coerceListOfSubmodulesToAttrs = submodule: keyFn: let
|
coerceListOfSubmodulesToAttrs = submodule: keyFn:
|
||||||
|
let
|
||||||
mergeValuesByFn = keyFn: values:
|
mergeValuesByFn = keyFn: values:
|
||||||
listToAttrs (map (value:
|
listToAttrs (map
|
||||||
nameValuePair (toString (keyFn value)) value
|
(value:
|
||||||
) values);
|
nameValuePair (toString (keyFn value)) value
|
||||||
|
)
|
||||||
|
values);
|
||||||
|
|
||||||
# Either value of type `finalType` or `coercedType`, the latter is
|
# Either value of type `finalType` or `coercedType`, the latter is
|
||||||
# converted to `finalType` using `coerceFunc`.
|
# converted to `finalType` using `coerceFunc`.
|
||||||
|
|
@ -113,14 +126,16 @@ rec {
|
||||||
else
|
else
|
||||||
let coerced = coerceFunc val; in assert finalType.check coerced; coerced;
|
let coerced = coerceFunc val; in assert finalType.check coerced; coerced;
|
||||||
|
|
||||||
in finalType.merge loc (map (def: def // { value = coerceVal def.value; }) defs);
|
in
|
||||||
|
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 coercedTo
|
in
|
||||||
|
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));
|
||||||
|
|
|
||||||
|
|
@ -13,19 +13,22 @@ with lib;
|
||||||
, namespace ? null
|
, namespace ? null
|
||||||
|
|
||||||
# values to pass to chart
|
# values to pass to chart
|
||||||
, values ? {}
|
, values ? { }
|
||||||
|
|
||||||
# kubernetes version to template chart for
|
# kubernetes version to template chart for
|
||||||
, kubeVersion ? null }: let
|
, kubeVersion ? null
|
||||||
|
}:
|
||||||
|
let
|
||||||
valuesJsonFile = builtins.toFile "${name}-values.json" (builtins.toJSON values);
|
valuesJsonFile = builtins.toFile "${name}-values.json" (builtins.toJSON values);
|
||||||
in stdenvNoCC.mkDerivation {
|
in
|
||||||
|
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
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
{ stdenvNoCC, lib, kubernetes-helm, cacert }:
|
{ stdenvNoCC, lib, kubernetes-helm, cacert }:
|
||||||
|
|
||||||
let
|
let
|
||||||
cleanName = name: lib.replaceStrings ["/"] ["-"] name;
|
cleanName = name: lib.replaceStrings [ "/" ] [ "-" ] name;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
# name of the chart
|
# name of the chart
|
||||||
chart
|
chart
|
||||||
|
|
||||||
|
|
@ -13,20 +13,21 @@ in {
|
||||||
# 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 }: stdenvNoCC.mkDerivation {
|
, devel ? false
|
||||||
|
}: stdenvNoCC.mkDerivation {
|
||||||
name = "${cleanName chart}-${if version == null then "dev" else version}";
|
name = "${cleanName chart}-${if version == null then "dev" else version}";
|
||||||
|
|
||||||
buildCommand = ''
|
buildCommand = ''
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
{ 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";
|
||||||
|
|
|
||||||
32
lib/k8s.nix
32
lib/k8s.nix
|
|
@ -4,7 +4,7 @@ with lib;
|
||||||
|
|
||||||
rec {
|
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 = {
|
||||||
|
|
@ -24,7 +24,7 @@ rec {
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
default = if default == null then null else {};
|
default = if default == null then null else { };
|
||||||
};
|
};
|
||||||
|
|
||||||
secretToEnv = value: {
|
secretToEnv = value: {
|
||||||
|
|
@ -34,7 +34,7 @@ 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,19 +42,23 @@ rec {
|
||||||
};
|
};
|
||||||
|
|
||||||
# Creates hashed kubernetes list from a list of kubernetes objects
|
# Creates hashed kubernetes list from a list of kubernetes objects
|
||||||
mkHashedList = { items, labels ? {} }: let
|
mkHashedList = { items, labels ? { } }:
|
||||||
hash = builtins.hashString "sha1" (builtins.toJSON items);
|
let
|
||||||
|
hash = builtins.hashString "sha1" (builtins.toJSON items);
|
||||||
|
|
||||||
labeledItems = map (item: recursiveUpdate item {
|
labeledItems = map
|
||||||
metadata.labels."kubenix/hash" = hash;
|
(item: recursiveUpdate item {
|
||||||
}) items;
|
metadata.labels."kubenix/hash" = hash;
|
||||||
|
})
|
||||||
|
items;
|
||||||
|
|
||||||
in mkList {
|
in
|
||||||
items = labeledItems;
|
mkList {
|
||||||
labels = {
|
items = labeledItems;
|
||||||
"kubenix/hash" = hash;
|
labels = {
|
||||||
} // labels;
|
"kubenix/hash" = hash;
|
||||||
};
|
} // labels;
|
||||||
|
};
|
||||||
|
|
||||||
toBase64 = lib.toBase64;
|
toBase64 = lib.toBase64;
|
||||||
octalToDecimal = lib.octalToDecimal;
|
octalToDecimal = lib.octalToDecimal;
|
||||||
|
|
|
||||||
|
|
@ -13,27 +13,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,10 +1,10 @@
|
||||||
{ config, lib, pkgs, docker, ... }:
|
{ config, lib, pkgs, docker, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.docker;
|
cfg = config.docker;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
imports = [ ./base.nix ];
|
imports = [ ./base.nix ];
|
||||||
|
|
||||||
options.docker = {
|
options.docker = {
|
||||||
|
|
@ -52,13 +52,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,7 +73,7 @@ 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 = [{
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
{ config, lib, pkgs, helm, ... }:
|
{ config, lib, pkgs, helm, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.kubernetes.helm;
|
cfg = config.kubernetes.helm;
|
||||||
|
|
||||||
|
|
@ -14,17 +13,20 @@ 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: let
|
parseApiVersion = apiVersion:
|
||||||
splitted = splitString "/" apiVersion;
|
let
|
||||||
in {
|
splitted = splitString "/" apiVersion;
|
||||||
group = if length splitted == 1 then "core" else head splitted;
|
in
|
||||||
version = last splitted;
|
{
|
||||||
};
|
group = if length splitted == 1 then "core" else head splitted;
|
||||||
|
version = last splitted;
|
||||||
|
};
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
imports = [ ./k8s.nix ];
|
imports = [ ./k8s.nix ];
|
||||||
|
|
||||||
options.kubernetes.helm = {
|
options.kubernetes.helm = {
|
||||||
|
|
@ -52,7 +54,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 {
|
||||||
|
|
@ -64,7 +66,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 {
|
||||||
|
|
@ -76,7 +78,7 @@ 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 = [ ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -88,7 +90,7 @@ in {
|
||||||
inherit (config) chart name namespace values kubeVersion;
|
inherit (config) chart name namespace values kubeVersion;
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
default = {};
|
default = { };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -96,15 +98,21 @@ in {
|
||||||
# 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 (_: instance:
|
kubernetes.api.resources = mkMerge (flatten (mapAttrsToList
|
||||||
map (object: let
|
(_: instance:
|
||||||
apiVersion = parseApiVersion object.apiVersion;
|
map
|
||||||
name = object.metadata.name;
|
(object:
|
||||||
in {
|
let
|
||||||
"${apiVersion.group}"."${apiVersion.version}".${object.kind}."${name}" = mkMerge ([
|
apiVersion = parseApiVersion object.apiVersion;
|
||||||
object
|
name = object.metadata.name;
|
||||||
] ++ instance.overrides);
|
in
|
||||||
}) instance.objects
|
{
|
||||||
) cfg.instances));
|
"${apiVersion.group}"."${apiVersion.version}".${object.kind}."${name}" = mkMerge ([
|
||||||
|
object
|
||||||
|
] ++ instance.overrides);
|
||||||
|
})
|
||||||
|
instance.objects
|
||||||
|
)
|
||||||
|
cfg.instances));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,12 @@
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
{
|
{
|
||||||
"istio_networking_v1alpha3_StringMatch" = recursiveUpdate (recursiveUpdate
|
"istio_networking_v1alpha3_StringMatch" = recursiveUpdate
|
||||||
definitions."istio_networking_v1alpha3_StringMatch_Exact"
|
(recursiveUpdate
|
||||||
definitions."istio_networking_v1alpha3_StringMatch_Prefix"
|
definitions."istio_networking_v1alpha3_StringMatch_Exact"
|
||||||
)
|
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"
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
# This file was generated with kubenix k8s generator, do not edit
|
# This file was generated with kubenix k8s generator, do not edit
|
||||||
{lib, config, ... }:
|
{ lib, config, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
types = lib.types // rec {
|
types = lib.types // rec {
|
||||||
str = mkOptionType {
|
str = mkOptionType {
|
||||||
|
|
@ -15,61 +14,68 @@ let
|
||||||
# Either value of type `finalType` or `coercedType`, the latter is
|
# Either value of type `finalType` or `coercedType`, the latter is
|
||||||
# converted to `finalType` using `coerceFunc`.
|
# converted to `finalType` using `coerceFunc`.
|
||||||
coercedTo = coercedType: coerceFunc: finalType:
|
coercedTo = coercedType: coerceFunc: finalType:
|
||||||
mkOptionType rec {
|
mkOptionType rec {
|
||||||
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 val
|
if finalType.check val then val
|
||||||
else let
|
else
|
||||||
coerced = coerceFunc val;
|
let
|
||||||
in assert finalType.check coerced; coerced;
|
coerced = coerceFunc val;
|
||||||
|
in
|
||||||
|
assert finalType.check coerced; coerced;
|
||||||
|
|
||||||
in finalType.merge loc (map (def: def // { value = coerceVal def.value; }) defs);
|
in
|
||||||
getSubOptions = finalType.getSubOptions;
|
finalType.merge loc (map (def: def // { value = coerceVal def.value; }) defs);
|
||||||
getSubModules = finalType.getSubModules;
|
getSubOptions = finalType.getSubOptions;
|
||||||
substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m);
|
getSubModules = finalType.getSubModules;
|
||||||
typeMerge = t1: t2: null;
|
substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m);
|
||||||
functor = (defaultFunctor name) // { wrapped = finalType; };
|
typeMerge = t1: t2: null;
|
||||||
};
|
functor = (defaultFunctor name) // { wrapped = finalType; };
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
mkOptionDefault = mkOverride 1001;
|
mkOptionDefault = mkOverride 1001;
|
||||||
|
|
||||||
extraOptions = {
|
extraOptions = {
|
||||||
kubenix = {};
|
kubenix = { };
|
||||||
};
|
};
|
||||||
|
|
||||||
mergeValuesByKey = mergeKey: values:
|
mergeValuesByKey = mergeKey: values:
|
||||||
listToAttrs (map
|
listToAttrs (map
|
||||||
(value: nameValuePair (
|
(value: nameValuePair
|
||||||
if isAttrs value.${mergeKey}
|
(
|
||||||
then toString value.${mergeKey}.content
|
if isAttrs value.${mergeKey}
|
||||||
else (toString value.${mergeKey})
|
then toString value.${mergeKey}.content
|
||||||
) value)
|
else (toString value.${mergeKey})
|
||||||
values);
|
)
|
||||||
|
value)
|
||||||
|
values);
|
||||||
|
|
||||||
submoduleOf = ref: types.submodule ({name, ...}: {
|
submoduleOf = ref: types.submodule ({ name, ... }: {
|
||||||
options = definitions."${ref}".options;
|
options = definitions."${ref}".options;
|
||||||
config = definitions."${ref}".config;
|
config = definitions."${ref}".config;
|
||||||
});
|
});
|
||||||
|
|
||||||
submoduleWithMergeOf = ref: mergeKey: types.submodule ({name, ...}: let
|
submoduleWithMergeOf = ref: mergeKey: types.submodule ({ name, ... }:
|
||||||
convertName = name:
|
let
|
||||||
if definitions."${ref}".options.${mergeKey}.type == types.int
|
convertName = name:
|
||||||
then toInt name
|
if definitions."${ref}".options.${mergeKey}.type == types.int
|
||||||
else name;
|
then toInt name
|
||||||
in {
|
else name;
|
||||||
options = definitions."${ref}".options;
|
in
|
||||||
config = definitions."${ref}".config // {
|
{
|
||||||
${mergeKey} = mkOverride 1002 (convertName name);
|
options = definitions."${ref}".options;
|
||||||
};
|
config = definitions."${ref}".config // {
|
||||||
});
|
${mergeKey} = mkOverride 1002 (convertName name);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
submoduleForDefinition = ref: resource: kind: group: version:
|
submoduleForDefinition = ref: resource: kind: group: version:
|
||||||
types.submodule ({name, ...}: {
|
types.submodule ({ name, ... }: {
|
||||||
options = definitions."${ref}".options // extraOptions;
|
options = definitions."${ref}".options // extraOptions;
|
||||||
config = mkMerge ([
|
config = mkMerge ([
|
||||||
definitions."${ref}".config
|
definitions."${ref}".config
|
||||||
|
|
@ -80,8 +86,8 @@ let
|
||||||
# metdata.name cannot use option default, due deep config
|
# metdata.name cannot use option default, due deep config
|
||||||
metadata.name = mkOptionDefault name;
|
metadata.name = mkOptionDefault name;
|
||||||
}
|
}
|
||||||
] ++ (config.defaults.${resource} or [])
|
] ++ (config.defaults.${resource} or [ ])
|
||||||
++ (config.defaults.all or []));
|
++ (config.defaults.all or [ ]));
|
||||||
});
|
});
|
||||||
|
|
||||||
coerceAttrsOfSubmodulesToListByKey = ref: mergeKey: (types.coercedTo
|
coerceAttrsOfSubmodulesToListByKey = ref: mergeKey: (types.coercedTo
|
||||||
|
|
@ -2846,7 +2852,7 @@ let
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
"istio_mixer_v1_ReportResponse" = {};
|
"istio_mixer_v1_ReportResponse" = { };
|
||||||
|
|
||||||
"istio_mixer_v1_RouteDirective" = {
|
"istio_mixer_v1_RouteDirective" = {
|
||||||
options = {
|
options = {
|
||||||
|
|
@ -4697,225 +4703,261 @@ let
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // (import ./istio-overrides.nix {inherit definitions lib;});
|
} // (import ./istio-overrides.nix { inherit definitions lib; });
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
kubernetes.customResources = [
|
kubernetes.customResources = [
|
||||||
{
|
{
|
||||||
group = "networking.istio.io";
|
group = "networking.istio.io";
|
||||||
version = "v1alpha3";
|
version = "v1alpha3";
|
||||||
kind = "DestinationRule";
|
kind = "DestinationRule";
|
||||||
description = "";
|
description = "";
|
||||||
module = definitions."istio_networking_v1alpha3_DestinationRule";
|
module = definitions."istio_networking_v1alpha3_DestinationRule";
|
||||||
}{
|
}
|
||||||
group = "networking.istio.io";
|
{
|
||||||
version = "v1alpha3";
|
group = "networking.istio.io";
|
||||||
kind = "EnvoyFilter";
|
version = "v1alpha3";
|
||||||
description = "";
|
kind = "EnvoyFilter";
|
||||||
module = definitions."istio_networking_v1alpha3_EnvoyFilter";
|
description = "";
|
||||||
}{
|
module = definitions."istio_networking_v1alpha3_EnvoyFilter";
|
||||||
group = "networking.istio.io";
|
}
|
||||||
version = "v1alpha3";
|
{
|
||||||
kind = "Gateway";
|
group = "networking.istio.io";
|
||||||
description = "";
|
version = "v1alpha3";
|
||||||
module = definitions."istio_networking_v1alpha3_Gateway";
|
kind = "Gateway";
|
||||||
}{
|
description = "";
|
||||||
group = "authentication.istio.io";
|
module = definitions."istio_networking_v1alpha3_Gateway";
|
||||||
version = "v1alpha1";
|
}
|
||||||
kind = "Policy";
|
{
|
||||||
description = "";
|
group = "authentication.istio.io";
|
||||||
module = definitions."istio_authentication_v1alpha1_Policy";
|
version = "v1alpha1";
|
||||||
}{
|
kind = "Policy";
|
||||||
group = "rbac.istio.io";
|
description = "";
|
||||||
version = "v1alpha1";
|
module = definitions."istio_authentication_v1alpha1_Policy";
|
||||||
kind = "RbacConfig";
|
}
|
||||||
description = "";
|
{
|
||||||
module = definitions."istio_rbac_v1alpha1_RbacConfig";
|
group = "rbac.istio.io";
|
||||||
}{
|
version = "v1alpha1";
|
||||||
group = "policy.istio.io";
|
kind = "RbacConfig";
|
||||||
version = "v1beta1";
|
description = "";
|
||||||
kind = "Rule";
|
module = definitions."istio_rbac_v1alpha1_RbacConfig";
|
||||||
description = "";
|
}
|
||||||
module = definitions."istio_policy_v1beta1_Rule";
|
{
|
||||||
}{
|
group = "policy.istio.io";
|
||||||
group = "networking.istio.io";
|
version = "v1beta1";
|
||||||
version = "v1alpha3";
|
kind = "Rule";
|
||||||
kind = "ServiceEntry";
|
description = "";
|
||||||
description = "";
|
module = definitions."istio_policy_v1beta1_Rule";
|
||||||
module = definitions."istio_networking_v1alpha3_ServiceEntry";
|
}
|
||||||
}{
|
{
|
||||||
group = "rbac.istio.io";
|
group = "networking.istio.io";
|
||||||
version = "v1alpha1";
|
version = "v1alpha3";
|
||||||
kind = "ServiceRole";
|
kind = "ServiceEntry";
|
||||||
description = "";
|
description = "";
|
||||||
module = definitions."istio_rbac_v1alpha1_ServiceRole";
|
module = definitions."istio_networking_v1alpha3_ServiceEntry";
|
||||||
}{
|
}
|
||||||
group = "rbac.istio.io";
|
{
|
||||||
version = "v1alpha1";
|
group = "rbac.istio.io";
|
||||||
kind = "ServiceRoleBinding";
|
version = "v1alpha1";
|
||||||
description = "";
|
kind = "ServiceRole";
|
||||||
module = definitions."istio_rbac_v1alpha1_ServiceRoleBinding";
|
description = "";
|
||||||
}{
|
module = definitions."istio_rbac_v1alpha1_ServiceRole";
|
||||||
group = "networking.istio.io";
|
}
|
||||||
version = "v1alpha3";
|
{
|
||||||
kind = "VirtualService";
|
group = "rbac.istio.io";
|
||||||
description = "";
|
version = "v1alpha1";
|
||||||
module = definitions."istio_networking_v1alpha3_VirtualService";
|
kind = "ServiceRoleBinding";
|
||||||
}{
|
description = "";
|
||||||
group = "config.istio.io";
|
module = definitions."istio_rbac_v1alpha1_ServiceRoleBinding";
|
||||||
version = "v1alpha2";
|
}
|
||||||
kind = "apikey";
|
{
|
||||||
description = "";
|
group = "networking.istio.io";
|
||||||
module = definitions."istio_mixer_apikey_InstanceMsg";
|
version = "v1alpha3";
|
||||||
}{
|
kind = "VirtualService";
|
||||||
group = "config.istio.io";
|
description = "";
|
||||||
version = "v1alpha2";
|
module = definitions."istio_networking_v1alpha3_VirtualService";
|
||||||
kind = "authorization";
|
}
|
||||||
description = "";
|
{
|
||||||
module = definitions."istio_mixer_authorization_InstanceMsg";
|
group = "config.istio.io";
|
||||||
}{
|
version = "v1alpha2";
|
||||||
group = "config.istio.io";
|
kind = "apikey";
|
||||||
version = "v1alpha2";
|
description = "";
|
||||||
kind = "bypass";
|
module = definitions."istio_mixer_apikey_InstanceMsg";
|
||||||
description = "";
|
}
|
||||||
module = definitions."istio_adapter_bypass_Params";
|
{
|
||||||
}{
|
group = "config.istio.io";
|
||||||
group = "config.istio.io";
|
version = "v1alpha2";
|
||||||
version = "v1alpha2";
|
kind = "authorization";
|
||||||
kind = "checknothing";
|
description = "";
|
||||||
description = "";
|
module = definitions."istio_mixer_authorization_InstanceMsg";
|
||||||
module = definitions."istio_mixer_checknothing_InstanceMsg";
|
}
|
||||||
}{
|
{
|
||||||
group = "config.istio.io";
|
group = "config.istio.io";
|
||||||
version = "v1alpha2";
|
version = "v1alpha2";
|
||||||
kind = "circonus";
|
kind = "bypass";
|
||||||
description = "";
|
description = "";
|
||||||
module = definitions."istio_adapter_circonus_Params";
|
module = definitions."istio_adapter_bypass_Params";
|
||||||
}{
|
}
|
||||||
group = "config.istio.io";
|
{
|
||||||
version = "v1alpha2";
|
group = "config.istio.io";
|
||||||
kind = "denier";
|
version = "v1alpha2";
|
||||||
description = "";
|
kind = "checknothing";
|
||||||
module = definitions."istio_adapter_denier_Params";
|
description = "";
|
||||||
}{
|
module = definitions."istio_mixer_checknothing_InstanceMsg";
|
||||||
group = "config.istio.io";
|
}
|
||||||
version = "v1alpha2";
|
{
|
||||||
kind = "edge";
|
group = "config.istio.io";
|
||||||
description = "";
|
version = "v1alpha2";
|
||||||
module = definitions."istio_mixer_edge_InstanceMsg";
|
kind = "circonus";
|
||||||
}{
|
description = "";
|
||||||
group = "config.istio.io";
|
module = definitions."istio_adapter_circonus_Params";
|
||||||
version = "v1alpha2";
|
}
|
||||||
kind = "fluentd";
|
{
|
||||||
description = "";
|
group = "config.istio.io";
|
||||||
module = definitions."istio_adapter_fluentd_Params";
|
version = "v1alpha2";
|
||||||
}{
|
kind = "denier";
|
||||||
group = "config.istio.io";
|
description = "";
|
||||||
version = "v1alpha2";
|
module = definitions."istio_adapter_denier_Params";
|
||||||
kind = "kubernetesenv";
|
}
|
||||||
description = "";
|
{
|
||||||
module = definitions."istio_adapter_kubernetesenv_Params";
|
group = "config.istio.io";
|
||||||
}{
|
version = "v1alpha2";
|
||||||
group = "config.istio.io";
|
kind = "edge";
|
||||||
version = "v1alpha2";
|
description = "";
|
||||||
kind = "listentry";
|
module = definitions."istio_mixer_edge_InstanceMsg";
|
||||||
description = "";
|
}
|
||||||
module = definitions."istio_mixer_listentry_InstanceMsg";
|
{
|
||||||
}{
|
group = "config.istio.io";
|
||||||
group = "config.istio.io";
|
version = "v1alpha2";
|
||||||
version = "v1alpha2";
|
kind = "fluentd";
|
||||||
kind = "logentry";
|
description = "";
|
||||||
description = "";
|
module = definitions."istio_adapter_fluentd_Params";
|
||||||
module = definitions."istio_mixer_logentry_InstanceMsg";
|
}
|
||||||
}{
|
{
|
||||||
group = "config.istio.io";
|
group = "config.istio.io";
|
||||||
version = "v1alpha2";
|
version = "v1alpha2";
|
||||||
kind = "memquota";
|
kind = "kubernetesenv";
|
||||||
description = "";
|
description = "";
|
||||||
module = definitions."istio_adapter_memquota_Params";
|
module = definitions."istio_adapter_kubernetesenv_Params";
|
||||||
}{
|
}
|
||||||
group = "config.istio.io";
|
{
|
||||||
version = "v1alpha2";
|
group = "config.istio.io";
|
||||||
kind = "metric";
|
version = "v1alpha2";
|
||||||
description = "";
|
kind = "listentry";
|
||||||
module = definitions."istio_mixer_metric_InstanceMsg";
|
description = "";
|
||||||
}{
|
module = definitions."istio_mixer_listentry_InstanceMsg";
|
||||||
group = "config.istio.io";
|
}
|
||||||
version = "v1alpha2";
|
{
|
||||||
kind = "opa";
|
group = "config.istio.io";
|
||||||
description = "";
|
version = "v1alpha2";
|
||||||
module = definitions."istio_adapter_opa_Params";
|
kind = "logentry";
|
||||||
}{
|
description = "";
|
||||||
group = "config.istio.io";
|
module = definitions."istio_mixer_logentry_InstanceMsg";
|
||||||
version = "v1alpha2";
|
}
|
||||||
kind = "prometheus";
|
{
|
||||||
description = "";
|
group = "config.istio.io";
|
||||||
module = definitions."istio_adapter_prometheus_Params";
|
version = "v1alpha2";
|
||||||
}{
|
kind = "memquota";
|
||||||
group = "config.istio.io";
|
description = "";
|
||||||
version = "v1alpha2";
|
module = definitions."istio_adapter_memquota_Params";
|
||||||
kind = "quota";
|
}
|
||||||
description = "";
|
{
|
||||||
module = definitions."istio_mixer_quota_InstanceMsg";
|
group = "config.istio.io";
|
||||||
}{
|
version = "v1alpha2";
|
||||||
group = "config.istio.io";
|
kind = "metric";
|
||||||
version = "v1alpha2";
|
description = "";
|
||||||
kind = "rbac";
|
module = definitions."istio_mixer_metric_InstanceMsg";
|
||||||
description = "";
|
}
|
||||||
module = definitions."istio_adapter_rbac_Params";
|
{
|
||||||
}{
|
group = "config.istio.io";
|
||||||
group = "config.istio.io";
|
version = "v1alpha2";
|
||||||
version = "v1alpha2";
|
kind = "opa";
|
||||||
kind = "redisquota";
|
description = "";
|
||||||
description = "";
|
module = definitions."istio_adapter_opa_Params";
|
||||||
module = definitions."istio_adapter_redisquota_Params";
|
}
|
||||||
}{
|
{
|
||||||
group = "config.istio.io";
|
group = "config.istio.io";
|
||||||
version = "v1alpha2";
|
version = "v1alpha2";
|
||||||
kind = "reportnothing";
|
kind = "prometheus";
|
||||||
description = "";
|
description = "";
|
||||||
module = definitions."istio_mixer_reportnothing_InstanceMsg";
|
module = definitions."istio_adapter_prometheus_Params";
|
||||||
}{
|
}
|
||||||
group = "config.istio.io";
|
{
|
||||||
version = "v1alpha2";
|
group = "config.istio.io";
|
||||||
kind = "servicecontrol";
|
version = "v1alpha2";
|
||||||
description = "";
|
kind = "quota";
|
||||||
module = definitions."istio_adapter_servicecontrol_Params";
|
description = "";
|
||||||
}{
|
module = definitions."istio_mixer_quota_InstanceMsg";
|
||||||
group = "config.istio.io";
|
}
|
||||||
version = "v1alpha2";
|
{
|
||||||
kind = "signalfx";
|
group = "config.istio.io";
|
||||||
description = "";
|
version = "v1alpha2";
|
||||||
module = definitions."istio_adapter_signalfx_Params";
|
kind = "rbac";
|
||||||
}{
|
description = "";
|
||||||
group = "config.istio.io";
|
module = definitions."istio_adapter_rbac_Params";
|
||||||
version = "v1alpha2";
|
}
|
||||||
kind = "solarwinds";
|
{
|
||||||
description = "";
|
group = "config.istio.io";
|
||||||
module = definitions."istio_adapter_solarwinds_Params";
|
version = "v1alpha2";
|
||||||
}{
|
kind = "redisquota";
|
||||||
group = "config.istio.io";
|
description = "";
|
||||||
version = "v1alpha2";
|
module = definitions."istio_adapter_redisquota_Params";
|
||||||
kind = "stackdriver";
|
}
|
||||||
description = "";
|
{
|
||||||
module = definitions."istio_adapter_stackdriver_Params";
|
group = "config.istio.io";
|
||||||
}{
|
version = "v1alpha2";
|
||||||
group = "config.istio.io";
|
kind = "reportnothing";
|
||||||
version = "v1alpha2";
|
description = "";
|
||||||
kind = "statsd";
|
module = definitions."istio_mixer_reportnothing_InstanceMsg";
|
||||||
description = "";
|
}
|
||||||
module = definitions."istio_adapter_statsd_Params";
|
{
|
||||||
}{
|
group = "config.istio.io";
|
||||||
group = "config.istio.io";
|
version = "v1alpha2";
|
||||||
version = "v1alpha2";
|
kind = "servicecontrol";
|
||||||
kind = "stdio";
|
description = "";
|
||||||
description = "";
|
module = definitions."istio_adapter_servicecontrol_Params";
|
||||||
module = definitions."istio_adapter_stdio_Params";
|
}
|
||||||
}{
|
{
|
||||||
group = "config.istio.io";
|
group = "config.istio.io";
|
||||||
version = "v1alpha2";
|
version = "v1alpha2";
|
||||||
kind = "tracespan";
|
kind = "signalfx";
|
||||||
description = "";
|
description = "";
|
||||||
module = definitions."istio_mixer_tracespan_InstanceMsg";
|
module = definitions."istio_adapter_signalfx_Params";
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
group = "config.istio.io";
|
||||||
|
version = "v1alpha2";
|
||||||
|
kind = "solarwinds";
|
||||||
|
description = "";
|
||||||
|
module = definitions."istio_adapter_solarwinds_Params";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
group = "config.istio.io";
|
||||||
|
version = "v1alpha2";
|
||||||
|
kind = "stackdriver";
|
||||||
|
description = "";
|
||||||
|
module = definitions."istio_adapter_stackdriver_Params";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
group = "config.istio.io";
|
||||||
|
version = "v1alpha2";
|
||||||
|
kind = "statsd";
|
||||||
|
description = "";
|
||||||
|
module = definitions."istio_adapter_statsd_Params";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
group = "config.istio.io";
|
||||||
|
version = "v1alpha2";
|
||||||
|
kind = "stdio";
|
||||||
|
description = "";
|
||||||
|
module = definitions."istio_adapter_stdio_Params";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
group = "config.istio.io";
|
||||||
|
version = "v1alpha2";
|
||||||
|
kind = "tracespan";
|
||||||
|
description = "";
|
||||||
|
module = definitions."istio_mixer_tracespan_InstanceMsg";
|
||||||
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,22 +4,24 @@ stdenv.mkDerivation rec {
|
||||||
pname = "k3s-airgap-images";
|
pname = "k3s-airgap-images";
|
||||||
version = k3s.version;
|
version = k3s.version;
|
||||||
|
|
||||||
src = let
|
src =
|
||||||
throwError = throw "Unsupported system ${stdenv.hostPlatform.system}";
|
let
|
||||||
in {
|
throwError = throw "Unsupported system ${stdenv.hostPlatform.system}";
|
||||||
x86_64-linux = fetchurl {
|
in
|
||||||
url = "https://github.com/rancher/k3s/releases/download/v${version}/k3s-airgap-images-amd64.tar";
|
{
|
||||||
sha256 = "sha256-6kQmlpNV+4cU1Kn5lyZhutXYK5qYdey0jubzYRRF3vA=";
|
x86_64-linux = fetchurl {
|
||||||
};
|
url = "https://github.com/rancher/k3s/releases/download/v${version}/k3s-airgap-images-amd64.tar";
|
||||||
aarch64-linux = fetchurl {
|
sha256 = "sha256-6kQmlpNV+4cU1Kn5lyZhutXYK5qYdey0jubzYRRF3vA=";
|
||||||
url = "https://github.com/rancher/k3s/releases/download/v${version}/k3s-airgap-images-arm64.tar";
|
};
|
||||||
sha256 = "sha256-OlqqdAmBN+azT0kfjZ/Bd0CFbbW5hTg9/8T9U05N0zE=";
|
aarch64-linux = fetchurl {
|
||||||
};
|
url = "https://github.com/rancher/k3s/releases/download/v${version}/k3s-airgap-images-arm64.tar";
|
||||||
armv7l-linux = fetchurl {
|
sha256 = "sha256-OlqqdAmBN+azT0kfjZ/Bd0CFbbW5hTg9/8T9U05N0zE=";
|
||||||
url = "https://github.com/rancher/k3s/releases/download/v${version}/k3s-airgap-images-arm.tar";
|
};
|
||||||
sha256 = "sha256-j/ARBtHDnfRk/7BpOvavoHe7L5dmsCZe5+wuZ5t4V/k=";
|
armv7l-linux = fetchurl {
|
||||||
};
|
url = "https://github.com/rancher/k3s/releases/download/v${version}/k3s-airgap-images-arm.tar";
|
||||||
}.${stdenv.hostPlatform.system} or throwError;
|
sha256 = "sha256-j/ARBtHDnfRk/7BpOvavoHe7L5dmsCZe5+wuZ5t4V/k=";
|
||||||
|
};
|
||||||
|
}.${stdenv.hostPlatform.system} or throwError;
|
||||||
|
|
||||||
preferLocalBuild = true;
|
preferLocalBuild = true;
|
||||||
dontUnpack = true;
|
dontUnpack = true;
|
||||||
|
|
|
||||||
343
modules/k8s.nix
343
modules/k8s.nix
|
|
@ -3,19 +3,20 @@
|
||||||
{ options, config, lib, pkgs, k8s, ... }:
|
{ options, config, lib, pkgs, k8s, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
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 (default:
|
catAttrs "default" (filter
|
||||||
(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) &&
|
||||||
) cfg.api.defaults);
|
(default.kind == null || default.kind == kind)
|
||||||
|
)
|
||||||
|
cfg.api.defaults);
|
||||||
|
|
||||||
moduleToAttrs = value:
|
moduleToAttrs = value:
|
||||||
if isAttrs value
|
if isAttrs value
|
||||||
|
|
@ -34,7 +35,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)";
|
||||||
|
|
@ -69,45 +70,47 @@ 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 = {
|
{
|
||||||
group = mkOption {
|
options = {
|
||||||
description = "Resource type group";
|
group = mkOption {
|
||||||
type = types.str;
|
description = "Resource type group";
|
||||||
};
|
type = types.str;
|
||||||
|
};
|
||||||
|
|
||||||
version = mkOption {
|
version = mkOption {
|
||||||
description = "Resoruce type version";
|
description = "Resoruce type version";
|
||||||
type = types.str;
|
type = types.str;
|
||||||
};
|
};
|
||||||
|
|
||||||
kind = mkOption {
|
kind = mkOption {
|
||||||
description = "Resource type kind";
|
description = "Resource type kind";
|
||||||
type = types.str;
|
type = types.str;
|
||||||
};
|
};
|
||||||
|
|
||||||
name = mkOption {
|
name = mkOption {
|
||||||
description = "Resource type name";
|
description = "Resource type name";
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
};
|
};
|
||||||
|
|
||||||
attrName = mkOption {
|
attrName = mkOption {
|
||||||
description = "Name of the nixified attribute";
|
description = "Name of the nixified attribute";
|
||||||
type = types.str;
|
type = types.str;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
} gvkKeyFn;
|
gvkKeyFn;
|
||||||
default = {};
|
default = { };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -120,24 +123,32 @@ 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: let
|
compareVersions = ver1: ver2:
|
||||||
getVersion = v: substring 1 10 v;
|
let
|
||||||
splittedVer1 = builtins.splitVersion (getVersion ver1);
|
getVersion = v: substring 1 10 v;
|
||||||
splittedVer2 = builtins.splitVersion (getVersion ver2);
|
splittedVer1 = builtins.splitVersion (getVersion ver1);
|
||||||
|
splittedVer2 = builtins.splitVersion (getVersion ver2);
|
||||||
|
|
||||||
v1 = if length splittedVer1 == 1 then "${getVersion ver1}prod" else getVersion ver1;
|
v1 = if length splittedVer1 == 1 then "${getVersion ver1}prod" else getVersion ver1;
|
||||||
v2 = if length splittedVer2 == 1 then "${getVersion ver2}prod" else getVersion ver2;
|
v2 = if length splittedVer2 == 1 then "${getVersion ver2}prod" else getVersion ver2;
|
||||||
in builtins.compareVersions v1 v2;
|
in
|
||||||
|
builtins.compareVersions v1 v2;
|
||||||
|
|
||||||
customResourceTypesByAttrName = zipAttrs (mapAttrsToList (_: resourceType: {
|
customResourceTypesByAttrName = zipAttrs (mapAttrsToList
|
||||||
${resourceType.attrName} = resourceType;
|
(_: resourceType: {
|
||||||
}) cfg.customTypes);
|
${resourceType.attrName} = resourceType;
|
||||||
|
})
|
||||||
|
cfg.customTypes);
|
||||||
|
|
||||||
customResourceTypesByAttrNameSortByVersion = mapAttrs (_: resourceTypes:
|
customResourceTypesByAttrNameSortByVersion = mapAttrs
|
||||||
reverseList (sort (r1: r2:
|
(_: resourceTypes:
|
||||||
compareVersions r1.version r2.version > 0
|
reverseList (sort
|
||||||
) resourceTypes)
|
(r1: r2:
|
||||||
) customResourceTypesByAttrName;
|
compareVersions r1.version r2.version > 0
|
||||||
|
)
|
||||||
|
resourceTypes)
|
||||||
|
)
|
||||||
|
customResourceTypesByAttrName;
|
||||||
|
|
||||||
latestCustomResourceTypes =
|
latestCustomResourceTypes =
|
||||||
mapAttrsToList (_: resources: last resources) customResourceTypesByAttrNameSortByVersion;
|
mapAttrsToList (_: resources: last resources) customResourceTypesByAttrNameSortByVersion;
|
||||||
|
|
@ -163,7 +174,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 = { };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -174,34 +185,43 @@ let
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
customResourceOptions = (mapAttrsToList (_: ct: {config, ...}: let
|
customResourceOptions = (mapAttrsToList
|
||||||
module = customResourceModuleForType config ct;
|
(_: ct: { config, ... }:
|
||||||
in {
|
let
|
||||||
options.resources.${ct.group}.${ct.version}.${ct.kind} = mkOption {
|
module = customResourceModuleForType config ct;
|
||||||
description = ct.description;
|
in
|
||||||
type = types.attrsOf (types.submodule module);
|
{
|
||||||
default = {};
|
options.resources.${ct.group}.${ct.version}.${ct.kind} = mkOption {
|
||||||
};
|
description = ct.description;
|
||||||
}) cfg.customTypes) ++ (map (ct: { options, config, ... }: let
|
type = types.attrsOf (types.submodule module);
|
||||||
module = customResourceModuleForType config ct;
|
default = { };
|
||||||
in {
|
};
|
||||||
options.resources.${ct.attrName} = mkOption {
|
})
|
||||||
description = ct.description;
|
cfg.customTypes) ++ (map
|
||||||
type = types.attrsOf (types.submodule module);
|
(ct: { options, config, ... }:
|
||||||
default = {};
|
let
|
||||||
};
|
module = customResourceModuleForType config ct;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.resources.${ct.attrName} = mkOption {
|
||||||
|
description = ct.description;
|
||||||
|
type = types.attrsOf (types.submodule module);
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
config.resources.${ct.group}.${ct.version}.${ct.kind} =
|
config.resources.${ct.group}.${ct.version}.${ct.kind} =
|
||||||
mkAliasDefinitions options.resources.${ct.attrName};
|
mkAliasDefinitions options.resources.${ct.attrName};
|
||||||
}) latestCustomResourceTypes);
|
})
|
||||||
|
latestCustomResourceTypes);
|
||||||
|
|
||||||
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";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -227,76 +247,80 @@ in {
|
||||||
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 = {
|
{
|
||||||
group = mkOption {
|
options = {
|
||||||
description = "Custom type group";
|
group = mkOption {
|
||||||
type = types.str;
|
description = "Custom type group";
|
||||||
};
|
type = types.str;
|
||||||
|
};
|
||||||
|
|
||||||
version = mkOption {
|
version = mkOption {
|
||||||
description = "Custom type version";
|
description = "Custom type version";
|
||||||
type = types.str;
|
type = types.str;
|
||||||
};
|
};
|
||||||
|
|
||||||
kind = mkOption {
|
kind = mkOption {
|
||||||
description = "Custom type kind";
|
description = "Custom type kind";
|
||||||
type = types.str;
|
type = types.str;
|
||||||
};
|
};
|
||||||
|
|
||||||
name = mkOption {
|
name = mkOption {
|
||||||
description = "Custom type resource name";
|
description = "Custom type resource name";
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = null;
|
default = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
attrName = mkOption {
|
attrName = mkOption {
|
||||||
description = "Name of the nixified attribute";
|
description = "Name of the nixified attribute";
|
||||||
type = types.str;
|
type = types.str;
|
||||||
};
|
};
|
||||||
|
|
||||||
description = mkOption {
|
description = mkOption {
|
||||||
description = "Custom type description";
|
description = "Custom type description";
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "";
|
default = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
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 (r1: r2:
|
apply = items: sort
|
||||||
if elem r1.kind cfg.resourceOrder && elem r2.kind cfg.resourceOrder
|
(r1: r2:
|
||||||
then indexOf cfg.resourceOrder r1.kind < indexOf cfg.resourceOrder r2.kind
|
if elem r1.kind cfg.resourceOrder && elem r2.kind cfg.resourceOrder
|
||||||
else if elem r1.kind cfg.resourceOrder then true else false
|
then indexOf cfg.resourceOrder r1.kind < indexOf cfg.resourceOrder r2.kind
|
||||||
) (unique items);
|
else if elem r1.kind cfg.resourceOrder then true else false
|
||||||
default = [];
|
)
|
||||||
|
(unique items);
|
||||||
|
default = [ ];
|
||||||
};
|
};
|
||||||
|
|
||||||
generated = mkOption {
|
generated = mkOption {
|
||||||
|
|
@ -321,41 +345,44 @@ in {
|
||||||
|
|
||||||
# module propagation options
|
# module propagation options
|
||||||
_m.propagate = [{
|
_m.propagate = [{
|
||||||
features = ["k8s"];
|
features = [ "k8s" ];
|
||||||
module = { config, ... }: {
|
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"];
|
{
|
||||||
module = { config, ... }: {
|
features = [ "k8s" "submodule" ];
|
||||||
# set module defaults
|
module = { config, ... }: {
|
||||||
kubernetes.api.defaults = (
|
# set module defaults
|
||||||
# propagate defaults if default propagation is enabled
|
kubernetes.api.defaults = (
|
||||||
(filter (default: default.propagate) cfg.api.defaults) ++
|
# propagate defaults if default propagation is enabled
|
||||||
|
(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 = {
|
||||||
"kubenix/module-name" = config.submodule.name;
|
"kubenix/module-name" = config.submodule.name;
|
||||||
"kubenix/module-version" = config.submodule.version;
|
"kubenix/module-version" = config.submodule.version;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}];
|
}];
|
||||||
|
|
||||||
# expose k8s helper methods as module argument
|
# expose k8s helper methods as module argument
|
||||||
_module.args.k8s = import ../lib/k8s.nix { inherit lib; };
|
_module.args.k8s = import ../lib/k8s.nix { inherit lib; };
|
||||||
|
|
||||||
kubernetes.api = mkMerge ([{
|
kubernetes.api = mkMerge ([{
|
||||||
# register custom types
|
# register custom types
|
||||||
types = mapAttrsToList (_: cr: {
|
types = mapAttrsToList
|
||||||
inherit (cr) name group version kind attrName;
|
(_: cr: {
|
||||||
}) cfg.customTypes;
|
inherit (cr) name group version kind attrName;
|
||||||
|
})
|
||||||
|
cfg.customTypes;
|
||||||
|
|
||||||
defaults = [{
|
defaults = [{
|
||||||
default = {
|
default = {
|
||||||
|
|
@ -373,24 +400,30 @@ in {
|
||||||
}] ++
|
}] ++
|
||||||
|
|
||||||
# import of yaml files
|
# import of yaml files
|
||||||
(map (i: let
|
(map
|
||||||
# load yaml file
|
(i:
|
||||||
object = loadYAML i;
|
let
|
||||||
groupVersion = splitString "/" object.apiVersion;
|
# load yaml file
|
||||||
name = object.metadata.name;
|
object = loadYAML i;
|
||||||
version = last groupVersion;
|
groupVersion = splitString "/" object.apiVersion;
|
||||||
group =
|
name = object.metadata.name;
|
||||||
if version == (head groupVersion)
|
version = last groupVersion;
|
||||||
then "core" else head groupVersion;
|
group =
|
||||||
kind = object.kind;
|
if version == (head groupVersion)
|
||||||
in {
|
then "core" else head groupVersion;
|
||||||
resources.${group}.${version}.${kind}.${name} = object;
|
kind = object.kind;
|
||||||
}) cfg.imports));
|
in
|
||||||
|
{
|
||||||
|
resources.${group}.${version}.${kind}.${name} = object;
|
||||||
|
})
|
||||||
|
cfg.imports));
|
||||||
|
|
||||||
kubernetes.objects = flatten (mapAttrsToList (_: type:
|
kubernetes.objects = flatten (mapAttrsToList
|
||||||
mapAttrsToList (name: resource: moduleToAttrs resource)
|
(_: type:
|
||||||
cfg.api.resources.${type.group}.${type.version}.${type.kind}
|
mapAttrsToList (name: resource: moduleToAttrs resource)
|
||||||
) cfg.api.types);
|
cfg.api.resources.${type.group}.${type.version}.${type.kind}
|
||||||
|
)
|
||||||
|
cfg.api.types);
|
||||||
|
|
||||||
kubernetes.generated = k8s.mkHashedList {
|
kubernetes.generated = k8s.mkHashedList {
|
||||||
items = config.kubernetes.objects;
|
items = config.kubernetes.objects;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
{ options, config, pkgs, lib, kubenix, ... }:
|
{ options, config, pkgs, lib, kubenix, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
parentModule = module;
|
parentModule = module;
|
||||||
globalConfig = config;
|
globalConfig = config;
|
||||||
|
|
@ -29,46 +28,50 @@ let
|
||||||
else if isAttrs mkOptionDefault.module then module // attrs
|
else if isAttrs mkOptionDefault.module then module // attrs
|
||||||
else module
|
else module
|
||||||
);
|
);
|
||||||
in [
|
in
|
||||||
|
[
|
||||||
{
|
{
|
||||||
_module.args.name = module.name;
|
_module.args.name = module.name;
|
||||||
_module.args.module = module;
|
_module.args.module = module;
|
||||||
}
|
}
|
||||||
./k8s.nix
|
./k8s.nix
|
||||||
./legacy.nix
|
./legacy.nix
|
||||||
(injectModuleAttrs moduleDefinition.module {_file = file;})
|
(injectModuleAttrs moduleDefinition.module { _file = file; })
|
||||||
{
|
{
|
||||||
config.kubernetes.namespace = mkOptionDefault module.namespace;
|
config.kubernetes.namespace = mkOptionDefault module.namespace;
|
||||||
config.kubenix.project = mkOptionDefault config.kubenix.project;
|
config.kubenix.project = mkOptionDefault config.kubenix.project;
|
||||||
}
|
}
|
||||||
] ++ config.kubernetes.defaultModuleConfiguration.all
|
] ++ config.kubernetes.defaultModuleConfiguration.all
|
||||||
++ (optionals (hasAttr moduleDefinition.name config.kubernetes.defaultModuleConfiguration)
|
++ (optionals (hasAttr moduleDefinition.name config.kubernetes.defaultModuleConfiguration)
|
||||||
config.kubernetes.defaultModuleConfiguration.${moduleDefinition.name});
|
config.kubernetes.defaultModuleConfiguration.${moduleDefinition.name});
|
||||||
|
|
||||||
# prefix kubernetes objects with ${serviceName}, this magic was removed in new kubenix
|
# prefix kubernetes objects with ${serviceName}, this magic was removed in new kubenix
|
||||||
prefixResources = resources: serviceName:
|
prefixResources = resources: serviceName:
|
||||||
mapAttrs' (name: resource: nameValuePair "${serviceName}-${name}" resource) resources;
|
mapAttrs' (name: resource: nameValuePair "${serviceName}-${name}" resource) resources;
|
||||||
|
|
||||||
# TODO: rewrite using mkOptionType
|
# TODO: rewrite using mkOptionType
|
||||||
defaultModuleConfigurationOptions = mapAttrs (name: moduleDefinition: mkOption {
|
defaultModuleConfigurationOptions = mapAttrs
|
||||||
description = "Module default configuration for ${name} module";
|
(name: moduleDefinition: mkOption {
|
||||||
type = types.coercedTo types.unspecified (value: [value]) (types.listOf types.unspecified);
|
description = "Module default configuration for ${name} module";
|
||||||
default = [];
|
type = types.coercedTo types.unspecified (value: [ value ]) (types.listOf types.unspecified);
|
||||||
apply = filter (v: v!=[]);
|
default = [ ];
|
||||||
}) config.kubernetes.moduleDefinitions;
|
apply = filter (v: v != [ ]);
|
||||||
|
})
|
||||||
|
config.kubernetes.moduleDefinitions;
|
||||||
|
|
||||||
getModuleDefinition = name:
|
getModuleDefinition = name:
|
||||||
if hasAttr name config.kubernetes.moduleDefinitions
|
if hasAttr name config.kubernetes.moduleDefinitions
|
||||||
then config.kubernetes.moduleDefinitions.${name}
|
then config.kubernetes.moduleDefinitions.${name}
|
||||||
else throw ''requested kubernetes moduleDefinition with name "${name}" does not exist'';
|
else throw ''requested kubernetes moduleDefinition with name "${name}" does not exist'';
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
imports = [ ./k8s.nix ];
|
imports = [ ./k8s.nix ];
|
||||||
|
|
||||||
options.kubernetes.moduleDefinitions = mkOption {
|
options.kubernetes.moduleDefinitions = mkOption {
|
||||||
description = "Legacy kubenix attribute set of module definitions";
|
description = "Legacy kubenix attribute set of module definitions";
|
||||||
default = {};
|
default = { };
|
||||||
type = types.attrsOf (types.submodule ({name, ...}: {
|
type = types.attrsOf (types.submodule ({ name, ... }: {
|
||||||
options = {
|
options = {
|
||||||
name = mkOption {
|
name = mkOption {
|
||||||
description = "Module definition name";
|
description = "Module definition name";
|
||||||
|
|
@ -101,19 +104,19 @@ in {
|
||||||
options = defaultModuleConfigurationOptions // {
|
options = defaultModuleConfigurationOptions // {
|
||||||
all = mkOption {
|
all = mkOption {
|
||||||
description = "Module default configuration for all modules";
|
description = "Module default configuration for all modules";
|
||||||
type = types.coercedTo types.unspecified (value: [value]) (types.listOf types.unspecified);
|
type = types.coercedTo types.unspecified (value: [ value ]) (types.listOf types.unspecified);
|
||||||
default = [];
|
default = [ ];
|
||||||
apply = filter (v: v != []);
|
apply = filter (v: v != [ ]);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
default = {};
|
default = { };
|
||||||
};
|
};
|
||||||
|
|
||||||
options.kubernetes.modules = mkOption {
|
options.kubernetes.modules = mkOption {
|
||||||
description = "Legacy kubenix attribute set of modules";
|
description = "Legacy kubenix attribute set of modules";
|
||||||
default = {};
|
default = { };
|
||||||
type = types.attrsOf (types.submodule ({config, name, ...}: {
|
type = types.attrsOf (types.submodule ({ config, name, ... }: {
|
||||||
options = {
|
options = {
|
||||||
name = mkOption {
|
name = mkOption {
|
||||||
description = "Module name";
|
description = "Module name";
|
||||||
|
|
@ -130,17 +133,19 @@ in {
|
||||||
labels = mkOption {
|
labels = mkOption {
|
||||||
description = "Attribute set of module lables";
|
description = "Attribute set of module lables";
|
||||||
type = types.attrsOf types.str;
|
type = types.attrsOf types.str;
|
||||||
default = {};
|
default = { };
|
||||||
};
|
};
|
||||||
|
|
||||||
configuration = mkOption {
|
configuration = mkOption {
|
||||||
description = "Module configuration";
|
description = "Module configuration";
|
||||||
type = submoduleWithSpecialArgs {
|
type = submoduleWithSpecialArgs
|
||||||
imports = mkModuleOptions (getModuleDefinition config.module) config;
|
{
|
||||||
} {
|
imports = mkModuleOptions (getModuleDefinition config.module) config;
|
||||||
inherit kubenix;
|
}
|
||||||
};
|
{
|
||||||
default = {};
|
inherit kubenix;
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
};
|
};
|
||||||
|
|
||||||
module = mkOption {
|
module = mkOption {
|
||||||
|
|
@ -153,9 +158,9 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
options.kubernetes.defaults = mkOption {
|
options.kubernetes.defaults = mkOption {
|
||||||
type = types.attrsOf (types.coercedTo types.attrs (value: [value]) (types.listOf types.attrs));
|
type = types.attrsOf (types.coercedTo types.attrs (value: [ value ]) (types.listOf types.attrs));
|
||||||
description = "Legacy kubenix kubernetes defaults.";
|
description = "Legacy kubenix kubernetes defaults.";
|
||||||
default = {};
|
default = { };
|
||||||
};
|
};
|
||||||
|
|
||||||
# for back compatibility with kubernetes.customResources
|
# for back compatibility with kubernetes.customResources
|
||||||
|
|
@ -163,50 +168,63 @@ in {
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
kubernetes = mkMerge [{
|
kubernetes = mkMerge [{
|
||||||
api.defaults = mapAttrsToList (attrName: default: let
|
api.defaults = mapAttrsToList
|
||||||
type = head (mapAttrsToList (_: v: v) (filterAttrs (_: type: type.attrName == attrName) config.kubernetes.api.types));
|
(attrName: default:
|
||||||
in {
|
let
|
||||||
default = { imports = default; };
|
type = head (mapAttrsToList (_: v: v) (filterAttrs (_: type: type.attrName == attrName) config.kubernetes.api.types));
|
||||||
} // (if (attrName == "all") then {} else {
|
in
|
||||||
resource = type.name;
|
{
|
||||||
})) config.kubernetes.defaults;
|
default = { imports = default; };
|
||||||
|
} // (if (attrName == "all") then { } else {
|
||||||
|
resource = type.name;
|
||||||
|
}))
|
||||||
|
config.kubernetes.defaults;
|
||||||
|
|
||||||
resources = mkMerge (
|
resources = mkMerge (
|
||||||
mapAttrsToList (name: module:
|
mapAttrsToList
|
||||||
mapAttrs' (_: type: let
|
(name: module:
|
||||||
moduleDefinition = getModuleDefinition module.module;
|
mapAttrs'
|
||||||
|
(_: type:
|
||||||
|
let
|
||||||
|
moduleDefinition = getModuleDefinition module.module;
|
||||||
|
|
||||||
moduleResources = module.configuration.kubernetes.api.resources.${type.attrName} or {};
|
moduleResources = module.configuration.kubernetes.api.resources.${type.attrName} or { };
|
||||||
|
|
||||||
moduleConfig =
|
moduleConfig =
|
||||||
if moduleDefinition.prefixResources && type.kind != "CustomResourceDefinition"
|
if moduleDefinition.prefixResources && type.kind != "CustomResourceDefinition"
|
||||||
then prefixResources (moduleToAttrs moduleResources) name
|
then prefixResources (moduleToAttrs moduleResources) name
|
||||||
else moduleToAttrs moduleResources;
|
else moduleToAttrs moduleResources;
|
||||||
in nameValuePair type.attrName
|
in
|
||||||
(if moduleDefinition.assignAsDefaults
|
nameValuePair type.attrName
|
||||||
then mkAllDefault moduleConfig 1000
|
(if moduleDefinition.assignAsDefaults
|
||||||
else moduleConfig)
|
then mkAllDefault moduleConfig 1000
|
||||||
) module.configuration.kubernetes.api.types
|
else moduleConfig)
|
||||||
) config.kubernetes.modules
|
)
|
||||||
|
module.configuration.kubernetes.api.types
|
||||||
|
)
|
||||||
|
config.kubernetes.modules
|
||||||
);
|
);
|
||||||
|
|
||||||
# custom types created from customResourceDefinitions
|
# custom types created from customResourceDefinitions
|
||||||
customTypes =
|
customTypes =
|
||||||
mapAttrsToList (name: crd: {
|
mapAttrsToList
|
||||||
group = crd.spec.group;
|
(name: crd: {
|
||||||
version = crd.spec.version;
|
group = crd.spec.group;
|
||||||
kind = crd.spec.names.kind;
|
version = crd.spec.version;
|
||||||
name = crd.spec.names.plural;
|
kind = crd.spec.names.kind;
|
||||||
attrName = mkOptionDefault name;
|
name = crd.spec.names.plural;
|
||||||
}) (config.kubernetes.resources.customResourceDefinitions or {});
|
attrName = mkOptionDefault name;
|
||||||
|
})
|
||||||
|
(config.kubernetes.resources.customResourceDefinitions or { });
|
||||||
|
|
||||||
defaultModuleConfiguration.all = {
|
defaultModuleConfiguration.all = {
|
||||||
_file = head options.kubernetes.defaultModuleConfiguration.files;
|
_file = head options.kubernetes.defaultModuleConfiguration.files;
|
||||||
config.kubernetes.version = mkDefault config.kubernetes.version;
|
config.kubernetes.version = mkDefault config.kubernetes.version;
|
||||||
config.kubernetes.moduleDefinitions = config.kubernetes.moduleDefinitions;
|
config.kubernetes.moduleDefinitions = config.kubernetes.moduleDefinitions;
|
||||||
};
|
};
|
||||||
} {
|
}
|
||||||
resources = mkAliasDefinitions options.kubernetes.customResources;
|
{
|
||||||
}];
|
resources = mkAliasDefinitions options.kubernetes.customResources;
|
||||||
|
}];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,24 +26,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,7 +1,6 @@
|
||||||
{ config, options, kubenix, pkgs, lib, ... }:
|
{ config, options, kubenix, pkgs, lib, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.submodules;
|
cfg = config.submodules;
|
||||||
parentConfig = config;
|
parentConfig = config;
|
||||||
|
|
@ -13,67 +12,82 @@ let
|
||||||
else requiredVersion == version
|
else requiredVersion == version
|
||||||
else true;
|
else true;
|
||||||
|
|
||||||
getDefaults = {name, version, tags, features}:
|
getDefaults = { name, version, tags, features }:
|
||||||
catAttrs "default" (filter (submoduleDefault:
|
catAttrs "default" (filter
|
||||||
(submoduleDefault.name == null || submoduleDefault.name == name) &&
|
(submoduleDefault:
|
||||||
(matchesVersion submoduleDefault.version version) &&
|
(submoduleDefault.name == null || submoduleDefault.name == name) &&
|
||||||
(
|
(matchesVersion submoduleDefault.version version) &&
|
||||||
(length submoduleDefault.tags == 0) ||
|
(
|
||||||
(length (intersectLists submoduleDefault.tags tags)) > 0
|
(length submoduleDefault.tags == 0) ||
|
||||||
) &&
|
(length (intersectLists submoduleDefault.tags tags)) > 0
|
||||||
(
|
) &&
|
||||||
(length submoduleDefault.features == 0) ||
|
(
|
||||||
(length (intersectLists submoduleDefault.features features)) > 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}: let
|
findSubmodule = { name, version ? null, latest ? true }:
|
||||||
matchingSubmodules = filter (el:
|
let
|
||||||
el.definition.name == name &&
|
matchingSubmodules = filter
|
||||||
(matchesVersion version el.definition.version)
|
(el:
|
||||||
) cfg.imports;
|
el.definition.name == name &&
|
||||||
|
(matchesVersion version el.definition.version)
|
||||||
|
)
|
||||||
|
cfg.imports;
|
||||||
|
|
||||||
versionSortedSubmodules = sort (s1: s2:
|
versionSortedSubmodules = sort
|
||||||
if builtins.compareVersions s1.definition.version s2.definition.version > 0
|
(s1: s2:
|
||||||
then true else false
|
if builtins.compareVersions s1.definition.version s2.definition.version > 0
|
||||||
) matchingSubmodules;
|
then true else false
|
||||||
|
)
|
||||||
|
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 matchingModule;
|
in
|
||||||
|
matchingModule;
|
||||||
|
|
||||||
passthruConfig = mapAttrsToList (name: opt: {
|
passthruConfig = mapAttrsToList
|
||||||
${name} = mkMerge (mapAttrsToList (_: inst:
|
(name: opt: {
|
||||||
if inst.passthru.enable
|
${name} = mkMerge (mapAttrsToList
|
||||||
then inst.config.submodule.passthru.${name} or {}
|
(_: inst:
|
||||||
else {}
|
if inst.passthru.enable
|
||||||
) config.submodules.instances);
|
then inst.config.submodule.passthru.${name} or { }
|
||||||
|
else { }
|
||||||
|
)
|
||||||
|
config.submodules.instances);
|
||||||
|
|
||||||
_module.args = mkMerge (mapAttrsToList (_: inst:
|
_module.args = mkMerge (mapAttrsToList
|
||||||
if inst.passthru.enable
|
(_: inst:
|
||||||
then inst.config.submodule.passthru._module.args or {}
|
if inst.passthru.enable
|
||||||
else {}
|
then inst.config.submodule.passthru._module.args or { }
|
||||||
) config.submodules.instances);
|
else { }
|
||||||
}) (removeAttrs options ["_definedNames" "_module" "_m" "submodules"]);
|
)
|
||||||
in {
|
config.submodules.instances);
|
||||||
|
})
|
||||||
|
(removeAttrs options [ "_definedNames" "_module" "_m" "submodules" ]);
|
||||||
|
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";
|
||||||
|
|
@ -93,23 +107,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 {
|
||||||
|
|
@ -123,139 +137,147 @@ 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, ... }:
|
||||||
evaledSubmodule' = evalModules {
|
let
|
||||||
inherit specialArgs;
|
evaledSubmodule' = evalModules {
|
||||||
modules = config.modules ++ [ ./base.nix ];
|
inherit specialArgs;
|
||||||
check = false;
|
modules = config.modules ++ [ ./base.nix ];
|
||||||
};
|
check = false;
|
||||||
|
|
||||||
evaledSubmodule =
|
|
||||||
if (!(elem "submodule" evaledSubmodule'.config._m.features))
|
|
||||||
then throw "no submodule defined"
|
|
||||||
else evaledSubmodule';
|
|
||||||
in {
|
|
||||||
options = {
|
|
||||||
module = mkOption {
|
|
||||||
description = "Module defining submodule";
|
|
||||||
type = types.unspecified;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
modules = mkOption {
|
evaledSubmodule =
|
||||||
description = "List of modules defining submodule";
|
if (!(elem "submodule" evaledSubmodule'.config._m.features))
|
||||||
type = types.listOf types.unspecified;
|
then throw "no submodule defined"
|
||||||
default = [config.module];
|
else evaledSubmodule';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
module = mkOption {
|
||||||
|
description = "Module defining submodule";
|
||||||
|
type = types.unspecified;
|
||||||
|
};
|
||||||
|
|
||||||
|
modules = mkOption {
|
||||||
|
description = "List of modules defining submodule";
|
||||||
|
type = types.listOf types.unspecified;
|
||||||
|
default = [ config.module ];
|
||||||
|
};
|
||||||
|
|
||||||
|
features = mkOption {
|
||||||
|
description = "List of features exposed by submodule";
|
||||||
|
type = types.listOf types.str;
|
||||||
|
};
|
||||||
|
|
||||||
|
definition = mkOption {
|
||||||
|
description = "Submodule definition";
|
||||||
|
type = types.attrs;
|
||||||
|
};
|
||||||
|
|
||||||
|
exportAs = mkOption {
|
||||||
|
description = "Name under which to register exports";
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
features = mkOption {
|
config = {
|
||||||
description = "List of features exposed by submodule";
|
definition = {
|
||||||
type = types.listOf types.str;
|
inherit (evaledSubmodule.config.submodule) name description version tags exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
definition = mkOption {
|
features = evaledSubmodule.config._m.features;
|
||||||
description = "Submodule definition";
|
|
||||||
type = types.attrs;
|
|
||||||
};
|
};
|
||||||
|
})
|
||||||
exportAs = mkOption {
|
)
|
||||||
description = "Name under which to register exports";
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = {
|
|
||||||
definition = {
|
|
||||||
inherit (evaledSubmodule.config.submodule) name description version tags exports;
|
|
||||||
};
|
|
||||||
|
|
||||||
features = evaledSubmodule.config._m.features;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
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, ...}: let
|
type = types.attrsOf (types.submodule ({ name, config, options, ... }:
|
||||||
# submodule associated with
|
let
|
||||||
submodule = findSubmodule {
|
# submodule associated with
|
||||||
name = config.submodule;
|
submodule = findSubmodule {
|
||||||
version = config.version;
|
name = config.submodule;
|
||||||
};
|
version = config.version;
|
||||||
|
|
||||||
# definition of a submodule
|
|
||||||
submoduleDefinition = submodule.definition;
|
|
||||||
|
|
||||||
# submodule defaults
|
|
||||||
defaults = getDefaults {
|
|
||||||
name = submoduleDefinition.name;
|
|
||||||
version = submoduleDefinition.version;
|
|
||||||
tags = submoduleDefinition.tags;
|
|
||||||
features = submodule.features;
|
|
||||||
};
|
|
||||||
in {
|
|
||||||
options = {
|
|
||||||
name = mkOption {
|
|
||||||
description = "Submodule instance name";
|
|
||||||
type = types.str;
|
|
||||||
default = name;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
submodule = mkOption {
|
# definition of a submodule
|
||||||
description = "Name of the submodule to use";
|
submoduleDefinition = submodule.definition;
|
||||||
type = types.str;
|
|
||||||
default = name;
|
|
||||||
};
|
|
||||||
|
|
||||||
version = mkOption {
|
# submodule defaults
|
||||||
description = ''
|
defaults = getDefaults {
|
||||||
Version of submodule to use, if version starts with "~" it is
|
name = submoduleDefinition.name;
|
||||||
threated as regex pattern for example "~1.0.*"
|
version = submoduleDefinition.version;
|
||||||
'';
|
tags = submoduleDefinition.tags;
|
||||||
type = types.nullOr types.str;
|
features = submodule.features;
|
||||||
default = null;
|
|
||||||
};
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
name = mkOption {
|
||||||
|
description = "Submodule instance name";
|
||||||
|
type = types.str;
|
||||||
|
default = name;
|
||||||
|
};
|
||||||
|
|
||||||
passthru.enable = mkOption {
|
submodule = mkOption {
|
||||||
description = "Whether to passthru submodule resources";
|
description = "Name of the submodule to use";
|
||||||
type = types.bool;
|
type = types.str;
|
||||||
default = true;
|
default = name;
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkOption {
|
version = mkOption {
|
||||||
description = "Submodule instance ${config.name} for ${submoduleDefinition.name}:${submoduleDefinition.version} config";
|
description = ''
|
||||||
type = submoduleWithSpecialArgs ({...}: {
|
Version of submodule to use, if version starts with "~" it is
|
||||||
imports = submodule.modules ++ defaults ++ [ ./base.nix ];
|
threated as regex pattern for example "~1.0.*"
|
||||||
_module.args.pkgs = pkgs;
|
'';
|
||||||
_module.args.name = config.name;
|
type = types.nullOr types.str;
|
||||||
_module.args.submodule = config;
|
default = null;
|
||||||
submodule.args = mkAliasDefinitions options.args;
|
};
|
||||||
}) specialArgs;
|
|
||||||
default = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
args = mkOption {
|
passthru.enable = mkOption {
|
||||||
description = "Submodule arguments (alias of config.submodule.args)";
|
description = "Whether to passthru submodule resources";
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkOption {
|
||||||
|
description = "Submodule instance ${config.name} for ${submoduleDefinition.name}:${submoduleDefinition.version} config";
|
||||||
|
type = submoduleWithSpecialArgs
|
||||||
|
({ ... }: {
|
||||||
|
imports = submodule.modules ++ defaults ++ [ ./base.nix ];
|
||||||
|
_module.args.pkgs = pkgs;
|
||||||
|
_module.args.name = config.name;
|
||||||
|
_module.args.submodule = config;
|
||||||
|
submodule.args = mkAliasDefinitions options.args;
|
||||||
|
})
|
||||||
|
specialArgs;
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
args = mkOption {
|
||||||
|
description = "Submodule arguments (alias of config.submodule.args)";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
}));
|
||||||
}));
|
|
||||||
};
|
};
|
||||||
default = {};
|
default = { };
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkMerge ([
|
config = mkMerge ([
|
||||||
{
|
{
|
||||||
# register exported functions as args
|
# register exported functions as args
|
||||||
_module.args = mkMerge (map (submodule: {
|
_module.args = mkMerge (map
|
||||||
${submodule.exportAs} = submodule.definition.exports;
|
(submodule: {
|
||||||
}) (filter (submodule: submodule.exportAs != null) cfg.imports));
|
${submodule.exportAs} = submodule.definition.exports;
|
||||||
|
})
|
||||||
|
(filter (submodule: submodule.exportAs != null) cfg.imports));
|
||||||
|
|
||||||
_m.features = ["submodules"];
|
_m.features = [ "submodules" ];
|
||||||
|
|
||||||
submodules.specialArgs.kubenix = kubenix;
|
submodules.specialArgs.kubenix = kubenix;
|
||||||
|
|
||||||
|
|
@ -267,17 +289,19 @@ in {
|
||||||
};
|
};
|
||||||
}]
|
}]
|
||||||
|
|
||||||
(map (propagate: {
|
(map
|
||||||
features = propagate.features;
|
(propagate: {
|
||||||
default = propagate.module;
|
features = propagate.features;
|
||||||
}) config._m.propagate)
|
default = propagate.module;
|
||||||
|
})
|
||||||
|
config._m.propagate)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
(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;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
{ nixosPath, config, pkgs, lib, kubenix, ... }:
|
{ nixosPath, config, pkgs, lib, kubenix, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.testing;
|
cfg = config.testing;
|
||||||
|
|
||||||
|
|
@ -18,7 +17,8 @@ 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
|
||||||
|
|
@ -40,30 +40,32 @@ in {
|
||||||
|
|
||||||
defaults = mkOption {
|
defaults = mkOption {
|
||||||
description = "List of defaults to apply to tests";
|
description = "List of defaults 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 defaults";
|
description = "List of features that test 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 test";
|
description = "Default to apply to test";
|
||||||
type = types.unspecified;
|
type = types.unspecified;
|
||||||
default = {};
|
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 (module: {
|
type = types.listOf (types.coercedTo types.path
|
||||||
inherit module;
|
(module: {
|
||||||
}) (types.submodule testModule));
|
inherit module;
|
||||||
|
})
|
||||||
|
(types.submodule testModule));
|
||||||
apply = tests: filter isTestEnabled tests;
|
apply = tests: filter isTestEnabled tests;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -82,7 +84,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,16 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
with import ../../lib/docker.nix { inherit lib pkgs; };
|
with import ../../lib/docker.nix { inherit lib pkgs; };
|
||||||
|
|
||||||
let
|
let
|
||||||
testing = config.testing;
|
testing = config.testing;
|
||||||
|
|
||||||
allImages = flatten (map (t: t.evaled.config.docker.export or []) testing.tests);
|
allImages = 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";
|
||||||
|
|
@ -38,7 +38,7 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
config.testing.defaults = [{
|
config.testing.defaults = [{
|
||||||
features = ["docker"];
|
features = [ "docker" ];
|
||||||
default = {
|
default = {
|
||||||
docker.registry.url = cfg.registryUrl;
|
docker.registry.url = cfg.registryUrl;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
{ lib, config, pkgs, ... }:
|
{ lib, config, pkgs, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
testing = config.testing;
|
testing = config.testing;
|
||||||
cfg = testing.driver.kubetest;
|
cfg = testing.driver.kubetest;
|
||||||
|
|
||||||
kubetest = import ./kubetestdrv.nix {inherit pkgs;};
|
kubetest = import ./kubetestdrv.nix { inherit pkgs; };
|
||||||
|
|
||||||
pythonEnv = pkgs.python38.withPackages (ps: with ps; [
|
pythonEnv = pkgs.python38.withPackages (ps: with ps; [
|
||||||
pytest
|
pytest
|
||||||
|
|
@ -16,18 +15,20 @@ let
|
||||||
|
|
||||||
toTestScript = t:
|
toTestScript = t:
|
||||||
if isString t.script
|
if isString t.script
|
||||||
then pkgs.writeText "${t.name}.py" ''
|
then
|
||||||
${cfg.defaultHeader}
|
pkgs.writeText "${t.name}.py" ''
|
||||||
${t.script}
|
${cfg.defaultHeader}
|
||||||
''
|
${t.script}
|
||||||
|
''
|
||||||
else t.script;
|
else t.script;
|
||||||
|
|
||||||
tests = pkgs.linkFarm "${testing.name}-tests" (
|
tests = pkgs.linkFarm "${testing.name}-tests" (
|
||||||
map (t: {
|
map
|
||||||
path = toTestScript t;
|
(t: {
|
||||||
name = "${t.name}_test.py";
|
path = toTestScript t;
|
||||||
})
|
name = "${t.name}_test.py";
|
||||||
( filter (t: t.script != null) testing.tests )
|
})
|
||||||
|
(filter (t: t.script != null) testing.tests)
|
||||||
);
|
);
|
||||||
|
|
||||||
testScript = pkgs.writeScript "test-${testing.name}.sh" ''
|
testScript = pkgs.writeScript "test-${testing.name}.sh" ''
|
||||||
|
|
@ -35,7 +36,8 @@ let
|
||||||
${pythonEnv}/bin/pytest -p no:cacheprovider ${tests} $@
|
${pythonEnv}/bin/pytest -p no:cacheprovider ${tests} $@
|
||||||
'';
|
'';
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
options.testing.driver.kubetest = {
|
options.testing.driver.kubetest = {
|
||||||
defaultHeader = mkOption {
|
defaultHeader = mkOption {
|
||||||
type = types.lines;
|
type = types.lines;
|
||||||
|
|
@ -48,7 +50,7 @@ in {
|
||||||
extraPackages = mkOption {
|
extraPackages = mkOption {
|
||||||
type = types.listOf types.package;
|
type = types.listOf types.package;
|
||||||
description = "Extra packages to pass to tests";
|
description = "Extra packages to pass to tests";
|
||||||
default = [];
|
default = [ ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
{ lib, config, testing, kubenix, ... }:
|
{ lib, config, testing, kubenix, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
modules = [
|
modules = [
|
||||||
# testing module
|
# testing module
|
||||||
|
|
@ -36,25 +35,29 @@ let
|
||||||
|
|
||||||
# defaults that can be applied on tests
|
# defaults that can be applied on tests
|
||||||
defaults =
|
defaults =
|
||||||
filter (d:
|
filter
|
||||||
(intersectLists d.features testFeatures) == d.features ||
|
(d:
|
||||||
(length d.features) == 0
|
(intersectLists d.features testFeatures) == d.features ||
|
||||||
) testing.defaults;
|
(length d.features) == 0
|
||||||
|
)
|
||||||
|
testing.defaults;
|
||||||
|
|
||||||
# add default modules to all modules
|
# add default modules to all modules
|
||||||
modulesWithDefaults = modules ++ (map (d: d.default) defaults);
|
modulesWithDefaults = modules ++ (map (d: d.default) defaults);
|
||||||
|
|
||||||
# evaled test
|
# evaled test
|
||||||
evaled = let
|
evaled =
|
||||||
evaled' = kubenix.evalModules {
|
let
|
||||||
modules = modulesWithDefaults;
|
evaled' = kubenix.evalModules {
|
||||||
};
|
modules = modulesWithDefaults;
|
||||||
in
|
};
|
||||||
|
in
|
||||||
if testing.throwError then evaled'
|
if testing.throwError 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";
|
||||||
|
|
@ -97,7 +100,7 @@ in {
|
||||||
description = "Test result";
|
description = "Test result";
|
||||||
type = types.unspecified;
|
type = types.unspecified;
|
||||||
internal = true;
|
internal = true;
|
||||||
default = [];
|
default = [ ];
|
||||||
};
|
};
|
||||||
|
|
||||||
script = mkOption {
|
script = mkOption {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
{ lib, config, pkgs, ... }:
|
{ lib, config, pkgs, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
testing = config.testing;
|
testing = config.testing;
|
||||||
|
|
||||||
|
|
@ -32,7 +31,8 @@ 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;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
}:
|
}:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
testing = config.testing;
|
testing = config.testing;
|
||||||
kubeconfig = "/etc/${config.services.kubernetes.pki.etcClusterAdminKubeconfig}";
|
kubeconfig = "/etc/${config.services.kubernetes.pki.etcClusterAdminKubeconfig}";
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
{ lib, config, pkgs, ... }:
|
{ lib, config, pkgs, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.test;
|
cfg = config.test;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
options.test = {
|
options.test = {
|
||||||
name = mkOption {
|
name = mkOption {
|
||||||
description = "Test name";
|
description = "Test name";
|
||||||
|
|
@ -38,8 +38,8 @@ 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
|
||||||
|
|
|
||||||
|
|
@ -27,4 +27,3 @@ stdenv.mkDerivation {
|
||||||
homepage = "https://github.com/kubernetes/kubectl";
|
homepage = "https://github.com/kubernetes/kubectl";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ in
|
||||||
}:
|
}:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
kubenix = import ./. { inherit pkgs; };
|
kubenix = import ./. { inherit pkgs; };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{ pkgs ? import <nixpkgs> {}
|
{ pkgs ? import <nixpkgs> { }
|
||||||
, lib ? pkgs.lib
|
, lib ? pkgs.lib
|
||||||
, kubenix ? import ../. { inherit pkgs lib; }
|
, kubenix ? import ../. { inherit pkgs lib; }
|
||||||
|
|
||||||
|
|
@ -7,12 +7,12 @@
|
||||||
, k8sVersion ? "1.21"
|
, k8sVersion ? "1.21"
|
||||||
, registryUrl ? throw "Registry url not defined"
|
, registryUrl ? throw "Registry url not defined"
|
||||||
, throwError ? true # whether any testing error should throw an error
|
, throwError ? true # whether any testing error should throw an error
|
||||||
, enabledTests ? null }:
|
, enabledTests ? null
|
||||||
|
}:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
images = pkgs.callPackage ./images.nix {};
|
images = pkgs.callPackage ./images.nix { };
|
||||||
|
|
||||||
config = (kubenix.evalModules {
|
config = (kubenix.evalModules {
|
||||||
modules = [
|
modules = [
|
||||||
|
|
@ -34,7 +34,7 @@ let
|
||||||
#./legacy/k8s.nix
|
#./legacy/k8s.nix
|
||||||
#./legacy/crd.nix
|
#./legacy/crd.nix
|
||||||
#./legacy/modules.nix
|
#./legacy/modules.nix
|
||||||
./helm/simple.nix
|
# ./helm/simple.nix
|
||||||
# ./istio/bookinfo.nix # infinite recursion
|
# ./istio/bookinfo.nix # infinite recursion
|
||||||
./submodules/simple.nix
|
./submodules/simple.nix
|
||||||
./submodules/defaults.nix
|
./submodules/defaults.nix
|
||||||
|
|
@ -48,7 +48,7 @@ let
|
||||||
docker.registryUrl = registryUrl;
|
docker.registryUrl = registryUrl;
|
||||||
defaults = [
|
defaults = [
|
||||||
{
|
{
|
||||||
features = ["k8s"];
|
features = [ "k8s" ];
|
||||||
default = {
|
default = {
|
||||||
kubernetes.version = k8sVersion;
|
kubernetes.version = k8sVersion;
|
||||||
};
|
};
|
||||||
|
|
@ -64,4 +64,5 @@ let
|
||||||
inherit kubenix nixosPath;
|
inherit kubenix nixosPath;
|
||||||
};
|
};
|
||||||
}).config;
|
}).config;
|
||||||
in pkgs.recurseIntoAttrs config.testing
|
in
|
||||||
|
pkgs.recurseIntoAttrs config.testing
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
with lib;
|
with lib;
|
||||||
with kubenix.lib;
|
with kubenix.lib;
|
||||||
with pkgs.dockerTools;
|
with pkgs.dockerTools;
|
||||||
|
|
||||||
let
|
let
|
||||||
corev1 = config.kubernetes.api.resources.core.v1;
|
corev1 = config.kubernetes.api.resources.core.v1;
|
||||||
appsv1 = config.kubernetes.api.resources.apps.v1;
|
appsv1 = config.kubernetes.api.resources.apps.v1;
|
||||||
|
|
@ -31,7 +30,8 @@ let
|
||||||
finalImageName = "docker.io/bitnami/bitnami-shell";
|
finalImageName = "docker.io/bitnami/bitnami-shell";
|
||||||
finalImageTag = "10";
|
finalImageTag = "10";
|
||||||
};
|
};
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
imports = [ kubenix.modules.test kubenix.modules.helm kubenix.modules.k8s ];
|
imports = [ kubenix.modules.test kubenix.modules.helm kubenix.modules.k8s ];
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
|
|
@ -43,15 +43,17 @@ in {
|
||||||
appsv1.StatefulSet ? "app-psql-postgresql-primary" &&
|
appsv1.StatefulSet ? "app-psql-postgresql-primary" &&
|
||||||
appsv1.StatefulSet ? "app-psql-postgresql-read" &&
|
appsv1.StatefulSet ? "app-psql-postgresql-read" &&
|
||||||
corev1.Secret ? "app-psql-postgresql" &&
|
corev1.Secret ? "app-psql-postgresql" &&
|
||||||
corev1.Service ? "app-psql-postgresql-headless" ;
|
corev1.Service ? "app-psql-postgresql-headless";
|
||||||
} {
|
}
|
||||||
message = "should have values passed";
|
{
|
||||||
assertion = appsv1.StatefulSet.app-psql-postgresql-read.spec.replicas == 2;
|
message = "should have values passed";
|
||||||
} {
|
assertion = appsv1.StatefulSet.app-psql-postgresql-read.spec.replicas == 2;
|
||||||
message = "should have namespace defined";
|
}
|
||||||
assertion =
|
{
|
||||||
appsv1.StatefulSet.app-psql-postgresql-primary.metadata.namespace == "test";
|
message = "should have namespace defined";
|
||||||
}];
|
assertion =
|
||||||
|
appsv1.StatefulSet.app-psql-postgresql-primary.metadata.namespace == "test";
|
||||||
|
}];
|
||||||
testScript = ''
|
testScript = ''
|
||||||
kube.wait_until_succeeds("docker load < ${postgresql}")
|
kube.wait_until_succeeds("docker load < ${postgresql}")
|
||||||
kube.wait_until_succeeds("docker load < ${postgresqlExporter}")
|
kube.wait_until_succeeds("docker load < ${postgresqlExporter}")
|
||||||
|
|
@ -61,7 +63,7 @@ in {
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
kubernetes.resources.namespaces.test = {};
|
kubernetes.resources.namespaces.test = { };
|
||||||
|
|
||||||
kubernetes.helm.instances.app-psql = {
|
kubernetes.helm.instances.app-psql = {
|
||||||
namespace = "test";
|
namespace = "test";
|
||||||
|
|
|
||||||
|
|
@ -10,47 +10,49 @@ with lib;
|
||||||
contents = [ pkgs.bash pkgs.curl pkgs.cacert ];
|
contents = [ pkgs.bash pkgs.curl pkgs.cacert ];
|
||||||
};
|
};
|
||||||
|
|
||||||
nginx = let
|
nginx =
|
||||||
nginxPort = "80";
|
let
|
||||||
nginxConf = pkgs.writeText "nginx.conf" ''
|
nginxPort = "80";
|
||||||
user nginx nginx;
|
nginxConf = pkgs.writeText "nginx.conf" ''
|
||||||
daemon off;
|
user nginx nginx;
|
||||||
error_log /dev/stdout info;
|
daemon off;
|
||||||
pid /dev/null;
|
error_log /dev/stdout info;
|
||||||
events {}
|
pid /dev/null;
|
||||||
http {
|
events {}
|
||||||
access_log /dev/stdout;
|
http {
|
||||||
server {
|
access_log /dev/stdout;
|
||||||
listen ${nginxPort};
|
server {
|
||||||
index index.html;
|
listen ${nginxPort};
|
||||||
location / {
|
index index.html;
|
||||||
root ${nginxWebRoot};
|
location / {
|
||||||
|
root ${nginxWebRoot};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
'';
|
||||||
'';
|
nginxWebRoot = pkgs.writeTextDir "index.html" ''
|
||||||
nginxWebRoot = pkgs.writeTextDir "index.html" ''
|
<html><body><h1>Hello from NGINX</h1></body></html>
|
||||||
<html><body><h1>Hello from NGINX</h1></body></html>
|
'';
|
||||||
'';
|
in
|
||||||
in 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
|
||||||
mkdir -p var/cache/nginx
|
mkdir -p var/cache/nginx
|
||||||
chmod u+w var/cache/nginx
|
chmod u+w var/cache/nginx
|
||||||
mkdir -p var/log/nginx
|
mkdir -p var/log/nginx
|
||||||
chmod u+w var/log/nginx
|
chmod u+w var/log/nginx
|
||||||
echo "nginx:x:1000:1000::/:" > etc/passwd
|
echo "nginx:x:1000:1000::/:" > etc/passwd
|
||||||
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" = { };
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,25 +18,28 @@
|
||||||
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";
|
||||||
} {
|
}
|
||||||
uri.exact = "/login";
|
{
|
||||||
} {
|
uri.exact = "/login";
|
||||||
uri.exact = "/logout";
|
}
|
||||||
} {
|
{
|
||||||
uri.prefix = "/api/v1/products";
|
uri.exact = "/logout";
|
||||||
}];
|
}
|
||||||
|
{
|
||||||
|
uri.prefix = "/api/v1/products";
|
||||||
|
}];
|
||||||
route = [{
|
route = [{
|
||||||
destination = {
|
destination = {
|
||||||
host = "productpage";
|
host = "productpage";
|
||||||
|
|
@ -63,13 +66,15 @@
|
||||||
subsets = [{
|
subsets = [{
|
||||||
name = "v1";
|
name = "v1";
|
||||||
labels.version = "v1";
|
labels.version = "v1";
|
||||||
} {
|
}
|
||||||
name = "v2";
|
{
|
||||||
labels.version = "v2";
|
name = "v2";
|
||||||
} {
|
labels.version = "v2";
|
||||||
name = "v3";
|
}
|
||||||
labels.version = "v3";
|
{
|
||||||
}];
|
name = "v3";
|
||||||
|
labels.version = "v3";
|
||||||
|
}];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -79,16 +84,19 @@
|
||||||
subsets = [{
|
subsets = [{
|
||||||
name = "v1";
|
name = "v1";
|
||||||
labels.version = "v1";
|
labels.version = "v1";
|
||||||
} {
|
}
|
||||||
name = "v2";
|
{
|
||||||
labels.version = "v2";
|
name = "v2";
|
||||||
} {
|
labels.version = "v2";
|
||||||
name = "v2-mysql";
|
}
|
||||||
labels.version = "v2-mysql";
|
{
|
||||||
} {
|
name = "v2-mysql";
|
||||||
name = "v2-mysql-vm";
|
labels.version = "v2-mysql";
|
||||||
labels.version = "v2-mysql-vm";
|
}
|
||||||
}];
|
{
|
||||||
|
name = "v2-mysql-vm";
|
||||||
|
labels.version = "v2-mysql-vm";
|
||||||
|
}];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -98,10 +106,11 @@
|
||||||
subsets = [{
|
subsets = [{
|
||||||
name = "v1";
|
name = "v1";
|
||||||
labels.version = "v1";
|
labels.version = "v1";
|
||||||
} {
|
}
|
||||||
name = "v2";
|
{
|
||||||
labels.version = "v2";
|
name = "v2";
|
||||||
}];
|
labels.version = "v2";
|
||||||
|
}];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
{ config, lib, kubenix, pkgs, ... }:
|
{ config, lib, kubenix, pkgs, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
latestCrontab = config.kubernetes.api.resources.cronTabs.latest;
|
latestCrontab = config.kubernetes.api.resources.cronTabs.latest;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
imports = with kubenix.modules; [ test k8s ];
|
imports = with kubenix.modules; [ test k8s ];
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
|
|
@ -37,7 +37,8 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
} {
|
}
|
||||||
|
{
|
||||||
group = "stable.example.com";
|
group = "stable.example.com";
|
||||||
version = "v2";
|
version = "v2";
|
||||||
kind = "CronTab";
|
kind = "CronTab";
|
||||||
|
|
@ -56,7 +57,8 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
} {
|
}
|
||||||
|
{
|
||||||
group = "stable.example.com";
|
group = "stable.example.com";
|
||||||
version = "v3";
|
version = "v3";
|
||||||
kind = "CronTab";
|
kind = "CronTab";
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
{ config, lib, kubenix, ... }:
|
{ config, lib, kubenix, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
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 = {
|
||||||
|
|
@ -14,16 +14,18 @@ in {
|
||||||
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";
|
||||||
} {
|
}
|
||||||
message = "Should have default label set with group, version, kind";
|
{
|
||||||
assertion = pod1.metadata.labels.gvk-label == "value";
|
message = "Should have default label set with group, version, kind";
|
||||||
} {
|
assertion = pod1.metadata.labels.gvk-label == "value";
|
||||||
message = "Should have conditional annotation set";
|
}
|
||||||
assertion = pod2.metadata.annotations.conditional-annotation == "value";
|
{
|
||||||
}];
|
message = "Should have conditional annotation set";
|
||||||
|
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";
|
||||||
|
|
@ -32,17 +34,19 @@ in {
|
||||||
kubernetes.api.defaults = [{
|
kubernetes.api.defaults = [{
|
||||||
resource = "pods";
|
resource = "pods";
|
||||||
default.metadata.labels.resource-label = "value";
|
default.metadata.labels.resource-label = "value";
|
||||||
} {
|
}
|
||||||
group = "core";
|
{
|
||||||
kind = "Pod";
|
group = "core";
|
||||||
version = "v1";
|
kind = "Pod";
|
||||||
default.metadata.labels.gvk-label = "value";
|
version = "v1";
|
||||||
} {
|
default.metadata.labels.gvk-label = "value";
|
||||||
resource = "pods";
|
}
|
||||||
default = { config, ... }: {
|
{
|
||||||
config.metadata.annotations = mkIf (config.metadata.labels ? "custom-label") {
|
resource = "pods";
|
||||||
conditional-annotation = "value";
|
default = { config, ... }: {
|
||||||
|
config.metadata.annotations = mkIf (config.metadata.labels ? "custom-label") {
|
||||||
|
conditional-annotation = "value";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
}];
|
||||||
}];
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
{ config, lib, pkgs, kubenix, images, ... }:
|
{ config, lib, pkgs, kubenix, images, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.kubernetes.api.resources.deployments.nginx;
|
cfg = config.kubernetes.api.resources.deployments.nginx;
|
||||||
image = images.nginx;
|
image = images.nginx;
|
||||||
|
|
@ -16,12 +15,13 @@ let
|
||||||
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 = {
|
||||||
|
|
@ -35,13 +35,15 @@ in {
|
||||||
else if ((builtins.compareVersions config.kubernetes.version "1.8") <= 0)
|
else if ((builtins.compareVersions config.kubernetes.version "1.8") <= 0)
|
||||||
then cfg.apiVersion == "apps/v1beta2"
|
then cfg.apiVersion == "apps/v1beta2"
|
||||||
else cfg.apiVersion == "apps/v1";
|
else cfg.apiVersion == "apps/v1";
|
||||||
} {
|
}
|
||||||
message = "should have corrent kind set";
|
{
|
||||||
assertion = cfg.kind == "Deployment";
|
message = "should have corrent kind set";
|
||||||
} {
|
assertion = cfg.kind == "Deployment";
|
||||||
message = "should have replicas set";
|
}
|
||||||
assertion = cfg.spec.replicas == 3;
|
{
|
||||||
}];
|
message = "should have replicas set";
|
||||||
|
assertion = cfg.spec.replicas == 3;
|
||||||
|
}];
|
||||||
script = ''
|
script = ''
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
{ config, lib, kubenix, ... }:
|
{ config, lib, kubenix, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
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 = {
|
||||||
|
|
@ -15,10 +15,11 @@ in {
|
||||||
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";
|
{
|
||||||
assertion = deployment.metadata.name == "nginx-deployment";
|
message = "Deployment should have name set";
|
||||||
}];
|
assertion = deployment.metadata.name == "nginx-deployment";
|
||||||
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
kubernetes.imports = [
|
kubernetes.imports = [
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
{ config, lib, kubenix, pkgs, ... }:
|
{ config, lib, kubenix, pkgs, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.kubernetes.api.resources.customResourceDefinitions.crontabs;
|
cfg = config.kubernetes.api.resources.customResourceDefinitions.crontabs;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
imports = with kubenix.modules; [ test k8s ];
|
imports = with kubenix.modules; [ test k8s ];
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
|
|
@ -34,7 +34,7 @@ in {
|
||||||
plural = "crontabs";
|
plural = "crontabs";
|
||||||
singular = "crontab";
|
singular = "crontab";
|
||||||
kind = "CronTab";
|
kind = "CronTab";
|
||||||
shortNames = ["ct"];
|
shortNames = [ "ct" ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -55,7 +55,7 @@ in {
|
||||||
};
|
};
|
||||||
}];
|
}];
|
||||||
|
|
||||||
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,8 +1,8 @@
|
||||||
{ config, kubenix, ... }:
|
{ config, kubenix, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.kubernetes.api.resources.pods.nginx;
|
cfg = config.kubernetes.api.resources.pods.nginx;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
imports = [ kubenix.modules.test kubenix.modules.k8s ];
|
imports = [ kubenix.modules.test kubenix.modules.k8s ];
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
|
|
@ -11,11 +11,12 @@ in {
|
||||||
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";
|
{
|
||||||
assertion = cfg.metadata.name == "nginx";
|
message = "should have name set";
|
||||||
}];
|
assertion = cfg.metadata.name == "nginx";
|
||||||
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
kubernetes.resources.pods.nginx = {};
|
kubernetes.resources.pods.nginx = { };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
{ name, config, lib, kubenix, images, ... }:
|
{ name, config, lib, kubenix, images, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.submodules.instances.passthru;
|
cfg = config.submodules.instances.passthru;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
imports = with kubenix.modules; [ test submodules k8s docker ];
|
imports = with kubenix.modules; [ test submodules k8s docker ];
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
|
|
@ -13,16 +13,17 @@ in {
|
||||||
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";
|
{
|
||||||
assertion = (head config.docker.export).imageName == "xtruder/nginx";
|
message = "Should expose docker image";
|
||||||
}];
|
assertion = (head config.docker.export).imageName == "xtruder/nginx";
|
||||||
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
kubernetes.namespace = "test-namespace";
|
kubernetes.namespace = "test-namespace";
|
||||||
|
|
||||||
submodules.imports = [{
|
submodules.imports = [{
|
||||||
module = {name, config, ...}: {
|
module = { name, config, ... }: {
|
||||||
imports = with kubenix.modules; [ submodule k8s docker ];
|
imports = with kubenix.modules; [ submodule k8s docker ];
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,18 @@
|
||||||
{ options, config, lib, kubenix, pkgs, ... }:
|
{ options, config, lib, kubenix, pkgs, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
findObject = { kind, name }: filter (object:
|
findObject = { kind, name }: filter
|
||||||
object.kind == kind && object.metadata.name == name
|
(object:
|
||||||
) config.kubernetes.objects;
|
object.kind == kind && object.metadata.name == name
|
||||||
|
)
|
||||||
|
config.kubernetes.objects;
|
||||||
|
|
||||||
getObject = filter: head (findObject filter);
|
getObject = filter: head (findObject filter);
|
||||||
|
|
||||||
hasObject = { kind, name }: length (findObject { inherit kind name; }) == 1;
|
hasObject = { kind, name }: length (findObject { inherit kind name; }) == 1;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
imports = with kubenix.modules; [ test k8s legacy ];
|
imports = with kubenix.modules; [ test k8s legacy ];
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
|
|
@ -20,12 +22,13 @@ in {
|
||||||
assertions = [{
|
assertions = [{
|
||||||
message = "should define crd in module";
|
message = "should define crd in module";
|
||||||
assertion =
|
assertion =
|
||||||
hasObject {kind = "SecretClaim"; name = "module-claim";};
|
hasObject { kind = "SecretClaim"; name = "module-claim"; };
|
||||||
} {
|
}
|
||||||
message = "should define crd in root";
|
{
|
||||||
assertion =
|
message = "should define crd in root";
|
||||||
hasObject {kind = "SecretClaim"; name = "root-claim";};
|
assertion =
|
||||||
}];
|
hasObject { kind = "SecretClaim"; name = "root-claim"; };
|
||||||
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
kubernetes.namespace = "test";
|
kubernetes.namespace = "test";
|
||||||
|
|
@ -40,7 +43,7 @@ in {
|
||||||
|
|
||||||
type = mkOption {
|
type = mkOption {
|
||||||
description = "Type of the secret";
|
description = "Type of the secret";
|
||||||
type = types.enum ["Opaque" "kubernetes.io/tls"];
|
type = types.enum [ "Opaque" "kubernetes.io/tls" ];
|
||||||
default = "Opaque";
|
default = "Opaque";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -62,7 +65,7 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
kubernetes.resources.customResourceDefinitions.secret-claims = {
|
kubernetes.resources.customResourceDefinitions.secret-claims = {
|
||||||
kind = "CustomResourceDefinition";
|
kind = "CustomResourceDefinition";
|
||||||
apiVersion = "apiextensions.k8s.io/v1beta1";
|
apiVersion = "apiextensions.k8s.io/v1beta1";
|
||||||
|
|
@ -74,7 +77,7 @@ in {
|
||||||
names = {
|
names = {
|
||||||
plural = "secretclaims";
|
plural = "secretclaims";
|
||||||
kind = "SecretClaim";
|
kind = "SecretClaim";
|
||||||
shortNames = ["scl"];
|
shortNames = [ "scl" ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
{ config, lib, kubenix, pkgs, ... }:
|
{ config, lib, kubenix, pkgs, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.kubernetes.api.resources.deployments.app;
|
cfg = config.kubernetes.api.resources.deployments.app;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
imports = with kubenix.modules; [ test k8s legacy ];
|
imports = with kubenix.modules; [ test k8s legacy ];
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
|
|
@ -15,13 +15,14 @@ in {
|
||||||
assertion =
|
assertion =
|
||||||
cfg.kind == "Deployment" &&
|
cfg.kind == "Deployment" &&
|
||||||
cfg.metadata.name == "app";
|
cfg.metadata.name == "app";
|
||||||
} {
|
}
|
||||||
message = "should have correct defaults set";
|
{
|
||||||
assertion =
|
message = "should have correct defaults set";
|
||||||
cfg.metadata.namespace == "test" &&
|
assertion =
|
||||||
cfg.metadata.labels.label1 == "value1" &&
|
cfg.metadata.namespace == "test" &&
|
||||||
cfg.metadata.labels.label2 == "value2";
|
cfg.metadata.labels.label1 == "value1" &&
|
||||||
}];
|
cfg.metadata.labels.label2 == "value2";
|
||||||
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
kubernetes.resources.deployments.app = {
|
kubernetes.resources.deployments.app = {
|
||||||
|
|
@ -39,7 +40,7 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
kubernetes.resources.configMaps.app = {
|
kubernetes.resources.configMaps.app = {
|
||||||
data."my-conf.json" = builtins.toJSON {};
|
data."my-conf.json" = builtins.toJSON { };
|
||||||
};
|
};
|
||||||
|
|
||||||
kubernetes.defaults = {
|
kubernetes.defaults = {
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,18 @@
|
||||||
{ options, config, lib, kubenix, pkgs, ... }:
|
{ options, config, lib, kubenix, pkgs, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
findObject = { kind, name }: filter (object:
|
findObject = { kind, name }: filter
|
||||||
object.kind == kind && object.metadata.name == name
|
(object:
|
||||||
) config.kubernetes.objects;
|
object.kind == kind && object.metadata.name == name
|
||||||
|
)
|
||||||
|
config.kubernetes.objects;
|
||||||
|
|
||||||
getObject = filter: head (findObject filter);
|
getObject = filter: head (findObject filter);
|
||||||
|
|
||||||
hasObject = { kind, name }: length (findObject { inherit kind name; }) == 1;
|
hasObject = { kind, name }: length (findObject { inherit kind name; }) == 1;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
imports = with kubenix.modules; [ test k8s legacy ];
|
imports = with kubenix.modules; [ test k8s legacy ];
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
|
|
@ -19,21 +21,21 @@ in {
|
||||||
assertions = [{
|
assertions = [{
|
||||||
message = "should have all objects";
|
message = "should have all objects";
|
||||||
assertion =
|
assertion =
|
||||||
hasObject {kind = "Deployment"; name = "myapp";} &&
|
hasObject { kind = "Deployment"; name = "myapp"; } &&
|
||||||
hasObject {kind = "Deployment"; name = "myapp2";} &&
|
hasObject { kind = "Deployment"; name = "myapp2"; } &&
|
||||||
hasObject {kind = "Deployment"; name = "myapp2-app2";};
|
hasObject { kind = "Deployment"; name = "myapp2-app2"; };
|
||||||
} {
|
}
|
||||||
message = "should have default labels set";
|
{
|
||||||
assertion =
|
message = "should have default labels set";
|
||||||
(getObject {kind = "Deployment"; name = "myapp2-app2";})
|
assertion =
|
||||||
.metadata.labels.module-label or false == "value" &&
|
(getObject { kind = "Deployment"; name = "myapp2-app2"; }).metadata.labels.module-label or false == "value" &&
|
||||||
(getObject {kind = "Deployment"; name = "myapp2";})
|
(getObject { kind = "Deployment"; name = "myapp2"; }).metadata.labels.module-label or false == "value";
|
||||||
.metadata.labels.module-label or false == "value";
|
}
|
||||||
} {
|
{
|
||||||
message = "should passthru resources to root module";
|
message = "should passthru resources to root module";
|
||||||
assertion =
|
assertion =
|
||||||
config.kubernetes.resources.deployments.myapp2-app2-app.metadata.labels.module-label or false == "value";
|
config.kubernetes.resources.deployments.myapp2-app2-app.metadata.labels.module-label or false == "value";
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
kubernetes.defaults.all.metadata.labels.module-label = "value";
|
kubernetes.defaults.all.metadata.labels.module-label = "value";
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
{ name, config, lib, kubenix, images, ... }:
|
{ name, config, lib, kubenix, images, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.submodules.instances.test.config;
|
cfg = config.submodules.instances.test.config;
|
||||||
deployment = cfg.kubernetes.api.deployments.nginx;
|
deployment = cfg.kubernetes.api.deployments.nginx;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
imports = [ kubenix.modules.test kubenix.module ];
|
imports = [ kubenix.modules.test kubenix.module ];
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
|
|
@ -14,13 +14,15 @@ in {
|
||||||
assertions = [{
|
assertions = [{
|
||||||
message = "Namespace not propagated";
|
message = "Namespace not propagated";
|
||||||
assertion = deployment.metadata.namespace == "test";
|
assertion = deployment.metadata.namespace == "test";
|
||||||
} {
|
}
|
||||||
message = "Version not propagated";
|
{
|
||||||
assertion = cfg.kubernetes.version == config.kubernetes.version;
|
message = "Version not propagated";
|
||||||
} {
|
assertion = cfg.kubernetes.version == config.kubernetes.version;
|
||||||
message = "docker image should be added to exported images";
|
}
|
||||||
assertion = (head config.docker.export) == images.nginx;
|
{
|
||||||
}];
|
message = "docker image should be added to exported images";
|
||||||
|
assertion = (head config.docker.export) == images.nginx;
|
||||||
|
}];
|
||||||
testScript = ''
|
testScript = ''
|
||||||
kube.wait_until_succeeds("docker load < ${images.nginx}")
|
kube.wait_until_succeeds("docker load < ${images.nginx}")
|
||||||
kube.wait_until_succeeds("kubectl apply -f ${config.kubernetes.result}")
|
kube.wait_until_succeeds("kubectl apply -f ${config.kubernetes.result}")
|
||||||
|
|
@ -31,7 +33,7 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
submodules.imports = [{
|
submodules.imports = [{
|
||||||
module = {name, config, ...}: {
|
module = { name, config, ... }: {
|
||||||
submodule.name = "nginx";
|
submodule.name = "nginx";
|
||||||
kubernetes.api.deployments.nginx = {
|
kubernetes.api.deployments.nginx = {
|
||||||
metadata = {
|
metadata = {
|
||||||
|
|
@ -55,7 +57,7 @@ in {
|
||||||
};
|
};
|
||||||
}];
|
}];
|
||||||
|
|
||||||
kubernetes.api.namespaces.test = {};
|
kubernetes.api.namespaces.test = { };
|
||||||
|
|
||||||
submodules.instances.test = {
|
submodules.instances.test = {
|
||||||
submodule = "nginx";
|
submodule = "nginx";
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
{ name, config, lib, kubenix, ... }:
|
{ name, config, lib, kubenix, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
instance1 = config.submodules.instances.instance1;
|
instance1 = config.submodules.instances.instance1;
|
||||||
instance2 = config.submodules.instances.instance2;
|
instance2 = config.submodules.instances.instance2;
|
||||||
|
|
@ -10,7 +9,7 @@ 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 = {
|
||||||
|
|
@ -25,7 +24,8 @@ let
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
imports = with kubenix.modules; [ test submodules ];
|
imports = with kubenix.modules; [ test submodules ];
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
|
|
@ -34,95 +34,130 @@ in {
|
||||||
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";
|
||||||
} {
|
}
|
||||||
message = "should apply defaults by tag2";
|
{
|
||||||
assertion = instance2.config.submodule.args.value == "value2";
|
message = "should apply defaults by tag2";
|
||||||
} {
|
assertion = instance2.config.submodule.args.value == "value2";
|
||||||
message = "should apply defaults by tag2";
|
}
|
||||||
assertion = instance3.config.submodule.args.value == "value2";
|
{
|
||||||
} {
|
message = "should apply defaults by tag2";
|
||||||
message = "should apply defaults to all";
|
assertion = instance3.config.submodule.args.value == "value2";
|
||||||
assertion =
|
}
|
||||||
instance1.config.submodule.args.defaultValue == "value" &&
|
{
|
||||||
instance2.config.submodule.args.defaultValue == "value";
|
message = "should apply defaults to all";
|
||||||
} {
|
assertion =
|
||||||
message = "instance1 and instance3 should have value of default-value";
|
instance1.config.submodule.args.defaultValue == "value" &&
|
||||||
assertion = instance3.config.submodule.args.defaultValue == "default-value";
|
instance2.config.submodule.args.defaultValue == "value";
|
||||||
} {
|
}
|
||||||
message = "should apply defaults by submodule name";
|
{
|
||||||
assertion = instance4.config.submodule.args.value == "value4";
|
message = "instance1 and instance3 should have value of default-value";
|
||||||
} {
|
assertion = instance3.config.submodule.args.defaultValue == "default-value";
|
||||||
message = "should apply defaults by custom condition";
|
}
|
||||||
assertion = instance5.config.submodule.args.defaultValue == "my-custom-value";
|
{
|
||||||
} {
|
message = "should apply defaults by submodule name";
|
||||||
message = "should apply defaults to versioned submodule";
|
assertion = instance4.config.submodule.args.value == "value4";
|
||||||
assertion = versioned-submodule.config.submodule.args.defaultValue == "versioned-submodule";
|
}
|
||||||
}];
|
{
|
||||||
|
message = "should apply defaults by custom condition";
|
||||||
|
assertion = instance5.config.submodule.args.defaultValue == "my-custom-value";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
message = "should apply defaults to versioned submodule";
|
||||||
|
assertion = versioned-submodule.config.submodule.args.defaultValue == "versioned-submodule";
|
||||||
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
submodules.imports = [{
|
submodules.imports = [{
|
||||||
modules = [submodule {
|
modules = [
|
||||||
submodule = {
|
submodule
|
||||||
name = "submodule1";
|
{
|
||||||
tags = ["tag1"];
|
submodule = {
|
||||||
};
|
name = "submodule1";
|
||||||
|
tags = [ "tag1" ];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
modules = [
|
||||||
|
submodule
|
||||||
|
{
|
||||||
|
submodule = {
|
||||||
|
name = "submodule2";
|
||||||
|
tags = [ "tag2" ];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
modules = [
|
||||||
|
submodule
|
||||||
|
{
|
||||||
|
submodule = {
|
||||||
|
name = "submodule3";
|
||||||
|
tags = [ "tag2" ];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
modules = [
|
||||||
|
submodule
|
||||||
|
{
|
||||||
|
submodule = {
|
||||||
|
name = "submodule4";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
modules = [
|
||||||
|
submodule
|
||||||
|
{
|
||||||
|
submodule = {
|
||||||
|
name = "submodule5";
|
||||||
|
};
|
||||||
|
submodule.args.value = "custom-value";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
modules = [
|
||||||
|
submodule
|
||||||
|
{
|
||||||
|
submodule = {
|
||||||
|
name = "versioned-submodule";
|
||||||
|
version = "2.0.0";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
}];
|
}];
|
||||||
} {
|
|
||||||
modules = [submodule {
|
|
||||||
submodule = {
|
|
||||||
name = "submodule2";
|
|
||||||
tags = ["tag2"];
|
|
||||||
};
|
|
||||||
}];
|
|
||||||
} {
|
|
||||||
modules = [submodule {
|
|
||||||
submodule = {
|
|
||||||
name = "submodule3";
|
|
||||||
tags = ["tag2"];
|
|
||||||
};
|
|
||||||
}];
|
|
||||||
} {
|
|
||||||
modules = [submodule {
|
|
||||||
submodule = {
|
|
||||||
name = "submodule4";
|
|
||||||
};
|
|
||||||
}];
|
|
||||||
} {
|
|
||||||
modules = [submodule {
|
|
||||||
submodule = {
|
|
||||||
name = "submodule5";
|
|
||||||
};
|
|
||||||
submodule.args.value = "custom-value";
|
|
||||||
}];
|
|
||||||
} {
|
|
||||||
modules = [submodule {
|
|
||||||
submodule = {
|
|
||||||
name = "versioned-submodule";
|
|
||||||
version = "2.0.0";
|
|
||||||
};
|
|
||||||
}];
|
|
||||||
}];
|
|
||||||
|
|
||||||
submodules.defaults = [{
|
submodules.defaults = [{
|
||||||
default.submodule.args.defaultValue = mkDefault "value";
|
default.submodule.args.defaultValue = mkDefault "value";
|
||||||
} {
|
}
|
||||||
tags = ["tag1"];
|
{
|
||||||
default.submodule.args.value = mkDefault "value1";
|
tags = [ "tag1" ];
|
||||||
} {
|
default.submodule.args.value = mkDefault "value1";
|
||||||
tags = ["tag2"];
|
}
|
||||||
default.submodule.args.value = mkDefault "value2";
|
{
|
||||||
} {
|
tags = [ "tag2" ];
|
||||||
name = "submodule4";
|
default.submodule.args.value = mkDefault "value2";
|
||||||
default.submodule.args.value = mkDefault "value4";
|
}
|
||||||
} {
|
{
|
||||||
default = {config, ...}: {
|
name = "submodule4";
|
||||||
submodule.args.defaultValue = mkIf (config.submodule.args.value == "custom-value") "my-custom-value";
|
default.submodule.args.value = mkDefault "value4";
|
||||||
};
|
}
|
||||||
} {
|
{
|
||||||
name = "versioned-submodule";
|
default = { config, ... }: {
|
||||||
version = "2.0.0";
|
submodule.args.defaultValue = mkIf (config.submodule.args.value == "custom-value") "my-custom-value";
|
||||||
default.submodule.args.value = mkDefault "versioned";
|
};
|
||||||
}];
|
}
|
||||||
|
{
|
||||||
|
name = "versioned-submodule";
|
||||||
|
version = "2.0.0";
|
||||||
|
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,7 +1,6 @@
|
||||||
{ name, config, lib, kubenix, subm-lib, ... }:
|
{ name, config, lib, kubenix, subm-lib, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
submodule = {
|
submodule = {
|
||||||
imports = [ kubenix.modules.submodule ];
|
imports = [ kubenix.modules.submodule ];
|
||||||
|
|
@ -13,7 +12,8 @@ let
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
imports = with kubenix.modules; [ test submodules ];
|
imports = with kubenix.modules; [ test submodules ];
|
||||||
|
|
||||||
test = {
|
test = {
|
||||||
|
|
@ -26,7 +26,7 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
submodules.imports = [{
|
submodules.imports = [{
|
||||||
modules = [submodule];
|
modules = [ submodule ];
|
||||||
exportAs = "subm-lib";
|
exportAs = "subm-lib";
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
{ name, config, lib, kubenix, ... }:
|
{ name, config, lib, kubenix, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
submodule = { name, ... }: {
|
submodule = { name, ... }: {
|
||||||
imports = [ kubenix.modules.submodule ];
|
imports = [ kubenix.modules.submodule ];
|
||||||
|
|
@ -11,14 +10,15 @@ let
|
||||||
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 = { };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -29,17 +29,19 @@ in {
|
||||||
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";
|
||||||
} {
|
}
|
||||||
message = "should not passthru values if passthru not enabled";
|
{
|
||||||
assertion = !(hasAttr "inst2" config.global);
|
message = "should not passthru values if passthru not enabled";
|
||||||
} {
|
assertion = !(hasAttr "inst2" config.global);
|
||||||
message = "should passthru by default";
|
}
|
||||||
assertion = hasAttr "inst3" config.global && config.global.inst3 == "true";
|
{
|
||||||
}];
|
message = "should passthru by default";
|
||||||
|
assertion = hasAttr "inst3" config.global && config.global.inst3 == "true";
|
||||||
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
submodules.imports = [{
|
submodules.imports = [{
|
||||||
modules = [submodule];
|
modules = [ submodule ];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
submodules.instances.inst1 = {
|
submodules.instances.inst1 = {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
{ name, config, lib, kubenix, ... }:
|
{ name, config, lib, kubenix, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
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 = {
|
||||||
|
|
@ -14,22 +14,27 @@ in {
|
||||||
assertions = [{
|
assertions = [{
|
||||||
message = "Submodule name is set";
|
message = "Submodule name is set";
|
||||||
assertion = cfg.name == "instance";
|
assertion = cfg.name == "instance";
|
||||||
} {
|
}
|
||||||
message = "Submodule version is set";
|
{
|
||||||
assertion = cfg.version == null;
|
message = "Submodule version is set";
|
||||||
} {
|
assertion = cfg.version == null;
|
||||||
message = "Submodule config has submodule definition";
|
}
|
||||||
assertion = cfg.config.submodule.name == "submodule";
|
{
|
||||||
} {
|
message = "Submodule config has submodule definition";
|
||||||
message = "Should have argument set";
|
assertion = cfg.config.submodule.name == "submodule";
|
||||||
assertion = args.value == "test";
|
}
|
||||||
} {
|
{
|
||||||
message = "Should have submodule name set";
|
message = "Should have argument set";
|
||||||
assertion = args.name == "instance";
|
assertion = args.value == "test";
|
||||||
} {
|
}
|
||||||
message = "should have tag set";
|
{
|
||||||
assertion = elem "tag" (cfg.config.submodule.tags);
|
message = "Should have submodule name set";
|
||||||
}];
|
assertion = args.name == "instance";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
message = "should have tag set";
|
||||||
|
assertion = elem "tag" (cfg.config.submodule.tags);
|
||||||
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
submodules.propagate.enable = true;
|
submodules.propagate.enable = true;
|
||||||
|
|
@ -51,7 +56,7 @@ in {
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
submodule.name = "submodule";
|
submodule.name = "submodule";
|
||||||
submodule.tags = ["tag"];
|
submodule.tags = [ "tag" ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}];
|
}];
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
{ name, config, lib, kubenix, ... }:
|
{ name, config, lib, kubenix, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
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;
|
||||||
|
|
@ -17,7 +16,8 @@ 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 = {
|
||||||
|
|
@ -26,36 +26,45 @@ in {
|
||||||
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";
|
||||||
} {
|
}
|
||||||
message = "should select regex version";
|
{
|
||||||
assertion = inst-regex.version == "1.2.1";
|
message = "should select regex version";
|
||||||
} {
|
assertion = inst-regex.version == "1.2.1";
|
||||||
message = "should select latest version";
|
}
|
||||||
assertion = inst-latest.version == "1.2.1";
|
{
|
||||||
}];
|
message = "should select latest version";
|
||||||
|
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 = [{
|
}
|
||||||
config.submodule.version = "1.1.0";
|
{
|
||||||
config.version = "1.1.0";
|
modules = [{
|
||||||
} submodule];
|
config.submodule.version = "1.1.0";
|
||||||
} {
|
config.version = "1.1.0";
|
||||||
modules = [{
|
}
|
||||||
config.submodule.version = "1.2.0";
|
submodule];
|
||||||
config.version = "1.2.0";
|
}
|
||||||
} submodule];
|
{
|
||||||
} {
|
modules = [{
|
||||||
modules = [{
|
config.submodule.version = "1.2.0";
|
||||||
config.submodule.version = "1.2.1";
|
config.version = "1.2.0";
|
||||||
config.version = "1.2.1";
|
}
|
||||||
} submodule];
|
submodule];
|
||||||
}];
|
}
|
||||||
|
{
|
||||||
|
modules = [{
|
||||||
|
config.submodule.version = "1.2.1";
|
||||||
|
config.version = "1.2.1";
|
||||||
|
}
|
||||||
|
submodule];
|
||||||
|
}];
|
||||||
|
|
||||||
submodules.instances.inst-exact = {
|
submodules.instances.inst-exact = {
|
||||||
submodule = "subm";
|
submodule = "subm";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue