ridley 0.0.2 → 0.0.3

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/Guardfile CHANGED
@@ -1,3 +1,6 @@
1
+ notification :off
2
+ interactor :coolline
3
+
1
4
  guard 'spork' do
2
5
  watch('Gemfile')
3
6
  watch('spec/spec_helper.rb') { :rspec }
@@ -10,7 +13,7 @@ guard 'yard', stdout: '/dev/null', stderr: '/dev/null' do
10
13
  watch(%r{ext/.+\.c})
11
14
  end
12
15
 
13
- guard 'rspec', version: 2, cli: "--color --drb --format Fuubar", all_on_start: false, all_after_pass: false, notification: false do
16
+ guard 'rspec', version: 2, cli: "--color --drb --format Fuubar", all_on_start: false, all_after_pass: false do
14
17
  watch(%r{^spec/unit/.+_spec\.rb$})
15
18
  watch(%r{^spec/acceptance/.+_spec\.rb$})
16
19
 
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # Ridley
2
2
  [![Build Status](https://secure.travis-ci.org/reset/ridley.png?branch=master)](http://travis-ci.org/reset/ridley)
3
+ [![Dependency Status](https://gemnasium.com/reset/ridley.png?travis)](https://gemnasium.com/reset/ridley)
3
4
  [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/reset/ridley)
4
5
 
5
6
  A reliable Chef API client with a clean syntax
data/Thorfile CHANGED
@@ -11,17 +11,17 @@ class Default < Thor
11
11
  include Thor::RakeCompat
12
12
  Bundler::GemHelper.install_tasks
13
13
 
14
- desc "build", "Build berkshelf-#{Ridley::VERSION}.gem into the pkg directory"
14
+ desc "build", "Build ridley-#{Ridley::VERSION}.gem into the pkg directory"
15
15
  def build
16
16
  Rake::Task["build"].execute
17
17
  end
18
18
 
19
- desc "install", "Build and install berkshelf-#{Ridley::VERSION}.gem into system gems"
19
+ desc "install", "Build and install ridley-#{Ridley::VERSION}.gem into system gems"
20
20
  def install
21
21
  Rake::Task["install"].execute
22
22
  end
23
23
 
24
- desc "release", "Create tag v#{Ridley::VERSION} and build and push berkshelf-#{Ridley::VERSION}.gem to Rubygems"
24
+ desc "release", "Create tag v#{Ridley::VERSION} and build and push ridley-#{Ridley::VERSION}.gem to Rubygems"
25
25
  def release
26
26
  Rake::Task["release"].execute
27
27
  end
data/lib/ridley.rb CHANGED
@@ -9,6 +9,7 @@ require 'forwardable'
9
9
  require 'set'
10
10
  require 'thread'
11
11
 
12
+ require 'ridley/version'
12
13
  require 'ridley/errors'
13
14
 
14
15
  # @author Jamie Winsor <jamie@vialstudios.com>
@@ -5,6 +5,18 @@ module Ridley
5
5
  def sync(options, &block)
6
6
  new(options).sync(&block)
7
7
  end
8
+
9
+ # @raise [ArgumentError]
10
+ #
11
+ # @return [Boolean]
12
+ def validate_options(options)
13
+ missing = (REQUIRED_OPTIONS - options.keys)
14
+
15
+ unless missing.empty?
16
+ missing.collect! { |opt| "'#{opt}'" }
17
+ raise ArgumentError, "Missing required option(s): #{missing.join(', ')}"
18
+ end
19
+ end
8
20
  end
9
21
 
10
22
  extend Forwardable
@@ -39,8 +51,15 @@ module Ridley
39
51
  DEFAULT_THREAD_COUNT = 8
40
52
 
41
53
  # @option options [String] :server_url
54
+ # URL to the Chef API
42
55
  # @option options [String] :client_name
56
+ # name of the client used to authenticate with the Chef API
43
57
  # @option options [String] :client_key
58
+ # filepath to the client's private key used to authenticate with
59
+ # the Chef API
60
+ # @option options [String] :organization
61
+ # the Organization to connect to. This is only used if you are connecting to
62
+ # private Chef or hosted Chef
44
63
  # @option options [Integer] :thread_count
45
64
  # @option options [Hash] :params
46
65
  # URI query unencoded key/value pairs
@@ -53,14 +72,12 @@ module Ridley
53
72
  # @option options [URI, String, Hash] :proxy
54
73
  # URI, String, or Hash of HTTP proxy options
55
74
  def initialize(options = {})
56
- options[:thread_count] ||= DEFAULT_THREAD_COUNT
57
-
58
- validate_options(options)
75
+ self.class.validate_options(options)
59
76
 
60
- @client_name = options[:client_name]
61
- @client_key = options[:client_key]
62
- @organization = options[:organization]
63
- @thread_count = options[:thread_count]
77
+ @client_name = options.fetch(:client_name)
78
+ @client_key = options.fetch(:client_key)
79
+ @organization = options.fetch(:organization, nil)
80
+ @thread_count = options.fetch(:thread_count, DEFAULT_THREAD_COUNT)
64
81
 
65
82
  faraday_options = options.slice(:params, :headers, :request, :ssl, :proxy)
66
83
  uri_hash = Addressable::URI.parse(options[:server_url]).to_hash.slice(:scheme, :host, :port)
@@ -69,7 +86,7 @@ module Ridley
69
86
  uri_hash[:port] = (uri_hash[:scheme] == "https" ? 443 : 80)
70
87
  end
71
88
 
72
- if organization
89
+ unless organization.nil?
73
90
  uri_hash[:path] = "/organizations/#{organization}"
74
91
  end
75
92
 
@@ -119,13 +136,5 @@ module Ridley
119
136
  def method_missing(method, *args, &block)
120
137
  @self_before_instance_eval.send(method, *args, &block)
121
138
  end
122
-
123
- def validate_options(options)
124
- missing = REQUIRED_OPTIONS - options.keys
125
- unless missing.empty?
126
- missing.collect! { |opt| "'#{opt}'" }
127
- raise ArgumentError, "missing required option(s): #{missing.join(', ')}"
128
- end
129
- end
130
139
  end
131
140
  end
data/lib/ridley/errors.rb CHANGED
@@ -47,7 +47,7 @@ module Ridley
47
47
 
48
48
  def initialize(env)
49
49
  @env = env
50
- @errors = Array(env[:body][:error]) || []
50
+ @errors = env[:body].is_a?(Hash) ? Array(env[:body][:error]) : []
51
51
 
52
52
  if errors.empty?
53
53
  @message = env[:body] || "no content body"
@@ -23,7 +23,7 @@ module Ridley
23
23
  user_id: client_name
24
24
  )
25
25
  authentication_headers = sign_obj.sign(client_key)
26
- env[:request_headers] = env[:request_headers].merge(authentication_headers).merge(default_headers)
26
+ env[:request_headers] = default_headers.merge(env[:request_headers]).merge(authentication_headers)
27
27
  env[:request_headers] = env[:request_headers].merge('Content-Length' => env[:body].bytesize.to_s) if env[:body]
28
28
 
29
29
  Ridley.log.debug(env)
@@ -24,7 +24,7 @@ module Ridley
24
24
  #
25
25
  # @return [Hash]
26
26
  def parse(body)
27
- MultiJson.load(body, symbolize_keys: true)
27
+ MultiJson.decode(body, symbolize_keys: true)
28
28
  end
29
29
 
30
30
  # Extracts the type of the response from the response headers
@@ -255,7 +255,7 @@ module Ridley
255
255
  #
256
256
  # @return [Object]
257
257
  def from_json(json, options = {})
258
- self.attributes = MultiJson.load(json, options)
258
+ self.attributes = MultiJson.decode(json, options)
259
259
  self
260
260
  end
261
261
 
@@ -272,7 +272,7 @@ module Ridley
272
272
  #
273
273
  # @return [String]
274
274
  def to_json(options = {})
275
- MultiJson.dump(self.attributes, options)
275
+ MultiJson.encode(self.attributes, options)
276
276
  end
277
277
  alias_method :as_json, :to_json
278
278
 
@@ -3,6 +3,32 @@ module Ridley
3
3
  class Cookbook
4
4
  include Ridley::Resource
5
5
 
6
+ class << self
7
+ # Save a new Cookbook Version of the given name, version with the
8
+ # given manifest of files and checksums.
9
+ #
10
+ # @param [Ridley::Connection] connection
11
+ # @param [String] name
12
+ # @param [String] version
13
+ # @param [String] manifest
14
+ # a JSON blob containing file names, file paths, and checksums for each
15
+ # that describe the cookbook version being uploaded.
16
+ #
17
+ # @option options [Boolean] :freeze
18
+ # @option options [Boolean] :force
19
+ #
20
+ # @return [Hash]
21
+ def save(connection, name, version, manifest, options = {})
22
+ freeze = options.fetch(:freeze, false)
23
+ force = options.fetch(:force, false)
24
+
25
+ url = "cookbooks/#{name}/#{version}"
26
+ url << "?force=true" if force
27
+
28
+ connection.put(url, manifest)
29
+ end
30
+ end
31
+
6
32
  set_chef_id "name"
7
33
  set_chef_type "cookbook"
8
34
  set_chef_json_class "Chef::Cookbook"
@@ -167,7 +167,7 @@ module Ridley
167
167
  #
168
168
  # @return [String]
169
169
  def to_json(options = {})
170
- MultiJson.dump(self.attributes, options)
170
+ MultiJson.encode(self.attributes, options)
171
171
  end
172
172
  alias_method :as_json, :to_json
173
173
 
@@ -0,0 +1,106 @@
1
+ module Ridley
2
+ class Sandbox
3
+ class << self
4
+ # @param [Ridley::Connection] connection
5
+ # @param [Array] checksums
6
+ #
7
+ # @return [Ridley::Sandbox]
8
+ def create(connection, checksums = [])
9
+ sumhash = { checksums: Hash.new }.tap do |chks|
10
+ Array(checksums).each { |chk| chks[:checksums][chk] = nil }
11
+ end
12
+
13
+ attrs = connection.post("sandboxes", sumhash.to_json).body
14
+ new(connection, attrs[:sandbox_id], attrs[:checksums])
15
+ end
16
+
17
+ # Checksum the file at the given filepath for a Chef API.
18
+ #
19
+ # @param [String] path
20
+ #
21
+ # @return [String]
22
+ def checksum(path)
23
+ File.open(path, 'rb') { |f| checksum_io(f, Digest::MD5.new) }
24
+ end
25
+
26
+ # Checksum and encode the file at the given filepath for uploading
27
+ #
28
+ # @param [String] path
29
+ #
30
+ # @return [String]
31
+ # a base64 encoded checksum
32
+ def checksum64(path)
33
+ Base64.encode64([checksum(path)].pack("H*")).strip
34
+ end
35
+
36
+ # @param [String] io
37
+ # @param [Object] digest
38
+ #
39
+ # @return [String]
40
+ def checksum_io(io, digest)
41
+ while chunk = io.read(1024 * 8)
42
+ digest.update(chunk)
43
+ end
44
+ digest.hexdigest
45
+ end
46
+ end
47
+
48
+ attr_reader :sandbox_id
49
+ attr_reader :checksums
50
+
51
+ def initialize(connection, id, checksums)
52
+ @connection = connection
53
+ @sandbox_id = id
54
+ @checksums = checksums
55
+ end
56
+
57
+ def checksum(chk_id)
58
+ checksums.fetch(chk_id.to_sym)
59
+ end
60
+
61
+ # @param [String] chk_id
62
+ # @param [String] path
63
+ #
64
+ # @return [Hash, nil]
65
+ def upload(chk_id, path)
66
+ checksum = self.checksum(chk_id)
67
+
68
+ unless checksum[:needs_upload]
69
+ return nil
70
+ end
71
+
72
+ headers = {
73
+ 'Content-Type' => 'application/x-binary',
74
+ 'content-md5' => self.class.checksum64(path)
75
+ }
76
+ contents = File.open(path, 'rb') { |f| f.read }
77
+
78
+ Faraday.put(checksum[:url], contents, headers)
79
+ end
80
+
81
+ def commit
82
+ connection.put("sandboxes/#{sandbox_id}", { is_completed: true }.to_json).body
83
+ end
84
+
85
+ def to_s
86
+ "#{sandbox_id}: #{checksums}"
87
+ end
88
+
89
+ private
90
+
91
+ attr_reader :connection
92
+ end
93
+
94
+ module DSL
95
+ # Coerces instance functions into class functions on Ridley::Sandbox. This coercion
96
+ # sends an instance of the including class along to the class function.
97
+ #
98
+ # @see Ridley::Context
99
+ #
100
+ # @return [Ridley::Context]
101
+ # a context object to delegate instance functions to class functions on Ridley::Sandbox
102
+ def sandbox
103
+ Context.new(Ridley::Sandbox, self)
104
+ end
105
+ end
106
+ end
@@ -1,3 +1,3 @@
1
1
  module Ridley
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
data/ridley.gemspec CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
21
21
  s.add_runtime_dependency 'mixlib-authentication'
22
22
  s.add_runtime_dependency 'addressable'
23
23
  s.add_runtime_dependency 'faraday'
24
- s.add_runtime_dependency 'multi_json'
24
+ s.add_runtime_dependency 'multi_json', '>= 1.0.4'
25
25
  s.add_runtime_dependency 'activemodel'
26
26
 
27
27
  s.add_development_dependency 'rake'
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Sandbox API operations", type: "acceptance" do
4
+ let(:server_url) { "https://api.opscode.com" }
5
+ let(:client_name) { "reset" }
6
+ let(:client_key) { "/Users/reset/.chef/reset.pem" }
7
+ let(:organization) { "ridley" }
8
+
9
+ let(:connection) do
10
+ Ridley.connection(
11
+ server_url: server_url,
12
+ client_name: client_name,
13
+ client_key: client_key,
14
+ organization: organization
15
+ )
16
+ end
17
+
18
+ before(:all) { WebMock.allow_net_connect! }
19
+ after(:all) { WebMock.disable_net_connect! }
20
+
21
+ let(:checksums) do
22
+ [
23
+ Ridley::Sandbox.checksum(fixtures_path.join("recipe_one.rb")),
24
+ Ridley::Sandbox.checksum(fixtures_path.join("recipe_two.rb"))
25
+ ]
26
+ end
27
+
28
+ describe "creating a new sandbox" do
29
+ it "returns an instance of Ridley::Sandbox" do
30
+ connection.sandbox.create(checksums).should be_a(Ridley::Sandbox)
31
+ end
32
+
33
+ it "contains a value for sandbox_id" do
34
+ connection.sandbox.create(checksums).sandbox_id.should_not be_nil
35
+ end
36
+
37
+ it "returns an instance with the same amount of checksums given to create" do
38
+ connection.sandbox.create(checksums).checksums.should have(2).items
39
+ end
40
+ end
41
+ end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "Role API operations", type: "acceptance" do
3
+ describe "Search API operations", type: "acceptance" do
4
4
  let(:server_url) { "https://api.opscode.com" }
5
5
  let(:client_name) { "reset" }
6
6
  let(:client_key) { "/Users/reset/.chef/reset.pem" }
@@ -0,0 +1 @@
1
+ testfile
@@ -0,0 +1 @@
1
+ testfile two
@@ -208,13 +208,13 @@ shared_examples_for "a Ridley Resource" do |resource_klass|
208
208
 
209
209
  describe "#to_json" do
210
210
  it "serializes the objects attributes using MultiJson" do
211
- MultiJson.should_receive(:dump).with(subject.attributes, kind_of(Hash))
211
+ MultiJson.should_receive(:encode).with(subject.attributes, kind_of(Hash))
212
212
 
213
213
  subject.to_json
214
214
  end
215
215
 
216
216
  it "returns the seralized value" do
217
- MultiJson.stub(:dump).and_return("{}")
217
+ MultiJson.stub(:encode).and_return("{}")
218
218
 
219
219
  subject.to_json.should eql("{}")
220
220
  end
@@ -68,7 +68,7 @@ describe Ridley::Connection do
68
68
  client_name: client_name,
69
69
  client_key: client_key
70
70
  )
71
- }.should raise_error(ArgumentError, "missing required option(s): 'server_url'")
71
+ }.should raise_error(ArgumentError, "Missing required option(s): 'server_url'")
72
72
  end
