예제 #1
0
    def test_check_cluster_instances_under_limit(self, mock_aws, mock_boto3):
        """Assert logs info and debug if launch times are under the configured limit."""
        instance_id_1 = helper.generate_dummy_instance_id()
        instance_id_2 = helper.generate_dummy_instance_id()
        instance_ids = [instance_id_1, instance_id_2]
        launch_time = TEST_TIME - timedelta(
            seconds=10)  # less than 600 seconds older
        mock_aws.describe_instances.return_value = dict((
            instance_id,
            helper.generate_dummy_describe_instance(instance_id,
                                                    launch_time=launch_time),
        ) for instance_id in instance_ids)

        with self.assertLogs("api.clouds.aws.tasks.inspection",
                             level="DEBUG") as logging_watcher:
            inspection.check_cluster_instances_age(instance_ids)

        self.assertEqual(len(logging_watcher.output), 4)
        self.assertInLog(instance_id_1, logging_watcher.output[0])
        self.assertInLog(instance_id_2, logging_watcher.output[1])
        self.assertInLog(instance_id_1, logging_watcher.output[2], "DEBUG")
        self.assertInLog(instance_id_2, logging_watcher.output[3], "DEBUG")
        self.assertInLog("fits within", logging_watcher.output[2], "DEBUG")
        self.assertInLog("10.0 seconds", logging_watcher.output[2], "DEBUG")
        self.assertInLog("fits within", logging_watcher.output[3], "DEBUG")
        self.assertInLog("10.0 seconds", logging_watcher.output[3], "DEBUG")

        mock_boto3.Session.assert_called_once()
        mock_aws.describe_instances.assert_called_once_with(
            mock_boto3.Session.return_value,
            instance_ids,
            mock_aws.ECS_CLUSTER_REGION,
        )
예제 #2
0
    def test_scale_up_inspection_cluster_aborts_when_not_scaled_down(
            self, mock_aws, mock_check, mock_attach_cluster_volumes):
        """Assert scale up aborts when not scaled down."""
        instance_ids = [
            helper.generate_dummy_instance_id(),
            helper.generate_dummy_instance_id(),
        ]
        mock_aws.is_scaled_down.return_value = (
            False,
            {
                "Instances": [{
                    "InstanceId": instance_id
                } for instance_id in instance_ids]
            },
        )

        tasks.scale_up_inspection_cluster()

        mock_check.assert_called_once_with(instance_ids)
        mock_aws.is_scaled_down.assert_called_once_with(
            settings.HOUNDIGRADE_AWS_AUTOSCALING_GROUP_NAME)
        mock_aws.scale_up.assert_not_called()
        mock_aws.read_messages_from_queue.assert_not_called()
        mock_attach_cluster_volumes.delay.assert_not_called()
        mock_aws.add_messages_to_queue.assert_not_called()
예제 #3
0
    def test_check_cluster_instances_age_no_launch_time(
            self, mock_aws, mock_boto3):
        """Assert logs info and errors if no launch times from AWS."""
        instance_id_1 = helper.generate_dummy_instance_id()
        instance_id_2 = helper.generate_dummy_instance_id()
        instance_ids = [instance_id_1, instance_id_2]
        mock_aws.describe_instances.return_value = dict((
            instance_id,
            helper.generate_dummy_describe_instance(instance_id,
                                                    launch_time=None),
        ) for instance_id in instance_ids)

        with self.assertLogs("api.clouds.aws.tasks.inspection",
                             level="INFO") as logging_watcher:
            inspection.check_cluster_instances_age(instance_ids)

        self.assertEqual(len(logging_watcher.output), 4)
        self.assertInLog(instance_id_1, logging_watcher.output[0])
        self.assertInLog(instance_id_2, logging_watcher.output[1])
        self.assertInLog(instance_id_1, logging_watcher.output[2], "ERROR")
        self.assertInLog(instance_id_2, logging_watcher.output[3], "ERROR")
        self.assertInLog("no launch time", logging_watcher.output[2], "ERROR")
        self.assertInLog("no launch time", logging_watcher.output[3], "ERROR")

        mock_boto3.Session.assert_called_once()
        mock_aws.describe_instances.assert_called_once_with(
            mock_boto3.Session.return_value,
            instance_ids,
            mock_aws.ECS_CLUSTER_REGION,
        )
