From 8502ad8253f664cbe162aaf729803f33f082678c Mon Sep 17 00:00:00 2001 From: waiting <1661926154@qq.com> Date: Wed, 5 Mar 2025 18:22:25 +0800 Subject: [PATCH] feat: pg completion for subcommands and postgres CLUSTER_NAME supports subcommands - edit-config: Edit cluster configuration - list: List the Patroni members for a given Patroni supports running anywhere and as any user --- roles/node/files/pg_completion | 80 ++++++++++++++++++++++++++++++++++ roles/node/tasks/admin.yml | 19 ++++++-- 2 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 roles/node/files/pg_completion diff --git a/roles/node/files/pg_completion b/roles/node/files/pg_completion new file mode 100644 index 000000000..cb04f0298 --- /dev/null +++ b/roles/node/files/pg_completion @@ -0,0 +1,80 @@ +#!/usr/bin/env bash +#==============================================================# +# File : pg_completion +# Desc : auto-completion for pg commands +# Path : /etc/bash_completion.d/pg +# License : MIT +# Author : waitingsong +#==============================================================# + +# subcommands +# - edit-config: Edit cluster configuration +# - list: List the Patroni members for a given Patroni + + +cache_duration=30 # seconds +cache_timestamp=0 +cache_pg_cls="" +pg_subcommands="list edit-config" # from patronictl + +if ! command -v ansible-inventory &> /dev/null; then + echo "ansible-inventory not found, skip auto-completion" + return +fi + +if ! command -v jq &> /dev/null; then + echo "jq not found, skip auto-completion" + return +fi + +yml='pigsty.yml' +yml2="/home/dba/pigsty/${yml}" +INVENTORY_FILE='' +if [[ -f "${yml2}" ]]; then + INVENTORY_FILE="${yml2}" +fi + +# Pick up pg* clusters from inventory file +_get_pg_cls() { + ansible-inventory -i "$1" --list 2>/dev/null | jq -r '.all.children | map(select(type == "string" and startswith("pg"))) | .[] ' +} + +_pg_completions() { + local subcommands="$2" + local cur prev words cword + _get_comp_words_by_ref -n : cur prev words cword + # echo "command: $command, subcommands: $subcommands, cur: $cur, prev: $prev, words: $words, cword: $cword" + + if [[ $cword -eq 1 ]]; then + COMPREPLY=($(compgen -W "$pg_subcommands" -- "$cur")) + return + fi + + if [[ -n $prev ]] && [[ ! " $pg_subcommands " =~ " $prev " ]]; then + echo $subcommands + return + fi + + local FILE='' + if [[ -f $yml ]]; then + FILE=$yml + else + FILE="${INVENTORY_FILE}" + fi + + if [[ $cword -eq 2 ]] && [[ -f "$FILE" ]]; then + local current_time=$(date +%s) + if [[ $cache_timestamp -eq 0 ]] || (( current_time - cache_timestamp > cache_duration )); then + # echo "refresh cache" + cache_pg_cls=$(_get_pg_cls $FILE) + cache_timestamp=$current_time + fi + + if [[ -n "$cache_pg_cls" ]]; then + COMPREPLY=($(compgen -W "$cache_pg_cls" -- "$cur")) + fi + fi +} + +complete -F _pg_completions pg + diff --git a/roles/node/tasks/admin.yml b/roles/node/tasks/admin.yml index c3aea8d5f..9e33732f2 100644 --- a/roles/node/tasks/admin.yml +++ b/roles/node/tasks/admin.yml @@ -23,7 +23,18 @@ {% endfor %} #--------------------------------------------------------------# -# Stage 3: Setup pam ulimit for node users [node_ulimit] +# Stage 3: Add node pg completion [node_alias] +#--------------------------------------------------------------# +- name: add pg completion + copy: src={{ item.src }} dest={{ item.dest }} mode=0644 + tags: node_alias + ignore_errors: true + with_items: + - { src: pg_completion ,dest: /etc/bash_completion.d/pg } + + +#--------------------------------------------------------------# +# Stage 4: Setup pam ulimit for node users [node_ulimit] #--------------------------------------------------------------# - name: set pam ulimit tags: node_ulimit @@ -31,7 +42,7 @@ #--------------------------------------------------------------# -# Stage 4: Create data dir if not exists [node_data] +# Stage 5: Create data dir if not exists [node_data] #--------------------------------------------------------------# - name: assure node data dir exists tags: node_data @@ -45,7 +56,7 @@ #--------------------------------------------------------------# -# Stage 5: Create default users/groups [node_admin] +# Stage 6: Create default users/groups [node_admin] #--------------------------------------------------------------# - name: create os node users and groups tags: node_admin @@ -107,4 +118,4 @@ key: "{{ lookup('file', item) }}" with_fileglob: - "~/.ssh/id*.pub" -... \ No newline at end of file +...