From 5af10484425ac388be51e5d4c9b792b323702cd3 Mon Sep 17 00:00:00 2001 From: Wesley Hayutin Date: Tue, 12 Aug 2025 13:36:06 -0600 Subject: [PATCH 1/2] DNM: example bash completion Signed-off-by: Wesley Hayutin Co-Authored: Entirely by mr. claude --- bash_completion.sh | 94 ++++++++++++++++++ install_completion.sh | 48 +++++++++ kubectl_complete_oadp.sh | 99 +++++++++++++++++++ kubectl_oadp_completion.sh | 198 +++++++++++++++++++++++++++++++++++++ oadp_completion.sh | 70 +++++++++++++ 5 files changed, 509 insertions(+) create mode 100644 bash_completion.sh create mode 100644 install_completion.sh create mode 100644 kubectl_complete_oadp.sh create mode 100755 kubectl_oadp_completion.sh create mode 100644 oadp_completion.sh diff --git a/bash_completion.sh b/bash_completion.sh new file mode 100644 index 00000000..01ff6400 --- /dev/null +++ b/bash_completion.sh @@ -0,0 +1,94 @@ +#!/bin/bash + +# Bash completion script for kubectl oadp plugin +# Source this file or add it to your bash completion directory + +_kubectl_oadp_complete() { + local cur prev words cword + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + words=("${COMP_WORDS[@]}") + cword=$COMP_CWORD + + # Find where 'oadp' appears in the command line + local oadp_index=0 + for ((i=0; i<${#words[@]}; i++)); do + if [[ "${words[i]}" == "oadp" ]]; then + oadp_index=$i + break + fi + done + + # Calculate position relative to 'oadp' command + local pos=$((cword - oadp_index)) + + case $pos in + 1) + # First level subcommands after 'oadp' + COMPREPLY=($(compgen -W "backup restore version client nabsl-request nonadmin na" -- "$cur")) + ;; + 2) + # Second level - depends on first subcommand + local subcmd="${words[$((oadp_index + 1))]}" + case "$subcmd" in + backup) + COMPREPLY=($(compgen -W "create delete describe download get logs" -- "$cur")) + ;; + restore) + COMPREPLY=($(compgen -W "create delete describe get logs" -- "$cur")) + ;; + client) + COMPREPLY=($(compgen -W "config" -- "$cur")) + ;; + nabsl-request) + COMPREPLY=($(compgen -W "get describe approve reject" -- "$cur")) + ;; + nonadmin|na) + COMPREPLY=($(compgen -W "backup bsl" -- "$cur")) + ;; + version) + # No subcommands for version + COMPREPLY=() + ;; + esac + ;; + 3) + # Third level - for nonadmin commands + local subcmd="${words[$((oadp_index + 1))]}" + local subsubcmd="${words[$((oadp_index + 2))]}" + case "$subcmd" in + nonadmin|na) + case "$subsubcmd" in + backup) + COMPREPLY=($(compgen -W "create get logs describe delete" -- "$cur")) + ;; + bsl) + COMPREPLY=($(compgen -W "create" -- "$cur")) + ;; + esac + ;; + esac + ;; + *) + # For resource names and flags, provide common options + if [[ "$cur" == -* ]]; then + COMPREPLY=($(compgen -W "--help -h --namespace -n --kubeconfig --context --include-resources --exclude-resources --include-namespaces --exclude-namespaces --snapshot-volumes --wait --dry-run -o --output" -- "$cur")) + fi + ;; + esac +} + +# Register completion for different command forms +complete -F _kubectl_oadp_complete kubectl-oadp +complete -F _kubectl_oadp_complete oadp + +# For kubectl plugin integration +_kubectl_oadp() { + _kubectl_oadp_complete +} + +# Register with kubectl if available +if command -v kubectl >/dev/null 2>&1; then + complete -F _kubectl_oadp_complete kubectl +fi \ No newline at end of file diff --git a/install_completion.sh b/install_completion.sh new file mode 100644 index 00000000..bb89c6df --- /dev/null +++ b/install_completion.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +# Installation script for OADP bash completion + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +COMPLETION_SCRIPT="$SCRIPT_DIR/kubectl_oadp_completion.sh" + +echo "Installing OADP bash completion..." + +# Check if the completion script exists +if [[ ! -f "$COMPLETION_SCRIPT" ]]; then + echo "Error: Completion script not found at $COMPLETION_SCRIPT" + exit 1 +fi + +# Option 1: Install to user's bash completion directory +USER_COMPLETION_DIR="$HOME/.bash_completion.d" +if [[ ! -d "$USER_COMPLETION_DIR" ]]; then + mkdir -p "$USER_COMPLETION_DIR" +fi + +cp "$COMPLETION_SCRIPT" "$USER_COMPLETION_DIR/kubectl_oadp" +echo "Installed to: $USER_COMPLETION_DIR/kubectl_oadp" + +# Option 2: Add to .bashrc if not already there +BASHRC="$HOME/.bashrc" +SOURCE_LINE="source $USER_COMPLETION_DIR/kubectl_oadp" + +if [[ -f "$BASHRC" ]] && ! grep -q "kubectl_oadp" "$BASHRC"; then + echo "" >> "$BASHRC" + echo "# OADP kubectl plugin completion" >> "$BASHRC" + echo "$SOURCE_LINE" >> "$BASHRC" + echo "Added source line to $BASHRC" +fi + +echo "" +echo "Installation complete!" +echo "" +echo "To activate completion in your current shell, run:" +echo " source $USER_COMPLETION_DIR/kubectl_oadp" +echo "" +echo "Or restart your terminal to load it automatically." +echo "" +echo "Test it with:" +echo " kubectl oadp " +echo " oc oadp " \ No newline at end of file diff --git a/kubectl_complete_oadp.sh b/kubectl_complete_oadp.sh new file mode 100644 index 00000000..043d122c --- /dev/null +++ b/kubectl_complete_oadp.sh @@ -0,0 +1,99 @@ +#!/bin/bash + +# Bash completion for kubectl oadp plugin + +_kubectl_oadp() { + local cur prev words cword + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + # Get all words in the command line + words=("${COMP_WORDS[@]}") + cword=$COMP_CWORD + + # Handle 'kubectl oadp ...' command structure + case $cword in + 2) + # Completing after 'kubectl oadp' + local commands="backup restore version client nabsl-request nonadmin na" + COMPREPLY=($(compgen -W "$commands" -- "$cur")) + ;; + 3) + # Completing after 'kubectl oadp SUBCOMMAND' + case "${words[2]}" in + backup) + COMPREPLY=($(compgen -W "create delete describe download get logs" -- "$cur")) + ;; + restore) + COMPREPLY=($(compgen -W "create delete describe get logs" -- "$cur")) + ;; + client) + COMPREPLY=($(compgen -W "config" -- "$cur")) + ;; + nabsl-request) + COMPREPLY=($(compgen -W "get describe approve reject" -- "$cur")) + ;; + nonadmin|na) + COMPREPLY=($(compgen -W "backup bsl" -- "$cur")) + ;; + esac + ;; + 4) + # Completing after 'kubectl oadp nonadmin/na SUBCOMMAND' + if [[ "${words[2]}" == "nonadmin" || "${words[2]}" == "na" ]]; then + case "${words[3]}" in + backup) + COMPREPLY=($(compgen -W "create get logs describe delete" -- "$cur")) + ;; + bsl) + COMPREPLY=($(compgen -W "create" -- "$cur")) + ;; + esac + fi + ;; + *) + # For flags/options + if [[ "$cur" == -* ]]; then + local flags="--help -h --namespace -n --kubeconfig --context --include-resources --exclude-resources --include-namespaces --exclude-namespaces --snapshot-volumes --wait --dry-run -o --output" + COMPREPLY=($(compgen -W "$flags" -- "$cur")) + fi + ;; + esac +} + +# Simple test function +test_oadp_completion() { + echo "=== Testing OADP Completion ===" + + # Test 1: Basic completion + echo "Test: kubectl oadp " + COMP_WORDS=("kubectl" "oadp" "") + COMP_CWORD=2 + _kubectl_oadp + echo "Results: ${COMPREPLY[*]}" + echo + + # Test 2: Nonadmin completion + echo "Test: kubectl oadp nonadmin " + COMP_WORDS=("kubectl" "oadp" "nonadmin" "") + COMP_CWORD=3 + _kubectl_oadp + echo "Results: ${COMPREPLY[*]}" + echo + + # Test 3: Backup completion + echo "Test: kubectl oadp nonadmin backup " + COMP_WORDS=("kubectl" "oadp" "nonadmin" "backup" "") + COMP_CWORD=4 + _kubectl_oadp + echo "Results: ${COMPREPLY[*]}" + echo +} + +# Register completion for kubectl +complete -F _kubectl_oadp kubectl + +echo "OADP bash completion loaded successfully!" +echo "Try typing: kubectl oadp " +echo "Run 'test_oadp_completion' to verify it works" \ No newline at end of file diff --git a/kubectl_oadp_completion.sh b/kubectl_oadp_completion.sh new file mode 100755 index 00000000..93704408 --- /dev/null +++ b/kubectl_oadp_completion.sh @@ -0,0 +1,198 @@ +#!/bin/bash + +# Bash completion for kubectl oadp plugin that integrates with kubectl's completion system +# This script properly handles "kubectl oadp" and "oc oadp" commands + +# First, ensure kubectl/oc completion is loaded +if ! complete -p kubectl &>/dev/null; then + if command -v kubectl &>/dev/null; then + source <(kubectl completion bash 2>/dev/null) + fi +fi + +if ! complete -p oc &>/dev/null; then + # Check for oc in common locations + oc_cmd="" + if command -v oc &>/dev/null; then + oc_cmd="oc" + elif [[ -x "$HOME/.local/bin/oc" ]]; then + oc_cmd="$HOME/.local/bin/oc" + elif [[ -x "/usr/local/bin/oc" ]]; then + oc_cmd="/usr/local/bin/oc" + fi + + if [[ -n "$oc_cmd" ]]; then + source <($oc_cmd completion bash 2>/dev/null) + echo "Loaded oc completion from: $oc_cmd" + fi +fi + +# Override the kubectl completion function to handle oadp plugin +_kubectl_oadp_plugin() { + local cur prev words cword + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + words=("${COMP_WORDS[@]}") + cword=$COMP_CWORD + + # Find the position of "oadp" in the command line + local oadp_index=-1 + for ((i=0; i<${#words[@]}; i++)); do + if [[ "${words[i]}" == "oadp" ]]; then + oadp_index=$i + break + fi + done + + # If "oadp" is not found, fall back to default kubectl completion + if [[ $oadp_index -eq -1 ]]; then + return 1 + fi + + # Calculate position relative to "oadp" + local pos=$((cword - oadp_index)) + + case $pos in + 1) + # Completing after "kubectl/oc oadp" + local commands="backup restore version client nabsl-request nonadmin na" + COMPREPLY=($(compgen -W "$commands" -- "$cur")) + return 0 + ;; + 2) + # Completing after "kubectl/oc oadp SUBCOMMAND" + case "${words[$((oadp_index + 1))]}" in + backup) + COMPREPLY=($(compgen -W "create delete describe download get logs" -- "$cur")) + ;; + restore) + COMPREPLY=($(compgen -W "create delete describe get logs" -- "$cur")) + ;; + client) + COMPREPLY=($(compgen -W "config" -- "$cur")) + ;; + nabsl-request) + COMPREPLY=($(compgen -W "get describe approve reject" -- "$cur")) + ;; + nonadmin|na) + COMPREPLY=($(compgen -W "backup bsl" -- "$cur")) + ;; + esac + return 0 + ;; + 3) + # Completing after "kubectl/oc oadp nonadmin/na SUBCOMMAND" + if [[ "${words[$((oadp_index + 1))]}" == "nonadmin" || "${words[$((oadp_index + 1))]}" == "na" ]]; then + case "${words[$((oadp_index + 2))]}" in + backup) + COMPREPLY=($(compgen -W "create get logs describe delete" -- "$cur")) + ;; + bsl) + COMPREPLY=($(compgen -W "create" -- "$cur")) + ;; + esac + fi + return 0 + ;; + *) + # For flags/options + if [[ "$cur" == -* ]]; then + local flags="--help -h --namespace -n --kubeconfig --context --include-resources --exclude-resources --include-namespaces --exclude-namespaces --snapshot-volumes --wait --dry-run -o --output" + COMPREPLY=($(compgen -W "$flags" -- "$cur")) + return 0 + fi + ;; + esac + + return 1 +} + +# Store the original kubectl completion function +if declare -f _kubectl &>/dev/null; then + _kubectl_original() { + # Call the original kubectl completion + _kubectl "$@" + } +fi + +if declare -f _oc &>/dev/null; then + _oc_original() { + # Call the original oc completion + _oc "$@" + } +fi + +# New kubectl completion function that handles oadp plugin +_kubectl_with_oadp() { + # Check if this is an oadp command + local words=("${COMP_WORDS[@]}") + for word in "${words[@]}"; do + if [[ "$word" == "oadp" ]]; then + _kubectl_oadp_plugin + if [[ ${#COMPREPLY[@]} -gt 0 ]]; then + return 0 + fi + break + fi + done + + # Fall back to original kubectl completion + if declare -f _kubectl_original &>/dev/null; then + _kubectl_original + fi +} + +# New oc completion function that handles oadp plugin +_oc_with_oadp() { + # Check if this is an oadp command + local words=("${COMP_WORDS[@]}") + for word in "${words[@]}"; do + if [[ "$word" == "oadp" ]]; then + _kubectl_oadp_plugin + if [[ ${#COMPREPLY[@]} -gt 0 ]]; then + return 0 + fi + break + fi + done + + # Fall back to original oc completion + if declare -f _oc_original &>/dev/null; then + _oc_original + fi +} + +# Override the completion functions +complete -F _kubectl_with_oadp kubectl +complete -F _oc_with_oadp oc + +# Test function +test_kubectl_oadp_completion() { + echo "=== Testing kubectl oadp completion ===" + + echo "Test 1: kubectl oadp " + COMP_WORDS=("kubectl" "oadp" "") + COMP_CWORD=2 + _kubectl_oadp_plugin + echo "Results: ${COMPREPLY[*]}" + echo + + echo "Test 2: oc oadp nonadmin " + COMP_WORDS=("oc" "oadp" "nonadmin" "") + COMP_CWORD=3 + _kubectl_oadp_plugin + echo "Results: ${COMPREPLY[*]}" + echo + + echo "Test 3: kubectl oadp na backup " + COMP_WORDS=("kubectl" "oadp" "na" "backup" "") + COMP_CWORD=4 + _kubectl_oadp_plugin + echo "Results: ${COMPREPLY[*]}" + echo +} + +echo "kubectl/oc oadp completion loaded!" +echo "Try: kubectl oadp or oc oadp " +echo "Run 'test_kubectl_oadp_completion' to test" \ No newline at end of file diff --git a/oadp_completion.sh b/oadp_completion.sh new file mode 100644 index 00000000..362fd1b7 --- /dev/null +++ b/oadp_completion.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +# Bash completion for standalone oadp binary (kubectl-oadp) + +_oadp_complete() { + local cur prev words cword + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + # Get all words in the command line + words=("${COMP_WORDS[@]}") + cword=$COMP_CWORD + + # Handle 'oadp ...' or 'kubectl-oadp ...' command structure + case $cword in + 1) + # Completing after 'oadp' or 'kubectl-oadp' + local commands="backup restore version client nabsl-request nonadmin na" + COMPREPLY=($(compgen -W "$commands" -- "$cur")) + ;; + 2) + # Completing after 'oadp SUBCOMMAND' + case "${words[1]}" in + backup) + COMPREPLY=($(compgen -W "create delete describe download get logs" -- "$cur")) + ;; + restore) + COMPREPLY=($(compgen -W "create delete describe get logs" -- "$cur")) + ;; + client) + COMPREPLY=($(compgen -W "config" -- "$cur")) + ;; + nabsl-request) + COMPREPLY=($(compgen -W "get describe approve reject" -- "$cur")) + ;; + nonadmin|na) + COMPREPLY=($(compgen -W "backup bsl" -- "$cur")) + ;; + esac + ;; + 3) + # Completing after 'oadp nonadmin/na SUBCOMMAND' + if [[ "${words[1]}" == "nonadmin" || "${words[1]}" == "na" ]]; then + case "${words[2]}" in + backup) + COMPREPLY=($(compgen -W "create get logs describe delete" -- "$cur")) + ;; + bsl) + COMPREPLY=($(compgen -W "create" -- "$cur")) + ;; + esac + fi + ;; + *) + # For flags/options + if [[ "$cur" == -* ]]; then + local flags="--help -h --namespace -n --kubeconfig --context --include-resources --exclude-resources --include-namespaces --exclude-namespaces --snapshot-volumes --wait --dry-run -o --output" + COMPREPLY=($(compgen -W "$flags" -- "$cur")) + fi + ;; + esac +} + +# Register completion for both binary names +complete -F _oadp_complete oadp +complete -F _oadp_complete kubectl-oadp + +echo "OADP standalone binary completion loaded!" +echo "Try typing: oadp or kubectl-oadp " \ No newline at end of file From 80266aeca94ca056b4f4c6d75a3540b4efa23b4b Mon Sep 17 00:00:00 2001 From: Wesley Hayutin Date: Tue, 12 Aug 2025 13:37:07 -0600 Subject: [PATCH 2/2] update --- kubectl_oadp_completion.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/kubectl_oadp_completion.sh b/kubectl_oadp_completion.sh index 93704408..ac188640 100755 --- a/kubectl_oadp_completion.sh +++ b/kubectl_oadp_completion.sh @@ -11,18 +11,19 @@ if ! complete -p kubectl &>/dev/null; then fi if ! complete -p oc &>/dev/null; then - # Check for oc in common locations + # Check for oc in common locations, prioritizing ~/.local/bin oc_cmd="" - if command -v oc &>/dev/null; then - oc_cmd="oc" - elif [[ -x "$HOME/.local/bin/oc" ]]; then + if [[ -x "$HOME/.local/bin/oc" ]]; then oc_cmd="$HOME/.local/bin/oc" + elif command -v oc &>/dev/null; then + oc_cmd="oc" elif [[ -x "/usr/local/bin/oc" ]]; then oc_cmd="/usr/local/bin/oc" fi if [[ -n "$oc_cmd" ]]; then - source <($oc_cmd completion bash 2>/dev/null) + # Load oc completion and ensure it gets registered + eval "$($oc_cmd completion bash 2>/dev/null)" echo "Loaded oc completion from: $oc_cmd" fi fi