Example #1
0
 def test_run_with_unit(self):
     env = JujuData("an-env", {"type": "nonlocal"})
     client = ModelClient(env, None, None)
     unit = "a-application/0"
     remote = remote_from_unit(client, unit, series="trusty")
     with patch.object(client, "get_juju_output") as mock_cmd:
         mock_cmd.return_value = "contents of /a/file"
         output = remote.run("cat /a/file")
         self.assertEqual(output, "contents of /a/file")
     mock_cmd.assert_called_once_with("ssh",
                                      unit,
                                      "cat /a/file",
                                      timeout=120)
Example #2
0
 def test_basic_args(self):
     args = ['bundles', 'an-env', '/bin/juju', 'logs', 'deployer-env']
     env = JujuData('an-env')
     client = ModelClient(env, '1.234-76', None)
     with patch('run_deployer.client_from_config',
                return_value=client) as c_mock:
         with patch('run_deployer.boot_context'):
             with patch('run_deployer.assess_deployer') as ad_mock:
                 main(args)
     c_mock.assert_called_once_with('an-env',
                                    '/bin/juju',
                                    debug=False,
                                    soft_deadline=None)
     ad_mock.assert_called_once_with(parse_args(args), client, 1200, 1800)
Example #3
0
 def test_is_healthy_fail(self):
     SCRIPT = """#!/bin/bash\necho -n 'FAIL'\nexit 1"""
     client = ModelClient(JujuData('foo', {}), None, '/foo/juju')
     with NamedTemporaryFile(delete=False) as health_script:
         health_script.write(SCRIPT)
         os.fchmod(health_script.fileno(), stat.S_IEXEC | stat.S_IREAD)
         health_script.close()
         monkey_runner = MonkeyRunner('foo',
                                      client,
                                      health_checker=health_script.name)
         with patch('logging.error') as le_mock:
             result = monkey_runner.is_healthy()
         os.unlink(health_script.name)
         self.assertFalse(result)
         self.assertEqual(le_mock.call_args[0][0], 'FAIL')
Example #4
0
 def test_wait_for_chaos_started(self):
     client = ModelClient(JujuData('foo', {}), None, '/foo')
     runner = MonkeyRunner('foo', client)
     units = [('blib', 'blab')]
     with patch.object(runner,
                       'iter_chaos_monkey_units',
                       autospec=True,
                       return_value=units) as ic_mock:
         with patch.object(runner,
                           'get_unit_status',
                           autospec=True,
                           return_value='running') as us_mock:
             returned = runner.wait_for_chaos(state='start')
     self.assertEqual(returned, None)
     self.assertEqual(ic_mock.call_count, 1)
     self.assertEqual(us_mock.call_count, 1)
Example #5
0
 def test_background_chaos_exits(self):
     client = ModelClient(JujuData('foo', {}), None, '/foo/juju')
     with patch('chaos.MonkeyRunner.deploy_chaos_monkey', autospec=True):
         with patch('chaos.MonkeyRunner.unleash_once', autospec=True):
             with patch('chaos.MonkeyRunner.wait_for_chaos', autospec=True):
                 with patch('chaos.remote_from_unit'):
                     with patch('remote.SSHRemote.copy'):
                         with patch('logging.exception') as le_mock:
                             with patch('sys.exit', autospec=True) as sm:
                                 log_dir = mkdtemp()
                                 with background_chaos(
                                         'foo', client, log_dir, 1):
                                     raise Exception()
                         rmtree(log_dir)
     self.assertEqual(1, le_mock.call_count)
     sm.assert_called_once_with(1)
Example #6
0
 def test_cat_on_windows(self):
     env = JujuData("an-env", {"type": "nonlocal"})
     client = ModelClient(env, None, None)
     unit = "a-application/0"
     with patch.object(client, "get_status", autospec=True) as st:
         st.return_value = Status.from_text(self.win2012hvr2_status_output)
         response = winrm.Response(("contents of /a/file", "", 0))
         remote = remote_from_unit(client, unit)
         with patch.object(remote.session,
                           "run_cmd",
                           autospec=True,
                           return_value=response) as mock_run:
             output = remote.cat("/a/file")
             self.assertEqual(output, "contents of /a/file")
     st.assert_called_once_with()
     mock_run.assert_called_once_with("type", ["/a/file"])
