Ejemplo n.º 1
0
    def test_generate_aws_ami_messages_deduplicate(self):
        """Test that messages are also deduplicated."""
        region = util_helper.get_random_region()
        image_id_1 = util_helper.generate_dummy_image_id()
        image_id_2 = util_helper.generate_dummy_image_id()
        instance_1 = util_helper.generate_dummy_describe_instance(
            image_id=image_id_1)
        instance_2 = util_helper.generate_dummy_describe_instance(
            image_id=image_id_1)
        instance_3 = util_helper.generate_dummy_describe_instance(
            image_id=image_id_1)
        instance_4 = util_helper.generate_dummy_describe_instance(
            image_id=image_id_2)
        instances_data = {
            region: [instance_1, instance_2, instance_3, instance_4]
        }
        ami_list = [image_id_1, image_id_2]

        expected = [
            {
                "cloud_provider": AWS_PROVIDER_STRING,
                "region": region,
                "image_id": image_id_1,
            },
            {
                "cloud_provider": AWS_PROVIDER_STRING,
                "region": region,
                "image_id": image_id_2,
            },
        ]

        result = generate_aws_ami_messages(instances_data, ami_list)
        self.assertEqual(len(result), len(expected))
        for message in expected:
            self.assertIn(message, result)
Ejemplo n.º 2
0
    def test_get_running_instances(self):
        """Assert we get expected instances in a dict keyed by regions."""
        mock_arn = helper.generate_dummy_arn()
        mock_regions = [f'region-{uuid.uuid4()}']
        mock_role = helper.generate_dummy_role()
        mock_running_instance = helper.generate_dummy_describe_instance(
            state=aws.InstanceState.running)
        mock_stopped_instance = helper.generate_dummy_describe_instance(
            state=aws.InstanceState.stopped)
        mock_described = {
            'Reservations': [
                {
                    'Instances': [
                        mock_running_instance,
                        mock_stopped_instance,
                    ],
                },
            ],
        }
        expected_found = {mock_regions[0]: [mock_running_instance]}

        with patch.object(aws, 'get_regions') as mock_get_regions, \
                patch.object(aws, 'boto3') as mock_boto3:
            mock_assume_role = mock_boto3.client.return_value.assume_role
            mock_assume_role.return_value = mock_role
            mock_get_regions.return_value = mock_regions
            mock_client = mock_boto3.Session.return_value.client.return_value
            mock_client.describe_instances.return_value = mock_described

            actual_found = aws.get_running_instances(aws.get_session(mock_arn))

        self.assertDictEqual(expected_found, actual_found)
Ejemplo n.º 3
0
    def test_create_succeeds_when_account_verified(self):
        """Test saving and processing of a test ARN."""
        aws_account_id = util_helper.generate_dummy_aws_account_id()
        arn = util_helper.generate_dummy_arn(aws_account_id)
        role = util_helper.generate_dummy_role()
        region = random.choice(util_helper.SOME_AWS_REGIONS)
        running_instances = {
            region: [
                util_helper.generate_dummy_describe_instance(
                    state=aws.InstanceState.running),
                util_helper.generate_dummy_describe_instance(
                    state=aws.InstanceState.stopping)
            ]
        }

        validated_data = {
            'account_arn': arn,
        }

        mock_request = Mock()
        mock_request.user = util_helper.generate_test_user()
        context = {'request': mock_request}

        with patch.object(aws, 'verify_account_access') as mock_verify, \
                patch.object(aws.sts, 'boto3') as mock_boto3, \
                patch.object(aws, 'get_running_instances') as mock_get_run, \
                patch.object(account_serializers,
                             'copy_ami_snapshot') as mock_copy_snapshot:
            mock_assume_role = mock_boto3.client.return_value.assume_role
            mock_assume_role.return_value = role
            mock_verify.return_value = True, []
            mock_get_run.return_value = running_instances
            mock_copy_snapshot.return_value = None
            serializer = AwsAccountSerializer(context=context)

            result = serializer.create(validated_data)
            self.assertIsInstance(result, AwsAccount)

        account = AwsAccount.objects.get(aws_account_id=aws_account_id)
        self.assertEqual(aws_account_id, account.aws_account_id)
        self.assertEqual(arn, account.account_arn)

        instances = AwsInstance.objects.filter(account=account).all()
        self.assertEqual(len(running_instances[region]), len(instances))
        for region, mock_instances_list in running_instances.items():
            for mock_instance in mock_instances_list:
                instance_id = mock_instance['InstanceId']
                instance = AwsInstance.objects.get(ec2_instance_id=instance_id)
                self.assertIsInstance(instance, AwsInstance)
                self.assertEqual(region, instance.region)
                event = InstanceEvent.objects.get(instance=instance)
                self.assertIsInstance(event, InstanceEvent)
                self.assertEqual(InstanceEvent.TYPE.power_on, event.event_type)

        amis = AwsMachineImage.objects.filter(account=account).all()
        self.assertEqual(len(running_instances[region]), len(amis))
