~andrewjbeach/juju-ci-tools/make-local-patcher

« back to all changes in this revision

Viewing changes to tests/test_jujuci.py

  • Committer: Aaron Bentley
  • Date: 2014-02-28 16:40:22 UTC
  • mto: This revision was merged to the branch mainline in revision 257.
  • Revision ID: aaron.bentley@canonical.com-20140228164022-kfip2tphn9m9invi
Add juju-backup script.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
from argparse import Namespace
2
 
from contextlib import contextmanager
3
 
import json
4
 
import os
5
 
from StringIO import StringIO
6
 
import urllib2
7
 
 
8
 
from mock import patch
9
 
 
10
 
from jujuci import (
11
 
    add_artifacts,
12
 
    Artifact,
13
 
    CERTIFY_UBUNTU_PACKAGES,
14
 
    clean_environment,
15
 
    Credentials,
16
 
    CredentialsMissing,
17
 
    find_artifacts,
18
 
    get_artifacts,
19
 
    get_build_data,
20
 
    get_buildvars,
21
 
    get_certification_bin,
22
 
    get_credentials,
23
 
    get_job_data,
24
 
    get_juju_bin,
25
 
    get_juju_binary,
26
 
    get_juju_bin_artifact,
27
 
    get_release_package_filename,
28
 
    JENKINS_URL,
29
 
    JobNamer,
30
 
    list_artifacts,
31
 
    Namer,
32
 
    PackageNamer,
33
 
    parse_args,
34
 
    main,
35
 
    retrieve_artifact,
36
 
    setup_workspace,
37
 
)
38
 
import jujupy
39
 
from utility import temp_dir
40
 
from tests import (
41
 
    FakeHomeTestCase,
42
 
    parse_error,
43
 
    TestCase,
44
 
)
45
 
 
46
 
 
47
 
def make_build_data(number='lastSuccessfulBuild'):
48
 
    if number == 'lastSuccessfulBuild':
49
 
        number = 2112
50
 
    return {
51
 
        "actions": [
52
 
            {
53
 
                "parameters": [
54
 
                    {
55
 
                        "name": "branch",
56
 
                        "value": "gitbranch:master:github.com/juju/juju"
57
 
                    },
58
 
                    {
59
 
                        "name": "revision",
60
 
                        "value": "3c53cf578ef100ba5368661224de4af5da72ee74"
61
 
                    }
62
 
                ]
63
 
            },
64
 
            {
65
 
                "causes": [
66
 
                    {
67
 
                        "shortDescription": "Started by user admin",
68
 
                        "userName": "admin"
69
 
                    }
70
 
                ]
71
 
            },
72
 
            {},
73
 
            {}
74
 
        ],
75
 
        "artifacts": [
76
 
            {
77
 
                "displayPath": "buildvars.bash",
78
 
                "fileName": "buildvars.bash",
79
 
                "relativePath": "buildvars.bash"
80
 
            },
81
 
            {
82
 
                "displayPath": "buildvars.json",
83
 
                "fileName": "buildvars.json",
84
 
                "relativePath": "buildvars.json"
85
 
            },
86
 
            {
87
 
                "displayPath": "juju-core_1.22-alpha1.tar.gz",
88
 
                "fileName": "juju-core_1.22-alpha1.tar.gz",
89
 
                "relativePath": "artifacts/juju-core_1.22-alpha1.tar.gz"
90
 
            }
91
 
        ],
92
 
        "building": False,
93
 
        "builtOn": "",
94
 
        "changeSet": {
95
 
            "items": [],
96
 
            "kind": None
97
 
        },
98
 
        "culprits": [],
99
 
        "description": "gitbranch:master:github.com/juju/juju 3c53cf57",
100
 
        "duration": 142986,
101
 
        "fullDisplayName": "build-revision #2102",
102
 
        "id": "2014-11-19_07-35-02",
103
 
        "keepLog": False,
104
 
        "number": 2102,
105
 
        "result": "SUCCESS",
106
 
        "timestamp": 1416382502379,
107
 
        "url": "http://juju-ci.vapour.ws:8080/job/build-revision/%s/" % number
108
 
    }
109
 
 
110
 
 
111
 
