_knife 6.09 KB
Newer Older
Frank Louwers's avatar
Frank Louwers committed
1
2
#compdef knife

3
4
5
6
7
# You can override the path to knife.rb and your cookbooks by setting
# KNIFE_CONF_PATH=/path/to/my/.chef/knife.rb
# KNIFE_COOKBOOK_PATH=/path/to/my/chef/cookbooks
# Read around where these are used for more detail.

Frank Louwers's avatar
Frank Louwers committed
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 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)
34
    compadd -Q "$@" bootstrap client configure cookbook "cookbook site" "data bag" diff exec environment index node recipe role search ssh status upload windows $cloudproviders
Frank Louwers's avatar
Frank Louwers committed
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
  ;;
  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
    ;;
50
51
52
53
    diff)
      _arguments '*:file or directory:_files -g "*"'
    ;;
    environment)
54
      compadd -Q "$@" list create delete edit show "from file"
55
    ;;
Frank Louwers's avatar
Frank Louwers committed
56
57
58
59
60
61
62
63
64
    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
    ;; 
65
66
67
    upload)
     _arguments '*:file or directory:_files -g "*"'
    ;;
Frank Louwers's avatar
Frank Louwers committed
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
144
145
146
147
148
149
150
151
152
153
154
    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() {
155
 (knife role list --format json | grep \" | awk '{print $1}' | awk -F"," '{print $1}' | awk -F"\"" '{print $2}')
Frank Louwers's avatar
Frank Louwers committed
156
157
158
}

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

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

_chef_cookbooks_remote() {
167
 (knife cookbook list --format json | grep \" | awk '{print $1}' | awk -F"," '{print $1}' | awk -F"\"" '{print $2}')
Frank Louwers's avatar
Frank Louwers committed
168
169
170
}

_chef_sitecookbooks_remote() {
171
 (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
172
173
174
}

_chef_data_bags_remote() {
175
 (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
176
177
}

178
179
180
181
_chef_environments_remote() {
  (knife environment list | awk '{print $1}')
}

Frank Louwers's avatar
Frank Louwers committed
182
183
# 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() {
184
185
186
187
188
189
190
  
  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
191
192
193
194
195
196
197
198
}

# 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 "$@"