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.
- data/lib/chef/knife/raw_essentials.rb +7 -1
- data/lib/chef_fs/file_system.rb +2 -2
- data/lib/chef_fs/file_system/chef_repository_file_system_root_dir.rb +1 -1
- data/lib/chef_fs/file_system/cookbooks_dir.rb +1 -0
- data/lib/chef_fs/file_system/data_bags_dir.rb +1 -0
- data/lib/chef_fs/file_system/file_system_entry.rb +5 -4
- data/lib/chef_fs/file_system/multiplexed_dir.rb +1 -0
- data/lib/chef_fs/file_system/operation_failed_error.rb +8 -0
- data/lib/chef_fs/file_system/rest_list_dir.rb +2 -0
- data/lib/chef_fs/raw_request.rb +12 -8
- data/lib/chef_fs/version.rb +1 -1
- data/spec/chef_fs/file_system/operation_failed_error_spec.rb +47 -0
- data/spec/integration/download_spec.rb +9 -0
- data/spec/integration/raw_spec.rb +63 -0
- data/spec/integration/upload_spec.rb +11 -4
- metadata +3 -3
- data/spec/integration/converge_spec.rb +0 -75
@@ -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
|
-
|
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
|
data/lib/chef_fs/file_system.rb
CHANGED
@@ -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
|
-
|
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(
|
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
|
@@ -46,13 +46,14 @@ module ChefFS
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def create_child(child_name, file_contents=nil)
|
49
|
-
|
49
|
+
child = FileSystemEntry.new(child_name, self)
|
50
50
|
if file_contents
|
51
|
-
|
51
|
+
child.write(file_contents)
|
52
52
|
else
|
53
|
-
Dir.mkdir(
|
53
|
+
Dir.mkdir(child.file_path)
|
54
54
|
end
|
55
|
-
|
55
|
+
@children = nil
|
56
|
+
child
|
56
57
|
end
|
57
58
|
|
58
59
|
def dir?
|
@@ -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
|
data/lib/chef_fs/raw_request.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
module ChefFS
|
2
2
|
module RawRequest
|
3
3
|
def self.raw_json(chef_rest, api_path)
|
4
|
-
|
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)
|
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=
|
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
|
-
|
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=
|
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[
|
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?
|
data/lib/chef_fs/version.rb
CHANGED
@@ -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
|
-
|
44
|
+
end
|
45
45
|
|
46
|
-
|
47
|
-
|
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
|
-
|
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.
|
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-
|
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
|