2024-03-01 00:34:53 +01:00
|
|
|
{ pkgs, lib, ... }:
|
|
|
|
let
|
2024-03-20 06:50:41 +01:00
|
|
|
pkgs' = pkgs;
|
|
|
|
|
2024-03-01 00:34:53 +01:00
|
|
|
shblib = pkgs.callPackage ../../lib {};
|
|
|
|
in
|
|
|
|
{
|
|
|
|
template =
|
|
|
|
let
|
|
|
|
aSecret = pkgs.writeText "a-secret.txt" "Secret of A";
|
|
|
|
bSecret = pkgs.writeText "b-secret.txt" "Secret of B";
|
|
|
|
userConfig = {
|
|
|
|
a.a.source = aSecret;
|
|
|
|
b.source = bSecret;
|
|
|
|
b.transform = v: "prefix-${v}-suffix";
|
|
|
|
c = "not secret C";
|
|
|
|
d.d = "not secret D";
|
|
|
|
};
|
|
|
|
|
|
|
|
wantedConfig = {
|
|
|
|
a.a = "Secret of A";
|
|
|
|
b = "prefix-Secret of B-suffix";
|
|
|
|
c = "not secret C";
|
|
|
|
d.d = "not secret D";
|
|
|
|
};
|
|
|
|
|
|
|
|
configWithTemplates = shblib.withReplacements userConfig;
|
|
|
|
|
|
|
|
nonSecretConfigFile = pkgs.writeText "config.yaml.template" (lib.generators.toJSON {} configWithTemplates);
|
|
|
|
|
|
|
|
replacements = shblib.getReplacements userConfig;
|
|
|
|
|
|
|
|
replaceInTemplate = shblib.replaceSecretsScript {
|
|
|
|
file = nonSecretConfigFile;
|
|
|
|
resultPath = "/var/lib/config.yaml";
|
|
|
|
inherit replacements;
|
|
|
|
};
|
|
|
|
|
2024-05-23 23:28:08 +02:00
|
|
|
replaceInTemplateJSON = shblib.replaceSecrets {
|
2024-03-01 00:34:53 +01:00
|
|
|
inherit userConfig;
|
2024-05-23 23:28:08 +02:00
|
|
|
resultPath = "/var/lib/config.json";
|
|
|
|
generator = shblib.replaceSecretsFormatAdapter (pkgs.formats.json {});
|
|
|
|
};
|
|
|
|
|
|
|
|
replaceInTemplateJSONGen = shblib.replaceSecrets {
|
|
|
|
inherit userConfig;
|
|
|
|
resultPath = "/var/lib/config_gen.json";
|
|
|
|
generator = shblib.replaceSecretsGeneratorAdapter (lib.generators.toJSON {});
|
|
|
|
};
|
|
|
|
|
|
|
|
replaceInTemplateXML = shblib.replaceSecrets {
|
|
|
|
inherit userConfig;
|
|
|
|
resultPath = "/var/lib/config.xml";
|
|
|
|
generator = shblib.replaceSecretsFormatAdapter (shblib.formatXML {enclosingRoot = "Root";});
|
2024-03-01 00:34:53 +01:00
|
|
|
};
|
|
|
|
in
|
2024-03-20 06:50:41 +01:00
|
|
|
pkgs.testers.runNixOSTest {
|
2024-03-01 00:34:53 +01:00
|
|
|
name = "lib-template";
|
|
|
|
nodes.machine = { config, pkgs, ... }:
|
|
|
|
{
|
|
|
|
imports = [
|
2024-03-20 06:50:41 +01:00
|
|
|
(pkgs'.path + "/nixos/modules/profiles/headless.nix")
|
|
|
|
(pkgs'.path + "/nixos/modules/profiles/qemu-guest.nix")
|
2024-03-01 00:34:53 +01:00
|
|
|
{
|
|
|
|
options = {
|
|
|
|
libtest.config = lib.mkOption {
|
|
|
|
type = lib.types.attrsOf (lib.types.oneOf [ lib.types.str shblib.secretFileType ]);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
];
|
|
|
|
|
|
|
|
system.activationScripts = {
|
|
|
|
libtest = replaceInTemplate;
|
2024-05-23 23:28:08 +02:00
|
|
|
libtestJSON = replaceInTemplateJSON;
|
|
|
|
libtestJSONGen = replaceInTemplateJSONGen;
|
|
|
|
libtestXML = replaceInTemplateXML;
|
2024-03-01 00:34:53 +01:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
testScript = { nodes, ... }: ''
|
|
|
|
import json
|
2024-05-23 23:28:08 +02:00
|
|
|
from collections import ChainMap
|
|
|
|
from xml.etree import ElementTree
|
|
|
|
|
2024-03-01 00:34:53 +01:00
|
|
|
start_all()
|
2024-05-23 23:28:08 +02:00
|
|
|
machine.wait_for_file("/var/lib/config.yaml")
|
|
|
|
machine.wait_for_file("/var/lib/config.json")
|
|
|
|
machine.wait_for_file("/var/lib/config_gen.json")
|
|
|
|
machine.wait_for_file("/var/lib/config.xml")
|
|
|
|
|
|
|
|
def xml_to_dict_recursive(root):
|
|
|
|
all_descendants = list(root)
|
|
|
|
if len(all_descendants) == 0:
|
|
|
|
return {root.tag: root.text}
|
|
|
|
else:
|
|
|
|
merged_dict = ChainMap(*map(xml_to_dict_recursive, all_descendants))
|
|
|
|
return {root.tag: dict(merged_dict)}
|
2024-03-01 00:34:53 +01:00
|
|
|
|
|
|
|
wantedConfig = json.loads('${lib.generators.toJSON {} wantedConfig}')
|
|
|
|
|
2024-05-23 23:28:08 +02:00
|
|
|
with subtest("config"):
|
|
|
|
print(machine.succeed("cat ${pkgs.writeText "replaceInTemplate" replaceInTemplate}"))
|
|
|
|
|
|
|
|
gotConfig = machine.succeed("cat /var/lib/config.yaml")
|
|
|
|
print(gotConfig)
|
|
|
|
gotConfig = json.loads(gotConfig)
|
|
|
|
|
|
|
|
if wantedConfig != gotConfig:
|
|
|
|
raise Exception("\nwantedConfig: {}\n!= gotConfig: {}".format(wantedConfig, gotConfig))
|
|
|
|
|
|
|
|
with subtest("config JSON Gen"):
|
|
|
|
print(machine.succeed("cat ${pkgs.writeText "replaceInTemplateJSONGen" replaceInTemplateJSONGen}"))
|
|
|
|
|
|
|
|
gotConfig = machine.succeed("cat /var/lib/config_gen.json")
|
|
|
|
print(gotConfig)
|
|
|
|
gotConfig = json.loads(gotConfig)
|
|
|
|
|
|
|
|
if wantedConfig != gotConfig:
|
|
|
|
raise Exception("\nwantedConfig: {}\n!= gotConfig: {}".format(wantedConfig, gotConfig))
|
|
|
|
|
|
|
|
with subtest("config JSON"):
|
|
|
|
print(machine.succeed("cat ${pkgs.writeText "replaceInTemplateJSON" replaceInTemplateJSON}"))
|
|
|
|
|
|
|
|
gotConfig = machine.succeed("cat /var/lib/config.json")
|
|
|
|
print(gotConfig)
|
|
|
|
gotConfig = json.loads(gotConfig)
|
|
|
|
|
|
|
|
if wantedConfig != gotConfig:
|
|
|
|
raise Exception("\nwantedConfig: {}\n!= gotConfig: {}".format(wantedConfig, gotConfig))
|
|
|
|
|
|
|
|
with subtest("config XML"):
|
|
|
|
print(machine.succeed("cat ${pkgs.writeText "replaceInTemplateXML" replaceInTemplateXML}"))
|
2024-03-01 00:34:53 +01:00
|
|
|
|
2024-05-23 23:28:08 +02:00
|
|
|
gotConfig = machine.succeed("cat /var/lib/config.xml")
|
|
|
|
print(gotConfig)
|
|
|
|
gotConfig = xml_to_dict_recursive(ElementTree.XML(gotConfig))['Root']
|
2024-03-01 00:34:53 +01:00
|
|
|
|
2024-05-23 23:28:08 +02:00
|
|
|
if wantedConfig != gotConfig:
|
|
|
|
raise Exception("\nwantedConfig: {}\n!= gotConfig: {}".format(wantedConfig, gotConfig))
|
2024-03-01 00:34:53 +01:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
}
|