github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/worker/uniter/runner/debug/client.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package debug 5 6 import ( 7 "encoding/base64" 8 "strings" 9 10 goyaml "gopkg.in/yaml.v1" 11 ) 12 13 type hookArgs struct { 14 Hooks []string `yaml:"hooks,omitempty"` 15 } 16 17 // ClientScript returns a bash script suitable for executing 18 // on the unit system to intercept hooks via tmux shell. 19 func ClientScript(c *HooksContext, hooks []string) string { 20 // If any hook is "*", then the client is interested in all. 21 for _, hook := range hooks { 22 if hook == "*" { 23 hooks = nil 24 break 25 } 26 } 27 28 s := strings.Replace(debugHooksClientScript, "{unit_name}", c.Unit, -1) 29 s = strings.Replace(s, "{tmux_conf}", tmuxConf, 1) 30 s = strings.Replace(s, "{entry_flock}", c.ClientFileLock(), -1) 31 s = strings.Replace(s, "{exit_flock}", c.ClientExitFileLock(), -1) 32 33 yamlArgs := encodeArgs(hooks) 34 base64Args := base64.StdEncoding.EncodeToString(yamlArgs) 35 s = strings.Replace(s, "{hook_args}", base64Args, 1) 36 return s 37 } 38 39 func encodeArgs(hooks []string) []byte { 40 // Marshal to YAML, then encode in base64 to avoid shell escapes. 41 yamlArgs, err := goyaml.Marshal(hookArgs{Hooks: hooks}) 42 if err != nil { 43 // This should not happen: we're in full control. 44 panic(err) 45 } 46 return yamlArgs 47 } 48 49 const debugHooksClientScript = `#!/bin/bash 50 ( 51 # Lock the juju-<unit>-debug lockfile. 52 flock -n 8 || (echo "Failed to acquire {entry_flock}: unit is already being debugged" 2>&1; exit 1) 53 ( 54 # Close the inherited lock FD, or tmux will keep it open. 55 exec 8>&- 56 57 # Write out the debug-hooks args. 58 echo "{hook_args}" | base64 -d > {entry_flock} 59 60 # Lock the juju-<unit>-debug-exit lockfile. 61 flock -n 9 || exit 1 62 63 # Wait for tmux to be installed. 64 while [ ! -f /usr/bin/tmux ]; do 65 sleep 1 66 done 67 68 if [ ! -f ~/.tmux.conf ]; then 69 if [ -f /usr/share/byobu/profiles/tmux ]; then 70 # Use byobu/tmux profile for familiar keybindings and branding 71 echo "source-file /usr/share/byobu/profiles/tmux" > ~/.tmux.conf 72 else 73 # Otherwise, use the legacy juju/tmux configuration 74 cat > ~/.tmux.conf <<END 75 {tmux_conf} 76 END 77 fi 78 fi 79 80 ( 81 # Close the inherited lock FD, or tmux will keep it open. 82 exec 9>&- 83 exec tmux new-session -s {unit_name} 84 ) 85 ) 9>{exit_flock} 86 ) 8>{entry_flock} 87 exit $? 88 ` 89 90 const tmuxConf = ` 91 # Status bar 92 set-option -g status-bg black 93 set-option -g status-fg white 94 95 set-window-option -g window-status-current-bg red 96 set-window-option -g window-status-current-attr bright 97 98 set-option -g status-right '' 99 100 # Panes 101 set-option -g pane-border-fg white 102 set-option -g pane-active-border-fg white 103 104 # Monitor activity on windows 105 set-window-option -g monitor-activity on 106 107 # Screen bindings, since people are more familiar with that. 108 set-option -g prefix C-a 109 bind C-a last-window 110 bind a send-key C-a 111 112 bind | split-window -h 113 bind - split-window -v 114 115 # Fix CTRL-PGUP/PGDOWN for vim 116 set-window-option -g xterm-keys on 117 118 # Prevent ESC key from adding delay and breaking Vim's ESC > arrow key 119 set-option -s escape-time 0 120 `