{ pkgs, lib, shb, ... }: let pkgs' = pkgs; 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 = shb.withReplacements userConfig; nonSecretConfigFile = pkgs.writeText "config.yaml.template" ( lib.generators.toJSON { } configWithTemplates ); replacements = shb.getReplacements userConfig; replaceInTemplate = shb.replaceSecretsScript { file = nonSecretConfigFile; resultPath = "/var/lib/config.yaml"; inherit replacements; }; replaceInTemplateJSON = shb.replaceSecrets { inherit userConfig; resultPath = "/var/lib/config.json"; generator = shb.replaceSecretsFormatAdapter (pkgs.formats.json { }); }; replaceInTemplateJSONGen = shb.replaceSecrets { inherit userConfig; resultPath = "/var/lib/config_gen.json"; generator = shb.replaceSecretsGeneratorAdapter (lib.generators.toJSON { }); }; replaceInTemplateXML = shb.replaceSecrets { inherit userConfig; resultPath = "/var/lib/config.xml"; generator = shb.replaceSecretsFormatAdapter (shb.formatXML { enclosingRoot = "Root"; }); }; in shb.test.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 lib.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)) ''; }; }