chef-api 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -2
- data/CHANGELOG.md +17 -0
- data/README.md +42 -0
- data/chef-api.gemspec +1 -1
- data/lib/chef-api/configurable.rb +3 -2
- data/lib/chef-api/connection.rb +77 -47
- data/lib/chef-api/defaults.rb +28 -8
- data/lib/chef-api/errors.rb +32 -3
- data/lib/chef-api/resource.rb +1 -0
- data/lib/chef-api/resources/base.rb +30 -21
- data/lib/chef-api/resources/client.rb +6 -8
- data/lib/chef-api/resources/collection_proxy.rb +19 -2
- data/lib/chef-api/resources/data_bag.rb +1 -1
- data/lib/chef-api/resources/organization.rb +22 -0
- data/lib/chef-api/resources/user.rb +72 -1
- data/lib/chef-api/schema.rb +59 -21
- data/lib/chef-api/version.rb +1 -1
- data/lib/chef-api.rb +26 -5
- data/spec/integration/resources/client_spec.rb +54 -0
- data/spec/integration/resources/user_spec.rb +8 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/support/chef_server.rb +1 -0
- data/spec/unit/errors_spec.rb +294 -0
- data/spec/unit/resources/client_spec.rb +0 -16
- data/spec/unit/resources/connection_spec.rb +51 -0
- data/templates/errors/abstract_method.erb +5 -0
- data/templates/errors/cannot_regenerate_key.erb +1 -0
- data/templates/errors/chef_api_error.erb +1 -0
- data/templates/errors/file_not_found.erb +1 -0
- data/templates/errors/http_bad_request.erb +3 -0
- data/templates/errors/http_forbidden_request.erb +3 -0
- data/templates/errors/http_gateway_timeout.erb +3 -0
- data/templates/errors/http_method_not_allowed.erb +3 -0
- data/templates/errors/http_not_acceptable.erb +3 -0
- data/templates/errors/http_not_found.erb +3 -0
- data/templates/errors/http_server_unavailable.erb +1 -0
- data/templates/errors/http_unauthorized_request.erb +3 -0
- data/templates/errors/insufficient_file_permissions.erb +1 -0
- data/templates/errors/invalid_resource.erb +1 -0
- data/templates/errors/invalid_validator.erb +1 -0
- data/templates/errors/missing_url_parameter.erb +1 -0
- data/templates/errors/not_a_directory.erb +1 -0
- data/templates/errors/resource_already_exists.erb +1 -0
- data/templates/errors/resource_not_found.erb +1 -0
- data/templates/errors/resource_not_mutable.erb +1 -0
- data/templates/errors/unknown_attribute.erb +1 -0
- metadata +43 -17
- data/lib/chef-api/logger.rb +0 -160
- data/lib/chef-api/proxy.rb +0 -72
- data/locales/en.yml +0 -89
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2eb1855e2b759c9728d8bb855286295c5051174a
|
4
|
+
data.tar.gz: e04becfd2a2fdbac4bfa2420810f4cedace3c4f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6bfa54343067d1ebe47610970206ed7c55701e01d942a4774fb1e1645a7d289bfc965975ad2b4d25ba468b5da6091ee8c94b2e21c86a46f88cdae74136cf2ee
|
7
|
+
data.tar.gz: 5bbfff5db04efb34eb49977bc62e89bdb3c21ba97c58194e5fb3b00aee44b271be2f33ef25919fea8db55376464bc52b39b0888f47745ee0ac6b19b3897538c7
|
data/.travis.yml
CHANGED
@@ -3,8 +3,8 @@ rvm:
|
|
3
3
|
- 2.0.0
|
4
4
|
- 2.1.0
|
5
5
|
|
6
|
-
# Don't install local development gems on Travis
|
7
|
-
bundler_args: --without development
|
6
|
+
# Don't install local development gems on Travis, use parallel gem downloads
|
7
|
+
bundler_args: --without development --jobs 7
|
8
8
|
|
9
9
|
# Only test master
|
10
10
|
branches:
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
ChefAPI Changelog
|
2
|
+
=================
|
3
|
+
|
4
|
+
v0.2.1 (2014-04-17)
|
5
|
+
-------------------
|
6
|
+
- Fix a series of typographical errors
|
7
|
+
- Improved documentation for loading resources from disk
|
8
|
+
- Improved spec coverage
|
9
|
+
- Switch to Logify for logging
|
10
|
+
- Add HEC endpoint for authenticating users
|
11
|
+
- Change the default options for Hosted Chef
|
12
|
+
- Implement HTTPGatewayTimeout (504)
|
13
|
+
- Do not automatically inflate JSON objects
|
14
|
+
- Improved logging awesomeness
|
15
|
+
- Add "flavors" when defining the schema (OSC is different than HEC)
|
16
|
+
- Remove i18n in favor of ERB
|
17
|
+
- Fix an issue when providing a key at an unexpanded path
|
data/README.md
CHANGED
@@ -48,6 +48,14 @@ ChefAPI.configure do |config|
|
|
48
48
|
# Hosted Chef Server, or Enterprise Chef Server.
|
49
49
|
config.endpoint = 'https://api.opscode.com/organizations/meats'
|
50
50
|
|
51
|
+
# ChefAPI will try to determine if you are running on an Enterprise Chef
|
52
|
+
# Server or Open Source Chef depending on the URL you provide for the
|
53
|
+
# +endpoint+ attribute. However, it may be incorrect. If is seems like the
|
54
|
+
# generated schema does not match the response from the server, it is
|
55
|
+
# possible this value was calculated incorrectly. Thus, you should set it
|
56
|
+
# manually. Possible values are +:enterprise+ and +:open_source+.
|
57
|
+
config.flavor = :enterprise
|
58
|
+
|
51
59
|
# The client and key must also be specified (unless you are running Chef Zero
|
52
60
|
# in no-authentication mode). The +key+ attribute may be the raw private key,
|
53
61
|
# the path to the private key on disk, or an +OpenSSLL::PKey+ object.
|
@@ -90,6 +98,33 @@ export CHEF_API_CLIENT=bacon
|
|
90
98
|
export CHEF_API_KEY=~/.chef/bacon.pem
|
91
99
|
```
|
92
100
|
|
101
|
+
If you prefer a more object-oriented approach (or if you want to support multiple simultaneous connections), you can create a raw `ChefAPI::Connection` object. All of the options that are available on the `ChefAPI` object are also available on a raw connection:
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
connection = ChefAPI::Connection.new(
|
105
|
+
endpoint: 'https://api.opscode.com/organizations/meats',
|
106
|
+
client: 'bacon',
|
107
|
+
key: '~/.chef/bacon.pem'
|
108
|
+
)
|
109
|
+
|
110
|
+
connection.clients.fetch('chef-webui')
|
111
|
+
connection.environments.delete('production')
|
112
|
+
```
|
113
|
+
|
114
|
+
If you do not want to manage a `ChefAPI::Connection` object, or if you just prefer an alternative syntax, you can use the block-form:
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
ChefAPI::Connection.new do |connection|
|
118
|
+
connection.endpoint = 'https://api.opscode.com/organizations/meats'
|
119
|
+
connection.client = 'bacon'
|
120
|
+
connection.key = '~/.chef/bacon.pem'
|
121
|
+
|
122
|
+
# The connection object is now setup, so you can use it directly:
|
123
|
+
connection.clients.fetch('chef-webui')
|
124
|
+
connection.environments.delete('production')
|
125
|
+
end
|
126
|
+
```
|
127
|
+
|
93
128
|
### Making Requests
|
94
129
|
The ChefAPI gem attempts to wrap the Chef Server API in an object-oriented and Rubyesque way. All of the methods and API calls are heavily documented inline using YARD. For a full list of every possible option, please see the inline documentation.
|
95
130
|
|
@@ -223,6 +258,13 @@ You can also force ChefAPI to raise an exception if the validations fail, using
|
|
223
258
|
client.save! #=> InvalidResource: There were errors saving your resource: `name' must be present
|
224
259
|
```
|
225
260
|
|
261
|
+
### Objects on Disk
|
262
|
+
ChefAPI also has the ability to read and manipulate objects on disk. This varies from resource-to-resource, but the `.from_file` method accepts a path to a resource on disk and loads as much information about the object on disk as it can. The attributes are then merged with the remote resource, if one exists. For example, you can read a Client resource from disk:
|
263
|
+
|
264
|
+
```ruby
|
265
|
+
client = Client.from_file('~/.chef/bacon.pem') #=> #<Resource::Client name: "bacon", admin: false, public_key: nil, private_key: "..." ...>
|
266
|
+
```
|
267
|
+
|
226
268
|
|
227
269
|
FAQ
|
228
270
|
---
|
data/chef-api.gemspec
CHANGED
@@ -20,6 +20,6 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
21
|
spec.require_paths = ['lib']
|
22
22
|
|
23
|
-
spec.add_dependency '
|
23
|
+
spec.add_dependency 'logify', '~> 0.1'
|
24
24
|
spec.add_dependency 'mixlib-authentication', '~> 1.3'
|
25
25
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module ChefAPI
|
2
2
|
#
|
3
|
-
# A re-usable class containing configuration information for the {
|
4
|
-
# {Defaults} for a list of default values.
|
3
|
+
# A re-usable class containing configuration information for the {Connection}.
|
4
|
+
# See {Defaults} for a list of default values.
|
5
5
|
#
|
6
6
|
module Configurable
|
7
7
|
class << self
|
@@ -13,6 +13,7 @@ module ChefAPI
|
|
13
13
|
def keys
|
14
14
|
@keys ||= [
|
15
15
|
:endpoint,
|
16
|
+
:flavor,
|
16
17
|
:client,
|
17
18
|
:key,
|
18
19
|
:proxy_address,
|
data/lib/chef-api/connection.rb
CHANGED
@@ -16,33 +16,54 @@ module ChefAPI
|
|
16
16
|
#
|
17
17
|
# @macro proxy
|
18
18
|
# @method $1
|
19
|
-
# Get
|
20
|
-
# the current connection into the $2, providing a very Rubyesque way
|
21
|
-
# for handling multiple connection objects.
|
19
|
+
# Get the list of $1 for this {Connection}. This method is threadsafe.
|
22
20
|
#
|
23
|
-
# @example Get the $1 from
|
21
|
+
# @example Get the $1 from this {Connection} object
|
24
22
|
# connection = ChefAPI::Connection.new('...')
|
25
|
-
# connection.$1 #=> $2
|
23
|
+
# connection.$1 #=> $2(attribute1, attribute2, ...)
|
26
24
|
#
|
27
|
-
# @return [
|
28
|
-
# a collection proxy for the $2
|
25
|
+
# @return [Class<$2>]
|
29
26
|
#
|
30
27
|
def proxy(name, klass)
|
31
28
|
class_eval <<-EOH, __FILE__, __LINE__ + 1
|
32
29
|
def #{name}
|
33
|
-
|
30
|
+
Thread.current['chefapi.connection'] = self
|
31
|
+
#{klass}
|
34
32
|
end
|
35
33
|
EOH
|
36
34
|
end
|
37
35
|
end
|
38
36
|
|
37
|
+
include Logify
|
39
38
|
include ChefAPI::Configurable
|
40
|
-
|
39
|
+
|
40
|
+
proxy :clients, 'Resource::Client'
|
41
|
+
proxy :cookbooks, 'Resource::Cookbook'
|
42
|
+
proxy :data_bags, 'Resource::DataBag'
|
43
|
+
proxy :environments, 'Resource::Environment'
|
44
|
+
proxy :nodes, 'Resource::Node'
|
45
|
+
proxy :principals, 'Resource::Principal'
|
46
|
+
proxy :roles, 'Resource::Role'
|
47
|
+
proxy :users, 'Resource::User'
|
41
48
|
|
42
49
|
#
|
43
50
|
# Create a new ChefAPI Connection with the given options. Any options
|
44
51
|
# given take precedence over the default options.
|
45
52
|
#
|
53
|
+
# @example Create a connection object from a list of options
|
54
|
+
# ChefAPI::Connection.new(
|
55
|
+
# endpoint: 'https://...',
|
56
|
+
# client: 'bacon',
|
57
|
+
# key: '~/.chef/bacon.pem',
|
58
|
+
# )
|
59
|
+
#
|
60
|
+
# @example Create a connection object using a block
|
61
|
+
# ChefAPI::Connection.new do |connection|
|
62
|
+
# connection.endpoint = 'https://...'
|
63
|
+
# connection.client = 'bacon'
|
64
|
+
# connection.key = '~/.chef/bacon.pem'
|
65
|
+
# end
|
66
|
+
#
|
46
67
|
# @return [ChefAPI::Connection]
|
47
68
|
#
|
48
69
|
def initialize(options = {})
|
@@ -56,6 +77,8 @@ module ChefAPI
|
|
56
77
|
|
57
78
|
instance_variable_set(:"@#{key}", value)
|
58
79
|
end
|
80
|
+
|
81
|
+
yield self if block_given?
|
59
82
|
end
|
60
83
|
|
61
84
|
#
|
@@ -149,14 +172,13 @@ module ChefAPI
|
|
149
172
|
# request against
|
150
173
|
# @param [#read, Hash, nil] data
|
151
174
|
# the data to use (varies based on the +verb+)
|
152
|
-
# @param [Hash] headers
|
153
|
-
# the list of headers to use
|
154
175
|
#
|
155
176
|
# @return [String, Hash]
|
156
177
|
# the response body
|
157
178
|
#
|
158
179
|
def request(verb, path, data = {})
|
159
|
-
log.info
|
180
|
+
log.info "#{verb.to_s.upcase} #{path}..."
|
181
|
+
log.debug "Chef flavor: #{flavor.inspect}"
|
160
182
|
|
161
183
|
# Build the URI and request object from the given information
|
162
184
|
uri = build_uri(verb, path, data)
|
@@ -201,7 +223,7 @@ module ChefAPI
|
|
201
223
|
# Naughty, naughty, naughty! Don't blame when when someone hops in
|
202
224
|
# and executes a MITM attack!
|
203
225
|
unless ssl_verify
|
204
|
-
log.warn "
|
226
|
+
log.warn "Disabling SSL verification..."
|
205
227
|
log.warn "Neither ChefAPI nor the maintainers are responsible for " \
|
206
228
|
"damanges incurred as a result of disabling SSL verification. " \
|
207
229
|
"Please use this with extreme caution, or consider specifying " \
|
@@ -215,11 +237,14 @@ module ChefAPI
|
|
215
237
|
connection.start do |http|
|
216
238
|
response = http.request(request)
|
217
239
|
|
240
|
+
log.debug "Raw response:"
|
241
|
+
log.debug response.body
|
242
|
+
|
218
243
|
case response
|
219
244
|
when Net::HTTPRedirection
|
220
|
-
redirect = URI.parse(response['location'])
|
221
|
-
log.debug "
|
222
|
-
request(verb, redirect,
|
245
|
+
redirect = URI.parse(response['location']).to_s
|
246
|
+
log.debug "Performing HTTP redirect to #{redirect}"
|
247
|
+
request(verb, redirect, data)
|
223
248
|
when Net::HTTPSuccess
|
224
249
|
success(response)
|
225
250
|
else
|
@@ -227,7 +252,7 @@ module ChefAPI
|
|
227
252
|
end
|
228
253
|
end
|
229
254
|
rescue SocketError, Errno::ECONNREFUSED, EOFError
|
230
|
-
log.warn "
|
255
|
+
log.warn "Unable to reach the Chef Server"
|
231
256
|
raise Error::HTTPServerUnavailable.new
|
232
257
|
end
|
233
258
|
|
@@ -250,13 +275,16 @@ module ChefAPI
|
|
250
275
|
# @return [URI]
|
251
276
|
#
|
252
277
|
def build_uri(verb, path, params = {})
|
253
|
-
log.info "
|
278
|
+
log.info "Building URI..."
|
254
279
|
|
255
280
|
# Add any query string parameters
|
256
281
|
if [:delete, :get].include?(verb)
|
257
|
-
|
258
|
-
|
259
|
-
|
282
|
+
if querystring = to_query_string(params)
|
283
|
+
log.debug "Detected verb deserves a querystring"
|
284
|
+
log.debug "Building querystring using #{params.inspect}"
|
285
|
+
log.debug "Compiled querystring is #{querystring.inspect}"
|
286
|
+
path = [path, querystring].compact.join('?')
|
287
|
+
end
|
260
288
|
end
|
261
289
|
|
262
290
|
# Parse the URI
|
@@ -264,8 +292,8 @@ module ChefAPI
|
|
264
292
|
|
265
293
|
# Don't merge absolute URLs
|
266
294
|
unless uri.absolute?
|
267
|
-
log.debug "
|
268
|
-
log.debug "
|
295
|
+
log.debug "Detected URI is relative"
|
296
|
+
log.debug "Appending #{path} to #{endpoint}"
|
269
297
|
uri = URI.parse(File.join(endpoint, path))
|
270
298
|
end
|
271
299
|
|
@@ -274,7 +302,7 @@ module ChefAPI
|
|
274
302
|
end
|
275
303
|
|
276
304
|
#
|
277
|
-
# Helper method to get the corresponding
|
305
|
+
# Helper method to get the corresponding +Net::HTTP+ class from the given
|
278
306
|
# HTTP verb.
|
279
307
|
#
|
280
308
|
# @param [#to_s] verb
|
@@ -323,24 +351,24 @@ module ChefAPI
|
|
323
351
|
def parsed_key
|
324
352
|
return @parsed_key if @parsed_key
|
325
353
|
|
326
|
-
log.info "
|
354
|
+
log.info "Parsing private key..."
|
327
355
|
|
328
356
|
if key.nil?
|
329
|
-
log.warn "
|
357
|
+
log.warn "No private key given!"
|
330
358
|
raise 'No private key given!'
|
331
359
|
end
|
332
360
|
|
333
361
|
if key.is_a?(OpenSSL::PKey::RSA)
|
334
|
-
log.debug "
|
362
|
+
log.debug "Detected private key is an OpenSSL Ruby object"
|
335
363
|
@parsed_key = key
|
336
364
|
end
|
337
365
|
|
338
|
-
if key =~ /(.+)\.pem$/ || File.exists?(key)
|
339
|
-
log.debug "
|
366
|
+
if key =~ /(.+)\.pem$/ || File.exists?(File.expand_path(key))
|
367
|
+
log.debug "Detected private key is the path to a file"
|
340
368
|
contents = File.read(File.expand_path(key))
|
341
369
|
@parsed_key = OpenSSL::PKey::RSA.new(contents)
|
342
370
|
else
|
343
|
-
log.debug "
|
371
|
+
log.debug "Detected private key was the literal string key"
|
344
372
|
@parsed_key = OpenSSL::PKey::RSA.new(key)
|
345
373
|
end
|
346
374
|
|
@@ -359,15 +387,15 @@ module ChefAPI
|
|
359
387
|
# the parsed response, as an object
|
360
388
|
#
|
361
389
|
def success(response)
|
362
|
-
log.info "
|
390
|
+
log.info "Parsing response as success..."
|
363
391
|
|
364
392
|
case response['Content-Type']
|
365
|
-
when
|
366
|
-
log.debug "
|
367
|
-
log.debug "
|
393
|
+
when /json/
|
394
|
+
log.debug "Detected response as JSON"
|
395
|
+
log.debug "Parsing response body as JSON"
|
368
396
|
JSON.parse(response.body)
|
369
397
|
else
|
370
|
-
log.debug "
|
398
|
+
log.debug "Detected response as text/plain"
|
371
399
|
response.body
|
372
400
|
end
|
373
401
|
end
|
@@ -380,15 +408,15 @@ module ChefAPI
|
|
380
408
|
# the response object from the request
|
381
409
|
#
|
382
410
|
def error(response)
|
383
|
-
log.info "
|
411
|
+
log.info "Parsing response as error..."
|
384
412
|
|
385
413
|
case response['Content-Type']
|
386
|
-
when
|
387
|
-
log.debug "
|
388
|
-
log.debug "
|
389
|
-
message = JSON.parse(response.body)['error'].
|
414
|
+
when /json/
|
415
|
+
log.debug "Detected error response as JSON"
|
416
|
+
log.debug "Parsing error response as JSON"
|
417
|
+
message = Array(JSON.parse(response.body)['error']).join(', ')
|
390
418
|
else
|
391
|
-
log.debug "
|
419
|
+
log.debug "Detected response as text/plain"
|
392
420
|
message = response.body
|
393
421
|
end
|
394
422
|
|
@@ -405,6 +433,8 @@ module ChefAPI
|
|
405
433
|
raise Error::HTTPMethodNotAllowed.new(message: message)
|
406
434
|
when 406
|
407
435
|
raise Error::HTTPNotAcceptable.new(message: message)
|
436
|
+
when 504
|
437
|
+
raise Error::HTTPGatewayTimeout.new(message: message)
|
408
438
|
when 500..600
|
409
439
|
raise Error::HTTPServerUnavailable.new
|
410
440
|
else
|
@@ -418,7 +448,7 @@ module ChefAPI
|
|
418
448
|
# @param [Net::HTTP::Request] request
|
419
449
|
#
|
420
450
|
def add_request_headers(request)
|
421
|
-
log.info "
|
451
|
+
log.info "Adding request headers..."
|
422
452
|
|
423
453
|
headers = {
|
424
454
|
'Accept' => 'application/json',
|
@@ -430,7 +460,7 @@ module ChefAPI
|
|
430
460
|
}
|
431
461
|
|
432
462
|
headers.each do |key, value|
|
433
|
-
log.debug "
|
463
|
+
log.debug "#{key}: #{value}"
|
434
464
|
request[key] = value
|
435
465
|
end
|
436
466
|
end
|
@@ -441,9 +471,9 @@ module ChefAPI
|
|
441
471
|
# @param [Net::HTTP::Request] request
|
442
472
|
#
|
443
473
|
def add_signing_headers(verb, uri, request, key)
|
444
|
-
log.info "
|
474
|
+
log.info "Adding signed header authentication..."
|
445
475
|
|
446
|
-
unless defined?(Mixlib::Authentication)
|
476
|
+
unless defined?(Mixlib::Authentication::SignedHeaderAuth)
|
447
477
|
require 'mixlib/authentication/signedheaderauth'
|
448
478
|
end
|
449
479
|
|
@@ -451,14 +481,14 @@ module ChefAPI
|
|
451
481
|
:http_method => verb,
|
452
482
|
:body => request.body || '',
|
453
483
|
:host => "#{uri.host}:#{uri.port}",
|
454
|
-
:path =>
|
484
|
+
:path => uri.path,
|
455
485
|
:timestamp => Time.now.utc.iso8601,
|
456
486
|
:user_id => client,
|
457
487
|
:file => '',
|
458
488
|
).sign(key)
|
459
489
|
|
460
490
|
headers.each do |key, value|
|
461
|
-
log.debug "
|
491
|
+
log.debug "#{key}: #{value}"
|
462
492
|
request[key] = value
|
463
493
|
end
|
464
494
|
end
|
data/lib/chef-api/defaults.rb
CHANGED
@@ -3,7 +3,7 @@ require 'chef-api/version'
|
|
3
3
|
module ChefAPI
|
4
4
|
module Defaults
|
5
5
|
# Default API endpoint
|
6
|
-
ENDPOINT = '
|
6
|
+
ENDPOINT = 'https://api.opscode.com/'.freeze
|
7
7
|
|
8
8
|
# Default User Agent header string
|
9
9
|
USER_AGENT = "ChefAPI Ruby Gem #{ChefAPI::VERSION}".freeze
|
@@ -21,22 +21,42 @@ module ChefAPI
|
|
21
21
|
#
|
22
22
|
# The endpoint where the Chef Server lives. This is equivalent to the
|
23
23
|
# +chef_server_url+ in Chef terminology. If you are using Enterprise
|
24
|
-
# Hosted Chef or Enterprise Chef on premise, this endpoint
|
25
|
-
# organization name
|
24
|
+
# Hosted Chef or Enterprise Chef on premise, this endpoint should include
|
25
|
+
# your organization name. For example:
|
26
26
|
#
|
27
|
-
# https://api.opscode.com/organizations/
|
27
|
+
# https://api.opscode.com/organizations/bacon
|
28
28
|
#
|
29
|
-
# If you are running Open Source Chef Server or Chef Zero, this is
|
30
|
-
#
|
29
|
+
# If you are running Open Source Chef Server or Chef Zero, this is the
|
30
|
+
# full URL to your Chef Server instance, including the server port and
|
31
|
+
# FQDN.
|
31
32
|
#
|
32
|
-
#
|
33
|
+
# https://chef.server.local:4567/
|
33
34
|
#
|
34
|
-
# @return [String]
|
35
|
+
# @return [String] (default: +https://api.opscode.com/+)
|
35
36
|
#
|
36
37
|
def endpoint
|
37
38
|
ENV['CHEF_API_ENDPOINT'] || ENDPOINT
|
38
39
|
end
|
39
40
|
|
41
|
+
#
|
42
|
+
# The flavor of the target Chef Server. There are two possible values:
|
43
|
+
#
|
44
|
+
# - enterprise
|
45
|
+
# - open_source
|
46
|
+
#
|
47
|
+
# "Enterprise" covers both Hosted Chef and Enterprise Chef. "Open Source"
|
48
|
+
# covers both Chef Zero and Open Source Chef Server.
|
49
|
+
#
|
50
|
+
# @return [true, false]
|
51
|
+
#
|
52
|
+
def flavor
|
53
|
+
if ENV['CHEF_API_FLAVOR']
|
54
|
+
ENV['CHEF_API_FLAVOR'].to_sym
|
55
|
+
else
|
56
|
+
endpoint.include?('/organizations') ? :enterprise : :open_source
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
40
60
|
#
|
41
61
|
# The User Agent header to send along.
|
42
62
|
#
|
data/lib/chef-api/errors.rb
CHANGED
@@ -1,11 +1,39 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
1
3
|
module ChefAPI
|
2
4
|
module Error
|
5
|
+
class ErrorBinding
|
6
|
+
def initialize(options = {})
|
7
|
+
options.each do |key, value|
|
8
|
+
instance_variable_set(:"@#{key}", value)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_binding
|
13
|
+
binding
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
3
17
|
class ChefAPIError < StandardError
|
4
18
|
def initialize(options = {})
|
5
|
-
|
6
|
-
|
19
|
+
@options = options
|
20
|
+
@filename = options.delete(:_template)
|
21
|
+
|
22
|
+
super()
|
23
|
+
end
|
7
24
|
|
8
|
-
|
25
|
+
def message
|
26
|
+
erb = ERB.new(File.read(template))
|
27
|
+
erb.result(ErrorBinding.new(@options).get_binding)
|
28
|
+
end
|
29
|
+
alias_method :to_s, :message
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def template
|
34
|
+
class_name = self.class.to_s.split('::').last
|
35
|
+
filename = @filename || Util.underscore(class_name)
|
36
|
+
ChefAPI.root.join('templates', 'errors', "#{filename}.erb")
|
9
37
|
end
|
10
38
|
end
|
11
39
|
|
@@ -16,6 +44,7 @@ module ChefAPI
|
|
16
44
|
class HTTPError < ChefAPIError; end
|
17
45
|
class HTTPBadRequest < HTTPError; end
|
18
46
|
class HTTPForbiddenRequest < HTTPError; end
|
47
|
+
class HTTPGatewayTimeout < HTTPError; end
|
19
48
|
class HTTPNotAcceptable < HTTPError; end
|
20
49
|
class HTTPNotFound < HTTPError; end
|
21
50
|
class HTTPMethodNotAllowed < HTTPError; end
|
data/lib/chef-api/resource.rb
CHANGED
@@ -9,6 +9,7 @@ module ChefAPI
|
|
9
9
|
autoload :DataBagItem, 'chef-api/resources/data_bag_item'
|
10
10
|
autoload :Environment, 'chef-api/resources/environment'
|
11
11
|
autoload :Node, 'chef-api/resources/node'
|
12
|
+
autoload :Organization, 'chef-api/resources/organization'
|
12
13
|
autoload :Principal, 'chef-api/resources/principal'
|
13
14
|
autoload :Role, 'chef-api/resources/role'
|
14
15
|
autoload :User, 'chef-api/resources/user'
|