env/linux-arm64/aws: add linux-arm64-aws builder image

This adds the ability for linux-arm64 builder images to be
created on AWS. Instead of writing a bash script which would create
an image with all of the dependencies on it, this experiments with
using packer to create the image.

The image is configured to install and daemonize rundockerbuildlet.
Rundockerbuildlet will download and run the latest stage0 image.
Stage0 then downloads the latest buildlet and begins processing jobs.

A follow-up change will enable rundockerbuildlet to initialize the
buildlet without setting it in reverse mode.

Updates golang/go#36841

Change-Id: Iee07c2600e2b91d34f5e6a1e062f763833d79904
Reviewed-on: https://go-review.googlesource.com/c/build/+/228799
Run-TryBot: Carlos Amedee <carlos@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Alexander Rakoczy <alex@golang.org>
diff --git a/cmd/buildlet/stage0/stage0.go b/cmd/buildlet/stage0/stage0.go
index 333cf52..47a6e48 100644
--- a/cmd/buildlet/stage0/stage0.go
+++ b/cmd/buildlet/stage0/stage0.go
@@ -232,7 +232,6 @@
 		}
 		sleepFatalf("Error running buildlet: %v", err)
 	}
-
 }
 
 // reverseHostTypeArgs returns the default arguments for the buildlet
