ridley 0.11.0.rc1 → 0.11.1

Sign up to get free protection for your applications and to get access to all the features.
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