chef 0.8.10 → 0.8.14

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of chef might be problematic. Click here for more details.

Files changed (105) hide show
  1. data/bin/chef-client +2 -2
  2. data/bin/chef-solo +1 -2
  3. data/bin/knife +1 -2
  4. data/bin/shef +2 -5
  5. data/lib/chef.rb +11 -7
  6. data/lib/chef/application.rb +25 -20
  7. data/lib/chef/application/client.rb +12 -7
  8. data/lib/chef/application/knife.rb +7 -1
  9. data/lib/chef/application/solo.rb +1 -1
  10. data/lib/chef/applications.rb +4 -0
  11. data/lib/chef/cache/checksum.rb +7 -6
  12. data/lib/chef/certificate.rb +2 -2
  13. data/lib/chef/client.rb +28 -4
  14. data/lib/chef/config.rb +4 -3
  15. data/lib/chef/cookbook_loader.rb +6 -1
  16. data/lib/chef/daemon.rb +2 -0
  17. data/lib/chef/data_bag_item.rb +2 -1
  18. data/lib/chef/exceptions.rb +5 -0
  19. data/lib/chef/file_cache.rb +18 -18
  20. data/lib/chef/index_queue/indexable.rb +5 -3
  21. data/lib/chef/knife.rb +45 -13
  22. data/lib/chef/knife/client_list.rb +1 -1
  23. data/lib/chef/knife/client_show.rb +1 -1
  24. data/lib/chef/knife/configure.rb +47 -36
  25. data/lib/chef/knife/cookbook_list.rb +1 -1
  26. data/lib/chef/knife/cookbook_metadata.rb +22 -27
  27. data/lib/chef/knife/cookbook_metadata_from_file.rb +40 -0
  28. data/lib/chef/knife/cookbook_show.rb +2 -2
  29. data/lib/chef/knife/cookbook_site_download.rb +57 -0
  30. data/lib/chef/knife/cookbook_site_list.rb +55 -0
  31. data/lib/chef/knife/cookbook_site_search.rb +50 -0
  32. data/lib/chef/knife/cookbook_site_show.rb +56 -0
  33. data/lib/chef/knife/cookbook_site_vendor.rb +114 -0
  34. data/lib/chef/knife/cookbook_test.rb +103 -0
  35. data/lib/chef/knife/cookbook_upload.rb +29 -38
  36. data/lib/chef/knife/data_bag_edit.rb +1 -1
  37. data/lib/chef/knife/data_bag_list.rb +2 -2
  38. data/lib/chef/knife/data_bag_show.rb +1 -1
  39. data/lib/chef/knife/ec2_instance_data.rb +1 -1
  40. data/lib/chef/knife/index_rebuild.rb +2 -2
  41. data/lib/chef/knife/node_from_file.rb +1 -1
  42. data/lib/chef/knife/node_list.rb +2 -2
  43. data/lib/chef/knife/node_run_list_add.rb +1 -1
  44. data/lib/chef/knife/node_run_list_remove.rb +1 -1
  45. data/lib/chef/knife/node_show.rb +1 -1
  46. data/lib/chef/knife/rackspace_server_create.rb +156 -0
  47. data/lib/chef/knife/rackspace_server_delete.rb +57 -0
  48. data/lib/chef/knife/rackspace_server_list.rb +59 -0
  49. data/lib/chef/knife/role_from_file.rb +1 -1
  50. data/lib/chef/knife/role_list.rb +1 -1
  51. data/lib/chef/knife/role_show.rb +1 -1
  52. data/lib/chef/knife/search.rb +1 -1
  53. data/lib/chef/knife/ssh.rb +21 -4
  54. data/lib/chef/knife/terremark_server_create.rb +152 -0
  55. data/lib/chef/knife/terremark_server_delete.rb +87 -0
  56. data/lib/chef/knife/terremark_server_list.rb +77 -0
  57. data/lib/chef/mixin/command.rb +11 -9
  58. data/lib/chef/mixin/params_validate.rb +1 -1
  59. data/lib/chef/mixin/recipe_definition_dsl_core.rb +4 -1
  60. data/lib/chef/mixin/template.rb +6 -5
  61. data/lib/chef/mixin/xml_escape.rb +3 -3
  62. data/lib/chef/mixins.rb +16 -0
  63. data/lib/chef/node.rb +53 -52
  64. data/lib/chef/openid_registration.rb +0 -1
  65. data/lib/chef/platform.rb +171 -137
  66. data/lib/chef/provider.rb +2 -2
  67. data/lib/chef/provider/cron.rb +22 -22
  68. data/lib/chef/provider/deploy/revision.rb +5 -1
  69. data/lib/chef/provider/erl_call.rb +2 -2
  70. data/lib/chef/provider/file.rb +44 -23
  71. data/lib/chef/provider/group/dscl.rb +6 -4
  72. data/lib/chef/provider/mdadm.rb +0 -4
  73. data/lib/chef/provider/mount/mount.rb +20 -8
  74. data/lib/chef/provider/package.rb +1 -1
  75. data/lib/chef/provider/package/freebsd.rb +22 -18
  76. data/lib/chef/provider/package/rubygems.rb +7 -10
  77. data/lib/chef/provider/remote_directory.rb +15 -0
  78. data/lib/chef/provider/remote_file.rb +73 -50
  79. data/lib/chef/provider/script.rb +10 -8
  80. data/lib/chef/provider/service/windows.rb +129 -0
  81. data/lib/chef/provider/subversion.rb +1 -1
  82. data/lib/chef/provider/template.rb +51 -50
  83. data/lib/chef/providers.rb +80 -0
  84. data/lib/chef/recipe.rb +2 -4
  85. data/lib/chef/resource.rb +21 -7
  86. data/lib/chef/resource/cron.rb +14 -5
  87. data/lib/chef/resource/deploy.rb +52 -45
  88. data/lib/chef/resource/execute.rb +1 -1
  89. data/lib/chef/resource/file.rb +16 -8
  90. data/lib/chef/resource/mount.rb +1 -1
  91. data/lib/chef/resource/remote_directory.rb +19 -10
  92. data/lib/chef/resource/scm.rb +23 -16
  93. data/lib/chef/resource/service.rb +10 -1
  94. data/lib/chef/resources.rb +60 -0
  95. data/lib/chef/rest.rb +234 -189
  96. data/lib/chef/rest/auth_credentials.rb +78 -0
  97. data/lib/chef/{application/server.rb → rest/cookie_jar.rb} +18 -6
  98. data/lib/chef/rest/rest_request.rb +151 -0
  99. data/lib/chef/role.rb +38 -46
  100. data/lib/chef/streaming_cookbook_uploader.rb +8 -2
  101. data/lib/chef/tasks/chef_repo.rake +14 -4
  102. data/lib/chef/util/file_edit.rb +0 -1
  103. data/lib/chef/webui_user.rb +0 -1
  104. metadata +46 -9
  105. data/distro/suse/etc/init.d/chef-client +0 -121
