Why terraform validate is giving error on my declared varaibles? - terraform

├── comp-B
│   ├── comp-B.tf
│   ├── outputs.tf
│   ├── terraform.tfvars
│   ├── variables.tf
│   └── vcn.tf
├── main.tf
├── outputs.tf
├── provider.tf
└── variables.tf
The argument "vcns" is required, but no definition was found
I have defined the vcns in comp-B/variables.tf and vcns value in terraform.tfvars
But still getting the error.

Without seeing your source code I can't be sure, but I'm assuming that what you mean by this directory tree is that the root main.tf contains a module block with source = "./comp-B", and the error you saw is indicating that module block as the source of the problem.
The terraform.tfvars file is only for setting variables in the root module, which means the ones defined in your root variables.tf. If you want to pass those values on to a child module then you can include an argument in the module block which refers to the variable:
module "example" {
source = "./comp-B"
vcns = var.vcns
# ...
}

Related

How should I apply a terraform root module construct using terragrunt?

I'm working on a terragrunt code base for the first time, having used terraform a lot in the past without terragrunt. I'm a bit confused as to the structure terragrunt seems to enforce. I would usually organise my terraform thus:
main.tf
--> module
main.tf
--> module2
main.tf
This is listed as best practice on the terraform docs:
The Root Module
Terraform always runs in the context of a single root module. A
complete Terraform configuration consists of a root module and the
tree of child modules (which includes the modules called by the root
module, any modules called by those modules, etc.).
Source
But none of the terragrunt structures seem to represent this. It seems to be designed so that each module is independent and run using the run-all command.
This seems problematic to me, from the existing code base I can see that this initialises terraform for every module and I'd say causes issues with sharing secrets between modules. So I'd prefer to work with one root module and multiple child modules.
I can't find a terragrunt pattern that will allow me to do this?
I'm also confused as to how this responsibility is decomposed, do I actually structure my terraform (as above) or do I need an extra root .hcl file?
I'm after something a little like this I guess
└── live
├── prod
│ ├── terragrunt.hcl
│ ├── app
│ │ └── terragrunt.hcl
│ ├── mysql
│ │ └── terragrunt.hcl
│ └── vpc
│ └── terragrunt.hcl
├── qa
│ ├── terragrunt.hcl
│ ├── app
│ │ └── terragrunt.hcl
│ ├── mysql
│ │ └── terragrunt.hcl
│ └── vpc
│ └── terragrunt.hcl
└── stage
├── terragrunt.hcl
├── app
│ └── terragrunt.hcl
├── mysql
│ └── terragrunt.hcl
└── vpc
└── terragrunt.hcl
But this example just talks about specifying the provider block and nothing about a root main.tf. So I'm lost?
Each TF module you used to use consumed inputs, created resources and provided outputs. The wiring of the modules was done via main.tf you are referring to in plain Terraform.
In your case with Terragrunt now, the wiring will be done by terragrunt.hcl files. On the module level (e.g.live/prod/app/terragrunt.hcl) you could define the module dependencies, i.e. where are the input values for this modules input variables, e.g.:
inputs {
username = dependency.iam.output.user.name
}
With this in mind, you might or might not use root-level terragrunt.hcl files. If you want to invoke the parent-folder terragrunt.hcl code, you need to add the following block into your module:
include "root" {
path = find_in_parent_folders()
expose = true
}
See the docs for this function here.

How to use variables defined in terraform.tfvars in main.tf

