def test_deploy_raised_no_vpc(self):
        # arrange
        my_vpc_service = Mock()
        my_vpc_service.find_vpc_for_reservation = Mock(return_value=None)
        deploy_operation = DeployAMIOperation(self.instance_service,
                                              self.credentials_manager,
                                              self.security_group_service,
                                              self.tag_service,
                                              my_vpc_service,
                                              self.key_pair,
                                              self.subnet_service,
                                              self.elastic_ip_service,
                                              self.network_interface_service,
                                              self.cancellation_service,
                                              self.device_index_strategy,
                                              self.vm_details_provider)

        # act & assert
        with self.assertRaisesRegexp(ValueError, 'VPC is not set for this reservation'):
            deploy_operation.deploy(ec2_session=Mock(),
                                    s3_session=Mock(),
                                    name=Mock(),
                                    reservation=Mock(),
                                    aws_ec2_cp_resource_model=Mock(),
                                    ami_deploy_action=Mock(),
                                    network_actions=Mock(),
                                    ec2_client=Mock(),
                                    cancellation_context=Mock(),
                                    logger=self.logger)
Ejemplo n.º 2
0
 def setUp(self):
     self.ec2_datamodel = Mock()
     self.ec2_session = Mock()
     self.ec2_client = Mock()
     self.s3_session = Mock()
     self.instance_service = Mock()
     self.security_group_service = Mock()
     self.tag_service = Mock()
     self.key_pair = Mock()
     self.vpc_service = Mock()
     self.subnet_service = Mock()
     self.credentials_manager = Mock()
     self.cancellation_service = Mock()
     self.logger = Mock()
     self.elastic_ip_service = Mock()
     self.network_interface_service = Mock()
     self.device_index_strategy = Mock()
     self.vm_details_provider = Mock()
     self.deploy_operation = DeployAMIOperation(
         instance_service=self.instance_service,
         ami_credential_service=self.credentials_manager,
         security_group_service=self.security_group_service,
         tag_service=self.tag_service,
         vpc_service=self.vpc_service,
         key_pair_service=self.key_pair,
         subnet_service=self.subnet_service,
         elastic_ip_service=self.elastic_ip_service,
         network_interface_service=self.network_interface_service,
         cancellation_service=self.cancellation_service,
         device_index_strategy=self.device_index_strategy,
         vm_details_provider=self.vm_details_provider,
     )
Ejemplo n.º 3
0
    def test_deploy_raised_no_vpc(self):
        # arrange
        my_vpc_service = Mock()
        my_vpc_service.find_vpc_for_reservation = Mock(return_value=None)
        deploy_operation = DeployAMIOperation(
            self.instance_service,
            self.credentials_manager,
            self.security_group_service,
            self.tag_service,
            my_vpc_service,
            self.key_pair,
            self.subnet_service,
            self.elastic_ip_service,
            self.network_interface_service,
            self.cancellation_service,
            self.device_index_strategy,
            self.vm_details_provider,
        )

        # act & assert
        with self.assertRaisesRegexp(ValueError,
                                     "VPC is not set for this reservation"):
            deploy_operation.deploy(
                ec2_session=Mock(),
                s3_session=Mock(),
                name=Mock(),
                reservation=Mock(),
                aws_ec2_cp_resource_model=Mock(),
                ami_deploy_action=Mock(),
                network_actions=Mock(),
                ec2_client=Mock(),
                cancellation_context=Mock(),
                logger=self.logger,
            )
 def setUp(self):
     self.ec2_datamodel = Mock()
     self.ec2_session = Mock()
     self.ec2_client = Mock()
     self.s3_session = Mock()
     self.instance_service = Mock()
     self.security_group_service = Mock()
     self.tag_service = Mock()
     self.key_pair = Mock()
     self.vpc_service = Mock()
     self.subnet_service = Mock()
     self.credentials_manager = Mock()
     self.cancellation_service = Mock()
     self.logger = Mock()
     self.elastic_ip_service = Mock()
     self.network_interface_service = Mock()
     self.device_index_strategy = Mock()
     self.vm_details_provider = Mock()
     self.deploy_operation = DeployAMIOperation(instance_service=self.instance_service,
                                                ami_credential_service=self.credentials_manager,
                                                security_group_service=self.security_group_service,
                                                tag_service=self.tag_service,
                                                vpc_service=self.vpc_service,
                                                key_pair_service=self.key_pair,
                                                subnet_service=self.subnet_service,
                                                elastic_ip_service=self.elastic_ip_service,
                                                network_interface_service=self.network_interface_service,
                                                cancellation_service=self.cancellation_service,
                                                device_index_strategy=self.device_index_strategy,
                                                vm_details_provider=self.vm_details_provider)
Ejemplo n.º 5
0
    def __init__(self):
        tag_creator_service = TagCreatorService()
        self.aws_api = AWSApi(tag_creator_service)
        self.ec2_instance_waiter = EC2InstanceWaiter()
        self.ec2_storage_service = EC2StorageService()
        self.model_parser = AWSModelsParser()
        self.cloudshell_session_helper = CloudshellDriverHelper()
        self.aws_session_manager = AWSSessionProvider()

        self.security_group_service = AWSSecurityGroupService()

        self.deploy_ami_operation = DeployAMIOperation(
            aws_api=self.aws_api,
            security_group_service=self.security_group_service,
            tag_creator_service=tag_creator_service)

        self.power_management_operation = PowerOperation(
            aws_api=self.aws_api, instance_waiter=self.ec2_instance_waiter)

        self.delete_ami_operation = DeleteAMIOperation(
            ec2_api=self.aws_api,
            instance_waiter=self.ec2_instance_waiter,
            ec2_storage_service=self.ec2_storage_service,
            security_group_service=self.security_group_service)
Ejemplo n.º 6
0
    def __init__(self):
        tag_creator_service = TagCreatorService()
        self.aws_api = AWSApi(tag_creator_service)
        self.ec2_instance_waiter = EC2InstanceWaiter()
        self.ec2_storage_service = EC2StorageService()
        self.model_parser = AWSModelsParser()
        self.cloudshell_session_helper = CloudshellDriverHelper()
        self.aws_session_manager = AWSSessionProvider()

        self.security_group_service = AWSSecurityGroupService()

        self.deploy_ami_operation = DeployAMIOperation(aws_api=self.aws_api,
                                                       security_group_service=self.security_group_service,
                                                       tag_creator_service=tag_creator_service)

        self.power_management_operation = PowerOperation(aws_api=self.aws_api,
                                                         instance_waiter=self.ec2_instance_waiter)

        self.delete_ami_operation = DeleteAMIOperation(ec2_api=self.aws_api,
                                                       instance_waiter=self.ec2_instance_waiter,
                                                       ec2_storage_service=self.ec2_storage_service,
                                                       security_group_service=self.security_group_service)
Ejemplo n.º 7
0
    def __init__(self):
        self.image_waiter = AMIWaiter()
        self.command_result_parser = CommandResultsParser()
        self.cancellation_service = CommandCancellationService()
        self.client_err_wrapper = ClientErrorWrapper()
        self.tag_service = TagService(
            client_err_wrapper=self.client_err_wrapper)
        self.ec2_instance_waiter = InstanceWaiter(
            cancellation_service=self.cancellation_service)
        self.instance_service = InstanceService(self.tag_service,
                                                self.ec2_instance_waiter)
        self.ec2_storage_service = EC2StorageService()
        self.model_parser = AWSModelsParser()
        self.cloudshell_session_helper = CloudshellDriverHelper()
        self.aws_session_manager = AWSSessionProvider()
        self.password_waiter = PasswordWaiter(self.cancellation_service)
        self.vm_custom_params_extractor = VmCustomParamsExtractor()
        self.ami_credentials_service = InstanceCredentialsService(
            self.password_waiter)
        self.security_group_service = SecurityGroupService(self.tag_service)
        self.subnet_waiter = SubnetWaiter()
        self.subnet_service = SubnetService(self.tag_service,
                                            self.subnet_waiter)
        self.s3_service = S3BucketService()
        self.vpc_peering_waiter = VpcPeeringConnectionWaiter()
        self.key_pair_service = KeyPairService(self.s3_service)
        self.vpc_waiter = VPCWaiter()
        self.route_tables_service = RouteTablesService(self.tag_service)
        self.network_interface_service = NetworkInterfaceService(
            subnet_service=self.subnet_service,
            security_group_service=self.security_group_service,
        )
        self.elastic_ip_service = ElasticIpService()
        self.vm_details_provider = VmDetailsProvider()
        self.session_number_service = SessionNumberService()
        self.traffic_mirror_service = TrafficMirrorService()
        self.request_parser = DriverRequestParser()

        self.vpc_service = VPCService(
            tag_service=self.tag_service,
            subnet_service=self.subnet_service,
            instance_service=self.instance_service,
            vpc_waiter=self.vpc_waiter,
            vpc_peering_waiter=self.vpc_peering_waiter,
            sg_service=self.security_group_service,
            route_table_service=self.route_tables_service,
            traffic_mirror_service=self.traffic_mirror_service,
        )
        self.prepare_connectivity_operation = PrepareSandboxInfraOperation(
            vpc_service=self.vpc_service,
            security_group_service=self.security_group_service,
            key_pair_service=self.key_pair_service,
            tag_service=self.tag_service,
            route_table_service=self.route_tables_service,
            cancellation_service=self.cancellation_service,
            subnet_service=self.subnet_service,
            subnet_waiter=self.subnet_waiter,
        )

        self.deploy_ami_operation = DeployAMIOperation(
            instance_service=self.instance_service,
            ami_credential_service=self.ami_credentials_service,
            security_group_service=self.security_group_service,
            tag_service=self.tag_service,
            vpc_service=self.vpc_service,
            key_pair_service=self.key_pair_service,
            subnet_service=self.subnet_service,
            elastic_ip_service=self.elastic_ip_service,
            network_interface_service=self.network_interface_service,
            cancellation_service=self.cancellation_service,
            device_index_strategy=AllocateMissingValuesDeviceIndexStrategy(),
            vm_details_provider=self.vm_details_provider,
        )

        self.refresh_ip_operation = RefreshIpOperation(
            instance_service=self.instance_service)

        self.power_management_operation = PowerOperation(
            instance_service=self.instance_service,
            instance_waiter=self.ec2_instance_waiter,
        )

        self.delete_ami_operation = DeleteAMIOperation(
            instance_service=self.instance_service,
            ec2_storage_service=self.ec2_storage_service,
            security_group_service=self.security_group_service,
            tag_service=self.tag_service,
            elastic_ip_service=self.elastic_ip_service,
        )

        self.clean_up_operation = CleanupSandboxInfraOperation(
            vpc_service=self.vpc_service,
            key_pair_service=self.key_pair_service,
            route_table_service=self.route_tables_service,
            traffic_mirror_service=self.traffic_mirror_service,
        )

        self.deployed_app_ports_operation = DeployedAppPortsOperation(
            self.vm_custom_params_extractor,
            security_group_service=self.security_group_service,
            instance_service=self.instance_service,
        )

        self.access_key_operation = GetAccessKeyOperation(
            key_pair_service=self.key_pair_service)

        self.set_app_security_groups_operation = SetAppSecurityGroupsOperation(
            instance_service=self.instance_service,
            tag_service=self.tag_service,
            security_group_service=self.security_group_service,
        )

        self.vm_details_operation = VmDetailsOperation(
            instance_service=self.instance_service,
            vm_details_provider=self.vm_details_provider,
        )

        self.autoload_operation = AutoloadOperation()

        self.snapshot_operation = SnapshotOperation(self.instance_service,
                                                    self.image_waiter)

        self.traffic_mirroring_operation = TrafficMirrorOperation(
            tag_service=self.tag_service,
            session_number_service=self.session_number_service,
            traffic_mirror_service=self.traffic_mirror_service,
            cancellation_service=self.cancellation_service,
        )
