{
"variables": {
"aws_access_key": "",
"aws_secret_key": ""
},
"builders": [{
"type": "amazon-ebs",
"access_key": "{{user `aws_access_key`}}",
"secret_key": "{{user `aws_secret_key`}}",
"region": "eu-central-1",
"source_ami": "ami-5900cc36", # debian Jessie
"instance_type": "t2.micro",
"ssh_username": "admin",
"ami_name": "sandbox_base_packer_{{timestamp}}",
"subnet_id": "subnet-b12121212",
"security_group_id": "sg-12121212",
"associate_public_ip_address": false
}],
"provisioners": [{
"type": "shell",
"inline": [
"echo 'Acquire::ForceIPv4 \"true\";' | sudo tee /etc/apt/apt.conf.d/99force-ipv4",
"echo 'deb http://cloudfront.debian.net/debian jessie-backports main' |sudo tee /etc/apt/sources.list.d/backports.list",
"sudo apt-get update",
"sudo apt-get -t jessie-backports install -y ansible"
]
}, {
"type": "ansible-local",
"playbook_file": "essentials.yml",
"command": "PYTHONUNBUFFERED=1 ansible-playbook"
}],
"post-processors": [
[
{
"output": "/tmp/manifest.json",
"strip_path": true,
"type": "manifest"
}
]
]
}
Ansible playbook used by this packer template
---
- hosts: all
become: true
vars:
vimrc: |
syntax on
set ts=8
set noai
set ruler
set tw=80
set t_Co=256
colorscheme molokai-transparent
set laststatus=2
loadpowerline: |
powerline-daemon -q
POWERLINE_BASH_CONTINUATION=1
POWERLINE_BASH_SELECT=1
tmuxconf: |
set-option -g prefix2 C-q
set-option -g default-terminal "screen-256color"
bashrc: |
EDITOR=vim
VISUAL=$EDITOR
export EDITOR VISUAL
myuser: bob
mykey: |
ssh-rsa key n_1
ssh-rsa key n_2
tasks:
- name: installs essential tools
apt: name={{item}} state=installed
with_items:
- vim-nox
- sudo
- tmux
- build-essential
- git
- python
- python-pip
## sudo
- name: make sudo group passwordless
blockinfile:
dest: /etc/sudoers
block: |
%sudo ALL=(ALL) NOPASSWD: ALL
## shell
- name: install powerline from pip
pip: name=powerline-status
- file:
path: "/home/{{myuser}}/.profile.d"
state: directory
mode: 0755
- name: record module path
command: python -c "import powerline, os; print(os.path.dirname(powerline.__file__))"
register: powerlinepath
failed_when: powerlinepath is undefined
- name: create powerline autoload
copy: content="{{loadpowerline}}\n. {{powerlinepath.stdout_lines[0]}}/bindings/bash/powerline.sh\n" dest="/home/{{myuser}}/.profile.d/powerline"
- name: append profile.d autoload
copy: content="{{bashrc}}\n[ -d ~/.profile.d ] && for s in ~/.profile.d/*;do . $s; done" dest="/home/{{myuser}}/.profile"
## vim
- name: fetch vim themes
git:
repo: https://github.com/hugoroy/.vim
dest: "/home/{{myuser}}/.vim"
- name: create basic vimrc
copy: content="{{vimrc}}\nset rtp+={{powerlinepath.stdout_lines[0]}}/bindings/vim\n" dest="/home/{{myuser}}/.vimrc"
## tmux
- name: powerline support for tmux
copy: content="{{tmuxconf}}\nsource {{powerlinepath.stdout_lines[0]}}/bindings/tmux/powerline.conf\n" dest="/home/{{myuser}}/.tmux.conf"
## chown user
- name: user add
user:
name: "{{myuser}}"
groups: sudo
shell: /bin/bash
- name: create .ssh directory
file:
path: "/home/{{myuser}}/.ssh"
state: directory
mode: 0700
- name: copy SSH pubkey
copy:
content: "{{mykey}}"
dest: "/home/{{myuser}}/.ssh/authorized_keys"
mode: 0600
- name: chown user
file:
path: "/home/{{myuser}}"
owner: "{{myuser}}"
recurse: yes
Create the AMI:
$ packer build basic.tpl
from troposphere import Base64, Join, Split
from troposphere import Parameter, Ref, Template, Tags
import troposphere.ec2 as ec2
import sys
params = {
'AmiId': 'AMI Id',
'InstanceName': 'Name tag of the instance',
'SecurityGroup': 'Security Group' ,
'KeyName': 'SSH Key Name' ,
'InstanceType': 'Instance Type',
'SubnetA': 'Subnet A',
}
t = Template()
for p in params.keys():
vars()[p] = t.add_parameter(Parameter(
p,
Type = "String",
Description = params[p]
))
for n in range(int(sys.argv[1])):
if n == 0:
name = 'master'
else:
name = 'slave_{0}'.format(n)
t.add_resource(ec2.Instance(
"Ec2Instance{0}".format(n),
ImageId = Ref(AmiId),
InstanceType = Ref(InstanceType),
KeyName = Ref(KeyName),
SecurityGroupIds = Split(',', Ref(SecurityGroup)),
SubnetId = Ref(SubnetA),
Tags = Tags(Name = Join('', [Ref(InstanceName), name])),
))
print(t.to_json())
Parameters file:
[
{
"ParameterKey": "InstanceType",
"ParameterValue": "t2.micro",
"UsePreviousValue": false
},
{
"ParameterKey": "AmiId",
"ParameterValue": "ami-12121212",
"UsePreviousValue": false
},
{
"ParameterKey": "KeyName",
"ParameterValue": "test-eu-central-1",
"UsePreviousValue": false
},
{
"ParameterKey": "SecurityGroup",
"ParameterValue": "sg-12121212,sg-21212121",
"UsePreviousValue": false
},
{
"ParameterKey": "SubnetA",
"ParameterValue": "subnet-12121212",
"UsePreviousValue": false
},
{
"ParameterKey": "InstanceName",
"ParameterValue": "my_test_instance_",
"UsePreviousValue": false
}
]
Generate CloudFormation template:
$ python ec2instance.py 3 > cf-ec2instances.json
Create the stack:
$ aws cloudformation create-stack --stack-name my_sandbox --parameters file://cf-ec2instances.params --template-body file://cf-ec2instances.json
- Fetch dynamic inventory addon ec2.py
- Make sure to have an
ec2.ini
file containing:
[ec2]
# example
regions = eu-central-1
destination_variable = private_dns_name
vpc_destination_variable = private_ip_address
Create the following playbook:
---
- hosts: tag_Name_my_test_instance*
become: true
tasks:
- apt_key:
url: https://repo.saltstack.com/apt/debian/8/amd64/latest/SALTSTACK-GPG-KEY.pub
state: present
- apt_repository:
repo: deb http://repo.saltstack.com/apt/debian/8/amd64/latest jessie main
state: present
- apt: update_cache=true
- hosts: tag_Name_my_test_instance_master
become: true
tasks:
- apt: name=salt-master state=installed
- hosts: tag_Name_my_test_instance_slave*
become: true
tasks:
- apt: name=salt-minion state=installed
- blockinfile:
block: "master: salt"
dest: "/etc/salt/minion"
- name: update hosts
blockinfile:
block: "{{groups['tag_Name_my_test_instance_master'][0]}} salt"
dest: "/etc/hosts"
Deploy the playbook:
$ ansible-playbook -i ec2.py salt.yml