env/linux-arm/aws, dashboard: add linux-arm-aws builder

This change adds the linux-arm-aws builder. This builder will be
started on a EC2 instance which will spawn a single instance
of the container. After the builder work is done, the instance will be
destroyed.

Updates golang/go#41867

Change-Id: I09d911c2f99d1dff8fe02feb458457e07e7d0cdd
Reviewed-on: https://go-review.googlesource.com/c/build/+/260797
Trust: Carlos Amedee <carlos@golang.org>
Run-TryBot: Carlos Amedee <carlos@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Alexander Rakoczy <alex@golang.org>
diff --git a/cmd/buildlet/stage0/Makefile b/cmd/buildlet/stage0/Makefile
index cc236a3..c5434ed 100644
--- a/cmd/buildlet/stage0/Makefile
+++ b/cmd/buildlet/stage0/Makefile
@@ -22,6 +22,10 @@
 	go install golang.org/x/build/cmd/upload
 	upload --verbose --osarch=$@ --file=go:golang.org/x/build/cmd/buildlet/stage0 --public --cacheable=false go-builder-data/$@
 
+buildlet-stage0.linux-arm: FORCE
+	go install golang.org/x/build/cmd/upload
+	upload --verbose --osarch=$@ --file=go:golang.org/x/build/cmd/buildlet/stage0 --public --cacheable=false go-builder-data/$@
+
 buildlet-stage0.linux-arm-scaleway: FORCE
 	go install golang.org/x/build/cmd/upload
 	upload --verbose --osarch=$@ --file=go:golang.org/x/build/cmd/buildlet/stage0 --public --cacheable=false go-builder-data/$@
diff --git a/dashboard/builders.go b/dashboard/builders.go
index 4ce2cbf..4f9b014 100644
--- a/dashboard/builders.go
+++ b/dashboard/builders.go
@@ -525,7 +525,17 @@
 		machineType:     "m6g.xlarge",
 		isEC2:           true,
 		env:             []string{"GOROOT_BOOTSTRAP=/usr/local/go-bootstrap"},