Ejemplo n.º 8
0
class AWSShell:
    CREDENTIALS_ERROR_MESSAGE = ("Oops, looks like there was a problem with "
                                 "your cloud provider credentials. "
                                 "Please check AWS Secret Access Key "
                                 "and AWS Access Key ID")

    def __init__(self):
        self.image_waiter = AMIWaiter()
        self.command_result_parser = CommandResultsParser()
        self.cancellation_service = CommandCancellationService()
        self.client_err_wrapper = ClientErrorWrapper()
        self.tag_service = TagService(
            client_err_wrapper=self.client_err_wrapper)
        self.ec2_instance_waiter = InstanceWaiter(
            cancellation_service=self.cancellation_service)
        self.instance_service = InstanceService(self.tag_service,
                                                self.ec2_instance_waiter)
        self.ec2_storage_service = EC2StorageService()
        self.model_parser = AWSModelsParser()
        self.cloudshell_session_helper = CloudshellDriverHelper()
        self.aws_session_manager = AWSSessionProvider()
        self.password_waiter = PasswordWaiter(self.cancellation_service)
        self.vm_custom_params_extractor = VmCustomParamsExtractor()
        self.ami_credentials_service = InstanceCredentialsService(
            self.password_waiter)
        self.security_group_service = SecurityGroupService(self.tag_service)
        self.subnet_waiter = SubnetWaiter()
        self.subnet_service = SubnetService(self.tag_service,
                                            self.subnet_waiter)
        self.s3_service = S3BucketService()
        self.vpc_peering_waiter = VpcPeeringConnectionWaiter()
        self.key_pair_service = KeyPairService(self.s3_service)
        self.vpc_waiter = VPCWaiter()
        self.route_tables_service = RouteTablesService(self.tag_service)
        self.network_interface_service = NetworkInterfaceService(
            subnet_service=self.subnet_service,
            security_group_service=self.security_group_service,
        )
        self.elastic_ip_service = ElasticIpService()
        self.vm_details_provider = VmDetailsProvider()
        self.session_number_service = SessionNumberService()
        self.traffic_mirror_service = TrafficMirrorService()
        self.request_parser = DriverRequestParser()

        self.vpc_service = VPCService(
            tag_service=self.tag_service,
            subnet_service=self.subnet_service,
            instance_service=self.instance_service,
            vpc_waiter=self.vpc_waiter,
            vpc_peering_waiter=self.vpc_peering_waiter,
            sg_service=self.security_group_service,
            route_table_service=self.route_tables_service,
            traffic_mirror_service=self.traffic_mirror_service,
        )
        self.prepare_connectivity_operation = PrepareSandboxInfraOperation(
            vpc_service=self.vpc_service,
            security_group_service=self.security_group_service,
            key_pair_service=self.key_pair_service,
            tag_service=self.tag_service,
            route_table_service=self.route_tables_service,
            cancellation_service=self.cancellation_service,
            subnet_service=self.subnet_service,
            subnet_waiter=self.subnet_waiter,
        )

        self.deploy_ami_operation = DeployAMIOperation(
            instance_service=self.instance_service,
            ami_credential_service=self.ami_credentials_service,
            security_group_service=self.security_group_service,
            tag_service=self.tag_service,
            vpc_service=self.vpc_service,
            key_pair_service=self.key_pair_service,
            subnet_service=self.subnet_service,
            elastic_ip_service=self.elastic_ip_service,
            network_interface_service=self.network_interface_service,
            cancellation_service=self.cancellation_service,
            device_index_strategy=AllocateMissingValuesDeviceIndexStrategy(),
            vm_details_provider=self.vm_details_provider,
        )

        self.refresh_ip_operation = RefreshIpOperation(
            instance_service=self.instance_service)

        self.power_management_operation = PowerOperation(
            instance_service=self.instance_service,
            instance_waiter=self.ec2_instance_waiter,
        )

        self.delete_ami_operation = DeleteAMIOperation(
            instance_service=self.instance_service,
            ec2_storage_service=self.ec2_storage_service,
            security_group_service=self.security_group_service,
            tag_service=self.tag_service,
            elastic_ip_service=self.elastic_ip_service,
        )

        self.clean_up_operation = CleanupSandboxInfraOperation(
            vpc_service=self.vpc_service,
            key_pair_service=self.key_pair_service,
            route_table_service=self.route_tables_service,
            traffic_mirror_service=self.traffic_mirror_service,
        )

        self.deployed_app_ports_operation = DeployedAppPortsOperation(
            self.vm_custom_params_extractor,
            security_group_service=self.security_group_service,
            instance_service=self.instance_service,
        )

        self.access_key_operation = GetAccessKeyOperation(
            key_pair_service=self.key_pair_service)

        self.set_app_security_groups_operation = SetAppSecurityGroupsOperation(
            instance_service=self.instance_service,
            tag_service=self.tag_service,
            security_group_service=self.security_group_service,
        )

        self.vm_details_operation = VmDetailsOperation(
            instance_service=self.instance_service,
            vm_details_provider=self.vm_details_provider,
        )

        self.autoload_operation = AutoloadOperation()

        self.snapshot_operation = SnapshotOperation(self.instance_service,
                                                    self.image_waiter)

        self.traffic_mirroring_operation = TrafficMirrorOperation(
            tag_service=self.tag_service,
            session_number_service=self.session_number_service,
            traffic_mirror_service=self.traffic_mirror_service,
            cancellation_service=self.cancellation_service,
        )

    def cleanup_connectivity(self, command_context, actions):
        """# noqa
        Will delete the reservation vpc and all related resources including all remaining instances
        :param ResourceCommandContext command_context:
        :param list[RequestActionBase] actions::
        :return: json string response
        :rtype: str
        """
        with AwsShellContext(
                context=command_context,
                aws_session_manager=self.aws_session_manager) as shell_context:
            shell_context.logger.info("Cleanup Connectivity")

            result = self.clean_up_operation.cleanup(
                ec2_client=shell_context.aws_api.ec2_client,
                ec2_session=shell_context.aws_api.ec2_session,
                s3_session=shell_context.aws_api.s3_session,
                aws_ec2_data_model=shell_context.aws_ec2_resource_model,
                reservation_id=command_context.reservation.reservation_id,
                actions=actions,
                logger=shell_context.logger,
            )
            return self.command_result_parser.set_command_result(
                {"driverResponse": {
                    "actionResults": [result]
                }})

    def prepare_connectivity(self, command_context, actions,
                             cancellation_context):
        """# noqa
        Will create a vpc for the reservation and will peer it with the management vpc
        :param ResourceCommandContext command_context: The Command Context
        :param list[RequestActionBase] actions:
        :return: json string response
        :param CancellationContext cancellation_context:
        :rtype: list[ActionResultBase]
        """
        with AwsShellContext(
                context=command_context,
                aws_session_manager=self.aws_session_manager) as shell_context:
            shell_context.logger.info("Prepare Connectivity")
            reservation = self.model_parser.convert_to_reservation_model(
                command_context.reservation)
            cs_subnet_service = CsSubnetService(
                shell_context.cloudshell_session, reservation.reservation_id)

            results = self.prepare_connectivity_operation.prepare_connectivity(
                ec2_client=shell_context.aws_api.ec2_client,
                ec2_session=shell_context.aws_api.ec2_session,
                s3_session=shell_context.aws_api.s3_session,
                reservation=reservation,
                aws_ec2_datamodel=shell_context.aws_ec2_resource_model,
                actions=actions,
                cancellation_context=cancellation_context,
                cs_subnet_service=cs_subnet_service,
                logger=shell_context.logger,
            )

            return results

    def get_inventory(self, command_context):
        """Validate Cloud Provider.

        :param command_context: ResourceCommandContext
        """
        try:
            with AwsShellContext(context=command_context,
                                 aws_session_manager=self.aws_session_manager
                                 ) as shell_context:
                shell_context.logger.info("Starting Autoload Operation...")
                result = self.autoload_operation.get_inventory(
                    cloud_provider_model=shell_context.aws_ec2_resource_model,
                    logger=shell_context.logger,
                    ec2_client=shell_context.aws_api.ec2_client,
                    ec2_session=shell_context.aws_api.ec2_session,
                    s3_session=shell_context.aws_api.s3_session,
                )
                shell_context.logger.info("End Autoload Operation...")
                return result

        except ClientError as ce:
            if "AuthorizationHeaderMalformed" in str(ce):
                raise Exception(self.CREDENTIALS_ERROR_MESSAGE)
            raise ce

        except NoCredentialsError:
            raise Exception(self.CREDENTIALS_ERROR_MESSAGE)

        except ValueError as ve:
            if "Invalid endpoint" in str(ve):
                raise Exception(
                    "Oops, like you didnt configure Region correctly. Please select "
                    "Region and try again ")
            else:
                raise ve

    def power_on_ami(self, command_context):
        """# noqa
        Will power on the ami
        :param ResourceRemoteCommandContext command_context:
        """
        with AwsShellContext(
                context=command_context,
                aws_session_manager=self.aws_session_manager) as shell_context:
            shell_context.logger.info("Power On")

            resource = command_context.remote_endpoints[0]
            data_holder = self.model_parser.convert_app_resource_to_deployed_app(
                resource)

            self.power_management_operation.power_on(
                ec2_session=shell_context.aws_api.ec2_session,
                ami_id=data_holder.vmdetails.uid,
            )

    def power_off_ami(self, command_context):
        """# noqa
        Will power on the ami
        :param ResourceRemoteCommandContext command_context:
        """
        with AwsShellContext(
                context=command_context,
                aws_session_manager=self.aws_session_manager) as shell_context:
            shell_context.logger.info("Power Off")

            resource = command_context.remote_endpoints[0]
            data_holder = self.model_parser.convert_app_resource_to_deployed_app(
                resource)

            self.power_management_operation.power_off(
                ec2_session=shell_context.aws_api.ec2_session,
                ami_id=data_holder.vmdetails.uid,
            )

    def delete_instance(self, command_context):
        """# noqa
        Will delete the ami instance
        :param ResourceRemoteCommandContext command_context:
        """
        with AwsShellContext(
                context=command_context,
                aws_session_manager=self.aws_session_manager) as shell_context:
            shell_context.logger.info("Delete instance")

            resource = command_context.remote_endpoints[0]
            data_holder = self.model_parser.convert_app_resource_to_deployed_app(
                resource)

            self.delete_ami_operation.delete_instance(
                logger=shell_context.logger,
                ec2_session=shell_context.aws_api.ec2_session,
                instance_id=data_holder.vmdetails.uid,
            )

    def get_application_ports(self, command_context):
        """# noqa
        Will return the application ports in a nicely formated manner
        :param ResourceRemoteCommandContext command_context:
        :rtype: str
        """
        with AwsShellContext(
                context=command_context,
                aws_session_manager=self.aws_session_manager) as shell_context:
            shell_context.logger.info("Get Application Ports")
            resource = command_context.remote_endpoints[0]

            # Get instance id
            deployed_instance_id = (
                self.model_parser.
                try_get_deployed_connected_resource_instance_id(
                    command_context))

            # Get Allow all Storage Traffic on deployed resource
            allow_all_storage_traffic = self.model_parser.get_allow_all_storage_traffic_from_connected_resource_details(  # noqa
                command_context)

            return self.deployed_app_ports_operation.get_app_ports_from_cloud_provider(
                ec2_session=shell_context.aws_api.ec2_session,
                instance_id=deployed_instance_id,
                resource=resource,
                allow_all_storage_traffic=allow_all_storage_traffic,
            )

    def deploy_ami(self, command_context, actions, cancellation_context):
        """# noqa
        Will deploy Amazon Image on the cloud provider
        :param ResourceCommandContext command_context:
        :param list[RequestActionBase] actions::
        :param CancellationContext cancellation_context:
        """
        with AwsShellContext(
                context=command_context,
                aws_session_manager=self.aws_session_manager) as shell_context:
            shell_context.logger.info("Deploying AMI")

            deploy_action = single(actions, lambda x: isinstance(x, DeployApp))
            network_actions = [
                a for a in actions if isinstance(a, ConnectSubnet)
            ]

            deploy_data = self.deploy_ami_operation.deploy(
                ec2_session=shell_context.aws_api.ec2_session,
                s3_session=shell_context.aws_api.s3_session,
                name=deploy_action.actionParams.appName,
                reservation=self.model_parser.convert_to_reservation_model(
                    command_context.reservation),
                aws_ec2_cp_resource_model=shell_context.aws_ec2_resource_model,
                ami_deploy_action=deploy_action,
                network_actions=network_actions,
                ec2_client=shell_context.aws_api.ec2_client,
                cancellation_context=cancellation_context,
                logger=shell_context.logger,
            )

            return deploy_data

    def refresh_ip(self, command_context):
        """# noqa
        :param ResourceRemoteCommandContext command_context:
        """
        with AwsShellContext(
                context=command_context,
                aws_session_manager=self.aws_session_manager) as shell_context:
            shell_context.logger.info("Refresh IP")

            # Get Private Ip on deployed resource
            private_ip_on_resource = (
                self.model_parser.
                get_private_ip_from_connected_resource_details(command_context)
            )
            # Get Public IP on deployed resource

            (
                public_ip_attr_name,
                public_ip_on_resource,
            ) = self.model_parser.get_public_ip_attr_from_connected_resource_details(
                command_context)
            # Get instance id
            deployed_instance_id = (
                self.model_parser.
                try_get_deployed_connected_resource_instance_id(
                    command_context))
            # Get connected resource name
            resource_fullname = self.model_parser.get_connectd_resource_fullname(
                command_context)

            self.refresh_ip_operation.refresh_ip(
                cloudshell_session=shell_context.cloudshell_session,
                ec2_session=shell_context.aws_api.ec2_session,
                deployed_instance_id=deployed_instance_id,
                private_ip_on_resource=private_ip_on_resource,
                public_ip_on_resource=public_ip_on_resource,
                public_ip_attribute_name=public_ip_attr_name,
                resource_fullname=resource_fullname,
            )

    def get_access_key(self, command_context):
        """# noqa
        Returns the pem file for the connected resource
        :param ResourceRemoteCommandContext command_context:
        :rtype str:
        """
        with AwsShellContext(
                context=command_context,
                aws_session_manager=self.aws_session_manager) as shell_context:
            shell_context.logger.info("GetAccessKey")
            reservation_id = self._get_reservation_id(command_context)
            return self.access_key_operation.get_access_key(
                s3_session=shell_context.aws_api.s3_session,
                aws_ec2_resource_model=shell_context.aws_ec2_resource_model,
                reservation_id=reservation_id,
            )

    def set_app_security_groups(self, context, request):
        """# noqa
        Set security groups (inbound rules only)
        :param context: todo - set the type of the parameter
        :param request: The json request
        :return:
        """
        with AwsShellContext(
                context=context,
                aws_session_manager=self.aws_session_manager) as shell_context:
            shell_context.logger.info("Set App Security Groups")

            reservation = self.model_parser.convert_to_reservation_model(
                context.reservation)
            app_security_group_models = (
                self.model_parser.convert_to_app_security_group_models(request)
            )

            result = self.set_app_security_groups_operation.set_apps_security_groups(
                app_security_group_models=app_security_group_models,
                reservation=reservation,
                ec2_session=shell_context.aws_api.ec2_session,
                logger=shell_context.logger,
            )

            json_result = SetAppSecurityGroupActionResult.to_json(result)

            return json_result

    def get_vm_details(self, context, cancellation_context, requests_json):
        """# noqa
        Get vm details for specific deployed app
        :type context: ResourceCommandContext
        :rtype str
        """
        results = []
        vm_details_requests = [
            VmDetailsRequest(item) for item in DeployDataHolder(
                jsonpickle.decode(requests_json)).items
        ]

        for request in vm_details_requests:
            if cancellation_context.is_cancelled:
                break

            try:
                with AwsShellContext(context=context,
                                     aws_session_manager=self.
                                     aws_session_manager) as shell_context:
                    shell_context.logger.info("Get VmDetails")
                    vm_details = self.vm_details_operation.get_vm_details(
                        request.uuid, shell_context.aws_api.ec2_session)
                    vm_details.appName = request.app_name
                    results.append(vm_details)
            except Exception as e:
                result = VmDetailsData()
                result.appName = request.app_name
                result.error = str(e)
                results.append(result)

        return self.command_result_parser.set_command_result(results)

    # def remote_get_snapshots(self, context):  # noqa
    #     with AwsShellContext(context=context, aws_session_manager=self.aws_session_manager) as shell_context:  # noqa
    #         with ErrorHandlingContext(shell_context.logger):  # noqa
    #             shell_context.logger.info('Get Snapshots')  # noqa
    #
    #             resource = context.remote_endpoints[0]  # noqa
    #             resource_fullname = self.model_parser.get_connectd_resource_fullname(context)  # noqa
    #             reservation_id = self._get_reservation_id(context)  # noqa
    #
    #             return self.snapshot_operation.get(shell_context.aws_api.ec2_client,  # noqa
    #                                                reservation_id, resource_fullname)  # noqa

    def remote_get_snapshots(self, context):
        with AwsShellContext(
                context=context,
                aws_session_manager=self.aws_session_manager) as shell_context:
            shell_context.logger.info("Get Snapshots")

            resource = context.remote_endpoints[0]
            data_holder = self.model_parser.convert_app_resource_to_deployed_app(
                resource)

            return self.snapshot_operation.get_snapshots(
                shell_context.aws_api.ec2_client,
                instance_id=data_holder.vmdetails.uid)

    def remote_save_snapshot(self, context, snapshot_name):
        with AwsShellContext(
                context=context,
                aws_session_manager=self.aws_session_manager) as shell_context:
            shell_context.logger.info("Save Snapshot")
            resource = context.remote_endpoints[0]
            reservation = ReservationModel(context.remote_reservation)
            tags = self.tag_service.get_default_tags(snapshot_name,
                                                     reservation)
            data_holder = self.model_parser.convert_app_resource_to_deployed_app(
                resource)
            self.snapshot_operation.save_snapshot(
                ec2_client=shell_context.aws_api.ec2_client,
                ec2_session=shell_context.aws_api.ec2_session,
                instance_id=data_holder.vmdetails.uid,
                snapshot_name=snapshot_name,
                tags=tags,
            )

    def remote_restore_snapshot(self, context, snapshot_name):
        with AwsShellContext(
                context=context,
                aws_session_manager=self.aws_session_manager) as shell_context:
            shell_context.logger.info("Save Snapshot")
            resource = context.remote_endpoints[0]
            reservation = ReservationModel(context.remote_reservation)
            tags = self.tag_service.get_default_tags(snapshot_name,
                                                     reservation)
            data_holder = self.model_parser.convert_app_resource_to_deployed_app(
                resource)
            self.snapshot_operation.save_snapshot(
                ec2_client=shell_context.aws_api.ec2_client,
                ec2_session=shell_context.aws_api.ec2_session,
                instance_id=data_holder.vmdetails.uid,
                snapshot_name=snapshot_name,
                tags=tags,
            )

    def save_app(self, context, cancellation_context):
        """# noqa
        :param context:
        :param cancellation_context:
        :return:
        """
        with AwsShellContext(
                context=context,
                aws_session_manager=self.aws_session_manager) as shell_context:
            shell_context.logger.info("Save Snapshot")

            resource = context.remote_endpoints[0]

            data_holder = self.model_parser.convert_app_resource_to_deployed_app(
                resource)
            resource_fullname = self.model_parser.get_connectd_resource_fullname(
                context)

            image_id = self.snapshot_operation.save(
                logger=shell_context.logger,
                ec2_session=shell_context.aws_api.ec2_session,
                instance_id=data_holder.vmdetails.uid,
                deployed_app_name=resource_fullname,
                snapshot_prefix="",
                no_reboot=True,
            )

            return json.dumps({"AWS EC2 Instance.AWS AMI Id": image_id})

    def add_custom_tags(self, context, request):
        """# noqa
        :param ResourceCommandContext context:
        :param str request:
        :return:
        """
        with AwsShellContext(
                context=context,
                aws_session_manager=self.aws_session_manager) as shell_context:
            shell_context.logger.info("Add custom tags")

            # Get instance id
            deployed_instance_id = (
                self.model_parser.
                try_get_deployed_connected_resource_instance_id(context))

            # Expected request syntax:
            # [{  # noqa
            #     'Key': 'string',  # noqa
            #     'Value': 'string'  # noqa
            # }]  # noqa
            tags = json.loads(request)

            instance = self.instance_service.get_instance_by_id(
                shell_context.aws_api.ec2_session, deployed_instance_id)
            instance.create_tags(Tags=tags)

    def create_traffic_mirroring(self, context, cancellation_context, request):
        """# noqa
        Will create a vpc for the reservation and will peer it with the management vpc
        :param request:
        :param ResourceCommandContext context:

        :return: json string response
        :param CancellationContext cancellation_context:
        :rtype: list[ActionResultBase]
        """
        with AwsShellContext(
                context=context,
                aws_session_manager=self.aws_session_manager) as shell_context:
            shell_context.logger.info("Create traffic mirroring")
            actions = self._parse_request(request, shell_context)
            self.traffic_mirroring_operation.validate_create_actions(
                actions, request, shell_context.logger)
            results = self.traffic_mirroring_operation.create(
                ec2_client=shell_context.aws_api.ec2_client,
                reservation=self.model_parser.convert_to_reservation_model(
                    context.reservation),
                actions=actions,
                cancellation_context=cancellation_context,
                logger=shell_context.logger,
                cloudshell=shell_context.cloudshell_session,
            )

            return results

    def _parse_request(self, request, shell_context):
        try:
            actions = self.request_parser.convert_driver_request_to_actions(
                request)
            if not actions:
                raise Exception("Invalid request: " + request)
        except Exception as e:
            shell_context.logger.exception("Invalid request " + request)
            raise e
        return actions

    @staticmethod
    def _get_reservation_id(context):
        reservation_id = None
        reservation = getattr(context, "reservation",
                              getattr(context, "remote_reservation", None))
        if reservation:
            reservation_id = reservation.reservation_id
        return reservation_id

    def remove_traffic_mirroring(self, context, request):
        """# noqa
        Can remove traffic mirroring sessions by session id, or all sessions associated with a traffic mirror target (by target nic id)
        :param str request:
        :param ResourceCommandContext context:
        :param ResourceCommandContext context:

        :return: json string response
        :rtype: list[ActionResultBase]
        """
        with AwsShellContext(
                context=context,
                aws_session_manager=self.aws_session_manager) as shell_context:
            shell_context.logger.info("Create traffic mirroring")

            self.traffic_mirroring_operation.validate_remove_request(
                request, shell_context.logger)

            actions = self._parse_request(request, shell_context)

            results = self.traffic_mirroring_operation.remove(
                ec2_client=shell_context.aws_api.ec2_client,
                reservation=self.model_parser.convert_to_reservation_model(
                    context.reservation),
                actions=actions,
                logger=shell_context.logger,
                cloudshell=shell_context.cloudshell_session,
            )

            return results

    def assign_additional_private_ipv4s(self, context, vnic_id, new_ips):
        with AwsShellContext(
                context=context,
                aws_session_manager=self.aws_session_manager) as shell_context:
            shell_context.logger.info("Assign additional IP Addresses")

            ips = map(str.strip, new_ips.split(";"))
            try:
                response = shell_context.aws_api.ec2_client.assign_private_ip_addresses(
                    AllowReassignment=True,
                    NetworkInterfaceId=vnic_id,
                    PrivateIpAddresses=ips,
                )
                assigned_ips_response = response.get(
                    "AssignedPrivateIpAddresses", [])
                return ";".join([
                    ip.get("PrivateIpAddress") for ip in assigned_ips_response
                    if ip.get("PrivateIpAddress")
                ])
            except Exception:
                shell_context.logger.error("Failed to add ips", exc_info=1)
                return None
