knife-essentials 1.5.3 → 1.5.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -48,7 +48,13 @@ class Chef
48
48
  end
49
49
  chef_rest = Chef::REST.new(Chef::Config[:chef_server_url])
50
50
  begin
51
- output ::ChefFS::RawRequest.api_request(chef_rest, config[:method].to_sym, chef_rest.create_url(name_args[0]), {}, data)
51
+ method = config[:method].to_sym
52
+ url = chef_rest.create_url(name_args[0])
53
+ result = ::ChefFS::RawRequest.api_request(chef_rest, method, url, {}, data, :parse_json => config[:pretty])
54
+ if result.is_a?(Hash) || result.is_a?(Array)
55
+ result = Chef::JSONCompat.to_json_pretty(result)
56
+ end
57
+ output result
52
58
  rescue Timeout::Error => e
53
59
  ui.error "Server timeout"
54
60
  exit 1
@@ -288,7 +288,7 @@ module ChefFS
288
288
  ui.output "Deleted extra entry #{dest_path} (purge is on)" if ui
289
289
  end
290
290
  else
291
- Chef::Log.info("Not deleting extra entry #{dest_path} (purge is off)") if ui
291
+ ui.output ("Not deleting extra entry #{dest_path} (purge is off)") if ui
292
292
  end
293
293
  end
294
294
 
@@ -406,7 +406,7 @@ module ChefFS
406
406
  parent = entry.parent
407
407
  if parent && !parent.exists?
408
408
  parent_path = format_path.call(parent) if ui
409
- parent_parent = get_or_create_parent(entry.parent, options, ui, format_path)
409
+ parent_parent = get_or_create_parent(parent, options, ui, format_path)
410
410
  if options[:dry_run]
411
411
  ui.output "Would create #{parent_path}" if ui
412
412
  else
@@ -53,7 +53,7 @@ module ChefFS
53
53
  Dir.mkdir(path)
54
54
  end
55
55
  child = make_child_entry(name)
56
- @children << child
56
+ @children = nil
57
57
  child
58
58
  end
59
59
 
@@ -62,6 +62,7 @@ module ChefFS
62
62
  end
63
63
 
64
64
  def create_child_from(other, options = {})
65
+ @children = nil
65
66
  upload_cookbook_from(other, options)
66
67
  end
67
68
 
@@ -63,6 +63,7 @@ module ChefFS
63
63
  raise ChefFS::FileSystem::OperationFailedError.new(:create_child, self, e), "HTTP error creating child '#{name}': #{e}"
64
64
  end
65
65
  end
66
+ @children = nil
66
67
  DataBagDir.new(name, self, true)
67
68
  end
68
69
  end
@@ -46,13 +46,14 @@ module ChefFS
46
46
  end
47
47
 
48
48
  def create_child(child_name, file_contents=nil)
49
- result = FileSystemEntry.new(child_name, self)
49
+ child = FileSystemEntry.new(child_name, self)
50
50
  if file_contents
51
- result.write(file_contents)
51
+ child.write(file_contents)
52
52
  else
53
- Dir.mkdir(result.file_path)
53
+ Dir.mkdir(child.file_path)
54
54
  end
55
- result
55
+ @children = nil
56
+ child
56
57
  end
57
58
 
58
59
  def dir?
@@ -39,6 +39,7 @@ module ChefFS
39
39
  end
40
40
 
41
41
  def create_child(name, file_contents = nil)
42
+ @children = nil
42
43
  write_dir.create_child(name, file_contents)
43
44
  end
44
45
  end
@@ -26,6 +26,14 @@ module ChefFS
26
26
  @operation = operation
27
27
  end
28
28
 
29
+ def message
30
+ if cause && cause.is_a?(Net::HTTPExceptions) && cause.response.code == "400"
31
+ "#{super} cause: #{cause.response.body}"
32
+ else
33
+ super
34
+ end
35
+ end
36
+
29
37
  attr_reader :operation
30
38
  end
31
39
  end
@@ -88,6 +88,8 @@ module ChefFS
88
88
  end
89
89
  end
90
90
 
91
+ @children = nil
92
+
91
93
  result
92
94
  end
93
95
 
@@ -1,15 +1,15 @@
1
1
  module ChefFS
2
2
  module RawRequest
3
3
  def self.raw_json(chef_rest, api_path)
