Skip to content

Commit 32fd8eb

Browse files
authored
DRIVERS-3158 Use AWS ECR pull through cache for Docker (#651)
1 parent 36dd90c commit 32fd8eb

File tree

12 files changed

+174
-8
lines changed

12 files changed

+174
-8
lines changed

.evergreen/auth_oidc/start_local_server.sh

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,8 @@ EOF
2727

2828
ENTRYPOINT=${ENTRYPOINT:-/root/docker_entry.sh}
2929
USE_TTY=""
30-
AWS_PROFILE=${AWS_PROFILE:-""}
3130

32-
if [ -z "$AWS_PROFILE" ]; then
31+
if [ -z "${AWS_PROFILE:-}" ]; then
3332
if [[ -z "${AWS_SESSION_TOKEN:-}" || -z "${AWS_ACCESS_KEY_ID:-}" || -z "${AWS_SECRET_ACCESS_KEY:-}" ]]; then
3433
echo "Please set AWS_PROFILE or set AWS credentials environment variables" 1>&2
3534
exit 1
@@ -55,6 +54,11 @@ if [ -n "${DOCKER_COMMAND:-}" ]; then
5554
DOCKER=$DOCKER_COMMAND
5655
fi
5756

57+
# Log in to docker if running on CI.
58+
if [ -n "${CI:-}" ]; then
59+
bash $SCRIPT_DIR/../docker/setup.sh
60+
fi
61+
5862
# Build from the root directory so we can include files.
5963
pushd $DRIVERS_TOOLS
6064
PLATFORM="--platform linux/amd64"

.evergreen/config.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,9 @@ functions:
306306
- SSL
307307
- STORAGE_ENGINE
308308
- TOPOLOGY
309+
- AWS_ACCESS_KEY_ID
310+
- AWS_SECRET_ACCESS_KEY
311+
- AWS_SESSION_TOKEN
309312
args:
310313
- ${DRIVERS_TOOLS}/.evergreen/run-orchestration.sh
311314
- -v
@@ -349,6 +352,7 @@ functions:
349352
binary: bash
350353
env:
351354
ENTRYPOINT: /root/test-entrypoint.sh
355+
include_expansions_in_env: [AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN]
352356
args:
353357
- ${DRIVERS_TOOLS}/.evergreen/docker/run-server.sh
354358
- command: subprocess.exec

.evergreen/docker/README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,25 @@ for your Driver that shares the binary files and communicates with this containe
77

88
You will need podman (or Docker) installed and running locally.
99

10-
# Run Local Server
10+
## Log in to Docker
11+
12+
Run the `setup.sh` script to log into docker. This is needed when using the ECR pull-through
13+
cache that DevProd maintains. This script can be run after assuming the Drivers test secrets role. For example:
14+
15+
```yaml
16+
"docker login":
17+
- command: ec2.assume_role
18+
params:
19+
role_arn: ${drivers_test_secrets_role}
20+
- command: subprocess.exec
21+
type: test
22+
params:
23+
binary: bash
24+
include_expansions_in_env: [AWS_SECRET_ACCESS_KEY, AWS_ACCESS_KEY_ID, AWS_SESSION_TOKEN]
25+
args: ["${DRIVERS_TOOLS}/.evergreen/docker/setup.sh"]
26+
```
27+
28+
## Run Local Server
1129
1230
To run a local server, change to this directory and run:
1331
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/usr/bin/env bash
2+
#
3+
# activate-dockervenv.sh
4+
#
5+
# Usage:
6+
# . ./activate-dockervenv.sh
7+
#
8+
# This file creates and/or activates the dockervenv virtual environment in the
9+
# current working directory. This file must be invoked from within the
10+
# .evergreen/ocsp directory in the Drivers Evergreen Tools repository.
11+
#
12+
# If a dockervenv virtual environment already exists, it will be activated and
13+
# no further action will be taken. If a dockervenv virtual environment must be
14+
# created, required packages will also be installed.
15+
16+
# If an error occurs during creation, activation, or installation of packages,
17+
# the dockervenv virtual environment will be deactivated and activate_dockervenv
18+
# will return a non-zero value.
19+
20+
if [ -z "$BASH" ]; then
21+
echo "activate-dockervenv.sh must be run in a Bash shell!" 1>&2
22+
return 1
23+
fi
24+
25+
# Automatically invoked by activate-dockervenv.sh.
26+
activate_dockervenv() {
27+
# shellcheck source=.evergreen/venv-utils.sh
28+
. ../venv-utils.sh || return
29+
30+
if [[ -d dockervenv ]]; then
31+
venvactivate dockervenv || return
32+
else
33+
# shellcheck source=.evergreen/find-python3.sh
34+
. ../find-python3.sh || return
35+
PYTHON=$(ensure_python3) || return
36+
37+
echo "Creating virtual environment 'dockervenv'..."
38+
venvcreate "${PYTHON:?}" dockervenv || return
39+
40+
python -m pip install -q -r requirements.txt || {
41+
local -r ret="$?"
42+
deactivate || return 1 # Deactivation should never fail!
43+
return "$ret"
44+
}
45+
echo "Creating virtual environment 'dockervenv'... done."
46+
fi
47+
}
48+
49+
activate_dockervenv

.evergreen/docker/login.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"""
2+
Python script to log in to the Dev Prod ECR registry.
3+
"""
4+
5+
import base64
6+
import os
7+
import shlex
8+
import shutil
9+
import subprocess
10+
11+
import boto3
12+
13+
registry = os.environ["ECR_REGISTRY"]
14+
account = registry.split(".")[0]
15+
if "CI" in os.environ:
16+
sts_client = boto3.client("sts", region_name=os.environ["AWS_REGION"])
17+
resp = sts_client.assume_role(
18+
RoleArn=os.environ["AWS_ROLE_ARN"],
19+
RoleSessionName=f"{account}-test",
20+
ExternalId=os.environ["AWS_EXTERNAL_ID"],
21+
)
22+
creds = resp["Credentials"]
23+
sts_client.close()
24+
else:
25+
creds = dict(AccessKeyId=None, SecretAccessKey=None, SessionToken=None)
26+
27+
ecr_client = boto3.client(
28+
"ecr",
29+
aws_access_key_id=creds["AccessKeyId"],
30+
aws_secret_access_key=creds["SecretAccessKey"],
31+
aws_session_token=creds["SessionToken"],
32+
region_name=os.environ["AWS_REGION"],
33+
)
34+
resp = ecr_client.get_authorization_token(registryIds=[account])
35+
ecr_client.close()
36+
37+
token = resp["authorizationData"][0]["authorizationToken"]
38+
_, _, token = base64.b64decode(token).partition(b":")
39+
40+
docker = shutil.which("docker") or shutil.which("podman")
41+
if "podman" in docker:
42+
docker = f"sudo {docker}"
43+
44+
cmd = f"{docker} login --username AWS --password-stdin {registry}"
45+
proc = subprocess.Popen(
46+
shlex.split(cmd),
47+
stdout=subprocess.PIPE,
48+
stdin=subprocess.PIPE,
49+
stderr=subprocess.PIPE,
50+
)
51+
stdout, stderr = proc.communicate(token)
52+
if stdout:
53+
print(stdout.decode("utf-8").strip())
54+
if stderr:
55+
print(stderr.decode("utf-8").strip())

.evergreen/docker/requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
boto3~=1.35.0
2+
docker~=7.1.0

.evergreen/docker/run-server.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ PLATFORM=${DOCKER_PLATFORM:-}
1414
ARCH=${ARCH:-}
1515
# e.g. --platform linux/amd64
1616

17+
# Log in to docker if running on CI.
18+
if [ -n "${CI:-}" ]; then
19+
bash $SCRIPT_DIR/setup.sh
20+
fi
21+
1722
if [[ -z $PLATFORM && -n $ARCH ]]; then
1823
PLATFORM="--platform linux/$ARCH"
1924
fi

.evergreen/docker/setup.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/usr/bin/env bash
2+
3+
set -eu
4+
5+
SCRIPT_DIR=$(dirname ${BASH_SOURCE[0]})
6+
. $SCRIPT_DIR/../handle-paths.sh
7+
pushd $SCRIPT_DIR
8+
9+
# Source secrets from the vault.
10+
if [ ! -f secrets-export.sh ]; then
11+
. $SCRIPT_DIR/../secrets_handling/setup-secrets.sh drivers/docker
12+
fi
13+
source secrets-export.sh
14+
15+
# Python script that uses boto3 to assume the role and get the login password, then passes it to docker login
16+
. ./activate-dockerenv.sh
17+
python login.py

.evergreen/docker/ubuntu20.04/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM ubuntu:20.04
1+
FROM 901841024863.dkr.ecr.us-east-1.amazonaws.com/dockerhub/library/ubuntu:20.04
22

33
RUN export DEBIAN_FRONTEND=noninteractive && \
44
apt-get -qq update && apt-get -qq -y install --no-install-recommends \

.evergreen/orchestration/drivers_orchestration.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,9 +246,15 @@ def run_command(cmd: str, exit_on_error=True, **kwargs):
246246

247247
def start_atlas(opts):
248248
mo_home = Path(opts.mongo_orchestration_home)
249-
image = f"docker.io/mongodb/mongodb-atlas-local:{opts.version}"
249+
image = f"mongodb/mongodb-atlas-local:{opts.version}"
250250
docker = get_docker_cmd()
251251
stop(opts)
252+
# If we're on evergreen, we need to log into docker and use the pull-through cache.
253+
if "CI" in os.environ and "GITHUB_ACTION" not in os.environ:
254+
LOGGER.info("Logging in to docker...")
255+
run_command("bash setup.sh", cwd=EVG_PATH / "docker")
256+
LOGGER.info("Logging in to ECR... done.")
257+
image = f"901841024863.dkr.ecr.us-east-1.amazonaws.com/dockerhub/{image}"
252258
cmd = f"{docker} run --rm -d --name mongodb_atlas_local -p 27017:27017"
253259
if opts.auth:
254260
cmd += " -e MONGODB_INITDB_ROOT_USERNAME=bob"

.evergreen/secrets_handling/setup_secrets.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@
1515
AWS_ROLE_ARN = "arn:aws:iam::857654397073:role/drivers-test-secrets-role"
1616

1717

18-
def get_secrets(vaults, region, profile):
18+
def get_secrets(vaults, region, profile, assume_role=False):
1919
"""Get the driver secret values."""
2020
# Handle local credentials.
2121
profile = profile or os.environ.get("AWS_PROFILE")
2222
session = boto3.Session(profile_name=profile)
2323
creds = None
2424
kwargs = dict(region_name=region)
25-
if "AWS_ACCESS_KEY_ID" not in os.environ and not profile:
25+
if assume_role or ("AWS_ACCESS_KEY_ID" not in os.environ and not profile):
26+
assume_role = True
2627
client = session.client(service_name="sts", **kwargs)
2728
try:
2829
# This will only fail locally.
@@ -49,12 +50,16 @@ def get_secrets(vaults, region, profile):
4950
for vault in vaults:
5051
secret = client.get_secret_value(SecretId=vault)["SecretString"]
5152
secrets.append(secret)
52-
except botocore.exceptions.BotoCoreError as e:
53+
except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e:
54+
# Try one more time with assume_role.
55+
if not assume_role:
56+
return get_secrets(vaults, region, profile, True)
5357
# For a list of exceptions thrown, see
5458
# https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
5559
print(f"\nERROR: {e}\n")
5660
sys.exit(1)
5761
except Exception as e:
62+
print("HERE I am also, I caught the exception!", assume_role)
5863
raise e
5964

6065
# Decrypts secret using the associated KMS key.

.github/workflows/tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ jobs:
2020
tests:
2121
name: "Tests"
2222
runs-on: ${{ matrix.os }}
23+
timeout-minutes: 5
2324

2425
strategy:
2526
fail-fast: false

0 commit comments

Comments
 (0)