@@ -44,10 +44,12 @@ class Chef
44
44
  self.class.index_object_type || Mixin::ConvertToClassName.snake_case_basename(self.class.name)
45
45
  end
46
46
 
47
- def with_indexer_metadata(with_metadata={})
47
+ def with_indexer_metadata(indexer_metadata={})
48
48
  # changing input param symbol keys to strings, as the keys in hash that goes to solr are expected to be strings [cb]
49
- with_metadata.each do |key,value|
50
- with_metadata[key.to_s] = with_metadata.delete(key)
49
+ # Ruby 1.9 hates you, cb [dan]
50
+ with_metadata = {}
51
+ indexer_metadata.each_key do |key|
52
+ with_metadata[key.to_s] = indexer_metadata[key]
51
53
  end
52
54
 
53
55
  with_metadata["type"] ||= self.index_object_type
@@ -20,6 +20,8 @@
20
20
  require 'mixlib/cli'
21
21
  require 'chef/mixin/convert_to_class_name'
22
22
 
23
+ require 'pp'
24
+
23
25
  class Chef
24
26
  class Knife
25
27
  include Mixlib::CLI
@@ -96,11 +98,17 @@ class Chef
96
98
  klass_instance
97
99
  end
98
100
 
99
- def ask_question(q)
100
- print q
101
- a = STDIN.readline
102
- a.chomp!
103
- a
101
+ def ask_question(question, opts={})
102
+ question = question + "[#{opts[:default]}] " if opts[:default]
103
+
104
+ stdout.print question
105
+ a = stdin.readline.strip
106
+
107
+ if opts[:default]
108
+ a.empty? ? opts[:default] : a
109
+ else
110
+ a
111
+ end
104
112
  end
105
113
 
106
114
  def configure_chef
@@ -126,8 +134,24 @@ class Chef
126
134
  puts data
