Skip to content

Commit 02b95ab

Browse files
committed
full refactor
1 parent f6ab41c commit 02b95ab

17 files changed

+81
-171
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ doc/**/*
77
.yardoc/*
88
Gemfile.lock
99
fixture.rb
10+
coverage
11+
wiki

Rakefile

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Bundler.require(:doc)
2323
desc "Generate documentation"
2424
YARD::Rake::YardocTask.new do |t|
2525
t.files = [ 'lib/**/*.rb' ]
26+
# t.options = [ "-M redcarpet" ]
2627
end
2728

2829
desc "Generate docs"

TODO.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
* Refactor classes that inherit from Spice::Chef to take config values
2-
* Add support for data bag item creation
2+
* Add support for data bag item creation
3+
* implement GET /cookbooks?num_versions=all

lib/spice.rb

+27-5
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
require 'spice/config'
44
require 'spice/connection'
55

6-
require 'spice/mock'
7-
86
module Spice
97
extend Spice::Config
108

@@ -27,8 +25,32 @@ def respond_to?(method, include_private=false)
2725
end # def respond_to?
2826

2927
def mock
30-
Spice::Mock.setup_mock_client
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
3133
end # def mock
32-
end
33-
end
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
53+
54+
end # class << self
55+
end # module Spice
3456

lib/spice/authentication.rb

+4-19
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,22 @@ module Spice
66
module Authentication
77

88
def signature_headers(method, path, json_body=nil)
9-
uri = URI(Spice.server_url)
9+
uri = URI(server_url)
1010

1111
params = {
1212
:http_method => method,
1313
:path => path,
1414
:body => json_body || "",
1515
:host => "#{uri.host}:#{uri.port}",
1616
:timestamp => Time.now.utc.iso8601,
17-
:user_id => Spice.client_name
17+
:user_id => client_name
1818
}
19-
20-
begin
21-
raw_key = File.read(Spice.key_file).strip
22-
rescue SystemCallError, IOError => e
23-
raise IOError, "Unable to read #{key_file}"
24-
end
25-
26-
unless (raw_key =~ /\A-----BEGIN RSA PRIVATE KEY-----$/) &&
27-
(raw_key =~ /^-----END RSA PRIVATE KEY-----\Z/)
28-
msg = "The file #{key_file} is not a properly formatted private key.\n"
29-
msg << "It must contain '-----BEGIN RSA PRIVATE KEY-----' and '-----END RSA PRIVATE KEY-----'"
30-
raise ArgumentError, msg
31-
end
32-
33-
key = OpenSSL::PKey::RSA.new(raw_key)
3419

3520
signing_object = Mixlib::Authentication::SignedHeaderAuth.signing_object(params)
36-
signed_headers = signing_object.sign(key)
21+
signed_headers = signing_object.sign(client_key)
3722

3823
# Platform requires X-Chef-Version header
39-
signed_headers['X-Chef-Version'] = Spice.chef_version
24+
signed_headers['X-Chef-Version'] = chef_version
4025
# signed_headers['Content-Length'] = json_body.bytesize.to_s if json_body
4126
signed_headers
4227
end # def signature_headers

lib/spice/config.rb

+7-7
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,17 @@ module Config
1919
DEFAULT_CONNECTION_OPTIONS = {}
2020

2121
# Default client name
22-
DEFAULT_CLIENT_NAME = nil
22+
DEFAULT_CLIENT_NAME = ""
2323

2424
# Default key file
25-
DEFAULT_KEY_FILE = nil
25+
DEFAULT_CLIENT_KEY = ""
2626

