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
Related
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.
I'm trying to something fairly simple, but can't seem to get my head around it. I have the following structure:
- terragrunt.hcl
-----dummy/
---------main.tf
---------terragrunt.hcl
I'm looking to set some common variables at the root level, and use them in main.tf. Howe would I go about declaring the varibale in the root terragrunt level, and have them available downstream?
I've tried setting them as inputs in the root, but then have to explicitly declare "variables" at the dummy level for the inputs to get picked up. I'm looking to somehow define these things at the root level and not repeat variable declarations at dummy/ level. Is this doable?
You can indeed do this documented here:
https://terragrunt.gruntwork.io/docs/reference/built-in-functions/#read_terragrunt_config
You can merge all inputs defined in some file above any module.
From the docs:
read_terragrunt_config(config_path, [default_val]) parses the terragrunt config at the given path and serializes the result into a map that can be used to reference the values of the parsed config. This function will expose all blocks and attributes of a terragrunt config.
For example, suppose you had a config file called common.hcl that contains common input variables:
inputs = {
stack_name = "staging"
account_id = "1234567890"
}
You can read these inputs in another config by using read_terragrunt_config, and merge them into the inputs:
locals {
common_vars = read_terragrunt_config(find_in_parent_folders("common.hcl"))
}
inputs = merge(
local.common_vars.inputs,
{
# additional inputs
}
)
This function also takes in an optional second parameter which will be returned if the file does not exist:
locals {
common_vars = read_terragrunt_config(find_in_parent_folders("i-dont-exist.hcl", "i-dont-exist.hcl"), {inputs = {}})
}
inputs = merge(
local.common_vars.inputs, # This will be {}
{
# additional inputs
}
)
Per the Terragrunt documentation: "Currently you can only reference locals defined in the same config file. Terragrunt does not automatically include locals defined in the parent config of an include block into the current context."
However, one way you can do this is as follows:
Create a file containing the common variables (e.g. myvars.hcl)
Load that in the child terragrunt:
locals {
myvars = read_terragrunt_config(find_in_parent_folders("myvars.hcl"))
foo = local.myvars.locals.foo
}
Hope that helps!
Other tools like Ansible has directory hierarchy where child can refer to or override the value of a variable set at the parent level.
Terraform does not have such a mechanism and each directory having tf files is a separate Terraform module. So directory hierarchy cannot be used to pass/inherit/reference Terraform variables.
Perhaps better to let the idea of "downstream or upstream" go.
One way to define common variables and share them among other modules is Data-only Modules . Extension of this and make the common variable world-wide available is using Terraform registry although it is not the intended use.
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.
In the scope of one class, I need to be able to access a variable from another class. The variable is passed as a parameter, e.g.
class parameterized_class (
$param1,
) {
...
}
and
class other_class () {
include parameterized_class
Class['parameterized_class'] -> Class['other_class']
$local_var = $parameterized_class::param1
}
With an example usage of:
node default {
class { 'parameterized_class':
param1 => 'somevalue',
}
class { 'other_class': }
}
The above example does not work, as I get an error that looks roughly like:
Must pass param1 to
Class[Parameterized_class] at
/path/to/modules/parameterized_class/manifests/init.pp:1
on node localhost
Obviously, include is trying to declare parameterized_class without passing any parameters. But from the docs, I can see that include allows for a class to have been already previously declared, and since I have the parameterized_class declaration as a dependency of other_class, I don't understand how I could be getting this error.
I'm using Puppet 3.4.3, the version available on Ubuntu 14.04 Trusty
How should I go about retrieving the value of the $param1 in parameterized_class from within other_class's scope? Is it not possible to use include on parameterized classes?
According to the Puppet documentation (https://docs.puppet.com/puppet/3.5/lang_classes.html#include-like-behavior) you cannot use include-like declarations with mandatory parameters. In your case, what you can do is just not bother with the include since you've already handled that by declaring it in your node definition. Also, because both are declared in your node definition you would want to order them there as well.
As a side note not providing default values is a bad practice as is using variables across modules.
Here, my question is, we use define function in php to define the
contant globally but how can i achive same thing in nodejs
in php:
define(nameofthecontant, value);
in nodejs how to?
var dataBaseInfo = result.databaseInfo;
// global.DB_HOST = dataBaseInfo['DB_HOST'];
for(var keys in dataBaseInfo) {
global.keys = dataBaseInfo[keys];
}
i have data in result.databaseInfo from database xml file and m trying to create global contant using for loop, its not working
This is how you can define a variable in the global namespace:
global.nameofthecontant = value
This is something that you don't want to do in node.js though. Your question possibly is a duplicate of this question: node.js global variables?
Change your code from this:
global.keys = dataBaseInfo[keys];
to this:
global[keys] = dataBaseInfo[keys];
When you want to access or assign a property and the property name is in a variable, you use the obj[variableName] syntax.
You could also use Object.assign here if you just want to copy a bunch of properties from one object to another:
Object.assign(global, databaseInfo);
As others have said, it is usually frowned upon to use globals in this way in node.js. Instead, you would typically expose these constants in a module and then just require in the module in any other module that wants to access the constants. This makes your code more modular and makes each module more self-contained.