def make_job_data():
112
 
    return {
113
 
        "actions": [
114
 
            {
115
 
                "parameterDefinitions": [
116
 
                    {
117
 
                        "defaultParameterValue": {
118
 
                            "value": "1.18.1"
119
 
                        },
120
 
                        "description": "",
121
 
                        "name": "old_version",
122
 
                        "type": "StringParameterDefinition"
123
 
                    }
124
 
                ]
125
 
            },
126
 
            {}
127
 
        ],
128
 
        "buildable": True,
129
 
        "builds": [
130
 
            {
131
 
                "number": 1510,
132
 
                "url": "http://juju-ci.vapour.ws:8080/job/ting/1510/"
133
 
            }
134
 
        ],
135
 
        "color": "red",
136
 
        "concurrentBuild": False,
137
 
        "description": "",
138
 
        "displayName": "ting",
139
 
        "downstreamProjects": [],
140
 
        "firstBuild": {
141
 
            "number": 1,
142
 
            "url": "http://juju-ci.vapour.ws:8080/job/ting/1/"
143
 
        },
144
 
        "healthReport": [
145
 
            {
146
 
                "description": "Build stability: All recent builds failed.",
147
 
                "iconUrl": "health-00to19.png",
148
 
                "score": 0
149
 
            }
150
 
        ],
151
 
        "inQueue": False,
152
 
        "keepDependencies": False,
153
 
        "lastBuild": {
154
 
            "number": 1510,
155
 
            "url": "http://juju-ci.vapour.ws:8080/job/ting/1510/"
156
 
        },
157
 
        "lastCompletedBuild": {
158
 
            "number": 1510,
159
 
            "url": "http://juju-ci.vapour.ws:8080/job/ting/1510/"
160
 
        },
161
 
        "lastFailedBuild": {
162
 
            "number": 1510,
163
 
            "url": "http://juju-ci.vapour.ws:8080/job/ting/1510/"
164
 
        },
165
 
        "lastStableBuild": {
166
 
            "number": 1392,
167
 
            "url": "http://juju-ci.vapour.ws:8080/job/ting/1392/"
168
 
        },
169
 
        "lastSuccessfulBuild": {
170
 
            "number": 1392,
171
 
            "url": "http://juju-ci.vapour.ws:8080/job/ting/1392/"
172
 
        },
173
 
        "lastUnstableBuild": None,
174
 
        "lastUnsuccessfulBuild": {
175
 
            "number": 1510,
176
 
            "url": "http://juju-ci.vapour.ws:8080/job/ting/1510/"
177
 
        },
178
 
        "name": "ting",
179
 
        "nextBuildNumber": 1511,
180
 
        "property": [
181
 
            {},
182
 
            {
183
 
                "parameterDefinitions": [
184
 
                    {
185
 
                        "defaultParameterValue": {
186
 
                            "name": "old_version",
187
 
                            "value": "1.18.1"
188
 
                        },
189
 
                        "description": "",
190
 
                        "name": "old_version",
191
 
                        "type": "StringParameterDefinition"
192
 
                    },
193
 
                ]
194
 
            }
195
 
        ],
196
 
        "queueItem": None,
197
 
        "upstreamProjects": [],
198
 
        "url": "http://juju-ci.vapour.ws:8080/job/ting/"
199
 
    }
200
 
 
201
 
 
202
 
class JujuCITestCase(FakeHomeTestCase):
203
 
 
204
 
    def test_get_credentials(self):
205
 
        self.assertEqual(
206
 
            get_credentials(Namespace(user='jrandom', password='password1')),
207
 
            Credentials('jrandom', 'password1'))
208
 
 
209
 
    def test_get_credentials_no_user(self):
210
 
        self.assertIs(get_credentials(Namespace()), None)
211
 
 
212
 
    def test_get_credentials_no_value(self):
213
 
        with self.assertRaisesRegexp(
214
 
                CredentialsMissing,
215
 
                'Jenkins username and/or password not supplied.'):
216
 
            get_credentials(Namespace(user=None, password='password1'))
217
 
        with self.assertRaisesRegexp(
218
 
                CredentialsMissing,
219
 
                'Jenkins username and/or password not supplied.'):
220
 
            get_credentials(Namespace(user='jrandom', password=None))
221
 
 
222
 
    def test_main_list_options(self):
223
 
        print_list = []
224
 
        with patch('jujuci.print_now', side_effect=print_list.append):
225
 
            with patch('jujuci.list_artifacts') as mock:
226
 
                main(['-d', '-v', 'list', '-b', '1234', 'foo', '*.tar.gz',
227
 
                      '--user', 'jrandom', '--password', '1password'])
228
 
        args, kwargs = mock.call_args
229
 
        self.assertEqual((Credentials('jrandom', '1password'), 'foo',
230
 
                         '1234', '*.tar.gz'), args)
231
 
        self.assertTrue(kwargs['verbose'])
232
 
        self.assertEqual(print_list, ['Done.'])
233
 
 
234
 
    def test_main_get_options(self):
235
 
        print_list = []
236
 
        with patch('jujuci.print_now', side_effect=print_list.append):
237
 
            with patch('jujuci.get_artifacts') as mock:
238
 
                main(['-d', '-v',
239
 
                      'get', '-a', '-b', '1234', 'foo', '*.tar.gz', 'bar',
240
 
                      '--user', 'jrandom', '--password', '1password'])
241
 
        args, kwargs = mock.call_args
