ridley 0.11.0.rc1 → 0.11.1

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.
Files changed (42) hide show
  1. data/.travis.yml +3 -2
  2. data/Gemfile +1 -0
  3. data/Guardfile +2 -2
  4. data/Thorfile +2 -2
  5. data/lib/ridley/chef.rb +1 -0
  6. data/lib/ridley/chef/chefignore.rb +76 -0
  7. data/lib/ridley/chef/cookbook.rb +17 -7
  8. data/lib/ridley/chef/cookbook/metadata.rb +8 -0
  9. data/lib/ridley/chef_objects/cookbook_object.rb +21 -37
  10. data/lib/ridley/chef_objects/data_bag_item_obect.rb +9 -0
  11. data/lib/ridley/client.rb +2 -2
  12. data/lib/ridley/connection.rb +12 -6
  13. data/lib/ridley/errors.rb +14 -0
  14. data/lib/ridley/host_connector.rb +10 -3
  15. data/lib/ridley/resource.rb +25 -5
  16. data/lib/ridley/resources/cookbook_resource.rb +19 -9
  17. data/lib/ridley/resources/data_bag_item_resource.rb +8 -4
  18. data/lib/ridley/resources/search_resource.rb +5 -5
  19. data/lib/ridley/sandbox_uploader.rb +6 -0
  20. data/lib/ridley/version.rb +1 -1
  21. data/ridley.gemspec +1 -1
  22. data/spec/acceptance/client_resource_spec.rb +44 -62
  23. data/spec/acceptance/cookbook_resource_spec.rb +27 -0
  24. data/spec/acceptance/data_bag_item_resource_spec.rb +36 -54
  25. data/spec/acceptance/data_bag_resource_spec.rb +9 -21
  26. data/spec/acceptance/environment_resource_spec.rb +34 -63
  27. data/spec/acceptance/node_resource_spec.rb +27 -47
  28. data/spec/acceptance/role_resource_spec.rb +27 -67
  29. data/spec/acceptance/sandbox_resource_spec.rb +3 -13
  30. data/spec/acceptance/search_resource_spec.rb +5 -15
  31. data/spec/fixtures/chefignore +8 -0
  32. data/spec/spec_helper.rb +15 -1
  33. data/spec/support/chef_server.rb +77 -0
  34. data/spec/unit/ridley/chef/chefignore_spec.rb +40 -0
  35. data/spec/unit/ridley/chef/cookbook_spec.rb +30 -2
  36. data/spec/unit/ridley/chef_objects/cookbook_object_spec.rb +3 -3
  37. data/spec/unit/ridley/connection_spec.rb +1 -2
  38. data/spec/unit/ridley/resources/cookbook_resource_spec.rb +85 -48
  39. data/spec/unit/ridley/resources/data_bag_resource_spec.rb +1 -1
  40. data/spec/unit/ridley/resources/search_resource_spec.rb +39 -2
  41. data/spec/unit/ridley/sandbox_uploader_spec.rb +25 -0
  42. metadata +19 -7
@@ -1,20 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "Sandbox API operations", type: "acceptance" do
4
- let(:server_url) { "https://api.opscode.com/organizations/ridley" }
4
+ let(:server_url) { Ridley::RSpec::ChefServer.server_url }
5
5
  let(:client_name) { "reset" }
6
- let(:client_key) { "/Users/reset/.chef/reset.pem" }
7
-
8
- let(:connection) do
9
- Ridley.new(
10
- server_url: server_url,
11
- client_name: client_name,
12
- client_key: client_key
13
- )
14
- end
15
-
16
- before(:all) { WebMock.allow_net_connect! }
17
- after(:all) { WebMock.disable_net_connect! }
6
+ let(:client_key) { fixtures_path.join('reset.pem').to_s }
7
+ let(:connection) { Ridley.new(server_url: server_url, client_name: client_name, client_key: client_key) }
18
8
 
19
9
  let(:checksums) do
