Skip to content

Commit

Permalink
feat: basic lib for terraform configs
Browse files Browse the repository at this point in the history
  • Loading branch information
justinrubek committed Nov 30, 2022
1 parent 2a47b3d commit 7d955dc
Show file tree
Hide file tree
Showing 4 changed files with 324 additions and 0 deletions.
29 changes: 29 additions & 0 deletions custom-outputs.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
config,
lib,
flake-parts-lib,
...
}: let
inherit
(lib)
mkOption
types
;
inherit
(flake-parts-lib)
mkTransposedPerSystemModule
;
in
mkTransposedPerSystemModule {
name = "terraformConfigurationPackages";
option = mkOption {
type = types.lazyAttrsOf types.package;
default = {};
description = ''
An attribute set of Terraform configuration packages.
The contents will be valid terraform HCL/JSON files containing the terraform configuration merged with the terranix configuration.
'';
};
# this refers to the current file
file = ./custom-outputs.nix;
}
178 changes: 178 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
inputs = {
nixpkgs.url = "nixpkgs/nixos-unstable";
flake-parts.url = "github:hercules-ci/flake-parts";
terranix.url = "github:terranix/terranix";
};

outputs = {
self,
flake-utils,
flake-parts,
...
}:
flake-parts.lib.mkFlake {inherit self;} {
systems = ["x86_64-linux" "aarch64-linux"];
imports = [
./lib.nix
];

flake.customOutputModule = ./custom-outputs.nix;
};
}
95 changes: 95 additions & 0 deletions lib.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
{
inputs,
self,
lib,
...
}: {
imports = [
./custom-outputs.nix
];

flake.lib = rec {
# call into terranix to build a configuration, loading all `.nix` files in the directory as modules
mkTerranixConfiguration = {
path,
system,
}: let
filterFileName = name: lib.strings.hasSuffix ".nix" name;

# filter out all directories and files that are not .nix files
directoryContents = builtins.readDir path;
filesOnly = lib.attrsets.filterAttrs (x: y: y == "regular") directoryContents;
nixFiles = builtins.attrNames (lib.attrsets.filterAttrs (x: y: filterFileName x) filesOnly);

modules = map (x: "${path}/${x}") nixFiles;
in
inputs.terranix.lib.terranixConfiguration {
inherit system modules;
# support manually specifying null values. without this terranix will remove keys with a null value
# strip_nulls = true;
};

# find all `.tf` and `.tf.json` files in the directory and create a list of paths to them
# includes all subdirectories so they can be used as terraform modules
mkTerraformConfiguration = {path}: let
# filter out all directories and files that are not .tf or .tf.json files
directoryContents = builtins.readDir path;
filesOnly = lib.attrsets.filterAttrs (x: y: y == "regular") directoryContents;
filterFileName = name: lib.strings.hasSuffix ".tf" name || lib.strings.hasSuffix ".tf.json" name;
tfFiles = builtins.attrNames (lib.attrsets.filterAttrs (x: y: filterFileName x) filesOnly);

includedFiles = map (x: "${path}/${x}") tfFiles;
subdirectories = builtins.attrNames (lib.attrsets.filterAttrs (x: y: y == "directory") directoryContents);
includedDirectories = map (x: "${path}/${x}") subdirectories;
in (includedFiles ++ includedDirectories);

# combine the terranix and terraform configurations into a single derivation containing all of the files
# intended for the final build output for terraform.
# the output is devoid of any nix-specific code
# bundles the generated terranix configurations with existing `.tf` and `.tf.json` files from their configuration directory
mkTerraformConfigurationPackage = {
name,
path,
pkgs,
system,
}: let
generatedConfig = self.lib.mkTerranixConfiguration {inherit path system;};
providedConfig = self.lib.mkTerraformConfiguration {inherit path;};
in
pkgs.runCommandNoCC "terraform-config-${name}" {} ''
mkdir -p $out
# copy the provided (terraform) configuration files
${lib.strings.concatStringsSep "\n" (map (x: "cp -r ${x} $out") providedConfig)}
# copy the generated (terranix) configuration file
cp ${generatedConfig} $out/config.tf.json
'';

# helper to create and bundle multiple configurations
buildTerraformConfigurations = {
configDir,
configNames,
system,
pkgs,
}: let
# reducer should provide an output containing the configurations keyed by name
reducer = l: r: let
path = "${configDir}/${r}";
configuration = self.lib.mkTerraformConfigurationPackage {
name = r;
inherit path pkgs system;
};
in
{
"${r}" = configuration;
}
// l;
in
builtins.foldl' reducer {} configNames;

determineSubdirNames = {path}: let
directoryContents = builtins.readDir path;
subdirectories = builtins.attrNames (lib.attrsets.filterAttrs (x: y: y == "directory") directoryContents);
in
subdirectories;
};
}

0 comments on commit 7d955dc

Please sign in to comment.