Our highest priority is to satisfy the customer
through early and continuous delivery of valuable software.
Create a repetable, reliable process for releasing software
Automate almost everything
Keep everything in version control
If it hurts, do it more frequently, and bring the pain forward
Build quality in
Done means released
Continuous Improvement
variables = JSON.parse(File.read("variables.json"))
args_name = ""
args_value = []
for i in 2..variables.count-1
args_name = args_name + "${#{i-1}} "
args_value.push(variables.values[i])
end
Vagrant.configure("2") do |config|
config.vm.box = "woohoolabs/api"
config.ssh.forward_agent = true
config.ssh.port = variables["ssh_port"]
config.exec.commands %w(go), directory: "/website"
config.vm.provider :virtualbox do |vb, override|
override.vm.network "private_network", ip: variables["private_ip"]
override.vm.network "forwarded_port", guest: 22, host: variables["ssh_port"], protocol: "tcp"
override.vm.synced_folder "./", "/vagrant", disabled: true
override.vm.synced_folder "./", "/website", owner: "vagrant", group: "www-data", mount_options: ["dmode=775,fmode=775"]
end
config.vm.provision :shell do |sh|
sh.inline = "go cd provision #{args_name}| tee -a ~/provision.log"
sh.args = args_value
sh.privileged = false
end
end
{
"variables": {
"api_box_name": "api",
"api_box_version": "2.7",
"api_web_project_root_path": "/website",
"api_web_project_web_absolute_path": "/website/web",
"api_web_project_var_absolute_path": "/etc/website/var",
"api_dev_web_box_name": "api-dev",
"api_dev_web_build_env": "dev",
"api_dev_web_ssh_user": "vagrant",
"api_dev_web_ssh_password": "vagrant",
"api_prod_web_box_name": "api-prod-web",
"api_prod_web_build_env": "prod",
"api_prod_web_ssh_user": "ubuntu",
"api_prod_web_ssh_port": "22",
"api_prod_web_aws_access_key": "{{env `AWS_ACCESS_KEY`}}",
"api_prod_web_aws_secret_key": "{{env `AWS_SECRET_KEY`}}",
"api_prod_web_aws_region": "eu-central-1",
"api_prod_web_aws_source_ami": "ami-70f9cb6d",
"api_prod_web_aws_instance_type": "t2.micro"
},
"builders": [
{
"name": "api-prod-web",
"ami_name": "{{user `api_prod_web_box_name`}}-{{user `api_box_version`}}-{{ timestamp }}",
"ami_description": "Ubuntu 14.04 64 bit web server for Woohoo Labs. API",
"type": "amazon-ebs",
"access_key": "{{user `api_prod_web_aws_access_key`}}",
"secret_key": "{{user `api_prod_web_aws_secret_key`}}",
"region": "{{user `api_prod_web_aws_region`}}",
"source_ami": "{{user `api_prod_web_aws_source_ami`}}",
"instance_type": "{{user `api_prod_web_aws_instance_type`}}",
"ssh_username": "{{user `api_prod_web_ssh_user`}}",
"ssh_port": "{{user `api_prod_web_ssh_port`}}",
"enhanced_networking": true,
"tags": {
"build_env": "prod",
"build_type": "web",
"build_version": "{{user `api_box_version`}}",
"build_time": "{{ timestamp }}"
}
},
{
"name": "api-dev",
"type": "virtualbox-iso",
"boot_command": [
"<esc><wait><esc><wait><enter><wait>",
"/install/vmlinuz",
" auto",
" console-setup/ask_detect=false",
" console-setup/layoutcode=hu",
" console-setup/modelcode=pc105",
" debconf/frontend=noninteractive",
" debian-installer=en_US",
" fb=false",
" initrd=/install/initrd.gz",
" kbd-chooser/method=hu",
" keyboard-configuration/layout=HUNGARY",
" keyboard-configuration/variant=HUNGARY",
" locale=en_US",
" hostname={{user `api_box_name`}}.{{user `api_dev_web_build_env`}}",
" netcfg/get_domain=site",
" netcfg/get_hostname=vagrant",
" noapic",
" preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg",
"<enter><wait>",
" -- <wait>"
],
"boot_wait": "10s",
"disk_size": 8000,
"guest_additions_path": "VBoxGuestAdditions_{{.Version}}.iso",
"guest_os_type": "Ubuntu_64",
"http_directory": "provisioners",
"iso_urls": [
"http://releases.ubuntu.com/14.04/ubuntu-14.04.2-server-amd64.iso",
"http://hu.releases.ubuntu.com/14.04/ubuntu-14.04.2-server-amd64.iso"
],
"iso_checksum": "3bfa6eac84d527380d0cc52db9092cde127f161e",
"iso_checksum_type": "sha1",
"output_directory": "{{user `api_dev_web_box_name`}}",
"shutdown_command": "echo 'vagrant'|sudo -S -E shutdown -P now",
"ssh_username": "{{user `api_dev_web_ssh_user`}}",
"ssh_password": "{{user `api_dev_web_ssh_password`}}",
"ssh_port": 22,
"ssh_wait_timeout": "10000s",
"headless": true,
"hard_drive_interface": "sata",
"vboxmanage": [
[
"modifyvm",
"{{user `api_dev_web_box_name`}}",
"--memory",
"1024"
],
[
"modifyvm",
"{{user `api_dev_web_box_name`}}",
"--cpus",
"2"
]
],
"virtualbox_version_file": ".vbox_version",
"vm_name": "{{user `api_dev_web_box_name`}}"
}
],
"post-processors": [
{
"type": "vagrant",
"output": "{{user `api_box_name`}}-{{user `api_box_version`}}-{{ .Provider }}.box"
}
],
"provisioners": [
{
"type": "shell",
"scripts": [
"provisioners/project/setup-envvars-build.sh",
"provisioners/server-web/add-dependencies.sh",
"provisioners/os/setup-os.sh",
"provisioners/os/setup-sshd.sh",
"provisioners/os/setup-sudoers.sh"
],
"execute_command": "echo 'vagrant'|{{.Vars}} sudo -S -E bash '{{.Path}}' 2>&1 | tee -a ~/build.log",
"override": {
"api-prod-web": {
"environment_vars": [
"BUILD_NAME={{user `api_prod_web_box_name`}}",
"BUILD_ENV={{user `api_prod_web_build_env`}}",
"BUILD_VERSION={{user `api_box_version`}}",
"SSH_USER={{user `api_prod_web_ssh_user`}}",
"PROJECT_DIR={{user `api_web_project_root_path`}}",
"WEB_DIR={{user `api_web_project_web_absolute_path`}}",
"VAR_DIR={{user `api_web_project_var_absolute_path`}}"
]
},
"api-dev": {
"environment_vars": [
"BUILD_NAME={{user `api_dev_web_box_name`}}",
"BUILD_ENV={{user `api_dev_web_build_env`}}",
"BUILD_VERSION={{user `api_box_version`}}",
"SSH_USER={{user `api_dev_web_ssh_user`}}",
"PROJECT_DIR={{user `api_web_project_root_path`}}",
"WEB_DIR={{user `api_web_project_web_absolute_path`}}",
"VAR_DIR={{user `api_web_project_var_absolute_path`}}"
]
}
}
},
{
"type": "shell",
"override": {
"api-prod-web": {
"scripts": [
"provisioners/os/setup-amazon.sh",
"provisioners/server-web/install-mysql-client.sh"
]
},
"api-dev": {
"scripts": [
"provisioners/os/setup-vagrant.sh",
"provisioners/server-web/install-mysql-server.sh"
]
}
},
"execute_command": "echo 'vagrant'|{{.Vars}} sudo -S -E bash '{{.Path}}' 2>&1 | tee -a ~/build.log"
},
{
"type": "shell",
"scripts": [
"provisioners/server-web/install-locales.sh",
"provisioners/server-web/install-web.sh",
"provisioners/server-web/install-beanstalkd.sh",
"provisioners/server-web/install-redis.sh",
"provisioners/server-web/install-mail.sh",
"provisioners/server-web/install-dev.sh",
"provisioners/project/setup-project.sh",
"provisioners/os/minimize.sh",
"provisioners/project/get-build-version.sh"
],
"execute_command": "echo 'vagrant'|{{.Vars}} sudo -S -E bash '{{.Path}}' 2>&1 | tee -a ~/build.log"
}
]
}
provider "aws" {
access_key = "${var.aws_access_key}"
secret_key = "${var.aws_secret_key}"
region = "${var.aws_region}"
}
resource "aws_security_group" "web" {
name = "api_staging_security_group"
description = "Default security group for the API"
# SSH access from anywhere
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# HTTP access from anywhere
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# HTTPS access from anywhere
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# MySQL access from anywhere
ingress {
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# HTTP access to anywhere
egress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# HTTPS access to anywhere
egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# MySQL access to anywhere
egress {
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_instance" "web" {
connection {
user = "ubuntu"
key_file = "${var.aws_key_path}"
}
instance_type = "${var.aws_instance_type}"
ami = "${var.aws_ami}"
key_name = "${var.aws_key_name}"
security_groups = ["${aws_security_group.web.name}"]
tags {
Name = "api-${var.app_env}-web-${var.deploy_time}"
App_Env = "${var.app_env}"
Deploy_Time = "${var.deploy_time}"
Deploy_Commit = "${var.deploy_commit}"
}
# Copies the Go script to the machine - cwd must be in the Terraform config folder
provisioner "file" {
source = "../../../../go"
destination = "~/go"
}
provisioner "remote-exec" {
inline = [
"chmod 750 ~/go",
"~/go cd checkout ${var.deploy_commit} /website ${var.bitbucket_username} ${var.bitbucket_password} | tee -a /home/ubuntu/provision.log",
"chmod 750 /website/go & rm ~/go & chmod 750 -R /website/app/build/images/provisioners",
"go cd provision ${var.app_env} ${var.beanstalkd_host} ${var.beanstalkd_port} ${aws_db_instance.web.address} ${aws_db_instance.web.port} ${var.db_common_name} ${var.db_common_user} ${var.db_common_password} ${var.redis_scheme} ${var.redis_host} ${var.redis_port} ${var.open_weather_map_api_key} ${var.blackfire_server_id} ${var.blackfire_server_token} ${var.blackfire_client_id} ${var.blackfire_client_token} | tee -a /home/ubuntu/provision.log",
"go cd auto-migrate '${var.db_root}' '${var.db_root_password}' | tee -a /home/ubuntu/provision.log"
]
}
}
resource "aws_db_instance" "web" {
identifier = "api-staging-rds"
allocated_storage = 5
engine = "mysql"
engine_version = "5.6.22"
instance_class = "db.t2.micro"
username = "${var.db_root}"
password = "${var.db_root_password}"
parameter_group_name = "default.mysql5.6"
availability_zone= "${var.aws_region}b"
backup_retention_period = 0
maintenance_window = "fri:08:22-fri:08:52"
multi_az = false
port = "${var.db_port}"
}
output "web-zone" {
value = "${aws_instance.web.availability_zone}"
}
output "web-ip" {
value = "${aws_instance.web.public_ip}"
}
output "web-dns" {
value = "${aws_instance.web.public_dns}"
}
output "db-address" {
value = "${aws_db_instance.web.address}"
}
People don't scale - machines do
Jeff Atwood