4
- JSON.parse(raw_request(chef_rest, api_path), :create_additions => false)
4
+ api_request(chef_rest, :GET, chef_rest.create_url(api_path), {}, nil, :parse_json => true)
5
5
  end
6
6
 
7
7
  def self.raw_request(chef_rest, api_path)
8
- api_request(chef_rest, :GET, chef_rest.create_url(api_path), {}, false)
8
+ api_request(chef_rest, :GET, chef_rest.create_url(api_path))
9
9
  end
10
10
 
11
- def self.api_request(chef_rest, method, url, headers={}, data=false)
12
- json_body = data
11
+ def self.api_request(chef_rest, method, url, headers={}, data=nil, options = {})
12
+ json_body = data || nil
13
13
  # json_body = data ? Chef::JSONCompat.to_json(data) : nil
14
14
  # Force encoding to binary to fix SSL related EOFErrors
15
15
  # cf. http://tickets.opscode.com/browse/CHEF-2363
@@ -23,11 +23,15 @@ module ChefFS
23
23
  response_body = chef_rest.decompress_body(response)
24
24
 
25
25
  if response.kind_of?(Net::HTTPSuccess)
26
- response_body
26
+ if options[:parse_json] && response['content-type'] =~ /json/
27
+ JSON.parse(response_body, :create_additions => false)
28
+ else
29
+ response_body
30
+ end
27
31
  elsif redirect_location = redirected_to(response)
28
32
  if [:GET, :HEAD].include?(method)
29
33
  chef_rest.follow_redirect do
30
- api_request(chef_rest, method, chef_rest.create_url(redirect_location))
34
+ api_request(chef_rest, method, chef_rest.create_url(redirect_location), headers, nil, options)
31
35
  end
32
36
  else
33
37
  raise Exceptions::InvalidRedirect, "#{method} request was redirected from #{url} to #{redirect_location}. Only GET and HEAD support redirects."
@@ -62,11 +66,11 @@ module ChefFS
62
66
  response['location']
63
67
  end
64
68
 
65
- def self.build_headers(chef_rest, method, url, headers={}, json_body=false, raw=false)
69
+ def self.build_headers(chef_rest, method, url, headers={}, json_body=nil, raw=nil)
66
70
  # headers = @default_headers.merge(headers)
67
71
  #headers['Accept'] = "application/json" unless raw
68
72
  headers['Accept'] = "application/json" unless raw
69
- headers["Content-Type"] = 'application/json' if json_body
73
+ headers['Content-Type'] = 'application/json' if json_body
70
74
  headers['Content-Length'] = json_body.bytesize.to_s if json_body
71
75
  headers[Chef::REST::RESTRequest::ACCEPT_ENCODING] = Chef::REST::RESTRequest::ENCODING_GZIP_DEFLATE
72
76
  headers.merge!(chef_rest.authentication_headers(method, url, json_body)) if chef_rest.sign_requests?
@@ -1,3 +1,3 @@
1
1
  module ChefFS
2
- VERSION = "1.5.3"
2
+ VERSION = "1.5.4"
3
3
  end
@@ -0,0 +1,47 @@
1
+ #
2
+ # Author:: John Keiser (<jkeiser@opscode.com>)
3
+ # Copyright:: Copyright (c) 2012 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'support/spec_helper'
20
+ require 'chef_fs/file_system/operation_failed_error'
21
+
22
+ describe ChefFS::FileSystem::OperationFailedError do
23
+ context 'message' do
24
+ let(:error_message) { 'HTTP error writing: 400 "Bad Request"' }
25
+
26
+ context 'has a cause attribute and HTTP result code is 400' do
27
+ it 'include error cause' do
28
+ allow_message_expectations_on_nil
29
+ response_body = '{"error":["Invalid key test in request body"]}'
30
+ @response.stub(:code).and_return("400")
31
+ @response.stub(:body).and_return(response_body)
32
+ exception = Net::HTTPServerException.new("(exception) unauthorized", @response)
33
+ proc {
34
+ raise ChefFS::FileSystem::OperationFailedError.new(:write, self, exception), error_message
35
+ }.should raise_error(ChefFS::FileSystem::OperationFailedError, "#{error_message} cause: #{response_body}")
36
+ end
37
+ end
38
+
39
+ context 'does not have a cause attribute' do
40
+ it 'does not include error cause' do
41
+ proc {
42
+ raise ChefFS::FileSystem::OperationFailedError.new(:write, self), error_message
43
+ }.should raise_error(ChefFS::FileSystem::OperationFailedError, error_message)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -239,6 +239,15 @@ Created /data_bags/x/y.json
239
239
  EOM
