def setUp(self): mock_opsworks = MagicMock(spec_set=boto3.client('opsworks')) mock_opsworks.describe_stacks.return_value = { 'Stacks': [ {'StackId': 'abcd1234', 'Name': 'test-stack'} ] } # must provide an 'admin' instance for mh controller creation mock_opsworks.describe_instances.return_value = { 'Instances': [{ 'InstanceId': '1', 'Hostname': 'admin1', 'PublicDns': 'http://mh.example.edu' }] } self.mock_boto3 = patch( 'boto3.client', autospec=True, return_value=mock_opsworks ) self.mock_mh = patch('moscaler.opsworks.MatterhornController') self.mock_boto3.start() self.mock_mh.start() self.addCleanup(self.mock_boto3.stop) self.addCleanup(self.mock_mh.stop) self.controller = OpsworksController('test-stack')
class TestOpsworksController(unittest.TestCase): def setUp(self): mock_opsworks = MagicMock(spec_set=boto3.client('opsworks')) mock_opsworks.describe_stacks.return_value = { 'Stacks': [ {'StackId': 'abcd1234', 'Name': 'test-stack'} ] } # must provide an 'admin' instance for mh controller creation mock_opsworks.describe_instances.return_value = { 'Instances': [{ 'InstanceId': '1', 'Hostname': 'admin1', 'PublicDns': 'http://mh.example.edu' }] } self.mock_boto3 = patch( 'boto3.client', autospec=True, return_value=mock_opsworks ) self.mock_mh = patch('moscaler.opsworks.MatterhornController') self.mock_boto3.start() self.mock_mh.start() self.addCleanup(self.mock_boto3.stop) self.addCleanup(self.mock_mh.stop) self.controller = OpsworksController('test-stack') def _create_instance(self, inst_dict, wrap=False): instance = OpsworksInstance(inst_dict, self.controller) if wrap: return MagicMock(wraps=instance) return instance def _create_instances(self, *inst_dicts, **kwargs): return [self._create_instance(x, **kwargs) for x in inst_dicts] def test_instances(self): self.controller._instances = self._create_instances( {'InstanceId': 1}, {'InstanceId': 2, 'AutoScalingType': 'foo'}, {'InstanceId': 3} ) self.assertEqual( [1,3], [x.InstanceId for x in self.controller.instances] ) def test_workers(self): self.controller._instances = self._create_instances( {'InstanceId': 1, 'Hostname': 'workers1'}, {'InstanceId': 2, 'Hostname': 'workers2'}, {'InstanceId': 3, 'Hostname': 'engage1'}, {'InstanceId': 4, 'Hostname': 'workers3'}, {'InstanceId': 5, 'Hostname': 'admin1'}, ) self.assertEqual( [1,2,4], [x.InstanceId for x in self.controller.workers] ) def test_online_workers(self): self.controller._instances = self._create_instances( {'InstanceId': 1, 'Hostname': 'storage1'}, {'InstanceId': 2, 'Hostname': 'workers1', 'Status': 'stopped'}, {'InstanceId': 3, 'Hostname': 'workers2', 'Status': 'online'}, {'InstanceId': 4, 'Hostname': 'workers3', 'Status': 'online'}, {'InstanceId': 5, 'Hostname': 'admin1'}, ) self.assertEqual( [3,4], [x.InstanceId for x in self.controller.online_workers] ) def test_pending_workers(self): self.controller._instances = self._create_instances( {'InstanceId': 1, 'Hostname': 'storage1', 'Status': 'online'}, {'InstanceId': 2, 'Hostname': 'workers1', 'Status': 'booting'}, {'InstanceId': 3, 'Hostname': 'workers2', 'Status': 'online'}, {'InstanceId': 4, 'Hostname': 'workers3', 'Status': 'stopping'}, {'InstanceId': 5, 'Hostname': 'admin1', 'Status': 'online'}, {'InstanceId': 6, 'Hostname': 'engage1', 'Status': 'pending'}, {'InstanceId': 7, 'Hostname': 'workers4', 'Status': 'pending'}, ) self.assertEqual( [2,7], [x.InstanceId for x in self.controller.pending_workers] ) def test_admin(self): self.controller._instances = self._create_instances( {'InstanceId': 1, 'Hostname': 'workers1'}, {'InstanceId': 2, 'Hostname': 'engage1'}, {'InstanceId': 3, 'Hostname': 'admin1'} ) self.assertEqual(self.controller.admin.InstanceId, 3) def test_no_admin(self): self.controller._instances = self._create_instances( {'InstanceId': 1, 'Hostname': 'workers1'}, {'InstanceId': 2, 'Hostname': 'engage1'}, {'InstanceId': 3, 'Hostname': 'workers2'} ) self.assertRaises( OpsworksControllerException, self.controller.__getattribute__, 'admin' ) def test_scale_to(self): self.controller._instances = self._create_instances( {'Hostname': 'workers1', 'Status': 'online'}, {'Hostname': 'workers2', 'Status': 'online'}, {'Hostname': 'workers3', 'Status': 'online'}, {'Hostname': 'workers4', 'Status': 'online'} ) with patch.object(self.controller, '_scale_up', autospec=True) as scale_up: self.controller.scale_to(9) scale_up.assert_called_once_with(5, False) with patch.object(self.controller, '_scale_down', autospec=True) as scale_down: self.controller.scale_to(2) scale_down.assert_called_once_with(2) self.assertRaises( OpsworksControllerException, self.controller.scale_to, 4 ) def test_scale_down_not_enough_workers(self): self.controller._instances = self._create_instances( {'Hostname': 'workers1', 'Status': 'online'}, {'Hostname': 'workers2', 'Status': 'online'}, {'Hostname': 'workers3', 'Status': 'running_setup'}, ) self.assertRaisesRegexp( OpsworksScalingException, "does not have 4 online or pending", self.controller._scale_down, 4 ) @patch.dict(os.environ, {'MOSCALER_MIN_WORKERS': '3'}) def test_scale_down_min_workers(self): self.controller._instances = self._create_instances( {'Hostname': 'workers1', 'Status': 'online'}, {'Hostname': 'workers2', 'Status': 'online'}, {'Hostname': 'workers3', 'Status': 'online'}, {'Hostname': 'workers4', 'Status': 'online'}, ) self.assertRaisesRegexp( OpsworksScalingException, "Stopping 2 workers", self.controller._scale_down, 2 ) def test_scale_down(self): self.controller._instances = self._create_instances( {'InstanceId': '1', 'Hostname': 'workers1', 'Status': 'online'}, {'InstanceId': '2', 'Hostname': 'workers2', 'Status': 'online'}, {'InstanceId': '3', 'Hostname': 'workers3', 'Status': 'online'}, {'InstanceId': '4', 'Hostname': 'workers4', 'Status': 'online'}, wrap=True ) with patch.object(self.controller, '_get_workers_to_stop') as get_workers: get_workers.return_value = self.controller._instances[:2] self.controller._scale_down(2, check_uptime=False) self.assertEqual( [1,1,0,0], [x.stop.call_count for x in self.controller._instances] ) def test_workers_to_stop_uptime_check(self): instances = self._create_instances( {'InstanceId': '1', 'Hostname': 'workers1', 'Status': 'online'}, {'InstanceId': '2', 'Hostname': 'workers2', 'Status': 'online'}, {'InstanceId': '3', 'Hostname': 'workers3', 'Status': 'online'}, {'InstanceId': '4', 'Hostname': 'workers4', 'Status': 'online'}, wrap=True ) instances[0]._mock_wraps.ec2_inst = MagicMock(launch_time=datetime(2015, 11, 13, 10, 45, 0)) instances[1]._mock_wraps.ec2_inst = MagicMock(launch_time=datetime(2015, 11, 13, 10, 20, 0)) instances[2]._mock_wraps.ec2_inst = MagicMock(launch_time=datetime(2015, 11, 13, 10, 04, 0))