def test_attach_volumes_to_cluster_instance_not_running( self, mock_boto3, mock_run_inspection_cluster ): """Asserts that an exception is raised if instance exists but is not running.""" ami_id = util_helper.generate_dummy_image_id() volume_id = util_helper.generate_dummy_volume_id() account_helper.generate_image(ec2_ami_id=ami_id, status=MachineImage.PENDING) instance_id = util_helper.generate_dummy_instance_id() mock_list_container_instances = {"containerInstanceArns": [instance_id]} mock_ec2 = Mock() mock_ec2_instance = mock_ec2.Instance.return_value mock_ec2_instance.state = EC2_INSTANCE_STATE_STOPPED mock_ecs = MagicMock() mock_ecs.list_container_instances.return_value = mock_list_container_instances mock_boto3.client.return_value = mock_ecs mock_boto3.resource.return_value = mock_ec2 messages = [{"ami_id": ami_id, "volume_id": volume_id}] with self.assertRaises(AwsECSInstanceNotReady): tasks.attach_volumes_to_cluster(messages) mock_run_inspection_cluster.delay.assert_not_called()
def test_run_inspection_cluster_success(self, mock_boto3): """Asserts successful starting of the houndigrade task.""" mock_list_container_instances = { 'containerInstanceArns': [util_helper.generate_dummy_instance_id()] } mock_ec2 = Mock() mock_ecs = MagicMock() mock_ecs.list_container_instances.return_value = \ mock_list_container_instances mock_boto3.client.return_value = mock_ecs mock_boto3.resource.return_value = mock_ec2 messages = [{ 'ami_id': util_helper.generate_dummy_image_id(), 'volume_id': util_helper.generate_dummy_volume_id() }] tasks.run_inspection_cluster(messages) mock_ecs.list_container_instances.assert_called_once_with( cluster=settings.HOUNDIGRADE_ECS_CLUSTER_NAME) mock_ecs.describe_container_instances.assert_called_once_with( containerInstances=[ mock_list_container_instances['containerInstanceArns'][0] ], cluster=settings.HOUNDIGRADE_ECS_CLUSTER_NAME) mock_ecs.register_task_definition.assert_called_once() mock_ecs.run_task.assert_called_once() mock_ec2.Volume.assert_called_once_with(messages[0]['volume_id']) mock_ec2.Volume.return_value.attach_to_instance.assert_called_once()
def test_attach_volumes_to_cluster_with_marketplace_volume( self, mock_boto3, mock_run_inspection_cluster ): """Assert that ami is marked as inspected if marketplace volume.""" ami_id = util_helper.generate_dummy_image_id() volume_id = util_helper.generate_dummy_volume_id() image = account_helper.generate_image( ec2_ami_id=ami_id, status=MachineImage.PENDING ) instance_id = util_helper.generate_dummy_instance_id() mock_list_container_instances = {"containerInstanceArns": [instance_id]} mock_ec2 = Mock() mock_ec2_instance = mock_ec2.Instance.return_value mock_ec2_instance.state = EC2_INSTANCE_STATE_RUNNING mock_volume = mock_ec2.Volume.return_value mock_volume.attach_to_instance.side_effect = ClientError( error_response={ "Error": { "Code": "OptInRequired", "Message": "Marketplace Error", } }, operation_name=Mock(), ) mock_ecs = MagicMock() mock_ecs.list_container_instances.return_value = mock_list_container_instances mock_boto3.client.return_value = mock_ecs mock_boto3.resource.return_value = mock_ec2 messages = [{"ami_id": ami_id, "volume_id": volume_id}] tasks.attach_volumes_to_cluster(messages) image.refresh_from_db() self.assertEqual(image.status, MachineImage.INSPECTED) mock_ecs.list_container_instances.assert_called_once_with( cluster=settings.HOUNDIGRADE_ECS_CLUSTER_NAME, status="ACTIVE" ) mock_ecs.describe_container_instances.assert_called_once_with( containerInstances=[instance_id], cluster=settings.HOUNDIGRADE_ECS_CLUSTER_NAME, ) mock_ecs.register_task_definition.assert_not_called() mock_ecs.run_task.assert_not_called() mock_ec2.Volume.assert_called_once_with(volume_id) mock_ec2.Volume.return_value.attach_to_instance.assert_called_once() mock_run_inspection_cluster.delay.assert_not_called()
def test_attach_volumes_to_cluster_success( self, mock_boto3, mock_run_inspection_cluster ): """Asserts successful starting of the houndigrade task.""" ami_id = util_helper.generate_dummy_image_id() volume_id = util_helper.generate_dummy_volume_id() device_name = misc.generate_device_name(0) expected_ami_mountpoints = [(ami_id, device_name)] image = account_helper.generate_image( ec2_ami_id=ami_id, status=MachineImage.PENDING ) instance_id = util_helper.generate_dummy_instance_id() mock_list_container_instances = {"containerInstanceArns": [instance_id]} mock_ec2 = Mock() mock_ec2_instance = mock_ec2.Instance.return_value mock_ec2_instance.state = EC2_INSTANCE_STATE_RUNNING mock_ecs = MagicMock() mock_ecs.list_container_instances.return_value = mock_list_container_instances mock_boto3.client.return_value = mock_ecs mock_boto3.resource.return_value = mock_ec2 mock_ecs.describe_container_instances.return_value = { "containerInstances": [{"ec2InstanceId": instance_id}] } messages = [{"ami_id": ami_id, "volume_id": volume_id}] tasks.attach_volumes_to_cluster(messages) image.refresh_from_db() self.assertEqual(image.status, MachineImage.INSPECTING) mock_ecs.list_container_instances.assert_called_once_with( cluster=settings.HOUNDIGRADE_ECS_CLUSTER_NAME, status="ACTIVE" ) mock_ecs.describe_container_instances.assert_called_once_with( containerInstances=[instance_id], cluster=settings.HOUNDIGRADE_ECS_CLUSTER_NAME, ) mock_ec2.Volume.assert_called_once_with(volume_id) mock_ec2.Volume.return_value.attach_to_instance.assert_called_once_with( Device=device_name, InstanceId=instance_id ) mock_run_inspection_cluster.delay.assert_called_once_with( instance_id, expected_ami_mountpoints )
def test_get_volume(self, mock_boto3): """Test that a Volume is returned.""" region = random.choice(helper.SOME_AWS_REGIONS) zone = helper.generate_dummy_availability_zone(region) volume_id = helper.generate_dummy_volume_id() mock_volume = helper.generate_mock_volume(volume_id=volume_id, zone=zone) resource = mock_boto3.resource.return_value resource.Volume.return_value = mock_volume actual_volume = ec2.get_volume(volume_id, region) self.assertEqual(actual_volume, mock_volume)
def test_enqueue_ready_volume_success(self, mock_aws, mock_queue): """Assert that volumes are enqueued when ready.""" ami_id = util_helper.generate_dummy_image_id() volume_id = util_helper.generate_dummy_volume_id() mock_volume = util_helper.generate_mock_volume(volume_id=volume_id, state="available") region = mock_volume.zone[:-1] mock_aws.get_volume.return_value = mock_volume messages = [{"ami_id": ami_id, "volume_id": volume_id}] enqueue_ready_volume(ami_id, volume_id, region) mock_queue.assert_called_with(self.ready_volumes_queue_name, messages)
def test_enqueue_ready_volume_error(self, mock_aws): """Assert that an error is raised on bad volume state.""" ami_id = util_helper.generate_dummy_image_id() volume_id = util_helper.generate_dummy_volume_id() mock_volume = util_helper.generate_mock_volume( volume_id=volume_id, state=random.choice(('in-use', 'deleting', 'deleted', 'error'))) region = mock_volume.zone[:-1] mock_aws.get_volume.return_value = mock_volume mock_aws.check_volume_state.side_effect = AwsVolumeError() with self.assertRaises(AwsVolumeError): enqueue_ready_volume(ami_id, volume_id, region)
def test_run_inspection_cluster_success(self, mock_aws, mock_boto3, mock_machine_image_objects): """Asserts successful starting of the houndigrade task.""" mock_machine_image_objects.get.return_value = \ mock_machine_image_objects mock_machine_image_objects.INSPECTING.return_value = 'inspecting' mock_list_container_instances = { 'containerInstanceArns': [util_helper.generate_dummy_instance_id()] } mock_ec2 = Mock() mock_ecs = MagicMock() mock_ecs.list_container_instances.return_value = \ mock_list_container_instances mock_boto3.client.return_value = mock_ecs mock_boto3.resource.return_value = mock_ec2 mock_session = mock_aws.boto3.Session.return_value mock_aws.get_session.return_value = mock_session mock_ami_id = util_helper.generate_dummy_image_id() messages = [{ 'ami_id': mock_ami_id, 'volume_id': util_helper.generate_dummy_volume_id() }] tasks.run_inspection_cluster(messages) mock_machine_image_objects.get.assert_called_once_with( ec2_ami_id=mock_ami_id) self.assertEqual(mock_machine_image_objects.status.return_value, mock_machine_image_objects.INSPECTING.return_value) mock_ecs.list_container_instances.assert_called_once_with( cluster=settings.HOUNDIGRADE_ECS_CLUSTER_NAME) mock_ecs.describe_container_instances.assert_called_once_with( containerInstances=[ mock_list_container_instances['containerInstanceArns'][0] ], cluster=settings.HOUNDIGRADE_ECS_CLUSTER_NAME) mock_ecs.register_task_definition.assert_called_once() mock_ecs.run_task.assert_called_once() mock_ec2.Volume.assert_called_once_with(messages[0]['volume_id']) mock_ec2.Volume.return_value.attach_to_instance.assert_called_once()
def test_enqueue_ready_volume_retry(self, mock_aws): """Assert that the task retries when volume is not available.""" ami_id = util_helper.generate_dummy_image_id() volume_id = util_helper.generate_dummy_volume_id() mock_volume = util_helper.generate_mock_volume(volume_id=volume_id, state="creating") region = mock_volume.zone[:-1] mock_aws.get_volume.return_value = mock_volume mock_aws.check_volume_state.side_effect = AwsVolumeNotReadyError() with patch.object(enqueue_ready_volume, "retry") as mock_retry: mock_retry.side_effect = Retry() with self.assertRaises(Retry): enqueue_ready_volume(ami_id, volume_id, region)
def test_delete_snapshot_success(self, mock_aws, mock_boto3): """Assert that the delete snapshot succeeds.""" mock_snapshot_copy_id = util_helper.generate_dummy_snapshot_id() mock_snapshot_copy = util_helper.generate_mock_snapshot( mock_snapshot_copy_id) resource = mock_boto3.resource.return_value resource.Snapshot.return_value = mock_snapshot_copy volume_id = util_helper.generate_dummy_volume_id() mock_volume = util_helper.generate_mock_volume(volume_id=volume_id, state="available") volume_region = mock_volume.zone[:-1] mock_aws.get_volume.return_value = mock_volume mock_aws.check_volume_state.return_value = None delete_snapshot(mock_snapshot_copy_id, volume_id, volume_region)
def test_run_inspection_cluster_with_no_instances( self, mock_boto3, mock_machine_image_objects): """Assert that an exception is raised if no instance is ready.""" messages = [{ 'ami_id': util_helper.generate_dummy_image_id(), 'volume_id': util_helper.generate_dummy_volume_id() }] mock_machine_image_objects.get.return_value = \ mock_machine_image_objects mock_list_container_instances = {'containerInstanceArns': []} mock_ecs = MagicMock() mock_ecs.list_container_instances.return_value = \ mock_list_container_instances mock_boto3.client.return_value = mock_ecs with self.assertRaises(AwsECSInstanceNotReady): tasks.run_inspection_cluster(messages)
def test_attach_volumes_to_cluster_with_no_instances( self, mock_boto3, mock_machine_image_objects, mock_run_inspection_cluster ): """Assert that an exception is raised if no instance is ready.""" messages = [ { "ami_id": util_helper.generate_dummy_image_id(), "volume_id": util_helper.generate_dummy_volume_id(), } ] mock_machine_image_objects.get.return_value = mock_machine_image_objects mock_list_container_instances = {"containerInstanceArns": []} mock_ecs = MagicMock() mock_ecs.list_container_instances.return_value = mock_list_container_instances mock_boto3.client.return_value = mock_ecs with self.assertRaises(AwsECSInstanceNotReady): tasks.attach_volumes_to_cluster(messages) mock_run_inspection_cluster.delay.assert_not_called()
def test_attach_volumes_to_cluster_with_too_many_instances( self, mock_boto3, mock_machine_image_objects, mock_run_inspection_cluster ): """Assert that an exception is raised with too many instances.""" ami_id = util_helper.generate_dummy_image_id() volume_id = util_helper.generate_dummy_volume_id() instance_ids = [ util_helper.generate_dummy_instance_id(), util_helper.generate_dummy_instance_id(), ] mock_machine_image_objects.get.return_value = mock_machine_image_objects mock_list_container_instances = {"containerInstanceArns": instance_ids} mock_ecs = MagicMock() mock_ecs.list_container_instances.return_value = mock_list_container_instances mock_boto3.client.return_value = mock_ecs messages = [{"ami_id": ami_id, "volume_id": volume_id}] with self.assertRaises(AwsTooManyECSInstances): tasks.attach_volumes_to_cluster(messages) mock_run_inspection_cluster.delay.assert_not_called()
def test_generate_dummy_volume_id(self): """Assert generation of an appropriate volume ID.""" volume_id = helper.generate_dummy_volume_id() self.assertTrue(volume_id.startswith('vol-')) self.assertEqual(len(volume_id), 21)