Ejemplo n.º 4
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,
        )
Ejemplo n.º 5
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,
        )
Ejemplo n.º 6
0
    def test_save_instance_with_available_image(self):
        """Test that save instance events also writes image on instance."""
        aws_account_id = util_helper.generate_dummy_aws_account_id()
        arn = util_helper.generate_dummy_arn(aws_account_id)
        account = api_helper.generate_cloud_account(
            arn=arn, aws_account_id=aws_account_id)

        region = util_helper.get_random_region()
        instances_data = {
            region: [
                util_helper.generate_dummy_describe_instance(
                    state=aws.InstanceState.running)
            ]
        }
        ami_id = instances_data[region][0]["ImageId"]

        mock_session = Mock()
        described_amis = util_helper.generate_dummy_describe_image(
            image_id=ami_id, owner_id=aws_account_id)

        with patch.object(util.aws, "describe_images") as mock_describe_images:
            mock_describe_images.return_value = [described_amis]
            util.create_new_machine_images(mock_session, instances_data)
            mock_describe_images.assert_called_with(mock_session, {ami_id},
                                                    region)
        awsinstance = util.save_instance(account, instances_data[region][0],
                                         region)
        instance = awsinstance.instance.get()
        self.assertEqual(instance.machine_image.content_object.ec2_ami_id,
                         ami_id)
        self.assertEqual(instance.machine_image.status, MachineImage.PENDING)
Ejemplo n.º 7
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())
Ejemplo n.º 8
0
    def test_create_new_machine_images_with_windows_image(self):
        """Test that new windows machine images are marked appropriately."""
        aws_account_id = util_helper.generate_dummy_aws_account_id()
        arn = util_helper.generate_dummy_arn(aws_account_id)
        account = AwsAccount(
            account_arn=arn,
            aws_account_id=aws_account_id,
            user=util_helper.generate_test_user(),
        )
        account.save()

        region = random.choice(util_helper.SOME_AWS_REGIONS)
        running_instances = {
            region: [
                util_helper.generate_dummy_describe_instance(
                    state=aws.InstanceState.running
                )
            ]
        }
        running_instances[region][0]['Platform'] = 'Windows'
        ami_id = running_instances[region][0]['ImageId']

        result = util.create_new_machine_images(account, running_instances)

        amis = AwsMachineImage.objects.filter(account=account).all()

        self.assertEqual(result, [ami_id])
        for ami in amis:
            self.assertEqual(ami.ec2_ami_id, ami_id)
            self.assertEqual(ImageTag.objects.filter(
                description='windows').first(),
                ami.tags.filter(description='windows').first())
Ejemplo n.º 9
0
    def test_create_new_machine_images_with_windows_image(self):
        """Test that new windows machine images are marked appropriately."""
        aws_account_id = util_helper.generate_dummy_aws_account_id()
        arn = util_helper.generate_dummy_arn(aws_account_id)
        api_helper.generate_cloud_account(arn=arn,
                                          aws_account_id=aws_account_id)

        region = util_helper.get_random_region()
        instances_data = {
            region: [
                util_helper.generate_dummy_describe_instance(
                    state=aws.InstanceState.running)
            ]
        }
        instances_data[region][0]["Platform"] = "Windows"
        ami_id = instances_data[region][0]["ImageId"]

        mock_session = Mock()
        described_amis = util_helper.generate_dummy_describe_image(
            image_id=ami_id, owner_id=aws_account_id)

        with patch.object(util.aws, "describe_images") as mock_describe_images:
            mock_describe_images.return_value = [described_amis]
            result = util.create_new_machine_images(mock_session,
                                                    instances_data)
            mock_describe_images.assert_called_with(mock_session, {ami_id},
                                                    region)

        self.assertEqual(result, [ami_id])

        images = list(AwsMachineImage.objects.all())
        self.assertEqual(len(images), 1)
        self.assertEqual(images[0].ec2_ami_id, ami_id)
        self.assertEqual(images[0].platform, AwsMachineImage.WINDOWS)