242
 
        self.assertEqual((Credentials('jrandom', '1password'), 'foo',
243
 
                         '1234', '*.tar.gz', 'bar'), args)
244
 
        self.assertTrue(kwargs['archive'])
245
 
        self.assertTrue(kwargs['verbose'])
246
 
        self.assertTrue(kwargs['dry_run'])
247
 
        self.assertEqual(print_list, ['Done.'])
248
 
 
249
 
    def test_main_setup_workspace_options(self):
250
 
        print_list = []
251
 
        with patch('jujuci.print_now', side_effect=print_list.append):
252
 
            with patch('jujuci.setup_workspace', autospec=True) as mock:
253
 
                main(['-d', '-v', 'setup-workspace', '--clean-env', 'bar',
254
 
                      './foo'])
255
 
        args, kwargs = mock.call_args
256
 
        self.assertEqual(('./foo', ), args)
257
 
        self.assertEqual('bar', kwargs['env'])
258
 
        self.assertTrue(kwargs['dry_run'])
259
 
        self.assertTrue(kwargs['verbose'])
260
 
        self.assertEqual(print_list, ['Done.'])
261
 
 
262
 
    def test_main_get_buildvars(self):
263
 
        print_list = []
264
 
        with patch('jujuci.print_now', side_effect=print_list.append):
265
 
            with patch('jujuci.get_buildvars', autospec=True,
266
 
                       return_value='sample buildvars') as mock:
267
 
                main(
268
 
                    ['get-build-vars', '--env', 'foo', '--summary',
269
 
                     '--revision-build', '--version', '--short-branch',
270
 
                     '--short-revision', '--branch', '--revision', '123',
271
 
                     '--user', 'jrandom', '--password', '1password'])
272
 
        args, kwargs = mock.call_args
273
 
        self.assertEqual((Credentials('jrandom', '1password'), '123'), args)
274
 
        self.assertEqual('foo', kwargs['env'])
275
 
        self.assertTrue(kwargs['summary'])
276
 
        self.assertTrue(kwargs['revision_build'])
277
 
        self.assertTrue(kwargs['version'])
278
 
        self.assertTrue(kwargs['short_revision'])
279
 
        self.assertTrue(kwargs['short_branch'])
280
 
        self.assertTrue(kwargs['branch'])
281
 
        self.assertTrue(kwargs['revision'])
282
 
        self.assertEqual(print_list, ['sample buildvars'])
283
 
 
284
 
    def test_parse_arg_buildvars_common_options(self):
285
 
        args, credentials = parse_args(
286
 
            ['get-build-vars', '--env', 'foo', '--summary',
287
 
             '--user', 'jrandom', '--password', '1password', '1234'])
288
 
        self.assertEqual(Credentials('jrandom', '1password'), credentials)
289
 
        self.assertEqual('foo', args.env)
290
 
        self.assertTrue(args.summary)
291
 
        args, credentials = parse_args(
292
 
            ['get-build-vars', '--version',
293
 
             '--user', 'jrandom', '--password', '1password', '1234'])
294
 
        self.assertTrue(args.version)
295
 
        args, credentials = parse_args(
296
 
            ['get-build-vars', '--short-branch',
297
 
             '--user', 'jrandom', '--password', '1password', '1234'])
298
 
        self.assertTrue(args.short_branch)
299
 
 
300
 
    def test_parse_arg_buildvars_error(self):
301
 
        with parse_error(self) as stderr:
302
 
            parse_args(['get-build-vars', '1234'])
303
 
        self.assertIn(
304
 
            'Expected --summary or one or more of:', stderr.getvalue())
305
 
 
306
 
    def test_parse_arg_get_package_name(self):
307
 
        with parse_error(self) as stderr:
308
 
            parse_args(['get-package-name'])
309
 
        self.assertIn('error: too few arguments', stderr.getvalue())
310
 
        args = parse_args(['get-package-name', '1.22.1'])
311
 
        expected = Namespace(command='get-package-name', version='1.22.1',
312
 
                             dry_run=False, verbose=False)
313
 
        self.assertEqual(args, (expected, None))
314
 
 
315
 
    def test_get_build_data(self):
316
 
        expected_data = make_build_data(1234)
317
 
        json_io = StringIO(json.dumps(expected_data))
318
 
        with patch('urllib2.urlopen', return_value=json_io) as mock:
319
 
            build_data = get_build_data(
320
 
                'http://foo:8080', Credentials('jrandom', '1password'), 'bar',
321
 
                '1234')
322
 
        self.assertEqual(1, mock.call_count)
323
 
        request = mock.mock_calls[0][1][0]
324
 
        self.assertRequest(
325
 
            request, 'http://foo:8080/job/bar/1234/api/json',
326
 
            {'Authorization': 'Basic anJhbmRvbToxcGFzc3dvcmQ='})
