3 require 'puppet/provider/keystone_user/openstack'
5 provider_class = Puppet::Type.type(:keystone_user).provider(:openstack)
7 describe provider_class do
16 :email => 'foo@example.com',
19 'password' => 'abc123',
20 'tenant_name' => 'foo',
21 'auth_url' => 'http://127.0.0.1:5000/v2.0',
27 Puppet::Type::Keystone_user.new(user_attrs)
31 provider_class.new(resource)
34 describe 'when updating a user' do
37 it 'creates a user' do
38 provider.class.stubs(:openstack)
39 .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
40 .returns('"ID","Name","Project","Email","Enabled"
41 "1cb05cfed7c24279be884ba4f6520262","foo","foo","foo@example.com",True
43 provider.class.stubs(:openstack)
44 .with('user', 'create', '--format', 'shell', [['foo', '--enable', '--password', 'foo', '--project', 'foo', '--email', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
45 .returns('email="foo@example.com"
47 id="12b23f07d4a3448d8189521ab09610b0"
49 project_id="5e2001b2248540f191ff22627dc0c2d7"
53 expect(provider.exists?).to be_truthy
57 describe '#destroy' do
58 it 'destroys a user' do
59 provider.class.stubs(:openstack)
60 .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
61 .returns('"ID","Name","Project","Email","Enabled"')
62 provider.class.stubs(:openstack)
63 .with('user', 'delete', [['foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
65 expect(provider.exists?).to be_falsey
71 context 'when user exists' do
74 provider.class.stubs(:openstack)
75 .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
76 .returns('"ID","Name","Project","Email","Enabled"
77 "1cb05cfed7c24279be884ba4f6520262","foo","foo","foo@example.com",True
79 response = provider.exists?
82 it { is_expected.to be_truthy }
85 context 'when user does not exist' do
88 provider.class.stubs(:openstack)
89 .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
90 .returns('"ID","Name","Project","Email","Enabled"')
91 response = provider.exists?
94 it { is_expected.to be_falsey }
98 describe '#instances' do
99 it 'finds every user' do
100 provider.class.stubs(:openstack)
101 .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
102 .returns('"ID","Name","Project","Email","Enabled"
103 "1cb05cfed7c24279be884ba4f6520262","foo","foo","foo@example.com",True
105 instances = provider.instances
106 expect(instances.count).to eq(1)
110 describe '#tenant' do
111 it 'gets the tenant with default backend' do
112 provider.class.stubs(:openstack)
113 .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
114 .returns('"ID","Name","Project","Email","Enabled"
115 "1cb05cfed7c24279be884ba4f6520262","foo","foo","foo@example.com",True
117 tenant = provider.tenant
118 expect(tenant).to eq('foo')
120 it 'gets the tenant with LDAP backend' do
121 provider.class.stubs(:openstack)
122 .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
123 .returns('"ID","Name","Project","Email","Enabled"
124 "1cb05cfed7c24279be884ba4f6520262","foo","","foo@example.com",True
126 provider.class.expects(:openstack)
127 .with('user role', 'list', '--quiet', '--format', 'csv', [['foo', '--project', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
128 .returns('"ID","Name","Project","User"
129 "1cb05cfed7c24279be884ba4f6520262","foo","foo","foo"
131 tenant = provider.tenant
132 expect(tenant).to eq('foo')
135 describe '#tenant=' do
136 context 'when using default backend' do
137 it 'sets the tenant' do
138 provider.class.expects(:openstack)
139 .with('user', 'set', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
140 provider.class.expects(:openstack)
141 .with('user role', 'list', '--quiet', '--format', 'csv', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
142 .returns('"ID","Name","Project","User"
143 "1cb05cfed7c24279be884ba4f6520262","foo","foo","foo"
145 provider.tenant=('bar')
148 context 'when using LDAP read-write backend' do
149 it 'sets the tenant when _member_ role exists' do
150 provider.class.expects(:openstack)
151 .with('user', 'set', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
152 provider.class.expects(:openstack)
153 .with('user role', 'list', '--quiet', '--format', 'csv', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
155 provider.class.expects(:openstack)
156 .with('role', 'show', '--format', 'shell', [['_member_', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
157 .returns('name="_member_"')
158 provider.class.expects(:openstack)
159 .with('role', 'add', [['_member_', '--project', 'bar', '--user', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
160 provider.tenant=('bar')
162 it 'sets the tenant when _member_ role does not exist' do
163 provider.class.expects(:openstack)
164 .with('user', 'set', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
165 provider.class.expects(:openstack)
166 .with('user role', 'list', '--quiet', '--format', 'csv', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
168 provider.class.expects(:openstack)
169 .with('role', 'show', '--format', 'shell', [['_member_', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
170 .raises(Puppet::ExecutionFailure, 'no such role _member_')
171 provider.class.expects(:openstack)
172 .with('role', 'create', '--format', 'shell', [['_member_', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
173 .returns('name="_member_"')
174 provider.class.expects(:openstack)
175 .with('role', 'add', [['_member_', '--project', 'bar', '--user', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
176 provider.tenant=('bar')
179 context 'when using LDAP read-only backend' do
180 it 'sets the tenant when _member_ role exists' do
181 provider.class.expects(:openstack)
182 .with('user', 'set', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
183 .raises(Puppet::ExecutionFailure, 'You are not authorized to perform the requested action: LDAP user update')
184 provider.class.expects(:openstack)
185 .with('user role', 'list', '--quiet', '--format', 'csv', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
187 provider.class.expects(:openstack)
188 .with('role', 'show', '--format', 'shell', [['_member_', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
189 .returns('name="_member_"')
190 provider.class.expects(:openstack)
191 .with('role', 'add', [['_member_', '--project', 'bar', '--user', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
192 provider.tenant=('bar')
194 it 'sets the tenant and gets an unexpected exception message' do
195 provider.class.expects(:openstack)
196 .with('user', 'set', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
197 .raises(Puppet::ExecutionFailure, 'unknown error message')
198 expect{ provider.tenant=('bar') }.to raise_error(Puppet::ExecutionFailure, /unknown error message/)
205 describe "#password" do
209 :ensure => 'present',
213 :email => 'foo@example.com',
215 'username' => 'test',
216 'password' => 'abc123',
217 'tenant_name' => 'foo',
218 'auth_url' => 'https://127.0.0.1:5000/v2.0',
223 it 'checks the password with HTTPS' do
224 httpobj = mock('Net::HTTP')
225 httpobj.stubs(:use_ssl=).with(true)
226 httpobj.stubs(:verify_mode=)
227 Net::HTTP.stubs(:start).returns(httpobj)
228 reqobj = mock('Net::HTTP::Post')
230 reqobj.stubs(:content_type=)
231 Net::HTTP::Post.stubs(:start).returns(reqobj)
232 respobj = mock('Net::HTTPResponse')
233 respobj.stubs(:code).returns('200')
234 httpobj.stubs(:request).returns(respobj)
235 password = provider.password
236 expect(password).to eq('foo')
238 it 'fails the password check with HTTPS' do
239 httpobj = mock('Net::HTTP')
240 httpobj.stubs(:use_ssl=).with(true)
241 httpobj.stubs(:verify_mode=)
242 Net::HTTP.stubs(:start).returns(httpobj)
243 reqobj = mock('Net::HTTP::Post')
245 reqobj.stubs(:content_type=)
246 Net::HTTP::Post.stubs(:start).returns(reqobj)
247 respobj = mock('Net::HTTPResponse')
248 respobj.stubs(:code).returns('401')
249 httpobj.stubs(:request).returns(respobj)
250 password = provider.password
251 expect(password).to eq(nil)
254 describe 'when updating a user with unmanaged password' do
259 :ensure => 'present',
262 :replace_password => 'False',
264 :email => 'foo@example.com',
266 'username' => 'test',
267 'password' => 'abc123',
268 'tenant_name' => 'foo',
269 'auth_url' => 'http://127.0.0.1:5000/v2.0',
275 Puppet::Type::Keystone_user.new(user_attrs)
279 provider_class.new(resource)
282 it 'should not try to check password' do
283 expect(provider.password).to eq('foo')