Ejemplo n.º 10
0
    def test_check_cluster_volume_mounts_not_ready(
            self, mock_describe_cluster_instances):
        """Assert checking the volume mounts when they are not ready."""
        device_mappings = [
            util_helper.generate_dummy_block_device_mapping(
                device_name=self.ami_mountpoints[0][1], status="attaching"),
            util_helper.generate_dummy_block_device_mapping(
                device_name=self.ami_mountpoints[1][1], status="suspicious"),
        ]
        described_instances = {
            self.ec2_instance_id:
            util_helper.generate_dummy_describe_instance(
                instance_id=self.ec2_instance_id,
                device_mappings=device_mappings)
        }
        mock_describe_cluster_instances.return_value = described_instances

        with self.assertLogs("api.clouds.aws.tasks.inspection",
                             level="INFO") as logging_watcher:
            volumes_mounted = tasks.inspection._check_cluster_volume_mounts(
                self.ec2_instance_id, self.ami_mountpoints)

        self.assertFalse(volumes_mounted)
        self.assertEqual(len(logging_watcher.output), 3)
        self.assertIn("INFO", logging_watcher.output[0])
        self.assertIn("is still attaching", logging_watcher.output[0])
        self.assertIn("ERROR", logging_watcher.output[1])
        self.assertIn("has unexpected status", logging_watcher.output[1])
        self.assertIn("WARNING", logging_watcher.output[2])
        self.assertIn("not found in", logging_watcher.output[2])
Ejemplo n.º 11
0
    def test_add_messages_to_queue(self, mock_kombu):
        """Test that messages get added to a message queue."""
        queue_name = 'Test Queue'
        region = random.choice(util_helper.SOME_AWS_REGIONS)
        instance = util_helper.generate_dummy_describe_instance()
        instances_data = {region: [instance]}
        ami_list = [instance['ImageId']]

        messages = util.generate_aws_ami_messages(instances_data, ami_list)
        mock_routing_key = queue_name
        mock_body = messages[0]

        mock_exchange = mock_kombu.Exchange.return_value
        mock_queue = mock_kombu.Queue.return_value
        mock_conn = mock_kombu.Connection.return_value
        mock_with_conn = mock_conn.__enter__.return_value
        mock_producer = mock_with_conn.Producer.return_value
        mock_pub = mock_producer.publish

        util.add_messages_to_queue(queue_name, messages)

        mock_pub.assert_called_with(mock_body,
                                    retry=True,
                                    exchange=mock_exchange,
                                    routing_key=mock_routing_key,
                                    declare=[mock_queue])
    def test_instance_already_power_off(self, mock_aws,
                                        mock_calculate_max_concurrent):
        """Don't create power_off for instance that already has recent power_off."""
        event = account_helper.generate_single_instance_event(
            self.instance,
            self.power_off_time,
            event_type=InstanceEvent.TYPE.power_off)
        self.process_event(event)
        mock_calculate_max_concurrent.reset_mock()

        described_instances = {
            self.region: [
                util_helper.generate_dummy_describe_instance(
                    instance_id=self.aws_instance.ec2_instance_id,
                    state=aws.InstanceState.stopped,
                )
            ]
        }
        mock_aws.describe_instances_everywhere.return_value = described_instances

        describe_time = self.power_off_time + datetime.timedelta(days=1)
        with util_helper.clouditardis(describe_time):
            tasks.initial_aws_describe_instances(self.account.id)

        mock_calculate_max_concurrent.assert_not_called()
        self.assertExpectedEventsAndRun()
Ejemplo n.º 13
0
    def test_create_new_machine_images(self):
        """Test that new machine images are saved to the DB."""
        aws_account_id = util_helper.generate_dummy_aws_account_id()
        arn = util_helper.generate_dummy_arn(aws_account_id)
        account = AwsAccount(
            account_arn=arn,
            aws_account_id=aws_account_id,
            user=util_helper.generate_test_user(),
        )
        account.save()

        region = random.choice(util_helper.SOME_AWS_REGIONS)
        running_instances = {
            region: [
                util_helper.generate_dummy_describe_instance(
                    state=aws.InstanceState.running
                )
            ]
        }
        ami_id = running_instances[region][0]['ImageId']

        result = util.create_new_machine_images(account, running_instances)

        amis = AwsMachineImage.objects.filter(account=account).all()

        self.assertEqual(result, [ami_id])
        for ami in amis:
            self.assertEqual(ami.ec2_ami_id, ami_id)
