34
35
class TestCheckEnvironment(unittest.TestCase):
37
38
'OS_USERNAME': 'os-user',
39
'GLANCE_OS_USERNAME': 'glance-os-user',
40
'GLANCE_OS_AUTH_URL': 'glance-url',
41
'GLANCE_OS_REGION_NAME': 'glance-region',
42
'GLANCE_OS_TENANT_NAME': 'glance-tenant',
43
'GLANCE_OS_PASSWORD': 'glance-password',
38
44
'OS_AUTH_URL': 'something.stack',
39
45
'CI_OAUTH_CONSUMER_KEY': 'key',
40
46
'CI_OAUTH_TOKEN': 'token',
52
58
'CI_CODE_SOURCE': None,
53
59
'CI_PRIVATE_PPAS_ONLY': None,
54
60
'CI_TEMPURL_EXPIRES': None,
61
'CI_TEMPURL_SIGNING_KEY': None,
62
'CI_KEYRING_URI': None,
63
'CI_KEYSERVER_URL': None,
55
64
'HP_ACCESS_KEY_ID': None,
56
65
'HP_TENANT_ID': None,
57
'HP_SECRET_KEY': None,
59
67
fixtures.isolate_from_env(self, ignored_env)
61
def test_check_environment_defaults(self):
69
@mock.patch('deploy.gen_random_key', return_value='RaMdOm_KeY')
70
def test_check_environment_defaults(self, mocked_gen_key):
62
71
# check that some of our values can be defaulted correctly:
63
72
env_required = self.DEFAULT_ENV.copy()
64
73
fixtures.isolate_from_env(self, env_required)
70
79
self.assertEqual(os.environ['CI_KEYRING_URI'], '')
72
81
os.environ['CI_KEYSERVER_URL'], 'keyserver.ubuntu.com')
73
# HP_* variables are set empty if the deployment is not
82
# CI_TEMPURL_SIGNING_KEY used for canonistack/prodstack TempURL
83
# generation and `deploy.py` generated a new random HMAC-SHA1
84
# (40 chars) key for each deployment.
85
self.assertEqual(os.environ['CI_TEMPURL_SIGNING_KEY'], 'RaMdOm_KeY')
86
# Other HP_* variables are set empty if the deployment is not
74
87
# targeted to HPCloud.
75
self.assertEqual(os.environ['HP_SECRET_KEY'], '')
76
88
self.assertEqual(os.environ['HP_ACCESS_KEY_ID'], '')
77
89
self.assertEqual(os.environ['HP_TENANT_ID'], '')
82
94
hp_env = self.DEFAULT_ENV.copy()
84
96
'OS_AUTH_URL': 'something.hpcloud',
85
'HP_SECRET_KEY': 'FROM_HORIZON',
97
'CI_TEMPURL_SIGNING_KEY': 'FROM_HORIZON',
86
98
'HP_ACCESS_KEY_ID': 'FROM_HORIZON',
87
99
'HP_TENANT_ID': 'FROM_HORIZON',
89
101
fixtures.isolate_from_env(self, hp_env)
90
102
deploy.check_environment()
104
def test_check_environment_hp_signing_key(self):
105
# check_environment bails out if it's a HPCloud deployment and
106
# it can't find the required CI_TEMPURL_SIGNING_KEY.
107
broken_hp_env = self.DEFAULT_ENV.copy()
108
broken_hp_env.update({
109
'OS_AUTH_URL': 'something.hpcloud',
110
'HP_ACCESS_KEY_ID': 'FROM_HORIZON',
111
'HP_TENANT_ID': 'FROM_HORIZON',
113
fixtures.isolate_from_env(self, broken_hp_env)
114
with self.assertRaises(SystemExit) as cm:
115
deploy.check_environment()
117
'CI_TEMPURL_SIGNING_KEY has to be defined as your HP access '
118
'\'secret_key\', which can be found in '
119
'https://horizon.hpcloud.com/.',
120
cm.exception.message)
92
122
def test_check_environment_hp_fails(self):
93
123
# check_environment bails out if it's a HPCloud deployment and
94
124
# it can't find the required HP_* variables.
95
125
broken_hp_env = self.DEFAULT_ENV.copy()
96
126
broken_hp_env.update({
97
127
'OS_AUTH_URL': 'something.hpcloud',
128
'CI_TEMPURL_SIGNING_KEY': 'FROM_HORIZON',
99
130
fixtures.isolate_from_env(self, broken_hp_env)
100
with self.assertRaises(SystemExit):
131
with self.assertRaises(SystemExit) as cm:
101
132
deploy.check_environment()
135
'ERROR: Missing required environment variables:',
138
'Please ensure the novarc file has been sourced.'],
139
cm.exception.message.splitlines())
103
141
def test_check_environment_fails(self):
104
142
# check_environment bails out if a valid novarc isn't sourced.
107
145
with self.assertRaises(SystemExit):
108
146
deploy.check_environment()
148
def test_gen_random_key(self):
149
# `gen_random_key` generates random alphanumeric keys of a
151
key_hmac_sha1 = deploy.gen_random_key()
152
self.assertTrue(key_hmac_sha1.isalnum())
153
self.assertTrue(40, len(key_hmac_sha1))
154
key_hmac_md5 = deploy.gen_random_key(length=32)
155
self.assertTrue(key_hmac_md5.isalnum())
156
self.assertTrue(32, len(key_hmac_md5))
111
159
class TestCheckDependencies(unittest.TestCase):
153
201
super(TestInstallDeployer, self).setUp()
154
202
fixtures.set_uniq_cwd(self)
156
def test_install_deployer(self):
204
@mock.patch('ci_utils.sourcecode.update_sourcecode')
205
def test_install_deployer(self, mocked_us):
157
206
fixtures.isolate_from_env(self, dict(PYTHONPATH=''))
158
# FIXME: calling build_sourcedeps is heavyweight and yet another hint
159
# the setup story needs love. -- vila 2014-04-29
208
def local_us(*args, **kwargs):
209
os.makedirs('juju-deployer/.bzr')
210
mocked_us.side_effect = local_us
160
211
deploy.build_sourcedeps('.')
161
212
deployer_dir = deploy.install_deployer('.')
162
213
self.addCleanup(shutil.rmtree, deployer_dir)
355
407
fixtures.set_uniq_cwd(self)
357
409
def test_build_charms(self):
358
charmsdir = tempfile.mkdtemp()
359
self.addCleanup(shutil.rmtree, charmsdir)
360
p = os.path.join(charmsdir, 'precise')
410
# `build_charms` builds tree charms, copies them to the working-dir
411
# and sets JUJU_REPOSITORY.
412
charms_dir = tempfile.mkdtemp()
413
self.addCleanup(shutil.rmtree, charms_dir)
414
working_dir = tempfile.mkdtemp()
415
self.addCleanup(shutil.rmtree, working_dir)
416
# Creates 'tree' fake-charms directories.
419
# | - charm2 (Makefile for creating 'make_called')
420
p = os.path.join(charms_dir, 'precise')
362
422
charm1 = os.path.join(p, 'charm1')
366
426
with open(os.path.join(charm2, 'Makefile'), 'w') as f:
367
427
f.write('all:\n')
368
f.write('\tmkdir ../build_charms_should_delete\n')
369
# webui is precious and should not be deleted
370
f.write('\tmkdir ../webui\n')
371
f.write('\ttouch make_called\n')
373
clean = deploy.build_charms(charmsdir)
376
self.assertTrue(os.path.exists(os.path.join(charm2, 'make_called')))
377
self.assertItemsEqual(['charm1', 'charm2', 'webui'], os.listdir(p))
428
f.write('\t@touch make_called\n')
429
# Copy the unbuilt tree for simulating a pre-existing working_dir.
430
charms_copy = os.path.join(working_dir, 'charms')
431
dir_util.copy_tree(charms_dir, charms_copy)
432
# Track charm built indicators. Both tree and working-dir are unbuilt.
433
built_path = 'precise/charm2/make_called'
434
tree_built = os.path.join(charms_dir, built_path)
435
copy_built = os.path.join(charms_copy, built_path)
436
self.assertFalse(os.path.exists(tree_built))
437
self.assertFalse(os.path.exists(copy_built))
439
deploy.build_charms(working_dir, charms_dir)
441
self.assertTrue(os.path.exists(tree_built))
442
self.assertTrue(os.path.exists(copy_built))
443
self.assertItemsEqual(['charms'], os.listdir(working_dir))
444
self.assertItemsEqual(os.listdir(charms_dir), os.listdir(charms_copy))
446
os.path.join(charms_copy), os.environ['JUJU_REPOSITORY'])
380
449
class TestPrivateIP(unittest.TestCase):
395
464
self.assertTrue(deploy.private_IP('192.168.0.16'))
398
class TestInstallAmulet(unittest.TestCase):
401
super(TestInstallAmulet, self).setUp()
402
fixtures.set_uniq_cwd(self)
404
def test_install_amulet(self):
405
fixtures.override_env(self, 'PYTHONPATH', '')
406
# FIXME: calling build_sourcedeps is heavyweight and yet another hint
407
# the setup story needs love. -- vila 2014-04-29
408
deploy.build_sourcedeps('.')
409
deploy.install_amulet('.')
410
self.assertTrue(os.path.exists(os.path.join('amulet', '.bzr')))
411
self.assertEqual(os.path.join(self.uniq_dir, 'amulet'),
412
os.environ['PYTHONPATH'])
415
467
class TestNeedsBotstrap(unittest.TestCase):
417
469
@mock.patch('deploy._get_control_bucket',
439
491
dcb.assert_called_with()
494
class TestGetEnvironment(unittest.TestCase):
496
super(TestGetEnvironment, self).setUp()
497
fixtures.set_uniq_cwd(self)
498
fixtures.isolate_from_env(
499
self, dict(HOME=self.uniq_dir, JUJU_HOME=None, JUJU_ENV=None))
501
self.juju_home = os.path.join(os.environ['HOME'], '.juju')
503
def test_get_juju_home(self):
504
juju_home = '~/.juju/'
505
os.environ['JUJU_HOME'] = juju_home
506
self.assertEquals(juju_home, deploy._get_juju_home())
508
def test_get_juju_home_unset(self):
509
self.assertEquals(self.juju_home, deploy._get_juju_home())
511
def test_get_juju_env_os_environ_set(self):
513
os.environ['JUJU_ENV'] = env
514
self.assertEquals(env, deploy._get_juju_env())
516
def test_get_juju_env_current_env(self):
518
with open(os.path.join(
519
self.juju_home, 'current-environment'), 'w') as fp:
521
self.assertEquals(env, deploy._get_juju_env())
523
def test_get_juju_env_default(self):
529
'default-series': 'precise',
530
'use-floating-ip': False,
534
with open(os.path.join(
535
self.juju_home, 'environments.yaml'), 'w') as f:
536
yaml.safe_dump(env, f)
537
self.assertEquals('hp', deploy._get_juju_env())
540
class TestUtilityFunctions(unittest.TestCase):
542
def test_juju_status(self):
543
mocked = {'environment': 'local', 'machines': {}, 'services': {}}
544
mocked = yaml.safe_dump(mocked)
545
with mock.patch('subprocess.check_output', return_value=mocked):
546
status = deploy.juju_status()
547
self.assertEqual('local', status['environment'])
442
550
if __name__ == '__main__':