127
135
  end
128
136
 
129
- def json_pretty_print(data)
130
- puts JSON.pretty_generate(data)
137
+ def output(data)
138
+ case config[:format]
139
+ when "json", nil
140
+ puts JSON.pretty_generate(data)
141
+ when "yaml"
142
+ require 'yaml'
143
+ puts YAML::dump(data)
144
+ when "text"
145
+ # If you were looking for some attribute and there is only one match
146
+ # just dump the attribute value
147
+ if data.length == 1 and config[:attribute]
148
+ puts data.values[0]
149
+ else
150
+ pp data
151
+ end
152
+ else
153
+ raise ArgumentError, "Unknown output format #{config[:format]}"
154
+ end
131
155
  end
132
156
 
133
157
  def format_list_for_display(list)
@@ -182,7 +206,7 @@ class Chef
182
206
  return true if config[:yes]
183
207
 
184
208
  print "#{question}? (Y/N) "
185
- answer = STDIN.readline
209
+ answer = stdin.readline
186
210
  answer.chomp!
187
211
  case answer
188
212
  when "Y", "y"
@@ -237,7 +261,7 @@ class Chef
237
261
 
238
262
  Chef::Log.info("Saved #{output}")
239
263
 
240
- json_pretty_print(format_for_display(object)) if config[:print_after]
264
+ output(format_for_display(object)) if config[:print_after]
241
265
  end
242
266
 
243
267
  def create_object(object, pretty_name=nil, &block)
@@ -253,7 +277,7 @@ class Chef
253
277
 
254
278
  Chef::Log.info("Created (or updated) #{pretty_name}")
255
279
 
256
- json_pretty_print(output) if config[:print_after]
280
+ output(output) if config[:print_after]
257
281
  end
258
282
 
259
283
  def delete_object(klass, name, delete_name=nil, &block)
@@ -266,7 +290,7 @@ class Chef
266
290
  object.destroy
267
291
  end
268
292
 
269
- json_pretty_print(format_for_display(object)) if config[:print_after]
293
+ output(format_for_display(object)) if config[:print_after]
270
294
 
271
295
  obj_name = delete_name ? "#{delete_name}[#{name}]" : object
272
296
  Chef::Log.warn("Deleted #{obj_name}!")
@@ -285,7 +309,7 @@ class Chef
285
309
  to_delete = object_list
286
310
  end
287
311
 
288
- json_pretty_print(format_list_for_display(to_delete))
312
+ output(format_list_for_display(to_delete))
289
313
 
290
314
  confirm("Do you really want to delete the above items")
291
315
 
@@ -295,10 +319,18 @@ class Chef
295
319
  else
296
320
  object.destroy
297
321
  end
298
- json_pretty_print(format_for_display(object)) if config[:print_after]
322
+ output(format_for_display(object)) if config[:print_after]
299
323
  Chef::Log.warn("Deleted #{fancy_name} #{name}")
300
324
  end
301
325
  end
326
+
327
+ def stdout
328
+ STDOUT
329
+ end
330
+
331
+ def stdin
332
+ STDIN
333
+ end
302
334
 
303
335
  def rest
304
336
  @rest ||= Chef::REST.new(Chef::Config[:chef_server_url])
@@ -32,7 +32,7 @@ class Chef
32
32
  :description => "Show corresponding URIs"
33
33
 
34
34
  def run
35
- json_pretty_print(format_list_for_display(Chef::ApiClient.list))
35
+ output(format_list_for_display(Chef::ApiClient.list))
36
36
  end
37
37
  end
38
38
  end
@@ -33,7 +33,7 @@ class Chef
33
33
 
34
34
  def run
35
35
  client = Chef::ApiClient.load(@name_args[0])
36
- json_pretty_print(format_for_display(client))
36
+ output(format_for_display(client))
37
37
  end
38
38
 
39
39
  end
@@ -6,9 +6,9 @@
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
8
8
  # You may obtain a copy of the License at
9
- #
9
+ #
10
10
  # http://www.apache.org/licenses/LICENSE-2.0
11
- #
11
+ #
12
12
  # Unless required by applicable law or agreed to in writing, software
13
13
  # distributed under the License is distributed on an "AS IS" BASIS,
14
14
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -21,6 +21,8 @@ require 'chef/knife'
21
21
  class Chef
22
22
  class Knife
23
23
  class Configure < Knife
