knife-essentials 1.5.3 → 1.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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