thesnowmancometh
7/28/2018 - 8:32 PM

Terraform Atlantis deployment to DigitialOcean

This snippet will deploy Atlantis to DigitalOcean using Terraform.

#!/bin/bash

set -e
set -x
set -u
set -C

function apt-get-install {
    apt-get clean
    apt-get update
    apt-get install -f -yq zip unzip
  }


function install_terraform {
  readonly TF_VERSION="0.11.7"
  CURDIR=`pwd`

  if [[ $(which terraform >/dev/null && terraform version | head -n 1 | cut -d ' ' -f 2) == "v$TF_VERSION" ]]; then
    echo "Terraform v$TF_VERSION already installed; Skipping"
    exit
  fi

  echo Fetching Terraform...
  cd /tmp/
  wget -q https://releases.hashicorp.com/terraform/$TF_VERSION/terraform_"$TF_VERSION"_linux_amd64.zip -O tf.zip
  echo Installing Terraform...
  unzip tf.zip
  sudo chmod +x terraform
  sudo mv terraform /usr/bin/terraform
  cd $CURDIR
}

function open_firewall {
  ufw allow 4141
  ufw allow 80
  ufw allow 443
}

function launch_atlantis {
  systemctl enable atlantis.service
  systemctl start  atlantis.service
}

function main {
  open_firewall
  apt-get-install
  install_terraform
  launch_atlantis
}

main
[Unit]
Description = "Atlantis"

[Service]
# Stop consul will not mark node as failed but left
KillSignal=INT
ExecStart=/usr/bin/docker run -p 4141:4141 hootsuite/atlantis server --gh-user=robbiemckinstry --gh-token=<redacted>
Restart=always
ExecStopPost=sleep 5
# First, add a variable called do_token,
# which is populated by my environment
# see .config/fish/config.fish for the value
variable "do_token" {
  default = <redacted>
  type = "string"
  description = "digitalocean token"
}

variable "templates" {
    default     = "templates"
    type        = "string"
    description = "directory of all files needed to be templated by TF"
}

variable "file_artifacts" {
    default     = "file_artifacts"
    type        = "string"
    description = "file actifacts is the output directory from templating everything"
}

variable "ssh_location_public" {
    default = "/ssh_keys/id_rsa.pub"
    type = "string"
    description = "where them ssh keys at?"
}

variable "ssh_location_private" {
    default = "/ssh_keys/id_rsa"
    type = "string"
    description = "where them ssh keys at?"
}

# Configure the DigitalOcean Provider
provider "digitalocean" {
  token = "${var.do_token}"
}

# Link my local ssh key
resource "digitalocean_ssh_key" "default" {
  name       = "tiny-macbook"
  public_key = "${file("${var.ssh_location_public}")}"
}

# Create the master node
resource "digitalocean_droplet" "atlantis" {
    image              = "docker-16-04"
    size               = "1gb"
    region             = "nyc3"
    name               = "atlantis"
    ssh_keys           = ["${digitalocean_ssh_key.default.fingerprint}"]
    ipv6               = true
    monitoring         = true
    private_networking = true
}

resource "template_dir" "custom_templates" {
    source_dir      = "${var.templates}"
    destination_dir = "${var.file_artifacts}"

    vars {
        master_ip  = "${digitalocean_droplet.atlantis.ipv4_address}"
    }
}

# Provision the nodes once
resource "null_resource" "provision_atlantis" {
    depends_on = ["digitalocean_droplet.atlantis", "template_dir.custom_templates"]

    triggers {
        do_node = "${digitalocean_droplet.atlantis.ipv4_address}"
    }

    connection {
        private_key = "${file("${var.ssh_location_private}")}"
        host =  "${digitalocean_droplet.atlantis.ipv4_address}"
    }

    provisioner "file" {
        source      = "${var.file_artifacts}/atlantis.service"
        destination = "/etc/systemd/system/atlantis.service"
    }

    provisioner "file" {
        source      = "${var.file_artifacts}/on_boot.sh"
        destination = "/tmp/on_boot.sh"
    }

    provisioner "remote-exec" {
        inline = [
            "chmod +x /tmp/on_boot.sh",
            "/tmp/on_boot.sh"
        ]
    }
}

output "atlantis_ip" {
  value = "${digitalocean_droplet.atlantis.ipv4_address}"
}