24
+ attr_reader :chef_server, :new_client_name, :admin_client_name, :admin_client_key
25
+ attr_reader :chef_repo, :new_client_key, :validation_client_name, :validation_key
24
26
 
25
27
  banner "Sub-Command: configure (options)"
26
28
 
@@ -37,58 +39,48 @@ class Chef
37
39
 
38
40
  def configure_chef
39
41
  # We are just faking out the system so that you can do this without a key specified
40
- Chef::Config[:node_name] = 'woot'
42
+ Chef::Config[:node_name] = 'woot'
41
43
  super
42
44
  Chef::Config[:node_name] = nil
43
45
  end
44
46
 
45
- def run
46
- config[:config_file] ||= ask_question("Where should I put the config file? ")
47
- if File.exists?(config[:config_file])
48
- confirm("Overwrite #{config[:config_file]}")
49
- end
47
+ def run
48
+ ask_user_for_config_path
50
49
 
51
50
  Mixlib::Log::Formatter.show_time = false
52
51
  Chef::Log.init(STDOUT)
53
52
  Chef::Log.level(:info)
54
53
 
55
- chef_config_path = File.dirname(config[:config_file])
56
- FileUtils.mkdir_p(File.dirname(config[:config_file]))
54
+ FileUtils.mkdir_p(chef_config_path)
57
55
 
58
- chef_server = config[:chef_server_url] || ask_question("Your chef server URL? ")
59
- opscode_user = config[:node_name] || ask_question("Your client user name? ")
60
- opscode_key = config[:client_key] || File.join(chef_config_path, "#{opscode_user}.pem")
61
- validation_user = config[:validation_client_name] || ask_question("Your validation client user name? ")
62
- validation_key = config[:validation_key] || File.join(chef_config_path, "#{validation_user}.pem")
63
- chef_repo = config[:repository] || ask_question("Path to a chef repository (or leave blank)? ")
64
-
56
+ ask_user_for_config
65
57
 
66
- File.open(config[:config_file], "w") do |f|
67
- f.puts <<EOH
58
+ ::File.open(config[:config_file], "w") do |f|
59
+ f.puts <<-EOH
68
60
  log_level :info
69
61
  log_location STDOUT
70
- node_name '#{opscode_user}'
71
- client_key '#{opscode_key}'
72
- validation_client_name '#{validation_user}'
62
+ node_name '#{new_client_name}'
63
+ client_key '#{new_client_key}'
64
+ validation_client_name '#{validation_client_name}'
73
65
  validation_key '#{validation_key}'
74
- chef_server_url '#{chef_server}'
66
+ chef_server_url '#{chef_server}'
75
67
  cache_type 'BasicFile'
76
68
  cache_options( :path => '#{File.join(chef_config_path, "checksums")}' )
77
69
  EOH
78
- unless chef_repo == ""
70
+ unless chef_repo.empty?
79
71
  f.puts "cookbook_path [ '#{chef_repo}/cookbooks', '#{chef_repo}/site-cookbooks' ]"
80
- end
72
+ end
81
73
  end
82
74
 
83
75
  if config[:initial]
84
76
  Chef::Log.warn("Creating initial API user...")
85
77
  Chef::Config[:chef_server_url] = chef_server
86
- Chef::Config[:node_name] = 'chef-webui'
87
- Chef::Config[:client_key] = '/etc/chef/webui.pem'
78
+ Chef::Config[:node_name] = admin_client_name
79
+ Chef::Config[:client_key] = admin_client_key
88
80
  client_create = Chef::Knife::ClientCreate.new
89
- client_create.name_args = [ opscode_user ]
81
+ client_create.name_args = [ new_client_name ]
90
82
  client_create.config[:admin] = true
91
- client_create.config[:file] = opscode_key
83
+ client_create.config[:file] = new_client_key
92
84
  client_create.config[:yes] = true
93
85
  client_create.config[:no_editor] = true
94
86
  client_create.run
@@ -96,7 +88,7 @@ EOH
96
88
  Chef::Log.warn("*****")
97
89
  Chef::Log.warn("")
98
90
  Chef::Log.warn("You must place your client key in:")
99
- Chef::Log.warn(" #{opscode_key}")
91
+ Chef::Log.warn(" #{new_client_key}")
100
92
  Chef::Log.warn("Before running commands with Knife!")
101
93
  Chef::Log.warn("")
102
94
  Chef::Log.warn("*****")
@@ -111,13 +103,32 @@ EOH
111
103
  Chef::Log.warn("Configuration file written to #{config[:config_file]}")
