diff --git a/modules/legacy.nix b/modules/legacy.nix index 72a736b..40051c2 100644 --- a/modules/legacy.nix +++ b/modules/legacy.nix @@ -7,6 +7,8 @@ with lib; let parentModule = module; + mkOptionDefault = mkOverride 1001; + mkModuleOptions = moduleDefinition: module: let # gets file where module is defined by looking into moduleDefinitions @@ -35,20 +37,16 @@ let ./legacy.nix (injectModuleAttrs moduleDefinition.module {_file = file;}) { - config.kubernetes.api.defaults = [{ - default.metadata.namespace = mkOptionDefault module.namespace; - }]; + config.kubernetes.namespace = mkOptionDefault module.namespace; + config.kubenix.project = mkOptionDefault config.kubenix.project; } ] ++ config.kubernetes.defaultModuleConfiguration.all ++ (optionals (hasAttr moduleDefinition.name config.kubernetes.defaultModuleConfiguration) config.kubernetes.defaultModuleConfiguration.${moduleDefinition.name}); # prefix kubernetes objects with ${serviceName}, this magic was removed in new kubenix - prefixResources = resources: serviceName: map (resource: resource // { - metadata = resource.metadata // { - name = "${serviceName}-${resource.metadata.name}"; - }; - }) resources; + prefixResources = resources: serviceName: + mapAttrs' (name: resource: nameValuePair "${serviceName}-${name}" resource) resources; defaultModuleConfigurationOptions = mapAttrs (name: moduleDefinition: mkOption { description = "Module default configuration for ${name} module"; @@ -171,13 +169,22 @@ in { resource = type.name; })) config.kubernetes.defaults; - kubernetes.objects = mkMerge ( - mapAttrsToList (name: module: let - moduleDefinition = getModuleDefinition module.module; - in - if moduleDefinition.prefixResources - then prefixResources (module.configuration.kubernetes.objects) module.name - else module.configuration.kubernetes.objects + kubernetes.resources = mkMerge ( + mapAttrsToList (name: module: + mapAttrs' (_: type: let + moduleDefinition = getModuleDefinition module.module; + + moduleResources = module.configuration.kubernetes.api.resources.${type.attrName} or {}; + + moduleConfig = + if moduleDefinition.prefixResources + then prefixResources (moduleToAttrs moduleResources) name + else moduleToAttrs moduleResources; + in nameValuePair type.attrName + (if moduleDefinition.assignAsDefaults + then mkAllDefault moduleConfig 1000 + else moduleConfig) + ) module.configuration.kubernetes.api.types ) config.kubernetes.modules ); diff --git a/tests/default.nix b/tests/default.nix index 92c2776..cf65d59 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -30,7 +30,8 @@ let ./k8s/order.nix ./k8s/submodule.nix ./k8s/imports.nix - ./k8s/legacy.nix + ./legacy/k8s.nix + ./legacy/modules.nix ./helm/simple.nix ./istio/bookinfo.nix ./submodules/simple.nix diff --git a/tests/k8s/legacy.nix b/tests/k8s/legacy.nix deleted file mode 100644 index 1ab4234..0000000 --- a/tests/k8s/legacy.nix +++ /dev/null @@ -1,58 +0,0 @@ -{ config, lib, kubenix, pkgs, k8sVersion, ... }: - -with lib; - -{ - - imports = with kubenix.modules; [ test k8s legacy ]; - - test = { - name = "k8s-legacy"; - description = "Simple test tesing kubenix legacy support"; - assertions = []; - }; - - kubernetes.version = k8sVersion; - - kubernetes.moduleDefinitions.app.module = { config, k8s, ... }: { - options = { - replicas = mkOption { - description = "Number of replicas to run"; - type = types.int; - default = 2; - }; - }; - - config.kubernetes.defaults = { - all = [{ - metadata.labels.default = "value"; - }]; - - deployments = [{ - metadata.labels.default2 = "value2"; - } { - metadata.labels.default3 = "value3"; - }]; - }; - - config.kubernetes.resources.deployments.app = { - spec = { - replicas = config.replicas; - selector = { - matchLabels.app = "app"; - }; - template.spec = { - containers.app = { - image = "hello-world"; - }; - }; - }; - }; - }; - - kubernetes.modules.myapp = { - module = "app"; - namespace = "test"; - configuration.replicas = 3; - }; -} diff --git a/tests/legacy/k8s.nix b/tests/legacy/k8s.nix new file mode 100644 index 0000000..9745a1d --- /dev/null +++ b/tests/legacy/k8s.nix @@ -0,0 +1,57 @@ +{ config, lib, kubenix, pkgs, k8sVersion, ... }: + +with lib; + +let + cfg = config.kubernetes.api.resources.deployments.app; +in { + imports = with kubenix.modules; [ test k8s legacy ]; + + test = { + name = "legacy-k8s"; + description = "Simple test kubenix legacy kubernetes support"; + assertions = [{ + message = "should have correct resource options set"; + assertion = + cfg.kind == "Deployment" && + cfg.metadata.name == "app"; + } { + message = "should have correct defaults set"; + assertion = + cfg.metadata.namespace == "test" && + cfg.metadata.labels.label1 == "value1" && + cfg.metadata.labels.label2 == "value2"; + }]; + }; + + kubernetes.version = k8sVersion; + + kubernetes.resources.deployments.app = { + spec = { + replicas = 2; + selector = { + matchLabels.app = "app"; + }; + template.spec = { + containers.app = { + image = "hello-world"; + }; + }; + }; + }; + + kubernetes.resources.configMaps.app = { + data."my-conf.json" = builtins.toJSON {}; + }; + + kubernetes.defaults = { + all = [{ + metadata.namespace = "test"; + metadata.labels.label1 = "value1"; + }]; + + deployments = [{ + metadata.labels.label2 = "value2"; + }]; + }; +} diff --git a/tests/legacy/modules.nix b/tests/legacy/modules.nix new file mode 100644 index 0000000..06d179b --- /dev/null +++ b/tests/legacy/modules.nix @@ -0,0 +1,108 @@ +{ options, config, lib, kubenix, pkgs, k8sVersion, ... }: + +with lib; + +let + findObject = { kind, name }: filter (object: + object.kind == kind && object.metadata.name == name + ) config.kubernetes.objects; + + getObject = filter: head (findObject filter); + + hasObject = { kind, name }: length (findObject { inherit kind name; }) == 1; +in { + imports = with kubenix.modules; [ test k8s legacy ]; + + test = { + name = "legacy-modules"; + description = "Simple test tesing kubenix legacy modules"; + assertions = [{ + message = "should have all objects"; + assertion = + hasObject {kind = "Deployment"; name = "myapp";} && + hasObject {kind = "Deployment"; name = "myapp2";} && + hasObject {kind = "Deployment"; name = "myapp2-app2";}; + } { + message = "should have default labels set"; + assertion = + (getObject {kind = "Deployment"; name = "myapp2-app2";}) + .metadata.labels.module-label or false == "value" && + (getObject {kind = "Deployment"; name = "myapp2";}) + .metadata.labels.module-label or false == "value"; + } { + message = "should passthru resources to root module"; + assertion = + config.kubernetes.resources.deployments.myapp2-app2-app.metadata.labels.module-label or false == "value"; + }]; + }; + + kubernetes.version = k8sVersion; + + kubernetes.defaults.all.metadata.labels.module-label = "value"; + + # propagate default module configuration and defaults + kubernetes.defaultModuleConfiguration = { + all.kubernetes.defaultModuleConfiguration = mkAliasDefinitions options.kubernetes.defaultModuleConfiguration; + all.kubernetes.defaults = mkAliasDefinitions options.kubernetes.defaults; + }; + + kubernetes.moduleDefinitions.app1.module = { config, k8s, module, ... }: { + config.kubernetes.resources.deployments.app = { + metadata.name = module.name; + spec = { + selector = { + matchLabels.app = "app"; + }; + template.spec = { + containers.app = { + image = "hello-world"; + }; + }; + }; + }; + }; + + kubernetes.moduleDefinitions.app2.module = { name, config, k8s, module, ... }: { + options = { + replicas = mkOption { + description = "Number of replicas to run"; + type = types.int; + default = 2; + }; + }; + + config = { + kubernetes.resources.deployments.app = { + metadata.name = module.name; + spec = { + replicas = config.replicas; + selector = { + matchLabels.app = "app"; + }; + template.spec = { + containers.app = { + image = "hello-world"; + }; + }; + }; + }; + + kubernetes.modules.app2 = { + name = "${name}-app2"; + module = "app1"; + namespace = module.namespace; + }; + }; + }; + + kubernetes.modules.myapp = { + module = "app1"; + namespace = "test"; + }; + + kubernetes.modules.myapp2 = { + module = "app2"; + namespace = "test"; + configuration.replicas = 3; + }; +}