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

« back to all changes in this revision

Viewing changes to tests/test_run_deployer.py

  • Committer: Aaron Bentley
  • Date: 2015-12-15 16:03:14 UTC
  • mto: This revision was merged to the branch mainline in revision 1197.
  • Revision ID: aaron.bentley@canonical.com-20151215160314-zsy2kn45fefnqlht
Switch FakeJujuClient to raise on accessing juju_home.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
from argparse import Namespace
2
2
import logging
3
3
import os
4
 
import pickle
5
4
import stat
6
5
import subprocess
7
6
from tempfile import NamedTemporaryFile
8
 
import unittest
 
7
from unittest import TestCase
9
8
 
10
 
from mock import (
11
 
    call,
12
 
    Mock,
13
 
    patch,
14
 
)
 
9
from mock import patch
15
10
 
16
11
from jujupy import (
17
12
    EnvJujuClient,
18
 
    JujuData,
 
13
    SimpleEnvironment,
 
14
    _temp_env as temp_env,
19
15
    )
20
16
from run_deployer import (
21
 
    apply_condition,
22
 
    assess_deployer,
23
17
    check_health,
24
 
    CLOCK_SKEW_SCRIPT,
25
 
    ErrUnitCondition,
26
 
    main,
27
18
    parse_args,
 
19
    run_deployer
28
20
    )
29
 
import tests
30
 
from tests.test_jujupy import fake_juju_client
31
 
 
32
 
 
33
 
class TestParseArgs(tests.TestCase):
 
21
 
 
22
 
 
23
class TestParseArgs(TestCase):
34
24
 
35
25
    def test_parse_args(self):
