Terraform Practice pt4: Module Inputs and Outputs
Tags: terraform, aws, devops, cloud
Published: 2022-06-19 07:44:53

To make out modules truly useful we need a way to pass input parameters to them and get output from them to use in our configuration.

Code for this example [HERE](https://github.com/periwinkleFTW/terraform-path-to-cert/tree/master/practice-pt-4)

It is usually done by creating a `varaibles.tf` and `outputs.tf`. This file layout is the best practice and people working with Terraform would generally implement it this way.

`varaibles.tf` will store input variables and `outputs.tf` will store outputs from our module.

&nbsp;

First, let's refactor out `server` module and create 3 files: `main.tf`, `variables.tf`, and `outputs.tf`.

Next we need to break down our code and put in inside the proper files:

```terraform
# modules/server/variables.tf

variable "subnet_id" {}
variable "size" {
    default = "t2.micro"
}
variable "security_groups" {
  type = list(any)
}
```

```terraform
# modules/server/main.tf

data "aws_ami" "ubuntu" {
  most_recent = true

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }

  owners = ["099720109477"]
}

resource "aws_instance" "web_server" {
  ami = data.aws_ami.ubuntu.id
  instance_type = var.size
  subnet_id = var.subnet_id
  vpc_security_group_ids = var.security_groups

  tags = {
    Name = "Web Server from module"
    Terraform = "true"
  }
}
```

```terraform
# modules/server/outputs.tf

output "public_ip" {
  value = aws_instance.web_server.public_ip
}
output "public_dns" {
  value = aws_instance.web_server.public_dns
}
```

We can now delete `server.tf`. Initialize, format, validate, and plan to check the new code.

&nbsp;

This is the new project structure:

```bash
.
├── main.tf
├── modules
│   └── server
│       ├── main.tf
│       ├── outputs.tf
│       ├── server.tf
│       └── variables.tf
├── outputs.tf
├── terraform.tf
├── terraform.tfstate
├── terraform.tfstate.backup
└── variables.tf
```

&nbsp;

# Terrafrom input variables

As with many configurations out there Terraform provides us with ability to specify required and optional parameters. If you look into server's `variable.tf` you can see that some variables have default values and some do not. 

Optional parameters will have a `default` value to fall back on in case it was not provided. 

Required parameters do not have `default` meaning that it should be specified one way or the other. 
 
&nbsp;

# Terraform outputs

Similar to variables, outputs serve the same purpose as inputs of providing data between different parts of the configuration. The difference lies in how they are accessed and the fact that outputs are read-only. In order to access outputs you must call them from the module where you intend to access them.

Outputs is the only way for us to access attributes from child modules. 

Outputs can be accessed using dot notation (this is `main.tf` in the root dir):
```terraform
# main.tf

# ... more code above

output "public_ip" {
  value = module.my_server_module.public_ip
}
```

Thank you for reading! See you in the next article!