_knife 5.73 KB
Newer Older
Frank Louwers's avatar
Frank Louwers committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#compdef knife

# These flags should be available everywhere according to man knife
knife_general_flags=( --help --server-url --key --config --editor --format --log_level --logfile --no-editor --user --print-after --version --yes )

# knife has a very special syntax, some example calls are:
# knife status
# knife cookbook list
# knife role show ROLENAME
# knife data bag show DATABAGNAME
# knife role show ROLENAME --attribute ATTRIBUTENAME
# knife cookbook show COOKBOOKNAME COOKBOOKVERSION recipes

# The -Q switch in compadd allow for completions of things like "data bag" without having to go through two rounds of completion and avoids zsh inserting a \ for escaping spaces
_knife() {
  local curcontext="$curcontext" state line
  typeset -A opt_args
  cloudproviders=(bluebox ec2 rackspace slicehost terremark)
  _arguments \
    '1: :->knifecmd'\
    '2: :->knifesubcmd'\
    '3: :->knifesubcmd2' \
    '4: :->knifesubcmd3' \
    '5: :->knifesubcmd4' \
    '6: :->knifesubcmd5'
  
  case $state in
  knifecmd)
29
    compadd -Q "$@" bootstrap client configure cookbook "cookbook site" "data bag" exec environment index node recipe role search ssh status windows $cloudproviders
Frank Louwers's avatar
Frank Louwers committed
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
  ;;
  knifesubcmd)
    case $words[2] in
    (bluebox|ec2|rackspace|slicehost|terremark)
      compadd "$@" server images
    ;;
    client)
      compadd -Q "$@" "bulk delete" list create show delete edit reregister
    ;;
    configure)
      compadd "$@" client
    ;;
    cookbook)
      compadd -Q "$@" test list create download delete "metadata from" show "bulk delete" metadata upload
    ;;
45
46
47
  environment)
      compadd -Q "$@" list create delete edit show "from file"
      ;;
Frank Louwers's avatar
Frank Louwers committed
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
    node)
     compadd -Q "$@" "from file" create show edit delete list run_list "bulk delete"
    ;;
    recipe)
     compadd "$@" list
    ;;
    role)
      compadd -Q "$@" "bulk delete" create delete edit "from file" list show
    ;; 
    windows)
      compadd "$@" bootstrap
    ;;
    *)
    _arguments '2:Subsubcommands:($(_knife_options1))'
    esac
   ;;
   knifesubcmd2)
    case $words[3] in
     server)
      compadd "$@" list create delete
    ;;
     images)
      compadd "$@" list
    ;;
     site)
      compadd "$@" vendor show share search download list unshare
    ;;
     (show|delete|edit)
     _arguments '3:Subsubcommands:($(_chef_$words[2]s_remote))'
    ;;
    (upload|test)
     _arguments '3:Subsubcommands:($(_chef_$words[2]s_local) --all)'
    ;;
    list)
     compadd -a "$@" knife_general_flags
    ;;
    bag)
      compadd -Q "$@" show edit list "from file" create delete
    ;;
    *)
      _arguments '3:Subsubcommands:($(_knife_options2))'
    esac
   ;;
   knifesubcmd3)
     case $words[3] in
      show)
       case $words[2] in
       cookbook)
          versioncomp=1
          _arguments '4:Cookbookversions:($(_cookbook_versions) latest)'
       ;;
       (node|client|role)
         compadd "$@" --attribute
       esac
     esac
     case $words[4] in
     (show|edit)
     _arguments '4:Subsubsubcommands:($(_chef_$words[2]_$words[3]s_remote))'
    ;;
     file)
     _arguments '*:file or directory:_files -g "*.(rb|json)"'
    ;;
      list)
     compadd -a "$@" knife_general_flags
    ;;
        *)
       _arguments '*:Subsubcommands:($(_knife_options3))'
    esac
    ;;
    knifesubcmd4)
      if (( versioncomp > 0 )); then
        compadd "$@" attributes definitions files libraries providers recipes resources templates
      else
       _arguments '*:Subsubcommands:($(_knife_options2))'
      fi
    ;; 
    knifesubcmd5) 
      _arguments '*:Subsubcommands:($(_knife_options3))'
   esac
}

# Helper functions to provide the argument completion for several depths of commands
_knife_options1() {
 ( for line in $( knife $words[2] --help | grep -v "^knife" ); do echo $line | grep "\-\-"; done )
}

_knife_options2() {
 ( for line in $( knife $words[2] $words[3] --help | grep -v "^knife" ); do echo $line | grep "\-\-"; done )
}

_knife_options3() {
 ( for line in $( knife $words[2] $words[3] $words[4] --help | grep -v "^knife" ); do echo $line | grep "\-\-"; done )
}

# The chef_x_remote functions use knife to get a list of objects of type x on the server
_chef_roles_remote() {
144
 (knife role list --format json | grep \" | awk '{print $1}' | awk -F"," '{print $1}' | awk -F"\"" '{print $2}')
Frank Louwers's avatar
Frank Louwers committed
145
146
147
}

_chef_clients_remote() {
148
 (knife client list --format json | grep \" | awk '{print $1}' | awk -F"," '{print $1}' | awk -F"\"" '{print $2}')
Frank Louwers's avatar
Frank Louwers committed
149
150
151
}

_chef_nodes_remote() {
152
 (knife node list --format json | grep \" | awk '{print $1}' | awk -F"," '{print $1}' | awk -F"\"" '{print $2}')
Frank Louwers's avatar
Frank Louwers committed
153
154
155
}

_chef_cookbooks_remote() {
156
 (knife cookbook list --format json | grep \" | awk '{print $1}' | awk -F"," '{print $1}' | awk -F"\"" '{print $2}')
Frank Louwers's avatar
Frank Louwers committed
157
158
159
}

_chef_sitecookbooks_remote() {
160
 (knife cookbook site list --format json | grep \" | awk '{print $1}' | awk -F"," '{print $1}' | awk -F"\"" '{print $2}')
Frank Louwers's avatar
Frank Louwers committed
161
162
163
}

_chef_data_bags_remote() {
164
 (knife data bag list --format json | grep \" | awk '{print $1}' | awk -F"," '{print $1}' | awk -F"\"" '{print $2}')
Frank Louwers's avatar
Frank Louwers committed
165
166
}

167
168
169
170
_chef_environments_remote() {
  (knife environment list | awk '{print $1}')
}

Frank Louwers's avatar
Frank Louwers committed
171
172
# The chef_x_local functions use the knife config to find the paths of relevant objects x to be uploaded to the server
_chef_cookbooks_local() {
173
174
175
176
177
178
179
  
  local knife_rb=${KNIFE_CONF_PATH:-${HOME}/.chef/knife.rb}
  if [ -f ./.chef/knife.rb ]; then
    knife_rb="./.chef/knife.rb"
  fi
  local cookbook_path=${KNIFE_COOKBOOK_PATH:-$(grep cookbook_path $knife_rb | awk 'BEGIN {FS = "[" }; {print $2}' | sed 's/\,//g' | sed "s/'//g" | sed 's/\(.*\)]/\1/' )}
  (for i in $cookbook_path; do ls $i; done)
Frank Louwers's avatar
Frank Louwers committed
180
181
182
183
184
185
186
187
}

# This function extracts the available cookbook versions on the chef server
_cookbook_versions() {
  (knife cookbook show $words[4] | grep -v $words[4] | grep -v -E '\]|\[|\{|\}' | sed 's/ //g' | sed 's/"//g')
}

_knife "$@"