예제 #4
0
    def test_describe_instances(self):
        """Assert that describe_instances returns a dict of instances data."""
        instance_ids = [
            helper.generate_dummy_instance_id(),
            helper.generate_dummy_instance_id(),
            helper.generate_dummy_instance_id(),
            helper.generate_dummy_instance_id(),
        ]
        individual_described_instances = [
            helper.generate_dummy_describe_instance(instance_id)
            for instance_id in instance_ids
        ]
        response = {
            "Reservations": [
                {
                    "Instances": individual_described_instances[:2],
                },
                {
                    "Instances": individual_described_instances[2:],
                },
            ],
        }

        mock_session = Mock()
        mock_client = mock_session.client.return_value
        mock_client.describe_instances.return_value = response

        region = helper.get_random_region()

        described_instances = ec2.describe_instances(mock_session,
                                                     instance_ids, region)

        self.assertEqual(set(described_instances.keys()), set(instance_ids))
        for described_instance in individual_described_instances:
            self.assertIn(described_instance, described_instances.values())
예제 #5
0
    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()
예제 #6
0
def generate_aws_instance(account, ec2_instance_id=None, region=None):
    """
    Generate an AwsInstance for the AwsAccount for testing.

    Any optional arguments not provided will be randomly generated.

    Args:
        account (AwsAccount): Account that owns the instance.
        ec2_instance_id (str): Optional EC2 instance id.
        region (str): Optional AWS region where the instance runs.

    Returns:
        AwsInstance: The created AwsInstance.

    """
    if ec2_instance_id is None:
        ec2_instance_id = helper.generate_dummy_instance_id()
    if region is None:
        region = random.choice(helper.SOME_AWS_REGIONS)

    return AwsInstance.objects.create(
        account=account,
        ec2_instance_id=ec2_instance_id,
        region=region,
    )
예제 #7
0
    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()
예제 #8
0
    def test_run_inspection_cluster_with_too_many_instances(self, mock_boto3):
        """Assert that an exception is raised with too many instances."""
        mock_list_container_instances = {
            'containerInstanceArns': [
                util_helper.generate_dummy_instance_id(),
                util_helper.generate_dummy_instance_id()
            ]
        }
        mock_ecs = MagicMock()
        mock_ecs.list_container_instances.return_value = \
            mock_list_container_instances

        mock_boto3.client.return_value = mock_ecs

        with self.assertRaises(AwsTooManyECSInstances):
            tasks.run_inspection_cluster([Mock()])
예제 #9
0
 def setUp(self):
     """Set up fixtures."""
     self.ec2_instance_id = util_helper.generate_dummy_instance_id()
     self.ami_id_a = util_helper.generate_dummy_image_id()
     self.ami_id_b = util_helper.generate_dummy_image_id()
     self.ami_id_c = util_helper.generate_dummy_image_id()
     self.ami_mountpoints = [
         (self.ami_id_a, "/dev/sdba"),
         (self.ami_id_b, "/dev/sdbb"),
         (self.ami_id_c, "/dev/sdbc"),
     ]
예제 #10
0
    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()
예제 #11
0
    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
        )
예제 #12
0
    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()
예제 #13
0
    def test_run_inspection_cluster_with_too_many_instances(
            self, mock_boto3, mock_machine_image_objects):
        """Assert that an exception is raised with too many instances."""
        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': [
                util_helper.generate_dummy_instance_id(),
                util_helper.generate_dummy_instance_id()
            ]
        }
        mock_ecs = MagicMock()
        mock_ecs.list_container_instances.return_value = \
            mock_list_container_instances

        mock_boto3.client.return_value = mock_ecs

        with self.assertRaises(AwsTooManyECSInstances):
            tasks.run_inspection_cluster(messages)
