From 473fb3ae509dcb3a4a8d762ee190583b056ec7e8 Mon Sep 17 00:00:00 2001 From: Matej Cotman Date: Tue, 26 Sep 2023 05:04:32 +0300 Subject: [PATCH] feat(k8s): add function for injecting names from hashed data objects (#33) --- CHANGELOG.md | 4 ++++ lib/k8s/default.nix | 17 +++++++++++++++++ modules/k8s.nix | 42 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b10724..9279f54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- add `optionalHashedNames` to inject hashed names for referencing inside modules + ### Changed - removed local `kubectl` and `kubernetes` packages in lieu of those from nixpkgs diff --git a/lib/k8s/default.nix b/lib/k8s/default.nix index 1a65a56..31f879b 100644 --- a/lib/k8s/default.nix +++ b/lib/k8s/default.nix @@ -62,6 +62,23 @@ with lib; rec { } // labels; }; + # Returns "-" + mkNameHash = { name, data, length ? 10 }: + "${name}-${builtins.substring 0 length (builtins.hashString "sha1" (builtins.toJSON data))}"; + + # Returns the same resources with addition of injected (or overwritten) metadata.name with hashed data + # name of the resource in Nix does not change for reference reasons + # useful for the ConfigMap and Secret resources + injectHashedNames = attrs: + lib.mapAttrs + (name: o: + recursiveUpdate o { + metadata.name = mkNameHash { inherit name; data = o.data; }; + } + ) + attrs; + + inherit (lib) toBase64; inherit (lib) octalToDecimal; } diff --git a/modules/k8s.nix b/modules/k8s.nix index f26677f..601ed2e 100644 --- a/modules/k8s.nix +++ b/modules/k8s.nix @@ -257,6 +257,39 @@ with lib; let (types.listOf (types.submodule submodule)) (mergeValuesByFn keyFn) (types.attrsOf (types.submodule submodule)); + + # inject hashed names for referencing inside modules, example: + # pod = { + # containers.nginx = { + # image = "nginx:1.25.1"; + # volumeMounts = { + # "/etc/nginx".name = "config"; + # "/var/lib/html".name = "static"; + # }; + # }; + # volumes = { + # config.configMap.name = config.kubernetes.resources.configMaps.nginx-config.metadata.name; + # static.configMap.name = config.kubernetes.resources.configMaps.nginx-static.metadata.name; + # }; + # }; + optionalHashedNames = object: + if cfg.enableHashedNames then + recursiveUpdate object + (mapAttrs + (ks: v: + if builtins.elem ks [ "configMaps" "secrets" ] then + k8s.injectHashedNames v + else + v + ) + object) + else object; + + # inject hashed names in the output + optionalHashedNames' = object: kind: + if cfg.enableHashedNames && elem kind [ "ConfigMap" "Secret" ] then + k8s.injectHashedNames object + else object; in { imports = [ ./base.nix ]; @@ -319,6 +352,7 @@ in description = "Alias for `config.kubernetes.api.resources` options"; default = { }; type = types.attrsOf types.attrs; + apply = optionalHashedNames; }; customTypes = mkOption { @@ -411,6 +445,12 @@ in description = "Genrated kubernetes YAML file"; type = types.package; }; + + enableHashedNames = mkOption { + description = "Enable hashing of resource (ConfigMap,Secret) names"; + type = types.bool; + default = false; + }; }; config = { @@ -497,7 +537,7 @@ in kubernetes.objects = flatten (mapAttrsToList (_: type: mapAttrsToList (_name: moduleToAttrs) - cfg.api.resources.${type.group}.${type.version}.${type.kind} + (optionalHashedNames' cfg.api.resources.${type.group}.${type.version}.${type.kind} type.kind) ) cfg.api.types);