diff --git a/moto/__init__.py b/moto/__init__.py index 4c9d4753c..79c1555d3 100644 --- a/moto/__init__.py +++ b/moto/__init__.py @@ -1,62 +1,114 @@ from __future__ import unicode_literals -from .acm import mock_acm # noqa -from .apigateway import mock_apigateway, mock_apigateway_deprecated # noqa -from .athena import mock_athena # noqa -from .autoscaling import mock_autoscaling, mock_autoscaling_deprecated # noqa -from .awslambda import mock_lambda, mock_lambda_deprecated # noqa -from .batch import mock_batch # noqa -from .cloudformation import mock_cloudformation # noqa -from .cloudformation import mock_cloudformation_deprecated # noqa -from .cloudwatch import mock_cloudwatch, mock_cloudwatch_deprecated # noqa -from .codecommit import mock_codecommit # noqa -from .codepipeline import mock_codepipeline # noqa -from .cognitoidentity import mock_cognitoidentity # noqa -from .cognitoidentity import mock_cognitoidentity_deprecated # noqa -from .cognitoidp import mock_cognitoidp, mock_cognitoidp_deprecated # noqa -from .config import mock_config # noqa -from .datapipeline import mock_datapipeline # noqa -from .datapipeline import mock_datapipeline_deprecated # noqa -from .datasync import mock_datasync # noqa -from .dynamodb import mock_dynamodb, mock_dynamodb_deprecated # noqa -from .dynamodb2 import mock_dynamodb2, mock_dynamodb2_deprecated # noqa -from .dynamodbstreams import mock_dynamodbstreams # noqa -from .elasticbeanstalk import mock_elasticbeanstalk # noqa -from .ec2 import mock_ec2, mock_ec2_deprecated # noqa -from .ec2_instance_connect import mock_ec2_instance_connect # noqa -from .ecr import mock_ecr, mock_ecr_deprecated # noqa -from .ecs import mock_ecs, mock_ecs_deprecated # noqa -from .elb import mock_elb, mock_elb_deprecated # noqa -from .elbv2 import mock_elbv2 # noqa -from .emr import mock_emr, mock_emr_deprecated # noqa -from .events import mock_events # noqa -from .glacier import mock_glacier, mock_glacier_deprecated # noqa -from .glue import mock_glue # noqa -from .iam import mock_iam, mock_iam_deprecated # noqa -from .iot import mock_iot # noqa -from .iotdata import mock_iotdata # noqa -from .kinesis import mock_kinesis, mock_kinesis_deprecated # noqa -from .kms import mock_kms, mock_kms_deprecated # noqa -from .logs import mock_logs, mock_logs_deprecated # noqa -from .opsworks import mock_opsworks, mock_opsworks_deprecated # noqa -from .organizations import mock_organizations # noqa -from .polly import mock_polly # noqa -from .rds import mock_rds, mock_rds_deprecated # noqa -from .rds2 import mock_rds2, mock_rds2_deprecated # noqa -from .redshift import mock_redshift, mock_redshift_deprecated # noqa -from .resourcegroups import mock_resourcegroups # noqa -from .resourcegroupstaggingapi import mock_resourcegroupstaggingapi # noqa -from .route53 import mock_route53, mock_route53_deprecated # noqa -from .s3 import mock_s3, mock_s3_deprecated # noqa -from .secretsmanager import mock_secretsmanager # noqa -from .ses import mock_ses, mock_ses_deprecated # noqa -from .sns import mock_sns, mock_sns_deprecated # noqa -from .sqs import mock_sqs, mock_sqs_deprecated # noqa -from .ssm import mock_ssm # noqa -from .stepfunctions import mock_stepfunctions # noqa -from .sts import mock_sts, mock_sts_deprecated # noqa -from .swf import mock_swf, mock_swf_deprecated # noqa -from .xray import XRaySegment, mock_xray, mock_xray_client # noqa +import importlib + + +def lazy_load(module_name, element): + def f(*args, **kwargs): + module = importlib.import_module(module_name, "moto") + return getattr(module, element)(*args, **kwargs) + + return f + + +mock_acm = lazy_load(".acm", "mock_acm") +mock_apigateway = lazy_load(".apigateway", "mock_apigateway") +mock_apigateway_deprecated = lazy_load(".apigateway", "mock_apigateway_deprecated") +mock_athena = lazy_load(".athena", "mock_athena") +mock_autoscaling = lazy_load(".autoscaling", "mock_autoscaling") +mock_autoscaling_deprecated = lazy_load(".autoscaling", "mock_autoscaling_deprecated") +mock_lambda = lazy_load(".awslambda", "mock_lambda") +mock_lambda_deprecated = lazy_load(".awslambda", "mock_lambda_deprecated") +mock_batch = lazy_load(".batch", "mock_batch") +mock_batch = lazy_load(".batch", "mock_batch") +mock_cloudformation = lazy_load(".cloudformation", "mock_cloudformation") +mock_cloudformation_deprecated = lazy_load( + ".cloudformation", "mock_cloudformation_deprecated" +) +mock_cloudwatch = lazy_load(".cloudwatch", "mock_cloudwatch") +mock_cloudwatch_deprecated = lazy_load(".cloudwatch", "mock_cloudwatch_deprecated") +mock_codecommit = lazy_load(".codecommit", "mock_codecommit") +mock_codepipeline = lazy_load(".codepipeline", "mock_codepipeline") +mock_cognitoidentity = lazy_load(".cognitoidentity", "mock_cognitoidentity") +mock_cognitoidentity_deprecated = lazy_load( + ".cognitoidentity", "mock_cognitoidentity_deprecated" +) +mock_cognitoidp = lazy_load(".cognitoidp", "mock_cognitoidp") +mock_cognitoidp_deprecated = lazy_load(".cognitoidp", "mock_cognitoidp_deprecated") +mock_config = lazy_load(".config", "mock_config") +mock_datapipeline = lazy_load(".datapipeline", "mock_datapipeline") +mock_datapipeline_deprecated = lazy_load( + ".datapipeline", "mock_datapipeline_deprecated" +) +mock_datasync = lazy_load(".datasync", "mock_datasync") +mock_dynamodb = lazy_load(".dynamodb", "mock_dynamodb") +mock_dynamodb_deprecated = lazy_load(".dynamodb", "mock_dynamodb_deprecated") +mock_dynamodb2 = lazy_load(".dynamodb2", "mock_dynamodb2") +mock_dynamodb2_deprecated = lazy_load(".dynamodb2", "mock_dynamodb2_deprecated") +mock_dynamodbstreams = lazy_load(".dynamodbstreams", "mock_dynamodbstreams") +mock_elasticbeanstalk = lazy_load(".elasticbeanstalk", "mock_elasticbeanstalk") +mock_ec2 = lazy_load(".ec2", "mock_ec2") +mock_ec2_deprecated = lazy_load(".ec2", "mock_ec2_deprecated") +mock_ec2_instance_connect = lazy_load( + ".ec2_instance_connect", "mock_ec2_instance_connect" +) +mock_ecr = lazy_load(".ecr", "mock_ecr") +mock_ecr_deprecated = lazy_load(".ecr", "mock_ecr_deprecated") +mock_ecs = lazy_load(".ecs", "mock_ecs") +mock_ecs_deprecated = lazy_load(".ecs", "mock_ecs_deprecated") +mock_elb = lazy_load(".elb", "mock_elb") +mock_elb_deprecated = lazy_load(".elb", "mock_elb_deprecated") +mock_elbv2 = lazy_load(".elbv2", "mock_elbv2") +mock_emr = lazy_load(".emr", "mock_emr") +mock_emr_deprecated = lazy_load(".emr", "mock_emr_deprecated") +mock_events = lazy_load(".events", "mock_events") +mock_glacier = lazy_load(".glacier", "mock_glacier") +mock_glacier_deprecated = lazy_load(".glacier", "mock_glacier_deprecated") +mock_glue = lazy_load(".glue", "mock_glue") +mock_iam = lazy_load(".iam", "mock_iam") +mock_iam_deprecated = lazy_load(".iam", "mock_iam_deprecated") +mock_iot = lazy_load(".iot", "mock_iot") +mock_iotdata = lazy_load(".iotdata", "mock_iotdata") +mock_kinesis = lazy_load(".kinesis", "mock_kinesis") +mock_kinesis_deprecated = lazy_load(".kinesis", "mock_kinesis_deprecated") +mock_kms = lazy_load(".kms", "mock_kms") +mock_kms_deprecated = lazy_load(".kms", "mock_kms_deprecated") +mock_logs = lazy_load(".logs", "mock_logs") +mock_logs_deprecated = lazy_load(".logs", "mock_logs_deprecated") +mock_opsworks = lazy_load(".opsworks", "mock_opsworks") +mock_opsworks_deprecated = lazy_load(".opsworks", "mock_opsworks_deprecated") +mock_organizations = lazy_load(".organizations", "mock_organizations") +mock_polly = lazy_load(".polly", "mock_polly") +mock_rds = lazy_load(".rds", "mock_rds") +mock_rds_deprecated = lazy_load(".rds", "mock_rds_deprecated") +mock_rds2 = lazy_load(".rds2", "mock_rds2") +mock_rds2_deprecated = lazy_load(".rds2", "mock_rds2_deprecated") +mock_redshift = lazy_load(".redshift", "mock_redshift") +mock_redshift_deprecated = lazy_load(".redshift", "mock_redshift_deprecated") +mock_resourcegroups = lazy_load(".resourcegroups", "mock_resourcegroups") +mock_resourcegroupstaggingapi = lazy_load( + ".resourcegroupstaggingapi", "mock_resourcegroupstaggingapi" +) +mock_route53 = lazy_load(".route53", "mock_route53") +mock_route53_deprecated = lazy_load(".route53", "mock_route53_deprecated") +mock_s3 = lazy_load(".s3", "mock_s3") +mock_s3_deprecated = lazy_load(".s3", "mock_s3_deprecated") +mock_secretsmanager = lazy_load(".secretsmanager", "mock_secretsmanager") +mock_ses = lazy_load(".ses", "mock_ses") +mock_ses_deprecated = lazy_load(".ses", "mock_ses_deprecated") +mock_sns = lazy_load(".sns", "mock_sns") +mock_sns_deprecated = lazy_load(".sns", "mock_sns_deprecated") +mock_sqs = lazy_load(".sqs", "mock_sqs") +mock_sqs_deprecated = lazy_load(".sqs", "mock_sqs_deprecated") +mock_ssm = lazy_load(".ssm", "mock_ssm") +mock_stepfunctions = lazy_load(".stepfunctions", "mock_stepfunctions") +mock_sts = lazy_load(".sts", "mock_sts") +mock_sts_deprecated = lazy_load(".sts", "mock_sts_deprecated") +mock_swf = lazy_load(".swf", "mock_swf") +mock_swf_deprecated = lazy_load(".swf", "mock_swf_deprecated") +XRaySegment = lazy_load(".xray", "XRaySegment") +mock_xray = lazy_load(".xray", "mock_xray") +mock_xray_client = lazy_load(".xray", "mock_xray_client") # import logging # logging.getLogger('boto').setLevel(logging.CRITICAL) diff --git a/moto/backends.py b/moto/backends.py index a48df74a4..bb71429eb 100644 --- a/moto/backends.py +++ b/moto/backends.py @@ -1,124 +1,99 @@ from __future__ import unicode_literals -from moto.acm import acm_backends -from moto.apigateway import apigateway_backends -from moto.athena import athena_backends -from moto.autoscaling import autoscaling_backends -from moto.awslambda import lambda_backends -from moto.batch import batch_backends -from moto.cloudformation import cloudformation_backends -from moto.cloudwatch import cloudwatch_backends -from moto.codecommit import codecommit_backends -from moto.codepipeline import codepipeline_backends -from moto.cognitoidentity import cognitoidentity_backends -from moto.cognitoidp import cognitoidp_backends -from moto.config import config_backends -from moto.core import moto_api_backends -from moto.datapipeline import datapipeline_backends -from moto.datasync import datasync_backends -from moto.dynamodb import dynamodb_backends -from moto.dynamodb2 import dynamodb_backends2 -from moto.dynamodbstreams import dynamodbstreams_backends -from moto.ec2 import ec2_backends -from moto.ec2_instance_connect import ec2_instance_connect_backends -from moto.ecr import ecr_backends -from moto.ecs import ecs_backends -from moto.elasticbeanstalk import eb_backends -from moto.elb import elb_backends -from moto.elbv2 import elbv2_backends -from moto.emr import emr_backends -from moto.events import events_backends -from moto.glacier import glacier_backends -from moto.glue import glue_backends -from moto.iam import iam_backends -from moto.instance_metadata import instance_metadata_backends -from moto.iot import iot_backends -from moto.iotdata import iotdata_backends -from moto.kinesis import kinesis_backends -from moto.kms import kms_backends -from moto.logs import logs_backends -from moto.opsworks import opsworks_backends -from moto.organizations import organizations_backends -from moto.polly import polly_backends -from moto.rds2 import rds2_backends -from moto.redshift import redshift_backends -from moto.resourcegroups import resourcegroups_backends -from moto.resourcegroupstaggingapi import resourcegroupstaggingapi_backends -from moto.route53 import route53_backends -from moto.s3 import s3_backends -from moto.secretsmanager import secretsmanager_backends -from moto.ses import ses_backends -from moto.sns import sns_backends -from moto.sqs import sqs_backends -from moto.ssm import ssm_backends -from moto.stepfunctions import stepfunction_backends -from moto.sts import sts_backends -from moto.swf import swf_backends -from moto.xray import xray_backends +import importlib BACKENDS = { - "acm": acm_backends, - "apigateway": apigateway_backends, - "athena": athena_backends, - "autoscaling": autoscaling_backends, - "batch": batch_backends, - "cloudformation": cloudformation_backends, - "cloudwatch": cloudwatch_backends, - "codecommit": codecommit_backends, - "codepipeline": codepipeline_backends, - "cognito-identity": cognitoidentity_backends, - "cognito-idp": cognitoidp_backends, - "config": config_backends, - "datapipeline": datapipeline_backends, - "datasync": datasync_backends, - "dynamodb": dynamodb_backends, - "dynamodb2": dynamodb_backends2, - "dynamodbstreams": dynamodbstreams_backends, - "ec2": ec2_backends, - "ec2_instance_connect": ec2_instance_connect_backends, - "ecr": ecr_backends, - "ecs": ecs_backends, - "elasticbeanstalk": eb_backends, - "elb": elb_backends, - "elbv2": elbv2_backends, - "events": events_backends, - "emr": emr_backends, - "glacier": glacier_backends, - "glue": glue_backends, - "iam": iam_backends, - "moto_api": moto_api_backends, - "instance_metadata": instance_metadata_backends, - "logs": logs_backends, - "kinesis": kinesis_backends, - "kms": kms_backends, - "opsworks": opsworks_backends, - "organizations": organizations_backends, - "polly": polly_backends, - "redshift": redshift_backends, - "resource-groups": resourcegroups_backends, - "rds": rds2_backends, - "s3": s3_backends, - "s3bucket_path": s3_backends, - "ses": ses_backends, - "secretsmanager": secretsmanager_backends, - "sns": sns_backends, - "sqs": sqs_backends, - "ssm": ssm_backends, - "stepfunctions": stepfunction_backends, - "sts": sts_backends, - "swf": swf_backends, - "route53": route53_backends, - "lambda": lambda_backends, - "xray": xray_backends, - "resourcegroupstaggingapi": resourcegroupstaggingapi_backends, - "iot": iot_backends, - "iot-data": iotdata_backends, + "acm": ("acm", "acm_backends"), + "apigateway": ("apigateway", "apigateway_backends"), + "athena": ("athena", "athena_backends"), + "autoscaling": ("autoscaling", "autoscaling_backends"), + "batch": ("batch", "batch_backends"), + "cloudformation": ("cloudformation", "cloudformation_backends"), + "cloudwatch": ("cloudwatch", "cloudwatch_backends"), + "codecommit": ("codecommit", "codecommit_backends"), + "codepipeline": ("codepipeline", "codepipeline_backends"), + "cognito-identity": ("cognitoidentity", "cognitoidentity_backends"), + "cognito-idp": ("cognitoidp", "cognitoidp_backends"), + "config": ("config", "config_backends"), + "datapipeline": ("datapipeline", "datapipeline_backends"), + "datasync": ("datasync", "datasync_backends"), + "dynamodb": ("dynamodb", "dynamodb_backends"), + "dynamodb2": ("dynamodb2", "dynamodb_backends2"), + "dynamodbstreams": ("dynamodbstreams", "dynamodbstreams_backends"), + "ec2": ("ec2", "ec2_backends"), + "ec2_instance_connect": ("ec2_instance_connect", "ec2_instance_connect_backends"), + "ecr": ("ecr", "ecr_backends"), + "ecs": ("ecs", "ecs_backends"), + "elasticbeanstalk": ("elasticbeanstalk", "eb_backends"), + "elb": ("elb", "elb_backends"), + "elbv2": ("elbv2", "elbv2_backends"), + "emr": ("emr", "emr_backends"), + "events": ("events", "events_backends"), + "glacier": ("glacier", "glacier_backends"), + "glue": ("glue", "glue_backends"), + "iam": ("iam", "iam_backends"), + "instance_metadata": ("instance_metadata", "instance_metadata_backends"), + "iot": ("iot", "iot_backends"), + "iot-data": ("iotdata", "iotdata_backends"), + "kinesis": ("kinesis", "kinesis_backends"), + "kms": ("kms", "kms_backends"), + "lambda": ("awslambda", "lambda_backends"), + "logs": ("logs", "logs_backends"), + "moto_api": ("core", "moto_api_backends"), + "opsworks": ("opsworks", "opsworks_backends"), + "organizations": ("organizations", "organizations_backends"), + "polly": ("polly", "polly_backends"), + "rds": ("rds2", "rds2_backends"), + "redshift": ("redshift", "redshift_backends"), + "resource-groups": ("resourcegroups", "resourcegroups_backends"), + "resourcegroupstaggingapi": ( + "resourcegroupstaggingapi", + "resourcegroupstaggingapi_backends", + ), + "route53": ("route53", "route53_backends"), + "s3": ("s3", "s3_backends"), + "s3bucket_path": ("s3", "s3_backends"), + "secretsmanager": ("secretsmanager", "secretsmanager_backends"), + "ses": ("ses", "ses_backends"), + "sns": ("sns", "sns_backends"), + "sqs": ("sqs", "sqs_backends"), + "ssm": ("ssm", "ssm_backends"), + "stepfunctions": ("stepfunctions", "stepfunction_backends"), + "sts": ("sts", "sts_backends"), + "swf": ("swf", "swf_backends"), + "xray": ("xray", "xray_backends"), } +def _import_backend(module_name, backends_name): + module = importlib.import_module("moto." + module_name) + return getattr(module, backends_name) + + +def backends(): + for module_name, backends_name in BACKENDS.values(): + yield _import_backend(module_name, backends_name) + + +def named_backends(): + for name, (module_name, backends_name) in BACKENDS.items(): + yield name, _import_backend(module_name, backends_name) + + +def get_backend(name): + module_name, backends_name = BACKENDS[name] + return _import_backend(module_name, backends_name) + + +def search_backend(predicate): + for name, backend in named_backends(): + if predicate(backend): + return name + + def get_model(name, region_name): - for backends in BACKENDS.values(): - for region, backend in backends.items(): + for backends_ in backends(): + for region, backend in backends_.items(): if region == region_name: models = getattr(backend.__class__, "__models__", {}) if name in models: diff --git a/moto/cloudformation/utils.py b/moto/cloudformation/utils.py index cd8481002..54c338b9b 100644 --- a/moto/cloudformation/utils.py +++ b/moto/cloudformation/utils.py @@ -6,7 +6,6 @@ import yaml import os import string -from cfnlint import decode, core from moto.core import ACCOUNT_ID @@ -62,6 +61,8 @@ def yaml_tag_constructor(loader, tag, node): def validate_template_cfn_lint(template): + # Importing cfnlint adds a significant overhead, so we keep it local + from cfnlint import decode, core # Save the template to a temporary file -- cfn-lint requires a file filename = "file.tmp" diff --git a/moto/core/models.py b/moto/core/models.py index 1ee11607a..1597efc7b 100644 --- a/moto/core/models.py +++ b/moto/core/models.py @@ -33,14 +33,15 @@ class BaseMockAWS(object): nested_count = 0 def __init__(self, backends): + from moto.instance_metadata import instance_metadata_backend + from moto.core import moto_api_backend + self.backends = backends self.backends_for_urls = {} - from moto.backends import BACKENDS - default_backends = { - "instance_metadata": BACKENDS["instance_metadata"]["global"], - "moto_api": BACKENDS["moto_api"]["global"], + "instance_metadata": instance_metadata_backend, + "moto_api": moto_api_backend, } self.backends_for_urls.update(self.backends) self.backends_for_urls.update(default_backends) @@ -721,12 +722,12 @@ class deprecated_base_decorator(base_decorator): class MotoAPIBackend(BaseBackend): def reset(self): - from moto.backends import BACKENDS + import moto.backends as backends - for name, backends in BACKENDS.items(): + for name, backends_ in backends.named_backends(): if name == "moto_api": continue - for region_name, backend in backends.items(): + for region_name, backend in backends_.items(): backend.reset() self.__init__() diff --git a/moto/core/responses.py b/moto/core/responses.py index c708edb8b..9a46f8ac5 100644 --- a/moto/core/responses.py +++ b/moto/core/responses.py @@ -20,7 +20,6 @@ import six from six.moves.urllib.parse import parse_qs, urlparse import xmltodict -from pkg_resources import resource_filename from werkzeug.exceptions import HTTPException import boto3 @@ -766,6 +765,9 @@ class AWSServiceSpec(object): """ def __init__(self, path): + # Importing pkg_resources takes ~60ms; keep it local + from pkg_resources import resource_filename # noqa + self.path = resource_filename("botocore", path) with io.open(self.path, "r", encoding="utf-8") as f: spec = json.load(f) diff --git a/moto/ec2/utils.py b/moto/ec2/utils.py index 61d22d8b2..3b363e45d 100644 --- a/moto/ec2/utils.py +++ b/moto/ec2/utils.py @@ -10,8 +10,6 @@ import six from cryptography.hazmat.primitives import serialization from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import rsa -import sshpubkeys.exceptions -from sshpubkeys.keys import SSHKey EC2_RESOURCE_TO_PREFIX = { @@ -544,6 +542,10 @@ def generate_instance_identity_document(instance): def rsa_public_key_parse(key_material): + # These imports take ~.5s; let's keep them local + import sshpubkeys.exceptions + from sshpubkeys.keys import SSHKey + try: if not isinstance(key_material, six.binary_type): key_material = key_material.encode("ascii") diff --git a/moto/ec2_instance_connect/models.py b/moto/ec2_instance_connect/models.py index cc8cc3f33..f3dbbe9f8 100644 --- a/moto/ec2_instance_connect/models.py +++ b/moto/ec2_instance_connect/models.py @@ -1,4 +1,4 @@ -import boto +import boto.ec2 from moto.core import BaseBackend diff --git a/moto/iam/models.py b/moto/iam/models.py index e34ca7cf8..08a1eb36a 100755 --- a/moto/iam/models.py +++ b/moto/iam/models.py @@ -288,6 +288,7 @@ class AWSManagedPolicy(ManagedPolicy): # AWS defines some of its own managed policies and we periodically # import them via `make aws_managed_policies` +# FIXME: Takes about 40ms at import time aws_managed_policies = [ AWSManagedPolicy.from_data(name, d) for name, d in json.loads(aws_managed_policies_data).items() diff --git a/moto/rds2/models.py b/moto/rds2/models.py index 722d7d4fd..7fa4f3316 100644 --- a/moto/rds2/models.py +++ b/moto/rds2/models.py @@ -8,7 +8,6 @@ from collections import defaultdict from boto3 import Session from jinja2 import Template from re import compile as re_compile -from moto.cloudformation.exceptions import UnformattedGetAttTemplateException from moto.compat import OrderedDict from moto.core import BaseBackend, BaseModel from moto.core.utils import get_random_hex @@ -308,6 +307,9 @@ class Database(BaseModel): setattr(self, key, value) def get_cfn_attribute(self, attribute_name): + # Local import to avoid circular dependency with cloudformation.parsing + from moto.cloudformation.exceptions import UnformattedGetAttTemplateException + if attribute_name == "Endpoint.Address": return self.address elif attribute_name == "Endpoint.Port": diff --git a/moto/server.py b/moto/server.py index 498f6c504..46e37d921 100644 --- a/moto/server.py +++ b/moto/server.py @@ -15,7 +15,7 @@ from six.moves.urllib.parse import urlencode from werkzeug.routing import BaseConverter from werkzeug.serving import run_simple -from moto.backends import BACKENDS +import moto.backends as backends from moto.core.utils import convert_flask_to_httpretty_response @@ -52,13 +52,15 @@ class DomainDispatcherApplication(object): if self.service: return self.service - if host in BACKENDS: + if host in backends.BACKENDS: return host - for backend_name, backend in BACKENDS.items(): - for url_base in list(backend.values())[0].url_bases: - if re.match(url_base, "http://%s" % host): - return backend_name + return backends.search_backend( + lambda backend: any( + re.match(url_base, "http://%s" % host) + for url_base in list(backend.values())[0].url_bases + ) + ) def infer_service_region_host(self, environ): auth = environ.get("HTTP_AUTHORIZATION") @@ -204,7 +206,7 @@ def create_backend_app(service): backend_app.view_functions = {} backend_app.url_map = Map() backend_app.url_map.converters["regex"] = RegexConverter - backend = list(BACKENDS[service].values())[0] + backend = list(backends.get_backend(service).values())[0] for url_path, handler in backend.flask_paths.items(): view_func = convert_flask_to_httpretty_response(handler) if handler.__name__ == "dispatch":