Ejemplo n.º 14
0
    def test_create_succeeds_when_account_verified(self):
        """Test saving and processing of a test ARN."""
        aws_account_id = util_helper.generate_dummy_aws_account_id()
        arn = util_helper.generate_dummy_arn(aws_account_id)
        role = util_helper.generate_dummy_role()
        region = f'region-{uuid.uuid4()}'
        running_instances = {
            region: [
                util_helper.generate_dummy_describe_instance(
                    state=aws.InstanceState.running),
                util_helper.generate_dummy_describe_instance(
                    state=aws.InstanceState.stopping)
            ]
        }
        validated_data = {
            'account_arn': arn,
        }

        with patch.object(aws, 'verify_account_access') as mock_verify, \
                patch.object(aws, 'boto3') as mock_boto3, \
                patch.object(aws, 'get_running_instances') as mock_get_running:
            mock_assume_role = mock_boto3.client.return_value.assume_role
            mock_assume_role.return_value = role
            mock_verify.return_value = True
            mock_get_running.return_value = running_instances
            serializer = AwsAccountSerializer()

            result = serializer.create(validated_data)
            self.assertIsInstance(result, AwsAccount)

        account = AwsAccount.objects.get(aws_account_id=aws_account_id)
        self.assertEqual(aws_account_id, account.aws_account_id)
        self.assertEqual(arn, account.account_arn)

        instances = AwsInstance.objects.filter(account=account).all()
        self.assertEqual(len(running_instances[region]), len(instances))
        for region, mock_instances_list in running_instances.items():
            for mock_instance in mock_instances_list:
                instance_id = mock_instance['InstanceId']
                instance = AwsInstance.objects.get(ec2_instance_id=instance_id)
                self.assertIsInstance(instance, AwsInstance)
                self.assertEqual(region, instance.region)
                event = InstanceEvent.objects.get(instance=instance)
                self.assertIsInstance(event, InstanceEvent)
                self.assertEqual(InstanceEvent.TYPE.power_on, event.event_type)
Ejemplo n.º 15
0
    def test_create_fails_when_another_arn_has_same_aws_account_id(self):
        """Test that an account is not saved if ARN reuses an AWS account."""
        user = util_helper.generate_test_user()
        aws_account_id = util_helper.generate_dummy_aws_account_id()
        arn = util_helper.generate_dummy_arn(aws_account_id)
        role = util_helper.generate_dummy_role()
        region = random.choice(util_helper.SOME_AWS_REGIONS)
        running_instances = {
            region: [
                util_helper.generate_dummy_describe_instance(
                    state=aws.InstanceState.running),
                util_helper.generate_dummy_describe_instance(
                    state=aws.InstanceState.stopping)
            ]
        }

        validated_data = {
            'account_arn': arn,
        }

        # Create one with the same AWS account ID but a different ARN.
        account_helper.generate_aws_account(
            aws_account_id=aws_account_id,
            user=user,
        )

        mock_request = Mock()
        mock_request.user = util_helper.generate_test_user()
        context = {'request': mock_request}

        with patch.object(aws, 'verify_account_access') as mock_verify, \
                patch.object(aws.sts, 'boto3') as mock_boto3, \
                patch.object(aws, 'get_running_instances') as mock_get_run:
            mock_assume_role = mock_boto3.client.return_value.assume_role
            mock_assume_role.return_value = role
            mock_verify.return_value = True, []
            mock_get_run.return_value = running_instances
            serializer = AwsAccountSerializer(context=context)

            with self.assertRaises(ValidationError) as cm:
                serializer.create(validated_data)
            raised_exception = cm.exception
            self.assertIn('account_arn', raised_exception.detail)
            self.assertIn(aws_account_id,
                          raised_exception.detail['account_arn'][0])
Ejemplo n.º 16
0
 def test_generate_dummy_describe_instance_default(self):
     """Assert generated instance has values where expected."""
     instance = helper.generate_dummy_describe_instance()
     self.assertIsNotNone(instance['ImageId'])
     self.assertIsNotNone(instance['InstanceId'])
     self.assertIsNotNone(instance['InstanceType'])
     self.assertIsNotNone(instance['SubnetId'])
     self.assertIsNotNone(instance['State'])
     self.assertIsNotNone(instance['State']['Code'])
     self.assertIsNotNone(instance['State']['Name'])
