move past legacy compat

This commit is contained in:
David Arnold 2021-05-13 19:45:26 -04:00
parent d1ad09a897
commit 70d249aaff
No known key found for this signature in database
GPG key ID: 6D6A936E69C59D08
6 changed files with 1 additions and 507 deletions

View file

@ -7,6 +7,5 @@
docker = ./docker.nix; docker = ./docker.nix;
testing = ./testing; testing = ./testing;
test = ./testing/test-options.nix; test = ./testing/test-options.nix;
module = ./module.nix; base = ./base.nix;
legacy = ./legacy.nix;
} }

View file

@ -1,230 +0,0 @@
# support for legacy kubenix
{ options, config, pkgs, lib, kubenix, ... }:
with lib;
let
parentModule = module;
globalConfig = config;
mkOptionDefault = mkOverride 1001;
mkModuleOptions = moduleDefinition: module:
let
# gets file where module is defined by looking into moduleDefinitions
# option.
file =
elemAt options.kubernetes.moduleDefinitions.files (
(findFirst (i: i > 0) 0
(imap
(i: def: if hasAttr module.module def then i else 0)
options.kubernetes.moduleDefinitions.definitions
)
) - 1
);
injectModuleAttrs = module: attrs: (
if isFunction module then args: (applyIfFunction file module args) // attrs
else if isAttrs mkOptionDefault.module then module // attrs
else module
);
in
[
{
_module.args.name = module.name;
_module.args.module = module;
}
./k8s.nix
./legacy.nix
(injectModuleAttrs moduleDefinition.module { _file = file; })
{
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:
mapAttrs' (name: resource: nameValuePair "${serviceName}-${name}" resource) resources;
# TODO: rewrite using mkOptionType
defaultModuleConfigurationOptions = mapAttrs
(name: moduleDefinition: mkOption {
description = "Module default configuration for ${name} module";
type = types.coercedTo types.unspecified (value: [ value ]) (types.listOf types.unspecified);
default = [ ];
apply = filter (v: v != [ ]);
})
config.kubernetes.moduleDefinitions;
getModuleDefinition = name:
if hasAttr name config.kubernetes.moduleDefinitions
then config.kubernetes.moduleDefinitions.${name}
else throw ''requested kubernetes moduleDefinition with name "${name}" does not exist'';
in
{
imports = [ ./k8s.nix ];
options.kubernetes.moduleDefinitions = mkOption {
description = "Legacy kubenix attribute set of module definitions";
default = { };
type = types.attrsOf (types.submodule ({ name, ... }: {
options = {
name = mkOption {
description = "Module definition name";
type = types.str;
default = name;
};
prefixResources = mkOption {
description = "Whether resources should be automatically prefixed with module name";
type = types.bool;
default = true;
};
assignAsDefaults = mkOption {
description = "Whether to assign resources as defaults, this is usefull for module that add some functionality";
type = types.bool;
default = false;
};
module = mkOption {
description = "Module definition";
};
};
}));
};
options.kubernetes.defaultModuleConfiguration = mkOption {
description = "Legacy kubenix module default options";
type = types.submodule {
options = defaultModuleConfigurationOptions // {
all = mkOption {
description = "Module default configuration for all modules";
type = types.coercedTo types.unspecified (value: [ value ]) (types.listOf types.unspecified);
default = [ ];
apply = filter (v: v != [ ]);
};
};
};
default = { };
};
options.kubernetes.modules = mkOption {
description = "Legacy kubenix attribute set of modules";
default = { };
type = types.attrsOf (types.submodule ({ config, name, ... }: {
options = {
name = mkOption {
description = "Module name";
type = types.str;
default = name;
};
namespace = mkOption {
description = "Namespace where to deploy module";
type = types.str;
default = globalConfig.kubernetes.namespace;
};
labels = mkOption {
description = "Attribute set of module lables";
type = types.attrsOf types.str;
default = { };
};
configuration = mkOption {
description = "Module configuration";
type = submoduleWithSpecialArgs
{
imports = mkModuleOptions (getModuleDefinition config.module) config;
}
{
inherit kubenix;
};
default = { };
};
module = mkOption {
description = "Name of the module to use";
type = types.str;
default = config.name;
};
};
}));
};
options.kubernetes.defaults = mkOption {
type = types.attrsOf (types.coercedTo types.attrs (value: [ value ]) (types.listOf types.attrs));
description = "Legacy kubenix kubernetes defaults.";
default = { };
};
# for back compatibility with kubernetes.customResources
options.kubernetes.customResources = options.kubernetes.resources;
config = {
kubernetes = mkMerge [{
api.defaults = mapAttrsToList
(attrName: default:
let
type = head (mapAttrsToList (_: v: v) (filterAttrs (_: type: type.attrName == attrName) config.kubernetes.api.types));
in
{
default = { imports = default; };
} // (if (attrName == "all") then { } else {
resource = type.name;
}))
config.kubernetes.defaults;
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 && type.kind != "CustomResourceDefinition"
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
);
# custom types created from customResourceDefinitions
customTypes =
mapAttrsToList
(name: crd: {
group = crd.spec.group;
version = crd.spec.version;
kind = crd.spec.names.kind;
name = crd.spec.names.plural;
attrName = mkOptionDefault name;
})
(config.kubernetes.resources.customResourceDefinitions or { });
defaultModuleConfiguration.all = {
_file = head options.kubernetes.defaultModuleConfiguration.files;
config.kubernetes.version = mkDefault config.kubernetes.version;
config.kubernetes.moduleDefinitions = config.kubernetes.moduleDefinitions;
};
}
{
resources = mkAliasDefinitions options.kubernetes.customResources;
}];
};
}