예제 #14
0
 def test_generate_aws_instance_with_args(self):
     """Assert generation of an AwsInstance with all specified args."""
     account = helper.generate_aws_account()
     ec2_instance_id = util_helper.generate_dummy_instance_id()
     region = random.choice(util_helper.SOME_AWS_REGIONS)
     instance = helper.generate_aws_instance(
         account,
         ec2_instance_id=ec2_instance_id,
         region=region,
     )
     self.assertIsInstance(instance, AwsInstance)
     self.assertEqual(instance.account, account)
     self.assertEqual(instance.ec2_instance_id, ec2_instance_id)
     self.assertEqual(instance.region, region)
예제 #15
0
    def test_get_ec2_instance(self):
        """Assert that get_ec2_instance returns an Instance."""
        mock_instance_id = helper.generate_dummy_instance_id()
        mock_instance = helper.generate_mock_ec2_instance(mock_instance_id)

        mock_session = Mock()
        mock_resource = mock_session.resource.return_value
        mock_resource.Instance.return_value = mock_instance

        actual_instance = ec2.get_ec2_instance(mock_session, mock_instance_id)
        self.assertEqual(actual_instance, mock_instance)

        mock_session.resource.assert_called_once_with('ec2')
        mock_resource.Instance.assert_called_once_with(mock_instance_id)
예제 #16
0
 def test_generate_aws_instance_with_args(self):
     """Assert generation of an AwsInstance with all specified args."""
     account = helper.generate_cloud_account()
     ec2_instance_id = util_helper.generate_dummy_instance_id()
     region = util_helper.get_random_region()
     instance = helper.generate_instance(
         account,
         ec2_instance_id=ec2_instance_id,
         region=region,
     )
     self.assertIsInstance(instance, Instance)
     self.assertEqual(instance.cloud_account, account)
     self.assertEqual(instance.content_object.ec2_instance_id, ec2_instance_id)
     self.assertEqual(instance.content_object.region, region)
예제 #17
0
    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()
예제 #18
0
 def test_generate_dummy_describe_instance_with_values(self):
     """Assert generated instance contains given values."""
     image_id = helper.generate_dummy_image_id()
     instance_id = helper.generate_dummy_instance_id()
     subnet_id = helper.generate_dummy_subnet_id()
     state = aws.InstanceState.shutting_down
     instance_type = random.choice(helper.SOME_EC2_INSTANCE_TYPES)
     instance = helper.generate_dummy_describe_instance(
         instance_id, image_id, subnet_id, state, instance_type)
     self.assertEqual(instance['ImageId'], image_id)
     self.assertEqual(instance['InstanceId'], instance_id)
     self.assertEqual(instance['InstanceType'], instance_type)
     self.assertEqual(instance['SubnetId'], subnet_id)
     self.assertEqual(instance['State']['Code'], state.value)
     self.assertEqual(instance['State']['Name'], state.name)
예제 #19
0
    def test_command_output_non_on_off_events(self, mock_receive, mock_s3,
                                              mock_del):
        """Test that non on/off events are not processed."""
        mock_instance_id = util_helper.generate_dummy_instance_id()
        mock_queue_url = 'https://sqs.queue.url'
        mock_receipt_handle = str(uuid.uuid4())

        mock_sqs_message_body = {
            'Records': [{
                's3': {
                    'bucket': {
                        'name': 'test-bucket',
                    },
                    'object': {
                        'key': 'path/to/log',
                    },
                },
            }]
        }
        mock_message = util_helper.generate_mock_sqs_message(
            mock_queue_url, json.dumps(mock_sqs_message_body),
            mock_receipt_handle)

        mock_cloudtrail_log = {
            'Records': [{
                'eventSource': 'null.amazonaws.com',
            }, {
                'errorCode': 123,
            }, {
                'eventName': 'InvalidEvent'
            }]
        }

        mock_receive.return_value = [mock_message]
        mock_s3.return_value = json.dumps(mock_cloudtrail_log)
        mock_del.return_value = 'Success'

        tasks.analyze_log()

        instances = list(
            AwsInstance.objects.filter(ec2_instance_id=mock_instance_id).all())
        instance_events = list(
            AwsInstanceEvent.objects.filter(
                instance=instances[0]).all()) if instances else []

        self.assertListEqual(instances, [])
        self.assertListEqual(instance_events, [])