class TestDeployOperation(TestCase):
    def setUp(self):
        self.ec2_datamodel = Mock()
        self.ec2_session = Mock()
        self.ec2_client = Mock()
        self.s3_session = Mock()
        self.instance_service = Mock()
        self.security_group_service = Mock()
        self.tag_service = Mock()
        self.key_pair = Mock()
        self.vpc_service = Mock()
        self.subnet_service = Mock()
        self.credentials_manager = Mock()
        self.cancellation_service = Mock()
        self.logger = Mock()
        self.elastic_ip_service = Mock()
        self.network_interface_service = Mock()
        self.device_index_strategy = Mock()
        self.vm_details_provider = Mock()
        self.deploy_operation = DeployAMIOperation(instance_service=self.instance_service,
                                                   ami_credential_service=self.credentials_manager,
                                                   security_group_service=self.security_group_service,
                                                   tag_service=self.tag_service,
                                                   vpc_service=self.vpc_service,
                                                   key_pair_service=self.key_pair,
                                                   subnet_service=self.subnet_service,
                                                   elastic_ip_service=self.elastic_ip_service,
                                                   network_interface_service=self.network_interface_service,
                                                   cancellation_service=self.cancellation_service,
                                                   device_index_strategy=self.device_index_strategy,
                                                   vm_details_provider=self.vm_details_provider)

    def test_deploy_rollback_called(self):
        # arrange
        ami_deploy_action = Mock()
        network_actions = None
        cancellation_context = Mock()
        inst_name = 'my name'
        reservation = Mock()
        self.deploy_operation._create_security_group_for_instance = Mock()
        self.deploy_operation._get_block_device_mappings = Mock()
        self.deploy_operation._rollback_deploy = Mock()
        self.instance_service.create_instance = Mock(side_effect=Exception)
        self.deploy_operation._prepare_network_result_models = Mock()

        # act & assert
        self.assertRaises(Exception, self.deploy_operation.deploy, self.ec2_session, self.s3_session, inst_name,
                          reservation, self.ec2_datamodel, ami_deploy_action, network_actions, self.ec2_client, cancellation_context,
                          self.logger)
        self.deploy_operation._rollback_deploy.assert_called_once()

    def test_rollback(self):
        # prepare
        self.deploy_operation._extract_instance_id_on_cancellation = Mock()
        inst_id = Mock()
        security_group = Mock()
        instance = Mock()
        network_config_results = [Mock(public_ip='pub1'), Mock(public_ip='pub2')]
        self.deploy_operation.instance_service.get_instance_by_id = Mock(return_value=instance)

        # act
        self.deploy_operation._rollback_deploy(ec2_session=self.ec2_session,
                                               instance_id=inst_id,
                                               custom_security_group=security_group,
                                               network_config_results=network_config_results,
                                               logger=self.logger)

        # assert
        self.deploy_operation.instance_service.get_instance_by_id.assert_called_once_with(ec2_session=self.ec2_session,
                                                                                          id=inst_id)
        self.deploy_operation.instance_service.terminate_instance.assert_called_once_with(instance=instance)
        self.deploy_operation.security_group_service.delete_security_group.assert_called_once_with(security_group)
        self.deploy_operation.elastic_ip_service.find_and_release_elastic_address.assert_has_calls(
                [call(ec2_session=self.ec2_session, elastic_ip='pub1'),
                 call(ec2_session=self.ec2_session, elastic_ip='pub2')],
                any_order=True)

    def test_extract_instance_id_on_cancellation(self):
        # prepare
        instance = Mock()
        instance_id = 'some_id'
        cancellation_exception = CancellationException("cancelled_test", {'instance_ids': [instance_id]})

        # act
        extracted_id = self.deploy_operation._extract_instance_id_on_cancellation(cancellation_exception, instance)

        # assert
        self.assertEquals(extracted_id, instance_id)

    def test_deploy(self):
        # prepare
        ami_datamodel = Mock()
        ami_datamodel.storage_size = 30
        ami_datamodel.inbound_ports = "80"
        ami_datamodel.outbound_ports = "20"
        ami_datamodel.add_public_ip = None
        ami_datamodel.allocate_elastic_ip = True
        ami_deploy_action = Mock()
        ami_deploy_action.actionParms = Mock()
        ami_deploy_action.actionParams.deployment = Mock()
        ami_deploy_action.actionParams.deployment.customModel = ami_datamodel
        instance = Mock()
        instance.network_interfaces = []
        instance.tags = [{'Key': 'Name', 'Value': 'my name'}]
        self.instance_service.create_instance = Mock(return_value=instance)
        sg = Mock()
        self.security_group_service.create_security_group = Mock(return_value=sg)
        self.deploy_operation._get_block_device_mappings = Mock()
        cancellation_context = Mock()
        inst_name = 'my name'
        reservation = Mock()
        ami_deployment_info = Mock()
        network_actions = None
        self.deploy_operation._create_deployment_parameters = Mock(return_value=ami_deployment_info)
        self.deploy_operation._populate_network_config_results_with_interface_data = Mock()
        network_config_results_dto = Mock()
        network_config_results = [Mock(device_index=0, public_ip=instance.public_ip_address)]
        self.deploy_operation._prepare_network_result_models = Mock(return_value=network_config_results)
        self.deploy_operation._prepare_network_config_results_dto = Mock(return_value=[])

        # act
        res = self.deploy_operation.deploy(ec2_session=self.ec2_session,
                                           s3_session=self.s3_session,
                                           name=inst_name,
                                           reservation=reservation,
                                           aws_ec2_cp_resource_model=self.ec2_datamodel,
                                           ami_deploy_action=ami_deploy_action,
                                           network_actions=network_actions,
                                           ec2_client=self.ec2_client,
                                           cancellation_context=cancellation_context,
                                           logger=self.logger)

        ami_credentials = self.credentials_manager.get_windows_credentials()

        # assert
        self.assertEqual(res[0].vmName, 'my name')
        self.assertEqual(res[0].deployedAppAdditionalData["inbound_ports"], ami_datamodel.inbound_ports)
        self.assertEqual(res[0].vmUuid, instance.instance_id)
        self.assertEqual(res[0].deployedAppAttributes[0].attributeName, 'Password')
        self.assertEqual(res[0].deployedAppAttributes[0].attributeValue, ami_credentials.password)
        self.assertEqual(res[0].deployedAppAttributes[1].attributeName, 'User')
        self.assertEqual(res[0].deployedAppAttributes[1].attributeValue, ami_credentials.user_name)
        self.assertTrue(self.tag_service.get_security_group_tags.called)
        self.assertTrue(self.security_group_service.create_security_group.called)
        self.assertTrue(self.instance_service.set_ec2_resource_tags.called_with(
                self.security_group_service.create_security_group()),
                self.tag_service.get_security_group_tags())

        self.assertTrue(self.key_pair.load.called_with(self.ec2_datamodel.key_pair_location,
                                                       instance.key_pair.key_name,
                                                       self.key_pair.FILE_SYSTEM))

        self.assertTrue(self.security_group_service.set_security_group_rules.called_with(
                ami_datamodel, self.security_group_service.create_security_group()))

        self.security_group_service.remove_allow_all_outbound_rule.assert_called_with(security_group=sg)

        self.instance_service.create_instance.assert_called_once_with(ec2_session=self.ec2_session,
                                                                      name=inst_name,
                                                                      reservation=reservation,
                                                                      ami_deployment_info=ami_deployment_info,
                                                                      ec2_client=self.ec2_client,
                                                                      wait_for_status_check=ami_datamodel.wait_for_status_check,
                                                                      cancellation_context=cancellation_context,
                                                                      logger=self.logger)

        self.deploy_operation.elastic_ip_service.set_elastic_ips.assert_called_once_with(
                ec2_session=self.ec2_session,
                ec2_client=self.ec2_client,
                instance=instance,
                ami_deployment_model=ami_datamodel,
                network_actions=None,
                network_config_results=network_config_results,
                logger=self.logger)

    def test_get_block_device_mappings_throws_max_storage_error(self):
        ec_model = Mock()
        ec_model.max_storage_size = 30
        ec_model.max_storage_iops = 0

        ami = Mock()
        ami.root_volume_name = 'name'
        ami.storage_size = 50
        ami.storage_iops = 0
        ami.storage_type = ''

        image = Mock()
        image.root_device_name = '/sda'
        root_device = {'DeviceName': image.root_device_name,
                       'Ebs': {}}
        image.block_device_mappings = [root_device]

        with self.assertRaisesRegexp(ValueError,
                                     'Requested storage size is bigger than the max allowed storage size of 30'):
            self.deploy_operation._get_block_device_mappings(image=image,
                                                             ami_deployment_model=ami,
                                                             aws_ec2_resource_model=ec_model)

    def test_get_block_device_mappings_throws_max_iops_error(self):
        ec_model = Mock()
        ec_model.max_storage_size = 30
        ec_model.max_storage_iops = 100

        ami = Mock()
        ami.root_volume_name = 'name'
        ami.storage_size = 30
        ami.storage_iops = 200
        ami.storage_type = 'io1'

        image = Mock()
        image.root_device_name = '/sda'
        root_device = {'DeviceName': image.root_device_name,
                       'Ebs': {}}
        image.block_device_mappings = [root_device]

        with self.assertRaisesRegexp(ValueError,
                                     'Requested storage IOPS is bigger than the max allowed storage IOPS of 100'):
            self.deploy_operation._get_block_device_mappings(image=image,
                                                             ami_deployment_model=ami,
                                                             aws_ec2_resource_model=ec_model)

    def test_get_block_device_mappings_from_image(self):
        ec_model = Mock()
        ec_model.max_storage_size = 0
        ec_model.max_storage_iops = 0

        ami = Mock()
        ami.root_volume_name = 'name'
        ami.storage_size = 0
        ami.storage_iops = 0
        ami.storage_type = 'auto'

        image = Mock()
        image.root_device_name = '/sda'
        root_device = {'DeviceName': image.root_device_name,
                       'Ebs': {
                           'VolumeSize': '40',
                           'VolumeType': 'io1',
                           'Iops': '240',
                       }}
        image.block_device_mappings = [root_device]

        res = self.deploy_operation._get_block_device_mappings(image=image,
                                                               ami_deployment_model=ami,
                                                               aws_ec2_resource_model=ec_model)

        self.assertEqual(res[0]['DeviceName'], ami.root_volume_name)
        self.assertEqual(str(res[0]['Ebs']['VolumeSize']), str(40))
        self.assertEqual(res[0]['Ebs']['DeleteOnTermination'], True)
        self.assertEqual(res[0]['Ebs']['VolumeType'], 'io1')
        self.assertEqual(res[0]['Ebs']['Iops'], 240)

    def test_get_block_device_mappings_from_app(self):
        ec_model = Mock()
        ec_model.max_storage_size = 0
        ec_model.max_storage_iops = 0

        ami = Mock()
        ami.root_volume_name = 'name'
        ami.storage_size = 30
        ami.storage_type = 'standart'

        image = Mock()
        image.root_device_name = '/sda'
        root_device = {'DeviceName': image.root_device_name,
                       'Ebs': {}}
        image.block_device_mappings = [root_device]

        res = self.deploy_operation._get_block_device_mappings(image=image,
                                                               ami_deployment_model=ami,
                                                               aws_ec2_resource_model=ec_model)

        self.assertEqual(res[0]['DeviceName'], ami.root_volume_name)
        self.assertEqual(str(res[0]['Ebs']['VolumeSize']), str(30))
        self.assertEqual(res[0]['Ebs']['DeleteOnTermination'], True)
        self.assertEqual(res[0]['Ebs']['VolumeType'], 'standart')
        self.assertFalse('Iops' in res[0]['Ebs'])

    def test_get_block_device_mappings_from_app_with_iops(self):
        ec_model = Mock()
        ec_model.max_storage_size = 0
        ec_model.max_storage_iops = 0

        ami = Mock()
        ami.root_volume_name = 'name'
        ami.storage_size = 30
        ami.storage_iops = 300
        ami.storage_type = 'io1'

        image = Mock()
        image.root_device_name = '/sda'
        root_device = {'DeviceName': image.root_device_name,
                       'Ebs': {}}
        image.block_device_mappings = [root_device]

        res = self.deploy_operation._get_block_device_mappings(image=image,
                                                               ami_deployment_model=ami,
                                                               aws_ec2_resource_model=ec_model)

        self.assertEqual(res[0]['DeviceName'], ami.root_volume_name)
        self.assertEqual(str(res[0]['Ebs']['VolumeSize']), str(30))
        self.assertEqual(res[0]['Ebs']['DeleteOnTermination'], True)
        self.assertEqual(res[0]['Ebs']['VolumeType'], 'io1')
        self.assertEqual(res[0]['Ebs']['Iops'], 300)

    def test_create_deployment_parameters_no_ami_id(self):
        ami = Mock()
        network_actions = MagicMock()
        ami.aws_ami_id = None
        self.assertRaises(ValueError,
                          self.deploy_operation._create_deployment_parameters,
                          ec2_session=Mock(),
                          aws_ec2_resource_model=self.ec2_datamodel,
                          ami_deployment_model=ami,
                          network_actions=network_actions,
                          vpc=Mock(),
                          security_group=None,
                          key_pair='keypair',
                          reservation=Mock(),
                          network_config_results=Mock(),
                          logger=self.logger)

    def test_create_deployment_parameters_single_subnet(self):
        image = Mock()
        image.state = 'available'
        ec2_session = Mock()
        ec2_session.Image = Mock(return_value=image)
        ami_model = Mock()
        ami_model.aws_ami_id = 'asd'
        ami_model.storage_size = '0'
        ami_model.iam_role = ""
        network_actions = None
        vpc = Mock()
        self.deploy_operation._get_block_device_mappings = Mock()

        aws_model = self.deploy_operation._create_deployment_parameters(ec2_session=ec2_session,
                                                                        aws_ec2_resource_model=self.ec2_datamodel,
                                                                        ami_deployment_model=ami_model,
                                                                        network_actions=network_actions,
                                                                        vpc=vpc,
                                                                        security_group=None,
                                                                        key_pair='keypair',
                                                                        reservation=Mock(),
                                                                        network_config_results=MagicMock(),
                                                                        logger=self.logger)

        self.assertEquals(aws_model.min_count, 1)
        self.assertEquals(aws_model.max_count, 1)
        self.assertEquals(aws_model.aws_key, 'keypair')
        self.assertTrue(len(aws_model.security_group_ids) == 1)
        self.assertTrue(len(aws_model.network_interfaces) == 1)

    def test_create_deployment_parameters_no_iam_role(self):
        image = Mock()
        image.state = 'available'
        ec2_session = Mock()
        ec2_session.Image = Mock(return_value=image)
        ami_model = Mock()
        ami_model.iam_role = ""
        network_actions = None
        vpc = Mock()
        self.deploy_operation._get_block_device_mappings = Mock()

        aws_model = self.deploy_operation._create_deployment_parameters(ec2_session=ec2_session,
                                                                        aws_ec2_resource_model=self.ec2_datamodel,
                                                                        ami_deployment_model=ami_model,
                                                                        network_actions=network_actions,
                                                                        vpc=vpc,
                                                                        security_group=None,
                                                                        key_pair='keypair',
                                                                        reservation=Mock(),
                                                                        network_config_results=MagicMock(),
                                                                        logger=self.logger,)

        # if instance doesnt have iam role, the deployment params will have an empty iam instance profile dict
        self.assertTrue(not any(aws_model.iam_role))  # not any(some_dict) => is empty dictionary

    def test_create_deployment_parameters_iam_role_not_arn(self):
        image = Mock()
        image.state = 'available'
        ec2_session = Mock()
        ec2_session.Image = Mock(return_value=image)
        ami_model = Mock()
        ami_model.iam_role = "admin_role"
        vpc = Mock()
        self.deploy_operation._get_block_device_mappings = Mock()
        network_actions = None

        aws_model = self.deploy_operation._create_deployment_parameters(ec2_session=ec2_session,
                                                                        aws_ec2_resource_model=self.ec2_datamodel,
                                                                        ami_deployment_model=ami_model,
                                                                        network_actions=network_actions,
                                                                        vpc=vpc,
                                                                        security_group=None,
                                                                        key_pair='keypair',
                                                                        reservation=Mock(),
                                                                        network_config_results=MagicMock(),
                                                                        logger=self.logger,)

        # if instance has iam role, but not in the form of arn, will return dict with iam role name
        self.assertTrue(aws_model.iam_role['Name'] == ami_model.iam_role)

    def test_create_deployment_parameters_iam_role_arn(self):
        image = Mock()
        image.state = 'available'
        ec2_session = Mock()
        ec2_session.Image = Mock(return_value=image)
        ami_model = Mock()
        network_actions = None
        ami_model.iam_role = "arn:aws:iam::admin_role"
        vpc = Mock()
        self.deploy_operation._get_block_device_mappings = Mock()

        aws_model = self.deploy_operation._create_deployment_parameters(ec2_session=ec2_session,
                                                                        aws_ec2_resource_model=self.ec2_datamodel,
                                                                        ami_deployment_model=ami_model,
                                                                        network_actions=network_actions,
                                                                        vpc=vpc,
                                                                        security_group=None,
                                                                        key_pair='keypair',
                                                                        reservation=Mock(),
                                                                        network_config_results=MagicMock(),
                                                                        logger=self.logger)

        # if instance has iam role, but not in the form of arn, will return dict with iam role name
        self.assertTrue(aws_model.iam_role['Arn'] == ami_model.iam_role)

    def test_prepare_network_interfaces_multi_subnets_with_public_ip(self):
        ami_model = Mock()
        ami_model.add_public_ip = True
        ami_model.network_configurations = [Mock(), Mock()]

        network_actions = [Mock(spec=ConnectSubnet),Mock(spec=ConnectSubnet)]

        with self.assertRaisesRegexp(ValueError, "Public IP option is not supported with multiple subnets"):
            self.deploy_operation._prepare_network_interfaces(ami_deployment_model=ami_model,
                                                              network_actions=network_actions,
                                                              vpc=Mock(),
                                                              security_group_ids=MagicMock(),
                                                              network_config_results=MagicMock(),
                                                              logger=self.logger)

    def test_prepare_network_interfaces_multi_subnets(self):
        def build_network_interface_handler(*args, **kwargs):
            return {'SubnetId': kwargs['subnet_id']}

        # arrange
        vpc = Mock()
        security_group_ids = MagicMock()

        action1 = ConnectSubnet()
        action1.actionId = 'action1'
        action1.actionParams = ConnectToSubnetParams()
        action1.actionParams.subnetId= 'sub1'
        action1.actionParams.vnicName = 0
        action1.actionParams.isPublic = True

        action2 = ConnectSubnet()
        action2.actionId = 'action2'
        action2.actionParams = ConnectToSubnetParams()
        action2.actionParams.subnetId = 'sub2'
        action2.actionParams.vnicName = 1

        ami_model = Mock()
        network_actions = [action1, action2]
        ami_model.add_public_ip = False

        res_model_1 = DeployNetworkingResultModel('action1')
        res_model_2 = DeployNetworkingResultModel('action2')
        network_config_results = [res_model_1, res_model_2]

        self.deploy_operation.network_interface_service.build_network_interface_dto = \
            Mock(side_effect=build_network_interface_handler)

        # act
        net_interfaces = self.deploy_operation._prepare_network_interfaces(ami_deployment_model=ami_model,
                                                                           network_actions=network_actions,
                                                                           vpc=vpc,
                                                                           security_group_ids=security_group_ids,
                                                                           network_config_results=network_config_results,
                                                                           logger=self.logger)

        # assert
        print res_model_1.device_index
        self.assertEquals(res_model_1.device_index, 0)
        self.assertEquals(res_model_2.device_index, 1)
        self.assertEquals(len(net_interfaces), 2)
        self.assertEquals(net_interfaces[0]['SubnetId'], 'sub1')
        self.assertEquals(net_interfaces[1]['SubnetId'], 'sub2')

    def test_prepare_network_config_results_dto_returns_empty_array_when_no_network_config(self):
        # arrange
        network_actions = None


        # act
        dtos = self.deploy_operation._prepare_network_config_results_dto(Mock(), network_actions)

        # assert
        self.assertTrue(isinstance(dtos, list))
        self.assertFalse(dtos)

    def test_prepare_network_config_results_dto(self):
        # arrange
        model1 = DeployNetworkingResultModel(action_id='aaa')
        model1.device_index = 0
        model1.interface_id = "interface1"
        model1.mac_address = "mac1"
        model1.private_ip = "priv1"
        model1.public_ip = "pub1"

        model2 = DeployNetworkingResultModel(action_id='bbb')
        model2.device_index = 1
        model2.interface_id = "interface2"
        model2.mac_address = "mac2"
        model2.private_ip = "priv2"
        model2.public_ip = "pub2"

        models = [model1, model2]

        network_actions = Mock()
        # act
        dtos = self.deploy_operation._prepare_network_config_results_dto(models, network_actions)

        self.assertEquals(len(dtos), 2)
        dto1 = dtos[0]
        dto2 = dtos[1]
        self.assertEquals(dto1.actionId, "aaa")
        self.assertEquals(dto2.actionId, "bbb")
        self.assertTrue(dto1.success)
        self.assertTrue(dto2.success)
        self.assertEquals(dto1.type, "ConnectToSubnet")
        self.assertEquals(dto2.type, "ConnectToSubnet")
        self.assertTrue('"interface_id": "interface1"' in dto1.interface)
        self.assertTrue('"Device Index": 0' in dto1.interface)
        self.assertTrue('"IP": "priv1"' in dto1.interface)
        self.assertTrue('"Public IP": "pub1"' in dto1.interface)
        self.assertTrue('"MAC Address": "mac1"' in dto1.interface)

    def test_deploy_raised_no_vpc(self):
        # arrange
        my_vpc_service = Mock()
        my_vpc_service.find_vpc_for_reservation = Mock(return_value=None)
        deploy_operation = DeployAMIOperation(self.instance_service,
                                              self.credentials_manager,
                                              self.security_group_service,
                                              self.tag_service,
                                              my_vpc_service,
                                              self.key_pair,
                                              self.subnet_service,
                                              self.elastic_ip_service,
                                              self.network_interface_service,
                                              self.cancellation_service,
                                              self.device_index_strategy,
                                              self.vm_details_provider)

        # act & assert
        with self.assertRaisesRegexp(ValueError, 'VPC is not set for this reservation'):
            deploy_operation.deploy(ec2_session=Mock(),
                                    s3_session=Mock(),
                                    name=Mock(),
                                    reservation=Mock(),
                                    aws_ec2_cp_resource_model=Mock(),
                                    ami_deploy_action=Mock(),
                                    network_actions=Mock(),
                                    ec2_client=Mock(),
                                    cancellation_context=Mock(),
                                    logger=self.logger)

    def test__prepare_network_result_models_returns_empty_model_when_no_network_config(self):
        # arrange
        network_actions = None

        # act
        models = self.deploy_operation._prepare_network_result_models(network_actions)

        # assert
        self.assertEquals(len(models), 1)
        self.assertEquals(models[0].action_id, '')
        self.assertTrue(isinstance(models[0], DeployNetworkingResultModel))

    def test__prepare_network_result_models_returns_result_model_per_action(self):
        # arrange
        action1 = Mock(spec=PrepareCloudInfra, actionId=Mock(spec=str))
        action1.actionParams = Mock(spec=ConnectToSubnetParams)

        action2 = Mock(spec=PrepareCloudInfra, actionId=Mock(spec=str))
        action2.actionParams = Mock(spec=ConnectToSubnetParams)

        network_actions = [action1, action2]

        # act
        models = self.deploy_operation._prepare_network_result_models(network_actions)

        # assert
        self.assertEquals(len(models), 2)
        self.assertTrue(isinstance(models[0], DeployNetworkingResultModel))
        self.assertTrue(isinstance(models[1], DeployNetworkingResultModel))
        self.assertEquals(models[0].action_id, action1.actionId)
        self.assertEquals(models[1].action_id, action2.actionId)

    def test_populate_network_config_results_with_interface_data(self):
        # arrange
        instance = Mock()
        instance.network_interfaces_attribute = [
            {
                "Attachment": {"DeviceIndex": 0},
                "NetworkInterfaceId": "int1",
                "PrivateIpAddress": "pri_ip_1",
                "MacAddress": "mac1",
                "Association": {"PublicIp": "pub_ip_1"}
            },
            {
                "Attachment": {"DeviceIndex": 1},
                "NetworkInterfaceId": "int2",
                "PrivateIpAddress": "pri_ip_2",
                "MacAddress": "mac2"
            }
        ]
        network_config_results = [DeployNetworkingResultModel("action1"), DeployNetworkingResultModel("action2")]
        network_config_results[0].device_index = 0
        network_config_results[1].device_index = 1

        # act
        self.deploy_operation._populate_network_config_results_with_interface_data(
                instance=instance,
                network_config_results=network_config_results)

        # assert
        self.assertEquals(network_config_results[0].interface_id, "int1")
        self.assertEquals(network_config_results[0].private_ip, "pri_ip_1")
        self.assertEquals(network_config_results[0].mac_address, "mac1")
        self.assertEquals(network_config_results[0].public_ip, "pub_ip_1")

        self.assertEquals(network_config_results[1].interface_id, "int2")
        self.assertEquals(network_config_results[1].private_ip, "pri_ip_2")
        self.assertEquals(network_config_results[1].mac_address, "mac2")
        self.assertEquals(network_config_results[1].public_ip, "")
