How to refrence a dependancies variable description in terraform? - terraform

When writing terraform modules, one is commonly writing pass through variables/inputs for dependent objects.
How can I write the variable so that the description/type just references the dependent description?
I imagine something like
variable "foo" {
type = dependant.resource.foo.var.type
description = dependant.resource.foo.var.description
default = "module default"
}

Variable descriptions are metadata used by Terraform itself (specifically: by documentation mechanisms like Terraform Registry) and are not data visible to your module code.
Each module's input variables and output values must be entirely self-contained. Mechanisms like the Terraform Registry rely on this so that they are able to generate the documentation for a module only by reference to that module, without any need to fetch and analyze any other modules or other dependencies.
If you do intend to have a variable just "pass through" to a child module or to a resource configuration then you will need to redeclare its type and description in your module.
I would also suggest considering the advice in the documentation section When to write a module; directly passing through a variable to a child object isn't necessarily a wrong thing to do, but it can result from a module not raising the level of abstraction and therefore not passing the test described there.
In such cases, it can be better to use module composition instead of nested modules.
In this case would mean that the caller of your module would themselves call the other module you are currently wrapping. Instead of your module taking that other module's input variables as its own, it would be declared to accept the other module's output values as its input, so that the caller can pass the object representing the first module result into the second module:
module "first" {
# ...
}
module "second" {
# ...
first = module.first
}
Inside this "second" module, the input variable first would be declared as requiring an object type with attributes matching whatever subset of the output values of "first" that the second module depends on.

Related

Modules variables as a file

I have a terraform module that looks like below
module "newserver" {
source = "./newserver"
// passing the variables here
}
Instead of passing the variables there, can i pass them as a file in the command like below
terraform apply -var-file="/path/variables.tfvars"
When i do that, i am getting errors like missing required argument, what am i missing here, any help on this would be appreciated.
Your module has variables defined inside it with variable blocks such as
variable "example_var" {}
When you instantiate the module, you'll need to pass the required variable into the module. If you want to pass variables into the module when you instantiate it, you'll also have to define those variables as well
module "newserver" {
source = "./newserver"
example_var = var.example_var
}
variable "example_var" {}
Terraform is scoped so that variables are scoped inside of modules, you'll have to make a new variable if you instantiate a module and want to pass variables into it

Terraform: output from multiple module calls

Pseudo-code:
module "foo-1" {
source="./foo"
input=1
}
module "foo-2" {
source="./foo"
input=2
}
module "foo-3"
source="./foo"
input=3
}
...etc...
(The module ./foo outputs a unique id based on the input value)
Problem:
I would like to be able to arbitrarily instantiate/call the ./foo module and have access to the unique id from each module instances. I can't see a way to do this with Terraform as the output syntax either requires a unique val=expression per module instantiation. Splat expressions on the module object (module.*.id) are unfortunately (and not surprisingly) not supported.
I'm guessing that this can't be done in terraform but would love to be wrong.
Because each of those modules is entirely separate from Terraform's perspective, to gather their results together into a single value will require writing an expression to describe that. For example:
locals {
foos = [
module.foo_1,
module.foo_2,
module.foo_3,
]
}
With a definition like that, elsewhere in your module you can then write an expression like local.foos[*].id to collect up all of the ids across all of the modules.

How to reuse variable *definitions* in Terraform?

