{ pkgs, lib, ... }: let pkgs' = pkgs; 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; }; replaceInTemplateJSON = shblib.replaceSecrets { inherit userConfig; 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";}); }; in pkgs.testers.runNixOSTest { name = "lib-template"; nodes.machine = { config, pkgs, ... }: { imports = [ (pkgs'.path + "/nixos/modules/profiles/headless.nix") (pkgs'.path + "/nixos/modules/profiles/qemu-guest.nix") { options = { libtest.config = lib.mkOption { type = lib.types.attrsOf (lib.types.oneOf [ lib.types.str shblib.secretFileType ]); }; }; } ]; system.activationScripts = { libtest = replaceInTemplate; libtestJSON = replaceInTemplateJSON; libtestJSONGen = replaceInTemplateJSONGen; libtestXML = replaceInTemplateXML; }; }; testScript = { nodes, ... }: '' import json from collections import ChainMap from xml.etree import ElementTree start_all() 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)} wantedConfig = json.loads('${lib.generators.toJSON {} wantedConfig}') 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}")) gotConfig = machine.succeed("cat /var/lib/config.xml") print(gotConfig) gotConfig = xml_to_dict_recursive(ElementTree.XML(gotConfig))['Root'] if wantedConfig != gotConfig: raise Exception("\nwantedConfig: {}\n!= gotConfig: {}".format(wantedConfig, gotConfig)) ''; }; }