terranix
terranix copied to clipboard
Use Terraform attributes
Currently there appears to be no way to use attributes of a terraform resource or data source from terranix. For sophisticated setups, e.g. for setting up an integrated AWS S3 and CloudFront with an OAI, this is essential.
I propose the following and am willing to make a PR if the maintainer approves in principle:
[ ] * Add layers of submodule structure to the data
and resource
option, so that they always exist with a resource/data-source type and identifier. The submodule would include as a config
underneath the identifier attribute a function which takes an attribute name, strips away config.resource
or config.data
, and the resource type from the Nix module path, and writes a Terraform string interpolation.
Thus it becomes possible to write e.g.
with config; resource."aws_s3_bucket"."my_s3_bucket".attribute "arn"
and receive the string output from Nix "${my_s3_bucket.arn}"
(note that we are escaping Nix's string interpolation because we want the "${...}"
form to appear in the JSON output for consumption by Terraform.)
This could be extended to easily support input/output/local variables once a proof-of-concept was evaluated.
Very good idea. Feel free to create a pull request, I'm happy to merge it. I had similar ideas when I initialized the terranix project, but I couldn't come up with a proper solution.
@eamsden may you proved config.nix with what you are trying to achieve?
I believe one may do in terranix all one can do in terraform.
But he will use strings, instead of referencing attr sets via atrribute names. So errors will not be detected by nix evaluator/instantiate, but by terraform validate
.
What can be improved if package during build will run check
with validate.
if this item about making lazy attr sets which allow to refer attributes via nix, not via strings, then it would be great.
just applied this well
{ config, lib, options, specialArgs }:
let var = options.variable;
in rec {
variable = {
PROJECT = {
type = "string";
description = "Google Cloud Project ID";
};
IMAGE_FILE = {
type = "string";
description = "NixOS image file for Google Cloud";
};
};
resource = {
local_file.test_import = {
filename = "test_import.txt";
content = "Hello";
};
google_service_account = {
default = {
account_id = "\${ var.PROJECT }-account";
project = "\${ var.PROJECT }";
};
};
time_sleep = {
google_service_account-default = {
depends_on = [ "resource.google_service_account.default" ];
create_duration = "30s";
};
};
google_compute_address = { static = { name = "ipv4-address"; }; };
google_storage_bucket = {
gce-image = {
name = "\${var.PROJECT}-gce-image";
location = "US";
force_destroy = true;
};
};
google_compute_image = {
gce-image = {
name = "gce-image";
raw_disk = {
source = "\${resource.google_storage_bucket_object.gce-image-gz.self_link}";
};
};
};
google_storage_bucket_object = {
gce-image-gz = {
name = "\${var.PROJECT}-image.tar.gz";
source = "\${var.IMAGE_FILE}";
bucket = "\${resource.google_storage_bucket.gce-image.name}";
};
};
};
provider = {
google = {
region = "us-central1";
zone = "us-central1-c";
project = "\${ var.PROJECT }";
};
};
}
gce = nixos-generators.nixosGenerate {
system = "x86_64-linux";
modules = [ ./modules/gce.nix ];
format = "gce";
};
apply = pkgs.writeShellApplication {
name = "apply";
text = ''
TF_VAR_IMAGE_FILE="$(find ${self.packages.x86_64-linux.gce} -type f)"
TF_VAR_PROJECT="composablefi"
export TF_VAR_IMAGE_FILE
export TF_VAR_PROJECT
cd terraform/layers/05
if [[ -e config.tf.json ]]; then rm -f config.tf.json; fi
cp ${self.packages.${system}.tfconfig} config.tf.json \
&& ${pkgs.terraform}/bin/terraform init \
&& ${pkgs.terraform}/bin/terraform apply -auto-approve
'';
};
see that bucket = "\${resource.google_storage_bucket.gce-image.name}";
is well working reference
I would prefer that somehow (sure, I do not know magic, yet), I can type like:
bucket = state.resource.google_storage_bucket.gce-image.name;
may be it could read the nix of module, and provide recursive state with all attributes if finds.
and during module evaluation (when tf json is generated), it may somehow detect such attr set references, and replace with stings.
Initial implementation (one that uses config.<attr>
as a function) has been merged in #59. The state.
attribute seems a bit harder to do, I'll consider it in the future :)