Example #7
0
    def test_deploy_chaos_monkey(self):
        def output(*args, **kwargs):
            status = yaml.safe_dump({
                'machines': {
                    '0': {
                        'agent-state': 'started'
                    }
                },
                'applications': {
                    'ser1': {
                        'units': {
                            'bar': {
                                'agent-state': 'started',
                                'subordinates': {
                                    'chaos-monkey/1': {
                                        'agent-state': 'started'
                                    }
                                }
                            }
                        }
                    }
                }
            })
            output = {
                ('show-status', '--format', 'yaml'): status,
            }
            return output[args]

        client = ModelClient(JujuData('foo', {}), '1.25.0', '/foo/juju')
        with patch.object(client,
                          'get_juju_output',
                          side_effect=output,
                          autospec=True) as gjo_mock:
            with patch('subprocess.check_call', autospec=True) as cc_mock:
                monkey_runner = MonkeyRunner('foo', client, service='ser1')
                with patch('jujupy.client.GroupReporter._write',
                           autospec=True):
                    monkey_runner.deploy_chaos_monkey()
        assert_juju_call(self, cc_mock, client,
                         ('juju', '--show-log', 'deploy', '-m', 'foo:foo',
                          'local:chaos-monkey'), 0)
        assert_juju_call(self, cc_mock, client,
                         ('juju', '--show-log', 'add-relation', '-m',
                          'foo:foo', 'ser1', 'chaos-monkey'), 1)
        self.assertEqual(cc_mock.call_count, 2)
        self.assertEqual(gjo_mock.call_count, 2)
    def test_run_finally(self):
        do_finally = MagicMock()

        def fake_iter_steps():
            try:
                yield {'bootstrap_host': 'foo'}
            finally:
                do_finally()

        client = ModelClient(
            JujuData('foo', {'type': 'local'}), '1.234-76', None)
        bs_manager = make_bootstrap_manager(client)
        quickstart = QuickstartTest(bs_manager, '/tmp/bundle.yaml', 2)
        with patch.object(quickstart, 'iter_steps',
                          side_effect=fake_iter_steps):
            quickstart.run()
        do_finally.assert_called_once_with()
Example #9
0
 def test_is_healthy_with_no_execute_perms(self):
     SCRIPT = """#!/bin/bash\nexit 0"""
     client = ModelClient(JujuData('foo', {}), None, '/foo/juju')
     with NamedTemporaryFile(delete=False) as health_script:
         health_script.write(SCRIPT)
         os.fchmod(health_script.fileno(), stat.S_IREAD)
         health_script.close()
         monkey_runner = MonkeyRunner('foo',
                                      client,
                                      health_checker=health_script.name)
         with patch('logging.error') as le_mock:
             with self.assertRaises(OSError):
                 monkey_runner.is_healthy()
         os.unlink(health_script.name)
     self.assertRegexpMatches(
         le_mock.call_args[0][0],
         r'The health check failed to execute with: \[Errno 13\].*')
Example #10
0
 def test_run_cmd(self):
     env = JujuData("an-env", {"type": "nonlocal"})
     client = ModelClient(env, None, None)
     unit = "a-application/0"
     with patch.object(client, "get_status", autospec=True) as st:
         st.return_value = Status.from_text(self.win2012hvr2_status_output)
         response = winrm.Response(("some out", "some err", 0))
         remote = remote_from_unit(client, unit)
         with patch.object(remote.session,
                           "run_cmd",
                           autospec=True,
                           return_value=response) as mock_run:
             output = remote.run_cmd(
                 ["C:\\Program Files\\bin.exe", "/IN", "Bob's Stuff"])
             self.assertEqual(output, response)
     st.assert_called_once_with()
     mock_run.assert_called_once_with('"C:\\Program Files\\bin.exe"',
                                      ['/IN "Bob\'s Stuff"'])
    def test_run_exception(self):
        tear_down = MagicMock()

        def fake_iter_steps():
            try:
                yield {'bootstrap_host': 'foo'}
            except:
                tear_down()

        client = ModelClient(
            JujuData('foo', {'type': 'local'}), '1.234-76', None)
        bs_manager = make_bootstrap_manager(client)
        quickstart = QuickstartTest(bs_manager, '/tmp/bundle.yaml', 2)
        with patch.object(quickstart, 'iter_steps',
                          side_effect=fake_iter_steps):
            with self.assertRaises(BaseException):
                with patch('logging.info', side_effect=Exception):
                    quickstart.run()
        tear_down.assert_called_once_with()