327
 
        self.assertEqual(expected_data, build_data)
328
 
 
329
 
    def test_get_job_data(self):
330
 
        expected_data = make_job_data()
331
 
        json_io = StringIO(json.dumps(expected_data))
332
 
        with patch('urllib2.urlopen', return_value=json_io) as mock:
333
 
            build_data = get_job_data(
334
 
                'http://foo:8080', Credentials('jrandom', '1password'), 'ting')
335
 
        self.assertEqual(1, mock.call_count)
336
 
        request = mock.mock_calls[0][1][0]
337
 
        self.assertRequest(
338
 
            request, 'http://foo:8080/job/ting/api/json',
339
 
            {'Authorization': 'Basic anJhbmRvbToxcGFzc3dvcmQ='})
340
 
        self.assertEqual(expected_data, build_data)
341
 
 
342
 
    def assertRequest(self, request, url, headers):
343
 
        self.assertIs(request.__class__, urllib2.Request)
344
 
        self.assertEqual(request.get_full_url(), url)
345
 
        self.assertEqual(request.headers, headers)
346
 
 
347
 
    def test_get_build_data_with_default_build(self):
348
 
        expected_data = make_build_data()
349
 
        json_io = StringIO(json.dumps(expected_data))
350
 
        with patch('urllib2.urlopen', return_value=json_io) as mock:
351
 
            get_build_data(
352
 
                'http://foo:8080', Credentials('jrandom', '1password'), 'bar')
353
 
        self.assertEqual(mock.call_count, 1)
354
 
        self.assertRequest(
355
 
            mock.mock_calls[0][1][0],
356
 
            'http://foo:8080/job/bar/lastSuccessfulBuild/api/json',
357
 
            {'Authorization': 'Basic anJhbmRvbToxcGFzc3dvcmQ='})
358
 
 
359
 
    def test_find_artifacts_all(self):
360
 
        expected_data = make_build_data()
361
 
        artifacts = find_artifacts(expected_data)
362
 
        self.assertEqual(
363
 
            ['buildvars.bash', 'buildvars.json',
364
 
             'juju-core_1.22-alpha1.tar.gz'],
365
 
            sorted(a.file_name for a in artifacts))
366
 
 
367
 
    def test_find_artifacts_glob_tarball(self):
368
 
        expected_data = make_build_data()
369
 
        artifacts = find_artifacts(expected_data, '*.tar.gz')
370
 
        artifact = artifacts[0]
371
 
        self.assertEqual('juju-core_1.22-alpha1.tar.gz', artifact.file_name)
372
 
        self.assertEqual(
373
 
            'http://juju-ci.vapour.ws:8080/job/build-revision/2112/'
374
 
            'artifact/artifacts/juju-core_1.22-alpha1.tar.gz',
375
 
            artifact.location)
376
 
 
377
 
    def test_list_artifacts(self):
378
 
        credentials = Credentials('jrandom', '1password')
379
 
        build_data = make_build_data(1234)
380
 
        with patch('jujuci.get_build_data', return_value=build_data) as mock:
381
 
            with patch('jujuci.print_now') as pn_mock:
382
 
                list_artifacts(credentials, 'foo', '1234', '*')
383
 
        mock.assert_called_once_with(JENKINS_URL, credentials, 'foo', '1234')
384
 
        files = sorted(call[1][0] for call in pn_mock.mock_calls)
385
 
        self.assertEqual(
386
 
            ['buildvars.bash', 'buildvars.json',
387
 
             'juju-core_1.22-alpha1.tar.gz'],
388
 
            files)
389
 
 
390
 
    def test_list_artifacts_verbose(self):
391
 
        build_data = make_build_data(1234)
392
 
        with patch('jujuci.get_build_data', return_value=build_data):
393
 
            with patch('jujuci.print_now') as pn_mock:
394
 
                list_artifacts(
395
 
                    Credentials('jrandom', '1password'), 'foo', '1234',
396
 
                    '*.bash', verbose=True)
397
 
        files = sorted(call[1][0] for call in pn_mock.mock_calls)
398
 
        self.assertEqual(
399
 
            ['http://juju-ci.vapour.ws:8080/job/build-revision/1234/artifact/'
400
 
             'buildvars.bash'],
401
 
            files)
402
 
 
403
 
    def test_retrieve_artifact(self):
404
 
        location = (
405
 
            'http://juju-ci.vapour.ws:8080/job/build-revision/1234/artifact/'
406
 
            'buildvars.bash')
407
 
        local_path = '%s/buildvars.bash' % os.path.abspath('./')
408
 
        with patch('urllib.urlretrieve') as uo_mock:
409
 
            retrieve_artifact(
410
 
                Credentials('jrandom', '1password'), location, local_path)
411
 
        self.assertEqual(1, uo_mock.call_count)
