diff --git a/Dockerfile b/Dockerfile index e6ea127..cabce19 100644 --- a/Dockerfile +++ b/Dockerfile @@ -122,6 +122,37 @@ RUN mkdir -p /etc/apt/keyrings && \ # environment (/mnt/repo/python_env/bin/python3), which doesn't exist here. /opt/az/bin/python3 -m pip install --no-cache-dir --break-system-packages --upgrade "cryptography==${CRYPTOGRAPHY_VERSION}" +# Install Google Cloud CLI +ARG GCLOUD_VERSION=575.0.1 +RUN mkdir -p /tmp/gcloud_env/ && \ + cd /tmp/gcloud_env/ && \ + wget "https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-${GCLOUD_VERSION}-linux-x86_64.tar.gz" && \ + tar -xzf google-cloud-cli-${GCLOUD_VERSION}-linux-x86_64.tar.gz -C /opt && \ + /opt/google-cloud-sdk/install.sh --quiet --usage-reporting=false --path-update=false --command-completion=false --rc-path=/dev/null && \ + ln -sf /opt/google-cloud-sdk/bin/gcloud /usr/local/bin/gcloud && \ + ln -sf /opt/google-cloud-sdk/bin/gsutil /usr/local/bin/gsutil && \ + ln -sf /opt/google-cloud-sdk/bin/bq /usr/local/bin/bq && \ + # gcloud vendors its own bundled Python under platform/bundledpythonunix + # with its own pinned deps, separate from the system pip environment - + # patch its cryptography too (same issue as azure-cli's /opt/az venv). + # gcloud also vendors pyOpenSSL, which imports cryptography's internal + # OpenSSL bindings directly - bumping cryptography alone (even with + # --no-deps, even with full --upgrade resolution, since pyOpenSSL isn't + # a *dependency* of cryptography so neither approach touches it) leaves + # pyOpenSSL calling attributes cryptography's bindings no longer expose + # ("AttributeError: module 'lib' has no attribute 'GEN_EMAIL'"). Bump + # both together, pinned to versions PyPI declares compatible with each + # other, and use --no-deps so nothing else in the pinned snapshot moves. + BUNDLED_PY=$(find /opt/google-cloud-sdk/platform/bundledpythonunix -maxdepth 2 -type f -name "python3*" ! -name "*-config" | head -1) && \ + "$BUNDLED_PY" -m pip install --no-cache-dir --break-system-packages --force-reinstall --no-deps \ + "cryptography==${CRYPTOGRAPHY_VERSION}" "pyOpenSSL==26.3.0" && \ + # gsutil vendors urllib3's entire source tree, including urllib3's own + # test-only dummy TLS server fixtures (dead weight here, and their + # checked-in dummy private keys trip vulnerability scanners as if they + # were real secrets) + rm -rf /opt/google-cloud-sdk/platform/gsutil/third_party/urllib3/dummyserver && \ + rm -rf /tmp/gcloud_env/ + # PowerShell Installation ARG PS_VERSION=7.6.3 ARG PS_PACKAGE=powershell_${PS_VERSION}-1.deb_amd64.deb diff --git a/README.md b/README.md index 52de51e..a2cc1a2 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ ## Key Features -- **Comprehensive Toolset**: Pre-installed with tools like Git, Python, Ansible, Terraform, kubectl, Helm, GitHub CLI, AWS CLI, Azure CLI, and more. +- **Comprehensive Toolset**: Pre-installed with tools like Git, Python, Ansible, Terraform, kubectl, Helm, GitHub CLI, AWS CLI, Azure CLI, Google Cloud CLI, and more. - **Easy Integration**: Use it directly or customize it with your preferred versions. - **Efficient Updates**: Tool versions are checked automatically and verified against the real installed binaries before every release, so published images track current, patched versions rather than drifting silently. - **Configuration Reusability**: Mounts host config folders for seamless reuse across sessions. @@ -116,6 +116,7 @@ Built on `ubuntu:24.04` base image | GitHub CLI | GH_VERSION=2.96.0 | [Check](https://github.com/cli/cli/releases) | [githubcli_usage](./docs/usage/githubcli_usage.md) | | AwsCLI | AWSCLI_VERSION=2.35.21 | [Check](https://raw.githubusercontent.com/aws/aws-cli/v2/CHANGELOG.rst) | [awscli_usage](./docs/usage/awscli_usage.md) | | AzureCLI | AZURECLI_VERSION=2.88.0 | [Check](https://learn.microsoft.com/en-us/cli/azure/release-notes-azure-cli) | [azurecli_usage](./docs/usage/azurecli_usage.md) | +| GCloudCLI | GCLOUD_VERSION=575.0.1 | [Check](https://cloud.google.com/sdk/docs/release-notes) | [gcloudcli_usage](./docs/usage/gcloudcli_usage.md) | | PowerShell | PS_VERSION=7.6.3 | [Check](https://github.com/PowerShell/PowerShell/releases) | [powershell_usage](./docs/usage/powershell_usage.md) | And more tools to be implemented... diff --git a/docs/usage/README.md b/docs/usage/README.md index 8f88516..74fab4d 100644 --- a/docs/usage/README.md +++ b/docs/usage/README.md @@ -34,6 +34,10 @@ This guide us how to use the `devops-toolkit` with serveral usecases - Check [**azurecli_usage**](./azurecli_usage.md) +## GCloudCLI + +- Check [**gcloudcli_usage**](./gcloudcli_usage.md) + ## PowerShell - Check [**powershell_usage**](./powershell_usage.md) diff --git a/docs/usage/gcloudcli_usage.md b/docs/usage/gcloudcli_usage.md new file mode 100644 index 0000000..c223e25 --- /dev/null +++ b/docs/usage/gcloudcli_usage.md @@ -0,0 +1,53 @@ +# Use gcloudcli in the devops-toolkit + +## Prerequisite + +A Google Cloud account + +## gcloudcli document + +Some document to help you start with the Google Cloud CLI + +- + +## Run with Docker command + +### Note + +To use the existing container instead of creating one, use `docker exec` command instead of `docker run` + +```bash +docker exec -it my_devops_toolkit /bin/bash +``` + +### Common Run Modes + +For instructions on common run modes, visit [**DevOps Toolkit Common Run Mode**](../usage/run_mode.md). + +### Use case 1: gcloud login and run command + +```bash +docker run --rm -it -v ~/.dtc:/dtc tungbq/devops-toolkit:latest + +# Login with gcloud CLI +gcloud auth login --no-launch-browser +### Copy the printed URL into a browser, sign in, then paste the verification code back into the terminal + +# Set the active project +gcloud config set project + +# List Compute Engine instances +gcloud compute instances list +``` + +Sample Result + +```bash +root@f097467db632:~# gcloud projects list +PROJECT_ID NAME PROJECT_NUMBER +your-project-id your-project 123456789012 +``` + +### Troubleshooting + +- For any issues, check [this reference](../troubleshooting/TROUBLESHOOTING.md) diff --git a/samples/README.md b/samples/README.md index 2a14444..a189af0 100644 --- a/samples/README.md +++ b/samples/README.md @@ -70,3 +70,10 @@ gh --version ## AzureCLI - TODO + +## GCloudCLI + +```bash +# Check Google Cloud CLI version +gcloud --version +``` diff --git a/samples/run_sample.sh b/samples/run_sample.sh index 1dc0d16..e573054 100644 --- a/samples/run_sample.sh +++ b/samples/run_sample.sh @@ -51,3 +51,9 @@ helm search repo bitnami | grep jenkins console_log "Running GitHub CLI sample: check version" gh --version +########### +# Google Cloud CLI +########### +console_log "Running Google Cloud CLI sample: check version" +gcloud --version + diff --git a/scripts/check_latest_version.py b/scripts/check_latest_version.py index 0b71c1c..908a494 100644 --- a/scripts/check_latest_version.py +++ b/scripts/check_latest_version.py @@ -52,6 +52,14 @@ def check_awscli_version(self): version_pattern = re.compile(r'\b(\d+\.\d+\.\d+)\b') return self.check_version("awscli", "https://raw.githubusercontent.com/aws/aws-cli/v2/CHANGELOG.rst", version_pattern) + def check_gcloud_version(self): + # Google Cloud CLI isn't distributed via GitHub releases; its rapid-channel + # manifest is the canonical source gcloud itself uses to check for updates. + req = self.do_http_request("https://dl.google.com/dl/cloudsdk/channels/rapid/components-2.json") + latest_version = req["version"] + print(f"Latest version of Google Cloud CLI: {latest_version}") + return latest_version + def check_github_release_version(self, name, repo, tag_prefix="v"): print(f"Checking {name} version from repo {repo} using tag prefix: {tag_prefix}") latest_version = None @@ -99,6 +107,10 @@ def main(output_file): azcli_version = version_parser.check_github_release_version("Azure CLI", "Azure/azure-cli", "azure-cli-") versions["azurecli"] = azcli_version + # Google Cloud CLI + gcloud_version = version_parser.check_gcloud_version() + versions["gcloudcli"] = gcloud_version + # PowerShell Core pwsh_version = version_parser.check_github_release_version("PowerShell", "PowerShell/PowerShell", "v") versions["pwsh"] = pwsh_version diff --git a/scripts/check_version_in_toolkit.sh b/scripts/check_version_in_toolkit.sh index f9b77ef..c539c2b 100644 --- a/scripts/check_version_in_toolkit.sh +++ b/scripts/check_version_in_toolkit.sh @@ -12,6 +12,7 @@ helm_version=$(cat "$toolkit_info_path" | jq -r '.helm') githubcli_version=$(cat "$toolkit_info_path" | jq -r '.githubcli') awscli_version=$(cat "$toolkit_info_path" | jq -r '.awscli') azurecli_version=$(cat "$toolkit_info_path" | jq -r '.azurecli') +gcloudcli_version=$(cat "$toolkit_info_path" | jq -r '.gcloudcli') pwsh_version=$(cat "$toolkit_info_path" | jq -r '.pwsh') # Print the versions @@ -24,6 +25,7 @@ echo "helm_version=$helm_version" echo "githubcli_version=$githubcli_version" echo "awscli_version=$awscli_version" echo "azurecli_version=$azurecli_version" +echo "gcloudcli_version=$gcloudcli_version" echo "pwsh_version=$pwsh_version" # Define the tools and their expected versions @@ -36,6 +38,7 @@ declare -A tools=( [gh]="$githubcli_version" [aws]="$awscli_version" [az]="$azurecli_version" + [gcloud]="$gcloudcli_version" [pwsh]="$pwsh_version" # Add more tools as needed ) diff --git a/scripts/update_latest_version.py b/scripts/update_latest_version.py index 02b91d3..6d66d90 100644 --- a/scripts/update_latest_version.py +++ b/scripts/update_latest_version.py @@ -61,6 +61,7 @@ def update_readme(readme_path, version_arg, new_version): {"name": "githubcli", "version_arg": "GH_VERSION"}, {"name": "awscli", "version_arg": "AWSCLI_VERSION"}, {"name": "azurecli", "version_arg": "AZURECLI_VERSION"}, + {"name": "gcloudcli", "version_arg": "GCLOUD_VERSION"}, {"name": "pwsh", "version_arg": "PS_VERSION"} ] diff --git a/toolkit_info.json b/toolkit_info.json index a7c5faa..2603cf8 100644 --- a/toolkit_info.json +++ b/toolkit_info.json @@ -7,5 +7,6 @@ "githubcli": "2.96.0", "awscli": "2.35.21", "azurecli": "2.88.0", + "gcloudcli": "575.0.1", "pwsh": "7.6.3" }