36
26
        args = parse_args(['/bundle/path', 'test_env', 'new/bin/juju',
40
30
        self.assertEqual(args.juju_bin, 'new/bin/juju')
41
31
        self.assertEqual(args.logs, '/tmp/logs')
42
32
        self.assertEqual(args.temp_env_name, 'test_job')
43
 
        self.assertEqual(args.allow_native_deploy, False)
44
33
        self.assertEqual(args.bundle_name, None)
45
34
        self.assertEqual(args.health_cmd, None)
46
35
        self.assertEqual(args.keep_env, False)
49
38
        self.assertEqual(args.series, None)
50
39
        self.assertEqual(args.debug, False)
51
40
        self.assertEqual(args.verbose, logging.INFO)
52
 
        self.assertEqual(args.upgrade, False)
53
 
        self.assertEqual(args.upgrade_condition, None)
54
 
        self.assertEqual(args.agent_timeout, 1200)
55
 
        self.assertEqual(args.workload_timeout, 1800)
56
 
 
57
 
    def test_allow_native_bundle(self):
58
 
        args = parse_args(['./bundle/path', 'an_env', './juju', './logs',
59
 
                           'temp_env', '--allow-native-deploy'])
60
 
        self.assertEqual(args.bundle_path, './bundle/path')
61
 
        self.assertEqual(args.env, 'an_env')
62
 
        self.assertEqual(args.juju_bin, './juju')
63
 
        self.assertEqual(args.logs, './logs')
64
 
        self.assertEqual(args.temp_env_name, 'temp_env')
65
 
        self.assertEqual(args.allow_native_deploy, True)
66
 
 
67
 
    def test_native_bundle_no_name(self):
68
 
        with tests.parse_error(self) as stderr:
69
 
            parse_args(['./bundle/path', 'an_env', './juju', './logs',
70
 
                        'temp_env', '--allow-native-deploy',
71
 
                        '--bundle-name', 'specific_bundle'])
72
 
        self.assertRegexpMatches(
73
 
            stderr.getvalue(),
74
 
            'error: cannot supply bundle name with native juju deploying$')
75
 
 
76
 
 
77
 
class TestMain(tests.FakeHomeTestCase):
78
 
 
79
 
    def test_basic_args(self):
80
 
        args = ['bundles', 'an-env', '/bin/juju', 'logs', 'deployer-env']
81
 
        env = JujuData('an-env')
82
 
        client = EnvJujuClient(env, '1.234-76', None)
83
 
        with patch('run_deployer.client_from_config',
84
 
                   return_value=client) as c_mock:
85
 
            with patch('run_deployer.boot_context'):
86
 
                with patch('run_deployer.assess_deployer') as ad_mock:
87
 
                    main(args)
88
 
        c_mock.assert_called_once_with('an-env', '/bin/juju', debug=False,
89
 
                                       soft_deadline=None)
90
 
        ad_mock.assert_called_once_with(parse_args(args), client, 1200, 1800)
91
 
 
92
 
    def test_basic_args_native_deploy(self):
93
 
        args = ['mediawiki-scalable.yaml', 'an-env', '/bin/juju', 'logs',
94
 
                'deployer-env', '--allow-native-deploy',
95
 
                '--bundle-verification-script',
96
 
                'verify_mediawiki_bundle.py']
97
 
        env = JujuData('an-env')
98
 
        client = EnvJujuClient(env, '1.234-76', None)
99
 
        with patch('run_deployer.client_from_config',
100
 
                   return_value=client) as c_mock:
101
 
            with patch('run_deployer.boot_context'):
102
 
                with patch('run_deployer.assess_deployer') as ad_mock:
103
 
                    with patch('run_deployer.run_command') as mb_mock:
104
 
                        main(args)
105
 
        c_mock.assert_called_once_with('an-env', '/bin/juju', debug=False,
106
 
                                       soft_deadline=None)
107
 
        ad_mock.assert_called_once_with(parse_args(args), client, 1200, 1800)
108
 
        client_ser = pickle.dumps(client)
109
 
        mb_mock.assert_called_once_with(['verify_mediawiki_bundle.py',
110
 
                                         client_ser])
111
 
 
112
 
    def test_basic_args_native_deploy_landscape(self):
113
 
        args = ['cs:~landscape/bundle/landscape-scalable', 'an-env',
114
 
                '/bin/juju', 'logs', 'deployer-env',
115
 
                '--allow-native-deploy',
116
 
                '--bundle-verification-script',
117
 
                'verify_landscape_bundle.py']
118
 
        env = JujuData('an-env')
119
 
        client = EnvJujuClient(env, '1.234-76', None)
120
 
        with patch('run_deployer.client_from_config',
121
 
                   return_value=client) as c_mock:
122
 
            with patch('run_deployer.boot_context'):
123
 
                with patch('run_deployer.assess_deployer') as ad_mock:
124
 
                        with patch('run_deployer.run_command') as rc:
125
 
                            main(args)
126
 
        c_mock.assert_called_once_with('an-env', '/bin/juju', debug=False,
127
 
                                       soft_deadline=None)
128
 
        ad_mock.assert_called_once_with(parse_args(args), client, 1200, 1800)
129
 
        client_ser = pickle.dumps(client)
130
 
        rc.assert_called_once_with(['verify_landscape_bundle.py',
131
 
                                   client_ser])
132
 
 
133
 
 
134
 
class TestAssessDeployer(tests.TestCase):
135
 
 
136
 
    @staticmethod
137
 
    def make_args(temp_env_name='foo', env='bar', series=None, agent_url=None,
138
 
                  agent_stream=None, juju_bin='', logs=None, keep_env=False,
139
 
                  health_cmd=None, debug=False, bundle_path='bundle.yaml',
140
 
                  bundle_name='bu', verbose=logging.INFO, region=None,
141
 
                  upgrade=False, upgrade_condition=None,
142
 
                  allow_native_deploy=False):
143
 
        return Namespace(
144
 
            temp_env_name=temp_env_name, env=env, series=series,
145
 
            agent_url=agent_url, agent_stream=agent_stream, juju_bin=juju_bin,
146
 
            logs=logs, keep_env=keep_env, health_cmd=health_cmd, debug=debug,
147
 
            bundle_path=bundle_path, bundle_name=bundle_name, verbose=verbose,
148
 
            region=region, upgrade=upgrade,
149
 
            allow_native_deploy=allow_native_deploy,
150
 
            upgrade_condition=upgrade_condition)
151
 
 
152
 
    def test_health(self):
153
 
        args = self.make_args(health_cmd='/tmp/check')
154
 
        client_mock = Mock(spec=EnvJujuClient)
155
 
        with patch('run_deployer.check_health', autospec=True) as ch_mock:
156
 
            assess_deployer(args, client_mock, 600, 1800)
157
 
        client_mock.deployer.assert_called_once_with('bundle.yaml', 'bu')
158
 
        client_mock.wait_for_workloads.assert_called_once_with(timeout=1800)
159
 
        environ = client_mock._shell_environ()
160
 
        ch_mock.assert_called_once_with('/tmp/check', 'foo', environ)
161
 
 
162
 
    def test_upgrade(self):
163
 
        args = self.make_args(juju_bin='new/juju', upgrade=True)
164
 
        client_mock = Mock(spec=EnvJujuClient)
165
 
        with patch('run_deployer.assess_upgrade', autospec=True) as au_mock:
166
 
            assess_deployer(args, client_mock, 600, 1800)
167
 
        client_mock.deployer.assert_called_once_with('bundle.yaml', 'bu')
168
 
        client_mock.show_status.assert_called_once_with()
169
 
        au_mock.assert_called_once_with(client_mock, 'new/juju')
170
 
        self.assertEqual(
171
 
            client_mock.wait_for_workloads.call_args_list,
172
 
            [call(timeout=1800), call()])
173
 
 
174
 
    def test_upgrade_and_health(self):
175
 
        args = self.make_args(health_cmd='/tmp/check', juju_bin='new/juju',
176
 
                              upgrade=True)
177
 
        client_mock = Mock(spec=EnvJujuClient)
178
 
        with patch('run_deployer.assess_upgrade', autospec=True) as au_mock:
179
 
            with patch('run_deployer.check_health', autospec=True) as ch_mock:
180
 
                assess_deployer(args, client_mock, 600, 1800)
181
 
        client_mock.deployer.assert_called_once_with('bundle.yaml', 'bu')
182
 
        client_mock.show_status.assert_called_once_with()
183
 
        au_mock.assert_called_once_with(client_mock, 'new/juju')
184
 
        self.assertEqual(
185
 
            client_mock.wait_for_workloads.call_args_list,
186
 
            [call(timeout=1800), call()])
187
 
        environ = client_mock._shell_environ()
188
 
        self.assertEqual(
189
 
            ch_mock.call_args_list, [call('/tmp/check', 'foo', environ)] * 2)
190
 
 
191
 
    @patch('run_deployer.boot_context', autospec=True)
192
 
    def test_run_deployer_upgrade(self, *args):
193
 
        args = self.make_args(
194
 
            juju_bin='baz/juju', upgrade=True,
195
 
            upgrade_condition=['bla/0:clock_skew', 'foo/1:fill_disk'])
196
 
        client = fake_juju_client()
197
 
        client.bootstrap()
198
 
        with patch('run_deployer.client_from_config', return_value=client):
199
 
            with patch('run_deployer.apply_condition') as ac_mock:
200
 
                with patch('run_deployer.assess_upgrade') as au_mock:
201
 
                    assess_deployer(args, client, 600, 1800)
202
 
        self.assertEqual(2, ac_mock.call_count)
203
 
        self.assertEqual(
204
 
            ac_mock.call_args_list,
205
 
            [call(client, 'bla/0:clock_skew'),
206
 
             call(client, 'foo/1:fill_disk')])
207
 
        au_mock.assert_called_once_with(client, 'baz/juju')
208
 
 
209
 
    def test_allow_native_deploy(self):
210
 
        args = self.make_args(allow_native_deploy=True)
211
 
        client_mock = Mock(spec=EnvJujuClient)
212
 
        assess_deployer(args, client_mock, 600, 1800)
213
 
        client_mock.deploy_bundle.assert_called_once_with('bundle.yaml')
214
 
        client_mock.wait_for_started.assert_called_once_with(timeout=600)
215
 
        client_mock.wait_for_workloads.assert_called_once_with(timeout=1800)
216
 
 
217
 
 
218
 
class FakeRemote():
219
 
    """Fake remote class for testing."""
220
 
 
221
 
    def __init__(self):
222
 
        self.series = 'foo'
223
 
 
224
 
    def is_windows(self):
225
 
        return False
226
 
 
227
 
    def run(self, command):
228
 
        self.command = command
229
 
 
230
 
 
231
 
class TestApplyCondition(tests.TestCase):
232
 
 
233
 
    def test_apply_condition_clock_skew(self):
234
 
        client = fake_juju_client()
235
 
        remote = FakeRemote()
236
 
        with patch('run_deployer.remote_from_unit',
237
 
                   return_value=remote, autospec=True) as ru_mock:
238
 
            apply_condition(client, 'bla/0:clock_skew')
239
 
        ru_mock.assert_called_once_with(client, 'bla/0')
240
 
        self.assertEqual(CLOCK_SKEW_SCRIPT, remote.command)
241
 
 
242
 
    def test_apply_condition_raises_ErrUnitCondition(self):
243
 
        client = fake_juju_client()
244
 
        remote = FakeRemote()
245
 
        with patch('run_deployer.remote_from_unit',
246
 
                   return_value=remote) as rfu_mock:
247
 
            with self.assertRaises(ErrUnitCondition):
248
 
                apply_condition(client, 'bla/0:foo')
249
 
            rfu_mock.assert_called_once_with(client, 'bla/0')
250
 
 
251
 
 
252
 
class TestIsHealthy(unittest.TestCase):
 
41
 
 
42
 
 
43
class TestRunDeployer(TestCase):
 
44
 
 
45
    def test_run_deployer(self):
 
46
        with patch('run_deployer.boot_context'):
 
47
            with patch('run_deployer.SimpleEnvironment.from_config',
 
48
                       return_value=SimpleEnvironment('bar')) as env:
 
49
                with patch('run_deployer.EnvJujuClient.by_version',
 
50
                           return_value=EnvJujuClient(env, '1.234-76', None)):
 
51
                    with patch('run_deployer.parse_args',
 
52
                               return_value=Namespace(
 
53
                                   temp_env_name='foo', env='bar', series=None,
 
54
                                   agent_url=None, agent_stream=None,
 
55
                                   juju_bin='', logs=None, keep_env=False,
 
56
                                   health_cmd=None, debug=False,
 
57
                                   bundle_path='', bundle_name='',
 
58
                                   verbose=logging.INFO, region=None,
 
59
                                   upgrade=False)):
 
60
                        with patch(
 
61
                                'run_deployer.EnvJujuClient.deployer') as dm:
 
62
                            with patch('run_deployer.check_health') as hm:
 
63
                                run_deployer()
 
64
        self.assertEqual(dm.call_count, 1)
 
65
        self.assertEqual(hm.call_count, 0)
 
66
 
 
67
    def test_run_deployer_health(self):
 
68
        with patch('run_deployer.boot_context'):
 
69
            with patch('run_deployer.SimpleEnvironment.from_config',
 
70
                       return_value=SimpleEnvironment('bar')) as env:
 
71
                with patch('run_deployer.EnvJujuClient.by_version',
 
72
                           return_value=EnvJujuClient(env, '1.234-76', None)):
 
73
                    with patch('run_deployer.parse_args',
 
74
                               return_value=Namespace(
 
75
                                   temp_env_name='foo', env='bar', series=None,
 
76
                                   agent_url=None, agent_stream=None,
 
77
                                   juju_bin='', logs=None, keep_env=False,
 
78
                                   health_cmd='/tmp/check', debug=False,
 
79
                                   bundle_path='', bundle_name='',
 
80
                                   verbose=logging.INFO, region=None,
 
81
                                   upgrade=False)):
 
82
                        with patch('run_deployer.EnvJujuClient.deployer'):
 
83
                            with patch('run_deployer.check_health') as hm:
 
84
                                run_deployer()
 
85
        self.assertEqual(hm.call_count, 1)
 
86
 
 
87
    def test_run_deployer_region(self):
 
88
        with temp_env({'environments': {'bar': {'type': 'bar'}}}):
 
89
            with patch('subprocess.check_output', return_value='foo'):
 
90
                with patch('subprocess.check_call', return_value='foo'):
 
91
                    with patch('run_deployer.boot_context') as bc_mock:
 
92
                        run_deployer(['foo', 'bar', 'baz/juju', 'qux', 'quxx',
 
93
                                      '--region', 'region-foo'])
 
94
        client = bc_mock.mock_calls[0][1][1]
 
95
        bc_mock.assert_called_once_with(
 
96
            'quxx', client, None, [], None, None, None, 'qux', False, False,
 
97
            region='region-foo')
 
98
 
 
99
 
 
100
class TestIsHealthy(TestCase):
253
101
 
254
102
    def test_check_health(self):
255
103
        SCRIPT = """#!/bin/bash\necho -n 'PASS'\nexit 0"""