Ejemplo n.º 10
0
class TestDeployOperation(TestCase):
    def setUp(self):
        self.ec2_datamodel = Mock()
        self.ec2_session = Mock()
        self.ec2_client = Mock()
        self.s3_session = Mock()
        self.instance_service = Mock()
        self.security_group_service = Mock()
        self.tag_service = Mock()
        self.key_pair = Mock()
        self.vpc_service = Mock()
        self.subnet_service = Mock()
        self.credentials_manager = Mock()
        self.cancellation_service = Mock()
        self.logger = Mock()
        self.elastic_ip_service = Mock()
        self.network_interface_service = Mock()
        self.device_index_strategy = Mock()
        self.vm_details_provider = Mock()
        self.deploy_operation = DeployAMIOperation(
            instance_service=self.instance_service,
            ami_credential_service=self.credentials_manager,
            security_group_service=self.security_group_service,
            tag_service=self.tag_service,
            vpc_service=self.vpc_service,
            key_pair_service=self.key_pair,
            subnet_service=self.subnet_service,
            elastic_ip_service=self.elastic_ip_service,
            network_interface_service=self.network_interface_service,
            cancellation_service=self.cancellation_service,
            device_index_strategy=self.device_index_strategy,
            vm_details_provider=self.vm_details_provider,
        )

    def test_deploy_rollback_called(self):
        # arrange
        ami_deploy_action = Mock()
        network_actions = None
        cancellation_context = Mock()
        inst_name = "my name"
        reservation = Mock()
        self.deploy_operation._create_security_group_for_instance = Mock()
        self.deploy_operation._get_block_device_mappings = Mock()
        self.deploy_operation._rollback_deploy = Mock()
        self.instance_service.create_instance = Mock(side_effect=Exception)
        self.deploy_operation._prepare_network_result_models = Mock()

        # act & assert
        self.assertRaises(
            Exception,
            self.deploy_operation.deploy,
            self.ec2_session,
            self.s3_session,
            inst_name,
            reservation,
            self.ec2_datamodel,
            ami_deploy_action,
            network_actions,
            self.ec2_client,
            cancellation_context,
            self.logger,
        )
        self.deploy_operation._rollback_deploy.assert_called_once()

    def test_rollback(self):
        # prepare
        self.deploy_operation._extract_instance_id_on_cancellation = Mock()
        inst_id = Mock()
        security_group = Mock()
        instance = Mock()
        network_config_results = [
            Mock(public_ip="pub1"),
            Mock(public_ip="pub2")
        ]
        self.deploy_operation.instance_service.get_instance_by_id = Mock(
            return_value=instance)

        # act
        self.deploy_operation._rollback_deploy(
            ec2_session=self.ec2_session,
            instance_id=inst_id,
            custom_security_group=security_group,
            network_config_results=network_config_results,
            logger=self.logger,
        )

        # assert
        self.deploy_operation.instance_service.get_instance_by_id.assert_called_once_with(  # noqa
            ec2_session=self.ec2_session, id=inst_id)
        self.deploy_operation.instance_service.terminate_instance.assert_called_once_with(  # noqa
            instance=instance)
        self.deploy_operation.security_group_service.delete_security_group.assert_called_once_with(  # noqa
            security_group)
        self.deploy_operation.elastic_ip_service.find_and_release_elastic_address.assert_has_calls(  # noqa
            [
                call(ec2_session=self.ec2_session, elastic_ip="pub1"),
                call(ec2_session=self.ec2_session, elastic_ip="pub2"),
            ],
            any_order=True,
        )

    def test_extract_instance_id_on_cancellation(self):
        # prepare
        instance = Mock()
        instance_id = "some_id"
        cancellation_exception = CancellationException(
            "cancelled_test", {"instance_ids": [instance_id]})

        # act
        extracted_id = self.deploy_operation._extract_instance_id_on_cancellation(
            cancellation_exception, instance)

        # assert
        self.assertEquals(extracted_id, instance_id)

    def test_deploy(self):
        # prepare
        ami_datamodel = self._create_ami_datamodel()
        ami_deploy_action = self._create_ami_deploy_action(ami_datamodel)
        ami_deployment_info = Mock()
        instance = self._create_instance()
        network_config_results = [
            Mock(device_index=0, public_ip=instance.public_ip_address)
        ]
        self.instance_service.create_instance = Mock(return_value=instance)
        sg = Mock()
        self.security_group_service.create_security_group = Mock(
            return_value=sg)

        self._mock_deploy_operation(ami_deployment_info,
                                    network_config_results)

        cancellation_context = Mock()
        inst_name = "my name"
        reservation = Mock()
        network_actions = None

        # act

        res = self.deploy_operation.deploy(
            ec2_session=self.ec2_session,
            s3_session=self.s3_session,
            name=inst_name,
            reservation=reservation,
            aws_ec2_cp_resource_model=self.ec2_datamodel,
            ami_deploy_action=ami_deploy_action,
            network_actions=network_actions,
            ec2_client=self.ec2_client,
            cancellation_context=cancellation_context,
            logger=self.logger,
        )

        ami_credentials = self.credentials_manager.get_windows_credentials()

        # assert
        self.assertEqual(res[0].vmName, "my name")
        self.assertEqual(
            res[0].deployedAppAdditionalData["inbound_ports"],
            ami_datamodel.inbound_ports,
        )
        self.assertEqual(res[0].vmUuid, instance.instance_id)
        self.assertEqual(res[0].deployedAppAttributes[0].attributeName,
                         "Password")
        self.assertEqual(res[0].deployedAppAttributes[0].attributeValue,
                         ami_credentials.password)
        self.assertEqual(res[0].deployedAppAttributes[1].attributeName, "User")
        self.assertEqual(res[0].deployedAppAttributes[1].attributeValue,
                         ami_credentials.user_name)
        self.assertTrue(self.tag_service.get_security_group_tags.called)
        self.assertTrue(
            self.security_group_service.create_security_group.called)
        self.assertTrue(
            self.instance_service.set_ec2_resource_tags.called_with(
                self.security_group_service.create_security_group()),
            self.tag_service.get_security_group_tags(),
        )

        self.assertTrue(
            self.key_pair.load.called_with(
                self.ec2_datamodel.key_pair_location,
                instance.key_pair.key_name,
                self.key_pair.FILE_SYSTEM,
            ))

        self.assertTrue(
            self.security_group_service.set_security_group_rules.called_with(
                ami_datamodel,
                self.security_group_service.create_security_group()))

        self.security_group_service.remove_allow_all_outbound_rule.assert_called_with(
            security_group=sg)

        self.instance_service.create_instance.assert_called_once_with(
            ec2_session=self.ec2_session,
            name=inst_name,
            reservation=reservation,
            ami_deployment_info=ami_deployment_info,
            ec2_client=self.ec2_client,
            wait_for_status_check=ami_datamodel.wait_for_status_check,
            cancellation_context=cancellation_context,
            logger=self.logger,
        )

        self.deploy_operation.elastic_ip_service.set_elastic_ips.assert_called_once_with(  # noqa
            ec2_session=self.ec2_session,
            ec2_client=self.ec2_client,
            instance=instance,
            ami_deployment_model=ami_datamodel,
            network_actions=None,
            network_config_results=network_config_results,
            logger=self.logger,
        )

    def test_2ndGen_deployed_app_with_namespaced_user(self):
        # prepare
        ami_datamodel = self._create_ami_datamodel()
        ami_deploy_action = self._create_ami_deploy_action(ami_datamodel)
        ami_deployment_info = Mock()
        instance = self._create_instance()
        instance.platform = None
        network_config_results = [
            Mock(device_index=0, public_ip=instance.public_ip_address)
        ]
        self.instance_service.create_instance = Mock(return_value=instance)
        sg = Mock()
        self.security_group_service.create_security_group = Mock(
            return_value=sg)

        self._mock_deploy_operation(ami_deployment_info,
                                    network_config_results)

        cancellation_context = Mock()
        inst_name = "my name"
        reservation = Mock()
        network_actions = None

        # act

        res = self.deploy_operation.deploy(
            ec2_session=self.ec2_session,
            s3_session=self.s3_session,
            name=inst_name,
            reservation=reservation,
            aws_ec2_cp_resource_model=self.ec2_datamodel,
            ami_deploy_action=ami_deploy_action,
            network_actions=network_actions,
            ec2_client=self.ec2_client,
            cancellation_context=cancellation_context,
            logger=self.logger,
        )

        self.credentials_manager.get_windows_credentials()

        # assert
        self.assertEqual(res[0].vmName, "my name")
        self.assertEqual(
            res[0].deployedAppAdditionalData["inbound_ports"],
            ami_datamodel.inbound_ports,
        )
        self.assertEqual(res[0].vmUuid, instance.instance_id)
        self.assertTrue(self.tag_service.get_security_group_tags.called)
        self.assertTrue(
            self.security_group_service.create_security_group.called)
        self.assertTrue(
            self.instance_service.set_ec2_resource_tags.called_with(
                self.security_group_service.create_security_group()),
            self.tag_service.get_security_group_tags(),
        )

        self.assertTrue(
            self.key_pair.load.called_with(
                self.ec2_datamodel.key_pair_location,
                instance.key_pair.key_name,
                self.key_pair.FILE_SYSTEM,
            ))

        self.assertTrue(
            self.security_group_service.set_security_group_rules.called_with(
                ami_datamodel,
                self.security_group_service.create_security_group()))

        self.security_group_service.remove_allow_all_outbound_rule.assert_called_with(
            security_group=sg)

        self.instance_service.create_instance.assert_called_once_with(
            ec2_session=self.ec2_session,
            name=inst_name,
            reservation=reservation,
            ami_deployment_info=ami_deployment_info,
            ec2_client=self.ec2_client,
            wait_for_status_check=ami_datamodel.wait_for_status_check,
            cancellation_context=cancellation_context,
            logger=self.logger,
        )

        self.deploy_operation.elastic_ip_service.set_elastic_ips.assert_called_once_with(  # noqa
            ec2_session=self.ec2_session,
            ec2_client=self.ec2_client,
            instance=instance,
            ami_deployment_model=ami_datamodel,
            network_actions=None,
            network_config_results=network_config_results,
            logger=self.logger,
        )

    def _mock_deploy_operation(self, ami_deployment_info,
                               network_config_results):
        self.deploy_operation._get_block_device_mappings = Mock()
        self.deploy_operation._create_deployment_parameters = Mock(
            return_value=ami_deployment_info)
        self.deploy_operation._populate_network_config_results_with_interface_data = (
            Mock())
        self.deploy_operation._prepare_network_result_models = Mock(
            return_value=network_config_results)
        self.deploy_operation._prepare_network_config_results_dto = Mock(
            return_value=[])

    def _create_instance(self):
        instance = Mock()
        instance.network_interfaces = []
        instance.tags = [{"Key": "Name", "Value": "my name"}]
        return instance

    def _create_ami_deploy_action(self, ami_datamodel):
        ami_deploy_action = Mock()
        ami_deploy_action.actionParms = Mock()
        ami_deploy_action.actionParams.deployment = Mock()
        ami_deploy_action.actionParams.deployment.customModel = ami_datamodel
        ami_deploy_action.actionParams.appResource.attributes = {
            "gen2.User": "******"
        }
        return ami_deploy_action

    def _create_ami_datamodel(self):
        ami_datamodel = Mock()
        ami_datamodel.storage_size = 30
        ami_datamodel.inbound_ports = "80"
        ami_datamodel.outbound_ports = "20"
        ami_datamodel.add_public_ip = None
        ami_datamodel.allocate_elastic_ip = True
        return ami_datamodel

    def test_get_block_device_mappings_throws_max_storage_error(self):
        ec_model = Mock()
        ec_model.max_storage_size = 30
        ec_model.max_storage_iops = 0

        ami = Mock()
        ami.root_volume_name = "name"
        ami.storage_size = 50
        ami.storage_iops = 0
        ami.storage_type = ""

        image = Mock()
        image.root_device_name = "/sda"
        root_device = {"DeviceName": image.root_device_name, "Ebs": {}}
        image.block_device_mappings = [root_device]

        with self.assertRaisesRegexp(
                ValueError,
                "Requested storage size is bigger than the max allowed storage size of 30",
        ):
            self.deploy_operation._get_block_device_mappings(
                image=image,
                ami_deployment_model=ami,
                aws_ec2_resource_model=ec_model)

    def test_get_block_device_mappings_throws_max_iops_error(self):
        ec_model = Mock()
        ec_model.max_storage_size = 30
        ec_model.max_storage_iops = 100

        ami = Mock()
        ami.root_volume_name = "name"
        ami.storage_size = 30
        ami.storage_iops = 200
        ami.storage_type = "io1"

        image = Mock()
        image.root_device_name = "/sda"
        root_device = {"DeviceName": image.root_device_name, "Ebs": {}}
        image.block_device_mappings = [root_device]

        with self.assertRaisesRegexp(
                ValueError,
                "Requested storage IOPS is bigger than the max allowed storage IOPS of 100",
        ):
            self.deploy_operation._get_block_device_mappings(
                image=image,
                ami_deployment_model=ami,
                aws_ec2_resource_model=ec_model)

    def test_get_block_device_mappings_from_image(self):
        ec_model = Mock()
        ec_model.max_storage_size = 0
        ec_model.max_storage_iops = 0

        ami = Mock()
        ami.root_volume_name = "name"
        ami.storage_size = 0
        ami.storage_iops = 0
        ami.storage_type = "auto"

        image = Mock()
        image.root_device_name = "/sda"
        root_device = {
            "DeviceName": image.root_device_name,
            "Ebs": {
                "VolumeSize": "40",
                "VolumeType": "io1",
                "Iops": "240",
            },
        }
        image.block_device_mappings = [root_device]

        res = self.deploy_operation._get_block_device_mappings(
            image=image,
            ami_deployment_model=ami,
            aws_ec2_resource_model=ec_model)

        self.assertEqual(res[0]["DeviceName"], ami.root_volume_name)
        self.assertEqual(str(res[0]["Ebs"]["VolumeSize"]), str(40))
        self.assertEqual(res[0]["Ebs"]["DeleteOnTermination"], True)
        self.assertEqual(res[0]["Ebs"]["VolumeType"], "io1")
        self.assertEqual(res[0]["Ebs"]["Iops"], 240)

    def test_get_block_device_mappings_from_app(self):
        ec_model = Mock()
        ec_model.max_storage_size = 0
        ec_model.max_storage_iops = 0

        ami = Mock()
        ami.root_volume_name = "name"
        ami.storage_size = 30
        ami.storage_type = "standart"

        image = Mock()
        image.root_device_name = "/sda"
        root_device = {"DeviceName": image.root_device_name, "Ebs": {}}
        image.block_device_mappings = [root_device]

        res = self.deploy_operation._get_block_device_mappings(
            image=image,
            ami_deployment_model=ami,
            aws_ec2_resource_model=ec_model)

        self.assertEqual(res[0]["DeviceName"], ami.root_volume_name)
        self.assertEqual(str(res[0]["Ebs"]["VolumeSize"]), str(30))
        self.assertEqual(res[0]["Ebs"]["DeleteOnTermination"], True)
        self.assertEqual(res[0]["Ebs"]["VolumeType"], "standart")
        self.assertFalse("Iops" in res[0]["Ebs"])

    def test_get_block_device_mappings_from_app_with_iops(self):
        ec_model = Mock()
        ec_model.max_storage_size = 0
        ec_model.max_storage_iops = 0

        ami = Mock()
        ami.root_volume_name = "name"
        ami.storage_size = 30
        ami.storage_iops = 300
        ami.storage_type = "io1"

        image = Mock()
        image.root_device_name = "/sda"
        root_device = {"DeviceName": image.root_device_name, "Ebs": {}}
        image.block_device_mappings = [root_device]

        res = self.deploy_operation._get_block_device_mappings(
            image=image,
            ami_deployment_model=ami,
            aws_ec2_resource_model=ec_model)

        self.assertEqual(res[0]["DeviceName"], ami.root_volume_name)
        self.assertEqual(str(res[0]["Ebs"]["VolumeSize"]), str(30))
        self.assertEqual(res[0]["Ebs"]["DeleteOnTermination"], True)
        self.assertEqual(res[0]["Ebs"]["VolumeType"], "io1")
        self.assertEqual(res[0]["Ebs"]["Iops"], 300)

    def test_create_deployment_parameters_no_ami_id(self):
        ami = Mock()
        network_actions = MagicMock()
        ami.aws_ami_id = None
        self.assertRaises(
            ValueError,
            self.deploy_operation._create_deployment_parameters,
            ec2_session=Mock(),
            aws_ec2_resource_model=self.ec2_datamodel,
            ami_deployment_model=ami,
            network_actions=network_actions,
            vpc=Mock(),
            security_group=None,
            key_pair="keypair",
            reservation=Mock(),
            network_config_results=Mock(),
            logger=self.logger,
        )

    def test_create_deployment_parameters_single_subnet(self):
        image = Mock()
        image.state = "available"
        ec2_session = Mock()
        ec2_session.Image = Mock(return_value=image)
        ami_model = Mock()
        ami_model.aws_ami_id = "asd"
        ami_model.storage_size = "0"
        ami_model.iam_role = ""
        ami_model.custom_tags = ""

        network_actions = None
        vpc = Mock()
        self.deploy_operation._get_block_device_mappings = Mock()

        aws_model = self.deploy_operation._create_deployment_parameters(
            ec2_session=ec2_session,
            aws_ec2_resource_model=self.ec2_datamodel,
            ami_deployment_model=ami_model,
            network_actions=network_actions,
            vpc=vpc,
            security_group=None,
            key_pair="keypair",
            reservation=Mock(),
            network_config_results=MagicMock(),
            logger=self.logger,
        )

        self.assertEquals(aws_model.min_count, 1)
        self.assertEquals(aws_model.max_count, 1)
        self.assertEquals(aws_model.aws_key, "keypair")
        self.assertTrue(len(aws_model.security_group_ids) == 1)
        self.assertTrue(len(aws_model.network_interfaces) == 1)

    def test_create_deployment_parameters_no_iam_role(self):
        image = Mock()
        image.state = "available"
        ec2_session = Mock()
        ec2_session.Image = Mock(return_value=image)
        ami_model = Mock()
        ami_model.iam_role = ""
        ami_model.custom_tags = ""
        network_actions = None
        vpc = Mock()
        self.deploy_operation._get_block_device_mappings = Mock()

        aws_model = self.deploy_operation._create_deployment_parameters(
            ec2_session=ec2_session,
            aws_ec2_resource_model=self.ec2_datamodel,
            ami_deployment_model=ami_model,
            network_actions=network_actions,
            vpc=vpc,
            security_group=None,
            key_pair="keypair",
            reservation=Mock(),
            network_config_results=MagicMock(),
            logger=self.logger,
        )

        # if instance doesnt have iam role, the deployment params will have an empty
        # iam instance profile dict
        self.assertTrue(not any(
            aws_model.iam_role))  # not any(some_dict) => is empty dictionary

    def test_create_deployment_parameters_iam_role_not_arn(self):
        image = Mock()
        image.state = "available"
        ec2_session = Mock()
        ec2_session.Image = Mock(return_value=image)
        ami_model = Mock()
        ami_model.iam_role = "admin_role"
        ami_model.custom_tags = ""

        vpc = Mock()
        self.deploy_operation._get_block_device_mappings = Mock()
        network_actions = None

        aws_model = self.deploy_operation._create_deployment_parameters(
            ec2_session=ec2_session,
            aws_ec2_resource_model=self.ec2_datamodel,
            ami_deployment_model=ami_model,
            network_actions=network_actions,
            vpc=vpc,
            security_group=None,
            key_pair="keypair",
            reservation=Mock(),
            network_config_results=MagicMock(),
            logger=self.logger,
        )

        # if instance has iam role, but not in the form of arn, will return dict with
        # iam role name
        self.assertTrue(aws_model.iam_role["Name"] == ami_model.iam_role)

    def test_create_deployment_parameters_iam_role_arn(self):
        image = Mock()
        image.state = "available"
        ec2_session = Mock()
        ec2_session.Image = Mock(return_value=image)
        ami_model = Mock()
        network_actions = None
        ami_model.iam_role = "arn:aws:iam::admin_role"
        ami_model.custom_tags = ""
        vpc = Mock()
        self.deploy_operation._get_block_device_mappings = Mock()

        aws_model = self.deploy_operation._create_deployment_parameters(
            ec2_session=ec2_session,
            aws_ec2_resource_model=self.ec2_datamodel,
            ami_deployment_model=ami_model,
            network_actions=network_actions,
            vpc=vpc,
            security_group=None,
            key_pair="keypair",
            reservation=Mock(),
            network_config_results=MagicMock(),
            logger=self.logger,
        )

        # if instance has iam role, but not in the form of arn, will return dict with
        # iam role name
        self.assertTrue(aws_model.iam_role["Arn"] == ami_model.iam_role)

    @pytest.mark.skip(reason="skip for now")
    def test_prepare_network_interfaces_multi_subnets_with_public_ip(self):
        ami_model = Mock()
        ami_model.add_public_ip = True
        ami_model.network_configurations = [Mock(), Mock()]

        network_actions = [Mock(spec=ConnectSubnet), Mock(spec=ConnectSubnet)]

        with self.assertRaisesRegexp(
                ValueError,
                "Public IP option is not supported with multiple subnets"):
            self.deploy_operation._prepare_network_interfaces(
                ami_deployment_model=ami_model,
                network_actions=network_actions,
                vpc=Mock(),
                security_group_ids=MagicMock(),
                network_config_results=MagicMock(),
                logger=self.logger,
            )

    @pytest.mark.skip(reason="skip for now")
    def test_prepare_network_interfaces_multi_subnets(self):
        def build_network_interface_handler(*args, **kwargs):
            return {"SubnetId": kwargs["subnet_id"]}

        # arrange
        vpc = Mock()
        security_group_ids = MagicMock()

        action1 = ConnectSubnet()
        action1.actionId = "action1"
        action1.actionParams = ConnectToSubnetParams()
        action1.actionParams.subnetId = "sub1"
        action1.actionParams.vnicName = 0
        action1.actionParams.isPublic = True

        action2 = ConnectSubnet()
        action2.actionId = "action2"
        action2.actionParams = ConnectToSubnetParams()
        action2.actionParams.subnetId = "sub2"
        action2.actionParams.vnicName = 1

        ami_model = Mock()
        network_actions = [action1, action2]
        ami_model.add_public_ip = False

        res_model_1 = DeployNetworkingResultModel("action1")
        res_model_2 = DeployNetworkingResultModel("action2")
        network_config_results = [res_model_1, res_model_2]

        self.deploy_operation.network_interface_service.build_network_interface_dto = (
            Mock(side_effect=build_network_interface_handler))

        # act
        net_interfaces = self.deploy_operation._prepare_network_interfaces(
            ami_deployment_model=ami_model,
            network_actions=network_actions,
            vpc=vpc,
            security_group_ids=security_group_ids,
            network_config_results=network_config_results,
            logger=self.logger,
        )

        # assert
        self.assertEquals(res_model_1.device_index, 0)
        self.assertEquals(res_model_2.device_index, 1)
        self.assertEquals(len(net_interfaces), 2)
        self.assertEquals(net_interfaces[0]["SubnetId"], "sub1")
        self.assertEquals(net_interfaces[1]["SubnetId"], "sub2")

    def test_prepare_network_config_results_dto_returns_empty_array_when_no_network_config(  # noqa
            self, ):
        # arrange
        network_actions = None

        # act
        dtos = self.deploy_operation._prepare_network_config_results_dto(
            Mock(), network_actions)

        # assert
        self.assertTrue(isinstance(dtos, list))
        self.assertFalse(dtos)

    def test_prepare_network_config_results_dto(self):
        # arrange
        model1 = DeployNetworkingResultModel(action_id="aaa")
        model1.device_index = 0
        model1.interface_id = "interface1"
        model1.mac_address = "mac1"
        model1.private_ip = "priv1"
        model1.public_ip = "pub1"

        model2 = DeployNetworkingResultModel(action_id="bbb")
        model2.device_index = 1
        model2.interface_id = "interface2"
        model2.mac_address = "mac2"
        model2.private_ip = "priv2"
        model2.public_ip = "pub2"

        models = [model1, model2]

        network_actions = Mock()
        # act
        dtos = self.deploy_operation._prepare_network_config_results_dto(
            models, network_actions)

        self.assertEquals(len(dtos), 2)
        dto1 = dtos[0]
        dto2 = dtos[1]
        self.assertEquals(dto1.actionId, "aaa")
        self.assertEquals(dto2.actionId, "bbb")
        self.assertTrue(dto1.success)
        self.assertTrue(dto2.success)
        self.assertEquals(dto1.type, "ConnectToSubnet")
        self.assertEquals(dto2.type, "ConnectToSubnet")
        self.assertTrue('"interface_id": "interface1"' in dto1.interface)
        self.assertTrue('"Device Index": 0' in dto1.interface)
        self.assertTrue('"IP": "priv1"' in dto1.interface)
        self.assertTrue('"Public IP": "pub1"' in dto1.interface)
        self.assertTrue('"MAC Address": "mac1"' in dto1.interface)

    @pytest.mark.skip(reason="skip for now")
    def test_deploy_raised_no_vpc(self):
        # arrange
        my_vpc_service = Mock()
        my_vpc_service.find_vpc_for_reservation = Mock(return_value=None)
        deploy_operation = DeployAMIOperation(
            self.instance_service,
            self.credentials_manager,
            self.security_group_service,
            self.tag_service,
            my_vpc_service,
            self.key_pair,
            self.subnet_service,
            self.elastic_ip_service,
            self.network_interface_service,
            self.cancellation_service,
            self.device_index_strategy,
            self.vm_details_provider,
        )

        # act & assert
        with self.assertRaisesRegexp(ValueError,
                                     "VPC is not set for this reservation"):
            deploy_operation.deploy(
                ec2_session=Mock(),
                s3_session=Mock(),
                name=Mock(),
                reservation=Mock(),
                aws_ec2_cp_resource_model=Mock(),
                ami_deploy_action=Mock(),
                network_actions=Mock(),
                ec2_client=Mock(),
                cancellation_context=Mock(),
                logger=self.logger,
            )

    def test__prepare_network_result_models_returns_empty_model_when_no_network_config(
        self, ):
        # arrange
        network_actions = None

        # act
        models = self.deploy_operation._prepare_network_result_models(
            network_actions)

        # assert
        self.assertEquals(len(models), 1)
        self.assertEquals(models[0].action_id, "")
        self.assertTrue(isinstance(models[0], DeployNetworkingResultModel))

    def test__prepare_network_result_models_returns_result_model_per_action(
            self):
        # arrange
        action1 = Mock(spec=PrepareCloudInfra, actionId=Mock(spec=str))
        action1.actionParams = Mock(spec=ConnectToSubnetParams)

        action2 = Mock(spec=PrepareCloudInfra, actionId=Mock(spec=str))
        action2.actionParams = Mock(spec=ConnectToSubnetParams)

        network_actions = [action1, action2]

        # act
        models = self.deploy_operation._prepare_network_result_models(
            network_actions)

        # assert
        self.assertEquals(len(models), 2)
        self.assertTrue(isinstance(models[0], DeployNetworkingResultModel))
        self.assertTrue(isinstance(models[1], DeployNetworkingResultModel))
        self.assertEquals(models[0].action_id, action1.actionId)
        self.assertEquals(models[1].action_id, action2.actionId)

    def test_populate_network_config_results_with_interface_data(self):
        # arrange
        instance = Mock()
        instance.network_interfaces_attribute = [
            {
                "Attachment": {
                    "DeviceIndex": 0
                },
                "NetworkInterfaceId": "int1",
                "PrivateIpAddress": "pri_ip_1",
                "MacAddress": "mac1",
                "Association": {
                    "PublicIp": "pub_ip_1"
                },
            },
            {
                "Attachment": {
                    "DeviceIndex": 1
                },
                "NetworkInterfaceId": "int2",
                "PrivateIpAddress": "pri_ip_2",
                "MacAddress": "mac2",
            },
        ]
        network_config_results = [
            DeployNetworkingResultModel("action1"),
            DeployNetworkingResultModel("action2"),
        ]
        network_config_results[0].device_index = 0
        network_config_results[1].device_index = 1

        # act
        self.deploy_operation._populate_network_config_results_with_interface_data(
            instance=instance, network_config_results=network_config_results)

        # assert
        self.assertEquals(network_config_results[0].interface_id, "int1")
        self.assertEquals(network_config_results[0].private_ip, "pri_ip_1")
        self.assertEquals(network_config_results[0].mac_address, "mac1")
        self.assertEquals(network_config_results[0].public_ip, "pub_ip_1")

        self.assertEquals(network_config_results[1].interface_id, "int2")
        self.assertEquals(network_config_results[1].private_ip, "pri_ip_2")
        self.assertEquals(network_config_results[1].mac_address, "mac2")
        self.assertEquals(network_config_results[1].public_ip, "")