diff --git a/env/linux-arm64/aws/Dockerfile b/env/linux-arm64/aws/Dockerfile
new file mode 100644
index 0000000..f81c5f4
--- /dev/null
+++ b/env/linux-arm64/aws/Dockerfile
@@ -0,0 +1,26 @@
+# Copyright 2020 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+FROM debian:buster
+
+ENV DEBIAN_FRONTEND noninteractive
+
+RUN apt-get update && \
+    apt-get install --yes \
+          gcc curl strace \
+          ca-certificates netbase \
+          procps lsof psmisc \
+          openssh-server
+
+RUN mkdir /usr/local/go-bootstrap && \
+    curl --silent https://storage.googleapis.com/go-builder-data/gobootstrap-linux-arm64.tar.gz | \
+    tar -C /usr/local/go-bootstrap -zxv
+
+ENV GOROOT_BOOTSTRAP /usr/local/go-bootstrap
+RUN curl -o  /usr/local/bin/stage0 https://storage.googleapis.com/go-builder-data/buildlet-stage0.linux-arm64 && \
+    chmod +x /usr/local/bin/stage0
+
+ENV GO_BUILDER_ENV host-linux-arm64-aws
+
+CMD ["/usr/local/bin/stage0"]
diff --git a/env/linux-arm64/aws/Makefile b/env/linux-arm64/aws/Makefile
new file mode 100644
index 0000000..20a2f30
--- /dev/null
+++ b/env/linux-arm64/aws/Makefile
@@ -0,0 +1,26 @@
+# Copyright 2020 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# Compiled stage0 binary must be in working dir.
+
+STAGING_BUCKET=dev-go-builder-data
+PROD_BUCKET=go-builder-data
+
+staging: Dockerfile
+	docker build --build-arg -t gobuilder-arm64-aws:latest .
+
+prod: Dockerfile
+	docker build --build-arg -t gobuilder-arm64-aws:latest .
+
+env-var-check:
+ifndef AWS_ACCESS_KEY_ID
+	$(error AWS_ACCESS_KEY_ID env var is not set)
+endif
+
+ifndef AWS_SECRET_ACCESS_KEY
+	$(error AWS_SECRET_ACCESS_KEY env var is not set)
+endif
+
+create-aws-image: env-var-check
+	packer build packer_image_aws_arm64.json
diff --git a/env/linux-arm64/aws/README.md b/env/linux-arm64/aws/README.md
new file mode 100644
index 0000000..cb6ca98
--- /dev/null
+++ b/env/linux-arm64/aws/README.md
@@ -0,0 +1,41 @@
+# AWS Linux ARM64 Builders
+
+## Machines
+
+The AWS builders use the a1 instance types which are arm64 based machines of varying specifications.
+The base type used will be a1.xlarge 4 vCPUs, 8192 MiB.
+
+## Machine Image
+
+Machine images are stored on AWS EBS service as a snapshot. New VMs can use the snapshot as an image
+by providing the AMI ID as the base image when a new VM is created. The machine image will be configured
+to install and initialize rundockerbuildlet.
+
+### Creating a New Image
+
+Requirements:
+
+Two environmental variables are required to be set before initiating the command:
+`AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` should be set with the appropriate values.
+
+The [packer](https://www.packer.io) binary should be in `PATH`.
+
+Command:
+
+`make create-aws-image`
+
+or
+
+`AWS_ACCESS_KEY_ID=<id> AWS_SECRET_ACCESS_KEY=<secret> make create-aws-image`
+
+## Buildlet Image
+
+Buildlet images with stage0 installed can be created via:
+
+Prod:
+
+`make prod`
+
+Staging:
+
+`make staging`
diff --git a/env/linux-arm64/aws/packer_image_aws_arm64.json b/env/linux-arm64/aws/packer_image_aws_arm64.json
new file mode 100644
index 0000000..369991a
--- /dev/null
+++ b/env/linux-arm64/aws/packer_image_aws_arm64.json
@@ -0,0 +1,49 @@
+{
+  "variables": {
+    "aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}",
+    "aws_secret_key": "{{env `AWS_SECRET_ACCESS_KEY`}}",
+    "region": "us-east-2"
+  },
+  "builders": [
+    {
+      "type": "amazon-ebs",
+      "access_key": "{{user `aws_access_key`}}",
+      "ami_name": "go-linux-arm64-{{timestamp}}",
+      "ami_description": "Image for linux-arm64 Go builder",
+      "instance_type": "a1.medium",
+      "region": "{{user `region`}}",
+      "secret_key": "{{user `aws_secret_key`}}",
+      "source_ami": "ami-0b1808bb4e7ed5ff5",
+      "decode_authorization_messages": true,
+      "ssh_username": "admin",
+      "tags": {
+        "Name": "Debian",
+        "Created": "{{isotime \"2006-01-02\"}}",
+        "OS": "Debian 10 Buster",
+        "Release": "Latest",
+        "Base_AMI_Name": "{{ .SourceAMIName }}",
+        "Extra": "{{ .SourceAMITags.TagName }}",
+        "Description": "{{user `description`}}"
+      },
+      "launch_block_device_mappings": [
+        {
+          "device_name": "/dev/xvda",
+          "volume_size": 10,
+          "volume_type": "gp2",
+          "delete_on_termination": true
+        }
+      ]
+    }
+  ],
+  "provisioners": [
+    {
+      "type": "file",
+      "source": "./rundockerbuildlet.service",
+      "destination": "/tmp/rundockerbuildlet.service"
+    },
+    {
+      "type": "shell",
+      "script": "./prepare_image.sh"
+    }
+  ]
+}
diff --git a/env/linux-arm64/aws/prepare_image.sh b/env/linux-arm64/aws/prepare_image.sh
new file mode 100644
index 0000000..56ab80b
--- /dev/null
+++ b/env/linux-arm64/aws/prepare_image.sh
@@ -0,0 +1,63 @@
+#!/usr/bin/env bash
+
+# Copyright 2020 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+#
+# Installs all dependencies for a Debian 10 linux arm64 Host.
+#
+
+set -euxo pipefail
+
+TMP_DIR="$(mktemp -d)"
+GO_PATH="$TMP_DIR/gopath"
+
+sudo apt-get update && sudo apt-get upgrade -y
+
+sudo apt-get install -y \
+	 apt-transport-https \
+	 ca-certificates \
+	 curl \
+	 gnupg-agent \
+	 gnupg2 \
+	 jq \
+	 software-properties-common
+
+curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
+
+sudo add-apt-repository "deb [arch=arm64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
+
+sudo apt-get update
+
+sudo apt-get install -y \
+	 docker-ce \
+	 docker-ce-cli \
+	 containerd.io
+
+# retrieve the latest version of Go
+GO_VERSION="$(curl -s https://golang.org/dl/?mode=json | jq --raw-output '.[0].version')"
+GO_PACKAGE="$GO_VERSION.linux-arm64.tar.gz"
+GO_SHA="$(curl -s https://golang.org/dl/?mode=json | jq --raw-output '.[0].files | map(select(.arch == "arm64")) | .[0].sha256')"
+
+# download Go package
+curl -o $TMP_DIR/$GO_PACKAGE" -L "https://golang.org/dl/$GO_PACKAGE"
+
+# verify sha256 shasum"
+echo "$GO_SHA $TMP_DIR/$GO_PACKAGE" | sha256sum --check --status
+
+# unzip Go package
+tar -xvf "$TMP_DIR/$GO_PACKAGE" -C "$TMP_DIR"
+
+# build rundockerbuildlet
+mkdir -p "$GO_PATH"
+GOPATH="$GO_PATH" "$TMP_DIR/go/bin/go" get -u golang.org/x/build/cmd/rundockerbuildlet
+GOPATH="$GO_PATH" "$TMP_DIR/go/bin/go" build -o "$TMP_DIR/rundockerbuildlet" golang.org/x/build/cmd/rundockerbuildlet
+sudo mv "$TMP_DIR/rundockerbuildlet" /usr/local/bin/rundockerbuildlet
+
+sudo mv /tmp/rundockerbuildlet.service /etc/systemd/user/rundockerbuildlet.service
+sudo systemctl enable /etc/systemd/user/rundockerbuildlet.service
+sudo systemctl start rundockerbuildlet
+
+# remove temporary directory
+rm -fr "$TMP_DIR"
diff --git a/env/linux-arm64/aws/rundockerbuildlet.service b/env/linux-arm64/aws/rundockerbuildlet.service
new file mode 100644
index 0000000..c6c1745
--- /dev/null
+++ b/env/linux-arm64/aws/rundockerbuildlet.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=Run Buildlets in Docker
+After=network.target
+
+[Install]
+WantedBy=network-online.target
+
+[Service]
+Type=simple
+ExecStart=/usr/local/bin/rundockerbuildlet \
+     -env=host-linux-arm64-aws \
+     -memory=7g \
+     -image=gobuilder-arm64-aws
+Restart=always
+RestartSec=2
+StartLimitInterval=0