Example #12
0
 def test_run_default_command_error_fallback(self):
     env = JujuData("an-env", {"type": "nonlocal"})
     client = ModelClient(env, None, None)
     unit = "a-application/0"
     error = subprocess.CalledProcessError(1, "ssh", output="bad command")
     with patch.object(client, "get_status") as st:
         st.return_value = Status.from_text(self.precise_status_output)
         remote = remote_from_unit(client, unit)
         with patch.object(client, "get_juju_output") as mock_gjo:
             mock_gjo.side_effect = error
             with self.assertRaises(subprocess.CalledProcessError) as c:
                 remote.run("cat /a/file")
     self.assertIs(c.exception, error)
     mock_gjo.assert_called_once_with("ssh",
                                      unit,
                                      "cat /a/file",
                                      timeout=120)
     self.assertRegexpMatches(
         self.log_stream.getvalue(),
         "(?m)^WARNING juju ssh to 'a-application/0' failed, .*")
 def test_iter_steps(self):
     log_dir = use_context(self, temp_dir())
     client = ModelClient(
         JujuData('foo', {'type': 'local'}), '1.234-76', None)
     bs_manager = make_bootstrap_manager(client, log_dir=log_dir)
     quickstart = QuickstartTest(bs_manager, '/tmp/bundle.yaml', 2)
     steps = quickstart.iter_steps()
     with patch.object(client, 'quickstart') as qs_mock:
         # Test first yield
         with patch('jujupy.client.check_free_disk_space',
                    autospec=True):
             with patch.object(client, 'kill_controller',
                               autospec=True) as kill_mock:
                 step = steps.next()
     kill_mock.assert_called_once_with()
     qs_mock.assert_called_once_with('/tmp/bundle.yaml')
     expected = {'juju-quickstart': 'Returned from quickstart'}
     self.assertEqual(expected, step)
     with patch('deploy_stack.get_machine_dns_name',
                return_value='mocked_name') as dns_mock:
         # Test second yield
         with patch.object(client, 'get_controller_client') as gcc_mock:
             step = steps.next()
     dns_mock.assert_called_once_with(gcc_mock.return_value, '0')
     self.assertEqual('mocked_name', step['bootstrap_host'])
     with patch.object(client, 'wait_for_deploy_started') as wds_mock:
         # Test third yield
         step = steps.next()
     wds_mock.assert_called_once_with(2)
     self.assertEqual('Deploy stated', step['deploy_started'])
     with patch.object(client, 'wait_for_started') as ws_mock:
         # Test forth yield
         step = steps.next()
     ws_mock.assert_called_once_with(ANY)
     self.assertEqual('All Agents started', step['agents_started'])
     with patch('deploy_stack.safe_print_status'):
         with patch('deploy_stack.BootstrapManager.tear_down'):
             with patch('quickstart_deploy.BootstrapManager.dump_all_logs'):
                 with patch('jujupy.ModelClient.iter_model_clients',
                            return_value=[]):
                     steps.close()
Example #14
0
    def test_suppresses_deadline(self):
        client = ModelClient(JujuData('local', juju_home=''), None, None)
        with client_past_deadline(client):

            real_check_timeouts = client.check_timeouts

            def get_models():
                with real_check_timeouts():
                    return {'models': [{'name': 'TestModelName'}]}

            controller_client = Mock()
            controller_client.get_models.side_effect = get_models

            with patch.object(client,
                              'get_controller_client',
                              autospec=True,
                              return_value=controller_client):
                with patch.object(client, 'check_timeouts', autospec=True):
                    amm._wait_for_model_check(client,
                                              lambda x: 'test',
                                              timeout=60)