-		buildletURLTmpl: "http://storage.googleapis.com/$BUCKET/buildlet.linux-amd64",
+		buildletURLTmpl: "http://storage.googleapis.com/$BUCKET/buildlet.linux-arm64",
+		SSHUsername:     "root",
+	},
+	"host-linux-arm-aws": &HostConfig{
+		Notes:           "Debian Buster, EC2 arm instance. See x/build/env/linux-arm/aws",
+		VMImage:         "ami-07409163bccd5ac4d",
+		ContainerImage:  "gobuilder-arm-aws:latest",
+		machineType:     "m6g.xlarge",
+		isEC2:           true,
+		env:             []string{"GOROOT_BOOTSTRAP=/usr/local/go-bootstrap"},
+		buildletURLTmpl: "http://storage.googleapis.com/$BUCKET/buildlet.linux-arm",
 		SSHUsername:     "root",
 	},
 	"host-illumos-amd64-jclulow": &HostConfig{
@@ -2290,6 +2300,11 @@
 		HostType: "host-linux-arm64-aws",
 	})
 	addBuilder(BuildConfig{
+		Name:       "linux-arm-aws",
+		HostType:   "host-linux-arm-aws",
+		KnownIssue: 41867, // builder being tested for reliability
+	})
+	addBuilder(BuildConfig{
 		FlakyNet:       true,
 		HostType:       "host-linux-mipsle-mengzhuo",
 		Name:           "linux-mips64le-mengzhuo",
diff --git a/env/linux-arm/aws/Dockerfile b/env/linux-arm/aws/Dockerfile
new file mode 100644
index 0000000..4bd3fc3
--- /dev/null
+++ b/env/linux-arm/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 arm32v6/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-arm.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-arm && \
+    chmod +x /usr/local/bin/stage0
+
+ENV GO_BUILDER_ENV host-linux-arm-aws
+
+CMD ["/usr/local/bin/stage0"]
diff --git a/env/linux-arm/aws/Makefile b/env/linux-arm/aws/Makefile
new file mode 100644
index 0000000..7d50426
--- /dev/null
+++ b/env/linux-arm/aws/Makefile
@@ -0,0 +1,25 @@
+# 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.
+
+# Run on a arm64 or arm instance.
+prod-build: Dockerfile
+	sudo docker build -t gcr.io/symbolic-datum-552/gobuilder-arm-aws:latest .
+
+# Run on a arm64 or arm instance.
+prod-push: prod-build
+	sudo docker login -u oauth2accesstoken https://gcr.io
+	sudo docker push gcr.io/symbolic-datum-552/gobuilder-arm-aws:latest
+	sudo rm /root/.docker/config.json
+
+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_arm.json
diff --git a/env/linux-arm/aws/README.md b/env/linux-arm/aws/README.md
new file mode 100644
index 0000000..988e176
--- /dev/null
+++ b/env/linux-arm/aws/README.md
@@ -0,0 +1,31 @@
+# AWS Linux ARM Builder
+
+## Machines
+
+The AWS builders use the m6 instance types which are arm64 based machines of varying specifications.
+The base type used will be m6g.xlarge 4 vCPUs, 16384 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.
+
+## Buildlet Container Image
+
+Buildlet container images must be build on an arm/arm64 instance with the proper credentials. The instructions
+are as follows:
+
+*  In your normal gcloud dev environment, retrieve a short-lived access token:
+
+  `you@dev:~$ gcloud auth print-access-token`
+
+*  On an arm64 instance, clone the build repository.
+
+*  cd into the `env/linux-arm/aws` directory.
+
+*  Execute: `make prod-push`
+
+*  When prompted for your password, paste in the access token from the first step.
+
+*  Ensure `/root/.docker/config.json` has been deleted.
diff --git a/env/linux-arm/aws/containerd.service b/env/linux-arm/aws/containerd.service
new file mode 100644
index 0000000..b9af453
--- /dev/null
+++ b/env/linux-arm/aws/containerd.service
@@ -0,0 +1,5 @@
+# overwrite containerd.service
+# /etc/systemd/system/containerd.service.d/override.conf
+[Service]
+ExecStart=
+ExecStart=/usr/bin/setarch linux32 -B /usr/bin/containerd
diff --git a/env/linux-arm/aws/packer_image_aws_arm.json b/env/linux-arm/aws/packer_image_aws_arm.json
new file mode 100644
index 0000000..62ad25a
--- /dev/null
+++ b/env/linux-arm/aws/packer_image_aws_arm.json
@@ -0,0 +1,63 @@
+{
+  "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-arm-{{timestamp}}",
+      "ami_description": "Image for linux-arm Go builder",
+      "instance_type": "a1.medium",
+      "region": "{{user `region`}}",
+      "secret_key": "{{user `aws_secret_key`}}",
+      "source_ami_filter": {
+        "filters": {
+          "architecture": "arm64",
+          "virtualization-type": "hvm",
+          "name": "debian-10-arm64-*",
+          "root-device-type": "ebs"
+        },
+        "owners": ["136693071363"],
+        "most_recent": true
+      },
+      "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": "file",
+      "source": "./containerd.service",
+      "destination": "/tmp/containerd.service"
+    },
+    {
+      "type": "shell",
+      "script": "./prepare_image.sh"
+    }
+  ]
+}
diff --git a/env/linux-arm/aws/prepare_image.sh b/env/linux-arm/aws/prepare_image.sh
new file mode 100644
index 0000000..9dcbfff
--- /dev/null
+++ b/env/linux-arm/aws/prepare_image.sh
@@ -0,0 +1,70 @@
+#!/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 which run arm containers.
+#
+
+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
+
+sudo usermod -aG docker "$USER"
+
+# 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 mkdir -p /etc/systemd/system/containerd.service.d/
+sudo mv /tmp/containerd.service /etc/systemd/system/containerd.service.d/override.conf
+sudo systemctl daemon-reload
+sudo systemctl restart docker
+
+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-arm/aws/rundockerbuildlet.service b/env/linux-arm/aws/rundockerbuildlet.service
new file mode 100644
index 0000000..970cc7a
--- /dev/null
+++ b/env/linux-arm/aws/rundockerbuildlet.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Run Buildlets in Docker
+After=network.target
+
+[Install]
+WantedBy=network-online.target
+
+[Service]
+Type=simple
+RemainAfterExit=true
+ExecStart=/usr/local/bin/rundockerbuildlet \
+     -env=host-linux-arm-aws \
+     -image=gobuilder-arm-aws