20
10
  [
@@ -1,24 +1,14 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "Search API operations", type: "acceptance" do
4
- let(:server_url) { "https://api.opscode.com/organizations/ridley" }
4
+ let(:server_url) { Ridley::RSpec::ChefServer.server_url }
5
5
  let(:client_name) { "reset" }
6
- let(:client_key) { "/Users/reset/.chef/reset.pem" }
7
-
8
- let(:client) do
9
- Ridley.new(
10
- server_url: server_url,
11
- client_name: client_name,
12
- client_key: client_key
13
- )
14
- end
15
-
16
- before(:all) { WebMock.allow_net_connect! }
17
- after(:all) { WebMock.disable_net_connect! }
6
+ let(:client_key) { fixtures_path.join('reset.pem').to_s }
7
+ let(:connection) { Ridley.new(server_url: server_url, client_name: client_name, client_key: client_key) }
18
8
 
19
9
  describe "listing indexes" do
20
10
  it "returns an array of indexes" do
21
- indexes = client.search_indexes
11
+ indexes = connection.search_indexes
22
12
 
23
13
  indexes.should include("role")
24
14
  indexes.should include("node")
@@ -30,7 +20,7 @@ describe "Search API operations", type: "acceptance" do
30
20
  describe "searching an index that doesn't exist" do
31
21
  it "it raises a Ridley::Errors::HTTPNotFound error" do
32
22
  lambda {
33
- client.search(:notthere)
23
+ connection.search(:notthere)
34
24
  }.should raise_error(Ridley::Errors::HTTPNotFound)
35
25
  end
36
26
  end
@@ -0,0 +1,8 @@
1
+ #
2
+ # The ignore file allows you to skip files in cookbooks with the same name that appear
3
+ # later in the search path.
4
+ #
5
+
6
+ recipes/ignoreme.rb
7
+ # comments can be indented
8
+ ignored
data/spec/spec_helper.rb CHANGED
@@ -11,6 +11,7 @@ def setup_rspec
11
11
 
12
12
  RSpec.configure do |config|
13
13
  config.include Ridley::SpecHelpers
14
+ config.include Ridley::RSpec::ChefServer
14
15
  config.include JsonSpec::Helpers
15
16
 
16
17
  config.mock_with :rspec
@@ -19,12 +20,25 @@ def setup_rspec
19
20
  config.run_all_when_everything_filtered = true
20
21
 
21
22
  config.before(:all) do
22
- Ridley.logger = nil
23
23
  Celluloid.logger = nil
24
+ Ridley.logger = nil
25
+ WebMock.disable_net_connect!(allow_localhost: true, net_http_connect_on_start: true)
26
+ Ridley::RSpec::ChefServer.start
27
+ end
28
+
29
+ config.after(:all) do
30
+ Ridley::RSpec::ChefServer.stop
24
31
  end
25
32
 
26
33
  config.before(:each) do
34
+ Celluloid.shutdown
35
+ Celluloid.boot
27
36
  clean_tmp_path
37
+ Ridley::RSpec::ChefServer.server.clear_data
38
+ end
39
+
40
+ config.after(:each) do
41
+ Ridley::RSpec::ChefServer.server.clear_data
28
42
  end
29
43
  end
30
44
  end
@@ -0,0 +1,77 @@
1
+ require 'chef_zero/server'
2
+ require_relative 'spec_helpers'
3
+
4
+ module Ridley::RSpec
5
+ module ChefServer
6
+ PORT = 8889
7
+
8
+ class << self
9
+ include Ridley::SpecHelpers
10
+
11
+ def clear_request_log
12
+ @request_log = Array.new
13
+ end
14
+
15
+ def request_log
16
+ @request_log ||= Array.new
17
+ end
18
+
19
+ def server
20
+ @server ||= ChefZero::Server.new(port: PORT, signals: false, log_requests: true)
21
+ end
22
+
23
+ def server_url
24
+ "http://localhost:#{PORT}"
25
+ end
26
+
27
+ def start
28
+ Thin::Logging.silent = true
29
+ server.start_background
30
+ server.on_response do |request, response|
31
+ request_log << [ request, response ]
32
+ end
33
+ clear_request_log
34
+
35
+ server
36
+ end
37
+
38
+ def stop
39
+ @server.stop if @server
40
+ end
41
+
42
+ def running?
43
+ @server && @server.running?
44
+ end
45
+ end
46
+
47
+ def chef_client(name, hash = Hash.new)
48
+ load_data(:clients, name, hash)
49
+ end
50
+
51
+ def chef_cookbook(name, version, cookbook = Hash.new)
52
+ ChefServer.server.load_data("cookbooks" => { "#{name}-#{version}" => cookbook })
53
+ end
54
+
55
+ def chef_data_bag(name, hash = Hash.new)
56
+ ChefServer.server.load_data({ 'data' => { name => hash }})
57
+ end
58
+
59
+ def chef_environment(name, hash = Hash.new)
60
+ load_data(:environments, name, hash)
61
+ end
62
+
63
+ def chef_node(name, hash = Hash.new)
64
+ load_data(:nodes, name, hash)
65
+ end
66
+
67
+ def chef_role(name, hash = Hash.new)
68
+ load_data(:roles, name, hash)
69
+ end
70
+
71
+ private
72
+
73
+ def load_data(key, name, hash)
74
+ ChefServer.server.load_data(key.to_s => { name => MultiJson.encode(hash) })
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ridley::Chef::Chefignore do
4
+ describe "ClassMethods" do
5
+ subject { described_class }
6
+
7
+ describe "::find_relative_to" do
8
+ let(:path) { tmp_path.join('chefignore-test') }
9
+ before(:each) { FileUtils.mkdir_p(path) }
10
+
11
+ it "finds a chefignore file in a 'cookbooks' directory relative to the given path" do
12
+ FileUtils.touch(path.join('chefignore'))
13
+ subject.find_relative_to(path)
14
+ end
15
+
16
+ it "finds a chefignore file relative to the given path" do
17
+ FileUtils.mkdir_p(path.join('cookbooks'))
18
+ FileUtils.touch(path.join('cookbooks', 'chefignore'))
19
+ subject.find_relative_to(path)
20
+ end
21
+ end
22
+ end
23
+
24
+ subject { described_class.new(File.join(fixtures_path)) }
25
+
26
+ it "loads the globs in the chefignore file" do
27
+ subject.ignores.should =~ %w[recipes/ignoreme.rb ignored]
28
+ end
29
+
30
+ it "removes items from an array that match the ignores" do
31
+ file_list = %w[ recipes/ignoreme.rb recipes/dontignoreme.rb ]
32
+ subject.remove_ignores_from(file_list).should == %w[recipes/dontignoreme.rb]
33
+ end
34
+
35
+ it "determines if a file is ignored" do
36
+ subject.ignored?('ignored').should be_true
37
+ subject.ignored?('recipes/ignoreme.rb').should be_true
38
+ subject.ignored?('recipes/dontignoreme.rb').should be_false
39
+ end
40
+ end
@@ -4,7 +4,7 @@ describe Ridley::Chef::Cookbook do
4
4
  describe "ClassMethods" do
5
5
  subject { described_class }
6
6
 
7
- describe "#from_path" do
7
+ describe "::from_path" do
8
8
  let(:cookbook_path) { fixtures_path.join("example_cookbook") }
9
9
 
10
10
  it "returns an instance of Ridley::Chef::Cookbook" do
@@ -26,9 +26,37 @@ describe Ridley::Chef::Cookbook do
26
26
  }.should raise_error(IOError)