If I create a varaible definition like this:
variable "aws_ecs_config" {
type = object({
cpu = number
memory = number
ecs_image_address = string
})
logs = {
type = object({
group = string
region = string
stream_prefix = string
})
}
}
How can I reuse that definition in multiple places without copy-pasting?
It is not possible to re-use variable declarations in Terraform. If variables in different modules will have the same type, that type must be repeated in each module.
Terraform has a structural type system rather than a nominal type system, so types themselves are not named and instead are matched/constrained by their form. When passing values between modules, we can use type constraints to create conventions between a family of related modules, but there is no mechanism to define a type (or declare a variable) in one place and reuse it in other places.
Terraform's type constraint mechanism considers any object with at least the attributes in the type constraint to be valid, so it's not necessary to define an exhaustive object type every time.
For example, if you define a variable with the following type:
object({
name = string
})
The following object value is acceptable for that type constraint, because it has a name attribute of the correct type regardless of any other attributes it defines:
{
name = "foo"
other = "bar"
}
For that reason, it can be better to limit the variable declaration in each module to only the subset of attributes that particular module actually requires, which reduces the coupling between the modules: they only need to be compatible to the extent that their attribute names overlap, and don't need to directly bind to one another.
Workaround
This is possible without explicit Terraform support. (There are some discussions about types. Weigh in if you think it would be handy)
Terraform allows variables to be declared over multiple files, and if the modules live on a Linux filesystem, reuse is vastly simplified. (Windows folks... well, it is possible, just not pretty and may not play well with version control.)
How?
Move the variable definition to a file named variable.aws_ecs_config.tf
Place it in a well known place. Say, a directory called variables that lives next to modules.
Whenever the variable is needed in a module, create a symlink to the variable file: ln -s <path/to/variables>/variable.aws_ecs_config.tf

Terraform: Automatically populate module's variables

I am calling a terraform module from my main.tf as follows:
module "vpc" {
source = "./modules/vpc"
match_pub_ip_env_vpc_sn = true
env_vpc_sg_name = "My name"
env_vpc_sg_desc = "My description"
}
My question is this: Can I use a file to populate the call to the above module with the values I want for the above variables without explicitly adding them in the module statement (as above). If so is there a file naming convention that terraform uses for such a purpose? (i.e. without me needing to pass -vars-file in the cmd?)
Unfortunately not. It's like a method/function call. The module needs to declare what variables it takes (eg the signature or parameter list in a programming language, with some being defaulted if not set) and then the caller of the module needs to pass any required variables when it declares the module.

Is it possible to take the name of a variable and turn it into a string in ActionScript 3.0?

I am making a simple debugger window in ActionScript for myself where I can add and remove variables I want to track. I was to be able to add variables to the list by just doing something like
DebuggerMonitor.trackVar(variable).
My question is, is there any way I can turn "variable" itself (the name, not the value) into a String to be added into a text field?
Depending on how "intelligent" your debugger should be, you could just pass the name along:
DebuggerMonitor.trackVar( variable, "variable" );
since obviously, when used in a context like this, the name should be known at the time you are writing the program.
You can also do some reflection magic to get instance variable names, but it won't work for temp variables (their names are dropped at compilation time):
public function getVariableName( instance:*, match:* ):String {
var typeDescription:XML = describeType( instance );
var variables:XMLList = typeDescription..variable;
var accessors:XMLList = typeDescription..accessor;
for each(var variable:XML in variables)
if(matchesXMLName( instance, variable, match ))
return variable.#name;
for each(var accessor:XML in accessors)
if(matchesXMLName( instance, accessor, match ))
return accessor.#name;
return "No name found.";
}
private function matchesXMLName( instance:*, xml:XML, match:* ):Boolean {
return match == instance[xml.#name.toString()];
}
var varName:String = getVariableName ( myObject, variable );
Using reflections like this will also be quite costly, if used often - you will have to think of a way to cache the type descriptions.
I recommend you check out the as3commons reflections package - there is a lot of useful functionality in there...
Short answer - No :(
You can access the type name but not individual instance names, as these are lost at run-time.
There is a confusion caused by the keyword 'var' because it is used to create several types of bindings.
Lexical bindings (the keyword 'var' was used inside a function).
Dynamic bindings (the keyword 'var' was used to declare a class' field).
Lexical bindings are interpreted by the compiler at compile time as addresses of the registers of the registers space occupied by the function. The names given to lexical bindings perish at this time and it is not possible to restore them at runtime - therefore you can't get the "name" of the variable.
Dynamic bindings are a kind of "public API" of the objects that declare them, they may be accessed from the code that was not compiled together with the code that created them, this is why, for the purpose of reflection the names of these bindings are stored in compiled code. However, ActionScript has no way of referencing LHS values, so you cannot, even if you know the name of the variable and the object declaring it, pass it to another function. But you can look it up in the debugger or by calling describeType on the object declaring the variable. Note that describeType will not show information on private variables even if you are calling it from the scope of the object in question.

Resources