예제 #20
0
 def test_generate_dummy_describe_instance_with_values(self):
     """Assert generated instance contains given values."""
     image_id = helper.generate_dummy_image_id()
     instance_id = helper.generate_dummy_instance_id()
     subnet_id = helper.generate_dummy_subnet_id()
     state = aws.InstanceState.shutting_down
     instance_type = helper.get_random_instance_type()
     device_mapping = helper.generate_dummy_block_device_mapping()
     instance = helper.generate_dummy_describe_instance(
         instance_id=instance_id,
         image_id=image_id,
         subnet_id=subnet_id,
         state=state,
         instance_type=instance_type,
         device_mappings=[device_mapping],
     )
     self.assertEqual(instance["ImageId"], image_id)
     self.assertEqual(instance["InstanceId"], instance_id)
     self.assertEqual(instance["InstanceType"], instance_type)
     self.assertEqual(instance["SubnetId"], subnet_id)
     self.assertEqual(instance["State"]["Code"], state.value)
     self.assertEqual(instance["State"]["Name"], state.name)
     self.assertEqual(instance["State"]["Name"], state.name)
     self.assertEqual(instance["BlockDeviceMappings"], [device_mapping])
예제 #21
0
def generate_instance(  # noqa: C901
    cloud_account,
    ec2_instance_id=None,
    region=None,
    image=None,
    no_image=False,
    cloud_type=AWS_PROVIDER_STRING,
    azure_instance_resource_id=None,
):
    """
    Generate an AwsInstance for the AwsAccount for testing.

    Any optional arguments not provided will be randomly generated.

    Args:
        cloud_account (CloudAccount): Account that owns the instance.
        ec2_instance_id (str): Optional EC2 instance id.
        region (str): Optional AWS region where the instance runs.
        image (MachineImage): Optional image to add instead of creating one.
        no_image (bool): Whether an image should be attached to this instance.
        cloud_type (str): Str denoting cloud type, defaults to "aws"
        azure_instance_resource_id (str): optional str for azure instance resource id

    Returns:
        Instance: The created Instance.

    """
    if region is None:
        region = helper.get_random_region(cloud_type=cloud_type)

    if cloud_type == AZURE_PROVIDER_STRING:
        if azure_instance_resource_id is None:
            azure_instance_resource_id = helper.generate_dummy_azure_instance_id(
            )
        if image is None:
            if not no_image:
                image_resource_id = helper.generate_dummy_azure_image_id()

                try:
                    azure_image = AzureMachineImage.objects.get(
                        resource_id=image_resource_id)
                    image = azure_image.machine_image.get()
                except AzureMachineImage.DoesNotExist:
                    image = generate_image(
                        azure_image_resource_id=image_resource_id,
                        status=MachineImage.PENDING,
                        cloud_type=cloud_type,
                    )
        provider_instance = AzureInstance.objects.create(
            resource_id=azure_instance_resource_id,
            region=region,
        )
    else:
        if ec2_instance_id is None:
            ec2_instance_id = helper.generate_dummy_instance_id()
        if image is None:
            if not no_image:
                ec2_ami_id = helper.generate_dummy_image_id()

                try:
                    aws_image = AwsMachineImage.objects.get(
                        ec2_ami_id=ec2_ami_id)
                    image = aws_image.machine_image.get()
                except AwsMachineImage.DoesNotExist:
                    aws_account_id = cloud_account.content_object.aws_account_id
                    image = generate_image(
                        ec2_ami_id=ec2_ami_id,
                        owner_aws_account_id=aws_account_id,
                        status=MachineImage.PENDING,
                    )

        provider_instance = AwsInstance.objects.create(
            ec2_instance_id=ec2_instance_id,
            region=region,
        )
    instance = Instance.objects.create(
        cloud_account=cloud_account,
        content_object=provider_instance,
        machine_image=image,
    )

    return instance
