def delete_integration( self, context: RequestContext, rest_api_id: String, resource_id: String, http_method: String ) -> None: try: call_moto(context) except Exception as e: raise NotFoundException("Invalid Resource identifier specified") from e
def test_call_with_sqs_creates_state_correctly(): qname = f"queue-{short_uid()}" response = moto.call_moto( moto.create_aws_request_context("sqs", "CreateQueue", {"QueueName": qname}), include_response_metadata=True, ) url = response["QueueUrl"] try: assert response["ResponseMetadata"]["HTTPStatusCode"] == 200 assert response["QueueUrl"].endswith(f"/{qname}") response = moto.call_moto( moto.create_aws_request_context("sqs", "ListQueues")) assert url in response["QueueUrls"] finally: moto.call_moto( moto.create_aws_request_context("sqs", "DeleteQueue", {"QueueUrl": url})) response = moto.call_moto( moto.create_aws_request_context("sqs", "ListQueues")) assert url not in response.get("QueueUrls", [])
def test_call_with_es_creates_state_correctly(): domain_name = f"domain-{short_uid()}" response = moto.call_moto( moto.create_aws_request_context( "es", "CreateElasticsearchDomain", { "DomainName": domain_name, "ElasticsearchVersion": "7.10", }, ), include_response_metadata=True, ) try: assert response["ResponseMetadata"]["HTTPStatusCode"] == 200 assert response["DomainStatus"]["DomainName"] == domain_name assert response["DomainStatus"]["ElasticsearchVersion"] == "7.10" finally: response = moto.call_moto( moto.create_aws_request_context("es", "DeleteElasticsearchDomain", {"DomainName": domain_name}), include_response_metadata=True, ) assert response["ResponseMetadata"]["HTTPStatusCode"] == 200
def test_call_include_response_metadata(): ctx = moto.create_aws_request_context("sqs", "ListQueues") response = moto.call_moto(ctx) assert "ResponseMetadata" not in response response = moto.call_moto(ctx, include_response_metadata=True) assert "ResponseMetadata" in response
def disable_rule( self, context: RequestContext, name: RuleName, event_bus_name: EventBusNameOrArn = None ) -> None: rule_scheduled_jobs = EventsBackend.get().rule_scheduled_jobs job_id = rule_scheduled_jobs.get(name) if job_id: LOG.debug("Disabling Rule: {} | job_id: {}".format(name, job_id)) JobScheduler.instance().disable_job(job_id=job_id) call_moto(context)
def put_metric_alarm( self, context: RequestContext, request: PutMetricAlarmInput, ) -> None: moto.call_moto(context) name = request.get("AlarmName") arn = aws_stack.cloudwatch_alarm_arn(name) self.tags.tag_resource(arn, request.get("Tags"))
def test_call_sqs_invalid_call_raises_http_exception(): with pytest.raises(ServiceException) as e: moto.call_moto( moto.create_aws_request_context( "sqs", "DeleteQueue", { "QueueUrl": "http://0.0.0.0/nonexistingqueue", }, )) e.match("The specified queue does not exist")
def delete_rest_api(self, context: RequestContext, rest_api_id: String) -> None: try: call_moto(context) except KeyError as e: # moto raises a key error if we're trying to delete an API that doesn't exist raise NotFoundException( f"Invalid API identifier specified {context.account_id}:{rest_api_id}" ) from e event_publisher.fire_event( event_publisher.EVENT_APIGW_DELETE_API, payload={"a": event_publisher.get_hash(rest_api_id)}, )
def delete_rule( self, context: RequestContext, name: RuleName, event_bus_name: EventBusNameOrArn = None, force: Boolean = None, ) -> None: rule_scheduled_jobs = EventsBackend.get().rule_scheduled_jobs job_id = rule_scheduled_jobs.get(name) if job_id: LOG.debug("Removing scheduled Events: {} | job_id: {}".format(name, job_id)) JobScheduler.instance().cancel_job(job_id=job_id) call_moto(context)
def test_call_with_sqs_modifies_state_in_moto_backend(): """Whitebox test to check that moto backends are populated correctly""" from moto.sqs.models import sqs_backends qname = f"queue-{short_uid()}" response = moto.call_moto( moto.create_aws_request_context("sqs", "CreateQueue", {"QueueName": qname})) url = response["QueueUrl"] assert qname in sqs_backends.get(config.AWS_REGION_US_EAST_1).queues moto.call_moto( moto.create_aws_request_context("sqs", "DeleteQueue", {"QueueUrl": url})) assert qname not in sqs_backends.get(config.AWS_REGION_US_EAST_1).queues
def test_request_with_response_header_location_fields(): # CreateHostedZoneResponse has a member "Location" that's located in the headers zone_name = f"zone-{short_uid()}.com" request = moto.create_aws_request_context("route53", "CreateHostedZone", { "Name": zone_name, "CallerReference": "test" }) response = moto.call_moto(request, include_response_metadata=True) # assert response["Location"] # FIXME: this is required according to the spec, but not returned by moto assert response["HostedZone"]["Id"] # clean up moto.call_moto( moto.create_aws_request_context("route53", "DeleteHostedZone", {"Id": response["HostedZone"]["Id"]}))
def create_connection( self, context: RequestContext, name: ConnectionName, authorization_type: ConnectionAuthorizationType, auth_parameters: CreateConnectionAuthRequestParameters, description: ConnectionDescription = None, ): errors = [] if not CONNECTION_NAME_PATTERN.match(name): error = f"{name} at 'name' failed to satisfy: Member must satisfy regular expression pattern: [\\.\\-_A-Za-z0-9]+" errors.append(error) if len(name) > 64: error = f"{name} at 'name' failed to satisfy: Member must have length less than or equal to 64" errors.append(error) if authorization_type not in ["BASIC", "API_KEY", "OAUTH_CLIENT_CREDENTIALS"]: error = f"{authorization_type} at 'authorizationType' failed to satisfy: Member must satisfy enum value set: [BASIC, OAUTH_CLIENT_CREDENTIALS, API_KEY]" errors.append(error) if len(errors) > 0: error_description = "; ".join(errors) error_plural = "errors" if len(errors) > 1 else "error" errors_amount = len(errors) message = f"{errors_amount} validation {error_plural} detected: {error_description}" raise CommonServiceException(message=message, code="ValidationException") return call_moto(context)
def send_templated_email( self, context: RequestContext, source: Address, destination: Destination, template: TemplateName, template_data: TemplateData, reply_to_addresses: AddressList = None, return_path: Address = None, source_arn: AmazonResourceName = None, return_path_arn: AmazonResourceName = None, tags: MessageTagList = None, configuration_set_name: ConfigurationSetName = None, template_arn: AmazonResourceName = None, ) -> SendTemplatedEmailResponse: response = call_moto(context) save_for_retrospection( response["MessageId"], context.region, Source=source, Template=template, TemplateData=template_data, Destination=destination, ) return response
def send_email( self, context: RequestContext, source: Address, destination: Destination, message: Message, reply_to_addresses: AddressList = None, return_path: Address = None, source_arn: AmazonResourceName = None, return_path_arn: AmazonResourceName = None, tags: MessageTagList = None, configuration_set_name: ConfigurationSetName = None, ) -> SendEmailResponse: response = call_moto(context) save_for_retrospection( response["MessageId"], context.region, Source=source, Destination=destination, Subject=message["Subject"].get("Data"), Body=message["Body"].get("Text", {}).get("Data"), ) return response
def put_log_events( self, context: RequestContext, log_group_name: LogGroupName, log_stream_name: LogStreamName, log_events: InputLogEvents, sequence_token: SequenceToken = None, ) -> PutLogEventsResponse: logs_backend = logs_backends[aws_stack.get_region()] metric_filters = logs_backend.filters.metric_filters for metric_filter in metric_filters: pattern = metric_filter.get("filterPattern", "") transformations = metric_filter.get("metricTransformations", []) matches = get_pattern_matcher(pattern) for log_event in log_events: if matches(pattern, log_event): for tf in transformations: value = tf.get("metricValue") or "1" if "$size" in value: LOG.info( "Expression not yet supported for log filter metricValue", value ) value = float(value) if is_number(value) else 1 data = [{"MetricName": tf["metricName"], "Value": value}] try: self.cw_client.put_metric_data( Namespace=tf["metricNamespace"], MetricData=data ) except Exception as e: LOG.info( "Unable to put metric data for matching CloudWatch log events", e ) return call_moto(context)
def describe_availability_zones( self, context: RequestContext, describe_availability_zones_request: DescribeAvailabilityZonesRequest, ) -> DescribeAvailabilityZonesResult: backend = ec2_backends.get(context.region) availability_zones = [] zone_names = describe_availability_zones_request.get("ZoneNames") if zone_names: for zone in zone_names: zone_detail = backend.get_zone_by_name(zone) if zone_detail: availability_zones.append( AvailabilityZone( State="available", Messages=[], RegionName=zone_detail.region_name, ZoneName=zone_detail.name, ZoneId=zone_detail.zone_id, )) return DescribeAvailabilityZonesResult( AvailabilityZones=availability_zones) return call_moto(context)
def create_rest_api(self, context: RequestContext, request: CreateRestApiRequest) -> RestApi: result = call_moto(context) event_publisher.fire_event( event_publisher.EVENT_APIGW_CREATE_API, payload={"a": event_publisher.get_hash(result["id"])}, ) return result
def get_api_keys( self, context: RequestContext, position: String = None, limit: NullableInteger = None, name_query: String = None, customer_id: String = None, include_values: NullableBoolean = None, ) -> ApiKeys: moto_response: ApiKeys = call_moto(context=context) item_list = PaginatedList(moto_response["items"]) def token_generator(item): return item["id"] def filter_function(item): return item["name"].startswith(name_query) paginated_list, next_token = item_list.get_page( token_generator=token_generator, next_token=position, page_size=limit, filter_function=filter_function if name_query else None, ) return ApiKeys( items=paginated_list, warnings=moto_response.get("warnings"), position=next_token )
def list_aliases( self, context: RequestContext, key_id: KeyIdType = None, limit: LimitType = None, marker: MarkerType = None, ) -> ListAliasesResponse: if key_id is None: return call_moto(context) response_aliases = PaginatedList() if kms_backends.get(context.region).keys.get(key_id) is None: raise NotFoundException(f"Unable to find key '{key_id}'") aliases_of_key = kms_backends.get( context.region).get_all_aliases().get(key_id) or [] for alias_name in aliases_of_key: response_aliases.append( AliasListEntry( AliasArn=kms_alias_arn(alias_name, region_name=context.region), AliasName=alias_name, TargetKeyId=key_id, )) page, nxt = response_aliases.get_page(lambda a: a["AliasName"], next_token=marker, page_size=limit) return ListAliasesResponse(Aliases=page, NextMarker=nxt, Truncated=nxt is not None)
def list_templates(self, context: RequestContext, next_token: NextToken = None, max_items: MaxItems = None) -> ListTemplatesResponse: for template in ses_backend.list_templates(): if isinstance(template["Timestamp"], (date, datetime)): template["Timestamp"] = timestamp_millis(template["Timestamp"]) return call_moto(context)
def get_caller_identity( self, context: RequestContext) -> GetCallerIdentityResponse: result = call_moto(context) username = config.TEST_IAM_USER_NAME or "localstack" result["Arn"] = result["Arn"].replace("user/moto", f"user/{username}") if config.TEST_IAM_USER_ID: result["UserId"] = config.TEST_IAM_USER_ID return result
def test_call_with_modified_request(): from moto.sqs.models import sqs_backends qname1 = f"queue-{short_uid()}" qname2 = f"queue-{short_uid()}" context = moto.create_aws_request_context("sqs", "CreateQueue", {"QueueName": qname1}) response = moto.call_moto_with_request( context, {"QueueName": qname2}) # overwrite old request url = response["QueueUrl"] assert qname2 in sqs_backends.get(config.AWS_REGION_US_EAST_1).queues assert qname1 not in sqs_backends.get(config.AWS_REGION_US_EAST_1).queues moto.call_moto( moto.create_aws_request_context("sqs", "DeleteQueue", {"QueueUrl": url}))
def label_parameter_version( self, context: RequestContext, name: PSParameterName, labels: ParameterLabelList, parameter_version: PSParameterVersion = None, ) -> LabelParameterVersionResult: SsmProvider._notify_event_subscribers(name, "LabelParameterVersion") return LabelParameterVersionResult(**call_moto(context))
def put_metric_alarm( self, context: RequestContext, request: PutMetricAlarmInput, ) -> None: # missing will be the default, when not set (but it will not explicitly be set) if not request.get("TreatMissingData", "missing") in [ "breaching", "notBreaching", "ignore", "missing", ]: raise ValidationError( f"The value {request['TreatMissingData']} is not supported for TreatMissingData parameter. Supported values are [breaching, notBreaching, ignore, missing]." ) # do some sanity checks: if request.get("Period"): # Valid values are 10, 30, and any multiple of 60. value = request.get("Period") if value not in (10, 30): if value % 60 != 0: raise ValidationError( "Period must be 10, 30 or a multiple of 60") if request.get("Statistic"): if not request.get("Statistic") in [ "SampleCount", "Average", "Sum", "Minimum", "Maximum", ]: raise ValidationError( f"Value '{request.get('Statistic')}' at 'statistic' failed to satisfy constraint: Member must satisfy enum value set: [Maximum, SampleCount, Sum, Minimum, Average]" ) moto.call_moto(context) name = request.get("AlarmName") arn = aws_stack.cloudwatch_alarm_arn(name) self.tags.tag_resource(arn, request.get("Tags")) self.alarm_scheduler.schedule_metric_alarm(arn)
def put_parameter(self, context: RequestContext, request: PutParameterRequest) -> PutParameterResult: name = request["Name"] nname = SsmProvider._normalize_name(name) if name != nname: request.update({"Name": nname}) moto_res = call_moto_with_request(context, request) else: moto_res = call_moto(context) SsmProvider._notify_event_subscribers(nname, "Create") return PutParameterResult(**moto_res)
def test_call_multi_region_backends(): from moto.sqs.models import sqs_backends qname_us = f"queue-us-{short_uid()}" qname_eu = f"queue-eu-{short_uid()}" moto.call_moto( moto.create_aws_request_context("sqs", "CreateQueue", {"QueueName": qname_us}, region="us-east-1")) moto.call_moto( moto.create_aws_request_context("sqs", "CreateQueue", {"QueueName": qname_eu}, region="eu-central-1")) assert qname_us in sqs_backends.get("us-east-1").queues assert qname_eu not in sqs_backends.get("us-east-1").queues assert qname_us not in sqs_backends.get("eu-central-1").queues assert qname_eu in sqs_backends.get("eu-central-1").queues del sqs_backends.get("us-east-1").queues[qname_us] del sqs_backends.get("eu-central-1").queues[qname_eu]
def put_rule( self, context: RequestContext, name: RuleName, schedule_expression: ScheduleExpression = None, event_pattern: EventPattern = None, state: RuleState = None, description: RuleDescription = None, role_arn: RoleArn = None, tags: TagList = None, event_bus_name: EventBusNameOrArn = None, ) -> PutRuleResponse: self.put_rule_job_scheduler(name, state, schedule_expression) return call_moto(context)
def request_certificate( self, context: RequestContext, request: RequestCertificateRequest, ) -> RequestCertificateResponse: response: RequestCertificateResponse = moto.call_moto(context) cert_arn = response["CertificateArn"] backend = acm_backends.get(context.region) cert = backend._certificates[cert_arn] if not hasattr(cert, "domain_validation_options"): cert.domain_validation_options = request.get( "DomainValidationOptions") return response
def revoke_security_group_egress( self, context: RequestContext, revoke_security_group_egress_request: RevokeSecurityGroupEgressRequest, ) -> RevokeSecurityGroupEgressResult: try: return call_moto(context) except Exception as e: if "specified rule does not exist" in str(e): backend = ec2_backends[context.region] group_id = revoke_security_group_egress_request["GroupId"] group = backend.get_security_group_by_name_or_id(group_id) if group and not group.egress_rules: return RevokeSecurityGroupEgressResult(Return=True) raise
def _call_moto(context: RequestContext, operation_name: str, parameters: ServiceRequest): """ Not necessarily the pattern we want to follow in the future, but this makes possible to nest moto call and still be interface compatible. Ripped :call_moto_with_request: from moto.py but applicable to any operation (operation_name). """ local_context = create_aws_request_context( service_name=context.service.service_name, action=operation_name, parameters=parameters, region=context.region, ) local_context.request.headers.extend(context.request.headers) return call_moto(local_context)