From 26bc162bf9c66eaf26b9453e744136d8e580aa18 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 20 Mar 2020 14:56:03 +0000 Subject: Automate some of the Gitaly HA demo setup --- _support/terraform/.gitignore | 3 + _support/terraform/README.md | 60 ++++++++++ _support/terraform/create-demo-cluster | 69 ++++++++++++ _support/terraform/destroy-demo-cluster | 12 ++ _support/terraform/helper.rb | 12 ++ _support/terraform/main.tf | 189 ++++++++++++++++++++++++++++++++ _support/terraform/print-info | 12 ++ _support/terraform/terraform.tfvars.erb | 5 + 8 files changed, 362 insertions(+) create mode 100644 _support/terraform/.gitignore create mode 100644 _support/terraform/README.md create mode 100755 _support/terraform/create-demo-cluster create mode 100755 _support/terraform/destroy-demo-cluster create mode 100644 _support/terraform/helper.rb create mode 100644 _support/terraform/main.tf create mode 100755 _support/terraform/print-info create mode 100644 _support/terraform/terraform.tfvars.erb (limited to '_support/terraform') diff --git a/_support/terraform/.gitignore b/_support/terraform/.gitignore new file mode 100644 index 000000000..5a6a4426c --- /dev/null +++ b/_support/terraform/.gitignore @@ -0,0 +1,3 @@ +/.terraform* +/*.tfstate* +/terraform.tfvars diff --git a/_support/terraform/README.md b/_support/terraform/README.md new file mode 100644 index 000000000..75aafe8fa --- /dev/null +++ b/_support/terraform/README.md @@ -0,0 +1,60 @@ +# terraform for gitaly ha demo + +## Creating a demo cluster + +### 1. Install Google Cloud SDK + +- For most platforms, including macOS, use the [official + guide](https://cloud.google.com/sdk/docs/quickstarts) +- For Arch Linux, go to [this + AUR](https://aur.archlinux.org/packages/google-cloud-sdk) + +### 2. Install Terraform + +On macOS with homebrew, use `brew install terraform`. For other +platforms see [the Terraform download +page](https://www.terraform.io/downloads.html). + +### 3. Run the script + +``` +./create-demo-cluster +``` + +This will open a browser to sign into GCP if necessary. Terraform will +print a plan and ask you to confirm it before it creates anything in +GCP. + +When the script is done, `apt-get install gitlab-ee` is still busy +running in the background on your new VM's. + +### 4. Manually create a CloudSQL instance + +In principle Terraform can also create a CloudSQL instance for +Praefect but this is still work in progress. In the meantime, please +use the GCP web UI to create a CloudSQL Postgres instance for +Praefect. + +### 5. Use SSH to manually configure the hosts + +Updating the config for all the demo cluster hosts is not yet +automated. Please follow the documentation at +https://docs.gitlab.com/ee/administration/gitaly/praefect.html. + +To see the list of IP's for your machines, run: + +``` +./print-info +``` + +## Destroying a demo cluster + +When you run the command below Terraform will print a plan of things +to destroy, that you then have to confirm (or abort with Ctrl-C). + +Be careful! Double check how many nodes are being destroyed, and what +their names are. + +``` +./destroy-demo-cluster +``` diff --git a/_support/terraform/create-demo-cluster b/_support/terraform/create-demo-cluster new file mode 100755 index 000000000..4c59c9163 --- /dev/null +++ b/_support/terraform/create-demo-cluster @@ -0,0 +1,69 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'erb' +require 'etc' + +require_relative 'helper.rb' + +TFVARS = 'terraform.tfvars' + +def main + unless gcloud_appliction_default_logged_in? + run!(%w[gcloud auth application-default login]) + end + + unless terraform_initialized? + run!(%w[terraform init]) + end + + unless File.exist?(TFVARS) + render!(TFVARS, 'terraform.tfvars.erb') + end + + run!(%w[terraform apply]) +end + +def praefect_demo_cluster_name + default_name = "#{username}-#{Time.now.utc.strftime('%Y%m%d')}" + get_input('Enter a name for your demo cluster', default_name) +end + +def username + Etc.getlogin +end + +def ssh_pubkey + default_path = File.join(Etc.getpwnam(username).dir, '.ssh/id_rsa.pub') + pubkey_path = get_input('Enter the path to your SSH public key', default_path) + pubkey = File.read(pubkey_path).chomp + + unless pubkey.start_with?('ssh-') + # Protect against accidentally using the private key + abort "contents of #{path} do not look like an SSH pubkey" + end + + pubkey +end + +def get_input(prompt, default) + puts "#{prompt} (default: #{default})." + print "> " + + input = gets.chomp + input.empty? ? default : input +end + +def render!(file, template_path) + IO.write(file, ERB.new(File.read(template_path)).result(binding)) +end + +def gcloud_appliction_default_logged_in? + system( + *%w[gcloud auth application-default print-access-token], + out: '/dev/null', + err: '/dev/null' + ) +end + +main diff --git a/_support/terraform/destroy-demo-cluster b/_support/terraform/destroy-demo-cluster new file mode 100755 index 000000000..88e7f81f7 --- /dev/null +++ b/_support/terraform/destroy-demo-cluster @@ -0,0 +1,12 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require_relative 'helper.rb' + +def main + return unless terraform_any_machines? + + run!(%w[terraform destroy]) +end + +main diff --git a/_support/terraform/helper.rb b/_support/terraform/helper.rb new file mode 100644 index 000000000..eddccbf33 --- /dev/null +++ b/_support/terraform/helper.rb @@ -0,0 +1,12 @@ +require 'json' + +require_relative '../run.rb' + +def terraform_initialized? + File.exist?('.terraform') +end + +def terraform_any_machines? + state = JSON.parse(capture!(%w[terraform show -json])) + state.has_key?('values') +end diff --git a/_support/terraform/main.tf b/_support/terraform/main.tf new file mode 100644 index 000000000..66c6b594f --- /dev/null +++ b/_support/terraform/main.tf @@ -0,0 +1,189 @@ +variable "demo_region" { default = "us-east4" } +variable "demo_zone" { default = "us-east4-c" } +variable "praefect_demo_cluster_name" { } +variable "ssh_user" {} +variable "ssh_pubkey" { } +variable "os_image" { default = "ubuntu-os-cloud/ubuntu-1804-lts" } +variable "startup_script" { + default = <