예제 #22
0
    def test_command_output_success_ec2_attributes_included(
            self, mock_receive, mock_s3, mock_del, mock_session, mock_ec2,
            mock_inspection):
        """Test processing a CloudTrail log with all data included."""
        mock_queue_url = 'https://sqs.queue.url'
        mock_receipt_handle = str(uuid.uuid4())
        mock_instance_id = util_helper.generate_dummy_instance_id()
        mock_instance_id2 = util_helper.generate_dummy_instance_id()
        mock_region = random.choice(util_helper.SOME_AWS_REGIONS)
        mock_event_type = 'RunInstances'
        now = datetime.datetime.utcnow()
        # Work around for sqlite handling of microseconds
        mock_occurred_at = datetime.datetime(year=now.year,
                                             month=now.month,
                                             day=now.day,
                                             hour=now.hour,
                                             minute=now.minute,
                                             second=now.second,
                                             tzinfo=tz.tzutc())
        mock_subnet = 'subnet-9000'
        mock_ec2_ami_id = util_helper.generate_dummy_image_id()
        mock_instance_type = 't2.nano'

        mock_instance = util_helper.generate_mock_ec2_instance(
            mock_instance_id, mock_ec2_ami_id, mock_subnet, None,
            mock_instance_type, 'windows')
        mock_inspection.delay.return_value = True

        mock_sqs_message_body = {
            'Records': [{
                's3': {
                    'bucket': {
                        'name': 'test-bucket',
                    },
                    'object': {
                        'key': 'path/to/log/log.json.gz',
                    },
                },
            }]
        }
        mock_message = util_helper.generate_mock_sqs_message(
            mock_queue_url, json.dumps(mock_sqs_message_body),
            mock_receipt_handle)

        mock_cloudtrail_log = {
            'Records': [{
                'awsRegion':
                mock_region,
                'eventName':
                mock_event_type,
                'eventSource':
                'ec2.amazonaws.com',
                'eventTime':
                mock_occurred_at.strftime('%Y-%m-%dT%H:%M:%SZ'),
                'eventType':
                'AwsApiCall',
                'responseElements': {
                    'instancesSet': {
                        'items': [{
                            'imageId': mock_ec2_ami_id,
                            'instanceId': mock_instance_id,
                            'instanceType': mock_instance_type,
                            'subnetId': mock_subnet
                        }]
                    },
                },
                'userIdentity': {
                    'accountId': self.mock_account_id
                }
            }, {
                'awsRegion':
                mock_region,
                'eventName':
                mock_event_type,
                'eventSource':
                'ec2.amazonaws.com',
                'eventTime':
                mock_occurred_at.strftime('%Y-%m-%dT%H:%M:%SZ'),
                'eventType':
                'AwsApiCall',
                'responseElements': {
                    'instancesSet': {
                        'items': [{
                            'imageId': mock_ec2_ami_id,
                            'instanceId': mock_instance_id,
                            'instanceType': mock_instance_type,
                            'subnetId': mock_subnet
                        }]
                    },
                },
                'userIdentity': {
                    'accountId': self.mock_account_id
                }
            }, {
                'awsRegion':
                mock_region,
                'eventName':
                mock_event_type,
                'eventSource':
                'ec2.amazonaws.com',
                'eventTime':
                mock_occurred_at.strftime('%Y-%m-%dT%H:%M:%SZ'),
                'eventType':
                'DifferentAwsApiCall',
                'responseElements': {
                    'instancesSet': {
                        'items': [{
                            'imageId': mock_ec2_ami_id,
                            'instanceId': mock_instance_id2,
                            'instanceType': mock_instance_type,
                            'subnetId': mock_subnet
                        }]
                    },
                },
                'userIdentity': {
                    'accountId': self.mock_account_id
                }
            }]
        }

        mock_receive.return_value = [mock_message]
        mock_s3.return_value = json.dumps(mock_cloudtrail_log)
        mock_del.return_value = 'Success'
        mock_session.return_value = 'Session'
        mock_ec2.return_value = mock_instance

        tasks.analyze_log()

        instances = list(
            AwsInstance.objects.filter(ec2_instance_id=mock_instance_id).all())
        instance_events = list(
            AwsInstanceEvent.objects.filter(
                instance=instances[0]).all()) if instances else []

        for instance in instances:
            self.assertEqual(instance.account, self.mock_account)
            self.assertEqual(instance.ec2_instance_id, mock_instance_id)
            self.assertEqual(instance.region, mock_region)

        for event in instance_events:
            self.assertEqual(event.instance, instances[0])
            self.assertEqual(event.event_type, InstanceEvent.TYPE.power_on)
            self.assertEqual(event.occurred_at, mock_occurred_at)
            self.assertEqual(event.subnet, mock_subnet)
            self.assertEqual(event.machineimage.ec2_ami_id, mock_ec2_ami_id)
            self.assertEqual(event.instance_type, mock_instance_type)
