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, )
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)
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 __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 __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, )
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, "")
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, "")
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
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