From 8536b0315183beff4175d1fdf26e4f38f70304ec Mon Sep 17 00:00:00 2001 From: Jaka Hudoklin Date: Tue, 26 Feb 2019 21:23:14 +0100 Subject: [PATCH] feat(submodules): refactor defaults --- k8s/submodule.nix | 35 +++++++----- submodules.nix | 71 ++++++++++++++++------- tests/default.nix | 1 + tests/submodules/defaults.nix | 102 ++++++++++++++++++++++++++++++++++ 4 files changed, 175 insertions(+), 34 deletions(-) create mode 100644 tests/submodules/defaults.nix diff --git a/k8s/submodule.nix b/k8s/submodule.nix index 143682f..fe9fc58 100644 --- a/k8s/submodule.nix +++ b/k8s/submodule.nix @@ -9,7 +9,7 @@ in { options = { kubernetes.propagateDefaults = mkOption { - description = "Whehter to propagate child defaults to submodules"; + description = "Whether to propagate child defaults to submodules"; type = types.bool; default = true; }; @@ -25,25 +25,32 @@ in { }; config.config = { - kubernetes.api.defaults.all.metadata.namespace = - mkDefault config.namespace; + kubernetes.api.defaults = [{ + default.metadata.namespace = mkDefault config.namespace; + }]; }; })); }; }; config = { - submodules.defaults = mkMerge [{ - imports = [ kubenix.k8s ]; - kubernetes.version = mkDefault config.kubernetes.version; - kubernetes.api.defaults = - mkIf config.kubernetes.propagateDefaults config.kubernetes.api.defaults; - } ({config, ...}: { - kubernetes.api.defaults.all.metadata.labels = { - "kubenix/module-name" = config.submodule.name; - "kubenix/module-version" = config.submodule.version; - }; - })]; + submodules.defaults = [{ + default = { + imports = [ kubenix.k8s ]; + kubernetes.version = mkDefault config.kubernetes.version; + kubernetes.api.defaults = + mkIf config.kubernetes.propagateDefaults config.kubernetes.api.defaults; + }; + } { + default = ({config, ...}: { + kubernetes.api.defaults = [{ + default.metadata.labels = { + "kubenix/module-name" = config.submodule.name; + "kubenix/module-version" = config.submodule.version; + }; + }]; + }); + }]; kubernetes.objects = mkMerge (mapAttrsToList (_: submodule: submodule.config.kubernetes.objects diff --git a/submodules.nix b/submodules.nix index 8d910d0..46a3025 100644 --- a/submodules.nix +++ b/submodules.nix @@ -5,6 +5,15 @@ with lib; let cfg = config.submodules; + getDefaults = name: tags: + catAttrs "default" (filter (submodule: + (submodule.name == null || submodule.name == name) && + ( + (length submodule.tags == 0) || + (length (intersectLists submodule.tags tags)) > 0 + ) + ) config.submodules.defaults); + submoduleWithSpecialArgs = opts: specialArgs: let opts' = toList opts; @@ -69,9 +78,9 @@ let default = "1.0.0"; }; - passthru = mkOption { - description = "Submodule passthru"; - type = types.coercedTo types.attrs (value: [value]) (types.listOf types.attrs); + tags = mkOption { + description = "List of submodule tags"; + type = types.listOf types.str; default = []; }; }; @@ -114,24 +123,35 @@ in { }; submodules.defaults = mkOption { - description = "Submodule defaults"; - type = types.coercedTo types.unspecified (value: [value]) (types.listOf types.unspecified); - example = literalExample ''{config, ...}: { - kubernetes.version = config.kubernetes.version; - }''; - default = []; - }; + description = "List of defaults to apply to submodule instances"; + type = types.listOf (types.submodule ({config, ...}: { + options = { + name = mkOption { + description = "Name of the submodule to apply defaults to"; + type = types.nullOr types.str; + default = null; + }; - submodules.propagateDefaults = mkOption { - description = "Whether to propagate defaults to submodules"; - type = types.bool; - default = true; + tags = mkOption { + description = "List of tags to apply defaults to"; + type = types.listOf types.str; + default = []; + }; + + default = mkOption { + description = "Default to apply to submodule instance"; + type = types.unspecified; + default = {}; + }; + }; + })); + default = []; }; submodules.propagate = mkOption { description = "Whether to propagate defaults and imports to submodule's submodules"; type = types.bool; - default = true; + default = false; }; submodules.imports = mkOption { @@ -150,6 +170,7 @@ in { options = { module = mkOption { description = "Module defining submodule"; + type = types.unspecified; }; modules = mkOption { @@ -172,12 +193,17 @@ in { submodules.instances = mkOption { description = "Attribute set of submodule instances"; type = types.attrsOf (types.submodule ({name, config, ...}: let + # submodule associated with submodule = findModule { name = config.submodule; version = config.version; }; + # definition of a submodule submoduleDefinition = submodule.definition; + + # submodule defaults + defaults = getDefaults submoduleDefinition.name submoduleDefinition.tags; in { options = { name = mkOption { @@ -201,7 +227,7 @@ in { config = mkOption { description = "Submodule instance ${config.name} for ${submoduleDefinition.name}:${submoduleDefinition.version} config"; type = submoduleWithSpecialArgs ({...}: { - imports = submodule.modules ++ cfg.defaults ++ [submoduleOptions ./submodules.nix]; + imports = submodule.modules ++ defaults ++ [submoduleOptions]; _module.args.name = config.name; }) specialArgs; default = {}; @@ -214,9 +240,14 @@ in { config = { submodules.specialArgs.kubenix = kubenix; - submodules.defaults = mkIf cfg.propagate { - submodules.defaults = cfg.defaults; - submodules.imports = cfg.imports; - }; + submodules.defaults = [(mkIf cfg.propagate { + default = { + imports = [./submodules.nix]; + submodules = { + defaults = cfg.defaults; + imports = cfg.imports; + }; + }; + })]; }; } diff --git a/tests/default.nix b/tests/default.nix index c04577d..e3489c3 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -32,6 +32,7 @@ let ./k8s/1.13/crd.nix ./k8s/submodule.nix ./submodules/simple.nix + ./submodules/defaults.nix ]; testing.defaults = ({kubenix, ...}: { imports = [kubenix.k8s]; diff --git a/tests/submodules/defaults.nix b/tests/submodules/defaults.nix new file mode 100644 index 0000000..cd349bb --- /dev/null +++ b/tests/submodules/defaults.nix @@ -0,0 +1,102 @@ +{ name, config, lib, kubenix, ... }: + +with lib; + +let + instance1 = config.submodules.instances.instance1; + instance2 = config.submodules.instances.instance2; + instance3 = config.submodules.instances.instance3; + instance4 = config.submodules.instances.instance4; + + module = {name, ...}: { + options.args.value = mkOption { + description = "Submodule value"; + type = types.str; + }; + + options.args.defaultValue = mkOption { + description = "Submodule default value"; + type = types.str; + }; + }; +in { + imports = [ + kubenix.submodules + ]; + + test = { + name = "submodules-defatuls"; + description = "Simple k8s submodule test"; + assertions = [{ + message = "instance1 should have value of value1"; + assertion = instance1.config.args.value == "value1"; + } { + message = "instance2 should have value of value2"; + assertion = instance2.config.args.value == "value2"; + } { + message = "instance2 should have value of value2"; + assertion = instance3.config.args.value == "value2"; + } { + message = "instance1 and instance2 should have value of value"; + assertion = + instance1.config.args.defaultValue == "value" && + instance2.config.args.defaultValue == "value"; + } { + message = "instance1 and instance3 should have value of default-value"; + assertion = instance3.config.args.defaultValue == "default-value"; + } { + message = "instance4 should have value of value4"; + assertion = instance4.config.args.value == "value4"; + }]; + }; + + submodules.imports = [{ + modules = [module { + submodule = { + name = "submodule1"; + tags = ["tag1"]; + }; + }]; + } { + modules = [module { + submodule = { + name = "submodule2"; + tags = ["tag2"]; + }; + }]; + } { + modules = [module { + submodule = { + name = "submodule3"; + tags = ["tag2"]; + }; + }]; + } { + modules = [module { + submodule = { + name = "submodule4"; + }; + }]; + }]; + + submodules.defaults = [{ + default.args.defaultValue = mkDefault "value"; + } { + tags = ["tag1"]; + default.args.value = mkDefault "value1"; + } { + tags = ["tag2"]; + default.args.value = mkDefault "value2"; + } { + name = "submodule4"; + default.args.value = mkDefault "value4"; + }]; + + submodules.instances.instance1.submodule = "submodule1"; + submodules.instances.instance2.submodule = "submodule2"; + submodules.instances.instance3 = { + submodule = "submodule3"; + config.args.defaultValue = "default-value"; + }; + submodules.instances.instance4.submodule = "submodule4"; +}