Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelogs/fragments/lazy-load-bash-completions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
minor_changes:
- install_cloud_clis - lazy-load and cache bash completions to eliminate subprocess spawns at shell startup
2 changes: 1 addition & 1 deletion roles/install_cloud_clis/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ When `install_cloud_clis_manage_bashrc_completion` is `true`, the role writes on

`# BEGIN ANSIBLE MANAGED BLOCK branic.system_management.install_cloud_clis` and `# END ANSIBLE MANAGED BLOCK branic.system_management.install_cloud_clis`

The block uses **`if command -v …; then` / `fi`** stanzas and `# shellcheck source=/dev/null` before `source <(…)` completions, matching common interactive shell style. Only CLIs listed in `install_cloud_clis_components` are included, in the same order as `install_cloud_clis_cli_installers` in [`vars/main.yml`](vars/main.yml).
The block defines a **`_lazy_completion`** shell function and registers one-liner calls for each CLI. Completions are deferred until the user's first tab-complete for a given command, then cached under **`~/.cache/bash_completions/`**. The cache auto-invalidates when the CLI binary is newer than the cached file. AWS CLI uses a direct binary completer (`aws_completer`) and does not use the lazy-load mechanism. Only CLIs listed in `install_cloud_clis_components` are included.

`blockinfile` runs with **`backup: true`** (timestamped `.bashrc` backup beside the file) and sets **`mode: 0644`** on `.bashrc` when the module updates the file. Add your own completions **outside** that marked region (for example in `~/.bashrc-local` or after the block) so the role does not manage them.

Expand Down
67 changes: 28 additions & 39 deletions roles/install_cloud_clis/templates/bashrc_cloud_cli_completion.j2
Original file line number Diff line number Diff line change
Expand Up @@ -5,58 +5,47 @@ if command -v aws &>/dev/null; then
fi

{% endif %}
{% if 'oc' in install_cloud_clis_components %}
if command -v oc &>/dev/null; then
# shellcheck source=/dev/null
source <(oc completion bash)
fi
{% set _lazy_cli_components = ['oc', 'ocm', 'rosa', 'tekton', 'kube_linter', 'kustomize', 'stern', 'helm'] %}
{% if _lazy_cli_components | intersect(install_cloud_clis_components) | length > 0 %}
_lazy_completion() {
local cmd=$1; shift
local gen_args=("$@")
local cache="${XDG_CACHE_HOME:-$HOME/.cache}/bash_completions/${cmd}.bash"
eval "_complete_lazy_${cmd}() {
unset -f _complete_lazy_${cmd}
complete -r ${cmd} 2>/dev/null
if [[ ! -f '${cache}' || \$(command -v ${cmd}) -nt '${cache}' ]]; then
mkdir -p '${XDG_CACHE_HOME:-$HOME/.cache}/bash_completions'
\"\${gen_args[@]}\" > '${cache}'
fi
source '${cache}'
return 124
}"
complete -F "_complete_lazy_${cmd}" "$cmd"
}

{% if 'oc' in install_cloud_clis_components %}
command -v oc &>/dev/null && _lazy_completion oc oc completion bash
{% endif %}
{% if 'ocm' in install_cloud_clis_components %}
if command -v ocm &>/dev/null; then
# shellcheck source=/dev/null
source <(ocm completion bash)
fi

command -v ocm &>/dev/null && _lazy_completion ocm ocm completion bash
{% endif %}
{% if 'rosa' in install_cloud_clis_components %}
if command -v rosa &>/dev/null; then
# shellcheck source=/dev/null
source <(rosa completion bash)
fi

command -v rosa &>/dev/null && _lazy_completion rosa rosa completion bash
{% endif %}
{% if 'tekton' in install_cloud_clis_components %}
if command -v tkn &>/dev/null; then
# shellcheck source=/dev/null
source <(tkn completion bash)
fi

command -v tkn &>/dev/null && _lazy_completion tkn tkn completion bash
{% endif %}
{% if 'kube_linter' in install_cloud_clis_components %}
if command -v kube-linter &>/dev/null; then
# shellcheck source=/dev/null
source <(kube-linter completion bash)
fi

command -v kube-linter &>/dev/null && _lazy_completion kube-linter kube-linter completion bash
{% endif %}
{% if 'kustomize' in install_cloud_clis_components %}
if command -v kustomize &>/dev/null; then
# shellcheck source=/dev/null
source <(kustomize completion bash)
fi

command -v kustomize &>/dev/null && _lazy_completion kustomize kustomize completion bash
{% endif %}
{% if 'stern' in install_cloud_clis_components %}
if command -v stern &>/dev/null; then
# shellcheck source=/dev/null
source <(stern --completion=bash)
fi

command -v stern &>/dev/null && _lazy_completion stern stern --completion=bash
{% endif %}
{% if 'helm' in install_cloud_clis_components %}
if command -v helm &>/dev/null; then
# shellcheck source=/dev/null
source <(helm completion bash)
fi
command -v helm &>/dev/null && _lazy_completion helm helm completion bash
{% endif %}
{% endif %}