knife-openstack 0.10.0 → 1.0.0.rc1

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 (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.travis.yml +6 -0
  4. data/CHANGELOG.md +20 -22
  5. data/Gemfile +11 -1
  6. data/README.md +6 -4
  7. data/Rakefile +33 -0
  8. data/knife-openstack.gemspec +7 -8
  9. data/lib/chef/knife/cloud/openstack_server_create_options.rb +75 -0
  10. data/lib/chef/knife/cloud/openstack_service.rb +62 -0
  11. data/lib/chef/knife/cloud/openstack_service_options.rb +50 -0
  12. data/lib/chef/knife/openstack_flavor_list.rb +37 -51
  13. data/lib/chef/knife/openstack_group_list.rb +38 -45
  14. data/lib/chef/knife/openstack_helpers.rb +30 -0
  15. data/lib/chef/knife/openstack_image_list.rb +42 -59
  16. data/lib/chef/knife/openstack_network_list.rb +25 -21
  17. data/lib/chef/knife/openstack_server_create.rb +166 -452
  18. data/lib/chef/knife/openstack_server_delete.rb +26 -106
  19. data/lib/chef/knife/openstack_server_list.rb +37 -59
  20. data/lib/chef/knife/openstack_server_show.rb +57 -0
  21. data/lib/knife-openstack/version.rb +1 -1
  22. data/spec/functional/flavor_list_func_spec.rb +45 -0
  23. data/spec/functional/group_list_func_spec.rb +67 -0
  24. data/spec/functional/image_list_func_spec.rb +51 -0
  25. data/spec/functional/network_list_func_spec.rb +44 -0
  26. data/spec/functional/server_create_func_spec.rb +118 -0
  27. data/spec/functional/server_delete_func_spec.rb +84 -0
  28. data/spec/functional/server_list_func_spec.rb +95 -0
  29. data/spec/functional/server_show_func_spec.rb +46 -0
  30. data/spec/integration/cleanup.rb +91 -0
  31. data/spec/integration/config/environment.yml.sample +13 -0
  32. data/spec/integration/openstack_spec.rb +618 -0
  33. data/spec/spec_helper.rb +126 -0
  34. data/spec/unit/openstack_flavor_list_spec.rb +30 -0
  35. data/spec/unit/openstack_group_list_spec.rb +43 -0
  36. data/spec/unit/openstack_image_list_spec.rb +32 -0
  37. data/spec/unit/openstack_network_list_spec.rb +39 -0
  38. data/spec/unit/openstack_server_create_spec.rb +344 -182
  39. data/spec/unit/openstack_server_delete_spec.rb +43 -0
  40. data/spec/unit/openstack_server_list_spec.rb +32 -0
  41. data/spec/unit/openstack_server_show_spec.rb +42 -0
  42. data/spec/unit/openstack_service_spec.rb +89 -0
  43. data/spec/unit/validate_spec.rb +55 -0
  44. metadata +95 -51
  45. data/lib/chef/knife/openstack_base.rb +0 -182
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,130 @@
1
+ # Copyright:: Copyright (c) 2013-2014 Chef Software, Inc.
2
+ # License: Apache License, Version 2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ # Author:: Siddheshwar More (<siddheshwar.more@clogeny.com>)
17
+
18
+
1
19
  $:.unshift File.expand_path('../../lib', __FILE__)
2
20
  require 'chef/knife/bootstrap'
21
+ require 'chef/knife/openstack_helpers'
22
+ require 'fog'
3
23
  require 'chef/knife/winrm_base'
24
+ require 'chef/knife/bootstrap_windows_winrm'
4
25
  require 'chef/knife/openstack_server_create'
26
+ require 'chef/knife/openstack_server_delete'
27
+ require 'chef/knife/bootstrap_windows_ssh'
28
+ require "securerandom"
29
+ require 'knife-openstack/version'
30
+ require 'test/knife-utils/test_bed'
31
+ require 'resource_spec_helper'
32
+ require 'server_command_common_spec_helper'
33
+ require 'tempfile'
34
+
35
+ def find_instance_id(instance_name, file)
36
+ file.lines.each do |line|
37
+ if line.include?("#{instance_name}")
38
+ return "#{line}".split(" ")[2].strip
39
+ end
40
+ end
41
+ end
42
+
43
+ def is_config_present
44
+ if ! ENV['RUN_INTEGRATION_TESTS']
45
+ puts("\nPlease set RUN_INTEGRATION_TESTS environment variable to run integration tests")
46
+ return false
47
+ end
48
+
49
+ unset_env_var = []
50
+ unset_config_options = []
51
+ is_config = true
52
+ config_file_exist = File.exist?(File.expand_path("../integration/config/environment.yml", __FILE__))
53
+ openstack_config = YAML.load(File.read(File.expand_path("../integration/config/environment.yml", __FILE__))) if config_file_exist
54
+ %w(OPENSTACK_USERNAME OPENSTACK_PASSWORD OPENSTACK_AUTH_URL OPENSTACK_TENANT).each do |os_env_var|
55
+ if ENV[os_env_var].nil?
56
+ unset_env_var << os_env_var
57
+ is_config = false
58
+ end
59
+ end
60
+
61
+ err_msg = "\nPlease set #{unset_env_var.join(', ')} environment"
62
+ err_msg = err_msg + ( unset_env_var.length > 1 ? " variables " : " variable " ) + "for integration tests."
63
+ puts err_msg unless unset_env_var.empty?
64
+
65
+ %w(OS_SSH_USER OPENSTACK_PRI_KEY OPENSTACK_KEY_PAIR OS_WINDOWS_SSH_USER OS_WINDOWS_SSH_PASSWORD OS_WINRM_USER OS_WINRM_PASSWORD OS_LINUX_IMAGE OS_LINUX_FLAVOR OS_INVALID_FLAVOR OS_INVALID_FLOATING_IP OS_WINDOWS_FLAVOR OS_WINDOWS_IMAGE OS_WINDOWS_SSH_IMAGE OS_NETWORK_IDS OS_AVAILABILITY_ZONE).each do |os_config_opt|
66
+ option_value = ENV[os_config_opt] || (openstack_config[os_config_opt] if openstack_config)
67
+ if option_value.nil?
68
+ unset_config_options << os_config_opt
69
+ is_config = false
70
+ end
71
+ end
72
+
73
+ config_err_msg = "\nPlease set #{unset_config_options.join(', ')} config"
74
+ config_err_msg = config_err_msg + ( unset_config_options.length > 1 ? " options in ../spec/integration/config/environment.yml or as environment variables" : " option in ../spec/integration/config/environment.yml or as environment variable" ) + " for integration tests."
75
+ puts config_err_msg unless unset_config_options.empty?
76
+
77
+ is_config
78
+ end
79
+
80
+ def get_gem_file_name
81
+ "knife-openstack-" + Knife::OpenStack::VERSION + ".gem"
82
+ end
83
+
84
+ def delete_instance_cmd(stdout)
85
+ "knife openstack server delete " + find_instance_id("Instance ID", stdout) +
86
+ append_openstack_creds(is_list_cmd = true) + " --yes"
87
+ end
88
+
89
+ def create_node_name(name)
90
+ @name_node = (name == "linux") ? "os-integration-test-linux-#{SecureRandom.hex(4)}" : "os-integration-test-win-#{SecureRandom.hex(4)}"
91
+ end
92
+
93
+
94
+ def init_openstack_test
95
+ init_test
96
+
97
+ begin
98
+ data_to_write = File.read(File.expand_path("../integration/config/incorrect_openstack.pem", __FILE__))
99
+ File.open("#{temp_dir}/incorrect_openstack.pem", 'w') {|f| f.write(data_to_write)}
100
+ rescue
101
+ puts "Error while creating file - incorrect_openstack.pem"
102
+ end
103
+
104
+ config_file_exist = File.exist?(File.expand_path("../integration/config/environment.yml", __FILE__))
105
+ openstack_config = YAML.load(File.read(File.expand_path("../integration/config/environment.yml", __FILE__))) if config_file_exist
106
+
107
+ %w(OS_SSH_USER OPENSTACK_KEY_PAIR OPENSTACK_PRI_KEY OS_WINDOWS_SSH_USER OS_WINDOWS_SSH_PASSWORD OS_WINRM_USER OS_WINRM_PASSWORD OS_LINUX_IMAGE OS_LINUX_FLAVOR OS_INVALID_FLAVOR OS_INVALID_FLOATING_IP OS_WINDOWS_FLAVOR OS_WINDOWS_IMAGE OS_WINDOWS_SSH_IMAGE OS_NETWORK_IDS OS_AVAILABILITY_ZONE).each do |os_config_opt|
108
+ instance_variable_set("@#{os_config_opt.downcase}", (openstack_config[os_config_opt] if openstack_config) || ENV[os_config_opt])
109
+ end
110
+ begin
111
+ key_file_path = @openstack_pri_key
112
+ key_file_exist = File.exist?(File.expand_path(key_file_path, __FILE__))
113
+ data_to_write = File.read(File.expand_path(key_file_path, __FILE__)) if key_file_exist
114
+ File.open("#{temp_dir}/openstack.pem", 'w') {|f| f.write(data_to_write)}
115
+ rescue
116
+ puts "Error while creating file - openstack.pem"
117
+ end
118
+ end
119
+
120
+ def create_sh_user_data_file
121
+ file = Tempfile.new(['test_user_data', '.sh'])
122
+ file.write("echo 'sample user data file created' >> #{Dir.tmpdir}/testuserdata.txt")
123
+ file.rewind
124
+ file
125
+ end
126
+
127
+ def delete_sh_user_data_file(file)
128
+ file.close
129
+ file.unlink
130
+ end
@@ -0,0 +1,30 @@
1
+ #
2
+ # Author:: Mukta Aphale (<mukta.aphale@clogeny.com>)
3
+ # Author:: Siddheshwar More (<siddheshwar.more@clogeny.com>)
4
+ # Author:: Ameya Varade (<ameya.varade@clogeny.com>)
5
+ # Copyright:: Copyright (c) 2013-2014 Chef Software, Inc.
6
+ # License:: Apache License, Version 2.0
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+
20
+ require 'spec_helper'
21
+ require 'chef/knife/openstack_flavor_list'
22
+ require 'chef/knife/cloud/openstack_service'
23
+ require 'support/shared_examples_for_command'
24
+ require 'unit/validate_spec'
25
+
26
+ describe Chef::Knife::Cloud::OpenstackFlavorList do
27
+ it_behaves_like Chef::Knife::Cloud::Command, Chef::Knife::Cloud::OpenstackFlavorList.new
28
+
29
+ include_context "#validate!", Chef::Knife::Cloud::OpenstackFlavorList.new
30
+ end
@@ -0,0 +1,43 @@
1
+ #
2
+ # Author:: Mukta Aphale (<mukta.aphale@clogeny.com>)
3
+ # Author:: Siddheshwar More (<siddheshwar.more@clogeny.com>)
4
+ # Author:: Ameya Varade (<ameya.varade@clogeny.com>)
5
+ # Copyright:: Copyright (c) 2013-2014 Chef Software, Inc.
6
+ # License:: Apache License, Version 2.0
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+
20
+ require 'spec_helper'
21
+ require 'chef/knife/openstack_group_list'
22
+ require 'chef/knife/cloud/openstack_service'
23
+ require 'support/shared_examples_for_command'
24
+ require 'unit/validate_spec'
25
+
26
+ describe Chef::Knife::Cloud::OpenstackGroupList do
27
+ it_behaves_like Chef::Knife::Cloud::Command, Chef::Knife::Cloud::OpenstackGroupList.new
28
+
29
+ include_context "#validate!", Chef::Knife::Cloud::OpenstackGroupList.new
30
+
31
+ let (:instance) {Chef::Knife::Cloud::OpenstackGroupList.new}
32
+
33
+ context "#list" do
34
+ before(:each) do
35
+ @security_groups = [TestResource.new({ "name" => "Unrestricted","description" => "testdescription", "security_group_rules" => [TestResource.new({"from_port"=>636, "group"=>{}, "ip_protocol"=>"tcp", "to_port"=>636, "parent_group_id"=>14, "ip_range"=>{"cidr"=>"0.0.0.0/0"}, "id"=>183})]})]
36
+ end
37
+
38
+ it "returns group list" do
39
+ expect(instance.ui).to receive(:list).with(["Name", "Protocol", "From", "To", "CIDR", "Description", "Unrestricted", "tcp", "636", "636", "0.0.0.0/0", "testdescription"],:uneven_columns_across, 6)
40
+ instance.list(@security_groups)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,32 @@
1
+ #
2
+ # Author:: Mukta Aphale (<mukta.aphale@clogeny.com>)
3
+ # Author:: Siddheshwar More (<siddheshwar.more@clogeny.com>)
4
+ # Author:: Ameya Varade (<ameya.varade@clogeny.com>)
5
+ # Copyright:: Copyright (c) 2013-2014 Chef Software, Inc.
6
+ # License:: Apache License, Version 2.0
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+
20
+ require 'spec_helper'
21
+ require 'chef/knife/openstack_image_list'
22
+ require 'chef/knife/cloud/openstack_service'
23
+ require 'support/shared_examples_for_command'
24
+ require 'unit/validate_spec'
25
+
26
+ describe Chef::Knife::Cloud::OpenstackImageList do
27
+ it_behaves_like Chef::Knife::Cloud::Command, Chef::Knife::Cloud::OpenstackImageList.new
28
+
29
+ let (:instance) {Chef::Knife::Cloud::OpenstackImageList.new}
30
+
31
+ include_context "#validate!", Chef::Knife::Cloud::OpenstackImageList.new
32
+ end
@@ -0,0 +1,39 @@
1
+ #
2
+ # Author:: Prabhu Das (<prabhu.das@clogeny.com>)
3
+ # Author:: Ameya Varade (<ameya.varade@clogeny.com>)
4
+ # Copyright:: Copyright (c) 2014 Chef Software, Inc.
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ require 'spec_helper'
20
+ require 'chef/knife/openstack_network_list'
21
+ require 'chef/knife/cloud/openstack_service'
22
+ require 'support/shared_examples_for_command'
23
+ require 'unit/validate_spec'
24
+
25
+ describe Chef::Knife::Cloud::OpenstackNetworkList do
26
+ it_behaves_like Chef::Knife::Cloud::Command, Chef::Knife::Cloud::OpenstackNetworkList.new
27
+
28
+ let (:instance) {Chef::Knife::Cloud::OpenstackNetworkList.new}
29
+
30
+ include_context "#validate!", Chef::Knife::Cloud::OpenstackNetworkList.new
31
+
32
+ context "query_resource" do
33
+ it "returns the networks using the fog service." do
34
+ instance.service = double
35
+ expect(instance.service).to receive(:list_networks)
36
+ instance.query_resource
37
+ end
38
+ end
39
+ end
@@ -1,257 +1,419 @@
1
1
  #
2
+ # Author:: Prabhu Das (<prabhu.das@clogeny.com>)
2
3
  # Author:: Mukta Aphale (<mukta.aphale@clogeny.com>)
4
+ # Author:: Siddheshwar More (<siddheshwar.more@clogeny.com>)
5
+ # Author:: Ameya Varade (<ameya.varade@clogeny.com>)
3
6
  # Copyright:: Copyright (c) 2013-2014 Chef Software, Inc.
7
+ # License:: Apache License, Version 2.0
8
+ #
9
+ # Licensed under the Apache License, Version 2.0 (the "License");
10
+ # you may not use this file except in compliance with the License.
11
+ # You may obtain a copy of the License at
12
+ #
13
+ # http://www.apache.org/licenses/LICENSE-2.0
14
+ #
15
+ # Unless required by applicable law or agreed to in writing, software
16
+ # distributed under the License is distributed on an "AS IS" BASIS,
17
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ # See the License for the specific language governing permissions and
19
+ # limitations under the License.
20
+
4
21
 
5
22
  require File.expand_path('../../spec_helper', __FILE__)
6
- require 'fog'
7
- require 'chef/knife/bootstrap'
8
- require 'chef/knife/bootstrap_windows_winrm'
9
-
10
- describe Chef::Knife::OpenstackServerCreate do
11
- before do
12
-
13
- @openstack_connection = double(Fog::Compute::OpenStack)
14
- @openstack_connection.stub_chain(:flavors, :find).and_return double('flavor', {:id => 'flavor_id'})
15
- @openstack_connection.stub_chain(:images, :find).and_return double('image', {:id => 'image_id'})
16
- @openstack_connection.stub_chain(:addresses).and_return [double('addresses', {
17
- :instance_id => nil,
18
- :ip => '111.111.111.111',
19
- :fixed_ip => true
20
- })]
21
-
22
- @knife_openstack_create = Chef::Knife::OpenstackServerCreate.new
23
- @knife_openstack_create.initial_sleep_delay = 0
24
- @knife_openstack_create.stub(:tcp_test_ssh).and_return(true)
25
- @knife_openstack_create.stub(:tcp_test_winrm).and_return(true)
26
-
27
- {
28
- :image => 'image',
29
- :openstack_username => 'openstack_username',
30
- :openstack_password => 'openstack_password',
31
- :openstack_auth_url => 'openstack_auth_url',
32
- :server_create_timeout => 1000
33
- }.each do |key, value|
34
- Chef::Config[:knife][key] = value
35
- end
36
-
37
- @knife_openstack_create.stub(:msg_pair)
38
- @knife_openstack_create.stub(:puts)
39
- @knife_openstack_create.stub(:print)
40
-
41
- @openstack_servers = double()
42
- @new_openstack_server = double()
43
-
44
- @openstack_server_attribs = { :name => 'Mock Server',
45
- :id => 'id-123456',
46
- :key_name => 'key_name',
47
- :flavor => 'flavor_id',
48
- :image => 'image_id',
49
- :availability_zone => 'zone1',
50
- :addresses => {
51
- 'foo' => [{'addr' => '34.56.78.90'}],
52
- 'public' => [{'addr' => '75.101.253.10'}],
53
- 'private' => [{'addr' => '10.251.75.20'}]
54
- },
55
- :password => 'password'
56
- }
57
-
58
- @openstack_server_attribs.each_pair do |attrib, value|
59
- @new_openstack_server.stub(attrib).and_return(value)
60
- end
61
- end
23
+ require 'chef/knife/openstack_server_create'
24
+ require 'support/shared_examples_for_servercreatecommand'
25
+ require 'support/shared_examples_for_command'
62
26
 
63
- describe "options" do
64
- before do
65
- @options = @knife_openstack_create.options
66
- end
27
+ describe Chef::Knife::Cloud::OpenstackServerCreate do
28
+ create_instance = Chef::Knife::Cloud::OpenstackServerCreate.new
29
+ create_instance.define_singleton_method(:post_connection_validations){}
67
30
 
68
- it "ensures default options" do
69
- @options[:bootstrap_protocol][:default].should == nil
70
- @options[:distro][:default].should == 'chef-full'
71
- @options[:availability_zone][:default].should == nil
72
- @options[:metadata][:default].should == nil
73
- @options[:floating_ip][:default].should == '-1'
74
- @options[:host_key_verify][:default].should == true
75
- @options[:private_network][:default].should == false
76
- @options[:network][:default].should == true
77
- @options[:bootstrap_network][:default].should == 'public'
78
- @options[:run_list][:default].should == []
79
- @options[:security_groups][:default].should == ['default']
80
- @options[:server_create_timeout][:default].should == 600
81
- @options[:ssh_port][:default].should == '22'
82
- @options[:ssh_user][:default].should == 'root'
83
- @options[:first_boot_attributes][:default].should == {}
84
- end
31
+ it_behaves_like Chef::Knife::Cloud::Command, Chef::Knife::Cloud::OpenstackServerCreate.new
32
+ it_behaves_like Chef::Knife::Cloud::ServerCreateCommand, create_instance
85
33
 
86
- it "doesn't set an OpenStack endpoint type by default" do
87
- Chef::Config[:knife][:openstack_endpoint_type].should == nil
34
+ describe "#create_service_instance" do
35
+ before(:each) do
36
+ @instance = Chef::Knife::Cloud::OpenstackServerCreate.new
88
37
  end
89
38
 
90
- it "user_data should be empty" do
91
- Chef::Config[:knife][:user_data].should == nil
39
+ it "return OpenstackService instance" do
40
+ expect(@instance.create_service_instance).to be_an_instance_of(Chef::Knife::Cloud::OpenstackService)
92
41
  end
42
+
43
+ it "has custom_arguments as its option" do
44
+ expect(@instance.options.include? :custom_attributes).to be true
45
+ end
93
46
  end
94
47
 
95
- describe "run" do
96
- before do
97
- @openstack_servers.should_receive(:create).and_return(@new_openstack_server)
98
- @openstack_connection.should_receive(:servers).and_return(@openstack_servers)
99
- Fog::Compute::OpenStack.should_receive(:new).and_return(@openstack_connection)
100
- @bootstrap = Chef::Knife::Bootstrap.new
101
- Chef::Knife::Bootstrap.stub(:new).and_return(@bootstrap)
102
- @bootstrap.should_receive(:run)
103
- @knife_openstack_create.config[:run_list] = []
104
- @knife_openstack_create.config[:floating_ip] = '-1'
48
+ describe "#validate_params!" do
49
+ before(:each) do
50
+ @instance = Chef::Knife::Cloud::OpenstackServerCreate.new
51
+ allow(@instance.ui).to receive(:error)
52
+ Chef::Config[:knife][:bootstrap_protocol] = "ssh"
53
+ Chef::Config[:knife][:identity_file] = "identity_file"
54
+ Chef::Config[:knife][:image_os_type] = "linux"
55
+ Chef::Config[:knife][:openstack_ssh_key_id] = "openstack_ssh_key"
105
56
  end
106
57
 
107
- it "Creates an OpenStack instance and bootstraps it" do
108
- @new_openstack_server.should_receive(:wait_for).and_return(true)
109
- @knife_openstack_create.run
58
+ after(:all) do
59
+ Chef::Config[:knife].delete(:bootstrap_protocol)
60
+ Chef::Config[:knife].delete(:identity_file)
61
+ Chef::Config[:knife].delete(:image_os_type)
62
+ Chef::Config[:knife].delete(:openstack_ssh_key_id)
110
63
  end
111
64
 
112
- it "Creates an OpenStack instance for Windows and bootstraps it" do
113
- @bootstrap_win = Chef::Knife::BootstrapWindowsWinrm.new
114
- Chef::Knife::BootstrapWindowsWinrm.stub(:new).and_return(@bootstrap_win)
115
- Chef::Config[:knife][:bootstrap_protocol] = 'winrm'
116
- @new_openstack_server.should_receive(:wait_for).and_return(true)
117
- @knife_openstack_create.run
65
+ it "run sucessfully on all params exist" do
66
+ expect { @instance.validate_params! }.to_not raise_error
118
67
  end
68
+ end
119
69
 
120
- it "creates an OpenStack instance, assigns existing floating ip and bootstraps it" do
121
- @knife_openstack_create.config[:floating_ip] = "111.111.111.111"
122
- @new_openstack_server.should_receive(:wait_for).and_return(true)
123
- @new_openstack_server.should_receive(:associate_address).with('111.111.111.111')
124
- @knife_openstack_create.run
70
+ describe "#before_exec_command" do
71
+ before(:each) do
72
+ @instance = Chef::Knife::Cloud::OpenstackServerCreate.new
73
+ allow(@instance.ui).to receive(:error)
74
+ @instance.config[:chef_node_name] = "chef_node_name"
75
+ Chef::Config[:knife][:image] = "image"
76
+ Chef::Config[:knife][:flavor] = "flavor"
77
+ Chef::Config[:knife][:openstack_security_groups] = "openstack_security_groups"
78
+ Chef::Config[:knife][:server_create_timeout] = "server_create_timeout"
79
+ Chef::Config[:knife][:openstack_ssh_key_id] = "openstack_ssh_key"
80
+ Chef::Config[:knife][:network_ids] = "test_network_id"
81
+ allow(Chef::Config[:knife][:network_ids]).to receive(:map).and_return(Chef::Config[:knife][:network_ids])
82
+ Chef::Config[:knife][:metadata] = "foo=bar"
83
+ end
84
+
85
+ after(:all) do
86
+ Chef::Config[:knife].delete(:image)
87
+ Chef::Config[:knife].delete(:flavor)
88
+ Chef::Config[:knife].delete(:openstack_ssh_key_id)
89
+ Chef::Config[:knife].delete(:openstack_security_groups)
90
+ Chef::Config[:knife].delete(:server_create_timeout)
91
+ Chef::Config[:knife].delete(:metadata)
92
+ end
93
+
94
+ it "set create_options" do
95
+ @instance.service = double
96
+ allow(@instance.service).to receive(:get_image).and_return(get_mock_resource('image'))
97
+ allow(@instance.service).to receive(:get_flavor).and_return(get_mock_resource('flavor'))
98
+ expect(@instance.service).to receive(:create_server_dependencies)
99
+ expect(@instance).to receive(:post_connection_validations)
100
+ @instance.before_exec_command
101
+ expect(@instance.create_options[:server_def][:name]).to be == @instance.config[:chef_node_name]
102
+ expect(@instance.create_options[:server_def][:image_ref]).to be == Chef::Config[:knife][:image]
103
+ expect(@instance.create_options[:server_def][:security_groups]).to be == Chef::Config[:knife][:openstack_security_groups]
104
+ expect(@instance.create_options[:server_def][:flavor_ref]).to be == Chef::Config[:knife][:flavor]
105
+ expect(@instance.create_options[:server_def][:nics]).to be == Chef::Config[:knife][:network_ids]
106
+ expect(@instance.create_options[:server_def][:metadata]).to be == Chef::Config[:knife][:metadata]
107
+ expect(@instance.create_options[:server_create_timeout]).to be == Chef::Config[:knife][:server_create_timeout]
108
+ end
109
+
110
+ it "doesn't set user data in server_def if user_data not specified" do
111
+ @instance.service = double("Chef::Knife::Cloud::OpenstackService", :create_server_dependencies => nil)
112
+ allow(@instance.service).to receive(:get_image).and_return(get_mock_resource('image'))
113
+ allow(@instance.service).to receive(:get_flavor).and_return(get_mock_resource('flavor'))
114
+ expect(@instance).to receive(:post_connection_validations)
115
+ @instance.before_exec_command
116
+ expect(@instance.create_options[:server_def]).to_not include(:user_data)
117
+ end
118
+
119
+ it "sets user data" do
120
+ user_data = "echo 'hello world' >> /tmp/user_data.txt"
121
+ Chef::Config[:knife][:user_data] = user_data
122
+ @instance.service = double("Chef::Knife::Cloud::OpenstackService", :create_server_dependencies => nil)
123
+ allow(@instance.service).to receive(:get_image).and_return(get_mock_resource('image'))
124
+ allow(@instance.service).to receive(:get_flavor).and_return(get_mock_resource('flavor'))
125
+ expect(@instance).to receive(:post_connection_validations)
126
+ @instance.before_exec_command
127
+ expect(@instance.create_options[:server_def][:user_data]).to be == user_data
128
+ end
129
+
130
+ context "with multiple network_ids specified" do
131
+ before(:each) do
132
+ @instance.service = double
133
+ allow(@instance.service).to receive(:get_image).and_return(get_mock_resource('image'))
134
+ allow(@instance.service).to receive(:get_flavor).and_return(get_mock_resource('flavor'))
135
+ expect(@instance.service).to receive(:create_server_dependencies)
136
+ Chef::Config[:knife][:network_ids] = "test_network_id1,test_network_id2"
137
+ allow(Chef::Config[:knife][:network_ids]).to receive(:map).and_return(Chef::Config[:knife][:network_ids].split(","))
138
+ expect(@instance).to receive(:post_connection_validations)
139
+ end
140
+
141
+ it "creates the server_def with multiple nic_ids." do
142
+ @instance.before_exec_command
143
+ expect(@instance.create_options[:server_def][:nics]).to be == ["test_network_id1", "test_network_id2"]
144
+ end
145
+ end
146
+
147
+ it "ensures default value for metadata" do
148
+ options = @instance.options
149
+ expect(options[:metadata][:default]).to be == nil
125
150
  end
126
151
  end
127
152
 
128
- describe "when configuring the bootstrap process" do
129
- before do
130
- @knife_openstack_create.config[:ssh_user] = "ubuntu"
131
- @knife_openstack_create.config[:ssh_port] = "44"
132
- @knife_openstack_create.config[:identity_file] = "~/.ssh/key.pem"
133
- @knife_openstack_create.config[:chef_node_name] = "blarf"
134
- @knife_openstack_create.config[:template_file] = '~/.chef/templates/my-bootstrap.sh.erb'
135
- @knife_openstack_create.config[:distro] = 'ubuntu-10.04-magic-sparkles'
136
- @knife_openstack_create.config[:first_boot_attributes] = {'some_var' => true}
137
- @knife_openstack_create.config[:run_list] = ['role[base]']
153
+ describe "#after_exec_command" do
154
+ before(:each) do
155
+ @instance = Chef::Knife::Cloud::OpenstackServerCreate.new
156
+ allow(@instance).to receive(:msg_pair)
157
+ end
158
+
159
+ after(:all) do
160
+ Chef::Config[:knife].delete(:openstack_floating_ip)
161
+ end
162
+
163
+ it "don't set openstack_floating_ip on missing openstack_floating_ip option" do
164
+ #default openstack_floating_ip is '-1'
165
+ Chef::Config[:knife][:openstack_floating_ip] = "-1"
166
+ @instance.service = Chef::Knife::Cloud::Service.new
167
+ @instance.server = double
168
+ expect(@instance.server).to_not receive(:associate_address)
169
+ allow(@instance.server).to receive(:addresses).and_return({"public"=>[{"version"=>4, "addr"=>"127.0.1.1"}]})
170
+ expect(@instance).to receive(:bootstrap)
171
+ @instance.after_exec_command
172
+ end
173
+
174
+ it "set openstack_floating_ip on openstack_floating_ip option" do
175
+ Chef::Config[:knife][:openstack_floating_ip] = nil
176
+ @instance.service = Chef::Knife::Cloud::Service.new
177
+ @instance.server = double
178
+ allow(@instance.server).to receive(:addresses).and_return({"public"=>[{"version"=>4, "addr"=>"127.0.1.1"}]})
179
+ expect(@instance).to receive(:bootstrap)
180
+ connection = double
181
+ allow(@instance.service).to receive(:connection).and_return(double)
182
+ free_floating = Object.new
183
+ free_floating.define_singleton_method(:fixed_ip) { return nil }
184
+ free_floating.define_singleton_method(:ip) { return "127.0.0.1" }
185
+ expect(@instance.service.connection).to receive(:addresses).and_return([free_floating])
186
+ expect(@instance.server).to receive(:associate_address).with(free_floating.ip)
187
+ @instance.after_exec_command
188
+ end
189
+
190
+ it "raise error on unavailability of free_floating ip" do
191
+ Chef::Config[:knife][:openstack_floating_ip] = nil
192
+ @instance.service = Chef::Knife::Cloud::Service.new
193
+ allow(@instance.ui).to receive(:fatal)
194
+ @instance.server = double
195
+ allow(@instance.server).to receive(:addresses).and_return({"public"=>[{"version"=>4, "addr"=>"127.0.1.1"}]})
196
+ expect(@instance).to_not receive(:bootstrap)
197
+ connection = double
198
+ allow(@instance.service).to receive(:connection).and_return(double)
199
+ free_floating = Object.new
200
+ free_floating.define_singleton_method(:fixed_ip) { return "127.0.0.1" }
201
+ expect(@instance.service.connection).to receive(:addresses).and_return([free_floating])
202
+ expect(@instance.server).to_not receive(:associate_address)
203
+ expect { @instance.after_exec_command }.to raise_error(Chef::Knife::Cloud::CloudExceptions::ServerSetupError, "Unable to assign a Floating IP from allocated IPs.")
204
+ end
205
+ end
138
206
 
139
- @bootstrap = @knife_openstack_create.bootstrap_for_node(@new_openstack_server,
140
- @new_openstack_server.addresses['public'].last['addr'])
207
+ describe "#before_bootstrap" do
208
+ before(:each) do
209
+ @instance = Chef::Knife::Cloud::OpenstackServerCreate.new
210
+ @instance.server = double
211
+ # default bootstrap_network is public
212
+ @instance.config[:bootstrap_network] = "public"
213
+ # default no network is true
214
+ @instance.config[:network] = true
215
+ Chef::Config[:knife][:ssh_password] = "config_ssh_password"
141
216
  end
142
217
 
143
- it "should set the bootstrap 'name argument' to the hostname of the OpenStack server" do
144
- @bootstrap.name_args.should == ['75.101.253.10']
218
+ after(:each) do
219
+ Chef::Config[:knife].delete(:ssh_password)
145
220
  end
146
221
 
147
- it "configures sets the bootstrap's run_list" do
148
- @bootstrap.config[:run_list].should == ['role[base]']
222
+ context "when no-network option specified" do
223
+ before(:each) { @instance.config[:network] = false }
224
+
225
+ it "set public ip as a bootstrap ip if both public and private ip available" do
226
+ allow(@instance.server).to receive(:addresses).and_return({"private"=>[{"version"=>4, "addr"=>"127.0.0.1"}], "public"=>[{"version"=>4, "addr"=>"127.0.0.2"}]})
227
+ @instance.before_bootstrap
228
+ expect(@instance.config[:bootstrap_ip_address]).to be == "127.0.0.2"
229
+ end
230
+
231
+ it "set private-ip as a bootstrap ip if private ip is available" do
232
+ allow(@instance.server).to receive(:addresses).and_return({"private"=>[{"version"=>4, "addr"=>"127.0.0.1"}]})
233
+ @instance.before_bootstrap
234
+ expect(@instance.config[:bootstrap_ip_address]).to be == "127.0.0.1"
235
+ end
236
+
237
+ it "set available ip as a bootstrap ip if no public, private ip available" do
238
+ allow(@instance.server).to receive(:addresses).and_return({1=>[{"version"=>4, "addr"=>"127.0.0.1"}]})
239
+ @instance.before_bootstrap
240
+ expect(@instance.config[:bootstrap_ip_address]).to be == "127.0.0.1"
241
+ end
149
242
  end
150
243
 
151
- it "configures the bootstrap to use the correct ssh_user login" do
152
- @bootstrap.config[:ssh_user].should == 'ubuntu'
244
+ it "set bootstrap_ip" do
245
+ allow(@instance.server).to receive(:addresses).and_return({"public"=>[{"version"=>4, "addr"=>"127.0.0.1"}]})
246
+ @instance.before_bootstrap
247
+ expect(@instance.config[:bootstrap_ip_address]).to be == "127.0.0.1"
153
248
  end
154
249
 
155
- it "configures the bootstrap to use the correct ssh_port" do
156
- @bootstrap.config[:ssh_port].should == '44'
250
+ it "set private-ip as a bootstrap-ip if private-network option set" do
251
+ allow(@instance.server).to receive(:addresses).and_return({"private"=>[{"version"=>4, "addr"=>"127.0.0.1"}], "public"=>[{"version"=>4, "addr"=>"127.0.0.2"}]})
252
+ @instance.config[:private_network] = true
253
+ @instance.before_bootstrap
254
+ expect(@instance.config[:bootstrap_ip_address]).to be == "127.0.0.1"
157
255
  end
158
256
 
159
- it "configures the bootstrap to use the correct ssh identity file" do
160
- @bootstrap.config[:identity_file].should == "~/.ssh/key.pem"
257
+ it "raise error on nil bootstrap_ip" do
258
+ allow(@instance.ui).to receive(:error)
259
+
260
+ allow(@instance.server).to receive(:addresses).and_return({"public"=>[{"version"=>4, "addr"=>nil}]})
261
+ expect { @instance.before_bootstrap }.to raise_error(Chef::Knife::Cloud::CloudExceptions::BootstrapError, "No IP address available for bootstrapping.")
262
+ end
263
+
264
+ it "set public ip as default bootstrap network is public" do
265
+ allow(@instance.server).to receive(:addresses).and_return({"private"=>[{"version"=>4, "addr"=>"127.0.0.1"}], "public"=>[{"version"=>4, "addr"=>"127.0.0.2"}]})
266
+ @instance.before_bootstrap
267
+ expect(@instance.config[:bootstrap_ip_address]).to be == "127.0.0.2"
161
268
  end
162
269
 
163
- it "configures the bootstrap to use the configured node name if provided" do
164
- @bootstrap.config[:chef_node_name].should == 'blarf'
270
+ it "configures the bootstrap to use alternate network" do
271
+ allow(@instance.server).to receive(:addresses).and_return({"foo"=>[{"version"=>1, "addr"=>"127.0.0.1"}], "private"=>[{"version"=>4, "addr"=>"127.0.0.2"}], "public"=>[{"version"=>4, "addr"=>"127.0.0.3"}]})
272
+ @instance.config[:bootstrap_network] = 'foo'
273
+ @instance.before_bootstrap
274
+ expect(@instance.config[:bootstrap_ip_address]).to be == "127.0.0.1"
165
275
  end
166
276
 
167
277
  it "configures the bootstrap to use the server password" do
168
- @bootstrap.config[:ssh_password].should == 'password'
278
+ allow(@instance.server).to receive(:addresses).and_return({"public"=>[{"version"=>4, "addr"=>"127.0.0.1"}]})
279
+ Chef::Config[:knife].delete(:ssh_password)
280
+ server_password = "adFRjk1089"
281
+ allow(@instance.server).to receive(:password).and_return(server_password)
282
+ @instance.before_bootstrap
283
+ expect(@instance.config[:ssh_password]).to be == server_password
169
284
  end
170
285
 
171
286
  it "configures the bootstrap to use the config ssh password" do
172
- @knife_openstack_create.config[:ssh_password] = 'testing123'
173
-
174
- bootstrap = @knife_openstack_create.bootstrap_for_node(@new_openstack_server,
175
- @new_openstack_server.addresses['public'].last['addr'])
287
+ allow(@instance.server).to receive(:addresses).and_return({"public"=>[{"version"=>4, "addr"=>"127.0.0.1"}]})
288
+ server_password = "config_ssh_password"
289
+ Chef::Config[:knife][:ssh_password] = server_password
290
+ expect(@instance.server).to_not receive(:password)
291
+ @instance.before_bootstrap
292
+ expect(@instance.config[:ssh_password]).to be == server_password
293
+ end
294
+ end
176
295
 
177
- bootstrap.config[:ssh_password].should == 'testing123'
296
+ describe "#post_connection_validations" do
297
+ before(:each) do
298
+ @instance = Chef::Knife::Cloud::OpenstackServerCreate.new
299
+ allow(@instance.ui).to receive(:error)
178
300
  end
179
301
 
180
- it "configures the bootstrap to use the OpenStack server id if no explicit node name is set" do
181
- @knife_openstack_create.config[:chef_node_name] = nil
182
-
183
- bootstrap = @knife_openstack_create.bootstrap_for_node(@new_openstack_server,
184
- @new_openstack_server.addresses['public'].last['addr'])
185
- bootstrap.config[:chef_node_name].should == @new_openstack_server.name
302
+ it "raise error on invalid image" do
303
+ allow(@instance).to receive(:is_flavor_valid?).and_return(true)
304
+ allow(@instance).to receive(:is_floating_ip_valid?).and_return(true)
305
+ expect(@instance).to receive(:is_image_valid?).and_return(false)
306
+ expect { @instance.post_connection_validations }.to raise_error(Chef::Knife::Cloud::CloudExceptions::ValidationError, " You have not provided a valid image ID. Please note the options for this value are -I or --image..")
186
307
  end
187
308
 
188
- it "configures the bootstrap to use prerelease versions of chef if specified" do
189
- @bootstrap.config[:prerelease].should be_false
190
-
191
- @knife_openstack_create.config[:prerelease] = true
192
-
193
- bootstrap = @knife_openstack_create.bootstrap_for_node(@new_openstack_server,
194
- @new_openstack_server.addresses['public'].last['addr'])
195
- bootstrap.config[:prerelease].should be_true
309
+ it "raise error on invalid flavor" do
310
+ allow(@instance).to receive(:is_image_valid?).and_return(true)
311
+ allow(@instance).to receive(:is_floating_ip_valid?).and_return(true)
312
+ expect(@instance).to receive(:is_flavor_valid?).and_return(false)
313
+ expect { @instance.post_connection_validations }.to raise_error(Chef::Knife::Cloud::CloudExceptions::ValidationError, " You have not provided a valid flavor ID. Please note the options for this value are -f or --flavor..")
196
314
  end
197
315
 
198
- it "configures the bootstrap to use the desired distro-specific bootstrap script" do
199
- @bootstrap.config[:distro].should == 'ubuntu-10.04-magic-sparkles'
316
+ it "raise error on invalid floating IP" do
317
+ allow(@instance).to receive(:is_flavor_valid?).and_return(true)
318
+ allow(@instance).to receive(:is_image_valid?).and_return(true)
319
+ expect(@instance).to receive(:is_floating_ip_valid?).and_return(false)
320
+ expect { @instance.post_connection_validations }.to raise_error(Chef::Knife::Cloud::CloudExceptions::ValidationError, " You have either requested an invalid floating IP address or none are available..")
200
321
  end
322
+ end
201
323
 
202
- it "configures the bootstrap to use sudo" do
203
- @bootstrap.config[:use_sudo].should be_true
324
+ describe "#is_floating_ip_valid?" do
325
+ before(:each) do
326
+ @instance = Chef::Knife::Cloud::OpenstackServerCreate.new
327
+ # Default value
328
+ Chef::Config[:knife][:openstack_floating_ip] = "-1"
329
+ @instance.service = double
204
330
  end
205
331
 
206
- it "configures the bootstrap with json attributes" do
207
- @bootstrap.config[:first_boot_attributes]['some_var'].should be_true
332
+ after(:all) do
333
+ Chef::Config[:knife].delete(:openstack_floating_ip)
208
334
  end
209
335
 
210
- it "configured the bootstrap to use the desired template" do
211
- @bootstrap.config[:template_file].should == '~/.chef/templates/my-bootstrap.sh.erb'
336
+ it "returns true for default" do
337
+ expect(@instance.is_floating_ip_valid?).to be true
212
338
  end
213
339
 
214
- it "configured the bootstrap to set an openstack hint (via Chef::Config)" do
215
- Chef::Config[:knife][:hints]['openstack'].should_not be_nil
340
+ it "returns false if no floating IPs" do
341
+ Chef::Config[:knife].delete(:openstack_floating_ip)
342
+ expect(@instance.service).to receive_message_chain(:connection, :addresses).and_return([])
343
+ expect(@instance.is_floating_ip_valid?).to be false
344
+ end
345
+
346
+ context "when floating ip requested without value" do
347
+ it "returns true if fixed_ip is nil" do
348
+ Chef::Config[:knife][:openstack_floating_ip] = nil
349
+ obj = Object.new
350
+ obj.define_singleton_method(:fixed_ip){nil}
351
+ expect(@instance.service).to receive_message_chain(:connection, :addresses).and_return([obj])
352
+ expect(@instance.is_floating_ip_valid?).to be true
353
+ end
216
354
  end
217
- end
218
355
 
219
- describe "when configuring the bootstrap process with private networks" do
220
- before do
221
- @knife_openstack_create.config[:private_network] = true
356
+ context "when floating ip requested with value" do
357
+ before {Chef::Config[:knife][:openstack_floating_ip] = "127.0.0.1"}
358
+ after {Chef::Config[:knife].delete(:openstack_floating_ip)}
222
359
 
223
- @bootstrap = @knife_openstack_create.bootstrap_for_node(@new_openstack_server,
224
- @new_openstack_server.addresses['private'].last['addr'])
225
- end
360
+ it "returns true if requested floating IP is exist" do
361
+ obj = Object.new
362
+ obj.define_singleton_method(:ip){return "127.0.0.1"}
363
+ expect(@instance.service).to receive_message_chain(:connection, :addresses).and_return([obj])
364
+ expect(@instance.is_floating_ip_valid?).to be true
365
+ end
226
366
 
227
- it "configures the bootstrap to use private network" do
228
- @bootstrap.name_args.should == ['10.251.75.20']
367
+ it "returns false if requested floating IP does not exist" do
368
+ obj = Object.new
369
+ obj.define_singleton_method(:ip){return "127.0.1.1"}
370
+ expect(@instance.service).to receive_message_chain(:connection, :addresses).and_return([obj])
371
+ expect(@instance.is_floating_ip_valid?).to be false
372
+ end
229
373
  end
230
374
  end
231
375
 
232
- describe "when configuring the bootstrap process with alternate networks" do
233
- before do
234
- @knife_openstack_create.config[:bootstrap_network] = 'foo'
376
+ describe "#is_image_valid?" do
377
+ before(:each) do
378
+ @instance = Chef::Knife::Cloud::OpenstackServerCreate.new
379
+ @instance.service = double
380
+ Chef::Config[:knife][:image] = "image_id"
381
+ end
235
382
 
236
- @bootstrap = @knife_openstack_create.bootstrap_for_node(@new_openstack_server,
237
- @new_openstack_server.addresses['foo'].last['addr'])
383
+ after(:each) do
384
+ Chef::Config[:knife].delete(:image)
238
385
  end
239
386
 
240
- it "configures the bootstrap to use alternate network" do
241
- @bootstrap.name_args.should == ['34.56.78.90']
387
+ it "returns false on invalid image" do
388
+ expect(@instance.service).to receive_message_chain(:get_image).and_return(nil)
389
+ expect(@instance.is_image_valid?).to be false
390
+ end
391
+
392
+ it "returns true on valid image" do
393
+ expect(@instance.service).to receive_message_chain(:get_image).and_return("image")
394
+ expect(@instance.is_image_valid?).to be true
242
395
  end
243
396
  end
244
397
 
245
- describe "when configuring the bootstrap process with no networks" do
246
- before do
247
- @knife_openstack_create.config[:network] = false
398
+ describe "#is_flavor_valid?" do
399
+ before(:each) do
400
+ @instance = Chef::Knife::Cloud::OpenstackServerCreate.new
401
+ @instance.service = double
402
+ Chef::Config[:knife][:flavor] = "flavor"
403
+ end
248
404
 
249
- @bootstrap = @knife_openstack_create.bootstrap_for_node(@new_openstack_server,
250
- @new_openstack_server.addresses['public'].last['addr'])
405
+ after(:each) do
406
+ Chef::Config[:knife].delete(:flavor)
407
+ end
408
+
409
+ it "returns false on invalid flavor" do
410
+ expect(@instance.service).to receive_message_chain(:get_flavor).and_return(nil)
411
+ expect(@instance.is_flavor_valid?).to be false
251
412
  end
252
413
 
253
- it "configures the bootstrap to use public network since none specified" do
254
- @bootstrap.name_args.should == ['75.101.253.10']
414
+ it "returns true on valid flavor" do
415
+ expect(@instance.service).to receive_message_chain(:get_flavor).and_return("flavor")
416
+ expect(@instance.is_flavor_valid?).to be true
255
417
  end
256
418
  end
257
419
  end