Dynamically creating Amazon EC2 instances using python-terraform

Posted: February 20, 2018 in Amazon Web Services (AWS), Linux, terraform

In previous post we deployed single machine by python script using terraform plugin.

In this one we’ll go through JSON file, extract username and count of instances and based on it create x instances for x user.

In this file for Djukes one instance will be created, for JWilson 2, for eflame 3.

JSON file:

{
"squadName": "Super hero squad",
"homeTown": "Metro City",
"formed": 2016,
"secretBase": "Super tower",
"active": true,
"customers": [
{
"name": "Molecule Man",
"age": 29,
"email": "DJukes@gmail.com",
"instances": 1,
"powers": [
"Radiation resistance",
"Turning tiny",
"Radiation blast"
]
},
{
"name": "Madame Uppercut",
"age": 39,
"email": "JWilson@gmail.com",
"instances": 2,
"powers": [
"Million tonne punch",
"Damage resistance",
"Superhuman reflexes"
]
},
{
"name": "Eternal Flame",
"age": 1000000,
"email": "eflame@gmail.com",
"instances": 3,
"powers": [
"Immortality",
"Heat Immunity",
"Inferno",
"Teleportation",
"Interdimensional travel"
]
}
]
}

Terraform files:

Get public IP:

output.tf

output "id" {
description = "List of IDs of instances"
value = ["${aws_instance.win-example.*.public_ip}"]
}

Security group-for each user allow-all will be replaced with particular user,so for every user new Security group will be created-name of security group will be username

resource "aws_security_group" "allow-all" {
name="allow-all"
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 0
to_port = 6556
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
tags {
Name = "allow-RDP"
}
}

vars.tf

variable "AWS_REGION" {
  default = "eu-west-1"
}
variable "WIN_AMIS" {
  type = "map"
  default = {
    us-east-1 = "ami-30540427"
    us-west-2 = "ami-9f5efbff"
    eu-west-1 = "ami-cc821eb5"
  }
}


variable "count" {

default="1"

}



variable "PATH_TO_PRIVATE_KEY" {
  default = "mykey"
}
variable "PATH_TO_PUBLIC_KEY" {
  default = "mykey.pub"
}
variable "INSTANCE_USERNAME" {
#  default = "Terraform"
}
variable "INSTANCE_PASSWORD" {
 default="Passw0rd012345"

}

windows.tf

resource "aws_instance" "win-example" {
  ami = "${lookup(var.WIN_AMIS, var.AWS_REGION)}"
  instance_type = "t2.medium"
  count="${var.count}"
  lifecycle {
ignore_changes="ami"

}

   
  vpc_security_group_ids=["${aws_security_group.allow-all.id}"]
#key_name = "${aws_key_pair.mykey.key_name}"
  user_data = <
net user ${var.INSTANCE_USERNAME} '${var.INSTANCE_PASSWORD}' /add /y
net localgroup administrators ${var.INSTANCE_USERNAME} /add

winrm quickconfig -q
winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="300"}'
winrm set winrm/config '@{MaxTimeoutms="1800000"}'
winrm set winrm/config/service '@{AllowUnencrypted="true"}'
winrm set winrm/config/service/auth '@{Basic="true"}'

netsh advfirewall firewall add rule name="WinRM 5985" protocol=TCP dir=in localport=5985 action=allow
netsh advfirewall firewall add rule name="WinRM 5986" protocol=TCP dir=in localport=5986 action=allow

net stop winrm
sc.exe config winrm start=auto
net start winrm

EOF

  provisioner "file" {
    source = "test.txt"
    destination = "C:/test.txt"
  }
  connection {
    type = "winrm"
    timeout = "10m"
    user = "${var.INSTANCE_USERNAME}"
     password = "${var.INSTANCE_PASSWORD}"
      
}

tags {
Name="${format("${var.INSTANCE_USERNAME}-%01d",count.index+1)}"

}
}