27
27
  end
28
28
  end
29
+
30
+ context "when the metadata does not contain a value for name and no value for :name option was given" do
31
+ let(:cookbook_path) { tmp_path.join("directory_name").to_s }
32
+
33
+ before do
34
+ FileUtils.mkdir_p(cookbook_path)
35
+ FileUtils.touch(File.join(cookbook_path, 'metadata.rb'))
36
+ end
37
+
38
+ it "sets the name of the cookbook to the name of the directory containing it" do
39
+ subject.from_path(cookbook_path).cookbook_name.should eql("directory_name")
40
+ end
41
+ end
42
+
43
+ context "when a metadata.rb is missing but metadata.json is present", focus: true do
44
+ let(:cookbook_path) { tmp_path.join("temp_cookbook").to_s }
45
+
46
+ before do
47
+ FileUtils.mkdir_p(cookbook_path)
48
+ File.open(File.join(cookbook_path, 'metadata.json'), 'w+') do |f|
49
+ f.write MultiJson.encode(name: "rspec_test")
50
+ end
51
+ end
52
+
53
+ it "sets the name of the cookbook from the metadata.json" do
54
+ subject.from_path(cookbook_path).cookbook_name.should eql("rspec_test")
55
+ end
56
+ end
29
57
  end
30
58
 