412
 
        args, kwargs = uo_mock.call_args
413
 
        auth_location = location.replace('http://',
414
 
                                         'http://jrandom:1password@')
415
 
        self.assertEqual((auth_location, local_path), args)
416
 
 
417
 
    def test_get_juju_bin_artifact(self):
418
 
        package_namer = PackageNamer('foo', 'bar', 'baz')
419
 
        bin_filename = 'juju-core_1.27.32-0ubuntu1~bar.1~juju1_foo.deb'
420
 
        artifact = get_juju_bin_artifact(package_namer, '1.27.32', {
421
 
            'url': 'http://asdf/',
422
 
            'artifacts': [{
423
 
                'relativePath': 'foo',
424
 
                'fileName': bin_filename,
425
 
                }],
426
 
            })
427
 
        self.assertEqual(artifact.location, 'http://asdf/artifact/foo')
428
 
        self.assertEqual(artifact.file_name, bin_filename)
429
 
 
430
 
    def test_get_release_package_filename(self):
431
 
        package_namer = PackageNamer('foo', 'bar', 'baz')
432
 
        credentials = ('jrandom', 'password1')
433
 
        publish_build_data = {'actions': [], }
434
 
        build_revision_data = json.dumps({
435
 
            'artifacts': [{
436
 
                'fileName': 'buildvars.json',
437
 
                'relativePath': 'buildvars.json'
438
 
                }],
439
 
            'url': 'http://foo/'})
440
 
 
441
 
        def mock_urlopen(request):
442
 
            if request.get_full_url() == 'http://foo/artifact/buildvars.json':
443
 
                data = json.dumps({'version': '1.42'})
444
 
            else:
445
 
                data = build_revision_data
446
 
            return StringIO(data)
447
 
 
448
 
        with patch('urllib2.urlopen', autospec=True,
449
 
                   side_effect=mock_urlopen):
450
 
            with patch.object(PackageNamer, 'factory',
451
 
                              return_value=package_namer):
452
 
                file_name = get_release_package_filename(
453
 
                    credentials, publish_build_data)
454
 
        self.assertEqual(file_name, package_namer.get_release_package('1.42'))
455
 
 
456
 
    def test_get_juju_bin(self):
457
 
        build_data = {
458
 
            'url': 'http://foo/',
459
 
            'artifacts': [{
460
 
                'fileName': 'steve',
461
 
                'relativePath': 'baz',
462
 
                }]
463
 
            }
464
 
        credentials = Credentials('jrandom', 'password1')
465
 
        job_namer = JobNamer('a64', '42.34', 'wacky')
466
 
 
467
 
        with self.get_juju_binary_mocks() as (workspace, cc_mock, uo_mock):
468
 
            with patch('jujuci.get_build_data', return_value=build_data,
469
 
                       autospec=True) as gbd_mock:
470
 
                with patch(
471
 
                        'jujuci.get_release_package_filename',
472
 
                        return_value='steve', autospec=True) as grpf_mock:
473
 
                    with patch.object(
474
 
                            JobNamer, 'factory', spec=JobNamer.factory,
475
 
                            return_value=job_namer) as jnf_mock:
476
 
                        bin_loc = get_juju_bin(credentials, workspace)
477
 
        self.assertEqual(bin_loc, os.path.join(
478
 
            workspace, 'extracted-bin', 'subdir', 'sub-subdir', 'juju'))
479
 
        grpf_mock.assert_called_once_with(credentials, build_data)
480
 
        gbd_mock.assert_called_once_with(
481
 
            JENKINS_URL, credentials, 'build-binary-wacky-a64', 'lastBuild')
482
 
        self.assertEqual(1, jnf_mock.call_count)
483
 
 
484
 
    def test_get_certification_bin(self):
485
 
        package_namer = PackageNamer('foo', 'bar', 'baz')
486
 
        build_data = {
487
 
            'url': 'http://foo/',
488
 
            'artifacts': [{
489
 
                'fileName': 'juju-core_36.1~0ubuntu1~bar.1_foo.deb',
490
 
                'relativePath': 'baz',
491
 
                }]
492
 
            }
493
 
        credentials = Credentials('jrandom', 'password1')
494
 
 
495
 
        with self.get_juju_binary_mocks() as (workspace, ur_mock, cc_mock):
496
 
            with patch('jujuci.get_build_data', return_value=build_data,
497
 
                       autospec=True) as gbd_mock:
498
 
                with patch.object(PackageNamer, 'factory',
499
 
                                  return_value=package_namer):
500
 
                    bin_loc = get_certification_bin(credentials,
501
 
                                                    '36.1~0ubuntu1',
502
 
                                                    workspace)
503
 
        self.assertEqual(bin_loc, os.path.join(
504
 
            workspace, 'extracted-bin', 'subdir', 'sub-subdir', 'juju'))