Ejemplo n.º 11
0
class AWSShell(object):
    def __init__(self):
        tag_creator_service = TagCreatorService()
        self.aws_api = AWSApi(tag_creator_service)
        self.ec2_instance_waiter = EC2InstanceWaiter()
        self.ec2_storage_service = EC2StorageService()
        self.model_parser = AWSModelsParser()
        self.cloudshell_session_helper = CloudshellDriverHelper()
        self.aws_session_manager = AWSSessionProvider()

        self.security_group_service = AWSSecurityGroupService()

        self.deploy_ami_operation = DeployAMIOperation(
            aws_api=self.aws_api,
            security_group_service=self.security_group_service,
            tag_creator_service=tag_creator_service)

        self.power_management_operation = PowerOperation(
            aws_api=self.aws_api, instance_waiter=self.ec2_instance_waiter)

        self.delete_ami_operation = DeleteAMIOperation(
            ec2_api=self.aws_api,
            instance_waiter=self.ec2_instance_waiter,
            ec2_storage_service=self.ec2_storage_service,
            security_group_service=self.security_group_service)

    def deploy_ami(self, command_context, deployment_request):
        """
        Will deploy Amazon Image on the cloud provider
        """
        aws_ami_deployment_model, name = self.model_parser.convert_to_deployment_resource_model(
            deployment_request)
        aws_ec2_resource_model = self.model_parser.convert_to_aws_resource_model(
            command_context.resource)
        cloudshell_session = self.cloudshell_session_helper.get_session(
            command_context.connectivity.server_address,
            command_context.connectivity.admin_auth_token,
            command_context.reservation.domain)
        ec2_session = self.aws_session_manager.get_ec2_session(
            cloudshell_session, aws_ec2_resource_model)
        reservation_id = command_context.reservation.reservation_id

        deploy_data = self.deploy_ami_operation.deploy(
            ec2_session=ec2_session,
            name=name,
            reservation_id=reservation_id,
            aws_ec2_cp_resource_model=aws_ec2_resource_model,
            ami_deployment_model=aws_ami_deployment_model)

        return self._set_command_result(deploy_data)

    def power_on_ami(self, command_context):
        """
        Will power on the ami
        :param command_context: RemoteCommandContext
        :return:
        """
        aws_ec2_resource_model = self.model_parser.convert_to_aws_resource_model(
            command_context.resource)
        cloudshell_session = self.cloudshell_session_helper.get_session(
            command_context.connectivity.server_address,
            command_context.connectivity.admin_auth_token,
            command_context.remote_reservation.domain)
        ec2_session = self.aws_session_manager.get_ec2_session(
            cloudshell_session, aws_ec2_resource_model)

        resource = command_context.remote_endpoints[0]
        data_holder = self.model_parser.convert_app_resource_to_deployed_app(
            resource)
        result = self.power_management_operation.power_on(
            ec2_session, data_holder.vmdetails.uid)
        cloudshell_session.SetResourceLiveStatus(resource.fullname, "Online",
                                                 "Active")
        return self._set_command_result(result)

    def power_off_ami(self, command_context):
        """
        Will power on the ami
        :param command_context: RemoteCommandContext
        :return:
        """
        aws_ec2_resource_model = self.model_parser.convert_to_aws_resource_model(
            command_context.resource)
        cloudshell_session = self.cloudshell_session_helper.get_session(
            command_context.connectivity.server_address,
            command_context.connectivity.admin_auth_token,
            command_context.remote_reservation.domain)
        ec2_session = self.aws_session_manager.get_ec2_session(
            cloudshell_session, aws_ec2_resource_model)

        resource = command_context.remote_endpoints[0]
        data_holder = self.model_parser.convert_app_resource_to_deployed_app(
            resource)
        result = self.power_management_operation.power_off(
            ec2_session, data_holder.vmdetails.uid)
        cloudshell_session.SetResourceLiveStatus(resource.fullname, "Offline",
                                                 "Powered Off")
        return self._set_command_result(result)

    def delete_ami(self, command_context, delete_resource=True):
        """
        Will delete the ami instance
        :param bool delete_resource:
        :param command_context: RemoteCommandContext
        :return:
        """
        aws_ec2_resource_model = self.model_parser.convert_to_aws_resource_model(
            command_context.resource)
        cloudshell_session = self.cloudshell_session_helper.get_session(
            command_context.connectivity.server_address,
            command_context.connectivity.admin_auth_token,
            command_context.remote_reservation.domain)
        ec2_session = self.aws_session_manager.get_ec2_session(
            cloudshell_session, aws_ec2_resource_model)

        resource = command_context.remote_endpoints[0]
        data_holder = self.model_parser.convert_app_resource_to_deployed_app(
            resource)
        result = self.delete_ami_operation.delete_instance(
            ec2_session, data_holder.vmdetails.uid)

        # todo this is temporary for the demo
        if delete_resource:
            cloudshell_session.DeleteResource(
                resourceFullPath=resource.fullname)

        return self._set_command_result(result)

    @staticmethod
    def _set_command_result(result, unpicklable=False):
        """
        Serializes output as JSON and writes it to console output wrapped with special prefix and suffix
        :param result: Result to return
        :param unpicklable: If True adds JSON can be deserialized as real object.
                            When False will be deserialized as dictionary
        """
        json = jsonpickle.encode(result, unpicklable=unpicklable)
        result_for_output = str(json)
        return result_for_output
