diff --git a/Dockerfile b/Dockerfile index 0575b17..cbe8199 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,11 @@ -FROM ubuntu:20.04 +# Wrangler requires glibc 2.35. Ubuntu 20.04 ships 2.31. +FROM ubuntu:22.04 ENV NVM_DIR=/usr/local/nvm -# Install dependencies, AWS CLI, kubectl, Helm, tfenv, NVM, and GitHub CLI. -# Node itself is installed at runtime by script.sh when NODE_VERSION is set. +# Install dependencies, AWS CLI, kubectl, Helm, tfenv, NVM, GitHub CLI, and Wrangler. +# A project Node version is installed at runtime by script.sh when NODE_VERSION is set. +# The Node under /opt/node exists only so Wrangler can run when NODE_VERSION is unset. RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \ git \ jq \ @@ -14,10 +16,11 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \ openssl \ python3 \ python3-pip \ + python3-yaml \ && arch=$(dpkg --print-architecture) \ && case "$arch" in \ - amd64) aws_cli_url="https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip"; kubectl_arch="amd64" ;; \ - arm64) aws_cli_url="https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip"; kubectl_arch="arm64" ;; \ + amd64) aws_cli_url="https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip"; kubectl_arch="amd64"; node_arch="x64" ;; \ + arm64) aws_cli_url="https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip"; kubectl_arch="arm64"; node_arch="arm64" ;; \ *) echo "Unsupported architecture: $arch" >&2; exit 1 ;; \ esac \ && curl -fsSL "$aws_cli_url" -o awscliv2.zip \ @@ -29,7 +32,8 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \ && chmod 700 get_helm.sh \ && ./get_helm.sh \ && git clone https://github.com/tfutils/tfenv.git /root/.tfenv \ - && pip3 install urllib3==1.26.7 print-env \ + && pip3 install 'urllib3==1.26.7' 'requests>=2,<3' 'click>=7,<8' 'python-dotenv==0.19.2' 'python-gnupg==0.4.8' \ + && pip3 install print-env --no-deps \ && mkdir -p "$NVM_DIR" \ && curl -fsSL -o /tmp/nvm-install.sh https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh \ && bash /tmp/nvm-install.sh \ @@ -38,8 +42,15 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \ && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" > /etc/apt/sources.list.d/github-cli.list \ && apt-get update \ && DEBIAN_FRONTEND=noninteractive apt-get install -y gh \ + && curl -fsSL -o node.tar.gz "https://nodejs.org/dist/v22.23.3/node-v22.23.3-linux-${node_arch}.tar.gz" \ + && mkdir -p /opt/node \ + && tar -xzf node.tar.gz -C /opt/node --strip-components=1 \ + && PATH="/opt/node/bin:$PATH" npm install -g wrangler@4.141.0 \ + && printf '%s\n' '#!/bin/sh' 'exec /opt/node/bin/node /opt/node/lib/node_modules/wrangler/bin/wrangler.js "$@"' > /usr/local/bin/wrangler \ + && chmod 755 /usr/local/bin/wrangler \ + && wrangler --version \ && apt-get clean \ - && rm -rf /var/lib/apt/lists/* awscliv2.zip aws kubectl get_helm.sh + && rm -rf /var/lib/apt/lists/* awscliv2.zip aws kubectl get_helm.sh node.tar.gz # tfenv is a real binary path. nvm is a shell function loaded by script.sh, # so a node version directory cannot be added here. diff --git a/Readme.md b/Readme.md index d9baf50..c7cad22 100644 --- a/Readme.md +++ b/Readme.md @@ -64,3 +64,9 @@ mfa 123456 `123456` is the code from your authenticator app. That command sources `/usr/local/bin/mfa.sh`, writes a session token to `~/.aws/credentials`, and exports `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN` in the current shell. `source ./mfa.sh` does not work here. `dev` mounts the project on `/work`, so a script copied into the project is hidden or left behind in that repository. `mfa` stays in the image, outside that mount. + +## Cloudflare CLI + +Wrangler is installed in the image. `dev /` authenticates it when that Portunus project sets `CLOUDFLARE_API_TOKEN`. Wrangler reads that variable itself. An optional `CLOUDFLARE_ACCOUNT_ID` on the same project is passed through the same way. + +Startup runs `wrangler whoami`. A token that Cloudflare rejects stops the container. A project without `CLOUDFLARE_API_TOKEN` still opens a shell, and Wrangler commands in that shell are not authenticated. `dev` with no project does not load Portunus, so it does not authenticate Wrangler either. diff --git a/script.sh b/script.sh index 5504cb9..623e248 100644 --- a/script.sh +++ b/script.sh @@ -129,6 +129,15 @@ EOF echo "GH_CLI_TOKEN is not set. Skipping GitHub CLI authentication." fi + # Wrangler reads CLOUDFLARE_API_TOKEN from the environment. Portunus exports it + # when this project defines it. Run whoami outside /work so it cannot write into the mounted project. + if [ -n "${CLOUDFLARE_API_TOKEN:-}" ]; then + echo "Authenticating Cloudflare CLI..." + ( cd /tmp && CI=true WRANGLER_SEND_METRICS=false wrangler whoami ) || error_exit "Failed to authenticate the Cloudflare CLI. Check CLOUDFLARE_API_TOKEN on this Portunus project." + else + echo "CLOUDFLARE_API_TOKEN is not set. Skipping Cloudflare CLI authentication." + fi + fi # Exit to a bash prompt