505
 
        ur_mock.assert_called_once_with(
506
 
            'http://jrandom:password1@foo/artifact/baz',
507
 
            os.path.join(workspace, 'juju-core_36.1~0ubuntu1~bar.1_foo.deb'))
508
 
        gbd_mock.assert_called_once_with(
509
 
            JENKINS_URL, credentials, CERTIFY_UBUNTU_PACKAGES, 'lastBuild')
510
 
 
511
 
    @contextmanager
512
 
    def get_juju_binary_mocks(self):
513
 
        def mock_extract_deb(args):
514
 
            parent = os.path.join(args[3], 'subdir', 'sub-subdir')
515
 
            os.makedirs(parent)
516
 
            with open(os.path.join(parent, 'juju'), 'w') as f:
517
 
                f.write('foo')
518
 
 
519
 
        with temp_dir() as workspace:
520
 
            with patch('urllib.urlretrieve') as ur_mock:
521
 
                with patch('subprocess.check_call',
522
 
                           side_effect=mock_extract_deb) as cc_mock:
523
 
                    yield workspace, ur_mock, cc_mock
524
 
 
525
 
    def test_get_juju_binary(self):
526
 
        build_data = {
527
 
            'url': 'http://foo/',
528
 
            'artifacts': [{
529
 
                'fileName': 'steve',
530
 
                'relativePath': 'baz',
531
 
                }]
532
 
            }
533
 
        credentials = Credentials('jrandom', 'password1')
534
 
        with self.get_juju_binary_mocks() as (workspace, ur_mock, cc_mock):
535
 
            bin_loc = get_juju_binary(credentials, 'steve', build_data,
536
 
                                      workspace)
537
 
        target_path = os.path.join(workspace, 'steve')
538
 
        ur_mock.assert_called_once_with(
539
 
            'http://jrandom:password1@foo/artifact/baz', target_path)
540
 
        out_dir = os.path.join(workspace, 'extracted-bin')
541
 
        cc_mock.assert_called_once_with(['dpkg', '-x', target_path, out_dir])
542
 
        self.assertEqual(
543
 
            bin_loc, os.path.join(workspace, 'extracted-bin', 'subdir',
544
 
                                  'sub-subdir', 'juju'))
545
 
 
546
 
    def test_get_artifacts(self):
547
 
        build_data = make_build_data(1234)
548
 
        print_list = []
549
 
        with patch('jujuci.print_now', side_effect=print_list.append):
550
 
            with patch('jujuci.get_build_data', return_value=build_data):
551
 
                with patch('urllib.urlretrieve') as uo_mock:
552
 
                    found = get_artifacts(
553
 
                        Credentials('jrandom', '1password'), 'foo', '1234',
554
 
                        '*.bash', './', verbose=True)
555
 
        location = (
556
 
            'http://juju-ci.vapour.ws:8080/job/build-revision/1234/artifact/'
557
 
            'buildvars.bash')
558
 
        buildvar_artifact = Artifact('buildvars.bash', location)
559
 
        self.assertEqual([buildvar_artifact], found)
560
 
        self.assertEqual(1, uo_mock.call_count)
561
 
        args, kwargs = uo_mock.call_args
562
 
        local_path = '%s/buildvars.bash' % os.path.abspath('./')
563
 
        auth_location = location.replace('http://',
564
 
                                         'http://jrandom:1password@')
565
 
        self.assertEqual((auth_location, local_path), args)
566
 
        self.assertEqual(
567
 
            print_list,
568
 
            ['Retrieving %s => %s' % (location, local_path)]
569
 
        )
570
 
 
571
 
    def test_get_artifacts_with_dry_run(self):
572
 
        build_data = make_build_data(1234)
573
 
        print_list = []
574
 
        with patch('jujuci.print_now', side_effect=print_list.append):
575
 
            with patch('jujuci.get_build_data', return_value=build_data):
576
 
                with patch('urllib.urlretrieve') as uo_mock:
577
 
                    get_artifacts(
578
 
                        Credentials('jrandom', '1password'), 'foo', '1234',
579
 
                        '*.bash', './', dry_run=True)
580
 
        self.assertEqual(0, uo_mock.call_count)
581
 
        self.assertEqual(print_list, ['buildvars.bash'])
582
 
 
583
 
    def test_get_artifacts_with_archive(self):
584
 
        build_data = make_build_data(1234)
585
 
        print_list = []
586
 
        with temp_dir() as base_dir:
587
 
            path = os.path.join(base_dir, 'foo')
588
 
            os.mkdir(path)
589
 
            old_file_path = os.path.join(path, 'old_file.txt')
590
 
            with open(old_file_path, 'w') as old_file:
591
 
                old_file.write('old')
592
 
            with patch('jujuci.print_now', side_effect=print_list.append):