For every user new folder will be created, all above terraform files will be copied to every user’s folder, one copied sg.tf and windows.tf files will be searched for “allow-all” and replaced with username variable,it is needed because for each user new security group needs to be created

#!/bin/python
import sys
import json
import os.path
import shutil
from os import mkdir
from pprint import pprint
from python_terraform import *

#open JSON file
json_data=open('./my.json')
data = json.load(json_data)

json_data.close()

 

#Function which will create instances,parameters are username and count of instances fetched from JSON file

def myfunc():

tf = Terraform(working_dir=final_path, variables={'count':count,'INSTANCE_USERNAME':user})
tf.plan(no_color=IsFlagged, refresh=True, capture_output=False)
approve = {"auto-approve": True}
print(tf.init(reconfigure=True))
print(tf.plan())
print(tf.apply(**approve))
return

 

 

 

# sweep through JSON file and store username and number of instances into user and count variables
for i in range (0, len (data['customers'])):
#print data['customers'][i]['email']
k=data['customers'][i]['email']
#print(k.split('@')[0])
user=k.split('@')[0]
#print(user)
count=data['customers'][i]['instances']
#print(count)
#enter = int(input('Enter number of instances: '))

#define "root" directory
start_path="/home/ja/terraform-course/demo-2b/"

#in order to avoid instance recreation,folder for each user needs to be created


#define subdirectories named by user and create it it folder doesn't exist
final_path=os.path.join(start_path,user)
if not os.path.exists(final_path):
os.makedirs(final_path)
#copy terraform files to each newly created folder for user

shutil.copy2('./vars.tf', final_path)
shutil.copy2('./sg.tf', final_path)
shutil.copy2('./windows.tf', final_path)
shutil.copy2('./provider.tf', final_path)
shutil.copy2('./test.txt', final_path)
shutil.copy2('./output.tf', final_path)

 

#for each user new security group needs to be created.Name of SG will be username
final=os.path.join(final_path,'sg.tf')
final1=os.path.join(final_path,'windows.tf')

#replace current name (allow-all) with variable username in sg.tf and windows.tf files
with open(final, 'r') as file :
filedata = file.read()
filedata = filedata.replace('allow-all', user)
with open(final, 'w') as file:
file.write(filedata)
with open(final1, 'r') as file :
filedata = file.read()
filedata = filedata.replace('allow-all', user)
with open(final1, 'w') as file:
file.write(filedata)

#call function for running terraform
myfunc()

 

#in each user folder open terraform.tfstate file and extract public IP to variable ip

final2=os.path.join(final_path,'terraform.tfstate')
json_data=open(final2)
data1 = json.load(json_data)
json_data.close()
#write Public IP,username and password to /home/ja/terraform-course/demo-2b/.txt file

filename="/home/ja/terraform-course/demo-2b/"+user+".txt"
print(filename)
for i in range (0, len (data1['modules'])):
ip=','.join(data1['modules'][i]['outputs']['id']['value'])
sys.stdout = open(filename,'wt')
print("Username is:"+" "+ user+".Password is Passw0rd01234.IP addrress is:"+ip)

 

Advertisements
Comments
  1. Akki says:

    Hi , I need help in to create the following resources in AWS

    EC2 instance
    S3 Bucket

    By making use of userdata, echo some (ie ami-id, hostname etc) instance metadata to a file and copy that file to the s3 bucket.

    The terraform command should look as follows
    terraform apply –var ‘aws_access_key_id=’ –var
    ‘aws_secret_access_key=’ -var ‘bucket_name=

    Constraints
    Do not use the aws_instance resource provided by terraform, rather, make use of autoscaling groups
    Do not commit any aws credentials to source control of any kind.
    No aws access key id or secret access key information is to be present on the ec2 instance
    Access to the S3 bucket from the EC2 instance should be done via Instance Roles

    Liked by 1 person

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s