Files
acdl/scripts/push_consumer_image.py
T
Jon Chery c2ca0e4631 docs(P08): complete account-id-externalization phase (v1.13.11)
---ci---
project: acdl
phase: 8
milestone: v1.14
status: complete
requirements:
  covered: [REQ-142]
  partial: []
---/ci---
2026-07-29 20:46:28 +00:00

131 lines
4.6 KiB
Python

#!/usr/bin/env python3
"""ACDL Phase 15 — push the consumer microservice Docker image to ECR.
Steps performed by this script:
1. Load AWS creds from /root/acdl/.env.secrets
(ACDL_AWS_ACCESS_KEY_ID, ACDL_AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION).
2. Create the ECR repo `acdl-microservice` if it doesn't exist
(ecr:DescribeRepositories / ecr:CreateRepository). Region: us-east-1.
3. Get the ECR login password (ecr:GetAuthorizationToken) and run
`docker login` with it.
After this script runs, it prints the docker `tag` and `push` commands
for the caller to run in the shell (steps 4-5 of T-15.1).
Usage:
python3 scripts/push_consumer_image.py
Constraints (T-15.1): the `aws` CLI is NOT installed — boto3 is used for
every AWS API call. `docker` is invoked via subprocess for the login
(since docker is the only thing that can use the auth token meaningfully).
"""
import os
import sys
import subprocess
import pathlib
import boto3
REPO_ROOT = pathlib.Path(__file__).resolve().parent.parent
ENV_FILE = REPO_ROOT / ".env.secrets"
AWS_ACCOUNT_ID = os.environ.get("ACDL_AWS_ACCOUNT_ID", "581513795199")
AWS_REGION = "us-east-1"
ECR_REPO_NAME = "acdl-microservice"
IMAGE_TAG = "latest"
def _load_env(path):
"""Load ACDL_AWS_* + AWS_DEFAULT_REGION from a flat KEY=VALUE file."""
creds = {}
with open(path, "r") as fh:
for line in fh:
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
k, v = line.split("=", 1)
creds[k.strip()] = v.strip()
return creds
def main():
if not ENV_FILE.exists():
print(f"FAIL: {ENV_FILE} not found", file=sys.stderr)
return 2
creds = _load_env(ENV_FILE)
access_key = creds.get("ACDL_AWS_ACCESS_KEY_ID")
secret_key = creds.get("ACDL_AWS_SECRET_ACCESS_KEY")
region = creds.get("AWS_DEFAULT_REGION", AWS_REGION)
if not access_key or not secret_key:
print("FAIL: ACDL_AWS_ACCESS_KEY_ID / ACDL_AWS_SECRET_ACCESS_KEY missing",
file=sys.stderr)
return 2
# Export the creds for the docker subprocess (it doesn't need them, but
# keeps parity with the terraform step that runs after this).
os.environ["AWS_ACCESS_KEY_ID"] = access_key
os.environ["AWS_SECRET_ACCESS_KEY"] = secret_key
os.environ["AWS_DEFAULT_REGION"] = region
session = boto3.Session(
aws_access_key_id=access_key,
aws_secret_access_key=secret_key,
region_name=region,
)
ecr = session.client("ecr")
# Step 2: create the ECR repo if it doesn't exist.
repo_uri = None
try:
resp = ecr.describe_repositories(repositoryNames=[ECR_REPO_NAME])
repo = resp["repositories"][0]
repo_uri = repo["repositoryUri"]
print(f"ecr: repository {ECR_REPO_NAME!r} already exists -> {repo_uri}")
except ecr.exceptions.RepositoryNotFoundException:
print(f"ecr: repository {ECR_REPO_NAME!r} not found, creating...")
resp = ecr.create_repository(repositoryName=ECR_REPO_NAME)
repo = resp["repository"]
repo_uri = repo["repositoryUri"]
print(f"ecr: created repository {ECR_REPO_NAME!r} -> {repo_uri}")
except Exception as exc:
print(f"FAIL: ecr describe/create failed: {exc}", file=sys.stderr)
return 1
# Step 3: get login password + run `docker login`.
auth = ecr.get_authorization_token()
token = auth["authorizationData"][0]["authorizationToken"]
# The token is base64(USERNAME:PASSWORD); docker login wants them split.
import base64
user_pw = base64.b64decode(token).decode("utf-8")
username, password = user_pw.split(":", 1)
registry = f"{AWS_ACCOUNT_ID}.dkr.ecr.{region}.amazonaws.com"
print(f"docker: logging in to {registry} ...")
login_cmd = [
"docker", "login",
"--username", username,
"--password-stdin",
registry,
]
proc = subprocess.run(login_cmd, input=password.encode("utf-8"),
capture_output=True)
if proc.returncode != 0:
print("FAIL: docker login failed:", file=sys.stderr)
sys.stderr.write(proc.stderr.decode("utf-8", "replace"))
return 1
print("docker: login OK")
# Steps 4-5: print the tag + push commands for the caller to run.
full_tag = f"{repo_uri}:{IMAGE_TAG}"
print("")
print("=== NEXT: run these commands in the shell to tag + push ===")
print(f"docker tag acdl-microservice:latest {full_tag}")
print(f"docker push {full_tag}")
print("")
print(f"ECR_IMAGE={full_tag}")
return 0
if __name__ == "__main__":
sys.exit(main())