593
 
                with patch('jujuci.get_build_data', return_value=build_data):
594
 
                    with patch('urllib.urlretrieve'):
595
 
                        get_artifacts(
596
 
                            Credentials('jrandom', '1password'), 'foo', '1234',
597
 
                            '*.bash', path, archive=True)
598
 
            self.assertFalse(os.path.isfile(old_file_path))
599
 
            self.assertTrue(os.path.isdir(path))
600
 
        self.assertEqual(print_list, ['buildvars.bash'])
601
 
 
602
 
    def test_get_artifacts_with_archive_error(self):
603
 
        build_data = make_build_data(1234)
604
 
        with patch('jujuci.get_build_data', return_value=build_data):
605
 
            with patch('urllib.urlretrieve'):
606
 
                with self.assertRaises(ValueError):
607
 
                    get_artifacts(
608
 
                        Credentials('jrandom', '1password'), 'foo', '1234',
609
 
                        '*.bash', '/foo-bar-baz', archive=True)
610
 
 
611
 
    def test_setup_workspace(self):
612
 
        with temp_dir() as base_dir:
613
 
            workspace_dir = os.path.join(base_dir, 'workspace')
614
 
            foo_dir = os.path.join(workspace_dir, 'foo')
615
 
            os.makedirs(foo_dir)
616
 
            with open(os.path.join(workspace_dir, 'old.txt'), 'w') as of:
617
 
                of.write('old')
618
 
            print_list = []
619
 
            with patch('jujuci.print_now', side_effect=print_list.append):
620
 
                setup_workspace(workspace_dir, dry_run=False, verbose=False)
621
 
            self.assertEqual(['artifacts'], os.listdir(workspace_dir))
622
 
            artifacts_dir = os.path.join(workspace_dir, 'artifacts')
623
 
            self.assertEqual(['empty'], os.listdir(artifacts_dir))
624
 
            self.assertEqual(
625
 
                print_list,
626
 
                ['Removing old.txt', 'Removing foo', 'Creating artifacts dir.']
627
 
            )
628
 
 
629
 
    def test_setup_workspace_with_env(self):
630
 
        with temp_dir() as base_dir:
631
 
            workspace_dir = os.path.join(base_dir, 'workspace')
632
 
            os.makedirs(workspace_dir)
633
 
            print_list = []
634
 
            with patch('jujuci.print_now', side_effect=print_list.append):
635
 
                with patch('jujuci.clean_environment', autospec=True) as mock:
636
 
                    setup_workspace(
637
 
                        workspace_dir, env='foo', dry_run=False, verbose=False)
638
 
            mock.assert_called_once_with('foo', verbose=False)
639
 
            self.assertEqual(print_list, ['Creating artifacts dir.'])
640
 
 
641
 
    def test_clean_environment_not_dirty(self):
642
 
        config = {'environments': {'local': {'type': 'local'}}}
643
 
        with jujupy._temp_env(config, set_home=True):
644
 
            with patch('jujuci.destroy_environment', autospec=True) as mock_de:
645
 
                with patch('jujupy.EnvJujuClient.by_version', side_effect=(
646
 
                        lambda env: jujupy.EnvJujuClient(env, '1', None))):
647
 
                    dirty = clean_environment('foo', verbose=False)
648
 
        self.assertFalse(dirty)
649
 
        self.assertEqual(0, mock_de.call_count)
650
 
 
651
 
    def test_clean_environment_dirty(self):
652
 
        config = {'environments': {'foo': {'type': 'local'}}}
653
 
        with jujupy._temp_env(config, set_home=True):
654
 
            with patch('jujuci.destroy_environment', autospec=True) as mock_de:
655
 
                with patch('jujupy.EnvJujuClient.by_version', side_effect=(
656
 
                        lambda env: jujupy.EnvJujuClient(env, '1', None))):
657
 
                    with patch.object(jujupy.JujuData, 'load_yaml'):
658
 
                        dirty = clean_environment('foo', verbose=False)
659
 
        self.assertTrue(dirty)
660
 
        self.assertEqual(1, mock_de.call_count)
661
 
        args, kwargs = mock_de.call_args
662
 
        self.assertIsInstance(args[0], jujupy.EnvJujuClient)
663
 
        self.assertEqual('foo', args[1])
664
 
 
665
 
    def test_add_artifacts_simple(self):
666
 
        with temp_dir() as workspace_dir:
667
 
            artifacts_dir = os.path.join(workspace_dir, 'artifacts')
668
 
            os.mkdir(artifacts_dir)
669
 
            for name in ['foo.tar.gz', 'bar.json', 'baz.txt',
670
 
                         'juju-core_1.2.3.tar.gz', 'juju-core-1.2.3.deb',
671
 
                         'buildvars.bash', 'buildvars.json']:
672
 
                with open(os.path.join(workspace_dir, name), 'w') as nf:
673
 
                    nf.write(name)
674
 
            globs = ['buildvars.*', 'juju-core_*.tar.gz', 'juju-*.deb']
675
 
            add_artifacts(
676
 
                workspace_dir, globs, dry_run=False, verbose=False)
677
 
            artifacts = sorted(os.listdir(artifacts_dir))
678
 
            expected = [
679
 
                'buildvars.bash', 'buildvars.json',
680
 
                'juju-core-1.2.3.deb', 'juju-core_1.2.3.tar.gz']
681
 
            self.assertEqual(expected, artifacts)
682
 
 
683
 
    def test_add_artifacts_deep(self):
684
 
        with temp_dir() as workspace_dir:
685
 
            artifacts_dir = os.path.join(workspace_dir, 'artifacts')
686
 
            os.mkdir(artifacts_dir)
687
 
            sub_dir = os.path.join(workspace_dir, 'sub_dir')
688
 
            os.mkdir(sub_dir)
689
 
            for name in ['foo.tar.gz', 'juju-core-1.2.3.deb']:
690
 
                with open(os.path.join(sub_dir, name), 'w') as nf:
691
 
                    nf.write(name)
692
 
            add_artifacts(
693
 
                workspace_dir, ['sub_dir/*.deb'], dry_run=False, verbose=False)
694
 
            artifacts = os.listdir(artifacts_dir)
695
 
            self.assertEqual(['juju-core-1.2.3.deb'], artifacts)
696
 
 
697
 
    def test_get_buildvars(self):
698
 
        buildvars = {
699
 
            'revision_id': '1234567abcdef',
700
 
            'version': '1.22.4',
701
 
            'revision_build': '1234',
702
 
            'branch': 'gitbranch:1.22:github.com/juju/juju',
703
 
            }
704
 
        credentials = Credentials('bar', 'baz')
705
 
        with patch('jujuci.retrieve_buildvars', autospec=True,
706
 
                   return_value=buildvars) as rb_mock:
707
 
            # The summary case for deploy and upgrade jobs.
708
 
            text = get_buildvars(
709
 
                credentials, 1234, env='foo',
710
 
                summary=True, revision_build=False, version=False,
711
 
                short_branch=False, short_revision=False,
712
 
                branch=False, revision=False)
713
 
            rb_mock.assert_called_once_with(credentials, 1234)
714
 
            self.assertEqual(
715
 
                'Testing gitbranch:1.22:github.com/juju/juju 1234567 '
716
 
                'on foo for 1234',
717
 
                text)
718
 
            # The version case used to skip jobs testing old versions.
719
 
            text = get_buildvars(
720
 
                credentials, 1234,
721
 
                summary=False, revision_build=True, version=True,
722
 
                branch=True, short_branch=True,
723
 
                revision=True, short_revision=True)
724
 
            self.assertEqual(
725
 
                '1234 1.22.4 1.22 1234567 '
726
 
                'gitbranch:1.22:github.com/juju/juju 1234567abcdef',
727
 
                text)
728
 
 
729
 
 
730
 
class TestNamer(TestCase):
731
 
 
732
 
    def test_factory(self):
733
 
        with patch('subprocess.check_output', return_value=' amd42 \n'):
734
 
            with patch('jujuci.get_distro_information',
735
 
                       return_value={'RELEASE': '42.42', 'CODENAME': 'wacky'}):
736
 
                namer = Namer.factory()
737
 
        self.assertIs(type(namer), Namer)
738
 
        self.assertEqual(namer.arch, 'amd42')
739
 
        self.assertEqual(namer.distro_release, '42.42')
740
 
        self.assertEqual(namer.distro_series, 'wacky')
741
 
 
742
 
 
743
 
class TestPackageNamer(TestNamer):
744
 
 
745
 
    def test_get_release_package(self):
746
 
        package_namer = PackageNamer('amd42', '42.34', 'wacky')
747
 
        self.assertEqual(
748
 
            package_namer.get_release_package('27.6'),
749
 
            'juju-core_27.6-0ubuntu1~42.34.1~juju1_amd42.deb')
750
 
 
751
 
    def test_get_certification_package(self):
752
 
        package_namer = PackageNamer('amd42', '42.34', 'wacky')
753
 
        self.assertEqual(
754
 
            package_namer.get_certification_package('27.6~0ubuntu1'),
755
 
            'juju-core_27.6~0ubuntu1~42.34.1_amd42.deb')
756
 
 
757
 
 
758
 
class TestJobNamer(TestNamer):
759
 
 
760
 
    def test_get_build_binary(self):
761
 
        self.assertEqual(
762
 
            JobNamer('ppc64el', '42.34', 'wacky').get_build_binary_job(),
763
 
            'build-binary-wacky-ppc64el')