How to provide a list of arguments to cookiecutter? - cookiecutter

I am trying to build a cookiecutter template for a terraform repository.
The repo is used to create buckets. I would like to add a "buckets" argument, where bucket is a list.
I tried something like this in the cookiecutter.json.
{
"buckets": ["bucket_1", "bucket_2", "bucket_3"],
"arg2": value
}
but it appears that doing this just asks if you want to pick bucket_1/2 or 3. I would actually to allow creating 1 bucket or several and not just pick an option in that list. Is it something feasible with cookiecutter ?

Related

Terraform - Rendering Local Values and Variables to speed up development

Is there a way to render the values of Local Values and Variables? As an example, I have this file
variable "foo" {
type = string
default = "bar"
}
locals {
my_var = "here is ${var.foo}"
}
# Rendered:
# my_var = "here is bar"
Is there a quick and easy way to do it? I've tried terraform console but it's hard to use it with complicated use-cases, such as templatefile, jsonencode, jsondecode, merge and the list goes on and on.
I need this capability to test functions that I'm not yet familiar with. Doing terraform apply for just checking how my functions are working is something that I'm trying to avoid.
I needed something like https://www.katacoda.com/courses/terraform/playground but for local usage with fast results.
I created this project - https://github.com/unfor19/tfcoding - which brings up a Docker container that watches for changes in the file tfcoding.tf and renders the Local Values automatically upon saving this file.
Demo:

Terraform: dynamically create list of resources

Due to some prior decisions, there is a script that creates ALBs and a completely separate one to setup alarms for each ALB created (odd, but I can't change this).
I could hard code a list of all the ALBs and iterate thru them, ie:
albs = ['a', 'b']
I know how to iterate thru a list with a "for_each".
What I need is to build the list dynamically so I don't have to manually maintain the list. I know I can get a list of ALBs using:
terraform state list [options] ## https://www.terraform.io/docs/commands/state/list.html
but that doesn't really help (sure, I can pipe that to a file and iterate through the lines in the file and pass them as parameters - but that is ugly as sin)
How do I dynamically build the list with all my ALBs? Something like:
albs = state_list([options])
Thanks! Using AWS.

Iterate through map for file function

I have a usecase for uploading multiple files to s3 using terraform. I would like to upload multiple objects using the count function. In doing this need to iterate through the source with file("${path.module}/path/to/file").
Is there anyway to make the file function a mapped variable leveraging the count.index?
Terraform 0.12.8 introduced a new function fileset which can return a set of file paths matching a particular pattern in a particular base directory.
We can combine that with resource for_each (rather than count) to upload the matching files to S3, like this:
resource "aws_s3_bucket_object" "example" {
for_each = fileset("${path.module}/files", "*") # could use ** instead for a recursive search
bucket = "example"
key = each.value
source = "${path.module}/${each.value.source_path}"
# Unless the bucket has encryption enabled, the ETag of each object is an
# MD5 hash of that object.
etag = filemd5("${path.module}/${each.value.source_path}")
}
Using for_each instead of count here means that Terraform will identify each instance of the resource by its S3 path rather than by its position in a list, and so you can add and remove files without disturbing other files. For example, if you have a file called example.txt then Terraform will track its instance as aws_s3_bucket_object.example["example.txt"], rather than an address like aws_s3_bucket_object.example[3] where 3 is its position in the list of files.
I have written a Terraform module that builds on fileset to also support template rendering and detecting filetypes based on filename suffixes, which might make life easier in some more complicated situations: apparentlymart/dir/template. You can use its result with aws_s3_bucket_object in a similar way to the above, as shown in its README.

Is there a way to input variable values from outside to terraform main file?

Is there a way I can input variable values from outside to terraform main file. It can be a excel sheet or sql db. Is it possible to do so ?
What you can't currently do is point you cmdline at a db i.e. to replace a tfvars file, but what you can set up in Terraform is to use a number of different key value stores:
consul
https://www.terraform.io/intro/examples/consul.html
aws parameter store (using a resource or data)
https://www.terraform.io/docs/providers/aws/d/ssm_parameter.html
There are quite a number of other key/value stores to choose from but there's no zero code solution and you will end up with lots of these statements:
Setup a key in Consul to provide inputs
data "consul_keys" "input" {
key {
name = "size"
path = "tf_test/size"
default = "m1.small"
}
}
There are many ways to do that;
You can use a tfvars file with all your inputs and you can use one file customer, user, environment
You can pass the variables to terraform executable on the command line
You can define environment files prefixed wit TF_VAR_[variable]
You can use https://www.terraform.io/docs/providers/aws/d/ssm_parameter.html as suggested above
You can even store variables in DynamoDB or any other database
You can use Consult+Vault as well

How do I append array items to a string over a loop in puppet

lets say I have an array with directory names
dirs = ['opt', 'apps', 'apache']
I want to iterate and generate a list of following paths
/opt
/opt/apps
/opt/apps/apache
through which I can create file resource.
Is there a reason you want to iterate through those files like that?
Because the simplest way to turn those into file resources would be this:
$dirs = ['/opt', '/opt/apps', '/opt/apps/apache']
file { $dirs:
ensure => directory,
}
If you just want to make sure that all the preceeding directories are created, there is also the dirtree module, which will do this all for you:
https://forge.puppet.com/pltraining/dirtree
$apache_dir = dirtree('/opt/apps/apache')
# Will return: ['/opt', '/opt/apps', '/opt/apps/apache']
You can then use that variable to create the directories.
As Matt mentions, you can also use maps, or an iterator to create the resources.
Basic example here:
$dirs = ['/opt', '/opt/apps', '/opt/apps/apache']
$dirs.each |String $path| {
file {$path:
ensure => directory,
}
}
Documented here: https://docs.puppet.com/puppet/latest/lang_iteration.html
There are a few different ways to do what you want to do in the code, it depends on how much management you want to do of those resources after creation.

Resources