github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/acceptancetests/tests/test_jujuci.py (about) 1 from argparse import Namespace 2 import json 3 import os 4 from StringIO import StringIO 5 import urllib2 6 7 try: 8 from mock import patch 9 except ImportError: 10 from unittest.mock import patch 11 12 from jujuci import ( 13 acquire_binary, 14 add_artifacts, 15 Credentials, 16 CredentialsMissing, 17 find_artifacts, 18 get_build_data, 19 get_credentials, 20 get_job_data, 21 JENKINS_URL, 22 JobNamer, 23 list_artifacts, 24 Namer, 25 PackageNamer, 26 main, 27 setup_workspace, 28 ) 29 from utility import temp_dir 30 from tests import ( 31 FakeHomeTestCase, 32 TestCase, 33 ) 34 35 36 def make_build_data(number='lastSuccessfulBuild'): 37 if number == 'lastSuccessfulBuild': 38 number = 2112 39 return { 40 "actions": [ 41 { 42 "parameters": [ 43 { 44 "name": "branch", 45 "value": "gitbranch:master:github.com/juju/juju" 46 }, 47 { 48 "name": "revision", 49 "value": "3c53cf578ef100ba5368661224de4af5da72ee74" 50 } 51 ] 52 }, 53 { 54 "causes": [ 55 { 56 "shortDescription": "Started by user admin", 57 "userName": "admin" 58 } 59 ] 60 }, 61 {}, 62 {} 63 ], 64 "artifacts": [ 65 { 66 "displayPath": "buildvars.bash", 67 "fileName": "buildvars.bash", 68 "relativePath": "buildvars.bash" 69 }, 70 { 71 "displayPath": "buildvars.json", 72 "fileName": "buildvars.json", 73 "relativePath": "buildvars.json" 74 }, 75 { 76 "displayPath": "juju-core_1.22-alpha1.tar.gz", 77 "fileName": "juju-core_1.22-alpha1.tar.gz", 78 "relativePath": "artifacts/juju-core_1.22-alpha1.tar.gz" 79 } 80 ], 81 "building": False, 82 "builtOn": "", 83 "changeSet": { 84 "items": [], 85 "kind": None 86 }, 87 "culprits": [], 88 "description": "gitbranch:master:github.com/juju/juju 3c53cf57", 89 "duration": 142986, 90 "fullDisplayName": "build-revision #2102", 91 "id": "2014-11-19_07-35-02", 92 "keepLog": False, 93 "number": 2102, 94 "result": "SUCCESS", 95 "timestamp": 1416382502379, 96 "url": "http://jenkins:8080/job/build-revision/%s/" % number 97 } 98 99 100 def make_job_data(): 101 return { 102 "actions": [ 103 { 104 "parameterDefinitions": [ 105 { 106 "defaultParameterValue": { 107 "value": "1.18.1" 108 }, 109 "description": "", 110 "name": "old_version", 111 "type": "StringParameterDefinition" 112 } 113 ] 114 }, 115 {} 116 ], 117 "buildable": True, 118 "builds": [ 119 { 120 "number": 1510, 121 "url": "http://jenkins:8080/job/ting/1510/" 122 } 123 ], 124 "color": "red", 125 "concurrentBuild": False, 126 "description": "", 127 "displayName": "ting", 128 "downstreamProjects": [], 129 "firstBuild": { 130 "number": 1, 131 "url": "http://jenkins:8080/job/ting/1/" 132 }, 133 "healthReport": [ 134 { 135 "description": "Build stability: All recent builds failed.", 136 "iconUrl": "health-00to19.png", 137 "score": 0 138 } 139 ], 140 "inQueue": False, 141 "keepDependencies": False, 142 "lastBuild": { 143 "number": 1510, 144 "url": "http://jenkins:8080/job/ting/1510/" 145 }, 146 "lastCompletedBuild": { 147 "number": 1510, 148 "url": "http://jenkins:8080/job/ting/1510/" 149 }, 150 "lastFailedBuild": { 151 "number": 1510, 152 "url": "http://jenkins:8080/job/ting/1510/" 153 }, 154 "lastStableBuild": { 155 "number": 1392, 156 "url": "http://jenkins:8080/job/ting/1392/" 157 }, 158 "lastSuccessfulBuild": { 159 "number": 1392, 160 "url": "http://jenkins:8080/job/ting/1392/" 161 }, 162 "lastUnstableBuild": None, 163 "lastUnsuccessfulBuild": { 164 "number": 1510, 165 "url": "http://jenkins:8080/job/ting/1510/" 166 }, 167 "name": "ting", 168 "nextBuildNumber": 1511, 169 "property": [ 170 {}, 171 { 172 "parameterDefinitions": [ 173 { 174 "defaultParameterValue": { 175 "name": "old_version", 176 "value": "1.18.1" 177 }, 178 "description": "", 179 "name": "old_version", 180 "type": "StringParameterDefinition" 181 }, 182 ] 183 } 184 ], 185 "queueItem": None, 186 "upstreamProjects": [], 187 "url": "http://jenkins:8080/job/ting/" 188 } 189 190 191 class JujuCITestCase(FakeHomeTestCase): 192 193 def test_get_credentials(self): 194 self.assertEqual( 195 get_credentials(Namespace(user='jrandom', password='password1')), 196 Credentials('jrandom', 'password1')) 197 198 def test_get_credentials_no_user(self): 199 self.assertIs(get_credentials(Namespace()), None) 200 201 def test_get_credentials_no_value(self): 202 with self.assertRaisesRegexp( 203 CredentialsMissing, 204 'Jenkins username and/or password not supplied.'): 205 get_credentials(Namespace(user=None, password='password1')) 206 with self.assertRaisesRegexp( 207 CredentialsMissing, 208 'Jenkins username and/or password not supplied.'): 209 get_credentials(Namespace(user='jrandom', password=None)) 210 211 def test_main_list_options(self): 212 print_list = [] 213 with patch('jujuci.print_now', side_effect=print_list.append): 214 with patch('jujuci.list_artifacts') as mock: 215 main(['-d', '-v', 'list', '-b', '1234', 'foo', '*.tar.gz', 216 '--user', 'jrandom', '--password', '1password']) 217 args, kwargs = mock.call_args 218 self.assertEqual((Credentials('jrandom', '1password'), 'foo', 219 '1234', '*.tar.gz'), args) 220 self.assertTrue(kwargs['verbose']) 221 self.assertEqual(print_list, ['Done.']) 222 223 def test_main_setup_workspace_options(self): 224 print_list = [] 225 with patch('jujuci.print_now', side_effect=print_list.append): 226 with patch('jujuci.setup_workspace', autospec=True) as mock: 227 main(['-d', '-v', 'setup-workspace', './foo']) 228 args, kwargs = mock.call_args 229 self.assertEqual(('./foo', ), args) 230 self.assertTrue(kwargs['dry_run']) 231 self.assertTrue(kwargs['verbose']) 232 self.assertEqual(print_list, ['Done.']) 233 234 def test_get_build_data(self): 235 expected_data = make_build_data(1234) 236 json_io = StringIO(json.dumps(expected_data)) 237 with patch('urllib2.urlopen', return_value=json_io) as mock: 238 build_data = get_build_data( 239 'http://foo:8080', Credentials('jrandom', '1password'), 'bar', 240 '1234') 241 self.assertEqual(1, mock.call_count) 242 request = mock.mock_calls[0][1][0] 243 self.assertRequest( 244 request, 'http://foo:8080/job/bar/1234/api/json', 245 {'Authorization': 'Basic anJhbmRvbToxcGFzc3dvcmQ='}) 246 self.assertEqual(expected_data, build_data) 247 248 def test_get_job_data(self): 249 expected_data = make_job_data() 250 json_io = StringIO(json.dumps(expected_data)) 251 with patch('urllib2.urlopen', return_value=json_io) as mock: 252 build_data = get_job_data( 253 'http://foo:8080', Credentials('jrandom', '1password'), 'ting') 254 self.assertEqual(1, mock.call_count) 255 request = mock.mock_calls[0][1][0] 256 self.assertRequest( 257 request, 'http://foo:8080/job/ting/api/json', 258 {'Authorization': 'Basic anJhbmRvbToxcGFzc3dvcmQ='}) 259 self.assertEqual(expected_data, build_data) 260 261 def assertRequest(self, request, url, headers): 262 self.assertIs(request.__class__, urllib2.Request) 263 self.assertEqual(request.get_full_url(), url) 264 self.assertEqual(request.headers, headers) 265 266 def test_get_build_data_with_default_build(self): 267 expected_data = make_build_data() 268 json_io = StringIO(json.dumps(expected_data)) 269 with patch('urllib2.urlopen', return_value=json_io) as mock: 270 get_build_data( 271 'http://foo:8080', Credentials('jrandom', '1password'), 'bar') 272 self.assertEqual(mock.call_count, 1) 273 self.assertRequest( 274 mock.mock_calls[0][1][0], 275 'http://foo:8080/job/bar/lastSuccessfulBuild/api/json', 276 {'Authorization': 'Basic anJhbmRvbToxcGFzc3dvcmQ='}) 277 278 def test_find_artifacts_all(self): 279 expected_data = make_build_data() 280 artifacts = find_artifacts(expected_data) 281 self.assertEqual( 282 ['buildvars.bash', 'buildvars.json', 283 'juju-core_1.22-alpha1.tar.gz'], 284 sorted(a.file_name for a in artifacts)) 285 286 def test_find_artifacts_glob_tarball(self): 287 expected_data = make_build_data() 288 artifacts = find_artifacts(expected_data, '*.tar.gz') 289 artifact = artifacts[0] 290 self.assertEqual('juju-core_1.22-alpha1.tar.gz', artifact.file_name) 291 self.assertEqual( 292 'http://jenkins:8080/job/build-revision/2112/' 293 'artifact/artifacts/juju-core_1.22-alpha1.tar.gz', 294 artifact.location) 295 296 def test_list_artifacts(self): 297 credentials = Credentials('jrandom', '1password') 298 build_data = make_build_data(1234) 299 with patch('jujuci.get_build_data', return_value=build_data) as mock: 300 with patch('jujuci.print_now') as pn_mock: 301 list_artifacts(credentials, 'foo', '1234', '*') 302 mock.assert_called_once_with(JENKINS_URL, credentials, 'foo', '1234') 303 files = sorted(call[1][0] for call in pn_mock.mock_calls) 304 self.assertEqual( 305 ['buildvars.bash', 'buildvars.json', 306 'juju-core_1.22-alpha1.tar.gz'], 307 files) 308 309 def test_setup_workspace(self): 310 with temp_dir() as base_dir: 311 workspace_dir = os.path.join(base_dir, 'workspace') 312 foo_dir = os.path.join(workspace_dir, 'foo') 313 os.makedirs(foo_dir) 314 with open(os.path.join(workspace_dir, 'old.txt'), 'w') as of: 315 of.write('old') 316 print_list = [] 317 with patch('jujuci.print_now', side_effect=print_list.append): 318 setup_workspace(workspace_dir, dry_run=False, verbose=False) 319 self.assertEqual(['artifacts'], os.listdir(workspace_dir)) 320 artifacts_dir = os.path.join(workspace_dir, 'artifacts') 321 self.assertEqual(['empty'], os.listdir(artifacts_dir)) 322 self.assertEqual( 323 print_list, 324 ['Removing old.txt', 'Removing foo', 'Creating artifacts dir.'] 325 ) 326 327 def test_add_artifacts_simple(self): 328 with temp_dir() as workspace_dir: 329 artifacts_dir = os.path.join(workspace_dir, 'artifacts') 330 os.mkdir(artifacts_dir) 331 for name in ['foo.tar.gz', 'bar.json', 'baz.txt', 332 'juju-core_1.2.3.tar.gz', 'juju-core-1.2.3.deb', 333 'buildvars.bash', 'buildvars.json']: 334 with open(os.path.join(workspace_dir, name), 'w') as nf: 335 nf.write(name) 336 globs = ['buildvars.*', 'juju-core_*.tar.gz', 'juju-*.deb'] 337 add_artifacts( 338 workspace_dir, globs, dry_run=False, verbose=False) 339 artifacts = sorted(os.listdir(artifacts_dir)) 340 expected = [ 341 'buildvars.bash', 'buildvars.json', 342 'juju-core-1.2.3.deb', 'juju-core_1.2.3.tar.gz'] 343 self.assertEqual(expected, artifacts) 344 345 def test_add_artifacts_deep(self): 346 with temp_dir() as workspace_dir: 347 artifacts_dir = os.path.join(workspace_dir, 'artifacts') 348 os.mkdir(artifacts_dir) 349 sub_dir = os.path.join(workspace_dir, 'sub_dir') 350 os.mkdir(sub_dir) 351 for name in ['foo.tar.gz', 'juju-core-1.2.3.deb']: 352 with open(os.path.join(sub_dir, name), 'w') as nf: 353 nf.write(name) 354 add_artifacts( 355 workspace_dir, ['sub_dir/*.deb'], dry_run=False, verbose=False) 356 artifacts = os.listdir(artifacts_dir) 357 self.assertEqual(['juju-core-1.2.3.deb'], artifacts) 358 359 360 class TestNamer(TestCase): 361 362 def test_factory(self): 363 with patch('subprocess.check_output', return_value=' amd42 \n'): 364 with patch('jujuci.get_distro_information', 365 return_value={'RELEASE': '42.42', 'CODENAME': 'wacky'}): 366 namer = Namer.factory() 367 self.assertIs(type(namer), Namer) 368 self.assertEqual(namer.arch, 'amd42') 369 self.assertEqual(namer.distro_release, '42.42') 370 self.assertEqual(namer.distro_series, 'wacky') 371 372 373 class TestPackageNamer(TestNamer): 374 375 def test_get_release_package(self): 376 package_namer = PackageNamer('amd42', '42.34', 'wacky') 377 self.assertEqual( 378 package_namer.get_release_package('27.6'), 379 'juju-core_27.6-0ubuntu1~42.34.1~juju1_amd42.deb') 380 381 def test_get_certification_package(self): 382 package_namer = PackageNamer('amd42', '42.34', 'wacky') 383 self.assertEqual( 384 package_namer.get_certification_package('27.6~0ubuntu1'), 385 'juju-core_27.6~0ubuntu1~42.34.1_amd42.deb') 386 387 388 class TestJobNamer(TestNamer): 389 390 def test_get_build_binary(self): 391 self.assertEqual( 392 JobNamer('ppc64el', '42.34', 'wacky').get_build_binary_job(), 393 'build-binary-wacky-ppc64el') 394 395 396 class TestAcquireBinary(TestCase): 397 398 def fake_call(self, args, parent='bin'): 399 dest = args[3] 400 parent_path = os.path.join(dest, 'bar', parent) 401 os.makedirs(parent_path) 402 bin_path = os.path.join(parent_path, 'juju') 403 open(bin_path, 'w').close() 404 405 def fake_call_completion(self, args): 406 return self.fake_call(args, parent='bash_completion.d') 407 408 def test_avoids_bash_completion(self): 409 with temp_dir() as workspace: 410 with patch('subprocess.check_call', 411 side_effect=self.fake_call_completion): 412 result = acquire_binary(None, workspace) 413 self.assertIs(None, result)