beaker 3.13.0 → 3.14.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,6 +5,7 @@ module Beaker
5
5
  describe Logger do
6
6
  let(:my_io) { StringIO.new }
7
7
  let(:logger) { Logger.new(my_io, :quiet => true) }
8
+ let(:basic_logger) { Logger.new(:quiet => true) }
8
9
  let(:test_dir) { 'tmp/tests' }
9
10
  let(:dummy_prefix) { 'dummy' }
10
11
 
@@ -424,5 +425,6 @@ module Beaker
424
425
  end
425
426
 
426
427
  end
428
+
427
429
  end
428
430
  end
@@ -146,6 +146,7 @@ module Beaker
146
146
  :user_known_hosts_file => 'hosts123'
147
147
  }
148
148
  } }
149
+ let(:subcommand_file) {@subcommand_file || {:level => 'fifth'}}
149
150
  let(:presets) { {:level => 'lowest',
150
151
  :ssh => {
151
152
  :config => 'config123',
@@ -173,10 +174,12 @@ module Beaker
173
174
 
174
175
  allow(OptionsFileParser).to receive(:parse_options_file).and_return(opt_file)
175
176
  allow(parser).to receive(:parse_hosts_options).and_return(host_file)
177
+
178
+ allow(SubcommandOptionsParser).to receive(:parse_subcommand_options).and_return(subcommand_file)
176
179
  end
177
180
 
178
181
  it 'presets have the lowest priority' do
179
- @env = @argv = @host_file = @opt_file = {}
182
+ @env = @argv = @host_file = @opt_file = @subcommand_file = {}
180
183
  mock_out_parsing
181
184
 
182
185
  opts = parser.parse_args([])
@@ -185,6 +188,16 @@ module Beaker
185
188
  expect(attribution[:level]).to be == 'preset'
186
189
  end
187
190
 
191
+ it 'subcommand_options should have fifth priority' do
192
+ @env = @argv = @host_file = @opt_file = {}
193
+ mock_out_parsing
194
+
195
+ opts = parser.parse_args([])
196
+ attribution = parser.attribution
197
+ expect(opts[:level]).to be == 'fifth'
198
+ expect(attribution[:level]).to be == 'subcommand'
199
+ end
200
+
188
201
  it 'options file has fourth priority' do
189
202
  @env = @argv = @host_file = {}
190
203
  mock_out_parsing
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ module Beaker
4
+ module Options
5
+ describe '#parse_subcommand_options' do
6
+ let( :parser ) {Beaker::Options::SubcommandOptionsParser.parse_subcommand_options(argv)}
7
+ let( :argv ) {[]}
8
+
9
+ it 'returns an empty OptionsHash if not executing a subcommand' do
10
+ expect(parser).to be_kind_of(OptionsHash)
11
+ expect(parser).to be_empty
12
+ end
13
+
14
+ describe 'when the subcommand is init' do
15
+ let( :argv ) {['init']}
16
+ it 'returns an empty OptionsHash' do
17
+ expect(parser).to be_kind_of(OptionsHash)
18
+ expect(parser).to be_empty
19
+ end
20
+ end
21
+
22
+ describe 'when the subcommand is not init' do
23
+ let( :argv ) {['provision']}
24
+ it 'checks for file existence and loads the YAML file' do
25
+ expect(Beaker::Subcommands::SubcommandUtil::SUBCOMMAND_OPTIONS).to receive(:exist?).and_return(true)
26
+ allow(YAML).to receive(:load_file).and_return({})
27
+ expect(parser).to be_kind_of(Hash)
28
+ expect(parser).not_to be_kind_of(OptionsHash)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -24,15 +24,37 @@ module Beaker
24
24
  double("host")
25
25
  }
26
26
 
27
- describe 'reset_argv' do
28
- it "resets argv" do
29
- args = ["test1", "test2"]
30
- expect(ARGV).to receive(:clear).exactly(1).times
31
- subject.reset_argv(args)
32
- expect(ARGV[0]).to eq(args[0])
33
- expect(ARGV[1]).to eq(args[1])
34
- end
35
- end
27
+ let(:hypervisors) {
28
+ double("hypervisors")
29
+ }
30
+
31
+ let(:hosts) {
32
+ double("hosts")
33
+ }
34
+
35
+ let(:hypervisors_object) {
36
+ double("hypervisors_object")
37
+ }
38
+
39
+ let(:hosts_object) {
40
+ double("hosts_object")
41
+ }
42
+
43
+ let(:network_manager){
44
+ double("network_manager")
45
+ }
46
+
47
+ let(:save_object){
48
+ double("save_object")
49
+ }
50
+
51
+ let(:load_object){
52
+ double("load_object")
53
+ }
54
+
55
+ let(:yaml_object){
56
+ double("yaml_object")
57
+ }
36
58
 
37
59
  describe 'execute_subcommand' do
38
60
  it "determines if we should execute the init subcommand" do
@@ -52,15 +74,6 @@ module Beaker
52
74
  end
53
75
  end
54
76
 
55
- describe 'execute_beaker' do
56
- it "executes beaker with arguments" do
57
- allow(cli).to receive(:execute!).and_return(true)
58
- allow(Beaker::CLI).to receive(:new).and_return(cli)
59
- expect(subject).to receive(:reset_argv).exactly(1).times
60
- expect(cli).to receive(:execute!).exactly(1).times
61
- subject.execute_beaker(['args'])
62
- end
63
- end
64
77
 
65
78
  describe 'error_with' do
66
79
  it "the exit value should default to 1" do
@@ -91,192 +104,6 @@ module Beaker
91
104
  end
92
105
  end
93
106
 
94
- describe 'init_vmpooler' do
95
- it "executes the vmpooler quick task" do
96
- expect(subject).to receive(:execute_rake_task).with("beaker_quickstart:gen_hosts[vmpooler]").exactly(1).times
97
- subject.init_vmpooler
98
- end
99
- end
100
-
101
- describe 'init_vagrant' do
102
- it "executes the vmpooler quick task" do
103
- expect(subject).to receive(:execute_rake_task).with("beaker_quickstart:gen_hosts[vagrant]").exactly(1).times
104
- subject.init_vagrant
105
- end
106
- end
107
-
108
- describe 'init_hypervisor' do
109
- it "calls init_vagrant" do
110
- expect(subject).to receive(:init_vagrant).with(no_args).exactly(1).times
111
- expect(subject).to receive(:init_vmpooler).with(no_args).exactly(0).times
112
- subject.init_hypervisor('vagrant')
113
- end
114
-
115
- it "calls init_vmpooler" do
116
- expect(subject).to receive(:init_vagrant).with(no_args).exactly(0).times
117
- expect(subject).to receive(:init_vmpooler).with(no_args).exactly(1).times
118
- subject.init_hypervisor('vmpooler')
119
- end
120
-
121
- it "fails to call init for a hypervisor" do
122
- expect(subject).to receive(:init_vagrant).with(no_args).exactly(0).times
123
- expect(subject).to receive(:init_vmpooler).with(no_args).exactly(0).times
124
- subject.init_hypervisor('invalid')
125
- end
126
- end
127
-
128
- describe 'execute_rake_task' do
129
-
130
- it "executes the rake task" do
131
- allow(Rake).to receive(:application).and_return(rake)
132
- expect(ARGV).to receive(:clear).exactly(1).times
133
- expect(rake).to receive(:init).and_return(true).exactly(1).times
134
- expect(rake).to receive(:load_rakefile).and_return(true).exactly(1).times
135
- expect(rake).to receive(:invoke_task).with("mytask").exactly(1).times
136
- subject.execute_rake_task("mytask")
137
- end
138
- end
139
-
140
- describe "determine_rake_file" do
141
-
142
- it "uses Rakefile if no rakefile exists" do
143
- allow(subject).to receive(:rake_app).and_return(rake)
144
- allow(rake).to receive(:find_rakefile_location).and_return(nil)
145
- expect subject.determine_rake_file == "Rakefile"
146
- end
147
-
148
- it "uses Rakefile if Rakefile exists" do
149
- allow(subject).to receive(:rake_app).and_return(rake)
150
- allow(rake).to receive(:find_rakefile_location).and_return("Rakefile")
151
- expect subject.determine_rake_file == "Rakefile"
152
- end
153
-
154
- it "uses rakefile if rakefile exists" do
155
- allow(subject).to receive(:rake_app).and_return(rake)
156
- allow(rake).to receive(:find_rakefile_location).and_return("rakefile")
157
- expect subject.determine_rake_file == "rakefile"
158
- end
159
-
160
- it "uses Rakefile.rb if Rakefile.rb exists" do
161
- allow(subject).to receive(:rake_app).and_return(rake)
162
- allow(rake).to receive(:find_rakefile_location).and_return("Rakefile.rb")
163
- expect subject.determine_rake_file == "Rakefile.rb"
164
- end
165
-
166
- it "uses rakefile.rb if rakefile.rb exists" do
167
- allow(subject).to receive(:rake_app).and_return(rake)
168
- allow(rake).to receive(:find_rakefile_location).and_return("rakefile.rb")
169
- expect subject.determine_rake_file == "rakefile.rb"
170
- end
171
- end
172
-
173
- describe "require_tasks" do
174
- it "appends the require if it isn't contained in the Rakefile" do
175
- allow(subject).to receive(:determine_rake_file).and_return("Rakefile")
176
- allow(File).to receive(:readlines).with("Rakefile").and_return([""])
177
- allow(File).to receive(:open).with("Rakefile", "a+").and_yield(file)
178
- allow(File).to receive(:puts).with("require 'beaker/tasks/quick_start'").and_return(true)
179
- expect(FileUtils).to receive(:touch).with("Rakefile").exactly(1).times
180
- expect(File).to receive(:open).with("Rakefile", "a+").and_yield(file).exactly(1).times
181
- expect(file).to receive(:puts).with("require 'beaker/tasks/quick_start'").exactly(1).times
182
- subject.require_tasks
183
- end
184
-
185
- it "does't append the require if it is contained in the Rakefile" do
186
- allow(subject).to receive(:determine_rake_file).and_return("Rakefile")
187
- allow(File).to receive(:readlines).with("Rakefile").and_return(["require 'beaker/tasks/quick_start'"])
188
- allow(File).to receive(:open).with("Rakefile", "a+").and_yield(file)
189
- allow(File).to receive(:puts).with("require 'beaker/tasks/quick_start'").and_return(true)
190
- expect(FileUtils).to receive(:touch).with("Rakefile").exactly(1).times
191
- expect(File).to receive(:open).with("Rakefile", "a+").and_yield(file).exactly(0).times
192
- expect(file).to receive(:puts).with("require 'beaker/tasks/quick_start'").exactly(0).times
193
- subject.require_tasks
194
- end
195
- end
196
-
197
- describe "init_config" do
198
- it "creates a .beaker folder and loads the config" do
199
- expect(FileUtils).to receive(:mkdir_p).with(".beaker").exactly(1).times
200
- expect(YAML::Store).to receive(:new).with(".beaker/config").exactly(1).times
201
- subject.init_config
202
- end
203
- end
204
-
205
- describe "store_config" do
206
- before(:each) { SubcommandUtil.class_variable_set :@@store, store}
207
-
208
- it "stores some values in the YAML store" do
209
- options = { :hypervisor => "vmpooler", :test => "abc", :provisioned => true}
210
- allow(store).to receive(:transaction).and_yield
211
- expect(store).to receive(:[]=).with(:hypervisor, "vmpooler").exactly(1).times
212
- expect(store).to receive(:[]=).with(:test, "abc").exactly(0).times
213
- expect(store).to receive(:[]=).with(:provisioned, true).exactly(1).times
214
- subject.store_config(options)
215
- end
216
-
217
- it "stores all values in the YAML store" do
218
- options = { :hypervisor => "vmpooler", :provisioned => true}
219
- allow(store).to receive(:transaction).and_yield
220
- expect(store).to receive(:[]=).with(:hypervisor, "vmpooler").exactly(1).times
221
- expect(store).to receive(:[]=).with(:provisioned, true).exactly(1).times
222
- subject.store_config(options)
223
- end
224
-
225
- it "stores no values in the YAML store" do
226
- options = {:test => "abc"}
227
- allow(store).to receive(:transaction).and_yield
228
- expect(store).to receive(:[]=).with(:hypervisor, anything).exactly(0).times
229
- expect(store).to receive(:[]=).with(:provisioned, anything).exactly(0).times
230
- subject.store_config(options)
231
- end
232
- end
233
-
234
- describe "delete_config" do
235
- before(:each) { SubcommandUtil.class_variable_set :@@store, store}
236
- it "deletes keys from the YAML store" do
237
- keys = [ :hypervisor, :test, :provisioned ]
238
- allow(store).to receive(:transaction).and_yield
239
- expect(store).to receive(:delete).with(:hypervisor).exactly(1).times
240
- expect(store).to receive(:delete).with(:test).exactly(1).times
241
- expect(store).to receive(:delete).with(:provisioned).exactly(1).times
242
- subject.delete_config(keys)
243
- end
244
- end
245
-
246
- describe "provision" do
247
- it "provisions, validates, and configures with vmpooler" do
248
- options = {:validate => true, :configure => true}
249
- expect(cli).to receive(:provision).and_return(true)
250
- expect(cli).to receive(:preserve_hosts_file).exactly(1).times
251
- allow(Beaker::CLI).to receive(:new).and_return(cli)
252
- allow(cli).to receive(:parse_options).and_return(cli)
253
- hypervisor = "vmpooler"
254
- expect(subject).to receive(:reset_argv).with(["--hosts",".beaker/acceptance/config/default_#{hypervisor}_hosts.yaml", "--validate", true, "--configure", true]).exactly(1).times
255
- subject.provision(hypervisor, options)
256
- end
257
-
258
- it "provisions and validates with vmpooler" do
259
- options = {:validate => true, :configure => false }
260
- expect(cli).to receive(:provision).and_return(true)
261
- expect(cli).to receive(:preserve_hosts_file).exactly(1).times
262
- allow(Beaker::CLI).to receive(:new).and_return(cli)
263
- allow(cli).to receive(:parse_options).and_return(cli)
264
- hypervisor = "vmpooler"
265
- expect(subject).to receive(:reset_argv).with(["--hosts",".beaker/acceptance/config/default_#{hypervisor}_hosts.yaml", "--validate", true, "--configure", false]).exactly(1).times
266
- subject.provision(hypervisor, options)
267
- end
268
-
269
- it "only provisions with vmpooler" do
270
- options = {:validate => false, :configure => false }
271
- expect(cli).to receive(:provision).and_return(true)
272
- expect(cli).to receive(:preserve_hosts_file).exactly(1).times
273
- allow(Beaker::CLI).to receive(:new).and_return(cli)
274
- allow(cli).to receive(:parse_options).and_return(cli)
275
- hypervisor = "vmpooler"
276
- expect(subject).to receive(:reset_argv).with(["--hosts",".beaker/acceptance/config/default_#{hypervisor}_hosts.yaml", "--validate", false, "--configure", false]).exactly(1).times
277
- subject.provision(hypervisor, options)
278
- end
279
- end
280
107
  end
281
108
  end
282
109
  end
@@ -0,0 +1,146 @@
1
+ require 'spec_helper'
2
+
3
+ module Beaker
4
+ SubcommandUtil = Beaker::Subcommands::SubcommandUtil
5
+ describe Subcommand do
6
+ let( :subcommand ) {
7
+ Beaker::Subcommand.new
8
+ }
9
+
10
+ context '#initialize' do
11
+ it 'creates a cli object' do
12
+ expect(Beaker::CLI).to receive(:new).once
13
+ subcommand
14
+ end
15
+ describe 'File operation initialization for subcommands' do
16
+ it 'checks to ensure subcommand file resources exist' do
17
+ expect(FileUtils).to receive(:mkdir_p).with(SubcommandUtil::CONFIG_DIR)
18
+ expect(SubcommandUtil::SUBCOMMAND_OPTIONS).to receive(:exist?).and_return(true)
19
+ expect(SubcommandUtil::SUBCOMMAND_STATE).to receive(:exist?).and_return(true)
20
+ subcommand
21
+ end
22
+
23
+ it 'touches the files when they do not exist' do
24
+ expect(FileUtils).to receive(:mkdir_p).with(SubcommandUtil::CONFIG_DIR)
25
+ allow(SubcommandUtil::SUBCOMMAND_OPTIONS).to receive(:exist?).and_return(false)
26
+ allow(SubcommandUtil::SUBCOMMAND_STATE).to receive(:exist?).and_return(false)
27
+ expect(FileUtils).to receive(:touch).with(SubcommandUtil::SUBCOMMAND_OPTIONS)
28
+ expect(FileUtils).to receive(:touch).with(SubcommandUtil::SUBCOMMAND_STATE)
29
+ subcommand
30
+ end
31
+
32
+ end
33
+ end
34
+
35
+ context '#init' do
36
+ let( :cli ) { subcommand.instance_variable_get(:@cli) }
37
+ let( :mock_options ) { {:timestamp => 'noon', :other_key => 'cordite'}}
38
+ let( :yaml_store_mock ) { double('yaml_store_mock') }
39
+ it 'calculates options and writes them to disk and deletes the' do
40
+ expect(cli).to receive(:parse_options)
41
+ allow(cli).to receive(:configured_options).and_return(mock_options)
42
+
43
+ allow(File).to receive(:open)
44
+ allow(YAML::Store).to receive(:new).with(SubcommandUtil::SUBCOMMAND_STATE).and_return(yaml_store_mock)
45
+ allow(yaml_store_mock).to receive(:transaction).and_yield
46
+ expect(yaml_store_mock).to receive(:[]=).with('provisioned', false)
47
+ subcommand.init
48
+ expect(mock_options).not_to have_key(:timestamp)
49
+ end
50
+ end
51
+
52
+ context '#provision' do
53
+ let ( :cli ) { subcommand.instance_variable_get(:@cli) }
54
+ let( :yaml_store_mock ) { double('yaml_store_mock') }
55
+ let ( :host_hash ) { {'mynode.net' => {:name => 'mynode', :platform => Beaker::Platform.new('centos-6-x86_64')}}}
56
+ let ( :cleaned_hosts ) {double()}
57
+ let ( :yielded_host_hash ) {double()}
58
+ let ( :yielded_host_name) {double()}
59
+ let ( :network_manager) {double('network_manager')}
60
+ let ( :hosts) {double('hosts')}
61
+ let ( :hypervisors) {double('hypervisors')}
62
+ let (:options) {double ('options')}
63
+ it 'provisions the host and saves the host info' do
64
+ expect(YAML::Store).to receive(:new).with(SubcommandUtil::SUBCOMMAND_STATE).and_return(yaml_store_mock)
65
+ allow(yaml_store_mock).to receive(:[]).and_return(false)
66
+ allow(cli).to receive(:preserve_hosts_file).and_return("/path/to/ho")
67
+ allow(cli).to receive(:network_manager).and_return(network_manager)
68
+ allow(cli).to receive(:options).and_return(options)
69
+ allow(options).to receive(:[]).with(:hosts_preserved_yaml_file).and_return("/path/to/hosts")
70
+ allow(network_manager).to receive(:hosts).and_return(hosts)
71
+ allow(network_manager).to receive(:hypervisors).and_return(hypervisors)
72
+ expect(cli).to receive(:parse_options).and_return(cli)
73
+ expect(cli).to receive(:provision)
74
+ expect(cli).to receive(:combined_instance_and_options_hosts).and_return(host_hash)
75
+ expect(SubcommandUtil).to receive(:sanitize_options_for_save).and_return(cleaned_hosts)
76
+ expect(cleaned_hosts).to receive(:each).and_yield(yielded_host_name, yielded_host_hash)
77
+ expect(yielded_host_hash).to receive(:[]=).with('provision', false)
78
+ expect(YAML::Store).to receive(:new).with(SubcommandUtil::SUBCOMMAND_OPTIONS).and_return(yaml_store_mock)
79
+
80
+ expect(yaml_store_mock).to receive(:transaction).and_yield.exactly(3).times
81
+ expect(yaml_store_mock).to receive(:[]=).with('HOSTS', cleaned_hosts)
82
+ expect(yaml_store_mock).to receive(:[]=).with('hosts_preserved_yaml_file', "/path/to/hosts")
83
+
84
+ expect(yaml_store_mock).to receive(:[]=).with('provisioned', true)
85
+ subcommand.provision
86
+ end
87
+ end
88
+
89
+
90
+ context 'exec' do
91
+ it 'calls execute! when no resource is given' do
92
+ expect_any_instance_of(Pathname).to_not receive(:directory?)
93
+ expect_any_instance_of(Pathname).to_not receive(:exist?)
94
+ expect_any_instance_of(Beaker::CLI).to receive(:parse_options).once
95
+ expect_any_instance_of(Beaker::CLI).to receive(:initialize_network_manager).once
96
+ expect_any_instance_of(Beaker::CLI).to receive(:execute!).once
97
+ expect{subcommand.exec}.to_not raise_error
98
+ end
99
+
100
+ it 'checks to to see if the resource is a file_resource' do
101
+
102
+ expect_any_instance_of(Pathname).to receive(:exist?).and_return(true)
103
+ expect_any_instance_of(Pathname).to receive(:directory?).and_return(false)
104
+ expect_any_instance_of(Pathname).to receive(:expand_path).once
105
+ expect_any_instance_of(Beaker::CLI).to receive(:execute!).once
106
+ expect{subcommand.exec('resource')}.to_not raise_error
107
+ end
108
+
109
+ it 'checks to see if the resource is a directory' do
110
+ expect_any_instance_of(Pathname).to receive(:exist?).and_return(true)
111
+ expect_any_instance_of(Pathname).to receive(:directory?).and_return(true)
112
+ expect(Dir).to receive(:glob)
113
+ expect_any_instance_of(Pathname).to receive(:expand_path).once
114
+ expect_any_instance_of(Beaker::CLI).to receive(:execute!).once
115
+ expect{subcommand.exec('resource')}.to_not raise_error
116
+ end
117
+
118
+ it 'allows a hard coded suite name to be specified' do
119
+
120
+ allow_any_instance_of(Pathname).to receive(:exist?).and_return(false)
121
+ expect_any_instance_of(Beaker::CLI).to receive(:execute!).once
122
+ expect{subcommand.exec('tests')}.to_not raise_error
123
+ end
124
+
125
+ it 'errors when a resource is neither a valid file resource or suite name' do
126
+ allow_any_instance_of(Pathname).to receive(:exist?).and_return(false)
127
+ expect{subcommand.exec('blahblahblah')}.to raise_error(ArgumentError)
128
+ end
129
+ end
130
+
131
+ context 'destroy' do
132
+ let( :cli ) { subcommand.instance_variable_get(:@cli) }
133
+ let( :mock_options ) { {:timestamp => 'noon', :other_key => 'cordite'}}
134
+ let( :yaml_store_mock ) { double('yaml_store_mock') }
135
+ it 'calls destroy and updates the yaml store' do
136
+ expect(YAML::Store).to receive(:new).with(SubcommandUtil::SUBCOMMAND_STATE).and_return(yaml_store_mock)
137
+ allow(SubcommandUtil).to receive(:cleanup).with(cli).and_return(true)
138
+ allow(yaml_store_mock).to receive(:transaction).and_yield
139
+ allow(yaml_store_mock).to receive(:[]).with('provisioned').and_return(true)
140
+ allow(yaml_store_mock).to receive(:delete).with('provisioned').and_return(true)
141
+ expect(SubcommandUtil).to receive(:error_with).with("Please provision an environment").exactly(0).times
142
+ subcommand.destroy
143
+ end
144
+ end
145
+ end
146
+ end