{ pkgs, lib, inputs ? null, ... }: rec { mapKeys = keyMapper: lib.mapAttrs' ( k: value: { name = keyMapper k; inherit value; } ); evalModel = module: (lib.evalModules { specialArgs = { inherit pkgs inputs; modulesPath = "${builtins.toString pkgs.path}/nixos/modules"; }; modules = [ ./data-model.nix module ]; }).config; evalOption = name: opts: conf: (lib.evalModules { modules = [ { options = { "${name}" = opts; }; config."${name}" = conf; } ]; }).config."${name}"; toBash = v: lib.replaceStrings [ "\"" ] [ "\\\"" ] ( if lib.isPath v || builtins.isNull v then toString v else if lib.isString v then v else lib.strings.toJSON v ); withPackages = packages: { makeWrapperArgs = [ "--prefix" "PATH" ":" "${lib.makeBinPath packages}" ]; }; filterNull = lib.filterAttrs (_: v: v != null); withEnv = environment: toString (lib.mapAttrsToList (k: v: "${k}=\"${toBash v}\"") environment); withSecrets = environment: toString (lib.mapAttrsToList (k: v: "${k}=\"$(cat ${v})\"") (filterNull environment)); tfApply = { directory, httpBackend, dependentDirs ? [ ], environment ? { }, # limit OOM risk parallelism ? 1, }: let env-vars = '' ${withEnv (mapKeys (k: "TF_VAR_${k}") (filterNull environment))} \ ${withEnv (filterNull httpBackend.value)} \ ''; tfPackage = pkgs.callPackage ./run/${directory}/tf.nix { }; tf-env = pkgs.callPackage ./run/tf-env.nix { inherit httpBackend tfPackage; tfDirs = lib.lists.map (dir: "deployment/run/${dir}") ([ directory ] ++ dependentDirs); }; in pkgs.writers.writeBashBin "tf-apply.sh" (withPackages [ tfPackage pkgs.jq ]) '' set -e dir="${tf-env}/deployment/run/${directory}" env ${env-vars} tofu -chdir="$dir" apply --auto-approve -parallelism=${builtins.toString parallelism} >&2 env ${env-vars} tofu -chdir="$dir" output -json ''; }