Example #15
0
 def test_basic_args_native_deploy_landscape(self):
     args = [
         'cs:~landscape/bundle/landscape-scalable', 'an-env', '/bin/juju',
         'logs', 'deployer-env', '--allow-native-deploy',
         '--bundle-verification-script', 'verify_landscape_bundle.py'
     ]
     env = JujuData('an-env')
     client = ModelClient(env, '1.234-76', None)
     with patch('run_deployer.client_from_config',
                return_value=client) as c_mock:
         with patch('run_deployer.boot_context'):
             with patch('run_deployer.assess_deployer') as ad_mock:
                 with patch('run_deployer.run_command') as rc:
                     main(args)
     c_mock.assert_called_once_with('an-env',
                                    '/bin/juju',
                                    debug=False,
                                    soft_deadline=None)
     ad_mock.assert_called_once_with(parse_args(args), client, 1200, 1800)
     client_ser = pickle.dumps(client)
     rc.assert_called_once_with(['verify_landscape_bundle.py', client_ser])
Example #16
0
 def test_copy_on_windows(self):
     env = JujuData("an-env", {"type": "nonlocal"})
     client = ModelClient(env, None, None)
     unit = "a-application/0"
     dest = "/local/path"
     with patch.object(client, "get_status", autospec=True) as st:
         st.return_value = Status.from_text(self.win2012hvr2_status_output)
         response = winrm.Response(("fake output", "", 0))
         remote = remote_from_unit(client, unit)
         with patch.object(remote.session,
                           "run_ps",
                           autospec=True,
                           return_value=response) as mock_run:
             with patch.object(remote,
                               "_encoded_copy_to_dir",
                               autospec=True) as mock_cpdir:
                 remote.copy(dest, ["C:\\logs\\*", "%APPDATA%\\*.log"])
     mock_cpdir.assert_called_once_with(dest, "fake output")
     st.assert_called_once_with()
     self.assertEquals(mock_run.call_count, 1)
     self.assertRegexpMatches(mock_run.call_args[0][0],
                              r'.*"C:\\logs\\[*]","%APPDATA%\\[*].log".*')
Example #17
0
    def test_unleash_once_raises_for_unexpected_action_output(self):
        def output(*args, **kwargs):
            status = yaml.safe_dump({
                'machines': {
                    '0': {
                        'agent-state': 'started'
                    }
                },
                'applications': {
                    'jenkins': {
                        'units': {
                            'foo': {
                                'subordinates': {
                                    'chaos-monkey/0': {
                                        'baz': 'qux'
                                    },
                                }
                            }
                        }
                    }
                }
            })
            output = {
                ('show-status', '--format', 'yaml'):
                status,
                ('run-action', 'chaos-monkey/0', 'start', 'mode=single', 'enablement-timeout=120'):
                'Action fail',
            }
            return output[args]

        client = ModelClient(JujuData('foo', {}), None, '/foo/juju')
        monkey_runner = MonkeyRunner('foo', client, service='jenkins')
        with patch.object(client,
                          'get_juju_output',
                          side_effect=output,
                          autospec=True):
            with self.assertRaisesRegexp(
                    Exception, 'Action id not found in output: Action fail'):
                monkey_runner.unleash_once()
Example #18
0
    def setUp(self):
        self.client = ModelClient(JujuData('foo', {'type': 'local'}),
                                  '1.234-76', None)

        def nil_func():
            return None

        self.juju_mock = JujuMock()
        self.ssh_mock = Mock()

        patches = [
            patch.object(self.client, 'juju', self.juju_mock.juju),
            patch.object(self.client, 'get_status', self.juju_mock.get_status),
            patch.object(self.client, 'juju_async', self.juju_mock.juju_async),
            patch.object(self.client, 'wait_for_started',
                         self.juju_mock.get_status),
            patch.object(self.client, 'get_juju_output', self.juju_mock.juju),
        ]

        for patcher in patches:
            patcher.start()
            self.addCleanup(patcher.stop)
    def setUp(self):
        self.client = ModelClient(
            JujuData('foo', {'type': 'local'}), '1.234-76', None)

        self.juju_mock = fake_juju_client(cls=JujuMock)
        self.juju_mock.bootstrap()
        self.ssh_mock = Mock()

        patches = [
            patch.object(self.client, 'juju', self.juju_mock.juju),
            patch.object(self.client, 'get_status', self.juju_mock.get_status),
            patch.object(self.client, 'juju_async', self.juju_mock.juju_async),
            patch.object(self.client, 'wait_for', lambda *args, **kw: None),
            patch.object(self.client, 'wait_for_started',
                         self.juju_mock.get_status),
            patch.object(
                self.client, 'get_juju_output',
                self.juju_mock.get_juju_output),
        ]

        for patcher in patches:
            patcher.start()
            self.addCleanup(patcher.stop)
