Use of variables in Terraform test experimental feature

I am trying out the new Terraform test feature in 0.15. My particular use case is writing modules that can be used by many different users in my company and being able to provide evidence that the module does what it claims to do. In order to do this effectively I need to be able to inject a region variable into the AWS provider block I use, ideally this would be through the cli (-var=) or a tfvars file (preferably the same handling of variables we get in our normal Terraform configuration). Is this something that could be added to the backlog ?
Something like this?
terraform test -var=“region=eu-west-1”

I don’t think this should replace the use of locals in the tests but for me allowing people to run the tests in different regions is important.

Hi @fergoid,

The intended design for this testing is that you encode the variable values you want to test into the test configuration directly, rather than specifying them on the command line, so that everyone who runs the test is testing the same thing. To test in multiple regions I think I would either write multiple test cases that each select a different region or write a single case that includes more than one provider configuration and separate instances of the module. The second case might look something like this:

provider "aws" {
  alias = "eu-west-1"

  region = "eu-west-1"
}

provider "aws" {
  alias = "us-west-2"

  region = "us-west-2"
}

module "eu-west-1" {
  source = "../.."

  providers = {
    aws = aws.eu-west-1
  }
}

module "us-west-2" {
  source = "../.."

  providers = {
    aws = aws.us-west-2
  }
}

Then running terraform test would test the module in both regions at once.

With that said, in this particular case the AWS provider does respond to the typical AWS environment variable AWS_DEFAULT_REGION as a fallback for explicit configuration, so if you don’t want to explicitly encode all of your different test scenarios as I showed above then an alternative would be to leave the provider unconfigured in the module and then use environment variables to configure it:

AWS_DEFAULT_REGION="eu-west-1" terraform test

In most cases I would recommend using environment variables (or other similar “ambient” methods such as the configuration/credentials files) only for settings related to who or what is running the test, and not for settings related to what is being tested, but the distinction between those two things is different in different situations depending on the design of the system being tested, and so what makes sense to be fixed as part of the test vs. dynamic based on the test execution environment will not always be the same answer.

1 Like

Thanks for the response. Will give the AWS environment variable a go.

Hi @apparentlymart ,

congrats on the testing feature! It’s very neat.

On the variables topic, I’d need to inject an API key (which is a secret), but don’t want to hardcode it in a configuration file.

I can’t make use of the TF_VAR_name variables, though. How can I achieve that?

Hi @alborworld,

The current design assumes that the only credentials needed by tests are provider credentials and that the provider always supports setting credentials in some way outside of the configuration, such as in environment variables or in credentials files.

The input variables for a test case are fixed to be whatever is written in the test scenario, so that the tests are self-contained aside from the provider configurations. (Shared modules typically don’t include their own provider configurations, so this design compromise is reflecting that a typical module doesn’t usually know anything about how its providers are configured anyway.)

If the credentials you need to provide are for a provider then I suggest referring to the provider’s documentation to see how it expects to receive credentials outside of the configuration.

If you are providing credentials for something other than a provider, or for a provider that doesn’t support seeing credentials in the usual ways, then the current design of terraform test will unfortunately not work for your situation, and you will instead need to init, apply, and then destroy your test configurations manually using the normal Terraform workflow commands. (That is in essence what terraform test is doing anyway, but with hard-coded planning options that don’t set any input variables.)