berkshelf 1.4.6 → 2.0.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/CHANGELOG.md +1 -5
- data/CONTRIBUTING.md +3 -1
- data/Gemfile +11 -1
- data/README.md +16 -0
- data/Thorfile +3 -1
- data/berkshelf.gemspec +26 -38
- data/features/apply_command.feature +32 -0
- data/features/configure_command.feature +31 -0
- data/features/contingent_command.feature +5 -5
- data/features/default_locations.feature +2 -2
- data/features/groups_install.feature +19 -20
- data/features/info_command.feature +13 -13
- data/features/install_command.feature +86 -83
- data/features/json_formatter.feature +60 -23
- data/features/list_command.feature +5 -11
- data/features/lockfile.feature +286 -6
- data/features/open_command.feature +8 -4
- data/features/outdated_command.feature +8 -15
- data/features/package_command.feature +39 -0
- data/features/show_command.feature +8 -9
- data/features/step_definitions/chef_server_steps.rb +20 -2
- data/features/step_definitions/cli_steps.rb +10 -2
- data/features/step_definitions/configure_cli_steps.rb +7 -0
- data/features/step_definitions/filesystem_steps.rb +19 -14
- data/features/step_definitions/json_steps.rb +22 -5
- data/features/step_definitions/utility_steps.rb +13 -1
- data/features/support/env.rb +10 -23
- data/features/update_command.feature +105 -24
- data/features/upload_command.feature +0 -14
- data/features/vendor_install.feature +3 -3
- data/generator_files/Vagrantfile.erb +11 -11
- data/lib/berkshelf.rb +6 -5
- data/lib/berkshelf/berksfile.rb +267 -99
- data/lib/berkshelf/cli.rb +70 -34
- data/lib/berkshelf/cli_commands/test_command.rb +11 -0
- data/lib/berkshelf/community_rest.rb +1 -1
- data/lib/berkshelf/config.rb +19 -2
- data/lib/berkshelf/cookbook_source.rb +41 -12
- data/lib/berkshelf/cookbook_store.rb +8 -4
- data/lib/berkshelf/errors.rb +61 -29
- data/lib/berkshelf/formatters.rb +13 -19
- data/lib/berkshelf/formatters/human_readable.rb +8 -0
- data/lib/berkshelf/formatters/json.rb +12 -1
- data/lib/berkshelf/formatters/null.rb +23 -0
- data/lib/berkshelf/init_generator.rb +22 -11
- data/lib/berkshelf/location.rb +8 -10
- data/lib/berkshelf/locations/chef_api_location.rb +4 -5
- data/lib/berkshelf/locations/git_location.rb +14 -12
- data/lib/berkshelf/locations/path_location.rb +16 -1
- data/lib/berkshelf/locations/site_location.rb +1 -3
- data/lib/berkshelf/lockfile.rb +230 -33
- data/lib/berkshelf/resolver.rb +2 -1
- data/lib/berkshelf/ui.rb +4 -8
- data/lib/berkshelf/version.rb +1 -1
- data/lib/thor/monkies/shell.rb +2 -5
- data/spec/fixtures/cassettes/Berkshelf_Resolver/{ClassMethods/_initialize → _initialize}/adds_the_dependencies_of_the_source_as_sources.yml +0 -0
- data/spec/fixtures/cookbooks/example_cookbook/.gitignore +2 -0
- data/spec/fixtures/cookbooks/example_cookbook/.kitchen.yml +26 -0
- data/spec/fixtures/cookbooks/example_cookbook/Berksfile.lock +5 -0
- data/spec/fixtures/lockfiles/default.lock +11 -0
- data/spec/{config/knife.rb → knife.rb.sample} +2 -2
- data/spec/spec_helper.rb +15 -3
- data/spec/support/chef_api.rb +19 -5
- data/spec/support/chef_server.rb +4 -3
- data/spec/support/knife.rb +18 -0
- data/spec/unit/berkshelf/berksfile_spec.rb +332 -235
- data/spec/unit/berkshelf/cached_cookbook_spec.rb +40 -42
- data/spec/unit/berkshelf/chef/cookbook/chefignore_spec.rb +11 -15
- data/spec/unit/berkshelf/community_rest_spec.rb +16 -14
- data/spec/unit/berkshelf/config_spec.rb +36 -20
- data/spec/unit/berkshelf/cookbook_generator_spec.rb +6 -10
- data/spec/unit/berkshelf/cookbook_source_spec.rb +244 -183
- data/spec/unit/berkshelf/cookbook_store_spec.rb +72 -76
- data/spec/unit/berkshelf/core_ext/file_utils_spec.rb +2 -2
- data/spec/unit/berkshelf/downloader_spec.rb +137 -157
- data/spec/unit/berkshelf/errors_spec.rb +1 -1
- data/spec/unit/berkshelf/formatters/null_spec.rb +17 -0
- data/spec/unit/berkshelf/formatters_spec.rb +83 -90
- data/spec/unit/berkshelf/git_spec.rb +219 -207
- data/spec/unit/berkshelf/init_generator_spec.rb +73 -73
- data/spec/unit/berkshelf/location_spec.rb +143 -162
- data/spec/unit/berkshelf/locations/chef_api_location_spec.rb +94 -89
- data/spec/unit/berkshelf/locations/git_location_spec.rb +75 -59
- data/spec/unit/berkshelf/locations/path_location_spec.rb +46 -30
- data/spec/unit/berkshelf/locations/site_location_spec.rb +4 -4
- data/spec/unit/berkshelf/lockfile_spec.rb +185 -1
- data/spec/unit/berkshelf/logger_spec.rb +6 -24
- data/spec/unit/berkshelf/mixin/logging_spec.rb +6 -8
- data/spec/unit/berkshelf/resolver_spec.rb +36 -38
- data/spec/unit/berkshelf/ui_spec.rb +9 -10
- data/spec/unit/berkshelf_spec.rb +41 -40
- data/spec/unit/chef/config_spec.rb +9 -11
- metadata +55 -203
- data/spec/config/berkshelf.pem +0 -27
- data/spec/config/validator.pem +0 -27
@@ -1,110 +1,106 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
describe
|
5
|
-
|
3
|
+
describe Berkshelf::CookbookStore do
|
4
|
+
describe '#initialize' do
|
5
|
+
it 'creates the storage_path' do
|
6
|
+
storage_path = tmp_path.join('random_storage')
|
7
|
+
Berkshelf::CookbookStore.new(storage_path)
|
6
8
|
|
7
|
-
|
8
|
-
it "creates the storage_path" do
|
9
|
-
storage_path = tmp_path.join("random_storage")
|
10
|
-
subject.class.new(storage_path)
|
11
|
-
|
12
|
-
storage_path.should exist
|
13
|
-
end
|
9
|
+
expect(storage_path).to exist
|
14
10
|
end
|
11
|
+
end
|
15
12
|
|
16
|
-
describe "#cookbook_path" do
|
17
|
-
let(:cookbook_name) { "nginx" }
|
18
|
-
let(:cookbook_version) { "0.101.2" }
|
19
13
|
|
20
|
-
before(:each) do
|
21
|
-
@cb_path = subject.cookbook_path(cookbook_name, cookbook_version)
|
22
|
-
end
|
23
14
|
|
24
|
-
|
25
|
-
@cb_path.should be_a(Pathname)
|
26
|
-
end
|
15
|
+
subject { Berkshelf::CookbookStore.new(tmp_path.join("cbstore_rspec")) }
|
27
16
|
|
28
|
-
|
29
|
-
|
30
|
-
|
17
|
+
describe '#cookbook_path' do
|
18
|
+
let(:cookbook_name) { 'nginx' }
|
19
|
+
let(:cookbook_version) { '0.101.2' }
|
20
|
+
let(:path) { subject.cookbook_path(cookbook_name, cookbook_version) }
|
31
21
|
|
32
|
-
|
33
|
-
|
34
|
-
end
|
22
|
+
it 'returns an instance of Pathname' do
|
23
|
+
expect(path).to be_a(Pathname)
|
35
24
|
end
|
36
25
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
let(:constraint) { Solve::Constraint.new("~> 0.101.2") }
|
41
|
-
let(:cached_cb) { double('cached-cb', name: name, version: Solve::Version.new(version)) }
|
42
|
-
let(:cached_two) { double('cached-two', name: "mysql", version: Solve::Version.new("1.2.6")) }
|
26
|
+
it 'returns a the filepath within the storage path' do
|
27
|
+
expect(path.dirname).to eq(subject.storage_path)
|
28
|
+
end
|
43
29
|
|
44
|
-
|
45
|
-
|
46
|
-
|
30
|
+
it 'returns a basename containing the cookbook name and version separated by a dash' do
|
31
|
+
expect(path.basename.to_s).to eq("#{cookbook_name}-#{cookbook_version}")
|
32
|
+
end
|
33
|
+
end
|
47
34
|
|
48
|
-
|
49
|
-
|
35
|
+
describe '#satisfy' do
|
36
|
+
let(:name) { 'nginx' }
|
37
|
+
let(:version) { '0.101.4' }
|
38
|
+
let(:constraint) { Solve::Constraint.new('~> 0.101.2') }
|
39
|
+
let(:cached_one) { double('cached-one', name: name, version: Solve::Version.new(version)) }
|
40
|
+
let(:cached_two) { double('cached-two', name: 'mysql', version: Solve::Version.new('1.2.6')) }
|
50
41
|
|
51
|
-
|
52
|
-
|
42
|
+
before { subject.stub(:cookbooks).and_return([cached_one, cached_two]) }
|
43
|
+
|
44
|
+
it 'gets and returns the the CachedCookbook best matching the name and constraint' do
|
45
|
+
subject.should_receive(:cookbook).with(name, version).and_return(cached_one)
|
46
|
+
result = subject.satisfy(name, constraint)
|
53
47
|
|
54
|
-
|
55
|
-
|
48
|
+
expect(result).to eq(cached_one)
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'when there are no cookbooks in the cookbook store' do
|
52
|
+
before { subject.stub(:cookbooks).and_return([]) }
|
56
53
|
|
57
|
-
|
58
|
-
|
59
|
-
|
54
|
+
it 'returns nil' do
|
55
|
+
result = subject.satisfy(name, constraint)
|
56
|
+
expect(result).to be_nil
|
60
57
|
end
|
58
|
+
end
|
61
59
|
|
62
|
-
|
63
|
-
|
64
|
-
|
60
|
+
context 'when there is no matching cookbook for the given name and constraint' do
|
61
|
+
let(:version) { Solve::Version.new('1.0.0') }
|
62
|
+
let(:constraint) { Solve::Constraint.new('= 0.1.0') }
|
65
63
|
|
66
|
-
|
67
|
-
subject.stub(:cookbooks).and_return([ double('badcache', name: 'none', version: version) ])
|
68
|
-
end
|
64
|
+
before { subject.stub(:cookbooks).and_return([ double('badcache', name: 'none', version: version) ]) }
|
69
65
|
|
70
|
-
|
71
|
-
|
72
|
-
|
66
|
+
it 'returns nil if there is no matching cookbook for the name and constraint' do
|
67
|
+
result = subject.satisfy(name, constraint)
|
68
|
+
expect(result).to be_nil
|
73
69
|
end
|
74
70
|
end
|
71
|
+
end
|
75
72
|
|
76
|
-
|
77
|
-
|
73
|
+
describe '#cookbook' do
|
74
|
+
subject { Berkshelf::CookbookStore.new(fixtures_path.join('cookbooks')) }
|
78
75
|
|
79
|
-
|
80
|
-
|
81
|
-
|
76
|
+
it 'returns a CachedCookbook if the specified cookbook version exists' do
|
77
|
+
expect(subject.cookbook('example_cookbook', '0.5.0')).to be_a(Berkshelf::CachedCookbook)
|
78
|
+
end
|
82
79
|
|
83
|
-
|
84
|
-
|
85
|
-
end
|
80
|
+
it 'returns nil if the specified cookbook version does not exist' do
|
81
|
+
expect(subject.cookbook('doesnotexist', '0.1.0')).to be_nil
|
86
82
|
end
|
83
|
+
end
|
87
84
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
85
|
+
describe '#cookbooks' do
|
86
|
+
before do
|
87
|
+
generate_cookbook(subject.storage_path, 'nginx', '0.101.2')
|
88
|
+
generate_cookbook(subject.storage_path, 'mysql', '1.2.6')
|
89
|
+
end
|
93
90
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
end
|
91
|
+
it 'returns a list of CachedCookbooks' do
|
92
|
+
subject.cookbooks.each do |cookbook|
|
93
|
+
expect(cookbook).to be_a(Berkshelf::CachedCookbook)
|
98
94
|
end
|
95
|
+
end
|
99
96
|
|
100
|
-
|
101
|
-
|
102
|
-
|
97
|
+
it 'contains a CachedCookbook for every cookbook in the storage path' do
|
98
|
+
expect(subject.cookbooks).to have(2).items
|
99
|
+
end
|
103
100
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
end
|
101
|
+
context 'given a value for the filter parameter' do
|
102
|
+
it 'returns only the CachedCookbooks whose name match the filter' do
|
103
|
+
expect(subject.cookbooks('mysql')).to have(1).item
|
108
104
|
end
|
109
105
|
end
|
110
106
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe FileUtils do
|
4
|
-
describe
|
4
|
+
describe '#mv' do
|
5
5
|
let(:src) { double('src') }
|
6
6
|
let(:dest) { double('dest') }
|
7
7
|
let(:options) { double('options') }
|
8
8
|
|
9
|
-
it
|
9
|
+
it 'replaces mv with cp_r and rm_rf' do
|
10
10
|
subject.stub(:windows?) { true }
|
11
11
|
FileUtils.should_receive(:cp_r).with(src, dest, options)
|
12
12
|
FileUtils.should_receive(:rm_rf).with(src)
|
@@ -1,210 +1,190 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
type: :chef_api,
|
28
|
-
value: double('capi2'),
|
29
|
-
options: double('capi_opts2')
|
30
|
-
}
|
31
|
-
]
|
32
|
-
end
|
33
|
-
|
34
|
-
it "sets the @locations instance variable to the given locations" do
|
35
|
-
downloader = subject.new(double('store'), locations: locations)
|
36
|
-
|
37
|
-
downloader.instance_variable_get(:@locations).should eql(locations)
|
38
|
-
end
|
39
|
-
end
|
3
|
+
describe Berkshelf::Downloader do
|
4
|
+
let(:locations) do
|
5
|
+
[
|
6
|
+
{
|
7
|
+
type: :chef_api,
|
8
|
+
value: double('capi'),
|
9
|
+
options: double('capi_opts')
|
10
|
+
},
|
11
|
+
{
|
12
|
+
type: :chef_api,
|
13
|
+
value: double('capi2'),
|
14
|
+
options: double('capi_opts2')
|
15
|
+
}
|
16
|
+
]
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '.initialize' do
|
20
|
+
context 'when no value for locations is given' do
|
21
|
+
it 'sets the @locations instance variable to a blank array' do
|
22
|
+
downloader = Berkshelf::Downloader.new(double('store'))
|
23
|
+
locations = downloader.instance_variable_get(:@locations)
|
24
|
+
|
25
|
+
expect(locations).to be_a(Array)
|
26
|
+
expect(locations).to be_empty
|
40
27
|
end
|
41
28
|
end
|
42
29
|
|
43
|
-
|
30
|
+
context 'when an explicit value of locations is given' do
|
31
|
+
it 'sets the @locations instance variable to the given locations' do
|
32
|
+
downloader = Berkshelf::Downloader.new(double('store'), locations: locations)
|
33
|
+
expect(downloader.instance_variable_get(:@locations)).to eq(locations)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
44
37
|
|
45
|
-
describe "#download" do
|
46
|
-
let(:source) { double('source', name: "artifact", version_constraint: "= 0.10.0") }
|
47
|
-
let(:location) { double('location') }
|
48
|
-
let(:cached_cookbook) { double('cached') }
|
49
38
|
|
50
|
-
context "when the source has a location" do
|
51
|
-
before(:each) do
|
52
|
-
source.stub(:location).and_return(location)
|
53
|
-
location.should_receive(:download).with(subject.storage_path).and_return(cached_cookbook)
|
54
|
-
source.should_receive(:cached_cookbook=).with(cached_cookbook)
|
55
|
-
end
|
56
39
|
|
57
|
-
|
58
|
-
|
59
|
-
end
|
40
|
+
let!(:cookbook_store) { Berkshelf::CookbookStore.new(tmp_path) }
|
41
|
+
subject { Berkshelf::Downloader.new(cookbook_store) }
|
60
42
|
|
61
|
-
|
62
|
-
|
43
|
+
describe '#download' do
|
44
|
+
let(:source) { double('source', name: 'artifact', version_constraint: '= 0.10.0') }
|
45
|
+
let(:location) { double('location') }
|
46
|
+
let(:cached_cookbook) { double('cached') }
|
63
47
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
48
|
+
context 'when the source has a location' do
|
49
|
+
before do
|
50
|
+
source.stub(:location).and_return(location)
|
51
|
+
location.should_receive(:download).with(subject.storage_path).and_return(cached_cookbook)
|
52
|
+
source.should_receive(:cached_cookbook=).with(cached_cookbook)
|
68
53
|
end
|
69
54
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
subject.stub(:locations).and_return([{type: :chef_api, value: :config, options: Hash.new}])
|
74
|
-
end
|
55
|
+
it "sends :download to the source's location and sets the source's cached_cookbook to the result" do
|
56
|
+
expect(subject.download(source)).to be_true
|
57
|
+
end
|
75
58
|
|
76
|
-
|
77
|
-
|
78
|
-
location.should_receive(:download).with(subject.storage_path).and_return(cached_cookbook)
|
79
|
-
source.should_receive(:cached_cookbook=).with(cached_cookbook)
|
59
|
+
it 'returns an Array containing the cached_cookbook and location used to download' do
|
60
|
+
result = subject.download(source)
|
80
61
|
|
81
|
-
|
82
|
-
|
62
|
+
expect(result).to be_a(Array)
|
63
|
+
expect(result[0]).to eq(cached_cookbook)
|
64
|
+
expect(result[1]).to eq(location)
|
83
65
|
end
|
84
66
|
end
|
85
67
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
68
|
+
context 'when the source does not have a location' do
|
69
|
+
before do
|
70
|
+
source.stub(:location).and_return(nil)
|
71
|
+
subject.stub(:locations).and_return([{ type: :chef_api, value: :config, options: {} }])
|
72
|
+
end
|
90
73
|
|
91
|
-
it
|
92
|
-
|
74
|
+
it 'sends the :download message to the default location' do
|
75
|
+
Berkshelf::Location.should_receive(:init).with(source.name, source.version_constraint, chef_api: :config).and_return(location)
|
76
|
+
location.should_receive(:download).with(subject.storage_path).and_return(cached_cookbook)
|
77
|
+
source.should_receive(:cached_cookbook=).with(cached_cookbook)
|
93
78
|
|
94
|
-
subject.
|
79
|
+
subject.download(source)
|
95
80
|
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe '#locations' do
|
85
|
+
let(:type) { :site }
|
86
|
+
let(:value) { double('value') }
|
87
|
+
let(:options) { double('options') }
|
96
88
|
|
97
|
-
|
98
|
-
|
89
|
+
it 'returns an array of Hashes representing locations' do
|
90
|
+
subject.add_location(type, value, options)
|
99
91
|
|
100
|
-
|
101
|
-
|
102
|
-
end
|
92
|
+
subject.locations.each do |location|
|
93
|
+
expect(location).to be_a(Hash)
|
103
94
|
end
|
95
|
+
end
|
104
96
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
value: double('capi'),
|
111
|
-
options: double('capi_opts')
|
112
|
-
},
|
113
|
-
{
|
114
|
-
type: :chef_api,
|
115
|
-
value: double('capi2'),
|
116
|
-
options: double('capi_opts2')
|
117
|
-
}
|
118
|
-
]
|
119
|
-
end
|
120
|
-
|
121
|
-
subject { Downloader.new(double('store'), locations: locations) }
|
122
|
-
|
123
|
-
it "contains only the locations passed to the initializer" do
|
124
|
-
subject.locations.should eql(locations)
|
125
|
-
end
|
126
|
-
|
127
|
-
it "does not include the array of default locations" do
|
128
|
-
subject.locations.should_not include(Downloader::DEFAULT_LOCATIONS)
|
129
|
-
end
|
97
|
+
context 'when no locations are explicitly added' do
|
98
|
+
subject { Berkshelf::Downloader.new(double('store')) }
|
99
|
+
|
100
|
+
it 'returns an array of default locations' do
|
101
|
+
expect(subject.locations).to eq(Berkshelf::Downloader::DEFAULT_LOCATIONS)
|
130
102
|
end
|
131
103
|
end
|
132
104
|
|
133
|
-
|
134
|
-
|
135
|
-
let(:value) { double('value') }
|
136
|
-
let(:options) { double('options') }
|
105
|
+
context 'when locations are explicitly added' do
|
106
|
+
subject { Berkshelf::Downloader.new(double('store'), locations: locations) }
|
137
107
|
|
138
|
-
it
|
139
|
-
subject.
|
108
|
+
it 'contains only the locations passed to the initializer' do
|
109
|
+
expect(subject.locations).to eq(locations)
|
110
|
+
end
|
140
111
|
|
141
|
-
|
112
|
+
it 'does not include the array of default locations' do
|
113
|
+
expect(subject.locations).to_not include(Berkshelf::Downloader::DEFAULT_LOCATIONS)
|
142
114
|
end
|
115
|
+
end
|
116
|
+
end
|
143
117
|
|
144
|
-
|
145
|
-
|
118
|
+
describe '#add_location' do
|
119
|
+
let(:type) { :site }
|
120
|
+
let(:value) { double('value') }
|
121
|
+
let(:options) { double('options') }
|
146
122
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
123
|
+
it 'adds a hash to the end of the array of locations' do
|
124
|
+
subject.add_location(type, value, options)
|
125
|
+
expect(subject.locations).to have(1).item
|
126
|
+
end
|
151
127
|
|
152
|
-
|
153
|
-
|
128
|
+
it 'adds a hash with a type, value, and options key' do
|
129
|
+
subject.add_location(type, value, options)
|
130
|
+
location = subject.locations.last
|
154
131
|
|
155
|
-
|
132
|
+
[:type, :value, :options].each do |key|
|
133
|
+
expect(location).to have_key(key)
|
156
134
|
end
|
135
|
+
end
|
157
136
|
|
158
|
-
|
159
|
-
|
137
|
+
it 'sets the value of the given :value to the value of the key :value' do
|
138
|
+
subject.add_location(type, value, options)
|
139
|
+
expect(subject.locations.last[:value]).to eq(value)
|
140
|
+
end
|
160
141
|
|
161
|
-
|
162
|
-
|
142
|
+
it 'sets the value of the given :type to the value of the key :type' do
|
143
|
+
subject.add_location(type, value, options)
|
144
|
+
expect(subject.locations.last[:type]).to eq(type)
|
145
|
+
end
|
163
146
|
|
164
|
-
|
165
|
-
|
147
|
+
it 'sets the value of the given :options to the value of the key :options' do
|
148
|
+
subject.add_location(type, value, options)
|
149
|
+
expect(subject.locations.last[:options]).to eq(options)
|
150
|
+
end
|
166
151
|
|
167
|
-
|
168
|
-
|
152
|
+
it 'raises a DuplicateLocationDefined error if a location of the given type and value was already added' do
|
153
|
+
subject.add_location(type, value, options)
|
169
154
|
|
170
|
-
|
155
|
+
expect {
|
171
156
|
subject.add_location(type, value, options)
|
157
|
+
}.to raise_error(Berkshelf::DuplicateLocationDefined)
|
158
|
+
end
|
172
159
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
context "adding multiple locations" do
|
179
|
-
let(:type_2) { :site }
|
180
|
-
let(:value_2) { double('value_2') }
|
181
|
-
let(:options_2) { double('options_2') }
|
160
|
+
context 'adding multiple locations' do
|
161
|
+
let(:type_2) { :site }
|
162
|
+
let(:value_2) { double('value_2') }
|
163
|
+
let(:options_2) { double('options_2') }
|
182
164
|
|
183
|
-
|
184
|
-
|
185
|
-
|
165
|
+
it 'adds locations in the order they are added' do
|
166
|
+
subject.add_location(type, value, options)
|
167
|
+
subject.add_location(type_2, value_2, options_2)
|
186
168
|
|
187
|
-
|
169
|
+
expect(subject.locations).to have(2).items
|
188
170
|
|
189
|
-
|
190
|
-
|
191
|
-
end
|
171
|
+
expect(subject.locations[0][:value]).to eql(value)
|
172
|
+
expect(subject.locations[1][:value]).to eql(value_2)
|
192
173
|
end
|
193
174
|
end
|
175
|
+
end
|
194
176
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
it "returns true if a source of the given type and value was already added" do
|
200
|
-
subject.add_location(type, value)
|
177
|
+
describe '#has_location?' do
|
178
|
+
let(:type) { :site }
|
179
|
+
let(:value) { double('value') }
|
201
180
|
|
202
|
-
|
203
|
-
|
181
|
+
it 'returns true if a source of the given type and value was already added' do
|
182
|
+
subject.add_location(type, value)
|
183
|
+
expect(subject.has_location?(type, value)).to be_true
|
184
|
+
end
|
204
185
|
|
205
|
-
|
206
|
-
|
207
|
-
end
|
186
|
+
it 'returns false if a source of the given type and value was not added' do
|
187
|
+
expect(subject.has_location?(type, value)).to be_false
|
208
188
|
end
|
209
189
|
end
|
210
190
|
end
|