1 # TODO: This should be extracted into openstacklib during the Kilo cycle
2 # Load libraries from aviator here to simulate how they live together in a real puppet run
3 $LOAD_PATH.push(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'modules', 'aviator', 'lib'))
6 require 'puppet/provider/openstack'
9 describe Puppet::Provider::Openstack do
12 ENV['OS_USERNAME'] = nil
13 ENV['OS_PASSWORD'] = nil
14 ENV['OS_TENANT_NAME'] = nil
15 ENV['OS_AUTH_URL'] = nil
19 Puppet::Type.newtype(:test_resource) do
20 newparam(:name, :namevar => true)
26 shared_examples 'authenticating with environment variables' do
27 it 'makes a successful request' do
28 ENV['OS_USERNAME'] = 'test'
29 ENV['OS_PASSWORD'] = 'abc123'
30 ENV['OS_TENANT_NAME'] = 'test'
31 ENV['OS_AUTH_URL'] = 'http://127.0.0.1:35357/v2.0'
32 if provider.class == Class
33 provider.stubs(:openstack)
34 .with('project', 'list', '--quiet', '--format', 'csv', [[ '--long' ]])
35 .returns('"ID","Name","Description","Enabled"
36 "1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True
39 provider.class.stubs(:openstack)
40 .with('project', 'list', '--quiet', '--format', 'csv', [[ '--long' ]])
41 .returns('"ID","Name","Description","Enabled"
42 "1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True
45 response = provider.request('project', 'list', nil, nil, '--long' )
46 expect(response.first[:description]).to match /Test tenant/
50 shared_examples 'it has no credentials' do
51 it 'fails to authenticate' do
52 expect{ provider.request('project', 'list', nil, nil, '--long') }.to raise_error(Puppet::Error::OpenstackAuthInputError, /No credentials provided/)
56 describe '#request' do
58 context 'with valid password credentials in parameters' do
59 let(:resource_attrs) do
61 :name => 'stubresource',
64 'password' => 'abc123',
65 'tenant_name' => 'test',
66 'auth_url' => 'http://127.0.0.1:5000/v2.0',
71 Puppet::Provider::Openstack.new(type.new(resource_attrs))
74 it 'makes a successful request' do
75 provider.class.stubs(:openstack)
76 .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'test', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
77 .returns('"ID","Name","Description","Enabled"
78 "1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True
80 response = provider.request('project', 'list', nil, resource_attrs[:auth], '--long')
81 expect(response.first[:description]).to match /Test tenant/
85 context 'with valid openrc file in parameters' do
86 mock = "export OS_USERNAME='test'\nexport OS_PASSWORD='abc123'\nexport OS_TENANT_NAME='test'\nexport OS_AUTH_URL='http://127.0.0.1:5000/v2.0'"
87 let(:resource_attrs) do
89 :name => 'stubresource',
91 'openrc' => '/root/openrc'
96 Puppet::Provider::Openstack.new(type.new(resource_attrs))
99 it 'makes a successful request' do
100 File.expects(:open).with('/root/openrc').returns(StringIO.new(mock))
101 provider.class.stubs(:openstack)
102 .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'test', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
103 .returns('"ID","Name","Description","Enabled"
104 "1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True
106 response = provider.request('project', 'list', nil, resource_attrs[:auth], '--long')
107 expect(response.first[:description]).to match /Test tenant/
111 context 'with valid service token in parameters' do
112 let(:resource_attrs) do
114 :name => 'stubresource',
116 'token' => 'secrettoken',
117 'auth_url' => 'http://127.0.0.1:5000/v2.0'
122 Puppet::Provider::Openstack.new(type.new(resource_attrs))
125 it 'makes a successful request' do
126 provider.class.stubs(:openstack)
127 .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-token', 'secrettoken', '--os-url', 'http://127.0.0.1:5000/v2.0']])
128 .returns('"ID","Name","Description","Enabled"
129 "1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True
131 response = provider.request('project', 'list', nil, resource_attrs[:auth], '--long')
132 expect(response.first[:description]).to match /Test tenant/
135 it 'makes a successful show request' do
136 provider.class.stubs(:openstack)
137 .with('project', 'show', '--format', 'shell', [['test', '--os-token', 'secrettoken', '--os-url', 'http://127.0.0.1:5000/v2.0']])
138 .returns('ID="1cb05cfed7c24279be884ba4f6520262"
140 Description="Test Tenant"
143 response = provider.request('project', 'show', 'test', resource_attrs[:auth])
144 expect(response[:description]).to match /Test Tenant/
145 expect(response[:id]).to match /1cb05cfed7c24279be884ba4f6520262/
146 expect(response[:name]).to match /test/
147 expect(response[:enabled]).to match /True/
152 context 'with valid password credentials in environment variables' do
153 it_behaves_like 'authenticating with environment variables' do
154 let(:resource_attrs) do
156 :name => 'stubresource',
160 Puppet::Provider::Openstack.new(type.new(resource_attrs))
165 context 'with no valid credentials' do
166 it_behaves_like 'it has no credentials' do
167 let(:resource_attrs) do
169 :name => 'stubresource',
173 Puppet::Provider::Openstack.new(type.new(resource_attrs))
178 context 'it retries on connection errors' do
179 let(:resource_attrs) do
181 :name => 'stubresource',
183 'username' => 'test',
184 'password' => 'abc123',
185 'tenant_name' => 'test',
186 'auth_url' => 'http://127.0.0.1:5000/v2.0',
191 Puppet::Provider::Openstack.new(type.new(resource_attrs))
194 provider.class.stubs(:openstack)
195 .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'test', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
196 .raises(Puppet::ExecutionFailure, 'Unable to establish connection')
199 provider.class.expects(:sleep).with(2).returns(nil)
200 provider.request('project', 'list', nil, resource_attrs[:auth], '--long')
206 describe '::request' do
208 context 'with valid password credentials in environment variables' do
209 it_behaves_like 'authenticating with environment variables' do
210 let(:resource_attrs) do
212 :name => 'stubresource',
216 Puppet::Provider::Openstack.dup
221 context 'with no valid credentials' do
222 it_behaves_like 'it has no credentials' do
223 let(:provider) { Puppet::Provider::Openstack.dup }
229 describe 'parse_csv' do
230 context 'with mixed stderr' do
231 text = "ERROR: Testing\n\"field\",\"test\",1,2,3\n"
232 csv = Puppet::Provider::Openstack.parse_csv(text)
233 it 'should ignore non-CSV text at the beginning of the input' do
234 expect(csv).to be_kind_of(Array)
235 expect(csv[0]).to match_array(['field', 'test', '1', '2', '3'])
236 expect(csv.size).to eq(1)
240 context 'with \r\n line endings' do
241 text = "ERROR: Testing\r\n\"field\",\"test\",1,2,3\r\n"
242 csv = Puppet::Provider::Openstack.parse_csv(text)
243 it 'ignore the carriage returns' do
244 expect(csv).to be_kind_of(Array)
245 expect(csv[0]).to match_array(['field', 'test', '1', '2', '3'])
246 expect(csv.size).to eq(1)
250 context 'with embedded newlines' do
251 text = "ERROR: Testing\n\"field\",\"te\nst\",1,2,3\n"
252 csv = Puppet::Provider::Openstack.parse_csv(text)
253 it 'should parse correctly' do
254 expect(csv).to be_kind_of(Array)
255 expect(csv[0]).to match_array(['field', "te\nst", '1', '2', '3'])
256 expect(csv.size).to eq(1)