2727
# An array of valid config options
28+
2829
VALID_OPTIONS_KEYS = [
2930
:server_url,
3031
:client_name,
31-
:key_file,
32+
:client_key,
3233
:chef_version,
3334
:user_agent,
3435
:connection_options,
@@ -56,11 +57,10 @@ def self.extended(base)
5657
# Spice.setup do |s|
5758
# s.server_url = "http://chef.example.com:4000"
5859
# s.client_name = "admin"
59-
# s.key_file = "/home/admin/.chef/admin.pem"
60+
# s.client_key = Spice.read_key_file("/path/to/key_file.pem")
6061
# end
6162
# @yieldparam Spice
62-
# @yieldreturn Spice
63-
63+
# @yieldreturn Spice
6464
def setup
6565
yield self
6666
self
@@ -79,7 +79,7 @@ def reset
7979
self.server_url = DEFAULT_SERVER_URL
8080
self.chef_version = DEFAULT_CHEF_VERSION
8181
self.client_name = DEFAULT_CLIENT_NAME
82-
self.key_file = DEFAULT_KEY_FILE
82+
self.client_key = DEFAULT_CLIENT_KEY
8383
self.connection_options = DEFAULT_CONNECTION_OPTIONS
8484
self.middleware = DEFAULT_MIDDLEWARE
8585
self

lib/spice/connection.rb

+6-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,12 @@ class Connection
3333
include Spice::Connection::Search
3434
include Spice::Request
3535
include Spice::Authentication
36-
37-
attr_accessor *Config::VALID_OPTIONS_KEYS
36+
37+
# @private
38+
39+
Config::VALID_OPTIONS_KEYS.each do |key|
40+
attr_accessor key
41+
end
3842

3943
def initialize(attrs=Mash.new)
4044
attrs = Spice.options.merge(attrs)

lib/spice/connection/cookbooks.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ module Cookbooks
88
def cookbooks
99
if Gem::Version.new(Spice.chef_version) >= Gem::Version.new("0.10.0")
1010
cookbooks = []
11-
get("/cookbooks").each_pair do |key, value|
11+
get("/cookbooks?num_versions=all").each_pair do |key, value|
1212
versions = value['versions'].map{ |v| v['version'] }
1313
cookbooks << Spice::Cookbook.get_or_new(:name => key, :versions => versions)
1414
end
1515
cookbooks
1616
else
1717
get("/cookbooks").keys.map do |cookbook|
18-
attributes = get("/cookbooks/#{cookbook}").to_a[0]
19-
Spice::Cookbook.get_or_new(:name => attributes[0], :versions => attributes[1])
18+
cb = get("/cookbooks/#{cookbook}")
19+
Spice::Cookbook.get_or_new(:name => cookbook, :versions => cb[cookbook])
2020
end
2121
end
2222
end # def cookbooks

lib/spice/connection/data_bags.rb

+2-3
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@ def data_bag(name)
2929
# @return [Spice::DataBagItem]
3030
# @raise [Spice::Error::NotFound] raised when data bag item does not exist
3131
def data_bag_item(name, id)
32-
data = get("/data/#{name}/#{id}")
33-
data.delete('id')
34-
Spice::DataBagItem.get_or_new(:_id => id, :data => data, :name => name)
32+
data_bag_item = get("/data/#{name}/#{id}")
33+
Spice::DataBagItem.get_or_new(data_bag_item)
3534
end # def data_bag_item
3635

3736
def create_data_bag(name)

lib/spice/connection/search.rb

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module Search
88
# @option options [Numeric] :start The number by which to offset the results
99
# @option options [Numeric] :rows The maximum number of rows to return
1010
def search(index, options=Mash.new)
11+
index = index.to_s
1112
options = {:q => options} if options.is_a? String
1213
options.symbolize_keys!
1314

lib/spice/core_ext/mash.rb

+4-10
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class Mash < Hash
5353
# @param constructor<Object>
5454
# The default value for the mash. Defaults to an empty hash.
5555
#
56-
# @details [Alternatives]
56+
# [Alternatives]
5757
# If constructor is a Hash, a new mash will be created based on the keys of
5858
# the hash and no default value will be set.
5959
def initialize(constructor = {})
@@ -81,7 +81,7 @@ def initialize_copy(orig)
8181

8282
# @param key<Object> The default value for the mash. Defaults to nil.
8383
#
84-
# @details [Alternatives]
84+
# [Alternatives]
8585
# If key is a Symbol and it is a key in the mash, then the default value will
8686
# be set to the value matching the key.
8787
def default(key = nil)
@@ -130,14 +130,14 @@ def key?(key)
130130
alias_method :member?, :key?
131131

132132
# @param key<Object> The key to fetch. This will be run through convert_key.
133-
# @param *extras<Array> Default value.
133+
# @param extras<Array> Default value.
134134
#
135135
# @return [Object] The value at key or the default value.
136136
def fetch(key, *extras)
137137
super(convert_key(key), *extras)
138138
end
139139

140-
# @param *indices<Array>
140+
# @param indices<Array>
141141
# The keys to retrieve values for. These will be run through +convert_key+.
142142
#
143143
# @return [Array] The values at each of the provided keys
@@ -158,8 +158,6 @@ def delete(key)
158158
super(convert_key(key))
159159
end
160160

161-
# @param *rejected<Array[(String, Symbol)] The mash keys to exclude.
162-
#
163161
# @return [Mash] A new mash without the selected keys.
164162
#
165163
# @example
@@ -197,10 +195,6 @@ def self.from_hash(hash)
197195
protected
198196
# @param key<Object> The key to convert.
199197
#
200-
# @param [Object]
201-
# The converted key. If the key was a symbol, it will be converted to a
202-
# string.
203-
#
204198
# @api private
205199
def convert_key(key)
206200
key.kind_of?(Symbol) ? key.to_s : key

lib/spice/environment.rb

+6-6
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ class Environment < Base
55
attr_reader :name, :description, :attributes, :cookbook_versions,
66
:chef_type, :json_class
77

8-
def json_class
9-
@json_class ||= "Chef::Environment"
8+
def initialize(attrs=Mash.new)
9+
super
10+
@attrs['json_class'] ||= "Chef::Environment"
11+
@attrs['chef_type'] ||= "environment"
12+
@attrs['attributes'] ||= Mash.new
13+
@attrs['cookbook_version'] ||= Mash.new
1014
end
1115

12-
def chef_type
13-
@chef_type ||= 'environment'
14-
end
15-
1616
end
1717
end

lib/spice/mock.rb

-45
This file was deleted.

lib/spice/persistence.rb

-62
This file was deleted.

0 commit comments

Comments
 (0)