240
240
  knife('diff --name-status /data_bags').should_succeed <<EOM
241
241
  D\t/data_bags/x/z.json
242
+ EOM
243
+ end
244
+
245
+ it 'knife download /data_bags/x /data_bags/x/y.json downloads x once' do
246
+ knife('download /data_bags/x /data_bags/x/y.json').should_succeed <<EOM
247
+ Created /data_bags
248
+ Created /data_bags/x
249
+ Created /data_bags/x/y.json
250
+ Created /data_bags/x/z.json
242
251
  EOM
243
252
  end
244
253
  end
@@ -142,6 +142,69 @@ EOM
142
142
  "name": "y",
143
143
  "description": "eek"
144
144
  }
145
+ EOM
146
+ end
147
+ end
148
+
149
+ context 'When a server returns raw json' do
150
+ before :each do
151
+ @real_chef_server_url = Chef::Config.chef_server_url
152
+ Chef::Config.chef_server_url = "http://127.0.0.1:9018"
153
+ app = lambda do |env|
154
+ [200, {'Content-Type' => 'application/json' }, ['{ "x": "y", "a": "b" }'] ]
155
+ end
156
+ @raw_server = Puma::Server.new(app, Puma::Events.new(STDERR, STDOUT))
157
+ @raw_server.add_tcp_listener("127.0.0.1", 9018)
158
+ @raw_server.run
159
+ end
160
+
161
+ after :each do
162
+ Chef::Config.chef_server_url = @real_chef_server_url
163
+ @raw_server.stop(true)
164
+ end
165
+
166
+ it 'knife raw /blah returns the prettified json', :pending => (RUBY_VERSION < "1.9") do
167
+ knife('raw /blah').should_succeed <<EOM
168
+ {
169
+ "x": "y",
170
+ "a": "b"
171
+ }
172
+ EOM
173
+ end
174
+
175
+ it 'knife raw --no-pretty /blah returns the raw json' do
176
+ knife('raw --no-pretty /blah').should_succeed <<EOM
177
+ { "x": "y", "a": "b" }
178
+ EOM
179
+ end
180
+ end
181
+
182
+ context 'When a server returns text' do
183
+ before :each do
184
+ @real_chef_server_url = Chef::Config.chef_server_url
185
+ Chef::Config.chef_server_url = "http://127.0.0.1:9018"
186
+ app = lambda do |env|
187
+ [200, {'Content-Type' => 'text' }, ['{ "x": "y", "a": "b" }'] ]
188
+ end
189
+ @raw_server = Puma::Server.new(app, Puma::Events.new(STDERR, STDOUT))
190
+ @raw_server.add_tcp_listener("127.0.0.1", 9018)
191
+ @raw_server.run
192
+ end
193
+
194
+ after :each do
195
+ Chef::Config.chef_server_url = @real_chef_server_url
196
+ @raw_server.stop(true)
197
+ end
198
+
199
+ it 'knife raw /blah returns the raw text' do
200
+ knife('raw /blah').should_succeed <<EOM
201
+ { "x": "y", "a": "b" }
202
+ EOM
203
+ end
204
+
205
+ it 'knife raw --no-pretty /blah returns the raw text' do
206
+ knife('raw --no-pretty /blah').should_succeed <<EOM
207
+ { "x": "y", "a": "b" }
145
208
  EOM
146
209
  end
147
210
  end
@@ -41,10 +41,10 @@ D\t/roles/x.json
41
41
  D\t/users/admin.json
42
42
  D\t/users/x.json
43
43
  EOM
44
- end
44
+ end
45
45
 
46
- it 'knife upload --purge deletes everything' do
47
- knife('upload --purge /').should_succeed(<<EOM, :stderr => "WARNING: /environments/_default.json cannot be deleted (default environment cannot be modified).\n")
46
+ it 'knife upload --purge deletes everything' do
47
+ knife('upload --purge /').should_succeed(<<EOM, :stderr => "WARNING: /environments/_default.json cannot be deleted (default environment cannot be modified).\n")
48
48
  Deleted extra entry /clients/chef-validator.json (purge is on)
49
49
  Deleted extra entry /clients/chef-webui.json (purge is on)
