Skip to content

Instantly share code, notes, and snippets.

@visar
Forked from tuannvm/0.12.tf
Created March 7, 2019 23:43
Show Gist options
  • Save visar/0a828a86e33c5782acaace83bd2f1e7f to your computer and use it in GitHub Desktop.
Save visar/0a828a86e33c5782acaace83bd2f1e7f to your computer and use it in GitHub Desktop.

Revisions

  1. @tuannvm tuannvm revised this gist Nov 16, 2018. No changes.
  2. @tuannvm tuannvm revised this gist Nov 16, 2018. 1 changed file with 227 additions and 0 deletions.
    227 changes: 227 additions & 0 deletions 0.12.tf
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,227 @@
    # first class expresssion
    variable "ami" {}
    resource "aws_instance" "example" {
    ami = var.ami
    }

    ###

    # list & map
    resource "aws_instance" "example" {
    vpc_security_group_ids = var.security_group_id != "" ? [var.security_group_id] : []
    }

    ###

    # In 0.12, HCL resolves this by making an explicit distinction between attributes and blocks. Attributes are single-assigned values using the assignment operator =. Blocks are repeated maps of key/value configuration pairs
    resource "aws_security_group" "example" {

    # "ingress" is parsed as a block because there is no equals sign
    ingress {
    # ..
    }

    # "value" is parsed as a attribute as it has equal sign
    value = {
    # ..
    }
    }

    ###

    # For Expressions for List and Map Transformations
    variable "subnet_numbers" {
    description = "List of 8-bit numbers of subnets of base_cidr_block that should be granted access."
    default = [1, 2, 3]
    }

    resource "aws_security_group" "example" {
    # For each number in subnet_numbers, extend the CIDR prefix of the
    # requested VPC to produce a subnet CIDR prefix.
    # For the default value of subnet_numbers above and a VPC CIDR prefix
    # of 10.1.0.0/16, this would produce:
    # ["10.1.1.0/24", "10.1.2.0/24", "10.1.3.0/24"]
    cidr_blocks = [
    for num in var.subnet_numbers:
    cidrsubnet(data.aws_vpc.example.cidr_block, 8, num)
    ]
    }
    }

    ###

    # how to produce a map
    output "instance_private_ip_addresses" {
    # Result is a map from instance id to private IP address, such as:
    # {"i-1234" = "192.168.1.2", "i-5678" = "192.168.1.5"}
    value = {
    for instance in aws_instance.example:
    instance.id => instance.private_ip
    # if statement
    if instance.associate_public_ip_address
    }
    }

    output "instances_by_availability_zone" {
    # Result is a map from availability zone to instance ids, such as:
    # {"us-east-1a": ["i-1234", "i-5678"]}
    value = {
    for instance in aws_instance.example:
    # mind the ...
    instance.availability_zone => instance.id...
    }
    }

    ###

    # Dynamic Nested Blocks
    variable "subnets" {
    default = [
    {
    name = "a"
    number = 1
    },
    {
    name = "b"
    number = 2
    },
    {
    name = "c"
    number = 3
    },
    ]
    }

    locals {
    base_cidr_block = "10.0.0.0/16"
    }

    resource "azurerm_virtual_network" "example" {
    name = "example-network"
    resource_group_name = azurerm_resource_group.test.name
    address_space = [local.base_cidr_block]
    location = "West US"

    dynamic "subnet" {
    # [{"name": "a", "prefix": "10.1.0.0/24"},
    # {"name": "b", "prefix": "10.2.0.0/24"},
    # {"name": "c", "prefix": "10.3.0.0/24"}]
    for_each = [for s in subnets: {
    name = s.name
    prefix = cidrsubnet(local.base_cidr_block, 4, s.number)
    }]

    content {
    name = subnet.name
    address_prefix = subnet.prefix
    }
    }
    }

    ###

    # splat operator
    # before only work with resource with "count", now work for any list value
    output "instance_ip_addrs" {
    value = google_compute_instance.example.network_interface.*.address
    }

    ###

    # full splat operator
    # instead of network_interface.*.
    output "instance_net_ip_addrs" {
    value = google_compute_instance.example.network_interface[*].access_config[0].assigned_nat_ip
    }

    ###

    # Conditional Operator Improvements
    locals {
    first_id = length(azurerm_virtual_machine.example) > 0 ? azurerm_virtual_machine.example[0].id : ""

    buckets = (var.env == "dev" ? [var.build_bucket, var.qa_bucket] : [var.prod_bucket])
    }

    ###

    # Conditionally Omitted Arguments
    variable "override_private_ip" {
    type = string
    default = null
    }

    resource "aws_instance" "example" {
    # By using the new null value, the aws_instance resource can dynamically assign a private IP address when no override is provided,
    # but set an explicit IP address if the calling module provides a value for override_private_ip.
    private_ip = var.override_private_ip
    }

    ###

    # Complex Values
    # complex objects can now be passed to child modules as inputs, and returned to parent modules as outputs
    # access with `for network in var.networks`
    module "subnets" {
    source = "./subnets"

    parent_vpc_id = "vpc-abcd1234"
    networks = {
    production_a = {
    network_number = 1
    availability_zone = "us-east-1a"
    }
    production_b = {
    network_number = 2
    availability_zone = "us-east-1b"
    }
    staging_a = {
    network_number = 1
    availability_zone = "us-east-1a"
    }
    }
    }

    ###

    # Rich types
    variable "networks" {
    # custom type
    # no quote
    type = map(object({
    network_number = number
    availability_zone = string
    tags = map(string)
    }))
    }

    ###

    # Resources and Modules as Values
    # return the whole object
    output "vpc" {
    value = aws_vpc.example
    }

    ###

    # New Template syntax
    locals {
    lb_config = <<EOT
    %{ for instance in opc_compute_instance.example ~}
    server ${instance.label} ${instance.ip_address}:8080
    %{ endfor }
    EOT
    }

    ###

    # JSON comment
    {
    "variable": {
    "example": {
    "#": "This property is ignored",
    "default": "foo"
    }
    }
    }
  3. @tuannvm tuannvm revised this gist Mar 29, 2018. 1 changed file with 20 additions and 20 deletions.
    40 changes: 20 additions & 20 deletions provider.md
    Original file line number Diff line number Diff line change
    @@ -18,11 +18,11 @@ import (
    )

    func Provider() *schema.Provider {
    return &schema.Provider{
    ResourcesMap: map[string]*schema.Resource{
    "example_server": resourceServer(),
    },
    }
    return &schema.Provider{
    ResourcesMap: map[string]*schema.Resource{
    "example_server": resourceServer(),
    },
    }
    }
    ```

    @@ -37,11 +37,11 @@ import (
    )

    func main() {
    plugin.Serve(&plugin.ServeOpts{
    ProviderFunc: func() terraform.ResourceProvider {
    return Provider()
    },
    })
    plugin.Serve(&plugin.ServeOpts{
    ProviderFunc: func() terraform.ResourceProvider {
    return Provider()
    },
    })
    }
    ```

    @@ -58,17 +58,17 @@ import (

    func resourceServer() *schema.Resource {
    return &schema.Resource{
    Create: resourceServerCreate,
    Read: resourceServerRead,
    Update: resourceServerUpdate,
    Delete: resourceServerDelete,

    Schema: map[string]*schema.Schema{
    "address": &schema.Schema{
    Type: schema.TypeString,
    Required: true,
    },
    Create: resourceServerCreate,
    Read: resourceServerRead,
    Update: resourceServerUpdate,
    Delete: resourceServerDelete,

    Schema: map[string]*schema.Schema{
    "address": &schema.Schema{
    Type: schema.TypeString,
    Required: true,
    },
    },
    }
    }

  4. @tuannvm tuannvm revised this gist Mar 29, 2018. 1 changed file with 13 additions and 13 deletions.
    26 changes: 13 additions & 13 deletions provider.md
    Original file line number Diff line number Diff line change
    @@ -57,19 +57,19 @@ import (
    )

    func resourceServer() *schema.Resource {
    return &schema.Resource{
    Create: resourceServerCreate,
    Read: resourceServerRead,
    Update: resourceServerUpdate,
    Delete: resourceServerDelete,

    Schema: map[string]*schema.Schema{
    "address": &schema.Schema{
    Type: schema.TypeString,
    Required: true,
    },
    },
    }
    return &schema.Resource{
    Create: resourceServerCreate,
    Read: resourceServerRead,
    Update: resourceServerUpdate,
    Delete: resourceServerDelete,

    Schema: map[string]*schema.Schema{
    "address": &schema.Schema{
    Type: schema.TypeString,
    Required: true,
    },
    },
    }
    }

    func resourceServerCreate(d *schema.ResourceData, m interface{}) error {
  5. @tuannvm tuannvm revised this gist Mar 29, 2018. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions provider.md
    Original file line number Diff line number Diff line change
    @@ -73,9 +73,9 @@ func resourceServer() *schema.Resource {
    }

    func resourceServerCreate(d *schema.ResourceData, m interface{}) error {
    address := d.Get("address").(string)
    d.SetId(address)
    return nil
    address := d.Get("address").(string)
    d.SetId(address)
    return nil
    }

    func resourceServerRead(d *schema.ResourceData, m interface{}) error {
  6. @tuannvm tuannvm revised this gist Mar 29, 2018. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions provider.md
    Original file line number Diff line number Diff line change
    @@ -73,6 +73,8 @@ func resourceServer() *schema.Resource {
    }

    func resourceServerCreate(d *schema.ResourceData, m interface{}) error {
    address := d.Get("address").(string)
    d.SetId(address)
    return nil
    }

  7. @tuannvm tuannvm revised this gist Mar 29, 2018. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions provider.md
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,7 @@
    # Terraform provider

    [Source](https://www.terraform.io/guides/writing-custom-terraform-providers.html)

    ```bash
    ├── main.go
    ├── provider.go
  8. @tuannvm tuannvm revised this gist Mar 29, 2018. 1 changed file with 7 additions and 0 deletions.
    7 changes: 7 additions & 0 deletions provider.md
    Original file line number Diff line number Diff line change
    @@ -86,3 +86,10 @@ func resourceServerDelete(d *schema.ResourceData, m interface{}) error {
    return nil
    }
    ```

    main.tf

    ```hcl
    resource "example_server" "my-server" {
    address = "1.2.3.4"
    }
  9. @tuannvm tuannvm revised this gist Mar 29, 2018. 1 changed file with 88 additions and 1 deletion.
    89 changes: 88 additions & 1 deletion provider.md
    Original file line number Diff line number Diff line change
    @@ -1 +1,88 @@
    touch
    # Terraform provider

    ```bash
    ├── main.go
    ├── provider.go
    ├── resource_server.go
    ```

    provider.go

    ```go
    package main

    import (
    "github.com/hashicorp/terraform/helper/schema"
    )

    func Provider() *schema.Provider {
    return &schema.Provider{
    ResourcesMap: map[string]*schema.Resource{
    "example_server": resourceServer(),
    },
    }
    }
    ```

    main.go

    ```go
    package main

    import (
    "github.com/hashicorp/terraform/plugin"
    "github.com/hashicorp/terraform/terraform"
    )

    func main() {
    plugin.Serve(&plugin.ServeOpts{
    ProviderFunc: func() terraform.ResourceProvider {
    return Provider()
    },
    })
    }
    ```

    > As a general convention, Terraform providers put each resource in their own file, named after the resource, prefixed with resource_
    resource_server.go

    ```go
    package main

    import (
    "github.com/hashicorp/terraform/helper/schema"
    )

    func resourceServer() *schema.Resource {
    return &schema.Resource{
    Create: resourceServerCreate,
    Read: resourceServerRead,
    Update: resourceServerUpdate,
    Delete: resourceServerDelete,

    Schema: map[string]*schema.Schema{
    "address": &schema.Schema{
    Type: schema.TypeString,
    Required: true,
    },
    },
    }
    }

    func resourceServerCreate(d *schema.ResourceData, m interface{}) error {
    return nil
    }

    func resourceServerRead(d *schema.ResourceData, m interface{}) error {
    return nil
    }

    func resourceServerUpdate(d *schema.ResourceData, m interface{}) error {
    return nil
    }

    func resourceServerDelete(d *schema.ResourceData, m interface{}) error {
    return nil
    }
    ```
  10. @tuannvm tuannvm revised this gist Mar 29, 2018. 1 changed file with 11 additions and 3 deletions.
    14 changes: 11 additions & 3 deletions terraform.md
    Original file line number Diff line number Diff line change
    @@ -1,22 +1,27 @@
    # Cheatsheet

    ## Map Loop

    For e.g, we have the following values:

    ```hcl
    vpc_peering_list = {
    k8s-production = "vpc-111111"
    k8s-service = "vpc-222222"
    k8s-zdata = "vpc-333333"
    k8s-zdata = "vpc-333333"
    }
    ```

    **IMPORTANT** Map follows alphanumeric sequence.

    We can loop through this map with:

    ```hcl
    resource "aws_vpc_peering_connection" "vpc_peering" {
    count = "${length(keys(var.vpc_peering_list))}"
    vpc_id = "${element(values(var.vpc_peering_list), count.index)}"
    peer_vpc_id = "${aws_vpc.vpc.id}"
    tags {
    Name = "${element(keys(var.vpc_peering_list), count.index)}-vpc-peering-${var.service_name}"
    }
    @@ -38,16 +43,19 @@ resource "aws_route53_record" "www" {
    ```

    ## Default values for external module output

    https://github.com/hashicorp/terraform/issues/11566#issuecomment-289417805

    https://github.com/coreos/tectonic-installer/blob/master/modules/aws/vpc/vpc.tf#L24

    External module should return output as a `list`

    ```hcl
    id = "${var.external_vpc_id == "" ? join(" ", aws_vpc.new_vpc.*.id) : var.external_vpc_id }"
    ```

    Default value when using conditional check. See [this](https://github.com/hashicorp/terraform/issues/2831#issuecomment-298751019)

    ```hcl
    resource "example" "conditional" {
    count = "${var.enabled ? 1 : 0}"
    @@ -56,4 +64,4 @@ resource "example" "conditional" {
    resource "example" "dependent" {
    argument = "${join("", example.conditional.*.attribute)}"
    }
    ```
    ```
  11. @tuannvm tuannvm revised this gist Mar 29, 2018. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions provider.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    touch
  12. @tuannvm tuannvm revised this gist Dec 1, 2017. 1 changed file with 11 additions and 0 deletions.
    11 changes: 11 additions & 0 deletions terraform.md
    Original file line number Diff line number Diff line change
    @@ -45,4 +45,15 @@ https://github.com/coreos/tectonic-installer/blob/master/modules/aws/vpc/vpc.tf#
    External module should return output as a `list`
    ```hcl
    id = "${var.external_vpc_id == "" ? join(" ", aws_vpc.new_vpc.*.id) : var.external_vpc_id }"
    ```

    Default value when using conditional check. See [this](https://github.com/hashicorp/terraform/issues/2831#issuecomment-298751019)
    ```hcl
    resource "example" "conditional" {
    count = "${var.enabled ? 1 : 0}"
    }
    resource "example" "dependent" {
    argument = "${join("", example.conditional.*.attribute)}"
    }
    ```
  13. @tuannvm tuannvm revised this gist Oct 3, 2017. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions terraform.md
    Original file line number Diff line number Diff line change
    @@ -39,6 +39,7 @@ resource "aws_route53_record" "www" {

    ## Default values for external module output
    https://github.com/hashicorp/terraform/issues/11566#issuecomment-289417805

    https://github.com/coreos/tectonic-installer/blob/master/modules/aws/vpc/vpc.tf#L24

    External module should return output as a `list`
  14. @tuannvm tuannvm revised this gist Oct 3, 2017. 1 changed file with 9 additions and 0 deletions.
    9 changes: 9 additions & 0 deletions terraform.md
    Original file line number Diff line number Diff line change
    @@ -35,4 +35,13 @@ variable "bucket_name" {
    resource "aws_route53_record" "www" {
    count = "${length(var.bucket_name)}"
    name = "${var.bucket_name[count.index]}"
    ```

    ## Default values for external module output
    https://github.com/hashicorp/terraform/issues/11566#issuecomment-289417805
    https://github.com/coreos/tectonic-installer/blob/master/modules/aws/vpc/vpc.tf#L24

    External module should return output as a `list`
    ```hcl
    id = "${var.external_vpc_id == "" ? join(" ", aws_vpc.new_vpc.*.id) : var.external_vpc_id }"
    ```
  15. @tuannvm tuannvm revised this gist Aug 31, 2017. 1 changed file with 14 additions and 0 deletions.
    14 changes: 14 additions & 0 deletions terraform.md
    Original file line number Diff line number Diff line change
    @@ -21,4 +21,18 @@ resource "aws_vpc_peering_connection" "vpc_peering" {
    Name = "${element(keys(var.vpc_peering_list), count.index)}-vpc-peering-${var.service_name}"
    }
    }
    ```

    ## List Loop

    ```hcl
    variable "bucket_name" {
    description = "Bucket Name"
    type = "list"
    default = ["develop", "staging", "prod"]
    }
    resource "aws_route53_record" "www" {
    count = "${length(var.bucket_name)}"
    name = "${var.bucket_name[count.index]}"
    ```
  16. @tuannvm tuannvm created this gist Aug 23, 2017.
    24 changes: 24 additions & 0 deletions terraform.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,24 @@
    ## Map Loop

    For e.g, we have the following values:
    ```hcl
    vpc_peering_list = {
    k8s-production = "vpc-111111"
    k8s-service = "vpc-222222"
    k8s-zdata = "vpc-333333"
    }
    ```
    **IMPORTANT** Map follows alphanumeric sequence.

    We can loop through this map with:
    ```hcl
    resource "aws_vpc_peering_connection" "vpc_peering" {
    count = "${length(keys(var.vpc_peering_list))}"
    vpc_id = "${element(values(var.vpc_peering_list), count.index)}"
    peer_vpc_id = "${aws_vpc.vpc.id}"
    tags {
    Name = "${element(keys(var.vpc_peering_list), count.index)}-vpc-peering-${var.service_name}"
    }
    }
    ```