NashTech Insights

How to use Terraform Provisioners

Sakshi Gawande
Sakshi Gawande
Table of Contents
woman using macbook sitting on white couch

In this blog we are gonna see about terraform provisoners .So basically there total 3 provisioners in terraform 1. file , 2. Local-exec , 3. Remote-exec but in this blog we are gonna see the file provisoners in detail . So without wasting any time lets see first what is terraform provisoners

Terraform Provisioners

Terraform provisoners are used to performe certain task0s s or action on local or remote machine which can not be handle declaratively by terraform. For example installing some software or provide some configuration.

How to use Provisoners

You can define those provisoners in your resource block, and those provioners can execute only once during resource creation. Also you can provide triggers for your provisoners.

resource "aws_instance" "web" {
  # ...

  provisioner "local-exec" {
    command = "echo The server's IP address is ${self.private_ip}"
  }
}

Here i am giving and example of local-exec provisioner but it same declartion for all provisioner, it is just give you an idea that how to use provisoner. The same we can use multiple provisioner within single resource block . as shown below . The order of execution is in the same way we declare them.

resource "aws_instance" "web" {
  # ...

  provisioner "local-exec" {
    command = "echo first"
  }

  provisioner "local-exec" {
    command = "echo second"
  }
}

File Provisoner

As the name given file provisoners is used to transfer file/directory fro,m one machine where terraform is working to the newly created machone/resource

So when we talk about copying files or directories from one machine to another machine then it has to be secured and file provisioner supports for ssh and winrm type of connections which can help you to achieve secure file transfer between the source machine and destination machine.

Example

Let us take an example to understand how to implement terraform file provisioner. The following code snippet shows –

  1. How to write your file provisioner
  2. How to specify source and destination` for copying/transferring the file.
provisioner "file" {
    source      = "/home/knoldus/devops/techhub/keys/aws/test-file.txt"
    destination = "/home/ubuntu/test-file.txt"
} 

In the above code snippet, we are trying to copy file test-file.txt from its source =/home/knoldus/devops/techhub/keys/aws/test-file.txt to its destination =/home/ubuntu/test-file.txt

Here is the complete terraform script which demonstrates on how to use terraform file provisioner

provider "aws" {
 region = "eu-central-1"
 #version = "~> 3.0"
 profile = "sakshi-aws"
}

resource "aws_instance" "ec2_example" {

    ami = "ami-0767046d1677be5a0"  
    instance_type = "t2.micro" 
    key_name= "aws_key"
    vpc_security_group_ids = [aws_security_group.main.id]

  provisioner "file" {
    source      = "/home/knoldus/devops/techhub/keys/aws/test-file.txt"
    destination = "/home/ubuntu/test-file.txt"
  }
  connection {
      type        = "ssh"
      host        = self.public_ip
      user        = "ubuntu"
      private_key = file("/home/knoldus/devops/techhub/keys/aws/test-file.txt")
      timeout     = "4m"
   }
}

resource "aws_security_group" "main" {
  egress = [
    {
      cidr_blocks      = [ "0.0.0.0/0", ]
      description      = ""
      from_port        = 0
      ipv6_cidr_blocks = []
      prefix_list_ids  = []
      protocol         = "-1"
      security_groups  = []
      self             = false
      to_port          = 0
    }
  ]
 ingress                = [
   {
     cidr_blocks      = [ "0.0.0.0/0", ]
     description      = ""
     from_port        = 22
     ipv6_cidr_blocks = []
     prefix_list_ids  = []
     protocol         = "tcp"
     security_groups  = []
     self             = false
     to_port          = 22
  }
  ]
}

resource "aws_key_pair" "deployer" {
  key_name   = "aws_key"
  public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDbvRN/gvQBhFe+dE8p3Q865T/xTKgjqTjj56p1IIKbq8SDyOybE8ia0rMPcBLAKds+wjePIYpTtRxT9UsUbZJTgF+SGSG2dC6+ohCQpi6F3xM7ryL9fy3BNCT5aPrwbR862jcOIfv7R1xVfH8OS0WZa8DpVy5kTeutsuH5FMAmEgba4KhYLTzIdhM7UKJvNoUMRBaxAqIAThqH9Vt/iR1WpXgazoPw6dyPssa7ye6tUPRipmPTZukfpxcPlsqytXWlXm7R89xAY9OXkdPPVsrQA0XFQnY8aFb9XaZP8cm7EOVRdxMsA1DyWMVZOTjhBwCHfEIGoePAS3jFMqQjGWQd rahul@rahul-HP-ZBook-15-G2"
}

Here is one thing to note – You need to generate the ssh keys to connect to your EC2 instance running in the AWS cloud. You can use the command ssh-keygen -t aws_key to generate the key-pair. You can read this blog post on Terraform how to do SSH in AWS EC2 instance?

Connection Block

You can create one or more connection block that describe how to access the remote resource. One use case for providing multiple connections is to have an initial provisioner connect as the root user to set up user accounts and then have subsequent provisioners connect as a user with more limited permissions.

 connection {
      type        = "ssh"
      host        = self.public_ip
      user        = "ubuntu"
      private_key = file("/home/knoldus/devops/techhub/keys/aws/test-file.txt")
      timeout     = "4m"
   }

Arguments

  • source – The source file or directory. Specify it either relative to the current working directory or as an absolute path. This argument cannot be combined with content.
  • content – The direct content to copy on the destination. If destination is a file, the content will be written on that file. In case of a directory, a file named tf-file-content is created inside that directory. We recommend using a file as the destination when using content. This argument cannot be combined with source.
  • destination – (Required) The destination path to write to on the remote system. See Destination Paths below for more information.

Directory Uploads

Note : When you are uploading directory directly rather than file using ssh connection type, then destinationion dir must be prestnt already . If destinatination directory is not present there then you must use remote-exec provisoner to create destination dir prior to file provisoner.

If you are are using winrm then there is no need to create destination dir, as winrm connection type will create it for you.

Proudly powered by WordPress

Sakshi Gawande

Sakshi Gawande

Leave a Comment

Your email address will not be published. Required fields are marked *

Suggested Article

%d bloggers like this: