(MODULES-9482) Bump translate dependency upper range
[puppet-modules/puppetlabs-apt.git] / spec / classes / apt_spec.rb
1 require 'spec_helper'
2
3 sources_list = {  ensure: 'file',
4                   path: '/etc/apt/sources.list',
5                   owner: 'root',
6                   group: 'root',
7                   mode: '0644',
8                   notify: 'Class[Apt::Update]' }
9
10 sources_list_d = { ensure: 'directory',
11                    path: '/etc/apt/sources.list.d',
12                    owner: 'root',
13                    group: 'root',
14                    mode: '0644',
15                    purge: false,
16                    recurse: false,
17                    notify: 'Class[Apt::Update]' }
18
19 preferences = { ensure: 'file',
20                 path: '/etc/apt/preferences',
21                 owner: 'root',
22                 group: 'root',
23                 mode: '0644',
24                 notify: 'Class[Apt::Update]' }
25
26 preferences_d = { ensure: 'directory',
27                   path: '/etc/apt/preferences.d',
28                   owner: 'root',
29                   group: 'root',
30                   mode: '0644',
31                   purge: false,
32                   recurse: false,
33                   notify: 'Class[Apt::Update]' }
34
35 describe 'apt' do
36   let(:facts) do
37     {
38       os: { family: 'Debian', name: 'Debian', release: { major: '8', full: '8.0' } },
39       lsbdistid: 'Debian',
40       osfamily: 'Debian',
41       lsbdistcodename: 'jessie',
42     }
43   end
44
45   context 'with defaults' do
46     it {
47       is_expected.to contain_file('sources.list').that_notifies('Class[Apt::Update]').only_with(sources_list)
48     }
49
50     it {
51       is_expected.to contain_file('sources.list.d').that_notifies('Class[Apt::Update]').only_with(sources_list_d)
52     }
53
54     it {
55       is_expected.to contain_file('preferences').that_notifies('Class[Apt::Update]').only_with(preferences)
56     }
57
58     it {
59       is_expected.to contain_file('preferences.d').that_notifies('Class[Apt::Update]').only_with(preferences_d)
60     }
61
62     it { is_expected.to contain_file('/etc/apt/auth.conf').with_ensure('absent') }
63
64     it 'lays down /etc/apt/apt.conf.d/15update-stamp' do
65       is_expected.to contain_file('/etc/apt/apt.conf.d/15update-stamp').with(group: 'root',
66                                                                              mode: '0644',
67                                                                              owner: 'root').with_content(
68                                                                                %r{APT::Update::Post-Invoke-Success {"touch /var/lib/apt/periodic/update-success-stamp 2>/dev/null || true";};},
69                                                                              )
70     end
71
72     it {
73       is_expected.to contain_exec('apt_update').with(refreshonly: 'true')
74     }
75
76     it { is_expected.not_to contain_apt__setting('conf-proxy') }
77   end
78
79   describe 'proxy=' do
80     context 'when host=localhost' do
81       let(:params) { { proxy: { 'host' => 'localhost' } } }
82
83       it {
84         is_expected.to contain_apt__setting('conf-proxy').with(priority: '01').with_content(
85           %r{Acquire::http::proxy "http://localhost:8080/";},
86         ).without_content(
87           %r{Acquire::https::proxy},
88         )
89       }
90     end
91
92     context 'when host=localhost and port=8180' do
93       let(:params) { { proxy: { 'host' => 'localhost', 'port' => 8180 } } }
94
95       it {
96         is_expected.to contain_apt__setting('conf-proxy').with(priority: '01').with_content(
97           %r{Acquire::http::proxy "http://localhost:8180/";},
98         ).without_content(
99           %r{Acquire::https::proxy},
100         )
101       }
102     end
103
104     context 'when host=localhost and https=true' do
105       let(:params) { { proxy: { 'host' => 'localhost', 'https' => true } } }
106
107       it {
108         is_expected.to contain_apt__setting('conf-proxy').with(priority: '01').with_content(
109           %r{Acquire::http::proxy "http://localhost:8080/";},
110         ).with_content(
111           %r{Acquire::https::proxy "https://localhost:8080/";},
112         )
113       }
114     end
115
116     context 'when host=localhost and direct=true' do
117       let(:params) { { proxy: { 'host' => 'localhost', 'direct' => true } } }
118
119       it {
120         is_expected.to contain_apt__setting('conf-proxy').with(priority: '01').with_content(
121           %r{Acquire::http::proxy "http://localhost:8080/";},
122         ).with_content(
123           %r{Acquire::https::proxy "DIRECT";},
124         )
125       }
126     end
127
128     context 'when host=localhost and https=true and direct=true' do
129       let(:params) { { proxy: { 'host' => 'localhost', 'https' => true, 'direct' => true } } }
130
131       it {
132         is_expected.to contain_apt__setting('conf-proxy').with(priority: '01').with_content(
133           %r{Acquire::http::proxy "http://localhost:8080/";},
134         ).with_content(
135           %r{Acquire::https::proxy "https://localhost:8080/";},
136         )
137       }
138       it {
139         is_expected.to contain_apt__setting('conf-proxy').with(priority: '01').with_content(
140           %r{Acquire::http::proxy "http://localhost:8080/";},
141         ).without_content(
142           %r{Acquire::https::proxy "DIRECT";},
143         )
144       }
145     end
146
147     context 'when ensure=absent' do
148       let(:params) { { proxy: { 'ensure' => 'absent' } } }
149
150       it {
151         is_expected.to contain_apt__setting('conf-proxy').with(ensure: 'absent',
152                                                                priority: '01')
153       }
154     end
155   end
156   context 'with lots of non-defaults' do
157     let :params do
158       {
159         update: { 'frequency' => 'always', 'timeout' => 1, 'tries' => 3 },
160         purge: { 'sources.list' => false, 'sources.list.d' => false,
161                  'preferences' => false, 'preferences.d' => false },
162       }
163     end
164
165     it {
166       is_expected.to contain_file('sources.list').with(content: nil)
167     }
168
169     it {
170       is_expected.to contain_file('sources.list.d').with(purge: false,
171                                                          recurse: false)
172     }
173
174     it {
175       is_expected.to contain_file('preferences').with(ensure: 'file')
176     }
177
178     it {
179       is_expected.to contain_file('preferences.d').with(purge: false,
180                                                         recurse: false)
181     }
182
183     it {
184       is_expected.to contain_exec('apt_update').with(refreshonly: false,
185                                                      timeout: 1,
186                                                      tries: 3)
187     }
188   end
189
190   context 'with entries for /etc/apt/auth.conf' do
191     let(:params) do
192       {
193         auth_conf_entries: [
194           { machine: 'deb.example.net',
195             login: 'foologin',
196             password: 'secret' },
197           { machine: 'apt.example.com',
198             login: 'aptlogin',
199             password: 'supersecret' },
200         ],
201       }
202     end
203
204     context 'with manage_auth_conf => true' do
205       let(:params) do
206         super().merge(manage_auth_conf: true)
207       end
208
209       auth_conf_content = "// This file is managed by Puppet. DO NOT EDIT.
210 machine deb.example.net login foologin password secret
211 machine apt.example.com login aptlogin password supersecret
212 "
213
214       it {
215         is_expected.to contain_file('/etc/apt/auth.conf').with(ensure: 'present',
216                                                                owner: 'root',
217                                                                group: 'root',
218                                                                mode: '0600',
219                                                                notify: 'Class[Apt::Update]',
220                                                                content: auth_conf_content)
221       }
222     end
223
224     context 'with manage_auth_conf => false' do
225       let(:params) do
226         super().merge(manage_auth_conf: false)
227       end
228
229       it {
230         is_expected.not_to contain_file('/etc/apt/auth.conf')
231       }
232     end
233   end
234
235   context 'with improperly specified entries for /etc/apt/auth.conf' do
236     let(:params) do
237       {
238         auth_conf_entries: [
239           { machinn: 'deb.example.net',
240             username: 'foologin',
241             password: 'secret' },
242           { machine: 'apt.example.com',
243             login: 'aptlogin',
244             password: 'supersecret' },
245         ],
246       }
247     end
248
249     it { is_expected.to raise_error(Puppet::Error) }
250   end
251
252   context 'with sources defined on valid osfamily' do
253     let :facts do
254       {
255         os: { family: 'Debian', name: 'Ubuntu', release: { major: '16', full: '16.04' } },
256         osfamily: 'Debian',
257         lsbdistcodename: 'xenial',
258         lsbdistid: 'Ubuntu',
259         lsbdistrelease: '16.04',
260       }
261     end
262     let(:params) do
263       { sources: {
264         'debian_unstable' => {
265           'location'          => 'http://debian.mirror.iweb.ca/debian/',
266           'release'           => 'unstable',
267           'repos'             => 'main contrib non-free',
268           'key'               => { 'id' => '150C8614919D8446E01E83AF9AA38DCD55BE302B', 'server' => 'subkeys.pgp.net' },
269           'pin'               => '-10',
270           'include'           => { 'src' => true },
271         },
272         'puppetlabs' => {
273           'location' => 'http://apt.puppetlabs.com',
274           'repos'      => 'main',
275           'key'        => { 'id' => '6F6B15509CF8E59E6E469F327F438280EF8D349F', 'server' => 'pgp.mit.edu' },
276         },
277       } }
278     end
279
280     it {
281       is_expected.to contain_apt__setting('list-debian_unstable').with(ensure: 'present')
282     }
283
284     it { is_expected.to contain_file('/etc/apt/sources.list.d/debian_unstable.list').with_content(%r{^deb http://debian.mirror.iweb.ca/debian/ unstable main contrib non-free$}) }
285     it { is_expected.to contain_file('/etc/apt/sources.list.d/debian_unstable.list').with_content(%r{^deb-src http://debian.mirror.iweb.ca/debian/ unstable main contrib non-free$}) }
286
287     it {
288       is_expected.to contain_apt__setting('list-puppetlabs').with(ensure: 'present')
289     }
290
291     it { is_expected.to contain_file('/etc/apt/sources.list.d/puppetlabs.list').with_content(%r{^deb http://apt.puppetlabs.com xenial main$}) }
292   end
293
294   context 'with confs defined on valid osfamily' do
295     let :facts do
296       {
297         os: { family: 'Debian', name: 'Ubuntu', release: { major: '16', full: '16.04' } },
298         osfamily: 'Debian',
299         lsbdistcodename: 'xenial',
300         lsbdistid: 'Ubuntu',
301       }
302     end
303     let(:params) do
304       { confs: {
305         'foo' => {
306           'content' => 'foo',
307         },
308         'bar' => {
309           'content' => 'bar',
310         },
311       } }
312     end
313
314     it {
315       is_expected.to contain_apt__conf('foo').with(content: 'foo')
316     }
317
318     it {
319       is_expected.to contain_apt__conf('bar').with(content: 'bar')
320     }
321   end
322
323   context 'with keys defined on valid osfamily' do
324     let :facts do
325       {
326         os: { family: 'Debian', name: 'Ubuntu', release: { major: '16', full: '16.04' } },
327         osfamily: 'Debian',
328         lsbdistcodename: 'xenial',
329         lsbdistid: 'Ubuntu',
330       }
331     end
332     let(:params) do
333       { keys: {
334         '55BE302B' => {
335           'server' => 'subkeys.pgp.net',
336         },
337         'EF8D349F' => {
338           'server' => 'pgp.mit.edu',
339         },
340       } }
341     end
342
343     it {
344       is_expected.to contain_apt__key('55BE302B').with(server: 'subkeys.pgp.net')
345     }
346
347     it {
348       is_expected.to contain_apt__key('EF8D349F').with(server: 'pgp.mit.edu')
349     }
350   end
351
352   context 'with ppas defined on valid osfamily' do
353     let :facts do
354       {
355         os: { family: 'Debian', name: 'Ubuntu', release: { major: '16', full: '16.04' } },
356         osfamily: 'Debian',
357         lsbdistcodename: 'xenial',
358         lsbdistid: 'Ubuntu',
359         lsbdistrelease: '16.04',
360       }
361     end
362     let(:params) do
363       { ppas: {
364         'ppa:drizzle-developers/ppa' => {},
365         'ppa:nginx/stable' => {},
366       } }
367     end
368
369     it { is_expected.to contain_apt__ppa('ppa:drizzle-developers/ppa') }
370     it { is_expected.to contain_apt__ppa('ppa:nginx/stable') }
371   end
372
373   context 'with settings defined on valid osfamily' do
374     let :facts do
375       {
376         os: { family: 'Debian', name: 'Ubuntu', release: { major: '16', full: '16.04' } },
377         osfamily: 'Debian',
378         lsbdistcodename: 'xenial',
379         lsbdistid: 'Ubuntu',
380       }
381     end
382     let(:params) do
383       { settings: {
384         'conf-banana' => { 'content' => 'banana' },
385         'pref-banana' => { 'content' => 'banana' },
386       } }
387     end
388
389     it { is_expected.to contain_apt__setting('conf-banana') }
390     it { is_expected.to contain_apt__setting('pref-banana') }
391   end
392
393   context 'with pins defined on valid osfamily' do
394     let :facts do
395       {
396         os: { family: 'Debian', name: 'Ubuntu', release: { major: '16', full: '16.04' } },
397         osfamily: 'Debian',
398         lsbdistcodename: 'xenial',
399         lsbdistid: 'Ubuntu',
400       }
401     end
402     let(:params) do
403       { pins: {
404         'stable' => { 'priority' => 600, 'order' => 50 },
405         'testing' =>  { 'priority' => 700, 'order' => 100 },
406       } }
407     end
408
409     it { is_expected.to contain_apt__pin('stable') }
410     it { is_expected.to contain_apt__pin('testing') }
411   end
412
413   describe 'failing tests' do
414     context "with purge['sources.list']=>'banana'" do
415       let(:params) { { purge: { 'sources.list' => 'banana' } } }
416
417       it do
418         is_expected.to raise_error(Puppet::Error)
419       end
420     end
421
422     context "with purge['sources.list.d']=>'banana'" do
423       let(:params) { { purge: { 'sources.list.d' => 'banana' } } }
424
425       it do
426         is_expected.to raise_error(Puppet::Error)
427       end
428     end
429
430     context "with purge['preferences']=>'banana'" do
431       let(:params) { { purge: { 'preferences' => 'banana' } } }
432
433       it do
434         is_expected.to raise_error(Puppet::Error)
435       end
436     end
437
438     context "with purge['preferences.d']=>'banana'" do
439       let(:params) { { purge: { 'preferences.d' => 'banana' } } }
440
441       it do
442         is_expected.to raise_error(Puppet::Error)
443       end
444     end
445   end
446 end