Example #20
0
    def test_unleash_once(self):
        def output(*args, **kwargs):
            status = yaml.safe_dump({
                'machines': {
                    '0': {
                        'agent-state': 'started'
                    }
                },
                'applications': {
                    'jenkins': {
                        'units': {
                            'foo': {
                                'subordinates': {
                                    'chaos-monkey/0': {
                                        'baz': 'qux'
                                    },
                                    'not-chaos/0': {
                                        'qwe': 'rty'
                                    },
                                }
                            },
                            'bar': {
                                'subordinates': {
                                    'chaos-monkey/1': {
                                        'abc': '123'
                                    },
                                }
                            }
                        }
                    }
                }
            })
            charm_config = yaml.safe_dump({
                'charm': {'jenkins'},
                'service': {'jenkins'},
                'settings': {
                    'chaos-dir': {
                        'default': 'true',
                        'description': 'bla bla',
                        'type': 'string',
                        'value': '/tmp/charm-dir',
                    }
                }
            })
            output = {
                ('show-status', '--format', 'yaml'):
                status,
                ('get', 'jenkins'):
                charm_config,
                ('run-action', 'chaos-monkey/0', 'start', 'mode=single', 'enablement-timeout=120'):
                ('Action queued with id: '
                 'abcdabcdabcdabcdabcdabcdabcdabcdabcd'),
                ('run-action', 'chaos-monkey/0', 'start', 'mode=single', 'enablement-timeout=120', 'monkey-id=abcdabcdabcdabcdabcdabcdabcdabcdabcd'):
                ('Action queued with id: '
                 'efabefabefabefabefabefabefabefabefab'),
                ('run-action', 'chaos-monkey/1', 'start', 'mode=single', 'enablement-timeout=120'):
                ('Action queued with id: '
                 '123412341234123412341234123412341234'),
                ('run-action', 'chaos-monkey/1', 'start', 'mode=single', 'enablement-timeout=120', 'monkey-id=123412341234123412341234123412341234'):
                ('Action queued with id: '
                 '567856785678567856785678567856785678'),
            }
            return output[args]

        def output2(*args, **kwargs):
            status = yaml.safe_dump({
                'machines': {
                    '0': {
                        'agent-state': 'started'
                    }
                },
                'applications': {
                    'jenkins': {
                        'units': {
                            'bar': {
                                'subordinates': {
                                    'chaos-monkey/1': {
                                        'abc': '123'
                                    },
                                }
                            }
                        }
                    }
                }
            })
            output = {
                ('show-status', '--format', 'yaml'):
                status,
                ('run-action', 'chaos-monkey/1', 'start', 'mode=single', 'enablement-timeout=120', 'monkey-id=123412341234123412341234123412341234'):
                ('Action queued with id: '
                 'abcdabcdabcdabcdabcdabcdabcdabcdabcd'),
            }
            return output[args]

        client = ModelClient(JujuData('foo', {}), None, '/foo/juju')
        monkey_runner = MonkeyRunner('foo', client, service='jenkins')
        with patch.object(client,
                          'get_juju_output',
                          side_effect=output,
                          autospec=True) as gjo_mock:
            returned = monkey_runner.unleash_once()
        expected = ['abcd' * 9, '1234' * 9]
        self.assertEqual([
            call('show-status', '--format', 'yaml', controller=False),
            call('run-action', 'chaos-monkey/1', 'start', 'mode=single',
                 'enablement-timeout=120'),
            call('run-action', 'chaos-monkey/0', 'start', 'mode=single',
                 'enablement-timeout=120'),
        ], gjo_mock.call_args_list)
        self.assertEqual(['chaos-monkey/1', 'chaos-monkey/0'],
                         monkey_runner.monkey_ids.keys())
        self.assertEqual(len(monkey_runner.monkey_ids), 2)
        self.assertItemsEqual(returned, expected)
        with patch.object(client,
                          'get_juju_output',
                          side_effect=output,
                          autospec=True) as gjo_mock:
            monkey_runner.unleash_once()
        self.assertEqual([
            call('show-status', '--format', 'yaml', controller=False),
            call('run-action', 'chaos-monkey/1', 'start', 'mode=single',
                 'enablement-timeout=120',
                 'monkey-id=123412341234123412341234123412341234'),
            call('run-action', 'chaos-monkey/0', 'start', 'mode=single',
                 'enablement-timeout=120',
                 'monkey-id=abcdabcdabcdabcdabcdabcdabcdabcdabcd'),
        ], gjo_mock.call_args_list)
        self.assertTrue('1234', monkey_runner.monkey_ids['chaos-monkey/1'])
        # Test monkey_ids.get(unit_name) does not change on second call to
        # unleash_once()
        with patch.object(client,
                          'get_juju_output',
                          side_effect=output2,
                          autospec=True):
            monkey_runner.unleash_once()
        self.assertEqual('1234' * 9,
                         monkey_runner.monkey_ids['chaos-monkey/1'])