73
73
 
74
74
  it "raises if a value for client_name is not given" do
@@ -77,7 +77,7 @@ describe Ridley::Connection do
77
77
  server_url: server_url,
78
78
  client_key: client_key
79
79
  )
80
- }.should raise_error(ArgumentError, "missing required option(s): 'client_name'")
80
+ }.should raise_error(ArgumentError, "Missing required option(s): 'client_name'")
81
81
  end
82
82
 
83
83
  it "raises if a value for client_key is not given" do
@@ -86,7 +86,7 @@ describe Ridley::Connection do
86
86
  server_url: server_url,
87
87
  client_name: client_name
88
88
  )
89
- }.should raise_error(ArgumentError, "missing required option(s): 'client_key'")
89
+ }.should raise_error(ArgumentError, "Missing required option(s): 'client_key'")
90
90
  end
91
91
  end
92
92
 
@@ -30,5 +30,13 @@ describe Ridley::Errors do
30
30
  end
31
31
  end
32
32
  end
33
+
34
+ context "with an HTML error payload" do
35
+ subject { Ridley::Errors::HTTPError.new(:body => "<html><body><h1>Redirected</h1></body></html>") }
36
+
37
+ it "has an HTML body" do
38
+ subject.message.should eq("<html><body><h1>Redirected</h1></body></html>")
39
+ end
40
+ end
33
41
  end