Ejemplo n.º 12
0
class AWSShell(object):
    def __init__(self):
        tag_creator_service = TagCreatorService()
        self.aws_api = AWSApi(tag_creator_service)
        self.ec2_instance_waiter = EC2InstanceWaiter()
        self.ec2_storage_service = EC2StorageService()
        self.model_parser = AWSModelsParser()
        self.cloudshell_session_helper = CloudshellDriverHelper()
        self.aws_session_manager = AWSSessionProvider()

        self.security_group_service = AWSSecurityGroupService()

        self.deploy_ami_operation = DeployAMIOperation(aws_api=self.aws_api,
                                                       security_group_service=self.security_group_service,
                                                       tag_creator_service=tag_creator_service)

        self.power_management_operation = PowerOperation(aws_api=self.aws_api,
                                                         instance_waiter=self.ec2_instance_waiter)

        self.delete_ami_operation = DeleteAMIOperation(ec2_api=self.aws_api,
                                                       instance_waiter=self.ec2_instance_waiter,
                                                       ec2_storage_service=self.ec2_storage_service,
                                                       security_group_service=self.security_group_service)

    def deploy_ami(self, command_context, deployment_request):
        """
        Will deploy Amazon Image on the cloud provider
        """
        aws_ami_deployment_model, name = self.model_parser.convert_to_deployment_resource_model(deployment_request)
        aws_ec2_resource_model = self.model_parser.convert_to_aws_resource_model(command_context.resource)
        cloudshell_session = self.cloudshell_session_helper.get_session(command_context.connectivity.server_address,
                                                                        command_context.connectivity.admin_auth_token,
                                                                        command_context.reservation.domain)
        ec2_session = self.aws_session_manager.get_ec2_session(cloudshell_session, aws_ec2_resource_model)
        reservation_id = command_context.reservation.reservation_id

        deploy_data = self.deploy_ami_operation.deploy(ec2_session=ec2_session,
                                                       name=name,
                                                       reservation_id=reservation_id,
                                                       aws_ec2_cp_resource_model=aws_ec2_resource_model,
                                                       ami_deployment_model=aws_ami_deployment_model)

        return self._set_command_result(deploy_data)

    def power_on_ami(self, command_context):
        """
        Will power on the ami
        :param command_context: RemoteCommandContext
        :return:
        """
        aws_ec2_resource_model = self.model_parser.convert_to_aws_resource_model(command_context.resource)
        cloudshell_session = self.cloudshell_session_helper.get_session(command_context.connectivity.server_address,
                                                                        command_context.connectivity.admin_auth_token,
                                                                        command_context.remote_reservation.domain)
        ec2_session = self.aws_session_manager.get_ec2_session(cloudshell_session, aws_ec2_resource_model)

        resource = command_context.remote_endpoints[0]
        data_holder = self.model_parser.convert_app_resource_to_deployed_app(resource)
        result = self.power_management_operation.power_on(ec2_session, data_holder.vmdetails.uid)
        cloudshell_session.SetResourceLiveStatus(resource.fullname, "Online", "Active")
        return self._set_command_result(result)

    def power_off_ami(self, command_context):
        """
        Will power on the ami
        :param command_context: RemoteCommandContext
        :return:
        """
        aws_ec2_resource_model = self.model_parser.convert_to_aws_resource_model(command_context.resource)
        cloudshell_session = self.cloudshell_session_helper.get_session(command_context.connectivity.server_address,
                                                                        command_context.connectivity.admin_auth_token,
                                                                        command_context.remote_reservation.domain)
        ec2_session = self.aws_session_manager.get_ec2_session(cloudshell_session, aws_ec2_resource_model)

        resource = command_context.remote_endpoints[0]
        data_holder = self.model_parser.convert_app_resource_to_deployed_app(resource)
        result = self.power_management_operation.power_off(ec2_session, data_holder.vmdetails.uid)
        cloudshell_session.SetResourceLiveStatus(resource.fullname, "Offline", "Powered Off")
        return self._set_command_result(result)

    def delete_ami(self, command_context, delete_resource=True):
        """
        Will delete the ami instance
        :param bool delete_resource:
        :param command_context: RemoteCommandContext
        :return:
        """
        aws_ec2_resource_model = self.model_parser.convert_to_aws_resource_model(command_context.resource)
        cloudshell_session = self.cloudshell_session_helper.get_session(command_context.connectivity.server_address,
                                                                        command_context.connectivity.admin_auth_token,
                                                                        command_context.remote_reservation.domain)
        ec2_session = self.aws_session_manager.get_ec2_session(cloudshell_session, aws_ec2_resource_model)

        resource = command_context.remote_endpoints[0]
        data_holder = self.model_parser.convert_app_resource_to_deployed_app(resource)
        result = self.delete_ami_operation.delete_instance(ec2_session, data_holder.vmdetails.uid)

        # todo this is temporary for the demo
        if delete_resource:
            cloudshell_session.DeleteResource(resourceFullPath=resource.fullname)

        return self._set_command_result(result)

    @staticmethod
    def _set_command_result(result, unpicklable=False):
        """
        Serializes output as JSON and writes it to console output wrapped with special prefix and suffix
        :param result: Result to return
        :param unpicklable: If True adds JSON can be deserialized as real object.
                            When False will be deserialized as dictionary
        """
        json = jsonpickle.encode(result, unpicklable=unpicklable)
        result_for_output = str(json)
        return result_for_output