31
- describe "#checksum" do
59
+ describe "::checksum" do
32
60
  it "delegates to Ridley::Chef::Digester.md5_checksum_for_file" do
33
61
  path = fixtures_path.join("example_cookbook", "metadata.rb")
34
62
  Ridley::Chef::Digester.should_receive(:md5_checksum_for_file).with(path)
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Ridley::CookbookObject do
4
- let(:connection) { double('chef-connection') }
5
- subject { described_class.new(double('registry')) }
6
- before { subject.stub(connection: connection) }
4
+ let(:connection) { double('connection') }
5
+ let(:resource) { double('resource', connection: connection) }
6
+ subject { described_class.new(resource) }
7
7
 
8
8
  describe "#download" do
9
9
  it "downloads each file" do
@@ -56,8 +56,7 @@ describe Ridley::Connection do
56
56
  let(:contents) { "SOME STRING STUFF\nHERE.\n" }
57
57
 
58
58
  before(:each) do
59
- stub_request(:get, "http://test.it/file").
60
- to_return(status: 200, body: contents)
59
+ stub_request(:get, "http://test.it/file").to_return(status: 200, body: contents)
61
60
  end
62
61
 
63
62
  it "creates a destination file on disk" do
@@ -3,85 +3,122 @@ require 'spec_helper'
3
3
  describe Ridley::CookbookResource do
4
4
  let(:client_name) { "reset" }
5
5
  let(:client_key) { fixtures_path.join('reset.pem') }
6
- let(:connection) { double('connection') }
6
+ let(:connection) { Ridley::Connection.new("http://localhost:8889", "reset", fixtures_path.join("reset.pem").to_s) }
7
7
  subject { described_class.new(double('registry'), client_name, client_key) }
8
8
  before { subject.stub(connection: connection) }
9
9
 
10
10
  describe "#download" do
11
- pending
11
+ let(:name) { "example_cookbook" }
12
+ let(:version) { "0.1.0" }
13
+ let(:destination) { tmp_path.join("example_cookbook-0.1.0").to_s }
14
+
15
+ context "when the cookbook of the name/version is found" do
16
+ it "downloads the cookbook to the destination" do
17
+ pending "can't test downloading until https://github.com/jkeiser/chef-zero/issues/5 is fixed"
18
+ end
19
+ end
20
+
21
+ context "when the cookbook of the name/version is not found" do
22
+ before { subject.should_receive(:find).with(name, version).and_return(nil) }
23
+
24
+ it "raises a ResourceNotFound error" do
25
+ expect {
26
+ subject.download(name, version, destination)
27
+ }.to raise_error(Ridley::Errors::ResourceNotFound)
28
+ end
29
+ end
12
30
  end
13
31
 
14
32
  describe "#latest_version" do
15
33
  let(:name) { "ant" }
16
34
 
17
- before(:each) do
18
- subject.should_receive(:versions).with(name).and_return(versions)
19
- end
20
-
21
35
  context "when the cookbook has no versions" do
22
- let(:versions) { Array.new }
23
-
24
- it "returns nil" do
25
- subject.latest_version(name).should be_nil
36
+ it "returns a ResourceNotFound error" do
37
+ expect {
38
+ subject.latest_version(name)
39
+ }.to raise_error(Ridley::Errors::ResourceNotFound)
26
40
  end
27
41
  end
28
42
 
29
43
  context "when the cookbook has versions" do