Ejemplo n.º 17
0
 def test_generate_dummy_describe_instance_default(self):
     """Assert generated instance has values where expected."""
     instance = helper.generate_dummy_describe_instance()
     self.assertIsNotNone(instance["ImageId"])
     self.assertIsNotNone(instance["InstanceId"])
     self.assertIsNotNone(instance["InstanceType"])
     self.assertIsNotNone(instance["SubnetId"])
     self.assertIsNotNone(instance["State"])
     self.assertIsNotNone(instance["State"]["Code"])
     self.assertIsNotNone(instance["State"]["Name"])
     self.assertEqual(len(instance["BlockDeviceMappings"]), 2)
Ejemplo n.º 18
0
    def test_generate_aws_ami_messages(self):
        """Test that messages are formatted correctly."""
        region = random.choice(util_helper.SOME_AWS_REGIONS)
        instance = util_helper.generate_dummy_describe_instance()
        instances_data = {region: [instance]}
        ami_list = [instance['ImageId']]

        expected = [{'cloud_provider': AWS_PROVIDER_STRING,
                     'region': region,
                     'image_id': instance['ImageId']}]

        result = util.generate_aws_ami_messages(instances_data, ami_list)

        self.assertEqual(result, expected)
Ejemplo n.º 19
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)
Ejemplo n.º 20
0
    def test_generate_aws_ami_messages(self):
        """Test that messages are formatted correctly."""
        region = util_helper.get_random_region()
        instance = util_helper.generate_dummy_describe_instance()
        instances_data = {region: [instance]}
        ami_list = [instance["ImageId"]]

        expected = [{
            "cloud_provider": AWS_PROVIDER_STRING,
            "region": region,
            "image_id": instance["ImageId"],
        }]

        result = generate_aws_ami_messages(instances_data, ami_list)

        self.assertEqual(result, expected)
    def test_instance_found_not_running(self, mock_aws,
                                        mock_calculate_max_concurrent):
        """Create power_off event for instance found stopped in the describe."""
        described_instances = {
            self.region: [
                util_helper.generate_dummy_describe_instance(
                    instance_id=self.aws_instance.ec2_instance_id,
                    state=aws.InstanceState.stopped,
                )
            ]
        }
        mock_aws.describe_instances_everywhere.return_value = described_instances

        with util_helper.clouditardis(self.power_off_time):
            tasks.initial_aws_describe_instances(self.account.id)

        mock_calculate_max_concurrent.assert_called()
        self.assertExpectedEventsAndRun()
Ejemplo n.º 22
0
    def test_save_instance_with_missing_machineimage(self):
        """
        Test that save_instance works around a missing MachineImage.

        This is a use case that we *shouldn't* need, but until we identify how
        exactly AwsMachineImage objects are being saved without their matching
        MachineImage objects, we have this workaround to create the
        MachineImage at the time it is needed.
        """
        aws_account_id = util_helper.generate_dummy_aws_account_id()
        arn = util_helper.generate_dummy_arn(aws_account_id)
        account = api_helper.generate_cloud_account(
            arn=arn, aws_account_id=aws_account_id)

        region = util_helper.get_random_region()
        instances_data = {
            region: [
                util_helper.generate_dummy_describe_instance(
                    state=aws.InstanceState.running)
            ]
        }
        ami_id = instances_data[region][0]["ImageId"]

        # Create the AwsMachineImage without its paired MachineImage.
        aws_machine_image = AwsMachineImage.objects.create(
            owner_aws_account_id=util_helper.generate_dummy_aws_account_id(),
            ec2_ami_id=ami_id,
            platform="none",
        )
        # Verify that the MachineImage was *not* created before proceeding.
        with self.assertRaises(MachineImage.DoesNotExist):
            aws_machine_image.machine_image.get()

        awsinstance = util.save_instance(account, instances_data[region][0],
                                         region)
        instance = awsinstance.instance.get()

        self.assertEqual(instance.machine_image.content_object.ec2_ami_id,
                         ami_id)
        self.assertEqual(instance.machine_image.status,
                         MachineImage.UNAVAILABLE)
