diff --git a/changelogs/fragments/install-cloud-clis-gws-cli.yml b/changelogs/fragments/install-cloud-clis-gws-cli.yml new file mode 100644 index 0000000..311d584 --- /dev/null +++ b/changelogs/fragments/install-cloud-clis-gws-cli.yml @@ -0,0 +1,3 @@ +--- +minor_changes: + - install_cloud_clis role - add Google Workspace CLI (gws) installation from GitHub releases diff --git a/roles/install_cloud_clis/README.md b/roles/install_cloud_clis/README.md index 1715e1d..ec4c1a6 100644 --- a/roles/install_cloud_clis/README.md +++ b/roles/install_cloud_clis/README.md @@ -10,13 +10,18 @@ Install and update common **cloud and Kubernetes CLIs** for the **user that runs - kustomize - stern - Helm +- Google Workspace CLI (`gws`) Binaries are placed under **`install_cloud_clis_bin_dir`**. If you do not set it, the role assigns **`{{ ansible_facts['user_dir'] }}/.local/bin`** after its first **`setup`** task. The AWS CLI also uses **`install_cloud_clis_aws_install_root`**; if unset, the role sets **`{{ ansible_facts['user_dir'] }}/.local/aws-cli`** when AWS tasks run. ## Requirements - Ansible **2.16+** (see [`meta/main.yml`](meta/main.yml)). -- Outbound **HTTPS** to vendor endpoints (GitHub, AWS, OpenShift mirrors, Helm) when checking and downloading releases. +- Outbound **HTTPS** when checking and downloading releases: + - **GitHub** (`api.github.com`, `github.com`) — version checks and release assets for most CLIs (including gws, stern, Tekton, kube-linter, kustomize, OCM, and Helm version discovery) + - **AWS** (`awscli.amazonaws.com`) — AWS CLI installer (tags resolved via GitHub) + - **Helm** (`get.helm.sh`) — Helm binary download + - **OpenShift mirrors** (`mirror.openshift.com`) — oc and rosa CLI binaries (ROSA version also uses GitHub) - Targets are **x86_64 Linux** (download URLs and archives are fixed for that architecture). ## Facts and connection @@ -30,7 +35,7 @@ See [`defaults/main.yml`](defaults/main.yml) (component list) and [`meta/argumen | Variable | Description | | --- | --- | -| `install_cloud_clis_components` | Subset of CLIs to install or update: `aws`, `oc`, `rosa`, `tekton`, `kube_linter`, `kustomize`, `stern`, `helm`. | +| `install_cloud_clis_components` | Subset of CLIs to install or update: `aws`, `oc`, `ocm`, `rosa`, `tekton`, `kube_linter`, `kustomize`, `stern`, `helm`, `gws`. | | `install_cloud_clis_bin_dir` | Directory for symlinks/binaries. If omitted, set after **`setup`** to `{{ ansible_facts['user_dir'] }}/.local/bin`. | | `install_cloud_clis_aws_install_root` | AWS CLI `-i` install root. If omitted, set when AWS tasks run to `{{ ansible_facts['user_dir'] }}/.local/aws-cli`. | | `install_cloud_clis_manage_bashrc_completion` | When `true` (default), maintain a single Ansible `blockinfile` region in `~/.bashrc` for bash completion of selected CLIs. Set `false` to skip `.bashrc` edits entirely. | diff --git a/roles/install_cloud_clis/defaults/main.yml b/roles/install_cloud_clis/defaults/main.yml index 099a930..9a09db2 100644 --- a/roles/install_cloud_clis/defaults/main.yml +++ b/roles/install_cloud_clis/defaults/main.yml @@ -9,5 +9,6 @@ install_cloud_clis_components: - kustomize - stern - helm + - gws install_cloud_clis_manage_bashrc_completion: true diff --git a/roles/install_cloud_clis/meta/argument_specs.yml b/roles/install_cloud_clis/meta/argument_specs.yml index 07b0628..0e830fe 100644 --- a/roles/install_cloud_clis/meta/argument_specs.yml +++ b/roles/install_cloud_clis/meta/argument_specs.yml @@ -22,8 +22,9 @@ argument_specs: - kustomize - stern - helm + - gws description: - - Which CLIs to install or update. Allowed values are aws, oc, ocm, rosa, tekton, kube_linter, kustomize, stern, helm. + - Which CLIs to install or update. Allowed values are aws, oc, ocm, rosa, tekton, kube_linter, kustomize, stern, helm, gws. install_cloud_clis_manage_bashrc_completion: type: bool diff --git a/roles/install_cloud_clis/tasks/gws_cli.yml b/roles/install_cloud_clis/tasks/gws_cli.yml new file mode 100644 index 0000000..76f4057 --- /dev/null +++ b/roles/install_cloud_clis/tasks/gws_cli.yml @@ -0,0 +1,117 @@ +--- +- name: gws_cli | Retrieve Google Workspace CLI releases from GitHub + ansible.builtin.uri: + url: https://api.github.com/repos/googleworkspace/cli/releases?per_page=100 + register: __install_cloud_clis_gws_cli_versions + +- name: gws_cli | List GA releases with semver tag names + ansible.builtin.set_fact: + __install_cloud_clis_gws_ga_releases: >- + {{ __install_cloud_clis_gws_cli_versions.json + | selectattr('prerelease', 'equalto', false) + | selectattr('draft', 'equalto', false) + | selectattr('tag_name', 'match', '^v([0-9.]+)$') + | list }} + +- name: gws_cli | Determine highest semver among GA releases + ansible.builtin.set_fact: + __install_cloud_clis_gws_highest_semver: >- + {{ (__install_cloud_clis_gws_ga_releases + | map(attribute='tag_name') + | map('regex_replace', '^v', '') + | list + | community.general.version_sort + | last) }} + +- name: gws_cli | Determine latest Google Workspace CLI GA release details + ansible.builtin.set_fact: + __install_cloud_clis_latest_gws_cli_ver_details: >- + {{ __install_cloud_clis_gws_ga_releases + | selectattr('tag_name', 'equalto', 'v' ~ __install_cloud_clis_gws_highest_semver) + | first }} + +- name: gws_cli | Assert a matching GA Google Workspace CLI release was resolved + ansible.builtin.assert: + that: + - __install_cloud_clis_latest_gws_cli_ver_details is defined + - __install_cloud_clis_latest_gws_cli_ver_details['tag_name'] is defined + fail_msg: >- + Could not resolve a GA Google Workspace CLI release for the highest semver (check API response and tag format). + quiet: true + +- name: gws_cli | Determine latest Google Workspace CLI version + ansible.builtin.set_fact: + __install_cloud_clis_latest_gws_cli_ver: >- + {{ __install_cloud_clis_latest_gws_cli_ver_details['tag_name'] | + regex_replace('^v(?P[0-9.]+)$', '\g') + }} + +- name: gws_cli | Determine latest Google Workspace CLI download URL + ansible.builtin.set_fact: + __install_cloud_clis_latest_gws_cli_url: >- + {{ __install_cloud_clis_latest_gws_cli_ver_details['assets'] | + selectattr('name', 'equalto', 'google-workspace-cli-x86_64-unknown-linux-gnu.tar.gz') | + map(attribute='browser_download_url') | + first + }} + +- name: gws_cli | Check if gws binary installed + ansible.builtin.stat: + path: "{{ install_cloud_clis_bin_dir }}/gws" + register: __install_cloud_clis_gws_cli_installed + +- name: gws_cli | Check Google Workspace CLI versions (Block) + when: __install_cloud_clis_gws_cli_installed.stat.exists + block: + - name: gws_cli | Retrieve installed Google Workspace CLI version + ansible.builtin.command: + cmd: gws --version + register: __install_cloud_clis_gws_ver_installed_result + changed_when: false + + - name: gws_cli | Determine installed Google Workspace CLI version + ansible.builtin.set_fact: + __install_cloud_clis_installed_gws_cli_ver: >- + {{ __install_cloud_clis_gws_ver_installed_result.stdout | + regex_replace('(?s)^gws (?P[0-9.]+).*$', '\g') + }} + +- name: gws_cli | Display Google Workspace CLI version info + ansible.builtin.debug: + msg: | + [ + "Installed Version: {{ __install_cloud_clis_installed_gws_cli_ver | default('NOT INSTALLED') }}", + "Latest Version: {{ __install_cloud_clis_latest_gws_cli_ver }}", + "URL for latest version: {{ __install_cloud_clis_latest_gws_cli_url }}" + ] + verbosity: 1 + +- name: gws_cli | Update Google Workspace CLI executable (Block) + when: >- + (not __install_cloud_clis_gws_cli_installed.stat.exists) + or ( + __install_cloud_clis_installed_gws_cli_ver is defined + and __install_cloud_clis_installed_gws_cli_ver is version(__install_cloud_clis_latest_gws_cli_ver, '<') + ) + block: + - name: gws_cli | Update Google Workspace CLI executable + ansible.builtin.unarchive: + src: "{{ __install_cloud_clis_latest_gws_cli_url }}" + dest: "{{ install_cloud_clis_bin_dir }}" + remote_src: true + include: + - "./gws" + + - name: gws_cli | Add updated message + when: >- + __install_cloud_clis_installed_gws_cli_ver is defined + and __install_cloud_clis_installed_gws_cli_ver is version(__install_cloud_clis_latest_gws_cli_ver, '<') + ansible.builtin.set_fact: + install_cloud_clis_update_messages: > + {{ install_cloud_clis_update_messages + ["Updated gws from " + __install_cloud_clis_installed_gws_cli_ver + " to " + __install_cloud_clis_latest_gws_cli_ver] }} + + - name: gws_cli | Add installed message + when: not __install_cloud_clis_gws_cli_installed.stat.exists + ansible.builtin.set_fact: + install_cloud_clis_update_messages: > + {{ install_cloud_clis_update_messages + ["Installed gws"] }} diff --git a/roles/install_cloud_clis/tasks/main.yml b/roles/install_cloud_clis/tasks/main.yml index 3808a07..8d304a0 100644 --- a/roles/install_cloud_clis/tasks/main.yml +++ b/roles/install_cloud_clis/tasks/main.yml @@ -63,6 +63,11 @@ ansible.builtin.include_tasks: file: helm.yml + - name: Install Google Workspace CLI + when: "'gws' in install_cloud_clis_components" + ansible.builtin.include_tasks: + file: gws_cli.yml + always: - name: Refresh .bashrc completion block when: install_cloud_clis_manage_bashrc_completion | bool