memcached (openstack) is no longer in use
[mirror/dsa-puppet.git] / 3rdparty / modules / nova / spec / unit / provider / nova_spec.rb
1 require 'puppet'
2 require 'spec_helper'
3 require 'puppet/provider/nova'
4 require 'rspec/mocks'
5
6 describe Puppet::Provider::Nova do
7
8   def klass
9     described_class
10   end
11
12   let :credential_hash do
13     {
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',
20     }
21   end
22
23   let :auth_endpoint do
24     'https://192.168.56.210:35357/v2.0/'
25   end
26
27   let :credential_error do
28     /Nova types will not work/
29   end
30
31   after :each do
32     klass.reset
33   end
34
35   describe 'when determining credentials' do
36
37     it 'should fail if config is empty' do
38       conf = {}
39       klass.expects(:nova_conf).returns(conf)
40       expect do
41         klass.nova_credentials
42       end.to raise_error(Puppet::Error, credential_error)
43     end
44
45     it 'should fail if config does not have keystone_authtoken section.' do
46       conf = {'foo' => 'bar'}
47       klass.expects(:nova_conf).returns(conf)
48       expect do
49         klass.nova_credentials
50       end.to raise_error(Puppet::Error, credential_error)
51     end
52
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)
56       expect do
57        klass.nova_credentials
58       end.to raise_error(Puppet::Error, credential_error)
59     end
60
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
65     end
66
67   end
68
69   describe 'when invoking the nova cli' do
70
71     it 'should set auth credentials in the environment' do
72       authenv = {
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'],
77       }
78       klass.expects(:get_nova_credentials).with().returns(credential_hash)
79       klass.expects(:withenv).with(authenv)
80       klass.auth_nova('test_retries')
81     end
82
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')
91       end
92     end
93
94   end
95
96   describe 'when parse a string line' do
97     it 'should return the same string' do
98       res = klass.str2hash("zone1")
99       res.should == "zone1"
100     end
101
102     it 'should return the string without quotes' do
103       res = klass.str2hash("'zone1'")
104       res.should == "zone1"
105     end
106
107     it 'should return the same string' do
108       res = klass.str2hash("z o n e1")
109       res.should == "z o n e1"
110     end
111
112     it 'should return a hash' do
113       res = klass.str2hash("a=b")
114       res.should == {"a"=>"b"}
115     end
116
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"}
120     end
121
122     it 'should return the same string' do
123       res = klass.str2list("zone1")
124       res.should == "zone1"
125     end
126
127     it 'should return a list of strings' do
128       res = klass.str2list("zone1, zone2")
129       res.should == ["zone1", "zone2"]
130     end
131
132
133     it 'should return a list of strings' do
134       res = klass.str2list("zo n e1,    zone2    ")
135       res.should == ["zo n e1", "zone2"]
136     end
137
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"}
141     end
142
143     it 'should return a single hash' do
144       res = klass.str2list("a=b")
145       res.should == {"a"=>"b"}
146     end
147   end
148
149   describe 'when parsing cli output' do
150
151     it 'should return a list with hashes' do
152       output = <<-EOT
153 +----+-------+-------------------+
154 | Id | Name  | Availability Zone |
155 +----+-------+-------------------+
156 | 1  | haha  | haha2             |
157 | 2  | haha2 | -                 |
158 +----+-------+-------------------+
159       EOT
160       res = klass.cliout2list(output)
161       res.should == [{"Id"=>"1", "Name"=>"haha", "Availability Zone"=>"haha2"},
162                      {"Id"=>"2", "Name"=>"haha2", "Availability Zone"=>""}]
163     end
164
165     it 'should return a list with hashes' do
166       output = <<-EOT
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 +----+-------+-------------------+-------+--------------------------------------------------+
172 EOT
173       res = klass.cliout2list(output)
174       res.should == [{"Id"=>"16",
175                        "Name"=>"agg94",
176                        "Availability Zone"=>"my_-zone1",
177                        "Hosts"=>"",
178                        "Metadata"=> {
179                          "a"=>"b",
180                          "availability_zone"=>" my_-zone1",
181                          "x_q-r"=>"y"
182                          }
183                      }]
184     end
185
186     it 'should return a empty list' do
187       output = <<-EOT
188 +----+------+-------------------+
189 | Id | Name | Availability Zone |
190 +----+------+-------------------+
191 +----+------+-------------------+
192       EOT
193       res = klass.cliout2list(output)
194       res.should == []
195     end
196
197     it 'should return a empty list because no input available' do
198       output = <<-EOT
199       EOT
200       res = klass.cliout2list(output)
201       res.should == []
202     end
203
204     it 'should return a list with hashes' do
205       output = <<-EOT
206 +----+----------------+-------------------+
207 | Id | Name           | Availability Zone |
208 +----+----------------+-------------------+
209 | 6  | my             | zone1             |
210 | 8  | my2            | -                 |
211 +----+----------------+-------------------+
212       EOT
213       res = klass.cliout2list(output)
214       res.should == [{"Id"=>"6", "Name"=>"my", "Availability Zone"=>"zone1"},
215                      {"Id"=>"8", "Name"=>"my2", "Availability Zone"=>""}]
216     end
217   end
218
219   describe 'when handling cli output' do
220     it 'should return the availble Id' do
221       output = <<-EOT
222 +----+-------+-------------------+
223 | Id | Name  | Availability Zone |
224 +----+-------+-------------------+
225 | 1  | haha  | haha2             |
226 | 2  | haha2 | -                 |
227 +----+-------+-------------------+
228       EOT
229       klass.expects(:auth_nova).returns(output)
230       res = klass.nova_aggregate_resources_get_name_by_id("haha2")
231       res.should eql(2)
232     end
233
234     it 'should return nil because given name is not available' do
235       output = <<-EOT
236 +----+-------+-------------------+
237 | Id | Name  | Availability Zone |
238 +----+-------+-------------------+
239 | 1  | haha  | haha2             |
240 | 2  | haha2 | -                 |
241 +----+-------+-------------------+
242       EOT
243       klass.expects(:auth_nova).returns(output)
244       res = klass.nova_aggregate_resources_get_name_by_id("notavailable")
245       res.should eql(nil)
246     end
247   end
248
249   describe 'when getting details for given Id' do
250     it 'should return a Hash with the details' do
251       output = <<-EOT
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 +----+-------+-------------------+-------+--------------------------------------------------+
257         EOT
258       klass.expects(:auth_nova).returns(output)
259       res = klass.nova_aggregate_resources_attr(16)
260       res.should == {
261         "Id"=>"16",
262         "Name"=>"agg94",
263         "Availability Zone"=>"my_-zone1",
264         "Hosts"=>[],
265         "Metadata"=>{
266           "a"=>"b",
267           "availability_zone"=>" my_-zone1",
268           "x_q-r"=>"y"
269         }
270       }
271     end
272
273   end
274 end