Ejemplo n.º 23
0
    def test_check_cluster_volume_mounts_success(
            self, mock_describe_cluster_instances):
        """Assert successfully checking the volume mounts are ready."""
        device_mappings = [
            util_helper.generate_dummy_block_device_mapping(
                device_name=self.ami_mountpoints[0][1]),
            util_helper.generate_dummy_block_device_mapping(
                device_name=self.ami_mountpoints[1][1]),
            util_helper.generate_dummy_block_device_mapping(
                device_name=self.ami_mountpoints[2][1]),
        ]
        described_instances = {
            self.ec2_instance_id:
            util_helper.generate_dummy_describe_instance(
                instance_id=self.ec2_instance_id,
                device_mappings=device_mappings)
        }
        mock_describe_cluster_instances.return_value = described_instances

        volumes_mounted = tasks.inspection._check_cluster_volume_mounts(
            self.ec2_instance_id, self.ami_mountpoints)
        self.assertTrue(volumes_mounted)
Ejemplo n.º 24
0
    def test_save_instance_with_unavailable_image(self):
        """Test that save instance events also writes image on instance."""
        aws_account_id = util_helper.generate_dummy_aws_account_id()
        arn = util_helper.generate_dummy_arn(aws_account_id)
        account = api_helper.generate_cloud_account(
            arn=arn, aws_account_id=aws_account_id)

        region = util_helper.get_random_region()
        instances_data = {
            region: [
                util_helper.generate_dummy_describe_instance(
                    state=aws.InstanceState.running)
            ]
        }
        ami_id = instances_data[region][0]["ImageId"]

        awsinstance = util.save_instance(account, instances_data[region][0],
                                         region)
        instance = awsinstance.instance.get()

        self.assertEqual(instance.machine_image.content_object.ec2_ami_id,
                         ami_id)
        self.assertEqual(instance.machine_image.status,
                         MachineImage.UNAVAILABLE)
Ejemplo n.º 25
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])
Ejemplo n.º 26
0
    def test_initial_aws_describe_instances(
            self, mock_util_aws, mock_aws, mock_start,
            mock_calculate_concurrent_usage_task):
        """
        Test happy-path behaviors of initial_aws_describe_instances.

        This test simulates a situation in which three running instances are
        found. One instance has the Windows platform, another instance has its
        image tagged for OpenShift, and a third instance has neither of those.

        The end result is that the three running instances should be saved,
        three power-on events should be saved (one for each instance), three
        images should be saved, and two new tasks should be spawned for
        inspecting the two not-windows images.
        """
        account = account_helper.generate_cloud_account()

        # Set up mocked data in AWS API responses.
        region = util_helper.get_random_region()
        described_ami_unknown = util_helper.generate_dummy_describe_image()
        described_ami_openshift = util_helper.generate_dummy_describe_image(
            openshift=True)
        described_ami_windows = util_helper.generate_dummy_describe_image()

        ami_id_unknown = described_ami_unknown["ImageId"]
        ami_id_openshift = described_ami_openshift["ImageId"]
        ami_id_windows = described_ami_windows["ImageId"]
        ami_id_unavailable = util_helper.generate_dummy_image_id()
        ami_id_gone = util_helper.generate_dummy_image_id()

        all_instances = [
            util_helper.generate_dummy_describe_instance(
                image_id=ami_id_unknown, state=aws.InstanceState.running),
            util_helper.generate_dummy_describe_instance(
                image_id=ami_id_openshift, state=aws.InstanceState.running),
            util_helper.generate_dummy_describe_instance(
                image_id=ami_id_windows,
                state=aws.InstanceState.running,
                platform=AwsMachineImage.WINDOWS,
            ),
            util_helper.generate_dummy_describe_instance(
                image_id=ami_id_unavailable, state=aws.InstanceState.running),
            util_helper.generate_dummy_describe_instance(
                image_id=ami_id_gone, state=aws.InstanceState.terminated),
        ]
        described_instances = {region: all_instances}

        mock_aws.describe_instances_everywhere.return_value = described_instances
        mock_util_aws.describe_images.return_value = [
            described_ami_unknown,
            described_ami_openshift,
            described_ami_windows,
        ]
        mock_util_aws.is_windows.side_effect = aws.is_windows
        mock_util_aws.OPENSHIFT_TAG = aws.OPENSHIFT_TAG
        mock_util_aws.InstanceState.is_running = aws.InstanceState.is_running

        start_inspection_calls = [
            call(
                account.content_object.account_arn,
                described_ami_unknown["ImageId"],
                region,
            )
        ]

        tasks.initial_aws_describe_instances(account.id)
        mock_start.assert_has_calls(start_inspection_calls)

        # Verify that we created all five instances.
        instances_count = Instance.objects.filter(
            cloud_account=account).count()
        self.assertEqual(instances_count, 5)

        # Verify that the running instances exist with power-on events.
        for described_instance in all_instances[:4]:
            instance_id = described_instance["InstanceId"]
            aws_instance = AwsInstance.objects.get(ec2_instance_id=instance_id)
            self.assertIsInstance(aws_instance, AwsInstance)
            self.assertEqual(region, aws_instance.region)
            event = InstanceEvent.objects.get(
                instance=aws_instance.instance.get())
            self.assertIsInstance(event, InstanceEvent)
            self.assertEqual(InstanceEvent.TYPE.power_on, event.event_type)

        # Verify that the not-running instances exist with no events.
        for described_instance in all_instances[4:]:
            instance_id = described_instance["InstanceId"]
            aws_instance = AwsInstance.objects.get(ec2_instance_id=instance_id)
            self.assertIsInstance(aws_instance, AwsInstance)
            self.assertEqual(region, aws_instance.region)
            self.assertFalse(
                InstanceEvent.objects.filter(
                    instance=aws_instance.instance.get()).exists())

        # Verify that we saved images for all instances, even if not running.
        images_count = AwsMachineImage.objects.count()
        self.assertEqual(images_count, 5)

        aws_image = AwsMachineImage.objects.get(ec2_ami_id=ami_id_unknown)
        image = aws_image.machine_image.get()
        self.assertFalse(image.rhel_detected)
        self.assertFalse(image.openshift_detected)
        self.assertEqual(image.name, described_ami_unknown["Name"])

        aws_image = AwsMachineImage.objects.get(ec2_ami_id=ami_id_openshift)
        image = aws_image.machine_image.get()
        self.assertFalse(image.rhel_detected)
        self.assertTrue(image.openshift_detected)
        self.assertEqual(image.name, described_ami_openshift["Name"])

        aws_image = AwsMachineImage.objects.get(ec2_ami_id=ami_id_windows)
        image = aws_image.machine_image.get()
        self.assertFalse(image.rhel_detected)
        self.assertFalse(image.openshift_detected)
        self.assertEqual(image.name, described_ami_windows["Name"])
        self.assertEqual(aws_image.platform, AwsMachineImage.WINDOWS)

        aws_image = AwsMachineImage.objects.get(ec2_ami_id=ami_id_unavailable)
        image = aws_image.machine_image.get()
        self.assertFalse(image.rhel_detected)
        self.assertFalse(image.openshift_detected)
        self.assertEqual(image.status, MachineImage.UNAVAILABLE)