예제 #23
0
    def test_other_tags_ignored(self, mock_receive, mock_s3, mock_del):
        """Test processing a CloudTrail log for other tags ignored."""
        mock_instance_id = util_helper.generate_dummy_instance_id()

        mock_sqs_message_body = {
            'Records': [{
                's3': {
                    'bucket': {
                        'name': 'test-bucket',
                    },
                    'object': {
                        'key': 'path/to/log/log.json.gz',
                    },
                },
            }]
        }

        mock_queue_url = 'https://sqs.queue.url'
        mock_receipt_handle = str(uuid.uuid4())
        mock_region = random.choice(util_helper.SOME_AWS_REGIONS)

        now = datetime.datetime.utcnow()
        mock_occurred_at = datetime.datetime(year=now.year,
                                             month=now.month,
                                             day=now.day,
                                             hour=now.hour,
                                             minute=now.minute,
                                             second=now.second,
                                             tzinfo=tz.tzutc())

        mock_message = util_helper.generate_mock_sqs_message(
            mock_queue_url, json.dumps(mock_sqs_message_body),
            mock_receipt_handle)

        mock_cloudtrail_log = {
            'Records': [{
                'eventTime':
                mock_occurred_at.strftime('%Y-%m-%dT%H:%M:%SZ'),
                'eventSource':
                'ec2.amazonaws.com',
                'awsRegion':
                mock_region,
                'eventName':
                tasks.DELETE_TAG,
                'requestParameters': {
                    'resourcesSet': {
                        'items': [{
                            'resourceId': mock_instance_id
                        }]
                    },
                    'tagSet': {
                        'items': [{
                            'key': tasks.AWS_OPENSHIFT_TAG,
                            'value': tasks.AWS_OPENSHIFT_TAG
                        }]
                    }
                }
            }]
        }

        mock_receive.return_value = [mock_message]
        mock_s3.return_value = json.dumps(mock_cloudtrail_log)

        try:
            tasks.analyze_log()
        except Exception:
            self.fail('Should not raise exceptions for ignored tag events.')
예제 #24
0
 def test_generate_dummy_instance_id(self):
     """Assert generation of an appropriate EC2 instance ID."""
     volume_id = helper.generate_dummy_instance_id()
     self.assertTrue(volume_id.startswith('i-'))
     self.assertEqual(len(volume_id), 19)