50
50
  Deleted extra entry /clients/x.json (purge is on)
@@ -59,7 +59,7 @@ EOM
59
59
  knife('diff --name-status /').should_succeed <<EOM
60
60
  D\t/environments/_default.json
61
61
  EOM
62
- end
62
+ end
63
63
  end
64
64
 
65
65
  when_the_repository 'has an identical copy of each thing' do
@@ -222,6 +222,13 @@ EOM
222
222
  EOM
223
223
  JSON.parse(knife('raw /data/x/y').stdout, :create_additions => false).keys.sort.should == [ 'foo', 'id' ]
224
224
  end
225
+
226
+ it 'knife upload /data_bags/x /data_bags/x/y.json uploads x once' do
227
+ knife('upload /data_bags/x /data_bags/x/y.json').should_succeed <<EOM
228
+ Created /data_bags/x
229
+ Created /data_bags/x/y.json
230
+ EOM
231
+ end
225
232
  end
226
233
 
227
234
  when_the_repository 'has a data bag item with keys chef_type and data_bag' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knife-essentials
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.3
4
+ version: 1.5.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-19 00:00:00.000000000 Z
12
+ date: 2013-09-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: chef
@@ -192,12 +192,12 @@ files:
192
192
  - lib/chef_fs.rb
193
193
  - spec/chef_fs/diff_spec.rb
194
194
  - spec/chef_fs/file_pattern_spec.rb
195
+ - spec/chef_fs/file_system/operation_failed_error_spec.rb
195
196
  - spec/chef_fs/file_system_spec.rb
196
197
  - spec/data/null_config.rb
197
198
  - spec/integration/chef_repo_path_spec.rb
198
199
  - spec/integration/chef_repository_file_system_spec.rb
199
200
  - spec/integration/chefignore_spec.rb
200
- - spec/integration/converge_spec.rb
201
201
  - spec/integration/delete_spec.rb
202
202
  - spec/integration/deps_spec.rb
203
203
  - spec/integration/diff_spec.rb
@@ -1,75 +0,0 @@
1
- require 'support/integration_helper'
2
- require 'chef/knife/converge_essentials'
3
-
4
- describe 'knife converge' do
5
- let(:sample_cookbook) do
6
- return
7
- end
8
-
9
- when_the_repository 'has a cookbook' do
10
- file 'cookbooks/x/recipes/default.rb', <<EOM
11
- file #{path_to('x.txt')} do
12
- content 'x::default'
13
- end
14
- EOM
15
- file 'cookbooks/x/recipes/y.rb', <<EOM
16
- file #{path_to('x.txt')} do
17
- content 'x::y'
18
- end
19
- EOM
20
- file 'cookbooks/x/recipes/fromrole.rb', <<EOM
21
- file #{path_to('x.txt')} do
22
- content 'x::fromrole'
23
- end
24
- EOM
25
- file 'roles/r.json', { 'run_list' => [ 'recipe[x::r]' ] }
26
-
27
- context 'and current directory is at the top of the repository' do
28
- cwd '.'
29
- it 'knife converge creates .chef/knife.rb' do
30
- end
31
- end
32
-
33
- it 'knife converge /cookbooks/x converges x::default' do
34
- end
35
-
36
- it 'knife converge recipe[x] converges x::default' do
37
- end
38
-
39
- it 'knife converge /cookbooks/x/recipes/y.rb converges x::y' do
40
- end
41
-
42
- it 'knife converge recipe[x::y] converges x::y' do
43
- end
44
-
45
- it 'knife converge /roles/ converges x::fromrole' do
46
- end
47
-
48
- it 'knife converge role[r] converges x::fromrole' do
49
- end
50
-
51
- context 'and current directory is cookbooks/x/default' do
52
- cwd 'cookbooks/x/default'
53
-
54
- it 'knife converge creates .chef/knife.rb' do
55
- end
56
- it 'knife converge y.rb converges x::y' do
57
- end
58
- end
59
-
60
- context 'and a .chef/knife.rb' do
61
- it 'knife converge converges' do
62
- end
63
- end
64
- end
65
-
66
- when_the_repository 'has a cookbook' do
67
- it 'knife converge with no arguments runs the node\'s run list' do
68
- end
69
- end
70
-
71
- when_the_chef_server 'has cookbooks' do
72
- it 'knife converge converges them' do
73
- end
74
- end
75
- end