spice 1.0.0.rc → 1.0.0
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.
- data/.gitignore +2 -0
- data/Gemfile +0 -14
- data/README.md +1 -1
- data/Rakefile +1 -1
- data/TODO.md +2 -1
- data/lib/spice.rb +47 -72
- data/lib/spice/authentication.rb +23 -45
- data/lib/spice/base.rb +104 -0
- data/lib/spice/client.rb +8 -48
- data/lib/spice/config.rb +37 -19
- data/lib/spice/connection.rb +33 -117
- data/lib/spice/connection/clients.rb +26 -6
- data/lib/spice/connection/cookbooks.rb +19 -14
- data/lib/spice/connection/data_bags.rb +31 -20
- data/lib/spice/connection/environments.rb +6 -7
- data/lib/spice/connection/nodes.rb +23 -6
- data/lib/spice/connection/roles.rb +5 -5
- data/lib/spice/connection/search.rb +12 -12
- data/lib/spice/cookbook.rb +3 -29
- data/lib/spice/cookbook_version.rb +9 -61
- data/lib/spice/core_ext/array.rb +7 -0
- data/lib/spice/core_ext/enumerable.rb +11 -0
- data/lib/spice/core_ext/hash.rb +49 -0
- data/lib/spice/core_ext/mash.rb +219 -0
- data/lib/spice/data_bag.rb +3 -37
- data/lib/spice/data_bag_item.rb +7 -47
- data/lib/spice/environment.rb +12 -27
- data/lib/spice/error.rb +22 -10
- data/lib/spice/identity_map.rb +8 -0
- data/lib/spice/node.rb +13 -34
- data/lib/spice/request.rb +73 -11
- data/lib/spice/response/parse_json.rb +8 -3
- data/lib/spice/role.rb +8 -33
- data/lib/spice/version.rb +1 -1
- data/spec/fixtures/client.pem +27 -0
- data/spec/fixtures/clients/create.json +4 -0
- data/spec/fixtures/clients/index.json +5 -0
- data/spec/fixtures/clients/reregister.json +5 -0
- data/spec/fixtures/clients/show.json +8 -0
- data/spec/fixtures/clients/update.json +5 -0
- data/spec/fixtures/cookbook_versions/show.json +108 -0
- data/spec/fixtures/cookbook_versions/update.json +62 -0
- data/spec/fixtures/cookbooks/index-0.10.json +28 -0
- data/spec/fixtures/cookbooks/index-0.9.json +4 -0
- data/spec/fixtures/cookbooks/show-0.10.json +15 -0
- data/spec/fixtures/cookbooks/show-apache2-0.9.json +5 -0
- data/spec/fixtures/cookbooks/show-unicorn-0.9.json +5 -0
- data/spec/fixtures/data_bag_items/create.json +1 -0
- data/spec/fixtures/data_bag_items/show.json +4 -0
- data/spec/fixtures/data_bag_items/update.json +4 -0
- data/spec/fixtures/data_bags/create.json +3 -0
- data/spec/fixtures/data_bags/index.json +3 -0
- data/spec/fixtures/data_bags/show.json +3 -0
- data/spec/fixtures/environments/cookbook.json +15 -0
- data/spec/fixtures/environments/cookbooks.json +28 -0
- data/spec/fixtures/environments/create.json +1 -0
- data/spec/fixtures/environments/delete.json +8 -0
- data/spec/fixtures/environments/index.json +3 -0
- data/spec/fixtures/environments/show.json +8 -0
- data/spec/fixtures/environments/update.json +8 -0
- data/spec/fixtures/nodes/cookbooks.json +41 -0
- data/spec/fixtures/nodes/create.json +1 -0
- data/spec/fixtures/nodes/delete.json +17 -0
- data/spec/fixtures/nodes/index.json +3 -0
- data/spec/fixtures/nodes/show.json +17 -0
- data/spec/fixtures/nodes/update.json +13 -0
- data/spec/fixtures/roles/create.json +1 -0
- data/spec/fixtures/roles/delete.json +11 -0
- data/spec/fixtures/roles/index.json +3 -0
- data/spec/fixtures/roles/show.json +12 -0
- data/spec/fixtures/roles/update.json +11 -0
- data/spec/fixtures/search/client.json +1 -0
- data/spec/fixtures/search/data_bag.json +1 -0
- data/spec/fixtures/search/environment.json +1 -0
- data/spec/fixtures/search/node.json +1 -0
- data/spec/fixtures/search/role.json +1 -0
- data/spec/spec_helper.rb +5 -4
- data/spec/spice/base_spec.rb +34 -0
- data/spec/spice/client_spec.rb +0 -61
- data/spec/spice/config_spec.rb +14 -0
- data/spec/spice/connection/clients_spec.rb +82 -0
- data/spec/spice/connection/cookbooks_spec.rb +86 -0
- data/spec/spice/connection/data_bags_spec.rb +126 -0
- data/spec/spice/connection_spec.rb +63 -0
- data/spec/spice/cookbook_spec.rb +0 -61
- data/spec/spice/data_bag_item_spec.rb +7 -0
- data/spec/spice/data_bag_spec.rb +0 -160
- data/spec/spice/environment_spec.rb +0 -89
- data/spec/spice/node_spec.rb +0 -74
- data/spec/spice/role_spec.rb +0 -61
- data/spec/spice_spec.rb +8 -116
- data/spec/support/helpers.rb +58 -0
- data/spice.gemspec +13 -15
- metadata +227 -87
- data/.watchr +0 -22
- data/lib/spice/connection/authentication.rb +0 -47
- data/lib/spice/mock.rb +0 -46
- data/lib/spice/persistence.rb +0 -62
- data/spec/spice/chef_spec.rb +0 -52
- data/spec/spice/search_spec.rb +0 -2
- data/spec/support/chef_requests.rb +0 -0
- data/spec/support/client_requests.rb +0 -95
- data/spec/support/cookbook_requests.rb +0 -95
- data/spec/support/data_bag_item_requests.rb +0 -138
- data/spec/support/data_bag_requests.rb +0 -95
- data/spec/support/environment_requests.rb +0 -221
- data/spec/support/node_requests.rb +0 -138
- data/spec/support/respond_with_matcher.rb +0 -53
- data/spec/support/role_requests.rb +0 -95
data/.gitignore
CHANGED
data/Gemfile
CHANGED
|
@@ -2,20 +2,6 @@ source "http://rubygems.org"
|
|
|
2
2
|
|
|
3
3
|
gemspec
|
|
4
4
|
|
|
5
|
-
group :development, :test do
|
|
6
|
-
gem 'rake'
|
|
7
|
-
gem 'rspec', '>= 2.8.0'
|
|
8
|
-
gem "webmock", ">= 1.7.10"
|
|
9
|
-
gem "timecop", ">= 0.3.5"
|
|
10
|
-
gem 'fakefs', '>= 0.3.2'
|
|
11
|
-
gem 'guard', '>= 0.10.0'
|
|
12
|
-
gem 'guard-rspec', '>= 0.6.0'
|
|
13
|
-
gem 'guard-spork', '>= 0.5.1'
|
|
14
|
-
gem 'spork', '>= 0.9.0.rc9'
|
|
15
|
-
gem 'rb-fsevent', '>= 0.4.3.1'
|
|
16
|
-
gem 'growl', '>= 1.0.3'
|
|
17
|
-
end
|
|
18
|
-
|
|
19
5
|
group :doc do
|
|
20
6
|
gem 'yard'
|
|
21
7
|
gem 'redcarpet'
|
data/README.md
CHANGED
|
@@ -24,7 +24,7 @@ Explicitly setting a `host`, `port`, and `scheme` value has been removed in favo
|
|
|
24
24
|
|
|
25
25
|
### Hat tip
|
|
26
26
|
|
|
27
|
-
Spice is very heavily inspired by the [Twitter gem](http://github.com/jnunemaker/twitter). Mad props to those folks.
|
|
27
|
+
The design and organization of Spice is very heavily inspired by the [Twitter gem](http://github.com/jnunemaker/twitter). Mad props to those folks.
|
|
28
28
|
|
|
29
29
|
## Contributing to spice
|
|
30
30
|
|
data/Rakefile
CHANGED
|
@@ -18,11 +18,11 @@ task :spork do
|
|
|
18
18
|
sh %{bundle exec spork}
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
|
|
22
21
|
Bundler.require(:doc)
|
|
23
22
|
desc "Generate documentation"
|
|
24
23
|
YARD::Rake::YardocTask.new do |t|
|
|
25
24
|
t.files = [ 'lib/**/*.rb' ]
|
|
25
|
+
t.options = [ "--markup-provider=redcarpet", "--markup=markdown" ]
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
desc "Generate docs"
|
data/TODO.md
CHANGED
data/lib/spice.rb
CHANGED
|
@@ -1,81 +1,56 @@
|
|
|
1
|
-
require '
|
|
2
|
-
require 'aequitas'
|
|
3
|
-
require 'active_model/callbacks'
|
|
4
|
-
require 'active_support/core_ext/hash/deep_merge'
|
|
5
|
-
require 'active_support/core_ext/hash/keys'
|
|
6
|
-
require 'mixlib/authentication'
|
|
1
|
+
require 'spice/core_ext/mash'
|
|
7
2
|
|
|
8
3
|
require 'spice/config'
|
|
9
|
-
require 'spice/error'
|
|
10
|
-
require 'spice/authentication'
|
|
11
|
-
|
|
12
|
-
require 'spice/role'
|
|
13
|
-
require 'spice/client'
|
|
14
|
-
require 'spice/cookbook'
|
|
15
|
-
require 'spice/cookbook_version'
|
|
16
|
-
require 'spice/data_bag'
|
|
17
|
-
require 'spice/data_bag_item'
|
|
18
|
-
require 'spice/node'
|
|
19
|
-
require 'spice/environment'
|
|
20
4
|
require 'spice/connection'
|
|
21
5
|
|
|
22
|
-
require 'spice/connection/clients'
|
|
23
|
-
require 'spice/connection/cookbooks'
|
|
24
|
-
require 'spice/connection/data_bags'
|
|
25
|
-
require 'spice/connection/environments'
|
|
26
|
-
require 'spice/connection/nodes'
|
|
27
|
-
require 'spice/connection/roles'
|
|
28
|
-
require 'spice/connection/search'
|
|
29
|
-
|
|
30
|
-
require 'spice/version'
|
|
31
|
-
require 'spice/mock'
|
|
32
|
-
|
|
33
6
|
module Spice
|
|
34
|
-
extend Config
|
|
35
|
-
extend self
|
|
7
|
+
extend Spice::Config
|
|
36
8
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
9
|
+
class << self
|
|
10
|
+
# Convience alias for Spice::Connection.new
|
|
11
|
+
#
|
|
12
|
+
# return [Spice::Connection]
|
|
13
|
+
def new(options=Mash.new)
|
|
14
|
+
Spice::Connection.new(options)
|
|
15
|
+
end # def new
|
|
44
16
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
17
|
+
# Delegate methods to Spice::Connection
|
|
18
|
+
def method_missing(method, *args, &block)
|
|
19
|
+
return super unless new.respond_to?(method)
|
|
20
|
+
new.send(method, *args, &block)
|
|
21
|
+
end # def method_missing
|
|
22
|
+
|
|
23
|
+
def respond_to?(method, include_private=false)
|
|
24
|
+
new.respond_to?(method, include_private) || super(method, include_private)
|
|
25
|
+
end # def respond_to?
|
|
26
|
+
|
|
27
|
+
def mock
|
|
28
|
+
Spice.server_url = 'http://localhost:4000'
|
|
29
|
+
Spice.client_name = "testclient"
|
|
30
|
+
Spice.client_key = Spice.read_key_file(File.expand_path("../../spec/fixtures/client.pem", __FILE__))
|
|
31
|
+
Spice.chef_version = "0.10.10"
|
|
32
|
+
self
|
|
33
|
+
end # def mock
|
|
34
|
+
|
|
35
|
+
def read_key_file(key_file_path)
|
|
36
|
+
|
|
37
|
+
begin
|
|
38
|
+
raw_key = File.read(key_file_path).strip
|
|
39
|
+
rescue SystemCallError, IOError => e
|
|
40
|
+
raise IOError, "Unable to read #{key_file_path}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
begin_rsa = "-----BEGIN RSA PRIVATE KEY-----"
|
|
44
|
+
end_rsa = "-----END RSA PRIVATE KEY-----"
|
|
45
|
+
|
|
46
|
+
unless (raw_key =~ /\A#{begin_rsa}$/) && (raw_key =~ /^#{end_rsa}\Z/)
|
|
47
|
+
msg = "The file #{key_file} is not a properly formatted private key.\n"
|
|
48
|
+
msg << "It must contain '#{begin_rsa}' and '#{end_rsa}'"
|
|
49
|
+
raise ArgumentError, msg
|
|
50
|
+
end
|
|
51
|
+
return OpenSSL::PKey::RSA.new(raw_key)
|
|
52
|
+
end # def read_key_file
|
|
79
53
|
|
|
54
|
+
end # class << self
|
|
55
|
+
end # module Spice
|
|
80
56
|
|
|
81
|
-
end
|
data/lib/spice/authentication.rb
CHANGED
|
@@ -1,52 +1,30 @@
|
|
|
1
1
|
require 'openssl'
|
|
2
|
+
# require 'mixlib/authentication'
|
|
2
3
|
require 'mixlib/authentication/signedheaderauth'
|
|
3
4
|
|
|
4
5
|
module Spice
|
|
5
|
-
|
|
6
|
-
attr_reader :key_file, :client_name, :key, :raw_key
|
|
6
|
+
module Authentication
|
|
7
7
|
|
|
8
|
-
def
|
|
9
|
-
|
|
10
|
-
load_signing_key if sign_requests?
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def sign_requests?
|
|
14
|
-
!!key_file
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def signature_headers(request_params={})
|
|
18
|
-
request_params = request_params.dup
|
|
19
|
-
request_params[:timestamp] = Time.now.utc.iso8601
|
|
20
|
-
request_params[:user_id] = client_name
|
|
21
|
-
host = request_params.delete(:host) || "localhost"
|
|
8
|
+
def signature_headers(method, path, json_body=nil)
|
|
9
|
+
uri = URI(server_url)
|
|
22
10
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
11
|
+
params = {
|
|
12
|
+
:http_method => method,
|
|
13
|
+
:path => path,
|
|
14
|
+
:body => json_body || "",
|
|
15
|
+
:host => "#{uri.host}:#{uri.port}",
|
|
16
|
+
:timestamp => Time.now.utc.iso8601,
|
|
17
|
+
:user_id => client_name
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
signing_object = Mixlib::Authentication::SignedHeaderAuth.signing_object(params)
|
|
21
|
+
signed_headers = signing_object.sign(client_key)
|
|
22
|
+
|
|
26
23
|
# Platform requires X-Chef-Version header
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
begin
|
|
35
|
-
@raw_key = File.read(key_file).strip
|
|
36
|
-
rescue SystemCallError, IOError => e
|
|
37
|
-
raise IOError, "Unable to read #{key_file}"
|
|
38
|
-
end
|
|
39
|
-
assert_valid_key_format!(@raw_key)
|
|
40
|
-
@key = OpenSSL::PKey::RSA.new(@raw_key)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def assert_valid_key_format!(raw_key)
|
|
44
|
-
unless (raw_key =~ /\A-----BEGIN RSA PRIVATE KEY-----$/) &&
|
|
45
|
-
(raw_key =~ /^-----END RSA PRIVATE KEY-----\Z/)
|
|
46
|
-
msg = "The file #{key_file} does not contain a correctly formatted private key.\n"
|
|
47
|
-
msg << "The key file should begin with '-----BEGIN RSA PRIVATE KEY-----' and end with '-----END RSA PRIVATE KEY-----'"
|
|
48
|
-
raise ArgumentError, msg
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
24
|
+
signed_headers['X-Chef-Version'] = chef_version
|
|
25
|
+
# signed_headers['Content-Length'] = json_body.bytesize.to_s if json_body
|
|
26
|
+
signed_headers
|
|
27
|
+
end # def signature_headers
|
|
28
|
+
|
|
29
|
+
end # module Authentication
|
|
30
|
+
end # module Spice
|
data/lib/spice/base.rb
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
require 'spice/identity_map'
|
|
2
|
+
|
|
3
|
+
module Spice
|
|
4
|
+
class Base
|
|
5
|
+
attr_accessor :attrs
|
|
6
|
+
alias :to_hash :attrs
|
|
7
|
+
|
|
8
|
+
@@identity_map = IdentityMap.new
|
|
9
|
+
|
|
10
|
+
def self.identity_map
|
|
11
|
+
@@identity_map
|
|
12
|
+
end # def self.identity_map
|
|
13
|
+
|
|
14
|
+
# Define methods that retrieve the value from an initialized instance variable Hash, using the attribute as a key
|
|
15
|
+
#
|
|
16
|
+
# @overload self.attr_reader(attr)
|
|
17
|
+
# @param attr [Symbol]
|
|
18
|
+
# @overload self.attr_reader(attrs)
|
|
19
|
+
# @param attrs [Array<Symbol>]
|
|
20
|
+
def self.attr_reader(*attrs)
|
|
21
|
+
attrs.each do |attribute|
|
|
22
|
+
class_eval do
|
|
23
|
+
define_method attribute do
|
|
24
|
+
@attrs[attribute.to_s]
|
|
25
|
+
end
|
|
26
|
+
define_method "#{attribute}=" do |value|
|
|
27
|
+
@attrs[attribute.to_s] = value
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end # def self.attr_reader
|
|
32
|
+
|
|
33
|
+
def self.get(attrs=Mash.new)
|
|
34
|
+
@@identity_map[self] ||= {}
|
|
35
|
+
if attrs['name']
|
|
36
|
+
@@identity_map[self][attrs['name']] && @@identity_map[self][attrs['name']].update(attrs)
|
|
37
|
+
elsif attrs['id']
|
|
38
|
+
@@identity_map[self][attrs['id']] && @@identity_map[self][attrs['id']].update(attrs)
|
|
39
|
+
else
|
|
40
|
+
@@identity_map[self][Marshal.dump(attrs)]
|
|
41
|
+
end
|
|
42
|
+
end # def self.get
|
|
43
|
+
|
|
44
|
+
# Retrieve an object from the identity map or initialize a new object
|
|
45
|
+
def self.get_or_new(attrs=Mash.new)
|
|
46
|
+
self.get(attrs) || self.new(attrs)
|
|
47
|
+
end # def self.get_or_new
|
|
48
|
+
|
|
49
|
+
# Initializes a new object
|
|
50
|
+
#
|
|
51
|
+
# @param attrs [Hash]
|
|
52
|
+
# @return [Spice::Base]
|
|
53
|
+
def initialize(attrs=Mash.new)
|
|
54
|
+
self.class.attr_reader *attrs.keys
|
|
55
|
+
attrs.stringify_keys!
|
|
56
|
+
if attrs['name']
|
|
57
|
+
self.update(attrs)
|
|
58
|
+
@@identity_map[self.class] ||= {}
|
|
59
|
+
@@identity_map[self.class][attrs['name']] = self
|
|
60
|
+
elsif attrs['id']
|
|
61
|
+
self.update(attrs)
|
|
62
|
+
@@identity_map[self.class] ||= {}
|
|
63
|
+
@@identity_map[self.class][attrs['id']] = self
|
|
64
|
+
else
|
|
65
|
+
self.update(attrs)
|
|
66
|
+
@@identity_map[self.class] ||= {}
|
|
67
|
+
@@identity_map[self.class][Marshal.dump(attrs)] = self
|
|
68
|
+
end
|
|
69
|
+
end # def initialize
|
|
70
|
+
|
|
71
|
+
# Fetches an attribute of an object using hash notation
|
|
72
|
+
#
|
|
73
|
+
# @param method [String, Symbol] Message to send to the object
|
|
74
|
+
def [](method)
|
|
75
|
+
self.__send__(method.to_sym)
|
|
76
|
+
rescue NoMethodError
|
|
77
|
+
nil
|
|
78
|
+
end # def []
|
|
79
|
+
|
|
80
|
+
# Update the attributes of an object
|
|
81
|
+
#
|
|
82
|
+
# @param attrs [Hash]
|
|
83
|
+
# @return [Spice::Base]
|
|
84
|
+
def update(attrs)
|
|
85
|
+
@attrs = attrs
|
|
86
|
+
self
|
|
87
|
+
end # def update
|
|
88
|
+
|
|
89
|
+
# @return [Integer]
|
|
90
|
+
def id
|
|
91
|
+
@attrs['id']
|
|
92
|
+
end # def id
|
|
93
|
+
|
|
94
|
+
# @return [String]
|
|
95
|
+
def name
|
|
96
|
+
@attrs['name']
|
|
97
|
+
end # def name
|
|
98
|
+
|
|
99
|
+
def keys
|
|
100
|
+
@attrs.keys
|
|
101
|
+
end # def keys
|
|
102
|
+
|
|
103
|
+
end
|
|
104
|
+
end
|
data/lib/spice/client.rb
CHANGED
|
@@ -1,55 +1,15 @@
|
|
|
1
|
-
require 'spice/
|
|
1
|
+
require 'spice/base'
|
|
2
2
|
|
|
3
3
|
module Spice
|
|
4
|
-
class Client
|
|
5
|
-
|
|
6
|
-
include Aequitas
|
|
7
|
-
include Spice::Persistence
|
|
8
|
-
extend Spice::Persistence
|
|
4
|
+
class Client < Base
|
|
5
|
+
attr_reader :name, :public_key, :private_key, :_rev, :admin
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
attribute :name, String
|
|
16
|
-
attribute :public_key, String
|
|
17
|
-
attribute :private_key, String
|
|
18
|
-
attribute :_rev, String
|
|
19
|
-
attribute :json_class, String, :default => "Chef::ApiClient"
|
|
20
|
-
attribute :admin, Boolean, :default => false
|
|
21
|
-
attribute :chef_type, String, :default => "client"
|
|
22
|
-
|
|
23
|
-
validates_presence_of :name, :json_class, :chef_type
|
|
24
|
-
|
|
25
|
-
after_create :wat
|
|
26
|
-
def wat
|
|
27
|
-
puts "WAT"
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def do_post
|
|
31
|
-
response = connection.post("/clients", :name => name)
|
|
32
|
-
update_attributes(response.body)
|
|
33
|
-
response = connection.get("/clients/#{name}")
|
|
34
|
-
update_attributes(response.body)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def do_put
|
|
38
|
-
response = connection.put("/clients/#{name}", attributes)
|
|
7
|
+
def initialize(attrs=Mash.new)
|
|
8
|
+
super
|
|
9
|
+
@attrs['json_class'] ||= "Chef::ApiClient"
|
|
10
|
+
@attrs['chef_type'] ||= 'client'
|
|
11
|
+
@attrs['admin'] ||= false
|
|
39
12
|
end
|
|
40
13
|
|
|
41
|
-
def self.get(name)
|
|
42
|
-
connection.client(name)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# Check if the client exists on the Chef server
|
|
46
|
-
def new_record?
|
|
47
|
-
begin
|
|
48
|
-
connection.get("/clients/#{name}")
|
|
49
|
-
return false
|
|
50
|
-
rescue Spice::Error::NotFound
|
|
51
|
-
return true
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
14
|
end
|
|
55
15
|
end
|
data/lib/spice/config.rb
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
|
+
require 'faraday'
|
|
2
|
+
require 'spice/response/parse_json'
|
|
3
|
+
require 'spice/response/client_error'
|
|
1
4
|
require 'spice/version'
|
|
2
5
|
|
|
3
6
|
module Spice
|
|
4
7
|
module Config
|
|
8
|
+
|
|
5
9
|
# The default Chef server URL
|
|
6
10
|
DEFAULT_SERVER_URL = "http://localhost:4000"
|
|
7
11
|
|
|
8
12
|
# The default Chef version (changing this will enable disable certain features)
|
|
9
|
-
DEFAULT_CHEF_VERSION = "0.10.
|
|
13
|
+
DEFAULT_CHEF_VERSION = "0.10.10"
|
|
10
14
|
|
|
11
15
|
# The default Spice User-Agent header
|
|
12
16
|
DEFAULT_USER_AGENT = "Spice #{Spice::VERSION}"
|
|
@@ -14,17 +18,31 @@ module Spice
|
|
|
14
18
|
# Default connection options
|
|
15
19
|
DEFAULT_CONNECTION_OPTIONS = {}
|
|
16
20
|
|
|
21
|
+
# Default client name
|
|
22
|
+
DEFAULT_CLIENT_NAME = ""
|
|
23
|
+
|
|
24
|
+
# Default key file
|
|
25
|
+
DEFAULT_CLIENT_KEY = ""
|
|
26
|
+
|
|
17
27
|
# An array of valid config options
|
|
28
|
+
|
|
18
29
|
VALID_OPTIONS_KEYS = [
|
|
19
30
|
:server_url,
|
|
20
31
|
:client_name,
|
|
21
|
-
:
|
|
22
|
-
:raw_key,
|
|
32
|
+
:client_key,
|
|
23
33
|
:chef_version,
|
|
24
34
|
:user_agent,
|
|
25
|
-
:connection_options
|
|
35
|
+
:connection_options,
|
|
36
|
+
:middleware
|
|
26
37
|
]
|
|
27
38
|
|
|
39
|
+
# Default middleware stack
|
|
40
|
+
DEFAULT_MIDDLEWARE = Proc.new do |builder|
|
|
41
|
+
builder.use Spice::Response::ParseJSON
|
|
42
|
+
builder.use Spice::Response::ClientError
|
|
43
|
+
builder.adapter Faraday.default_adapter
|
|
44
|
+
end
|
|
45
|
+
|
|
28
46
|
VALID_OPTIONS_KEYS.each do |key|
|
|
29
47
|
attr_accessor key
|
|
30
48
|
end
|
|
@@ -32,40 +50,40 @@ module Spice
|
|
|
32
50
|
# Reset all config options to default when the module is extended
|
|
33
51
|
def self.extended(base)
|
|
34
52
|
base.reset
|
|
35
|
-
end
|
|
53
|
+
end # def self.extended
|
|
36
54
|
|
|
37
55
|
# Convenience method to configure Spice in a block
|
|
38
56
|
# @example Configuring spice
|
|
39
57
|
# Spice.setup do |s|
|
|
40
58
|
# s.server_url = "http://chef.example.com:4000"
|
|
41
59
|
# s.client_name = "admin"
|
|
42
|
-
# s.
|
|
60
|
+
# s.client_key = Spice.read_key_file("/path/to/key_file.pem")
|
|
43
61
|
# end
|
|
44
62
|
# @yieldparam Spice
|
|
45
|
-
# @yieldreturn Spice
|
|
46
|
-
|
|
63
|
+
# @yieldreturn Spice
|
|
47
64
|
def setup
|
|
48
65
|
yield self
|
|
49
66
|
self
|
|
50
|
-
end
|
|
67
|
+
end # def setup
|
|
51
68
|
|
|
52
69
|
# Create an options hash from valid options keys
|
|
53
70
|
def options
|
|
54
71
|
options = {}
|
|
55
72
|
VALID_OPTIONS_KEYS.each{|k| options[k] = send(k)}
|
|
56
73
|
options
|
|
57
|
-
end
|
|
74
|
+
end # def options
|
|
58
75
|
|
|
59
76
|
# Reset all config options to their defaults
|
|
60
77
|
def reset
|
|
61
|
-
self.user_agent
|
|
62
|
-
self.server_url
|
|
63
|
-
self.chef_version
|
|
64
|
-
self.client_name
|
|
65
|
-
self.
|
|
66
|
-
self.raw_key = nil
|
|
78
|
+
self.user_agent = DEFAULT_USER_AGENT
|
|
79
|
+
self.server_url = DEFAULT_SERVER_URL
|
|
80
|
+
self.chef_version = DEFAULT_CHEF_VERSION
|
|
81
|
+
self.client_name = DEFAULT_CLIENT_NAME
|
|
82
|
+
self.client_key = DEFAULT_CLIENT_KEY
|
|
67
83
|
self.connection_options = DEFAULT_CONNECTION_OPTIONS
|
|
68
|
-
|
|
84
|
+
self.middleware = DEFAULT_MIDDLEWARE
|
|
85
|
+
self
|
|
86
|
+
end # def reset
|
|
69
87
|
|
|
70
|
-
end
|
|
71
|
-
end
|
|
88
|
+
end # module Config
|
|
89
|
+
end # module Spice
|