3 require 'puppet/provider/nova'
6 describe Puppet::Provider::Nova do
12 let :credential_hash do
14 'auth_host' => '192.168.56.210',
15 'auth_port' => '35357',
16 'auth_protocol' => 'https',
17 'admin_tenant_name' => 'admin_tenant',
18 'admin_user' => 'admin',
19 'admin_password' => 'password',
24 'https://192.168.56.210:35357/v2.0/'
27 let :credential_error do
28 /Nova types will not work/
35 describe 'when determining credentials' do
37 it 'should fail if config is empty' do
39 klass.expects(:nova_conf).returns(conf)
41 klass.nova_credentials
42 end.to raise_error(Puppet::Error, credential_error)
45 it 'should fail if config does not have keystone_authtoken section.' do
46 conf = {'foo' => 'bar'}
47 klass.expects(:nova_conf).returns(conf)
49 klass.nova_credentials
50 end.to raise_error(Puppet::Error, credential_error)
53 it 'should fail if config does not contain all auth params' do
54 conf = {'keystone_authtoken' => {'invalid_value' => 'foo'}}
55 klass.expects(:nova_conf).returns(conf)
57 klass.nova_credentials
58 end.to raise_error(Puppet::Error, credential_error)
61 it 'should use specified host/port/protocol in the auth endpoint' do
62 conf = {'keystone_authtoken' => credential_hash}
63 klass.expects(:nova_conf).returns(conf)
64 klass.get_auth_endpoint.should == auth_endpoint
69 describe 'when invoking the nova cli' do
71 it 'should set auth credentials in the environment' do
73 :OS_AUTH_URL => auth_endpoint,
74 :OS_USERNAME => credential_hash['admin_user'],
75 :OS_TENANT_NAME => credential_hash['admin_tenant_name'],
76 :OS_PASSWORD => credential_hash['admin_password'],
78 klass.expects(:get_nova_credentials).with().returns(credential_hash)
79 klass.expects(:withenv).with(authenv)
80 klass.auth_nova('test_retries')
83 ['[Errno 111] Connection refused',
84 '(HTTP 400)'].reverse.each do |valid_message|
85 it "should retry when nova cli returns with error #{valid_message}" do
86 klass.expects(:get_nova_credentials).with().returns({})
87 klass.expects(:sleep).with(10).returns(nil)
88 klass.expects(:nova).twice.with(['test_retries']).raises(
89 Exception, valid_message).then.returns('')
90 klass.auth_nova('test_retries')
96 describe 'when parse a string line' do
97 it 'should return the same string' do
98 res = klass.str2hash("zone1")
102 it 'should return the string without quotes' do
103 res = klass.str2hash("'zone1'")
104 res.should == "zone1"
107 it 'should return the same string' do
108 res = klass.str2hash("z o n e1")
109 res.should == "z o n e1"
112 it 'should return a hash' do
113 res = klass.str2hash("a=b")
114 res.should == {"a"=>"b"}
117 it 'should return a hash with containing spaces' do
118 res = klass.str2hash("a b = c d")
119 res.should == {"a b "=>" c d"}
122 it 'should return the same string' do
123 res = klass.str2list("zone1")
124 res.should == "zone1"
127 it 'should return a list of strings' do
128 res = klass.str2list("zone1, zone2")
129 res.should == ["zone1", "zone2"]
133 it 'should return a list of strings' do
134 res = klass.str2list("zo n e1, zone2 ")
135 res.should == ["zo n e1", "zone2"]
138 it 'should return a hash with multiple keys' do
139 res = klass.str2list("a=b, c=d")
140 res.should == {"a"=>"b", "c"=>"d"}
143 it 'should return a single hash' do
144 res = klass.str2list("a=b")
145 res.should == {"a"=>"b"}
149 describe 'when parsing cli output' do
151 it 'should return a list with hashes' do
153 +----+-------+-------------------+
154 | Id | Name | Availability Zone |
155 +----+-------+-------------------+
158 +----+-------+-------------------+
160 res = klass.cliout2list(output)
161 res.should == [{"Id"=>"1", "Name"=>"haha", "Availability Zone"=>"haha2"},
162 {"Id"=>"2", "Name"=>"haha2", "Availability Zone"=>""}]
165 it 'should return a list with hashes' do
167 +----+-------+-------------------+-------+--------------------------------------------------+
168 | Id | Name | Availability Zone | Hosts | Metadata |
169 +----+-------+-------------------+-------+--------------------------------------------------+
170 | 16 | agg94 | my_-zone1 | | 'a=b', 'availability_zone= my_-zone1', 'x_q-r=y' |
171 +----+-------+-------------------+-------+--------------------------------------------------+
173 res = klass.cliout2list(output)
174 res.should == [{"Id"=>"16",
176 "Availability Zone"=>"my_-zone1",
180 "availability_zone"=>" my_-zone1",
186 it 'should return a empty list' do
188 +----+------+-------------------+
189 | Id | Name | Availability Zone |
190 +----+------+-------------------+
191 +----+------+-------------------+
193 res = klass.cliout2list(output)
197 it 'should return a empty list because no input available' do
200 res = klass.cliout2list(output)
204 it 'should return a list with hashes' do
206 +----+----------------+-------------------+
207 | Id | Name | Availability Zone |
208 +----+----------------+-------------------+
211 +----+----------------+-------------------+
213 res = klass.cliout2list(output)
214 res.should == [{"Id"=>"6", "Name"=>"my", "Availability Zone"=>"zone1"},
215 {"Id"=>"8", "Name"=>"my2", "Availability Zone"=>""}]
219 describe 'when handling cli output' do
220 it 'should return the availble Id' do
222 +----+-------+-------------------+
223 | Id | Name | Availability Zone |
224 +----+-------+-------------------+
227 +----+-------+-------------------+
229 klass.expects(:auth_nova).returns(output)
230 res = klass.nova_aggregate_resources_get_name_by_id("haha2")
234 it 'should return nil because given name is not available' do
236 +----+-------+-------------------+
237 | Id | Name | Availability Zone |
238 +----+-------+-------------------+
241 +----+-------+-------------------+
243 klass.expects(:auth_nova).returns(output)
244 res = klass.nova_aggregate_resources_get_name_by_id("notavailable")
249 describe 'when getting details for given Id' do
250 it 'should return a Hash with the details' do
252 +----+-------+-------------------+-------+--------------------------------------------------+
253 | Id | Name | Availability Zone | Hosts | Metadata |
254 +----+-------+-------------------+-------+--------------------------------------------------+
255 | 16 | agg94 | my_-zone1 | | 'a=b', 'availability_zone= my_-zone1', 'x_q-r=y' |
256 +----+-------+-------------------+-------+--------------------------------------------------+
258 klass.expects(:auth_nova).returns(output)
259 res = klass.nova_aggregate_resources_attr(16)
263 "Availability Zone"=>"my_-zone1",
267 "availability_zone"=>" my_-zone1",