30
- let(:versions) do
31
- [ "1.0.0", "1.2.0", "3.0.0", "1.4.1" ]
44
+ before do
45
+ chef_cookbook(name, "1.0.0")
46
+ chef_cookbook(name, "1.2.0")
47
+ chef_cookbook(name, "3.0.0")
32
48
  end
33
49
 
34
- it "returns nil" do
50
+ it "returns the latest version" do
35
51
  subject.latest_version(name).should eql("3.0.0")
36
52
  end
37
53
  end
38
54
  end
39
55
 
40
56
  describe "#versions" do
41
- let(:cookbook) { "artifact" }
42
- let(:versions_path) { "#{described_class.resource_path}/#{cookbook}" }
43
- let(:response) do
44
- double(body: {
45
- cookbook => {
46
- "versions" => [
47
- {
48
- "url" => "https://api.opscode.com/organizations/ridley/cookbooks/artifact/1.0.0",
49
- "version" => "1.0.0"
50
- },
51
- {
52
- "url" => "https://api.opscode.com/organizations/ridley/cookbooks/artifact/1.1.0",
53
- "version" => "1.1.0"
54
- },
55
- {
56
- "url" => "https://api.opscode.com/organizations/ridley/cookbooks/artifact/1.2.0",
57
- "version" => "1.2.0"
58
- }
59
- ],
60
- "url" => "https://api.opscode.com/organizations/ridley/cookbooks/artifact"
61
- }
62
- })
57
+ let(:name) { "artifact" }
58
+
59
+ context "when the cookbook has versions" do
60
+ before do
61
+ chef_cookbook(name, "1.0.0")
62
+ chef_cookbook(name, "1.1.0")
63
+ chef_cookbook(name, "1.2.0")
64
+ end
65
+
66
+ it "returns an array" do
67
+ subject.versions(name).should be_a(Array)
68
+ end
69
+
70
+ it "contains a version string for each cookbook version available" do
71
+ result = subject.versions(name)
72
+
73
+ result.should have(3).versions
74
+ result.should include("1.0.0")
75
+ result.should include("1.1.0")
76
+ result.should include("1.2.0")
77
+ end
63
78
  end
64
79
 
65
- before(:each) do
66
- connection.should_receive(:get).with(versions_path).and_return(response)
80
+ context "when the cookbook has no versions" do
81
+ it "raises a ResourceNotFound error" do
82
+ expect {
83
+ subject.versions(name)
84
+ }.to raise_error(Ridley::Errors::ResourceNotFound)
85
+ end
67
86
  end
87
+ end
68
88
 
69
- it "returns an array" do
70
- subject.versions(cookbook).should be_a(Array)
89
+ describe "#satisfy" do
90
+ let(:name) { "ridley_test" }
91
+
92
+ context "when there is a solution" do
93
+ before do
94
+ chef_cookbook(name, "2.0.0")
95
+ chef_cookbook(name, "3.0.0")
96
+ end
97
+
98
+ it "returns a CookbookObject" do
99
+ subject.satisfy(name, ">= 2.0.0").should be_a(Ridley::CookbookObject)
100
+ end
101
+
102
+ it "is the best solution" do
103
+ subject.satisfy(name, ">= 2.0.0").version.should eql("3.0.0")
104
+ end
71
105
  end
72
106
 
73
- it "contains a version string for each cookbook version available" do
74
- result = subject.versions(cookbook)
107
+ context "when there is no solution" do
108
+ before { chef_cookbook(name, "1.0.0") }
75
109
 
76
- result.should have(3).versions
77
- result.should include("1.0.0")
78
- result.should include("1.1.0")
79
- result.should include("1.2.0")
110
+ it "returns nil" do
111
+ subject.satisfy(name, ">= 2.0.0").should be_nil
112
+ end
80
113
  end
81
- end
82
114
 
83
- describe "#satisfy" do
84
- pending
115
+ context "when the cookbook does not exist" do
116
+ it "raises a ResourceNotFound error" do
117
+ expect {
118
+ subject.satisfy(name, ">= 1.2.3")
119
+ }.to raise_error(Ridley::Errors::ResourceNotFound)
120
+ end
121
+ end
85
122
  end
86
123
 
87
124
  describe "#upload" do