34
42
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ridley
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
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: 2012-08-22 00:00:00.000000000 Z
12
+ date: 2012-09-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: yajl-ruby
@@ -98,7 +98,7 @@ dependencies:
98
98
  requirements:
99
99
  - - ! '>='
100
100
  - !ruby/object:Gem::Version
101
- version: '0'
101
+ version: 1.0.4
102
102
  type: :runtime
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
@@ -106,7 +106,7 @@ dependencies:
106
106
  requirements:
107
107
  - - ! '>='
108
108
  - !ruby/object:Gem::Version
109
- version: '0'
109
+ version: 1.0.4
110
110
  - !ruby/object:Gem::Dependency
111
111
  name: activemodel
112
112
  requirement: !ruby/object:Gem::Requirement
@@ -363,6 +363,7 @@ files:
363
363
  - lib/ridley/resources/environment.rb
364
364
  - lib/ridley/resources/node.rb
365
365
  - lib/ridley/resources/role.rb
366
+ - lib/ridley/resources/sandbox.rb
366
367
  - lib/ridley/resources/search.rb
367
368
  - lib/ridley/version.rb
368
369
  - ridley.gemspec
@@ -373,7 +374,10 @@ files:
373
374
  - spec/acceptance/environment_resource_spec.rb
374
375
  - spec/acceptance/node_resource_spec.rb