View file

@ -31,9 +31,6 @@ let
./k8s/order.nix ./k8s/order.nix
./k8s/submodule.nix ./k8s/submodule.nix
./k8s/imports.nix ./k8s/imports.nix
#./legacy/k8s.nix
#./legacy/crd.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

View file

@ -1,108 +0,0 @@
{ options, config, lib, kubenix, pkgs, ... }:
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-crd";
description = "Simple test tesing kubenix legacy integration with crds crd";
enable = builtins.compareVersions config.kubernetes.version "1.15" <= 0;
assertions = [{
message = "should define crd in module";
assertion =
hasObject { kind = "SecretClaim"; name = "module-claim"; };
}
{
message = "should define crd in root";
assertion =
hasObject { kind = "SecretClaim"; name = "root-claim"; };
}];
};
kubernetes.namespace = "test";
kubernetes.moduleDefinitions.secret-claim.module = { config, k8s, module, ... }: {
options = {
name = mkOption {
description = "Name of the secret claim";
type = types.str;
default = module.name;
};
type = mkOption {
description = "Type of the secret";
type = types.enum [ "Opaque" "kubernetes.io/tls" ];
default = "Opaque";
};
path = mkOption {
description = "Secret path";
type = types.str;
};
renew = mkOption {
description = "Renew time in seconds";
type = types.nullOr types.int;
default = null;
};
data = mkOption {
type = types.nullOr types.attrs;
description = "Data to pass to get secrets";
default = null;
};
};
config = {
kubernetes.resources.customResourceDefinitions.secret-claims = {
kind = "CustomResourceDefinition";
apiVersion = "apiextensions.k8s.io/v1beta1";
metadata.name = "secretclaims.vaultproject.io";
spec = {
group = "vaultproject.io";
version = "v1";
scope = "Namespaced";
names = {
plural = "secretclaims";
kind = "SecretClaim";
shortNames = [ "scl" ];
};
};
};
kubernetes.customResources.secret-claims.claim = {
metadata.name = config.name;
spec = {
inherit (config) type path;
} // (optionalAttrs (config.renew != null) {
inherit (config) renew;
}) // (optionalAttrs (config.data != null) {
inherit (config) data;
});
};
};
};
kubernetes.modules.module-claim = {
module = "secret-claim";
configuration.path = "tokens/test";
};
kubernetes.customResources.secret-claims.root-claim = {
spec = {
path = "secrets/test2";
};
};
}

View file

@ -1,56 +0,0 @@
{ config, lib, kubenix, pkgs, ... }:
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.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";
}];
};
}

View file

@ -1,108 +0,0 @@
{ options, config, lib, kubenix, pkgs, ... }:
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.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;
};
}