Skip to content

Commit

Permalink
Merge pull request #616 from amazonlinux/builder-container
Browse files Browse the repository at this point in the history
Create a common builder container
  • Loading branch information
jahkeup authored Jan 9, 2020
2 parents ee4919b + 5a39288 commit 65bda1e
Show file tree
Hide file tree
Showing 24 changed files with 322 additions and 74 deletions.
2 changes: 2 additions & 0 deletions Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ script = [
'''
set -o pipefail
if ! docker image inspect ${BUILDSYS_SDK_IMAGE} >/dev/null 2>&1 ; then
# Let curl resolve the certificates instead of the tasks resolved bundle.
unset SSL_CERT_FILE SSL_CERT_DIR
if ! curl https://thar-upstream-lookaside-cache.s3.us-west-2.amazonaws.com/${BUILDSYS_SDK_IMAGE}.tar.gz \
| gunzip | docker load ; then
echo "failed to load '${BUILDSYS_SDK_IMAGE}'" >&2
Expand Down
2 changes: 1 addition & 1 deletion bin/amiize.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash

# Register partitioned root and data images as an AMI in EC2.
# Only registers with HVM virtualization type and GP2 EBS volume type.
Expand Down
2 changes: 1 addition & 1 deletion bin/upload-sources
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash

set -euo pipefail

Expand Down
2 changes: 1 addition & 1 deletion tools/docker-go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash

# Helper script for running commands in a golang build/runtime environment for testing/vendoring/building a go module

Expand Down
2 changes: 1 addition & 1 deletion tools/gen-docs.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
DOCS=(START.md README.md INSTALL.md CHANGELOG.md extras/dogswatch/README.md)
EXTRAS=(extras/dogswatch/{dogswatch,dev/deployment}.yaml)

Expand Down
9 changes: 1 addition & 8 deletions tools/infra/buildspec/thar-pr-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,13 @@ env:
INFRA_DIR: "./tools/infra"

phases:
install:
runtime-versions:
docker: 18
commands:
- . "${INFRA_DIR}/env/lib/environment-setup"
- . setup-rust-builder
pre_build:
commands:
- start-build-environment
- environment-report
- write-build-meta
build:
commands:
# Retry fetches a few times before failing
- retry 2 'fetch dependencies' -- cargo make fetch
- cargo make world

artifacts:
Expand Down
1 change: 1 addition & 0 deletions tools/infra/container/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Makefile
33 changes: 33 additions & 0 deletions tools/infra/container/Dockerfile.builder
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Dockerfile.builder - Base build environment container image
#
# The builder image provides an environment in which packages and images may be
# built. This includes the necessary compilers, libraries, services, and
# executable dependencies used in the course of the build process.
#
# Facilitating scripts may be found in the ./runtime and ./scripts directory
# where scripts are generally participants in the build of the environment.
#
FROM amazonlinux:2 as base
RUN yum update -y \
&& yum groupinstall -y 'Development Tools' \
&& yum install -y socat procps-ng awscli jq openssh rsync \
&& amazon-linux-extras install -y docker \
&& yum clean all \
&& rm -rf /var/cache/yum /var/cache/amzn2extras

FROM base
ENV PATH="$PATH:/build/runtime/bin:/build/scripts:/build/.cargo/bin"
ENV CARGO_HOME="/build/.cargo"
ENV RUNTIME_SCRIPT_LIB="/build/runtime/lib"

COPY scripts /build/scripts
COPY runtime /build/runtime
WORKDIR /build
RUN install-rust && configure-rust && install-crates
COPY builder/entrypoint.sh /build/entrypoint.sh

ENTRYPOINT ["/build/entrypoint.sh"]

CMD [ "bash" ]
20 changes: 20 additions & 0 deletions tools/infra/container/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
DOCKERFILES = $(filter-out %~,$(wildcard Dockerfile.*))
NAMES = $(DOCKERFILES:Dockerfile.%=%)

IMAGE_REPO_PREFIX ?= infra/
IMAGE_NAME ?= $(IMAGE_REPO_PREFIX)$(NAME):$(IMAGE_TAG)

.PHONY: force all release $(NAMES)
.DEFAULT: all
force:

all : IMAGE_TAG ?= develop
all: $(NAMES)

release : IMAGE_TAG ?= latest
release: $(if $(NAME),$(NAME),$(NAMES))

$(NAMES) : NAME = $@
$(NAMES): force
@echo "Building container image for '$(NAME)'"
docker build -t $(IMAGE_NAME) -f Dockerfile.$(NAME) .
39 changes: 39 additions & 0 deletions tools/infra/container/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Container Environments

Container images, defined in this directory, provide environments for infra's build and automation needs.

## Images

Each image is defined in their own `Dockerfile` and suffixed with its name. For example the `builder` container - used in CI builds - is defined by `Dockerfile.builder`.
The containers copy in common resources and others as needed from this shared root context.

**`builder` image**

The `builder` image provides an environment in which packages and images may be built.
`builder`'s container image is created with all required dependencies used by the build driver, `buildsys`, and the supporting tools & scripts used by it (including many of the `cargo-make` tasks' dependencies).

# Building

## Development Images

To all build images locally, a single `make` call can be made:

```bash
make all
```

Each `Dockerfile.<name>` can be built individually with `make $name` as needed.

## Release Images

As with the development images, all images may be built at once:

```bash
make release
```

To build a specific image, for instance named `builder`, `make` may be provided this name to build its release image:

```bash
make release NAME=builder
```
4 changes: 4 additions & 0 deletions tools/infra/container/builder/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env bash
set -e
start-build-environment
exec -- "$@"
File renamed without changes.
File renamed without changes.
17 changes: 17 additions & 0 deletions tools/infra/container/runtime/bin/start-build-environment
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
#
# start-build-environment - Setup the build environment & start supporting services
#
# Intended primarily for use in the builder container image, the
# start-build-environment provides a single call setup for the common use cases
# in the context of builds.
#
# usage:
#
# start-build-environment
#
set -xe
# Ensure we have a logging facility (or stubbed service)
start-log-listener
# Ensure the docker daemon is running.
start-docker-daemon
80 changes: 80 additions & 0 deletions tools/infra/container/runtime/bin/start-docker-daemon
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/env bash
#
# start-docker-daemon - Start up a docker daemon for the build environment
#
# Builds depend on a series of docker images and containers used to run builds
# for various stages of the system. In the CodeBuild task, the docker daemon
# must be started as part of the environment startup (in the buildspec) as the
# CodeBuild Agent does not execute an image's ENTRYPOINT.
#
# usage:
#
# start-docker-daemon
#

if ! hash docker dockerd; then
logger -s --no-act -t ERROR "missing required commands"
fi

# If not configured, we'll use the default docker daemon socket address.
export DOCKER_HOST="${DOCKER_HOST:-unix:///var/run/docker.sock}"
# Don't startup our own daemon if the environment has access configured for the
if docker version &>/dev/null; then
logger -s --no-act -t INFO "delegating to running & configured dockerd (via $DOCKER_HOST)"
exit 0
fi

# Also check to see if the daemon is running but we're unable to access it, the
# environment may already have docker daemon running but not fully configured
# for use.
if [[ -S "${DOCKER_HOST:+${DOCKER_HOST##unix://}}" ]]; then
logger -s --no-act -t ERROR "unable to access running dockerd (via $DOCKER_HOST)"
exit 1
fi

# Verify we're a user that can start the docker daemon (assuming for now that
# being root means that).
euid="$(id -u)"
if [[ "$euid" -ne 0 ]]; then
logger -s --no-act -t ERROR "unable to start dockerd as non-root user (euid: $euid != 0)"
exit 1
fi

# In all other cases, start the docker daemon
logger -s --no-act -t INFO "starting dockerd"
nohup dockerd \
--host="$DOCKER_HOST" \
&>/var/log/docker.log &
daemon_pid="$!"

sleep 1

if [[ ! -e "/proc/$daemon_pid" ]]; then
logger -s --no-act -t ERROR "dockerd did not start"
exit 1
fi

# Starting up the daemon asynchronously may take a moment or may fail to start
# in the background, tries are made to check in on the brief time between exec
# and the daemon ready to work.
#
# sleep interval before attempting each try
try_interval="0.1s"
# maximum try attempts that will be made
try_max_count=3
# try attempts
try_count=0

until docker info &>/dev/null; do
((try_count++))
if [[ "$try_count" -gt "$try_max_count" ]]; then
logger -s --no-act -t ERROR "dockerd start exceeded deadline (may be slow or failed to start, check logs)"
if [[ -s "/var/log/docker.log" ]]; then
sed 's/^/docker.log: /' /var/log/docker.log
else
logger -s --no-act -t WARN "dockerd logs are empty"
fi
exit 1
fi
sleep "$try_interval"
done
55 changes: 55 additions & 0 deletions tools/infra/container/runtime/bin/start-log-listener
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env bash
#
# start-log-listener - Setup a socket at /dev/log when missing
#
# The kernel's /dev/log socket may not be present in some environments so this
# script stands up a blackhole listener, to avoid logger from complaining and
# not outputting our messages.
#
# usage:
#
# start-log-listener
#
if ! hash socat; then
echo "ERROR: missing required commands"
fi

log_sock="/dev/log"

# Starting up the socket asynchronously may take a moment or may fail to start
# in the background, tries are made to check in on the brief time between exec
# and the listener bound.
#
# sleep interval before attempting each try
try_interval="0.1s"
# maximum try attempts that will be made
try_max_count=3

# Let the existing socket be.
if [[ -S "$log_sock" ]]; then
logger -s --no-act -t INFO -- "kernel's log socket is already present /dev/log"
logger -s --no-act -t INFO -- "not replacing /dev/log"
exit 0
fi

# Require EUID 0 as we're mucking about in /dev
euid="$(id -u)"
if [[ "$euid" -ne 0 ]]; then
echo "ERROR: unable to start log listener socket as non-root user (euid: $euid != 0)"
exit 1
fi

# Listen on syslog unix socket and dump any sent datagrams.
nohup socat "UNIX-LISTEN:$log_sock,fork" - &>/dev/null &

# Wait for the listener to start and assume the process didn't successfully bind
# to the socket otherwise.
try_count=0
until [[ -S "$log_sock" ]]; do
((try_count++))
if [[ "$try_count" -gt "$try_max_count" ]]; then
echo "ERROR: unable to start log listener at $log_sock" >&2
exit 1
fi
sleep "$try_interval"
done
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fi

write_common

if [[ -z "${CODEBUILD_BUILD_ID}" ]]; then
if [[ -n "${CODEBUILD_BUILD_ID}" ]]; then
write_codebuild
fi

Expand Down
6 changes: 6 additions & 0 deletions tools/infra/container/runtime/lib/lib.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# shellcheck shell=bash

# Logger provides the corrected interface to log to stderr.
logger() {
command logger --no-act -s "$@"
}
44 changes: 6 additions & 38 deletions tools/infra/env/bin/setup-rust-builder → tools/infra/container/scripts/configure-rust
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
#!/usr/bin/env sh
#!/usr/bin/env bash
#
# setup-rust-builder - install rust and configure shell for its use by a builder
#
# This script is expected to be sourced by callers in order to affect their PATH
# directly AND is used in CodeBuild environments where the SHELL is /bin/sh.
# confgure-rust - configure container environment for rust usage
#
# usage:
#
# . setup-rust-builder
# configure-rust
#

# shellcheck source=../runtime/lib/lib.bash
source "$RUNTIME_SCRIPT_LIB/lib.bash"

configure_color_output() {
# Prepare Cargo for build and CI usage
PATH="$HOME/.cargo/bin:$PATH"
Expand Down Expand Up @@ -42,37 +42,5 @@ configure_color_output() {
unset cargo_make_config
}

cargo_dep() {
cargo_install_package="$@"
logger -s -t INFO "installing cargo dep with 'cargo install $cargo_install_package'"
if ! cargo install --force $cargo_install_package; then
logger -s -t ERROR "failed to install dep with 'cargo install $cargo_install_package'"
exit 1
fi
}

install_rust_toolchain() {
test -f rustup-init.sh || rm -f rustup-init.sh
if ! curl -o rustup-init.sh --proto '=https' --tlsv1.2 -sS "https://sh.rustup.rs"; then
logger -s -t ERROR "could not fetch rustup, needed for managing rust toolchain"
exit 1
fi
if ! bash rustup-init.sh -y --no-modify-path --default-toolchain stable ; then
logger -s -t ERROR "could not setup rustup & rust toolchain for build"
exit 1
fi
rm -f rustup-init.sh
}

configure_color_output

install_rust_toolchain

# Install build tooling dependencies
cargo_dep --version 0.23.0 cargo-make
cargo_dep --version 0.2.6 cargo-deny

unset -f configure_color_output
unset -f install_rust_toolchain
unset -f cargo_dep

Loading

0 comments on commit 65bda1e

Please sign in to comment.