From 32be384c0edeaf115d282c23665a0da75c8af7a6 Mon Sep 17 00:00:00 2001 From: Kenji Morishige Date: Mon, 23 Feb 2026 13:23:49 -0600 Subject: [PATCH] refactor: modular .bashrc.d/ structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rewrite .bashrc as minimal loader (34 lines → loads .bashrc.d/*.sh) - Clean .bash_profile: single source, Apple Silicon/Intel brew path - Add .bashrc.d/ with 7 topic modules: 00_env.sh PS1, OSTYPE, colors, pyenv 10_aliases.sh universal aliases 20_functions.sh proxy, dbash, git helpers 30_work.sh work-host detection, LDAP, AWX, Juniper tools (+ unified-hub-login with env-var creds) 40_k8s.sh kubectl completion + aliases 50_ai_env.sh WORKSPACE/DATA_ROOT/MODEL_ROOT paths 60_dotfiles.sh dotfiles manager aliases, zet shortcuts - Secrets (SN_PASSWORD, LDAP bind PWs, Unified Hub token) moved to ~/.bashrc.local (gitignored, written by setup script) - Update .dotfiles_manifest to track .bashrc.d directory --- .bash_profile | 34 ++- .bashrc | 588 ++---------------------------------- .bashrc.d/00_env.sh | 68 +++++ .bashrc.d/10_aliases.sh | 33 ++ .bashrc.d/20_functions.sh | 131 ++++++++ .bashrc.d/30_work.sh | 211 +++++++++++++ .bashrc.d/40_k8s.sh | 33 ++ .bashrc.d/50_ai_env.sh | 20 ++ .bashrc.d/60_dotfiles.sh | 19 ++ .dotfiles_manifest | 1 + scripts/dotfiles_manager.sh | 93 +++++- 11 files changed, 658 insertions(+), 573 deletions(-) create mode 100644 .bashrc.d/00_env.sh create mode 100644 .bashrc.d/10_aliases.sh create mode 100644 .bashrc.d/20_functions.sh create mode 100644 .bashrc.d/30_work.sh create mode 100644 .bashrc.d/40_k8s.sh create mode 100644 .bashrc.d/50_ai_env.sh create mode 100644 .bashrc.d/60_dotfiles.sh diff --git a/.bash_profile b/.bash_profile index c005597..31a6e8f 100644 --- a/.bash_profile +++ b/.bash_profile @@ -1,16 +1,24 @@ -. ~/.bashrc +# ~/.bash_profile — macOS login shell entry point +# Managed via dotfiles repo: http://172.27.0.35:3000/kenjim/dotfiles +# ============================================================================= -[[ -r "/opt/homebrew/etc/profile.d/bash_completion.sh" ]] && . "/opt/homebrew/etc/profile.d/bash_completion.sh" +# Load main shell config (which in turn loads .bashrc.d/ and .bashrc.local) +[ -f ~/.bashrc ] && source ~/.bashrc -test -e "${HOME}/.iterm2_shell_integration.bash" && source "${HOME}/.iterm2_shell_integration.bash" || true - -export BASH_SILENCE_DEPRECATION_WARNING=1 - -eval "$(/opt/homebrew/bin/brew shellenv)" - -export DOCKER_DEFAULT_PLATFORM=linux/amd64 - -# Load .bashrc if it exists -if [ -f ~/.bashrc ]; then - source ~/.bashrc +# Homebrew environment (Apple Silicon path first, Intel fallback) +if [ -x /opt/homebrew/bin/brew ]; then + eval "$(/opt/homebrew/bin/brew shellenv)" 2>/dev/null || true +elif [ -x /usr/local/bin/brew ]; then + eval "$(/usr/local/bin/brew shellenv)" 2>/dev/null || true fi + +# Bash completion (installed via brew) +[[ -r "/opt/homebrew/etc/profile.d/bash_completion.sh" ]] && \ + . "/opt/homebrew/etc/profile.d/bash_completion.sh" + +# iTerm2 shell integration (optional, sourced only if present) +test -e "${HOME}/.iterm2_shell_integration.bash" && \ + source "${HOME}/.iterm2_shell_integration.bash" || true + +# Suppress macOS "default shell is now zsh" warning +export BASH_SILENCE_DEPRECATION_WARNING=1 diff --git a/.bashrc b/.bashrc index 7228745..4d94df6 100644 --- a/.bashrc +++ b/.bashrc @@ -1,558 +1,34 @@ -# Kenji's .bashrc file -# Should be symlinked to DBX/projects/unix/.bashrc -# Also should be synced to /homes/kenjim/.bashrc - -if [ -f /etc/profile ]; then source /etc/profile; fi -if [ -f /etc/bashrc ]; then source /etc/bashrc; fi - -export PS1='\h:\w\$ ' -export PS2='> ' -export FTP_PASSIVE_MODE=YES -export RSYNC_RSH=ssh - -OSTYPE=$(uname -s) -HOSTNAME=$(hostname -f) -HOSTDOMAIN=$(hostname -d) -EDITOR=vim -set -o vi - -alias gitresetpw='git config --global' -alias giturl='git config --get remote.origin.url' - -# OS specific #################### -case $OSTYPE in -Linux) - alias ls='ls -F' - alias pst='ps axjf' - # specify default shell tools ########### - if type $EDITOR >/dev/null 2>&1; then - export EDITOR=$EDITOR - alias vi=${EDITOR} - else - export EDITOR=vi - fi - - if type less >/dev/null 2>&1; then - export PAGER='less' - else - export PAGER=more - fi - - function yaml2json { - python -c 'import sys, yaml, json; print(json.dumps(yaml.safe_load(sys.stdin.read())))' - } - - ;; -Darwin) - # pstree install with brew - alias pst='pstree' - ;; -FreeBSD) - export CLICOLOR=1 - LSCOLORS=fxgxcxdxbxegedabagacad - ;; -esac - -# terminal specific ############### -case $TERM in -xterm*) - export LS_COLORS='no=00:fi=00:di=00;35:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=00;31:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=00;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;31:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00;35:*.xpm=00;35:*.png=00;35:*.tif=00;35:*.pl=00;32:' - alias ls='ls -F --color' - #PROMPT_COMMAND='echo -ne "\033]0;${HOSTNAME}: ${PWD}\007"' - #HOSTNAMESHORT="${HOSTNAME%%.*}" - #export PROMPT_COMMAND='echo -ne "\033]0;${HOSTNAMESHORT}: ${PWD##*/}\007"' - #export PROMPT_COMMAND='echo -ne "\033];${PWD##*/}\007"; ':"$PROMPT_COMMAND"; - ;; -esac - -# Domain specific environment ################# -case $HOSTDOMAIN in -juniper.net | jnpr.net) - # juniper.net hosts - export PATH=$PATH:/volume/labtools/bin - export PGUSER=ddladmin - export PGHOST=localhost - - function setawx() { - echo -n "AWX Host: " - read TOWER_HOST - echo -n "AWX Username: " - read TOWER_USERNAME - echo -n "AWX Password: " - read TOWER_PASSWORD - awx -k -f human login - awx config -f human | grep base_url - } - - alias awxjobs='awx jobs list -f human --filter id,name,limit,failed --all' - - alias j_proxy_on='proxy_on qcwebproxylb.juniper.net:3128' - - case $OSTYPE in - Linux) - alias pstree='/usr/bin/pstree -c -l -a -n -p -u' - ;; - FreeBSD) ;; - esac - - case $HOSTNAME in - # Special configuration specific for Juniper hosts - etqc-kenjim* | engtech-dev*) - # applies to both workstations - #export MAIL=${HOME}/Mail/mbox - #export MAILCHECK=600 - PATH=${HOME}/bin:${PATH} - alias awx='~/.local/bin/awx' - - source /usr/share/bash-completion/bash_completion - - ;; - esac - ;; -esac - -#alias realias='$EDITOR ~/.aliases; source ~/.aliases; PWDSAVE=${PWD}; cd ~/cvs/kenjim; cvs -d kenji@rad.kenjim.com:/home/cvs commit -m "updated" .aliases; cd ${PWDSAVE}' -#alias rebash='$EDITOR ~/.bashrc; source ~/.bashrc; PWDSAVE=${PWD}; cd ~/cvs/kenjim; cvs -d kenji@rad.kenjim.com:/home/cvs commit -m "updated" .bashrc; cd ${PWDSAVE}' - -# Host specific configurations -case $HOSTNAME in -kenjim-mbp | etqc-kenjim-* | engtech-dev-01*) - # default aliases to override whatever is in .aliases - source $HOME/k8configs/engtech_k8_env.sh - - # Add RVM to PATH for scripting - # /usr/texbin for MacTex/Latex stuff - #PATH=$PATH:/usr/local/sbin:$HOME/bin:$HOME/.rvm/bin:/usr/texbin - PATH=$HOME/bin:~/.local/bin:$PATH - #PATH=/Users/kenjim/bin/Sencha/Cmd/5.1.2.52:$PATH - #export SENCHA_CMD_3_0_0="/Users/kenjim/bin/Sencha/Cmd/5.1.2.52" - export CLICOLOR=1 - - export RAILS_ENV=development - #export TIM_SSH_USER_PASS='B3k1nD+' - #export TIM_EK_R_LP='emccolganoansarikenjimjhayespsen' - export SN_USERNAME='_integ-soap-read' - export SN_PASSWORD='e3Qw&%b7' - - #export PYENV_VERSION='3.8.1' - #export ANSIBLE_CONFIG='/Users/kenjim/Juniper/git-m16/infra-ansible/ansible_cli.cfg' - #export KUBECONFIG='/Users/kenjim/Juniper/K8_Configs/kenjim-k8-config' - - # Personal Shortcuts - alias l='less' - alias t='tail -f' - alias psg='pstree | grep' - alias sl='screen -list' - alias sr='screen -r' - #alias conncount='netstat -ant | awk "{print $6}" | sort | uniq -c | sort -n' - alias a='alias' - alias h='history 25' - alias la='ls -a' - alias lf='ls -FA' - alias ll='ls -lAh|more' - alias lt='ls -tlAh|more' - alias tl='tail -f /var/log/messages' - alias sl='screen -list' - alias sr='screen -r' - alias ps-m='ps aux --sort -rss' - - #alias sa='ssh-add /export/kenjim/.ssh/juniper_kenjim_rsa_id' - #alias lair='ssh-keygen -f "/home/kenjim/.ssh/known_hosts" -R lair.kenjim.com; ssh -f -N -R 11322:localhost:22 lair' - #alias bar='ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o ServerAliveInterval=540 -o Compression=no -f -N -R 11322:localhost:22 root@192.241.205.115' - #alias sa='ssh-add /export/kenjim/.ssh/juniper_kenjim_rsa_id' - - alias rvmi='source "$HOME/.rvm/scripts/rvm"; echo "rvm initialized..."' - #alias psql='/Applications/Postgres.app/Contents/Versions/9.6/bin/psql' - #alias ctags='/usr/local/bin/ctags' - #alias rtags='/usr/local/bin/ctags -R -f .tags --languages=ruby --exclude=.git --exclude=log . $(bundle list --paths)' - - alias pstat='passenger status' - alias pstart='passenger start' - alias pstop='passenger stop' - alias prest='passenger stop; sleep 2; passenger start' - alias renv='env|sort|egrep -i "(gem|ruby|rvm|rails|tim)"' - - # Postgres Logins - alias pgtimdev='psql -U tim_api tim_api_dev' - alias pgtimqdev='psql -U tim_api -h ttqc-tim-mmonit-02 kenjim_devel' - alias pgtimqdev2='psql -U tim_api -h ttqc-tim-mmonit-02 kenjim_devel2' - alias pgtimtest='psql -U tim_api tim_api_test' - alias pgtimint='psql -h ttqc-tim-mm-02.juniper.net -U tim_api tim_api_int' - alias pgtimint2='psql -h ttsv-db-03.juniper.net -U tim_api tim_api_int2' - alias pgtimprod='psql -h ttqc-tim-mm-02.juniper.net -p 5432 -U tim_api tim' - alias pgtimloc='psql -U tim_api kenjim_tim' - alias pgtimweekly='psql -h ttqc-testdb-01 -U tim_api weekly_systest_live' - alias pgtimqmm='psql -h ttqc-tim-mmonit-02 -U mmonit mmonit' - alias pgtimbmm='psql -h ttbg-tim-mmonit-01 -U mmonit mmonit' - alias pgbdrqc='psql -h ttqc-bdr-db01.juniper.net -U tim_api systest_live' - alias pgbdrbg='psql -h ttbg-bdr-db01.juniper.net -U tim_api systest_live' - alias pgdlm='psql -h ttqc-dlm-db-ms.ttglb.juniper.net -U ddladmin systest_live' - - alias jira='jira-cli --v2 view --oneline --search-jql "assignee=kenjim and status!=closed and status!=resolved order by priority desc, created asc"' - - # retired - #alias tim='GLI_DEBUG=true bundle exec bin/timcl' - - #alias ap='ansible-playbook -i inventory/engtech-prod' - #alias ai='ANSIBLE_CONFIG=/Users/kenjim/Juniper/git-m16/infra-ansible/ansible_cli.cfg ansible-inventory -i inventory/cmdb/now.py -i inventory/engtech_prod' - - alias ai='ANSIBLE_CONFIG=/Users/kenjim/Juniper/git-m16/infra-ansible/ansible_cli.cfg ansible-inventory -i inventory/cmdb_rendered/engtech.yml' - alias ans='ANSIBLE_CONFIG=/Users/kenjim/Juniper/git-m16/infra-ansible/ansible_cli.cfg ansible -i ~/ansible/inventory/cmdb/now.py -i ~/ansible/inventory/engtech_prod' - #alias apy='rm ~/ansible.log ; ANSIBLE_CONFIG=/Users/kenjim/Juniper/git/infra-ansible/ansible_cli.cfg ANSIBLE_STDOUT_CALLBACK=yaml ansible-playbook -i inventory/cmdb/now.py -i inventory/engtech_prod' - alias apy='rm ~/ansible.log ; ANSIBLE_CONFIG=/Users/kenjim/Juniper/git/infra-ansible/ansible_cli.cfg ANSIBLE_STDOUT_CALLBACK=yaml ansible-playbook -i inventory/cmdb_rendered/engtech.yml --vault-id vault_engtech_default' - alias aps='rm ~/ansible.log ; ANSIBLE_CONFIG=/Users/kenjim/Juniper/git/infra-ansible/ansible_cli.cfg ANSIBLE_STDOUT_CALLBACK=selective ansible-playbook -i inventory/cmdb_rendered/engtech.yml --vault-id vault_engtech_default' - alias apa='rm ~/ansible.log ; ANSIBLE_CONFIG=/Users/kenjim/Juniper/git/infra-ansible/ansible_cli.cfg ANSIBLE_STDOUT_CALLBACK=actionable ansible-playbook -i inventory/cmdb_rendered/engtech.yml --vault-id vault_engtech_default' - alias apd='rm ~/ansible.log ; ANSIBLE_CONFIG=/Users/kenjim/Juniper/git/infra-ansible/ansible_cli.cfg ANSIBLE_STDOUT_CALLBACK=debug ansible-playbook -i inventory/cmdb/now.py -i inventory/engtech_prod' - alias apj='rm ~/ansible.log ; ANSIBLE_CONFIG=/Users/kenjim/Juniper/git/infra-ansible/ansible_cli.cfg ANSIBLE_STDOUT_CALLBACK=json ansible-playbook -i inventory/cmdb/now.py -i inventory/engtech_prod' - alias giturl='git config --get remote.origin.url' - alias gitresetpw='git config --global credential.helper osxkeychain' - - alias d='docker' - alias di='docker images' - alias dp='docker ps' - alias dr='docker run' - alias db='docker build' - alias dbash='docker run -it --entrypoint /bin/bash' - - function tmls { ssh $1 ls /etc/monit.d; } - function tmlog { ssh $1 tail -f /var/log/monit.log; } - - function tdiffstat { svn diff -x --ignore-eol-style -x -w https://tt-svn.juniper.net/svn/adp/projects/tim/tags/$1/rails-api https://tt-svn.juniper.net/svn/adp/projects/tim/trunk/rails-api | diffstat; } - function tdiff { svn diff -x --ignore-eol-style -x -w https://tt-svn.juniper.net/svn/adp/projects/tim/tags/$1/rails-api https://tt-svn.juniper.net/svn/adp/projects/tim/trunk/rails-api; } - - function timsvncopy { svn copy --parents https://tt-svn.juniper.net/svn/adp/projects/tim/trunk/rails-api https://tt-svn.juniper.net/svn/adp/projects/tim/tags/$1/rails-api -m "$1 new branch"; } - - function curl_time { curl -w "@curl-format.txt" -o /dev/null -s "$1"; } - - # copies my protected ssh pub key - function copy_pub_key { cat ~/.ssh/authorized_keys.kenjim-protected | ssh $1 'umask 0077; mkdir -p .ssh; cat >> .ssh/authorized_keys && echo "Key copied"'; } - - function ldaps() { - ldapsearch -LLL -x -b 'dc=jnpr,dc=net' -h ldap-eqx-lb.jnpr.net -D 'CN=_eng_jira_bind_new,OU=Service Accounts,OU=Misc,OU=Common,DC=jnpr,DC=net' -w 'xqYzhL%lLe!FIr!67LJX%7a^PWOWY0' sAMAccountName=$1 | perl -p00e 's/\r?\n //g' - } - - function ldaps2() { - ldapsearch -LLL -x -b 'dc=jnpr,dc=net' -h ldap-qnc-lb.jnpr.net -D 'CN=_eng_labrsrcmgr_bind,OU=Service Accounts,OU=Misc,OU=Common,DC=jnpr,DC=net' -w 'tF#w3St@nGqq36XZDym#857U)v4xKw' sAMAccountName=$1 | perl -p00e 's/\r?\n //g' - } - - function netseg() { - curl -k https://netseg.juniper.net/api/find_ip?hostname=$1 | jq '.' - } - - function dbash() { - docker exec -it $1 bash - } - - # Kubectl Autocomplete - source <(kubectl completion bash) - alias k=kubectl - complete -o default -F __start_kubectl k - - alias kc='kubectl config view' - alias kd='kubectl describe' - alias ke='kubectl explain' - alias kg='kubectl get' - alias kl='kubectl logs -f' - alias kp='kubectl get pods -o wide' - alias kq='kubectl describe quota' - alias ks='kubectl get services' - alias kuc='kubectl config use-context' - alias kpl='kubectl get pods --show-labels' - alias kdp='kubectl describe pod' - alias kgs='kubectl get secrets' - - # Kubectl aliases - alias kx='f() { [ "$1" ] && kubectl config use-context $1 || kubectl config current-context ; } ; f' - alias kn='f() { [ "$1" ] && kubectl config set-context --current --namespace $1 || kubectl config view --minify | grep namespace | cut -d" " -f6 ; } ; f' - - #export NVM_DIR="$HOME/.nvm" - #[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm - #[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion - - #export COPYFILE_DISABLE=1 - #export GRAPHVIZ_DOT=/usr/local/bin/dot - ;; -esac - -case $HOSTNAME in -################################################################################ -kenjim-mbp*) - #export DOCKER_DEFAULT_PLATFORM=linux/amd64 - - # add MacTex Path, installer unable to add symlink in /usr/texbin - #PATH=/usr/local/opt/libiconv/bin:/Library/TeX/texbin:$PATH - #PATH=/usr/local/opt/libiconv/bin:/Library/TeX/texbin:$PATH - #PATH=/opt/homebrew/bin:$PATH - - #export LDFLAGS="-L/usr/local/opt/zlib/lib" - #export CPPFLAGS="-I/usr/local/opt/zlib/include" - #source ~/perl5/perlbrew/etc/bashrc - - if command -v pyenv 1>/dev/null 2>&1; then - export PYENV_ROOT="$HOME/.pyenv" - export PATH="$PYENV_ROOT/bin:$PATH" - eval "$(pyenv init --path)" - eval "$(pyenv init -)" - fi - - export AWS_PROFILE=kenjim-qnc - # make connection to k ssh config first localhost forward: LocalForward 8888 qnc-engdata5vs3.juniper.net:80 - #alias aws='aws --endpoint-url http://localhost:8888' - alias aws-pgdb-qnc-du="aws --profile pgdb-qnc s3 ls s3://engtech-pgdb-s3-qnc/ --recursive | awk 'BEGIN {total=0}{total+=\$3}END{print total/1024/1024/1024\" GB\"}'" - alias aws-pgdb-bng-du="aws --profile pgdb-bng s3 ls s3://engtech-pgdb-s3-bng/ --recursive | awk 'BEGIN {total=0}{total+=\$3}END{print total/1024/1024/1024\" GB\"}'" - alias aws-pgdb-qnc-ls="aws --profile pgdb-qnc s3 ls s3://engtech-pgdb-s3-qnc/ --recursive" - alias aws-pgdb-bng-ls="aws --profile pgdb-bng s3 ls s3://engtech-pgdb-s3-bng/ --recursive" - export AWS_SDK_LOAD_CONFIG=1 - - #export KUBECONFIG='/Users/kenjim/.kube/config' - - function k8proxy { - export KUBECONFIG='/Users/kenjim/Juniper/K8_Configs/kenjim-k8-config' - export no_proxy="localhost,127.0.0.1,localaddress,.localdomain.com" - export http_proxy="socks5://localhost:3133/" - export https_proxy=$http_proxy - export ftp_proxy=$http_proxy - export rsync_proxy=$http_proxy - } - - function killcrashplan() { - sudo launchctl unload /Library/LaunchDaemons/com.crashplan.engine.plist - } - ;; - -etqc-kenjim-* | engtech-dev-01*) - # Make symlink git checkout location - # ~k8configs -> ~/EngTech/Infra/k8configs - source $HOME/k8configs/engtech_k8_env.sh - export AWS_PROFILE=pgdb-qnc - # make connection to k8dev ssh config first localhost forward: LocalForward 8888 qnc-engdata5vs3.juniper.net:80 - alias aws='aws --endpoint-url http://qnc-engdata5vs3.juniper.net' - alias aws-pgdb-qnc-du="aws s3 ls s3://engtech-pgdb-s3-qnc/ --recursive | awk 'BEGIN {total=0}{total+=\$3}END{print total/1024/1024/1024\" GB\"}'" - alias aws-pgdb-bng-du="aws s3 ls s3://engtech-pgdb-s3-bng/ --recursive | awk 'BEGIN {total=0}{total+=\$3}END{print total/1024/1024/1024\" GB\"}'" - alias aws-pgdb-qnc-ls="aws s3 ls s3://engtech-pgdb-s3-qnc/ --recursive" - alias aws-pgdb-bng-ls="aws s3 ls s3://engtech-pgdb-s3-bng/ --recursive" - export AWS_SDK_LOAD_CONFIG=1 - ;; - -################################################################################ -# akira-mt*) -# #export CVSROOT=ace.kenjim.com:/cvs -# alias rvmi='source "$HOME/.rvm/scripts/rvm"; echo "rvm initialized..."' -# alias kl='ssh kenjim-lnx-tun' -# #dispwin -d1 -I ~/projects/monitor_calibration/GTX660_VP2770_C60_B29_D65.icm -# #dispwin -d2 -I ~/projects/monitor_calibration/GTX660_HDMI_23EA63_C83_B26_D65.icm -# export RAILS_ENV=kenjim_local - -# ;; -################################################################################ -esac - -function proxy_on() { - export no_proxy="localhost,127.0.0.1,localaddress,.localdomain.com" - - if (($# > 0)); then - #valid=$(echo $@ | sed -n 's/\([0-9]\{1,3\}.\)\{4\}:\([0-9]\+\)/&/p') - #if [[ $valid != $@ ]]; then - # >&2 echo "Invalid address" - # return 1 - #fi - - export http_proxy="http://$1/" - export https_proxy=$http_proxy - export ftp_proxy=$http_proxy - export rsync_proxy=$http_proxy - echo "Proxy environment variable set." - return 0 - fi - - echo -n "username: " - read username - if [[ $username != "" ]]; then - echo -n "password: " - read -es password - local pre="$username:$password@" - fi - - echo -n "server: " - read server - echo -n "port: " - read port - - export http_proxy="http://$pre$server:$port/" - export https_proxy=$http_proxy - export ftp_proxy=$http_proxy - export rsync_proxy=$http_proxy - export HTTP_PROXY=$http_proxy - export HTTPS_PROXY=$http_proxy - export FTP_PROXY=$http_proxy - export RSYNC_PROXY=$http_proxy -} - -function proxy_off() { - unset http_proxy - unset https_proxy - unset ftp_proxy - unset rsync_proxy - echo -e "Proxy environment variable removed." -} - -function unified-hub-login() { - UNIFIED_HUB_URL="unified-hub.juniper.net" - UNIFIED_HUB_USERNAME="kenjim@juniper.net" - UNIFIED_HUB_PASSWORD="cmVmdGtuOjAxOjE3NDA3ODI3NDk6OGt6WUJvcFJwa29RdEhKWWE1U1MzNkJnZXVE" - echo $UNIFIED_HUB_PASSWORD | docker login -u "$UNIFIED_HUB_USERNAME" --password-stdin $UNIFIED_HUB_URL -} - -unified-hub-engtech-bin-upload() { - local file="$1" - local remote_path="$2" - - # Validation - if [[ -z "$file" ]] || [[ -z "$remote_path" ]]; then - echo "Usage: unified-hub-engtech-bin-upload " - echo "" - echo "Example:" - echo " unified-hub-engtech-bin-upload kubectl dl.k8s.io/release/v1.28.4/bin/linux/amd64/kubectl" - echo "" - echo "Uploads to: https://unified-hub.juniper.net/artifactory/engtech-binaries/" - return 1 - fi - - if [[ ! -f "$file" ]]; then - echo "Error: File '$file' not found in current directory" - return 1 - fi - - # Configuration - local username="kenjim@juniper.net" - local token="cmVmdGtuOjAxOjE3NzY5NzgzNDY6Nm4xZU9uOEZvUzVLM1RNQkxXY2ZVdThBOVFY" - local base_url="https://unified-hub.juniper.net/artifactory/engtech-binaries" - local full_url="${base_url}/${remote_path}" - - echo "📦 Uploading: $file" - echo "📍 To: $full_url" - echo "" - - # Upload with progress - if curl -u "${username}:${token}" \ - -T "$file" \ - --progress-bar \ - "$full_url"; then - echo "" - echo "✅ Upload successful!" - echo "🔗 URL: $full_url" - else - echo "" - echo "❌ Upload failed!" - return 1 - fi -} - -# Add this to your ~/.bashrc or ~/.zshrc - -git-prune-branches() { - echo "🌿 Git Branch Cleanup" - echo "====================" - echo "" - - # Check if we're in a git repo - if ! git rev-parse --git-dir > /dev/null 2>&1; then - echo "❌ Error: Not in a git repository" - return 1 - fi - - # Get main branch name (main or master) - local main_branch=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@') - if [[ -z "$main_branch" ]]; then - main_branch="main" - fi - - echo "📡 Fetching latest from remote and pruning..." - git fetch --all --prune - echo "" - - # Show merged branches - echo "🗑️ Local branches merged into $main_branch:" - local merged_branches=$(git branch --merged "$main_branch" | grep -v "^\*" | grep -v "$main_branch" | grep -v "master") - if [[ -z "$merged_branches" ]]; then - echo " (none)" - else - echo "$merged_branches" - echo "" - read -p "Delete these merged local branches? (y/N): " -n 1 -r - echo - if [[ $REPLY =~ ^[Yy]$ ]]; then - echo "$merged_branches" | xargs -n 1 git branch -d - echo "✅ Merged branches deleted" - else - echo "⏭️ Skipped" - fi - fi - - echo "" - # Show orphaned branches - echo "🗑️ Local branches tracking deleted remotes:" - local orphaned_branches=$(git branch -vv | grep ': gone]' | awk '{print $1}') - if [[ -z "$orphaned_branches" ]]; then - echo " (none)" - else - echo "$orphaned_branches" - echo "" - read -p "Delete these orphaned local branches? (y/N): " -n 1 -r - echo - if [[ $REPLY =~ ^[Yy]$ ]]; then - echo "$orphaned_branches" | xargs -n 1 git branch -D - echo "✅ Orphaned branches deleted" - else - echo "⏭️ Skipped" - fi - fi - - echo "" - echo "📊 Remaining local branches:" - git branch -vv - - echo "" - echo "✨ Cleanup complete!" -} - -alias git-clean='git-prune-branches' - -touch ~/.aliases -source ~/.aliases - - -### ENTERPRISE_AI_ENV ### -export WORKSPACE="$HOME/workspace" -export DATA_ROOT="$HOME/data" -export MODEL_ROOT="$HOME/models" - -# HuggingFace cache location -export HF_HOME="$MODEL_ROOT/huggingface" - -# Ollama model location -export OLLAMA_MODELS="$MODEL_ROOT/ollama" - -# Convenience aliases -alias ws='cd $WORKSPACE' -alias src='cd $WORKSPACE/src' -alias data='cd $DATA_ROOT' -alias models='cd $MODEL_ROOT' - -# Machine-local overrides (cloud paths, work vs personal — not synced via dotfiles) +# ~/.bashrc — Kenji's shell configuration loader +# Managed via dotfiles repo: http://172.27.0.35:3000/kenjim/dotfiles +# +# Structure: +# ~/.bashrc — this file: loader only (SHARED, tracked in dotfiles) +# ~/.bashrc.d/*.sh — modular configs by topic (SHARED, tracked in dotfiles) +# ~/.bashrc.local — machine secrets + profile overrides (NOT tracked) +# ~/.aliases — legacy aliases file (optional, NOT tracked) +# +# Machines: +# kenjim-mbp work Mac (MACHINE_PROFILE=work) +# kenjim-mbm personal Mac (MACHINE_PROFILE=personal) +# etqc-*, etbg-*, engtech-dev-* work servers (auto-detected by hostname) +# zet local Gitea server +# ============================================================================= + +# Source system-wide files first +[ -f /etc/profile ] && source /etc/profile +[ -f /etc/bashrc ] && source /etc/bashrc + +# Load all modular configs (sorted: 00_ before 10_ etc.) +if [ -d ~/.bashrc.d ]; then + for _f in ~/.bashrc.d/*.sh; do + [ -r "$_f" ] && source "$_f" + done + unset _f +fi + +# Machine-local overrides: MACHINE_PROFILE, CLOUD_ROOT, secrets +# This file is written by setup_enterprise_ai_bash.sh — never committed [ -f ~/.bashrc.local ] && source ~/.bashrc.local - -### DOTFILES_ALIASES ### -export DOTFILES_DIR="$HOME/dotfiles" -export DOTFILES_REMOTE="http://172.27.0.35:3000/kenjim/dotfiles" - -# Dotfiles manager shortcut -alias dotfiles='bash $HOME/scripts/dotfiles_manager.sh' -alias dot='bash $HOME/scripts/dotfiles_manager.sh' - -# Quick sync alias -alias dots-sync='bash $HOME/scripts/dotfiles_manager.sh sync' -alias dots-push='bash $HOME/scripts/dotfiles_manager.sh push' -alias dots-status='bash $HOME/scripts/dotfiles_manager.sh status' - +# Legacy aliases file (kept for compatibility) +[ -f ~/.aliases ] && source ~/.aliases diff --git a/.bashrc.d/00_env.sh b/.bashrc.d/00_env.sh new file mode 100644 index 0000000..dde44f9 --- /dev/null +++ b/.bashrc.d/00_env.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +# 00_env.sh — Core environment: prompt, editor, OS detection, terminal colors +# Shared across all machines. No secrets. No machine-specific paths. +# ============================================================================ + +export PS1='\h:\w\$ ' +export PS2='> ' +export FTP_PASSIVE_MODE=YES +export RSYNC_RSH=ssh + +# Use short hostname consistently (macOS and Linux) +HOSTNAME=$(hostname -s) +HOSTDOMAIN=$(hostname -d 2>/dev/null || true) +export HOSTNAME HOSTDOMAIN + +EDITOR=vim +export EDITOR +set -o vi + +# ----------------------------------------------------------------------- +# OS-specific +# ----------------------------------------------------------------------- +_OSTYPE=$(uname -s) + +case $_OSTYPE in +Linux) + alias ls='ls -F' + alias pst='ps axjf' + if type "$EDITOR" >/dev/null 2>&1; then + alias vi="${EDITOR}" + else + EDITOR=vi + fi + export PAGER=$(type less >/dev/null 2>&1 && echo less || echo more) + + function yaml2json { + python -c 'import sys, yaml, json; print(json.dumps(yaml.safe_load(sys.stdin.read())))' + } + ;; +Darwin) + alias pst='pstree' + export CLICOLOR=1 + export DOCKER_DEFAULT_PLATFORM=linux/amd64 + export BASH_SILENCE_DEPRECATION_WARNING=1 + + # pyenv — only init if installed + if command -v pyenv >/dev/null 2>&1; then + export PYENV_ROOT="$HOME/.pyenv" + export PATH="$PYENV_ROOT/bin:$PATH" + eval "$(pyenv init --path)" + eval "$(pyenv init -)" + fi + ;; +FreeBSD) + export CLICOLOR=1 + export LSCOLORS=fxgxcxdxbxegedabagacad + ;; +esac + +# ----------------------------------------------------------------------- +# Terminal-specific +# ----------------------------------------------------------------------- +case $TERM in +xterm*) + export LS_COLORS='no=00:fi=00:di=00;35:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=00;31:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=00;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;31:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00;35:*.xpm=00;35:*.png=00;35:*.tif=00;35:*.pl=00;32:' + alias ls='ls -F --color' + ;; +esac diff --git a/.bashrc.d/10_aliases.sh b/.bashrc.d/10_aliases.sh new file mode 100644 index 0000000..bc623f8 --- /dev/null +++ b/.bashrc.d/10_aliases.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# 10_aliases.sh — Universal aliases, safe on all machines and profiles +# ============================================================================ + +# Navigation / file listing +alias l='less' +alias t='tail -f' +alias la='ls -a' +alias lf='ls -FA' +alias ll='ls -lAh | more' +alias lt='ls -tlAh | more' +alias a='alias' +alias h='history 25' + +# Screen +alias sl='screen -list' +alias sr='screen -r' + +# Process inspection +alias psg='pstree | grep' +alias ps-m='ps aux --sort -rss' + +# Docker — short forms +alias d='docker' +alias di='docker images' +alias dp='docker ps' +alias dr='docker run' +alias db='docker build' + +# Git helpers +alias giturl='git config --get remote.origin.url' +alias gitresetpw='git config --global credential.helper osxkeychain' +alias git-clean='git-prune-branches' diff --git a/.bashrc.d/20_functions.sh b/.bashrc.d/20_functions.sh new file mode 100644 index 0000000..32f5d1c --- /dev/null +++ b/.bashrc.d/20_functions.sh @@ -0,0 +1,131 @@ +#!/usr/bin/env bash +# 20_functions.sh — Universal shell functions, safe on all machines +# ============================================================================ + +# ----------------------------------------------------------------------- +# Proxy management +# ----------------------------------------------------------------------- +function proxy_on() { + export no_proxy="localhost,127.0.0.1,localaddress,.localdomain.com" + + if (($# > 0)); then + export http_proxy="http://$1/" + export https_proxy=$http_proxy + export ftp_proxy=$http_proxy + export rsync_proxy=$http_proxy + export HTTP_PROXY=$http_proxy + export HTTPS_PROXY=$http_proxy + echo "Proxy set to: $http_proxy" + return 0 + fi + + echo -n "username (leave blank if none): " + read -r username + local pre="" + if [[ $username != "" ]]; then + echo -n "password: " + read -rs password; echo + pre="$username:$password@" + fi + + echo -n "server: " + read -r server + echo -n "port: " + read -r port + + export http_proxy="http://${pre}${server}:${port}/" + export https_proxy=$http_proxy + export ftp_proxy=$http_proxy + export rsync_proxy=$http_proxy + export HTTP_PROXY=$http_proxy + export HTTPS_PROXY=$http_proxy + export FTP_PROXY=$http_proxy + export RSYNC_PROXY=$http_proxy + echo "Proxy environment set." +} + +function proxy_off() { + unset http_proxy https_proxy ftp_proxy rsync_proxy + unset HTTP_PROXY HTTPS_PROXY FTP_PROXY RSYNC_PROXY + echo "Proxy environment cleared." +} + +# ----------------------------------------------------------------------- +# Docker helpers +# ----------------------------------------------------------------------- +function dbash() { + docker exec -it "$1" bash +} + +function curl_time() { + curl -w "@curl-format.txt" -o /dev/null -s "$1" +} + +# ----------------------------------------------------------------------- +# Git: prune merged/orphaned local branches +# ----------------------------------------------------------------------- +function git-prune-branches() { + echo "🌿 Git Branch Cleanup" + echo "====================" + echo + + if ! git rev-parse --git-dir >/dev/null 2>&1; then + echo "❌ Not in a git repository"; return 1 + fi + + local main_branch + main_branch=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@') + [[ -z "$main_branch" ]] && main_branch="main" + + echo "📡 Fetching and pruning..." + git fetch --all --prune + echo + + local merged_branches + merged_branches=$(git branch --merged "$main_branch" | grep -v "^\*" | grep -v "$main_branch" | grep -v "master" || true) + echo "🗑️ Merged branches:" + if [[ -z "$merged_branches" ]]; then + echo " (none)" + else + echo "$merged_branches" + echo + read -r -p "Delete merged branches? (y/N): " -n 1 + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + echo "$merged_branches" | xargs -n 1 git branch -d + echo "✅ Deleted." + fi + fi + + echo + local orphaned + orphaned=$(git branch -vv | grep ': gone]' | awk '{print $1}' || true) + echo "🗑️ Orphaned branches (remote deleted):" + if [[ -z "$orphaned" ]]; then + echo " (none)" + else + echo "$orphaned" + echo + read -r -p "Delete orphaned branches? (y/N): " -n 1 + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + echo "$orphaned" | xargs -n 1 git branch -D + echo "✅ Deleted." + fi + fi + + echo + echo "📊 Remaining branches:" + git branch -vv + echo + echo "✨ Done." +} + +# ----------------------------------------------------------------------- +# SSH key distribution helper +# ----------------------------------------------------------------------- +function copy_pub_key() { + # Usage: copy_pub_key user@host + cat ~/.ssh/authorized_keys.kenjim-protected | \ + ssh "$1" 'umask 0077; mkdir -p .ssh; cat >> .ssh/authorized_keys && echo "Key copied"' +} diff --git a/.bashrc.d/30_work.sh b/.bashrc.d/30_work.sh new file mode 100644 index 0000000..c12c9b0 --- /dev/null +++ b/.bashrc.d/30_work.sh @@ -0,0 +1,211 @@ +#!/usr/bin/env bash +# 30_work.sh — Work / Juniper environment config +# +# Loaded when MACHINE_PROFILE=work OR hostname matches work patterns. +# Secrets (passwords, tokens, API keys) are NOT stored here. +# They live in ~/.bashrc.local on each work machine. +# ============================================================================ + +# ----------------------------------------------------------------------- +# Host detection helper — true on work Mac and all work servers +# ----------------------------------------------------------------------- +_is_work_host() { + # Check MACHINE_PROFILE first (set in .bashrc.local on managed machines) + [[ "${MACHINE_PROFILE:-}" == "work" ]] && return 0 + # Fallback hostname pattern for work servers where .bashrc.local may not exist + case "$(hostname -s)" in + kenjim-mbp*|etqc-*|etbg-*|engtech-dev-*|zet*) return 0 ;; + *) return 1 ;; + esac +} + +_is_work_host || return 0 # exit this file silently on personal machines + +# ----------------------------------------------------------------------- +# PATH additions (work only) +# ----------------------------------------------------------------------- +PATH="${HOME}/bin:${HOME}/.local/bin:${PATH}" +export PATH + +# Juniper lab tools (Linux work servers) +if [[ -d /volume/labtools/bin ]]; then + export PATH="${PATH}:/volume/labtools/bin" +fi + +# ----------------------------------------------------------------------- +# Domain: Juniper +# ----------------------------------------------------------------------- +case "${HOSTDOMAIN:-}" in +juniper.net|jnpr.net) + export PGUSER=ddladmin + export PGHOST=localhost + ;; +esac + +# ----------------------------------------------------------------------- +# Work Mac (kenjim-mbp) specific +# ----------------------------------------------------------------------- +case "$(hostname -s)" in +kenjim-mbp*) + export CLICOLOR=1 + export RAILS_ENV=development + export AWS_SDK_LOAD_CONFIG=1 + + # AWS profiles — work Mac uses named profile via ~/.aws/config + # Override AWS_PROFILE in ~/.bashrc.local if needed per-project + export AWS_PROFILE="${AWS_PROFILE:-kenjim-qnc}" + + alias aws-pgdb-qnc-du="aws --profile pgdb-qnc s3 ls s3://engtech-pgdb-s3-qnc/ --recursive | awk 'BEGIN {total=0}{total+=\$3}END{print total/1024/1024/1024\" GB\"}'" + alias aws-pgdb-bng-du="aws --profile pgdb-bng s3 ls s3://engtech-pgdb-s3-bng/ --recursive | awk 'BEGIN {total=0}{total+=\$3}END{print total/1024/1024/1024\" GB\"}'" + alias aws-pgdb-qnc-ls="aws --profile pgdb-qnc s3 ls s3://engtech-pgdb-s3-qnc/ --recursive" + alias aws-pgdb-bng-ls="aws --profile pgdb-bng s3 ls s3://engtech-pgdb-s3-bng/ --recursive" + + function k8proxy() { + export KUBECONFIG="${HOME}/Juniper/K8_Configs/kenjim-k8-config" + export no_proxy="localhost,127.0.0.1,localaddress,.localdomain.com" + export http_proxy="socks5://localhost:3133/" + export https_proxy=$http_proxy + export ftp_proxy=$http_proxy + export rsync_proxy=$http_proxy + echo "k8s proxy set via localhost:3133" + } + + function killcrashplan() { + sudo launchctl unload /Library/LaunchDaemons/com.crashplan.engine.plist + } + ;; + +# ----------------------------------------------------------------------- +# Work servers (etqc-*, etbg-*, engtech-dev-*) +# ----------------------------------------------------------------------- +etqc-*|etbg-*|engtech-dev-*) + export AWS_SDK_LOAD_CONFIG=1 + export AWS_PROFILE=pgdb-qnc + + alias aws-pgdb-qnc-du="aws s3 ls s3://engtech-pgdb-s3-qnc/ --recursive | awk 'BEGIN {total=0}{total+=\$3}END{print total/1024/1024/1024\" GB\"}'" + alias aws-pgdb-bng-du="aws s3 ls s3://engtech-pgdb-s3-bng/ --recursive | awk 'BEGIN {total=0}{total+=\$3}END{print total/1024/1024/1024\" GB\"}'" + alias aws-pgdb-qnc-ls="aws s3 ls s3://engtech-pgdb-s3-qnc/ --recursive" + alias aws-pgdb-bng-ls="aws s3 ls s3://engtech-pgdb-s3-bng/ --recursive" + + # Bash completion on Linux work servers + [ -f /usr/share/bash-completion/bash_completion ] && \ + source /usr/share/bash-completion/bash_completion + ;; +esac + +# ----------------------------------------------------------------------- +# Ansible — Juniper infra-ansible shortcuts +# ----------------------------------------------------------------------- +_ANSIBLE_CFG="${HOME}/Juniper/git/infra-ansible/ansible_cli.cfg" +_ANSIBLE_INV="inventory/cmdb_rendered/engtech.yml" + +if [[ -f "$_ANSIBLE_CFG" ]]; then + alias apy="rm -f ~/ansible.log; ANSIBLE_CONFIG=${_ANSIBLE_CFG} ANSIBLE_STDOUT_CALLBACK=yaml ansible-playbook -i ${_ANSIBLE_INV} --vault-id vault_engtech_default" + alias aps="rm -f ~/ansible.log; ANSIBLE_CONFIG=${_ANSIBLE_CFG} ANSIBLE_STDOUT_CALLBACK=selective ansible-playbook -i ${_ANSIBLE_INV} --vault-id vault_engtech_default" + alias apa="rm -f ~/ansible.log; ANSIBLE_CONFIG=${_ANSIBLE_CFG} ANSIBLE_STDOUT_CALLBACK=actionable ansible-playbook -i ${_ANSIBLE_INV} --vault-id vault_engtech_default" + alias ai="ANSIBLE_CONFIG=${_ANSIBLE_CFG} ansible-inventory -i ${_ANSIBLE_INV}" + alias ans="ANSIBLE_CONFIG=${_ANSIBLE_CFG} ansible -i ~/ansible/inventory/cmdb/now.py -i ~/ansible/inventory/engtech_prod" +fi +unset _ANSIBLE_CFG _ANSIBLE_INV + +# ----------------------------------------------------------------------- +# AWX / Tower +# ----------------------------------------------------------------------- +alias awxjobs='awx jobs list -f human --filter id,name,limit,failed --all' + +function setawx() { + echo -n "AWX Host: "; read -r TOWER_HOST + echo -n "AWX Username: "; read -r TOWER_USERNAME + echo -n "AWX Password: "; read -r -s TOWER_PASSWORD; echo + export TOWER_HOST TOWER_USERNAME TOWER_PASSWORD + awx -k -f human login + awx config -f human | grep base_url +} + +# ----------------------------------------------------------------------- +# Monit helpers (remote) +# ----------------------------------------------------------------------- +function tmls() { ssh "$1" ls /etc/monit.d; } +function tmlog() { ssh "$1" tail -f /var/log/monit.log; } + +# ----------------------------------------------------------------------- +# Postgres shortcuts (Juniper TIM environments) +# ----------------------------------------------------------------------- +alias pgtimdev='psql -U tim_api tim_api_dev' +alias pgtimtest='psql -U tim_api tim_api_test' +alias pgtimqdev='psql -U tim_api -h ttqc-tim-mmonit-02 kenjim_devel' +alias pgtimint='psql -h ttqc-tim-mm-02.juniper.net -U tim_api tim_api_int' +alias pgtimint2='psql -h ttsv-db-03.juniper.net -U tim_api tim_api_int2' +alias pgtimprod='psql -h ttqc-tim-mm-02.juniper.net -p 5432 -U tim_api tim' +alias pgtimloc='psql -U tim_api kenjim_tim' +alias pgtimweekly='psql -h ttqc-testdb-01 -U tim_api weekly_systest_live' +alias pgtimqmm='psql -h ttqc-tim-mmonit-02 -U mmonit mmonit' +alias pgtimbmm='psql -h ttbg-tim-mmonit-01 -U mmonit mmonit' +alias pgbdrqc='psql -h ttqc-bdr-db01.juniper.net -U tim_api systest_live' +alias pgbdrbg='psql -h ttbg-bdr-db01.juniper.net -U tim_api systest_live' +alias pgdlm='psql -h ttqc-dlm-db-ms.ttglb.juniper.net -U ddladmin systest_live' + +# ----------------------------------------------------------------------- +# Juniper proxy shortcut +# ----------------------------------------------------------------------- +alias j_proxy_on='proxy_on qcwebproxylb.juniper.net:3128' + +# ----------------------------------------------------------------------- +# k8configs env (if checked out) +# ----------------------------------------------------------------------- +[[ -f "${HOME}/k8configs/engtech_k8_env.sh" ]] && \ + source "${HOME}/k8configs/engtech_k8_env.sh" + +# ----------------------------------------------------------------------- +# RVM (Ruby — if installed) +# ----------------------------------------------------------------------- +alias rvmi='source "$HOME/.rvm/scripts/rvm"; echo "rvm initialized..."' + +# ----------------------------------------------------------------------- +# LDAP helpers — credentials injected from ~/.bashrc.local +# Set JNPR_LDAP_BIND_DN and JNPR_LDAP_BIND_PW in ~/.bashrc.local +# ----------------------------------------------------------------------- +function ldaps() { + local dn="${JNPR_LDAP_BIND_DN:-CN=_eng_jira_bind_new,OU=Service Accounts,OU=Misc,OU=Common,DC=jnpr,DC=net}" + local pw="${JNPR_LDAP_BIND_PW:?Set JNPR_LDAP_BIND_PW in ~/.bashrc.local}" + ldapsearch -LLL -x -b 'dc=jnpr,dc=net' \ + -h ldap-eqx-lb.jnpr.net \ + -D "$dn" -w "$pw" \ + sAMAccountName="$1" | perl -p00e 's/\r?\n //g' +} + +function ldaps2() { + local dn="${JNPR_LDAP_BIND_DN2:-CN=_eng_labrsrcmgr_bind,OU=Service Accounts,OU=Misc,OU=Common,DC=jnpr,DC=net}" + local pw="${JNPR_LDAP_BIND_PW2:?Set JNPR_LDAP_BIND_PW2 in ~/.bashrc.local}" + ldapsearch -LLL -x -b 'dc=jnpr,dc=net' \ + -h ldap-qnc-lb.jnpr.net \ + -D "$dn" -w "$pw" \ + sAMAccountName="$1" | perl -p00e 's/\r?\n //g' +} + +# ----------------------------------------------------------------------- +# Network / misc Juniper tools +# ----------------------------------------------------------------------- +function netseg() { + curl -k "https://netseg.juniper.net/api/find_ip?hostname=$1" | jq '.' +} + +# Jira CLI shortcut +alias jira='jira-cli --v2 view --oneline --search-jql "assignee=kenjim and status!=closed and status!=resolved order by priority desc, created asc"' + +# ----------------------------------------------------------------------- +# Unified Hub (Artifactory / unified-hub.juniper.net) +# Credentials pulled from ~/.bashrc.local: +# UNIFIED_HUB_USERNAME e.g. kenjim@juniper.net +# UNIFIED_HUB_TOKEN base64 API token from Artifactory +# ----------------------------------------------------------------------- +function unified-hub-login() { + local url="unified-hub.juniper.net" + local user="${UNIFIED_HUB_USERNAME:-}" + local token="${UNIFIED_HUB_TOKEN:-}" + if [[ -z "$user" || -z "$token" ]]; then + echo "ERROR: UNIFIED_HUB_USERNAME and UNIFIED_HUB_TOKEN must be set (add to ~/.bashrc.local)" >&2 + return 1 + fi + echo "$token" | docker login -u "$user" --password-stdin "$url" +} diff --git a/.bashrc.d/40_k8s.sh b/.bashrc.d/40_k8s.sh new file mode 100644 index 0000000..b5be991 --- /dev/null +++ b/.bashrc.d/40_k8s.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# 40_k8s.sh — Kubernetes / kubectl aliases and completion +# +# Loaded on all machines but only meaningful on work hosts. +# kubectl must be installed for completion to activate. +# ============================================================================ + +command -v kubectl >/dev/null 2>&1 || return 0 # skip silently if not installed + +# Bash completion +source <(kubectl completion bash) +alias k=kubectl +complete -o default -F __start_kubectl k + +# Config inspection +alias kc='kubectl config view' +alias kuc='kubectl config use-context' + +# Resource shortcuts +alias kd='kubectl describe' +alias ke='kubectl explain' +alias kg='kubectl get' +alias kl='kubectl logs -f' +alias kp='kubectl get pods -o wide' +alias kq='kubectl describe quota' +alias ks='kubectl get services' +alias kpl='kubectl get pods --show-labels' +alias kdp='kubectl describe pod' +alias kgs='kubectl get secrets' + +# Context / namespace switchers +alias kx='f() { [ "$1" ] && kubectl config use-context "$1" || kubectl config current-context; }; f' +alias kn='f() { [ "$1" ] && kubectl config set-context --current --namespace "$1" || kubectl config view --minify | grep namespace | cut -d" " -f6; }; f' diff --git a/.bashrc.d/50_ai_env.sh b/.bashrc.d/50_ai_env.sh new file mode 100644 index 0000000..0f82f35 --- /dev/null +++ b/.bashrc.d/50_ai_env.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# 50_ai_env.sh — AI / ML workspace environment variables and aliases +# Shared across all machines, profile-neutral. +# ============================================================================ + +export WORKSPACE="$HOME/workspace" +export DATA_ROOT="$HOME/data" +export MODEL_ROOT="$HOME/models" + +# HuggingFace cache +export HF_HOME="$MODEL_ROOT/huggingface" + +# Ollama model store +export OLLAMA_MODELS="$MODEL_ROOT/ollama" + +# Navigation shortcuts +alias ws='cd $WORKSPACE' +alias src='cd $WORKSPACE/src' +alias data='cd $DATA_ROOT' +alias models='cd $MODEL_ROOT' diff --git a/.bashrc.d/60_dotfiles.sh b/.bashrc.d/60_dotfiles.sh new file mode 100644 index 0000000..7f8ed97 --- /dev/null +++ b/.bashrc.d/60_dotfiles.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +# 60_dotfiles.sh — Dotfiles manager aliases and git server shortcut +# ============================================================================ + +export DOTFILES_DIR="$HOME/dotfiles" +export DOTFILES_REMOTE="http://172.27.0.35:3000/kenjim/dotfiles" + +# Main command +alias dotfiles='bash $HOME/scripts/dotfiles_manager.sh' +alias dot='bash $HOME/scripts/dotfiles_manager.sh' + +# Quick shortcuts +alias dots-sync='bash $HOME/scripts/dotfiles_manager.sh sync' +alias dots-push='bash $HOME/scripts/dotfiles_manager.sh push' +alias dots-status='bash $HOME/scripts/dotfiles_manager.sh status' + +# Gitea server shortcut (ssh into the server itself) +alias zet='ssh zet' +alias gitea='open http://172.27.0.35:3000 2>/dev/null || echo "http://172.27.0.35:3000"' diff --git a/.dotfiles_manifest b/.dotfiles_manifest index 6128631..b4a563c 100644 --- a/.dotfiles_manifest +++ b/.dotfiles_manifest @@ -1,5 +1,6 @@ .bash_profile .bashrc +.bashrc.d .gitconfig .ssh/config .ssh/known_hosts diff --git a/scripts/dotfiles_manager.sh b/scripts/dotfiles_manager.sh index da2343f..8525b7d 100755 --- a/scripts/dotfiles_manager.sh +++ b/scripts/dotfiles_manager.sh @@ -107,6 +107,28 @@ dgit() { git -C "$DOTFILES_DIR" "$@" } +# Credentials file (never committed — chmod 600) +CREDS_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/dotfiles/credentials" + +# Read saved token (returns empty string if not set) +_read_token() { + [ -f "$CREDS_FILE" ] && grep -m1 '^GITEA_TOKEN=' "$CREDS_FILE" | cut -d= -f2- || true +} + +# Inject token into an HTTP(S) remote URL for a single git operation. +# Keeps the stored remote URL clean — only the transient call gets credentials. +_authed_url() { + local url="$1" + local token; token="${GITEA_TOKEN:-$(_read_token)}" + if [[ -n "$token" && "$url" == http* ]]; then + local host_path; host_path="${url#*://}" + host_path="${host_path#*@}" # strip any existing user:pass + echo "${url%%://*}://kenjim:${token}@${host_path}" + else + echo "$url" + fi +} + # ----------------------------------------------------------------------- # COMMAND: init # ----------------------------------------------------------------------- @@ -200,6 +222,9 @@ vault/ # Machine-local overrides — never commit (written by setup_enterprise_ai_bash.sh) .bashrc.local .bash_profile.local + +# Credential store — never commit +.config/dotfiles/credentials GITIGNORE # Seed README @@ -403,6 +428,8 @@ cmd_sync() { bold "=== Syncing from remote ===" is_git_repo || die "Not a git repo: $DOTFILES_DIR. Run 'init' first." + local pull_url; pull_url="$(_authed_url "$DOTFILES_REMOTE")" + # Stash any local changes so pull is clean local stashed=false if ! dgit diff --quiet || ! dgit diff --cached --quiet; then @@ -411,8 +438,10 @@ cmd_sync() { stashed=true fi - dgit pull --rebase origin main 2>/dev/null || dgit pull --rebase origin master 2>/dev/null || { - warn "Could not pull (remote unreachable or branch mismatch). Working offline." + dgit pull --rebase "$pull_url" main 2>/dev/null || \ + dgit pull --rebase "$pull_url" master 2>/dev/null || { + warn "Could not pull (remote unreachable or no token set). Working offline." + warn "Run 'dotfiles auth' to save credentials if push/pull keep failing." } if $stashed; then @@ -423,6 +452,49 @@ cmd_sync() { success "Sync complete." } +# ----------------------------------------------------------------------- +# CREDENTIAL HELPERS — cmd_auth is defined further below +# (CREDS_FILE, _read_token, _authed_url are in the HELPERS block above) +# ----------------------------------------------------------------------- + +# ----------------------------------------------------------------------- +# COMMAND: auth — save Gitea credentials once +# ----------------------------------------------------------------------- +cmd_auth() { + bold "=== Gitea Authentication Setup ===" + echo + info "Remote: $DOTFILES_REMOTE" + info "Credentials are saved to $CREDS_FILE (chmod 600, never committed)" + echo + echo "Options:" + echo " [1] Personal Access Token (recommended — Settings → Applications → Generate Token)" + echo " [2] Password (not recommended)" + read -r -p "Choice [1]: " _method + _method="${_method:-1}" + + local token + if [[ "$_method" == "2" ]]; then + read -r -s -p "Gitea password: " token; echo + else + echo + info "To generate a token: $DOTFILES_REMOTE (open in browser)" + info " → Settings (top-right avatar) → Applications → Generate Token" + info " → Name it 'dotfiles', tick Contents+Write, copy the token" + echo + read -r -s -p "Paste token: " token; echo + fi + + [[ -z "$token" ]] && die "No token entered." + + mkdir -p "$(dirname "$CREDS_FILE")" + chmod 700 "$(dirname "$CREDS_FILE")" + printf 'GITEA_TOKEN=%s\n' "$token" > "$CREDS_FILE" + chmod 600 "$CREDS_FILE" + + success "Credentials saved to $CREDS_FILE" + info "Test with: dotfiles push" +} + # ----------------------------------------------------------------------- # COMMAND: push # ----------------------------------------------------------------------- @@ -444,11 +516,22 @@ cmd_push() { local branch branch=$(dgit rev-parse --abbrev-ref HEAD) + # Build push URL — inject token for HTTP remotes so we never hang on a prompt + local push_url; push_url="$(_authed_url "$DOTFILES_REMOTE")" + if [[ "$push_url" == "$DOTFILES_REMOTE" && "$DOTFILES_REMOTE" == http* ]]; then + warn "No Gitea token found. Run 'dotfiles auth' to save one." + warn "Attempting push anyway (may hang waiting for password)..." + fi + # Set upstream on first push if needed if ! dgit config "branch.$branch.remote" &>/dev/null; then - dgit push --set-upstream origin "$branch" + dgit push --set-upstream "$push_url" "$branch" + # Record the clean URL as upstream (not the token-embedded one) + dgit remote set-url origin "$DOTFILES_REMOTE" 2>/dev/null || true + dgit config "branch.$branch.remote" origin + dgit config "branch.$branch.merge" "refs/heads/$branch" else - dgit push origin "$branch" + dgit push "$push_url" "$branch" fi success "Pushed to $DOTFILES_REMOTE ($branch)." @@ -802,6 +885,7 @@ ${BOLD}COMMANDS — Core${RESET} sync Pull latest from remote, reapply symlinks push [message] Commit all changes and push to $DOTFILES_REMOTE status / list Show tracked files and symlink health + auth Save Gitea token so push never prompts for credentials ${BOLD}COMMANDS — SSH & Keys${RESET} ssh-setup Guided SSH config + key migration @@ -945,6 +1029,7 @@ main() { ssh-setup) cmd_ssh_setup "$@" ;; ssh-export) cmd_ssh_export "$@" ;; ssh-import) cmd_ssh_import "$@" ;; + auth) cmd_auth "$@" ;; remote-bootstrap) cmd_remote_bootstrap "$@" ;; help|--help|-h) cmd_help ;; *)