112
104
  end
113
105
 
114
- end
115
- end
116
- end
117
-
118
-
119
-
106
+ def ask_user_for_config_path
107
+ config[:config_file] ||= ask_question("Where should I put the config file? ")
108
+ if File.exists?(config[:config_file])
109
+ confirm("Overwrite #{config[:config_file]}")
110
+ end
111
+ end
120
112
 
113
+ def ask_user_for_config
114
+ @chef_server = config[:chef_server_url] || ask_question("Your chef server URL? ", :default => 'http://localhost:4000')
115
+ @new_client_name = config[:node_name] || ask_question("Select a user name for your new client: ", :default => Etc.getlogin)
116
+ @admin_client_name = config[:admin_client_name] || ask_question("Your existing admin client user name? ", :default => 'chef-webui')
117
+ @admin_client_key = config[:admin_client_key] || ask_question("The location of your existing admin key? ", :default => '/etc/chef/webui.pem')
118
+ @validation_client_name = config[:validation_client_name] || ask_question("Your validation client user name? ", :default => 'chef-validator')
119
+ @validation_key = config[:validation_key] || ask_question("The location of your validation key? ", :default => '/etc/chef/validation.pem')
120
+ @chef_repo = config[:repository] || ask_question("Path to a chef repository (or leave blank)? ")
121
121
 
122
+ @new_client_key = config[:client_key] || File.join(chef_config_path, "#{@new_client_name}.pem")
123
+ end
122
124
 
125
+ def config_file
126
+ config[:config_file]
127
+ end
123
128
 
129
+ def chef_config_path
130
+ File.dirname(config_file)
131
+ end
132
+ end
133
+ end
134
+ end
@@ -31,7 +31,7 @@ class Chef
31
31
  :description => "Show corresponding URIs"
32
32
 
33
33
  def run
34
- json_pretty_print(format_list_for_display(rest.get_rest('cookbooks')))
34
+ output(format_list_for_display(rest.get_rest('cookbooks')))
35
35
  end
36
36
  end
37
37
  end
@@ -7,9 +7,9 @@
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
9
9
  # You may obtain a copy of the License at
10
- #
10
+ #
11
11
  # http://www.apache.org/licenses/LICENSE-2.0
12
- #
12
+ #
13
13
  # Unless required by applicable law or agreed to in writing, software
14
14
  # distributed under the License is distributed on an "AS IS" BASIS,
15
15
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -36,20 +36,20 @@ class Chef
36
36
  :long => "--all",
37
37
  :description => "Generate metadata for all cookbooks, rather than just a single cookbook"
38
38
 
39
- def run
39
+ def run
40
40
  if config[:cookbook_path]
41
41
  Chef::Config[:cookbook_path] = config[:cookbook_path]
42
42
  else
43
43
  config[:cookbook_path] = Chef::Config[:cookbook_path]
44
44
  end
45
45
 
46
- if config[:all]
46
+ if config[:all]
47
47
  cl = Chef::CookbookLoader.new
48
48
  cl.each do |cookbook|
49
49
  generate_metadata(cookbook.name.to_s)
50
50
  end
51
51
  else
52
- generate_metadata(@name_args[0])
52
+ generate_metadata(@name_args[0])
53
53
  end
54
54
  end
55
55
 
@@ -57,31 +57,26 @@ class Chef
57
57
  Chef::Log.info("Generating metadata for #{cookbook}")
58
58
  config[:cookbook_path].reverse.each do |path|
59
59
  file = File.expand_path(File.join(path, cookbook, 'metadata.rb'))
60
- if File.exists?(file)
61
- Chef::Log.info("Generating from #{file}")
62
- md = Chef::Cookbook::Metadata.new
63
- md.name(cookbook)
64
- md.from_file(file)
65
- json_file = File.join(File.dirname(file), 'metadata.json')
66
- File.open(json_file, "w") do |f|
67
- f.write(JSON.pretty_generate(md))
68
- end
69
- generated = true
70
- Chef::Log.info("Generated #{json_file}")
71
- else
72
- Chef::Log.debug("No #{file} found; skipping!")
73
- end
60
+ generate_metadata_from_file(cookbook, file)
74
61
  end
75
62
  end
76
63
 