Example #21
0
 def test_wait_for_chaos_unexpected_state(self):
     client = ModelClient(JujuData('foo', {}), None, '/foo')
     runner = MonkeyRunner('foo', client)
     with self.assertRaisesRegexp(Exception, 'Unexpected state value: foo'):
         runner.wait_for_chaos(state='foo')
Example #22
0
 def test_returns_true_when_greater_than_21(self):
     client = ModelClient(JujuData('local', juju_home=''), None, None)
     self.assertTrue(amm.client_is_at_least_2_1(client))
Example #23
0
 def test_wait_for_chaos_complete_timesout(self):
     client = ModelClient(JujuData('foo', {}), None, '/foo')
     runner = MonkeyRunner('foo', client)
     with self.assertRaisesRegexp(Exception,
                                  'Chaos operations did not complete.'):
         runner.wait_for_chaos(timeout=0)
def fake_ModelClient(env, path=None, debug=None):
    return ModelClient(env=env, version='1.2.3.4', full_path=path)
Example #25
0
    def test_get_unit_status(self):
        def output(*args, **kwargs):
            status = yaml.safe_dump({
                'machines': {
                    '0': {
                        'agent-state': 'started'
                    }
                },
                'applications': {
                    'jenkins': {
                        'units': {
                            'foo': {
                                'subordinates': {
                                    'chaos-monkey/0': {
                                        'baz': 'qux'
                                    },
                                    'not-chaos/0': {
                                        'qwe': 'rty'
                                    },
                                }
                            },
                            'bar': {
                                'subordinates': {
                                    'chaos-monkey/1': {
                                        'abc': '123'
                                    },
                                }
                            }
                        }
                    }
                }
            })
            charm_config = yaml.safe_dump({
                'charm': {'jenkins'},
                'service': {'jenkins'},
                'settings': {
                    'chaos-dir': {
                        'default': 'true',
                        'description': 'bla bla',
                        'type': 'string',
                        'value': '/tmp/charm-dir',
                    }
                }
            })
            output = {
                ('status', ): status,
                ('config', 'chaos-monkey'): charm_config,
            }
            return output[args]

        client = ModelClient(JujuData('foo', {}), None, '/foo')
        monkey_runner = MonkeyRunner('foo', client, service='jenkins')
        monkey_runner.monkey_ids = {
            'chaos-monkey/0': 'workspace0',
            'chaos-monkey/1': 'workspace1'
        }
        with patch.object(client,
                          'get_juju_output',
                          side_effect=output,
                          autospec=True):
            with patch('subprocess.call', autospec=True,
                       return_value=0) as call_mock:
                for unit_name in ['chaos-monkey/1', 'chaos-monkey/0']:
                    self.assertEqual(monkey_runner.get_unit_status(unit_name),
                                     'running')
            self.assertEqual(call_mock.call_count, 2)
        with patch.object(client,
                          'get_juju_output',
                          side_effect=output,
                          autospec=True):
            with patch('subprocess.call', autospec=True,
                       return_value=1) as call_mock:
                for unit_name in ['chaos-monkey/1', 'chaos-monkey/0']:
                    self.assertEqual(monkey_runner.get_unit_status(unit_name),
                                     'done')
            self.assertEqual(call_mock.call_count, 2)