Ejemplo n.º 27
0
    def test_initial_aws_describe_instances_after_disable_enable(
        self,
        mock_util_aws,
        mock_aws,
        mock_start,
        mock_sources_notify,
        mock_schedule_concurrent_calculation_task,
    ):
        """
        Test calling initial_aws_describe_instances multiple times.

        Historically (and in the simplified ideal happy-path), we would only ever call
        initial_aws_describe_instances exactly once when an AwsCloudAccount was first
        created. However, since we added support to disable accounts, it's now possible
        (and likely common) for an account to be created (and enabled), call describe,
        be disabled, be enabled again, and call describe again during the enable.

        We need to ensure that running described instances that generated "power_off"
        InstanceEvents as a result of AwsCloudAccount.disable would later correctly get
        new "power_on" InstanceEvents as a result of AwsCloudAccount.enable.
        """
        account = account_helper.generate_cloud_account()

        # Set up mocked data in AWS API responses.
        region = util_helper.get_random_region()

        described_ami = util_helper.generate_dummy_describe_image()
        ami_id = described_ami["ImageId"]
        all_instances = [
            util_helper.generate_dummy_describe_instance(
                image_id=ami_id, state=aws.InstanceState.running),
        ]
        described_instances = {region: all_instances}
        mock_aws.describe_instances_everywhere.return_value = described_instances
        mock_util_aws.describe_images.return_value = [described_ami]
        mock_util_aws.is_windows.side_effect = aws.is_windows
        mock_util_aws.InstanceState.is_running = aws.InstanceState.is_running
        mock_util_aws.AwsArn = aws.AwsArn
        mock_util_aws.verify_account_access.return_value = True, []

        inspection_call = call(
            account.content_object.account_arn,
            described_ami["ImageId"],
            region,
        )

        date_of_initial_describe = util_helper.utc_dt(2020, 3, 1, 0, 0, 0)
        date_of_disable = util_helper.utc_dt(2020, 3, 2, 0, 0, 0)
        date_of_reenable = util_helper.utc_dt(2020, 3, 3, 0, 0, 0)

        with util_helper.clouditardis(date_of_initial_describe):
            tasks.initial_aws_describe_instances(account.id)
            mock_start.assert_has_calls([inspection_call])

        with util_helper.clouditardis(date_of_disable):
            account.disable()
            mock_util_aws.delete_cloudtrail.assert_called()

        # Before calling "start_image_inspection" again, let's change the mocked return
        # values from AWS to include another instance and image. We should ultimately
        # expect the original instance + ami to be found but *not* describe its image.
        # Only the new instance + ami should be fully described.

        described_ami_2 = util_helper.generate_dummy_describe_image()
        ami_id_2 = described_ami_2["ImageId"]
        all_instances.append(
            util_helper.generate_dummy_describe_instance(
                image_id=ami_id_2, state=aws.InstanceState.running))
        described_instances = {region: all_instances}
        mock_aws.describe_instances_everywhere.return_value = described_instances
        mock_util_aws.describe_images.return_value = [
            described_ami, described_ami_2
        ]

        inspection_call_2 = call(
            account.content_object.account_arn,
            described_ami_2["ImageId"],
            region,
        )

        with patch.object(
                tasks, "initial_aws_describe_instances"
        ) as mock_initial, util_helper.clouditardis(date_of_reenable):
            # Even though we want to test initial_aws_describe_instances, we need to
            # mock this particular call because we need to short-circuit Celery.
            account.enable()
            mock_initial.delay.assert_called()

        with util_helper.clouditardis(date_of_reenable):
            tasks.initial_aws_describe_instances(account.id)
            mock_start.assert_has_calls([inspection_call_2])

        # Now that the dust has settled, let's check that the two instances have events
        # in the right configuration. The first instance is on, off, and on; the second
        # instance is on.

        aws_instance_1_events = (AwsInstance.objects.get(
            ec2_instance_id=all_instances[0]["InstanceId"]).instance.get(
            ).instanceevent_set.order_by("occurred_at").all())
        self.assertEqual(len(aws_instance_1_events), 3)
        instance_1_event_1 = aws_instance_1_events[0]
        self.assertEqual(instance_1_event_1.occurred_at,
                         date_of_initial_describe)
        self.assertEqual(instance_1_event_1.event_type,
                         InstanceEvent.TYPE.power_on)
        instance_1_event_2 = aws_instance_1_events[1]
        self.assertEqual(instance_1_event_2.occurred_at, date_of_disable)
        self.assertEqual(instance_1_event_2.event_type,
                         InstanceEvent.TYPE.power_off)
        instance_1_event_3 = aws_instance_1_events[2]
        self.assertEqual(instance_1_event_3.occurred_at, date_of_reenable)
        self.assertEqual(instance_1_event_3.event_type,
                         InstanceEvent.TYPE.power_on)

        aws_instance_2_events = (AwsInstance.objects.get(
            ec2_instance_id=all_instances[1]["InstanceId"]).instance.get(
            ).instanceevent_set.order_by("occurred_at").all())
        self.assertEqual(len(aws_instance_2_events), 1)
        instance_2_event_1 = aws_instance_2_events[0]
        self.assertEqual(instance_2_event_1.occurred_at, date_of_reenable)
        self.assertEqual(instance_2_event_1.event_type,
                         InstanceEvent.TYPE.power_on)
Ejemplo n.º 28
0
 def test_is_instance_windows_with_other_platform(self):
     """Test that an instance with Platform 'other' is not windows."""
     dummy_instance = helper.generate_dummy_describe_instance(
         platform='other')
     self.assertFalse(ec2.is_instance_windows(dummy_instance))
Ejemplo n.º 29
0
 def test_is_instance_windows_with_empty_platform(self):
     """Test that an instance with no Platform is not windows."""
     dummy_instance = helper.generate_dummy_describe_instance()
     self.assertFalse(ec2.is_instance_windows(dummy_instance))
Ejemplo n.º 30
0
 def test_is_instance_windows_with_unexpected_case(self):
     """Test that an instance with Platform 'WiNdOwS' is windows."""
     dummy_instance = helper.generate_dummy_describe_instance(
         platform='WiNdOwS')
     self.assertTrue(ec2.is_instance_windows(dummy_instance))