64
+ def generate_metadata_from_file(cookbook, file)
65
+ if File.exists?(file)
66
+ Chef::Log.info("Generating from #{file}")
67
+ md = Chef::Cookbook::Metadata.new
68
+ md.name(cookbook)
69
+ md.from_file(file)
70
+ json_file = File.join(File.dirname(file), 'metadata.json')
71
+ File.open(json_file, "w") do |f|
72
+ f.write(JSON.pretty_generate(md))
73
+ end
74
+ generated = true
75
+ Chef::Log.info("Generated #{json_file}")
76
+ else
77
+ Chef::Log.debug("No #{file} found; skipping!")
78
+ end
79
+ end
77
80
  end
78
81
  end
79
82
  end
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
@@ -0,0 +1,40 @@
1
+ #
2
+ #
3
+ # Author:: Adam Jacob (<adam@opscode.com>)
4
+ # Author:: Matthew Kent (<mkent@magoazul.com>)
5
+ # Copyright:: Copyright (c) 2009 Opscode, Inc.
6
+ # Copyright:: Copyright (c) 2010 Matthew Kent
7
+ # License:: Apache License, Version 2.0
8
+ #
9
+ # Licensed under the Apache License, Version 2.0 (the "License");
10
+ # you may not use this file except in compliance with the License.
11
+ # You may obtain a copy of the License at
12
+ #
13
+ # http://www.apache.org/licenses/LICENSE-2.0
14
+ #
15
+ # Unless required by applicable law or agreed to in writing, software
16
+ # distributed under the License is distributed on an "AS IS" BASIS,
17
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ # See the License for the specific language governing permissions and
19
+ # limitations under the License.
20
+ #
21
+
22
+ require 'chef/knife'
23
+
24
+ class Chef
25
+ class Knife
26
+ class CookbookMetadataFromFile < Knife
27
+
28
+ banner "Sub-Command: cookbook metadata from FILE (options)"
29
+
30
+ def run
31
+ file = @name_args[0]
32
+ cookbook = File.basename(File.dirname(file))
33
+
34
+ @metadata = Chef::Knife::CookbookMetadata.new
35
+ @metadata.generate_metadata_from_file(cookbook, file)
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -52,9 +52,9 @@ class Chef
52
52
  pretty_print(result)
53
53
  when 2 # We are showing a specific part of the cookbook
54
54
  result = rest.get_rest("cookbooks/#{@name_args[0]}")
55
- json_pretty_print(result[@name_args[1]])
55
+ output(result[@name_args[1]])
56
56
  when 1 # We are showing the whole cookbook data
57
- json_pretty_print(rest.get_rest("cookbooks/#{@name_args[0]}"))
57
+ output(rest.get_rest("cookbooks/#{@name_args[0]}"))
58
58
  end
59
59
  end
60
60
 
@@ -0,0 +1,57 @@
1
+ # Author:: Adam Jacob (<adam@opscode.com>)
2
+ # Copyright:: Copyright (c) 2009 Opscode, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'chef/knife'
19
+
20
+ class Chef
21
+ class Knife
22
+ class CookbookSiteDownload < Knife
23
+
24
+ attr_reader :version
25
+
26
+ banner "Sub-Command: cookbook site download COOKBOOK [VERSION] (options)"
27
+
28
+ option :file,
29
+ :short => "-f FILE",
30
+ :long => "--file FILE",
31
+ :description => "The filename to write to"
32
+
33
+ def run
34
+ if @name_args.length == 1
35
+ current = rest.get_rest("http://cookbooks.opscode.com/api/v1/cookbooks/#{name_args[0]}")
36
+ cookbook_data = rest.get_rest(current["latest_version"])
37
+ else
38
+ cookbook_data = rest.get_rest("http://cookbooks.opscode.com/api/v1/cookbooks/#{name_args[0]}/versions/#{name_args[1].gsub('.', '_')}")
39
+ end
40
+
41
+ @version = cookbook_data['version']
42
+
43
+ Chef::Log.info("Downloading #{@name_args[0]} from the cookbooks site at version #{cookbook_data['version']}")
44
+ rest.sign_on_redirect = false
45
+ tf = rest.get_rest(cookbook_data["file"], true)
46
+ unless config[:file]
47
+ config[:file] = File.join(Dir.pwd, "#{@name_args[0]}-#{cookbook_data['version']}.tar.gz")
48
+ end
49
+ FileUtils.cp(tf.path, config[:file])
50
+ Chef::Log.info("Cookbook saved: #{config[:file]}")
51
+ end
52
+
53
+ end
54
+ end
55
+ end
56
+
57
+