structure in my terraform source
├── main.tf
├── outputs.tf
├── serverless
│   ├── main.tf
│   ├── outputs.tf
│   ├── terraform.tfvars
│   ├── variables.tf
│   └── versions.tf
├── variables.tf
└── versions.tf
question
How can I use variables defined in terraform.tfvars in main.tf?
My code is based on this example and add the following code with it(replaced ~/examples/serverless with ~/serverless).
terraform-aws-modules/terraform-aws-rds-aurora
https://github.com/terraform-aws-modules/terraform-aws-rds-aurora
code in serverless/terraform.tfvars
SAMPLE_VALUE="xxx"
code in serverless/main.tf
variable "SAMPLE_VALUE" {}
deploy command
$ terraform apply
official document
It lacks of usage in other .tf file
Variable Definitions (.tfvars) Files
https://www.terraform.io/language/values/variables#variable-definitions-tfvars-files
If you create your variable in variable file, you can use it in the same directory's main.tf with var. In your case, the variable you are trying to locate should be located to its place in main.tf using var.SAMPLE_VALUE
There is pretty clear explanation with example here ;
https://jhooq.com/terraform-variable-and-tfvars-file/#2-terraform-tfvars-file---terraformtfvars
I succeeded to overcome this problem to define variable "SAMPLE_VALUE" {} both serverless/main.tf and ~/main.tf.
Thanks everyone for reply!!

terraform Resource share

I have a terraform template module that looks like this
.
├── example
│   ├── main.tf
│   └── variables.tf
├── policies.tf
├── roles.tf
├── main.tf
├── provider.tf
└── variable.tf
inside the main.tf inside example path I have a resource that depends on a resource that is part of me main.tf how can I call resource with depends_on = [] if they're not part of the same file and path
if they're not part of the same file and path
You can't do this. You have to re-think your architecture and probably change it so that such dependency does not happen.

Source Terraform Module From Sub-Directories In a BitBucket Repository With A different branch

I have a terraform modules repository with different set of modules with below structure
BitBucket Repository(URL: git#bitbucket.org:/{repoName}.git?ref=develop
└── modules
├── s3
│   ├── locals.tf
│   ├── main.tf
│   ├── output.tf
│   └── variables.tf
└── tfstate
└── main.tf
develop is the branch that I want to use which I have given in the source URL. I am calling the module repository as given below:
├── examples
│   ├── gce-nextgen-dev.tfvars
│   └── main.tf
main.tf
module "name" {
source = "git#bitbucket.org:{url}/terraform-modules.git? ref=develop/"
bucketName = "terraformbucket"
environment = "dev"
tags = map("ExtraTag", "ExtraTagValue")
}
How can I call the modules from sub-directories which is in a BitBucket repository.
It works if I remove the ref=develop from the URL and just give git#bitbucket.org:{url}/terraform-modules.git//modules//s3
But I don't want to use master but develop branch in this case.

How to name resources dynamically based on the env they are in?

I'm trying to unify naming of resources, depending on the environment (dev, stage or prod). I will illustrate with an example.
Let's say I want to create an aws iam user resource like:
resource "aws_iam_user" "iam_foo" {
name = "foo_dev"
}
Here I hard-coded "dev" into the name of the resource. But ideally I would like that to be done dynamically based on the folder it is located in (folder resembles an environment like dev or prod).
The folder structure looks something like:
├── README.md
├── meow-development
│   ├── locals.tf -> ../locals.tf
│   ├── main.tf
│   └── s3.tf
├── meow-production
│   ├── locals.tf -> ../locals.tf
│   ├── main.tf
│   └── s3.tf
├── meow-staging
│   ├── locals.tf -> ../locals.tf
│   ├── main.tf
│   └── s3.tf
So what I am trying to achieve is something like:
resource "aws_iam_user" "iam_foo" {
name = naming_function(name) # Not intended as actual code
}
The naming function takes a name as input and names it according to the env. So if this resource is created under dev, then naming_function(woof) should return the string "woof_dev"
So my questions are:
How can I name things dynamically?
Is using a naming convention that includes the environment such as meow_{env_name} correct?
Create a terraform.tfvars inside the meow-development folder with
env_name = "dev"
In the main.tf inside the meow-development folder:
resource "aws_iam_user" "iam_foo" {
name = "foo_${var.env_name}"
}
Same for other environments. Regarding naming convention, depends on the resource, having env as part of the name is considered a best practice.

Resources