375
376
  - spec/acceptance/role_resource_spec.rb
377
+ - spec/acceptance/sandbox_resource_spec.rb
376
378
  - spec/acceptance/search_resource_spec.rb
379
+ - spec/fixtures/recipe_one.rb
380
+ - spec/fixtures/recipe_two.rb
377
381
  - spec/fixtures/reset.pem
378
382
  - spec/spec_helper.rb
379
383
  - spec/support/each_matcher.rb
@@ -414,7 +418,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
414
418
  version: '0'
415
419
  segments:
416
420
  - 0
417
- hash: -2920625488512692680
421
+ hash: -1393828720209258724
418
422
  requirements: []
419
423
  rubyforge_project:
420
424
  rubygems_version: 1.8.23
@@ -429,7 +433,10 @@ test_files:
429
433
  - spec/acceptance/environment_resource_spec.rb
430
434
  - spec/acceptance/node_resource_spec.rb
431
435
  - spec/acceptance/role_resource_spec.rb
436
+ - spec/acceptance/sandbox_resource_spec.rb
432
437
  - spec/acceptance/search_resource_spec.rb
438
+ - spec/fixtures/recipe_one.rb
439
+ - spec/fixtures/recipe_two.rb
433
440
  - spec/fixtures/reset.pem
434
441
  - spec/spec_helper.rb
435
442
  - spec/support/each_matcher.rb