diff --git a/docs/docs/configuration/recorder/index.rst b/docs/docs/configuration/recorder/index.rst
index 07974d284..11976fd8f 100644
--- a/docs/docs/configuration/recorder/index.rst
+++ b/docs/docs/configuration/recorder/index.rst
@@ -68,3 +68,46 @@ The requests are stored in a file called `moto_recording`, in the directory that
The recorder is disabled by default. If you want to enable it, use the following environment variable:
`MOTO_ENABLE_RECORDING=True`
+
+
+Deterministic Identifiers
+##############################
+
+Moto creates random identifiers for most resources, just like AWS. The Recorder will recreate the same resources every time, but with different identifiers.
+
+It is possible to seed Moto and ensure that the 'random' identifiers are always the same for subsequent requests.
+
+Example invocation:
+
+.. sourcecode:: python
+
+ # Ensure the provided parameter `a` is an integer
+ requests.post("http://motoapi.amazonaws.com/moto-api/seed?a=42")
+
+ # To try this out, generate a EC2 instance
+ client = boto3.client("ec2", region_name="us-east-1")
+ resp = client.run_instances(ImageId="ami-12c6146b", MinCount=1, MaxCount=1)
+
+ # The resulting InstanceId will always be the same
+ instance_id = resp["Instances"][0]["InstanceId"]
+ assert instance_id == "i-d1026706d7e805da8"
+
+To seed Moto in ServerMode:
+
+.. sourcecode:: python
+
+ requests.post(f"http://localhost:5000/moto-api/seed?a=42")
+
+
+Because the seeding API is only exposed as a request, it will be recorded just like any other request. :raw-html:`
`
+Seed Moto at the beginning of a recording to ensure the resulting state will always be the same:
+
+.. sourcecode:: python
+
+ requests.post("http://localhost:5000/moto-api/recorder/start-recording")
+ requests.post("http://localhost:5000/moto-api/seed?a=42")
+
+ client = boto3.client("ec2", region_name="us-east-1")
+ resp = client.run_instances(ImageId="ami-12c6146b", MinCount=1, MaxCount=1)
+
+ requests.post("http://localhost:5000/moto-api/recorder/stop-recording")
diff --git a/moto/acm/utils.py b/moto/acm/utils.py
index 6d695d95c..c25e17213 100644
--- a/moto/acm/utils.py
+++ b/moto/acm/utils.py
@@ -1,9 +1,9 @@
-import uuid
+from moto.moto_api._internal import mock_random
def make_arn_for_certificate(account_id, region_name):
# Example
# arn:aws:acm:eu-west-2:764371465172:certificate/c4b738b8-56fe-4b3a-b841-1c047654780b
return "arn:aws:acm:{0}:{1}:certificate/{2}".format(
- region_name, account_id, uuid.uuid4()
+ region_name, account_id, mock_random.uuid4()
)
diff --git a/moto/amp/models.py b/moto/amp/models.py
index 1159d62fb..02160b1a4 100644
--- a/moto/amp/models.py
+++ b/moto/amp/models.py
@@ -2,10 +2,10 @@
from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict, unix_time
+from moto.moto_api._internal import mock_random
from moto.utilities.paginator import paginate
from moto.utilities.tagging_service import TaggingService
from typing import Dict
-from uuid import uuid4
from .exceptions import RuleGroupNamespaceNotFound, WorkspaceNotFound
from .utils import PAGINATION_MODEL
@@ -38,7 +38,7 @@ class RuleGroupNamespace(BaseModel):
class Workspace(BaseModel):
def __init__(self, account_id, region, alias, tag_fn):
self.alias = alias
- self.workspace_id = f"ws-{uuid4()}"
+ self.workspace_id = f"ws-{mock_random.uuid4()}"
self.arn = f"arn:aws:aps:{region}:{account_id}:workspace/{self.workspace_id}"
self.endpoint = f"https://aps-workspaces.{region}.amazonaws.com/workspaces/{self.workspace_id}/"
self.status = {"statusCode": "ACTIVE"}
diff --git a/moto/apigateway/models.py b/moto/apigateway/models.py
index 1390db1a3..544174e7e 100644
--- a/moto/apigateway/models.py
+++ b/moto/apigateway/models.py
@@ -1,6 +1,5 @@
from __future__ import absolute_import
-import random
import string
import re
from collections import defaultdict
@@ -66,6 +65,7 @@ from .exceptions import (
)
from ..core.models import responses_mock
from moto.apigateway.exceptions import MethodNotFoundException
+from moto.moto_api._internal import mock_random as random
STAGE_URL = "https://{api_id}.execute-api.{region_name}.amazonaws.com/{stage_name}"
diff --git a/moto/apigateway/utils.py b/moto/apigateway/utils.py
index 416e10631..facecca82 100644
--- a/moto/apigateway/utils.py
+++ b/moto/apigateway/utils.py
@@ -1,7 +1,7 @@
-import random
import string
import json
import yaml
+from moto.moto_api._internal import mock_random as random
def create_id():
diff --git a/moto/apigatewayv2/models.py b/moto/apigatewayv2/models.py
index 9ce721ea9..52b338cad 100644
--- a/moto/apigatewayv2/models.py
+++ b/moto/apigatewayv2/models.py
@@ -1,10 +1,10 @@
"""ApiGatewayV2Backend class with methods for supported APIs."""
-import random
import string
import yaml
from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict, unix_time
+from moto.moto_api._internal import mock_random as random
from moto.utilities.tagging_service import TaggingService
from .exceptions import (
diff --git a/moto/applicationautoscaling/models.py b/moto/applicationautoscaling/models.py
index b0f369de8..027e5ce48 100644
--- a/moto/applicationautoscaling/models.py
+++ b/moto/applicationautoscaling/models.py
@@ -1,11 +1,11 @@
from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict
from moto.ecs import ecs_backends
+from moto.moto_api._internal import mock_random
from .exceptions import AWSValidationException
from collections import OrderedDict
from enum import Enum, unique
import time
-import uuid
@unique
@@ -418,7 +418,7 @@ class FakeApplicationAutoscalingPolicy(BaseModel):
self.scalable_dimension = scalable_dimension
self.policy_name = policy_name
self.policy_type = policy_type
- self._guid = uuid.uuid4()
+ self._guid = mock_random.uuid4()
self.policy_arn = "arn:aws:autoscaling:{}:scalingPolicy:{}:resource/{}/{}:policyName/{}".format(
region_name,
self._guid,
diff --git a/moto/appsync/models.py b/moto/appsync/models.py
index 1b7b65654..ecce39a6b 100644
--- a/moto/appsync/models.py
+++ b/moto/appsync/models.py
@@ -2,10 +2,9 @@ import base64
from datetime import timedelta, datetime, timezone
from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict, unix_time
+from moto.moto_api._internal import mock_random
from moto.utilities.tagging_service import TaggingService
-from uuid import uuid4
-
from .exceptions import GraphqlAPINotFound
@@ -66,7 +65,7 @@ class GraphqlAPI(BaseModel):
):
self.region = region
self.name = name
- self.api_id = str(uuid4())
+ self.api_id = str(mock_random.uuid4())
self.authentication_type = authentication_type
self.additional_authentication_providers = additional_authentication_providers
self.lambda_authorizer_config = lambda_authorizer_config
@@ -157,7 +156,7 @@ class GraphqlAPI(BaseModel):
class GraphqlAPIKey(BaseModel):
def __init__(self, description, expires):
- self.key_id = str(uuid4())[0:6]
+ self.key_id = str(mock_random.uuid4())[0:6]
self.description = description
self.expires = expires
if not self.expires:
diff --git a/moto/athena/models.py b/moto/athena/models.py
index 7bf7e3f79..beb7923e6 100644
--- a/moto/athena/models.py
+++ b/moto/athena/models.py
@@ -2,8 +2,7 @@ import time
from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict
-
-from uuid import uuid4
+from moto.moto_api._internal import mock_random
class TaggableResourceMixin(object):
@@ -66,7 +65,7 @@ class DataCatalog(TaggableResourceMixin, BaseModel):
class Execution(BaseModel):
def __init__(self, query, context, config, workgroup):
- self.id = str(uuid4())
+ self.id = str(mock_random.uuid4())
self.query = query
self.context = context
self.config = config
@@ -77,7 +76,7 @@ class Execution(BaseModel):
class NamedQuery(BaseModel):
def __init__(self, name, description, database, query_string, workgroup):
- self.id = str(uuid4())
+ self.id = str(mock_random.uuid4())
self.name = name
self.description = description
self.database = database
diff --git a/moto/autoscaling/models.py b/moto/autoscaling/models.py
index e06575724..1a2d4af41 100644
--- a/moto/autoscaling/models.py
+++ b/moto/autoscaling/models.py
@@ -1,6 +1,4 @@
import itertools
-import random
-from uuid import uuid4
from moto.packages.boto.ec2.blockdevicemapping import (
BlockDeviceType,
@@ -15,6 +13,7 @@ from moto.ec2 import ec2_backends
from moto.elb import elb_backends
from moto.elbv2 import elbv2_backends
from moto.elb.exceptions import LoadBalancerNotFoundError
+from moto.moto_api._internal import mock_random as random
from .exceptions import (
AutoscalingClientError,
ResourceContentionError,
@@ -375,7 +374,7 @@ class FakeAutoScalingGroup(CloudFormationModel):
self.autoscaling_backend = autoscaling_backend
self.ec2_backend = ec2_backend
self.name = name
- self._id = str(uuid4())
+ self._id = str(random.uuid4())
self.region = self.autoscaling_backend.region_name
self.account_id = self.autoscaling_backend.account_id
self.service_linked_role = f"arn:aws:iam::{self.account_id}:role/aws-service-role/autoscaling.amazonaws.com/AWSServiceRoleForAutoScaling"
diff --git a/moto/autoscaling/responses.py b/moto/autoscaling/responses.py
index e6e355111..924970565 100644
--- a/moto/autoscaling/responses.py
+++ b/moto/autoscaling/responses.py
@@ -1,11 +1,8 @@
import datetime
from moto.core.responses import BaseResponse
-from moto.core.utils import (
- amz_crc32,
- amzn_request_id,
- iso_8601_datetime_with_milliseconds,
-)
+from moto.core.utils import iso_8601_datetime_with_milliseconds
+from moto.utilities.aws_headers import amz_crc32, amzn_request_id
from .models import autoscaling_backends
diff --git a/moto/awslambda/models.py b/moto/awslambda/models.py
index 11740ae54..dd2318c97 100644
--- a/moto/awslambda/models.py
+++ b/moto/awslambda/models.py
@@ -16,7 +16,6 @@ import os
import json
import re
import zipfile
-import uuid
import tarfile
import calendar
import threading
@@ -26,11 +25,12 @@ import requests.exceptions
from moto.awslambda.policy import Policy
from moto.core import BaseBackend, BaseModel, CloudFormationModel
from moto.core.exceptions import RESTError
+from moto.core.utils import unix_time_millis, BackendDict
from moto.iam.models import iam_backends
from moto.iam.exceptions import IAMNotFoundException
-from moto.core.utils import unix_time_millis, BackendDict
-from moto.s3.models import s3_backends
from moto.logs.models import logs_backends
+from moto.moto_api._internal import mock_random as random
+from moto.s3.models import s3_backends
from moto.s3.exceptions import MissingBucket, MissingKey
from moto import settings
from .exceptions import (
@@ -54,7 +54,6 @@ from moto.dynamodb import dynamodb_backends
from moto.dynamodbstreams import dynamodbstreams_backends
from moto.utilities.docker_utilities import DockerModel, parse_image_ref
from tempfile import TemporaryDirectory
-from uuid import uuid4
logger = logging.getLogger(__name__)
@@ -335,7 +334,7 @@ class LambdaAlias(BaseModel):
self.function_version = function_version
self.description = description
self.routing_config = routing_config
- self.revision_id = str(uuid4())
+ self.revision_id = str(random.uuid4())
def update(self, description, function_version, routing_config):
if description is not None:
@@ -439,7 +438,7 @@ class LambdaFunction(CloudFormationModel, DockerModel):
) = _zipfile_content(self.code["ZipFile"])
# TODO: we should be putting this in a lambda bucket
- self.code["UUID"] = str(uuid.uuid4())
+ self.code["UUID"] = str(random.uuid4())
self.code["S3Key"] = "{}-{}".format(self.function_name, self.code["UUID"])
elif "S3Bucket" in self.code:
key = _validate_s3_bucket_and_key(self.account_id, data=self.code)
@@ -610,7 +609,7 @@ class LambdaFunction(CloudFormationModel, DockerModel):
) = _zipfile_content(updated_spec["ZipFile"])
# TODO: we should be putting this in a lambda bucket
- self.code["UUID"] = str(uuid.uuid4())
+ self.code["UUID"] = str(random.uuid4())
self.code["S3Key"] = "{}-{}".format(self.function_name, self.code["UUID"])
elif "S3Bucket" in updated_spec and "S3Key" in updated_spec:
key = None
@@ -757,7 +756,7 @@ class LambdaFunction(CloudFormationModel, DockerModel):
def save_logs(self, output):
# Send output to "logs" backend
- invoke_id = uuid.uuid4().hex
+ invoke_id = random.uuid4().hex
log_stream_name = (
"{date.year}/{date.month:02d}/{date.day:02d}/[{version}]{invoke_id}".format(
date=datetime.datetime.utcnow(),
@@ -935,7 +934,7 @@ class FunctionUrlConfig:
def __init__(self, function: LambdaFunction, config):
self.function = function
self.config = config
- self.url = f"https://{uuid.uuid4().hex}.lambda-url.{function.region}.on.aws"
+ self.url = f"https://{random.uuid4().hex}.lambda-url.{function.region}.on.aws"
self.created = datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S")
self.last_modified = self.created
@@ -970,7 +969,7 @@ class EventSourceMapping(CloudFormationModel):
self.starting_position_timestamp = spec.get("StartingPositionTimestamp", None)
self.function_arn = spec["FunctionArn"]
- self.uuid = str(uuid.uuid4())
+ self.uuid = str(random.uuid4())
self.last_modified = time.mktime(datetime.datetime.utcnow().timetuple())
def _get_service_source_from_arn(self, event_source_arn):
diff --git a/moto/awslambda/policy.py b/moto/awslambda/policy.py
index c17aa8c9f..17eabb4b6 100644
--- a/moto/awslambda/policy.py
+++ b/moto/awslambda/policy.py
@@ -1,15 +1,15 @@
import json
-import uuid
from moto.awslambda.exceptions import (
PreconditionFailedException,
UnknownPolicyException,
)
+from moto.moto_api._internal import mock_random
class Policy:
def __init__(self, parent):
- self.revision = str(uuid.uuid4())
+ self.revision = str(mock_random.uuid4())
self.statements = []
self.parent = parent
@@ -45,7 +45,7 @@ class Policy:
policy.statements[0]["Resource"] + ":" + qualifier
)
self.statements.append(policy.statements[0])
- self.revision = str(uuid.uuid4())
+ self.revision = str(mock_random.uuid4())
# removes the statement that matches 'sid' from the policy
def del_statement(self, sid, revision=""):
@@ -73,7 +73,7 @@ class Policy:
# set some default values if these keys are not set
self.ensure_set(obj, "Effect", "Allow")
self.ensure_set(obj, "Resource", self.parent.function_arn + ":$LATEST")
- self.ensure_set(obj, "StatementId", str(uuid.uuid4()))
+ self.ensure_set(obj, "StatementId", str(mock_random.uuid4()))
# transform field names and values
self.transform_property(obj, "StatementId", "Sid", self.nop_formatter)
diff --git a/moto/awslambda/responses.py b/moto/awslambda/responses.py
index e64c1c9dd..94588b615 100644
--- a/moto/awslambda/responses.py
+++ b/moto/awslambda/responses.py
@@ -3,7 +3,8 @@ import sys
from urllib.parse import unquote
-from moto.core.utils import amz_crc32, amzn_request_id, path_url
+from moto.core.utils import path_url
+from moto.utilities.aws_headers import amz_crc32, amzn_request_id
from moto.core.responses import BaseResponse
from .models import lambda_backends
diff --git a/moto/batch/models.py b/moto/batch/models.py
index 0af0677b1..6e58161d8 100644
--- a/moto/batch/models.py
+++ b/moto/batch/models.py
@@ -3,7 +3,6 @@ from itertools import cycle
from time import sleep
import datetime
import time
-import uuid
import logging
import threading
import dateutil.parser
@@ -29,6 +28,7 @@ from moto.ec2.models.instance_types import INSTANCE_FAMILIES as EC2_INSTANCE_FAM
from moto.iam.exceptions import IAMNotFoundException
from moto.core.utils import unix_time_millis, BackendDict
from moto.moto_api import state_manager
+from moto.moto_api._internal import mock_random
from moto.moto_api._internal.managed_state_model import ManagedState
from moto.utilities.docker_utilities import DockerModel
from moto import settings
@@ -444,7 +444,7 @@ class Job(threading.Thread, BaseModel, DockerModel, ManagedState):
)
self.job_name = name
- self.job_id = str(uuid.uuid4())
+ self.job_id = str(mock_random.uuid4())
self.job_definition = job_def
self.container_overrides = container_overrides or {}
self.job_queue = job_queue
@@ -1110,7 +1110,7 @@ class BatchBackend(BaseBackend):
# Create ECS cluster
# Should be of format P2OnDemand_Batch_UUID
- cluster_name = "OnDemand_Batch_" + str(uuid.uuid4())
+ cluster_name = "OnDemand_Batch_" + str(mock_random.uuid4())
ecs_cluster = self.ecs_backend.create_cluster(cluster_name)
new_comp_env.set_ecs(ecs_cluster.arn, cluster_name)
diff --git a/moto/ce/models.py b/moto/ce/models.py
index beee9c424..77666d464 100644
--- a/moto/ce/models.py
+++ b/moto/ce/models.py
@@ -3,7 +3,7 @@
from .exceptions import CostCategoryNotFound
from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict
-from uuid import uuid4
+from moto.moto_api._internal import mock_random
class CostCategoryDefinition(BaseModel):
@@ -15,7 +15,7 @@ class CostCategoryDefinition(BaseModel):
self.rules = rules
self.default_value = default_value
self.split_charge_rules = split_charge_rules
- self.arn = f"arn:aws:ce::{account_id}:costcategory/{str(uuid4())}"
+ self.arn = f"arn:aws:ce::{account_id}:costcategory/{str(mock_random.uuid4())}"
def update(self, rule_version, rules, default_value, split_charge_rules):
self.rule_version = rule_version
diff --git a/moto/cloudformation/custom_model.py b/moto/cloudformation/custom_model.py
index 2b888b088..b101bb7d2 100644
--- a/moto/cloudformation/custom_model.py
+++ b/moto/cloudformation/custom_model.py
@@ -4,7 +4,7 @@ import threading
from moto import settings
from moto.core import CloudFormationModel
from moto.awslambda import lambda_backends
-from uuid import uuid4
+from moto.moto_api._internal import mock_random
class CustomModel(CloudFormationModel):
@@ -44,7 +44,7 @@ class CustomModel(CloudFormationModel):
backend = lambda_backends[account_id][region_name]
fn = backend.get_function(service_token)
- request_id = str(uuid4())
+ request_id = str(mock_random.uuid4())
custom_resource = CustomModel(
region_name, request_id, logical_id, resource_name
diff --git a/moto/cloudformation/models.py b/moto/cloudformation/models.py
index 53f769891..9a65d789d 100644
--- a/moto/cloudformation/models.py
+++ b/moto/cloudformation/models.py
@@ -1,7 +1,6 @@
from datetime import datetime, timedelta
import json
import yaml
-import uuid
from collections import OrderedDict
from yaml.parser import ParserError # pylint:disable=c-extension-no-member
@@ -13,6 +12,7 @@ from moto.core.utils import (
iso_8601_datetime_without_milliseconds,
BackendDict,
)
+from moto.moto_api._internal import mock_random
from moto.sns.models import sns_backends
from .parsing import ResourceMap, OutputMap
@@ -103,7 +103,7 @@ class FakeStackSet(BaseModel):
operation_id=None,
):
if not operation_id:
- operation_id = uuid.uuid4()
+ operation_id = mock_random.uuid4()
self.template = template if template else self.template
self.description = description if description is not None else self.description
@@ -126,7 +126,7 @@ class FakeStackSet(BaseModel):
def create_stack_instances(self, accounts, regions, parameters, operation_id=None):
if not operation_id:
- operation_id = uuid.uuid4()
+ operation_id = mock_random.uuid4()
if not parameters:
parameters = self.parameters
@@ -141,7 +141,7 @@ class FakeStackSet(BaseModel):
def delete_stack_instances(self, accounts, regions, operation_id=None):
if not operation_id:
- operation_id = uuid.uuid4()
+ operation_id = mock_random.uuid4()
self.instances.delete(accounts, regions)
@@ -156,7 +156,7 @@ class FakeStackSet(BaseModel):
def update_instances(self, accounts, regions, parameters, operation_id=None):
if not operation_id:
- operation_id = uuid.uuid4()
+ operation_id = mock_random.uuid4()
self.instances.update(accounts, regions, parameters)
operation = self._create_operation(
@@ -488,7 +488,7 @@ class FakeEvent(BaseModel):
self.resource_status_reason = resource_status_reason
self.resource_properties = resource_properties
self.timestamp = datetime.utcnow()
- self.event_id = uuid.uuid4()
+ self.event_id = mock_random.uuid4()
self.client_request_token = client_request_token
def sendToSns(self, account_id, region, sns_topic_arns):
diff --git a/moto/cloudformation/responses.py b/moto/cloudformation/responses.py
index 1bb19baf8..9edc88e04 100644
--- a/moto/cloudformation/responses.py
+++ b/moto/cloudformation/responses.py
@@ -5,9 +5,9 @@ from yaml.parser import ParserError # pylint:disable=c-extension-no-member
from yaml.scanner import ScannerError # pylint:disable=c-extension-no-member
from moto.core.responses import BaseResponse
-from moto.core.utils import amzn_request_id
from moto.s3.models import s3_backends
from moto.s3.exceptions import S3ClientError
+from moto.utilities.aws_headers import amzn_request_id
from .models import cloudformation_backends
from .exceptions import ValidationError, MissingParameterError
from .utils import yaml_tag_constructor
diff --git a/moto/cloudformation/utils.py b/moto/cloudformation/utils.py
index e31273063..5ddfb073e 100644
--- a/moto/cloudformation/utils.py
+++ b/moto/cloudformation/utils.py
@@ -1,22 +1,21 @@
-import uuid
-import random
import yaml
import os
import string
+from moto.moto_api._internal import mock_random as random
def generate_stack_id(stack_name, region, account):
- random_id = uuid.uuid4()
+ random_id = random.uuid4()
return f"arn:aws:cloudformation:{region}:{account}:stack/{stack_name}/{random_id}"
def generate_changeset_id(changeset_name, region_name, account_id):
- random_id = uuid.uuid4()
+ random_id = random.uuid4()
return f"arn:aws:cloudformation:{region_name}:{account_id}:changeSet/{changeset_name}/{random_id}"
def generate_stackset_id(stackset_name):
- random_id = uuid.uuid4()
+ random_id = random.uuid4()
return "{}:{}".format(stackset_name, random_id)
diff --git a/moto/cloudfront/models.py b/moto/cloudfront/models.py
index d4cc7f682..58b738b3d 100644
--- a/moto/cloudfront/models.py
+++ b/moto/cloudfront/models.py
@@ -1,4 +1,3 @@
-import random
import string
from datetime import datetime
@@ -6,8 +5,8 @@ from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict, iso_8601_datetime_with_milliseconds
from moto.moto_api import state_manager
from moto.moto_api._internal.managed_state_model import ManagedState
+from moto.moto_api._internal import mock_random as random
from moto.utilities.tagging_service import TaggingService
-from uuid import uuid4
from .exceptions import (
OriginDoesNotExist,
@@ -153,7 +152,7 @@ class DistributionConfig:
self.enabled = config.get("Enabled") or False
self.viewer_certificate = ViewerCertificate()
self.geo_restriction = GeoRestrictions(config.get("Restrictions") or {})
- self.caller_reference = config.get("CallerReference", str(uuid4()))
+ self.caller_reference = config.get("CallerReference", str(random.uuid4()))
self.origins = config["Origins"]["Items"]["Origin"]
if not isinstance(self.origins, list):
self.origins = [self.origins]
diff --git a/moto/cloudwatch/models.py b/moto/cloudwatch/models.py
index 0751b747c..189b55212 100644
--- a/moto/cloudwatch/models.py
+++ b/moto/cloudwatch/models.py
@@ -6,9 +6,9 @@ from moto.core.utils import (
iso_8601_datetime_with_nanoseconds,
BackendDict,
)
+from moto.moto_api._internal import mock_random
from datetime import datetime, timedelta
from dateutil.tz import tzutc
-from uuid import uuid4
from .exceptions import (
InvalidFormat,
@@ -678,7 +678,7 @@ class CloudWatchBackend(BaseBackend):
def _get_paginated(self, metrics):
if len(metrics) > 500:
- next_token = str(uuid4())
+ next_token = str(mock_random.uuid4())
self.paged_metric_data[next_token] = metrics[500:]
return next_token, metrics[0:500]
else:
diff --git a/moto/cloudwatch/responses.py b/moto/cloudwatch/responses.py
index 3f4061a82..e340a66e3 100644
--- a/moto/cloudwatch/responses.py
+++ b/moto/cloudwatch/responses.py
@@ -3,7 +3,7 @@ import json
from dateutil.parser import parse as dtparse
from moto.core.responses import BaseResponse
-from moto.core.utils import amzn_request_id
+from moto.utilities.aws_headers import amzn_request_id
from .models import cloudwatch_backends, MetricDataQuery, MetricStat, Metric, Dimension
from .exceptions import InvalidParameterCombination
diff --git a/moto/codebuild/models.py b/moto/codebuild/models.py
index 306483a98..2f4635267 100644
--- a/moto/codebuild/models.py
+++ b/moto/codebuild/models.py
@@ -1,10 +1,9 @@
from moto.core import BaseBackend, BaseModel
from moto.core.utils import iso_8601_datetime_with_milliseconds, BackendDict
+from moto.moto_api._internal import mock_random
from collections import defaultdict
-from random import randint
from dateutil import parser
import datetime
-import uuid
class CodeBuildProjectMetadata(BaseModel):
@@ -26,7 +25,7 @@ class CodeBuildProjectMetadata(BaseModel):
"arn"
] = f"arn:aws:codebuild:{region_name}:{account_id}:build/{build_id}"
- self.build_metadata["buildNumber"] = randint(1, 100)
+ self.build_metadata["buildNumber"] = mock_random.randint(1, 100)
self.build_metadata["startTime"] = current_date
self.build_metadata["currentPhase"] = "QUEUED"
self.build_metadata["buildStatus"] = "IN_PROGRESS"
@@ -168,7 +167,7 @@ class CodeBuildBackend(BaseBackend):
def start_build(self, project_name, source_version=None, artifact_override=None):
- build_id = "{0}:{1}".format(project_name, uuid.uuid4())
+ build_id = "{0}:{1}".format(project_name, mock_random.uuid4())
# construct a new build
self.build_metadata[project_name] = CodeBuildProjectMetadata(
@@ -215,7 +214,7 @@ class CodeBuildBackend(BaseBackend):
phase["phaseStatus"] = "SUCCEEDED"
phase["startTime"] = current_date
phase["endTime"] = current_date
- phase["durationInSeconds"] = randint(10, 100)
+ phase["durationInSeconds"] = mock_random.randint(10, 100)
phases.append(phase)
return phases
@@ -229,7 +228,7 @@ class CodeBuildBackend(BaseBackend):
build["phases"] = self._set_phases(build["phases"])
build["endTime"] = iso_8601_datetime_with_milliseconds(
parser.parse(build["startTime"])
- + datetime.timedelta(minutes=randint(1, 5))
+ + datetime.timedelta(minutes=mock_random.randint(1, 5))
)
build["currentPhase"] = "COMPLETED"
build["buildStatus"] = "SUCCEEDED"
@@ -264,7 +263,7 @@ class CodeBuildBackend(BaseBackend):
build["phases"] = self._set_phases(build["phases"])
build["endTime"] = iso_8601_datetime_with_milliseconds(
parser.parse(build["startTime"])
- + datetime.timedelta(minutes=randint(1, 5))
+ + datetime.timedelta(minutes=mock_random.randint(1, 5))
)
build["currentPhase"] = "COMPLETED"
build["buildStatus"] = "STOPPED"
diff --git a/moto/codecommit/models.py b/moto/codecommit/models.py
index 4a662666d..6da08bcd6 100644
--- a/moto/codecommit/models.py
+++ b/moto/codecommit/models.py
@@ -1,8 +1,8 @@
from moto.core import BaseBackend, BaseModel
from moto.core.utils import iso_8601_datetime_with_milliseconds, BackendDict
+from moto.moto_api._internal import mock_random
from datetime import datetime
from .exceptions import RepositoryDoesNotExistException, RepositoryNameExistsException
-import uuid
class CodeCommit(BaseModel):
@@ -23,7 +23,7 @@ class CodeCommit(BaseModel):
self.repository_metadata["creationDate"] = current_date
self.repository_metadata["lastModifiedDate"] = current_date
self.repository_metadata["repositoryDescription"] = repository_description
- self.repository_metadata["repositoryId"] = str(uuid.uuid4())
+ self.repository_metadata["repositoryId"] = str(mock_random.uuid4())
self.repository_metadata[
"Arn"
] = f"arn:aws:codecommit:{region}:{account_id}:{repository_name}"
diff --git a/moto/cognitoidentity/utils.py b/moto/cognitoidentity/utils.py
index 54016ad17..34a1798d1 100644
--- a/moto/cognitoidentity/utils.py
+++ b/moto/cognitoidentity/utils.py
@@ -1,5 +1,5 @@
-from uuid import uuid4
+from moto.moto_api._internal import mock_random
def get_random_identity_id(region):
- return "{0}:{1}".format(region, uuid4())
+ return "{0}:{1}".format(region, mock_random.uuid4())
diff --git a/moto/cognitoidp/models.py b/moto/cognitoidp/models.py
index 577c347b2..d49965e98 100644
--- a/moto/cognitoidp/models.py
+++ b/moto/cognitoidp/models.py
@@ -3,13 +3,12 @@ import json
import os
import time
import typing
-import uuid
import enum
-import random
from jose import jws
from collections import OrderedDict
from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict
+from moto.moto_api._internal import mock_random as random
from .exceptions import (
GroupExistsException,
NotAuthorizedError,
@@ -562,7 +561,7 @@ class CognitoIdpUserPool(BaseModel):
return id_token, expires_in
def create_refresh_token(self, client_id, username):
- refresh_token = str(uuid.uuid4())
+ refresh_token = str(random.uuid4())
self.refresh_tokens[refresh_token] = (client_id, username)
return refresh_token
@@ -633,7 +632,7 @@ class CognitoIdpUserPoolDomain(BaseModel):
if extended:
return {
"UserPoolId": self.user_pool_id,
- "AWSAccountId": str(uuid.uuid4()),
+ "AWSAccountId": str(random.uuid4()),
"CloudFrontDistribution": distribution,
"Domain": self.domain,
"S3Bucket": None,
@@ -649,7 +648,7 @@ class CognitoIdpUserPoolClient(BaseModel):
def __init__(self, user_pool_id, generate_secret, extended_config):
self.user_pool_id = user_pool_id
self.id = create_id()
- self.secret = str(uuid.uuid4())
+ self.secret = str(random.uuid4())
self.generate_secret = generate_secret or False
self.extended_config = extended_config or {}
@@ -736,7 +735,7 @@ class CognitoIdpGroup(BaseModel):
class CognitoIdpUser(BaseModel):
def __init__(self, user_pool_id, username, password, status, attributes):
- self.id = str(uuid.uuid4())
+ self.id = str(random.uuid4())
self.user_pool_id = user_pool_id
# Username is None when users sign up with an email or phone_number,
# and should be given the value of the internal id generate (sub)
@@ -1289,7 +1288,7 @@ class CognitoIdpBackend(BaseBackend):
UserStatus.FORCE_CHANGE_PASSWORD,
UserStatus.RESET_REQUIRED,
]:
- session = str(uuid.uuid4())
+ session = str(random.uuid4())
self.sessions[session] = user_pool
return {
@@ -1635,15 +1634,15 @@ class CognitoIdpBackend(BaseBackend):
if user.status is UserStatus.UNCONFIRMED:
raise UserNotConfirmedException("User is not confirmed.")
- session = str(uuid.uuid4())
+ session = str(random.uuid4())
self.sessions[session] = user_pool
return {
"ChallengeName": "PASSWORD_VERIFIER",
"Session": session,
"ChallengeParameters": {
- "SALT": uuid.uuid4().hex,
- "SRP_B": uuid.uuid4().hex,
+ "SALT": random.uuid4().hex,
+ "SRP_B": random.uuid4().hex,
"USERNAME": user.username,
"USER_ID_FOR_SRP": user.id,
"SECRET_BLOCK": session,
@@ -1664,7 +1663,7 @@ class CognitoIdpBackend(BaseBackend):
if user.status is UserStatus.UNCONFIRMED:
raise UserNotConfirmedException("User is not confirmed.")
- session = str(uuid.uuid4())
+ session = str(random.uuid4())
self.sessions[session] = user_pool
if user.status is UserStatus.FORCE_CHANGE_PASSWORD:
@@ -1732,7 +1731,7 @@ class CognitoIdpBackend(BaseBackend):
_, username = user_pool.access_tokens[access_token]
self.admin_get_user(user_pool.id, username)
- return {"SecretCode": str(uuid.uuid4())}
+ return {"SecretCode": str(random.uuid4())}
raise NotAuthorizedError(access_token)
diff --git a/moto/cognitoidp/utils.py b/moto/cognitoidp/utils.py
index b4e7b0bb8..f1a594d27 100644
--- a/moto/cognitoidp/utils.py
+++ b/moto/cognitoidp/utils.py
@@ -1,10 +1,9 @@
-import random
import string
import hashlib
import hmac
import base64
import re
-import uuid
+from moto.moto_api._internal import mock_random as random
FORMATS = {
"email": r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b",
@@ -92,7 +91,7 @@ def generate_id(strategy, *args):
def _generate_id_uuid():
- return uuid.uuid4().hex
+ return random.uuid4().hex
def _generate_id_hash(args):
diff --git a/moto/config/models.py b/moto/config/models.py
index b5732db89..c516410c7 100644
--- a/moto/config/models.py
+++ b/moto/config/models.py
@@ -2,8 +2,6 @@
import json
import re
import time
-import random
-import string
from datetime import datetime
@@ -53,6 +51,7 @@ from moto.core import BaseBackend, BaseModel
from moto.core.responses import AWSServiceSpec
from moto.core.utils import BackendDict
from moto.iam.config import role_config_query, policy_config_query
+from moto.moto_api._internal import mock_random as random
from moto.s3.config import s3_config_query
from moto.s3control.config import s3_account_public_access_block_query
from moto.utilities.utils import load_resource
@@ -107,11 +106,7 @@ def snake_to_camels(original, cap_start, cap_arn):
def random_string():
"""Returns a random set of 8 lowercase letters for the Config Aggregator ARN"""
- chars = []
- for _ in range(0, 8):
- chars.append(random.choice(string.ascii_lowercase))
-
- return "".join(chars)
+ return random.get_random_string(length=8, include_digits=False, lower_case=True)
def validate_tag_key(tag_key, exception_param="tags.X.member.key"):
diff --git a/moto/core/base_backend.py b/moto/core/base_backend.py
index a6d3d97cb..6068dfd80 100644
--- a/moto/core/base_backend.py
+++ b/moto/core/base_backend.py
@@ -1,4 +1,3 @@
-import random
import re
import string
from collections import defaultdict
@@ -113,6 +112,8 @@ class BaseBackend:
@staticmethod
def vpce_random_number():
+ from moto.moto_api._internal import mock_random as random
+
"""Return random number for a VPC endpoint service ID."""
return "".join([random.choice(string.hexdigits.lower()) for i in range(17)])
diff --git a/moto/core/models.py b/moto/core/models.py
index 041ef717a..5179f2e90 100644
--- a/moto/core/models.py
+++ b/moto/core/models.py
@@ -21,7 +21,6 @@ from .custom_responses_mock import (
not_implemented_callback,
reset_responses_mock,
)
-from .utils import convert_flask_to_responses_response
DEFAULT_ACCOUNT_ID = "123456789012"
@@ -272,6 +271,9 @@ class BotocoreEventMockAWS(BaseMockAWS):
reset_responses_mock(responses_mock)
def enable_patching(self, reset=True): # pylint: disable=unused-argument
+ # Circumvent circular imports
+ from .utils import convert_flask_to_responses_response
+
botocore_stubber.enabled = True
for method in BOTOCORE_HTTP_METHODS:
for backend in self.backends_for_urls:
diff --git a/moto/core/utils.py b/moto/core/utils.py
index 0595fbf8a..cff0ad78d 100644
--- a/moto/core/utils.py
+++ b/moto/core/utils.py
@@ -1,11 +1,8 @@
-from functools import lru_cache, wraps
+from functools import lru_cache
-import binascii
import datetime
import inspect
-import random
import re
-import string
from botocore.exceptions import ClientError
from boto3 import Session
from moto.settings import allow_unknown_region
@@ -14,10 +11,6 @@ from urllib.parse import urlparse
from uuid import uuid4
-REQUEST_ID_LONG = string.digits + string.ascii_uppercase
-HEX_CHARS = list(range(10)) + ["a", "b", "c", "d", "e", "f"]
-
-
def camelcase_to_underscores(argument):
"""Converts a camelcase param like theNewAttribute to the equivalent
python underscore variable like the_new_attribute"""
@@ -75,20 +68,6 @@ def method_names_from_class(clazz):
return [x[0] for x in inspect.getmembers(clazz, predicate=predicate)]
-def get_random_hex(length=8):
- return "".join(str(random.choice(HEX_CHARS)) for _ in range(length))
-
-
-def get_random_message_id():
- return "{0}-{1}-{2}-{3}-{4}".format(
- get_random_hex(8),
- get_random_hex(4),
- get_random_hex(4),
- get_random_hex(4),
- get_random_hex(12),
- )
-
-
def convert_regex_to_flask_path(url_path):
"""
Converts a regex matching url to one that can be used with flask
@@ -206,86 +185,6 @@ def unix_time_millis(dt=None):
return unix_time(dt) * 1000.0
-def gen_amz_crc32(response, headerdict=None):
- if not isinstance(response, bytes):
- response = response.encode("utf-8")
-
- crc = binascii.crc32(response)
-
- if headerdict is not None and isinstance(headerdict, dict):
- headerdict.update({"x-amz-crc32": str(crc)})
-
- return crc
-
-
-def gen_amzn_requestid_long(headerdict=None):
- req_id = "".join([random.choice(REQUEST_ID_LONG) for _ in range(0, 52)])
-
- if headerdict is not None and isinstance(headerdict, dict):
- headerdict.update({"x-amzn-requestid": req_id})
-
- return req_id
-
-
-def amz_crc32(f):
- @wraps(f)
- def _wrapper(*args, **kwargs):
- response = f(*args, **kwargs)
-
- headers = {}
- status = 200
-
- if isinstance(response, str):
- body = response
- else:
- if len(response) == 2:
- body, new_headers = response
- status = new_headers.get("status", 200)
- else:
- status, new_headers, body = response
- headers.update(new_headers)
- # Cast status to string
- if "status" in headers:
- headers["status"] = str(headers["status"])
-
- gen_amz_crc32(body, headers)
-
- return status, headers, body
-
- return _wrapper
-
-
-def amzn_request_id(f):
- @wraps(f)
- def _wrapper(*args, **kwargs):
- response = f(*args, **kwargs)
-
- headers = {}
- status = 200
-
- if isinstance(response, str):
- body = response
- else:
- if len(response) == 2:
- body, new_headers = response
- status = new_headers.get("status", 200)
- else:
- status, new_headers, body = response
- headers.update(new_headers)
-
- request_id = gen_amzn_requestid_long(headers)
-
- # Update request ID in XML
- try:
- body = re.sub(r"(?<=).*(?=<\/RequestId>)", request_id, body)
- except Exception: # Will just ignore if it cant work
- pass
-
- return status, headers, body
-
- return _wrapper
-
-
def path_url(url):
parsed_url = urlparse(url)
path = parsed_url.path
diff --git a/moto/databrew/responses.py b/moto/databrew/responses.py
index 400ff3716..056380c0e 100644
--- a/moto/databrew/responses.py
+++ b/moto/databrew/responses.py
@@ -2,7 +2,7 @@ import json
from urllib.parse import urlparse
from moto.core.responses import BaseResponse
-from moto.core.utils import amzn_request_id
+from moto.utilities.aws_headers import amzn_request_id
from .models import databrew_backends
diff --git a/moto/datapipeline/utils.py b/moto/datapipeline/utils.py
index cb9c5e46c..0372c7b3e 100644
--- a/moto/datapipeline/utils.py
+++ b/moto/datapipeline/utils.py
@@ -1,9 +1,9 @@
import collections.abc as collections_abc
-from moto.core.utils import get_random_hex
+from moto.moto_api._internal import mock_random
def get_random_pipeline_id():
- return "df-{0}".format(get_random_hex(length=19))
+ return "df-{0}".format(mock_random.get_random_hex(length=19))
def remove_capitalization_of_dict_keys(obj):
diff --git a/moto/dax/models.py b/moto/dax/models.py
index e293a1993..2fbd9e21a 100644
--- a/moto/dax/models.py
+++ b/moto/dax/models.py
@@ -1,7 +1,8 @@
"""DAXBackend class with methods for supported APIs."""
from moto.core import BaseBackend, BaseModel
-from moto.core.utils import BackendDict, get_random_hex, unix_time
+from moto.core.utils import BackendDict, unix_time
from moto.moto_api import state_manager
+from moto.moto_api._internal import mock_random as random
from moto.moto_api._internal.managed_state_model import ManagedState
from moto.utilities.tagging_service import TaggingService
from moto.utilities.paginator import paginate
@@ -89,7 +90,7 @@ class DaxCluster(BaseModel, ManagedState):
self.arn = f"arn:aws:dax:{region}:{account_id}:cache/{self.name}"
self.node_type = node_type
self.replication_factor = replication_factor
- self.cluster_hex = get_random_hex(6)
+ self.cluster_hex = random.get_random_hex(6)
self.endpoint = DaxEndpoint(
name=name, cluster_hex=self.cluster_hex, region=region
)
@@ -99,7 +100,10 @@ class DaxCluster(BaseModel, ManagedState):
self.iam_role_arn = iam_role_arn
self.parameter_group = DaxParameterGroup()
self.security_groups = [
- {"SecurityGroupIdentifier": f"sg-{get_random_hex(10)}", "Status": "active"}
+ {
+ "SecurityGroupIdentifier": f"sg-{random.get_random_hex(10)}",
+ "Status": "active",
+ }
]
self.sse_specification = sse_specification
self.encryption_type = encryption_type
diff --git a/moto/ds/models.py b/moto/ds/models.py
index c4eb1a274..c555e4123 100644
--- a/moto/ds/models.py
+++ b/moto/ds/models.py
@@ -2,7 +2,7 @@
from datetime import datetime, timezone
from moto.core import BaseBackend, BaseModel
-from moto.core.utils import get_random_hex, BackendDict
+from moto.core.utils import BackendDict
from moto.ds.exceptions import (
ClientException,
DirectoryLimitExceededException,
@@ -16,6 +16,7 @@ from moto.ds.utils import PAGINATION_MODEL
from moto.ds.validations import validate_args
from moto.ec2.exceptions import InvalidSubnetIdError
from moto.ec2 import ec2_backends
+from moto.moto_api._internal import mock_random
from moto.utilities.paginator import paginate
from moto.utilities.tagging_service import TaggingService
@@ -71,7 +72,7 @@ class Directory(BaseModel): # pylint: disable=too-many-instance-attributes
self.edition = edition
# Calculated or default values for the directory attributes.
- self.directory_id = f"d-{get_random_hex(10)}"
+ self.directory_id = f"d-{mock_random.get_random_hex(10)}"
self.access_url = f"{self.directory_id}.awsapps.com"
self.alias = self.directory_id
self.desired_number_of_domain_controllers = 0
diff --git a/moto/dynamodb/models/__init__.py b/moto/dynamodb/models/__init__.py
index 8b23a1aeb..c0f5f4354 100644
--- a/moto/dynamodb/models/__init__.py
+++ b/moto/dynamodb/models/__init__.py
@@ -4,7 +4,6 @@ import datetime
import decimal
import json
import re
-import uuid
from collections import OrderedDict
from moto.core import BaseBackend, BaseModel, CloudFormationModel
@@ -40,6 +39,7 @@ from moto.dynamodb.parsing.executors import UpdateExpressionExecutor
from moto.dynamodb.parsing.expressions import UpdateExpressionParser
from moto.dynamodb.parsing.validators import UpdateExpressionValidator
from moto.dynamodb.limits import HASH_KEY_MAX_LENGTH, RANGE_KEY_MAX_LENGTH
+from moto.moto_api._internal import mock_random
class DynamoJsonEncoder(json.JSONEncoder):
@@ -222,7 +222,7 @@ class StreamRecord(BaseModel):
keys[table.range_key_attr] = rec.range_key.to_json()
self.record = {
- "eventID": uuid.uuid4().hex,
+ "eventID": mock_random.uuid4().hex,
"eventName": event_name,
"eventSource": "aws:dynamodb",
"eventVersion": "1.0",
@@ -1125,7 +1125,7 @@ class Backup(object):
def _make_identifier(self):
timestamp = int(unix_time_millis(self.creation_date_time))
timestamp_padded = str("0" + str(timestamp))[-16:16]
- guid = str(uuid.uuid4())
+ guid = str(mock_random.uuid4())
guid_shortened = guid[:8]
return "{}-{}".format(timestamp_padded, guid_shortened)
diff --git a/moto/dynamodb/responses.py b/moto/dynamodb/responses.py
index 3d6007b9a..38c506aa6 100644
--- a/moto/dynamodb/responses.py
+++ b/moto/dynamodb/responses.py
@@ -5,7 +5,7 @@ import itertools
from functools import wraps
from moto.core.responses import BaseResponse
-from moto.core.utils import camelcase_to_underscores, amz_crc32, amzn_request_id
+from moto.core.utils import camelcase_to_underscores
from moto.dynamodb.parsing.key_condition_expression import parse_expression
from moto.dynamodb.parsing.reserved_keywords import ReservedKeywords
from .exceptions import (
@@ -14,6 +14,7 @@ from .exceptions import (
ConditionalCheckFailed,
)
from moto.dynamodb.models import dynamodb_backends, dynamo_json_dump
+from moto.utilities.aws_headers import amz_crc32, amzn_request_id
TRANSACTION_MAX_ITEMS = 25
diff --git a/moto/ebs/models.py b/moto/ebs/models.py
index df342ef5f..aa0883294 100644
--- a/moto/ebs/models.py
+++ b/moto/ebs/models.py
@@ -4,7 +4,7 @@ from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict, unix_time
from moto.ec2 import ec2_backends
from moto.ec2.models.elastic_block_store import Snapshot
-from uuid import uuid4
+from moto.moto_api._internal import mock_random
class Block(BaseModel):
@@ -13,7 +13,7 @@ class Block(BaseModel):
self.checksum = checksum
self.checksum_algorithm = checksum_algorithm
self.data_length = data_length
- self.block_token = str(uuid4())
+ self.block_token = str(mock_random.uuid4())
class EBSSnapshot(BaseModel):
diff --git a/moto/ec2/models/vpc_service_configuration.py b/moto/ec2/models/vpc_service_configuration.py
index e679d7760..a7c760e70 100644
--- a/moto/ec2/models/vpc_service_configuration.py
+++ b/moto/ec2/models/vpc_service_configuration.py
@@ -1,5 +1,5 @@
from moto.core import CloudFormationModel
-from moto.core.utils import get_random_hex
+from moto.moto_api._internal import mock_random
from .core import TaggedEC2Resource
from ..exceptions import UnknownVpcEndpointService
@@ -8,7 +8,7 @@ class VPCServiceConfiguration(TaggedEC2Resource, CloudFormationModel):
def __init__(
self, load_balancers, region, acceptance_required, private_dns_name, ec2_backend
):
- self.id = f"vpce-svc-{get_random_hex(length=8)}"
+ self.id = f"vpce-svc-{mock_random.get_random_hex(length=8)}"
self.service_name = f"com.amazonaws.vpce.{region}.{self.id}"
self.service_state = "Available"
diff --git a/moto/ec2/responses/launch_templates.py b/moto/ec2/responses/launch_templates.py
index 92cfe7cf4..7a35affd1 100644
--- a/moto/ec2/responses/launch_templates.py
+++ b/moto/ec2/responses/launch_templates.py
@@ -1,5 +1,5 @@
-import uuid
from moto.ec2.exceptions import FilterNotImplementedError
+from moto.moto_api._internal import mock_random
from ._base_response import EC2BaseResponse
from xml.etree import ElementTree
@@ -10,7 +10,7 @@ def xml_root(name):
root = ElementTree.Element(
name, {"xmlns": "http://ec2.amazonaws.com/doc/2016-11-15/"}
)
- request_id = str(uuid.uuid4()) + "example"
+ request_id = str(mock_random.uuid4()) + "example"
ElementTree.SubElement(root, "requestId").text = request_id
return root
diff --git a/moto/ec2/responses/subnets.py b/moto/ec2/responses/subnets.py
index a82149768..34f318f9a 100644
--- a/moto/ec2/responses/subnets.py
+++ b/moto/ec2/responses/subnets.py
@@ -1,5 +1,5 @@
-import random
from moto.core.utils import camelcase_to_underscores
+from moto.moto_api._internal import mock_random as random
from ._base_response import EC2BaseResponse
diff --git a/moto/ec2/utils.py b/moto/ec2/utils.py
index 1c080b34f..74e180b50 100644
--- a/moto/ec2/utils.py
+++ b/moto/ec2/utils.py
@@ -1,6 +1,5 @@
import base64
import fnmatch
-import random
import re
import ipaddress
@@ -10,6 +9,7 @@ from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
from moto.iam import iam_backends
+from moto.moto_api._internal import mock_random as random
from moto.utilities.utils import md5_hash
EC2_RESOURCE_TO_PREFIX = {
diff --git a/moto/ecr/models.py b/moto/ecr/models.py
index ec7678074..51056842d 100644
--- a/moto/ecr/models.py
+++ b/moto/ecr/models.py
@@ -1,10 +1,8 @@
import hashlib
import json
import re
-import uuid
from collections import namedtuple
from datetime import datetime, timezone
-from random import random
from typing import Dict, List
from botocore.exceptions import ParamValidationError
@@ -27,6 +25,7 @@ from moto.ecr.exceptions import (
from moto.ecr.policy_validation import EcrLifecyclePolicyValidator
from moto.iam.exceptions import MalformedPolicyDocument
from moto.iam.policy_validation import IAMPolicyDocumentValidator
+from moto.moto_api._internal import mock_random as random
from moto.utilities.tagging_service import TaggingService
ECR_REPOSITORY_ARN_PATTERN = "^arn:(?P[^:]+):ecr:(?P[^:]+):(?P[^:]+):repository/(?P.*)$"
@@ -97,7 +96,7 @@ class Repository(BaseObject, CloudFormationModel):
if encryption_config == {"encryptionType": "KMS"}:
encryption_config[
"kmsKey"
- ] = f"arn:aws:kms:{self.region_name}:{self.account_id}:key/{uuid.uuid4()}"
+ ] = f"arn:aws:kms:{self.region_name}:{self.account_id}:key/{random.uuid4()}"
return encryption_config
def _get_image(self, image_tag, image_digest):
@@ -250,7 +249,7 @@ class Image(BaseObject):
self.last_scan = None
def _create_digest(self):
- image_contents = "docker_image{0}".format(int(random() * 10**6))
+ image_contents = "docker_image{0}".format(int(random.random() * 10**6))
self.image_digest = (
"sha256:%s" % hashlib.sha256(image_contents.encode("utf-8")).hexdigest()
)
diff --git a/moto/ecs/models.py b/moto/ecs/models.py
index 1b53cd14b..cb4f4140f 100644
--- a/moto/ecs/models.py
+++ b/moto/ecs/models.py
@@ -1,8 +1,6 @@
import re
-import uuid
from copy import copy
from datetime import datetime
-from random import random, randint
import pytz
@@ -16,6 +14,7 @@ from moto.core.utils import (
BackendDict,
)
from moto.ec2 import ec2_backends
+from moto.moto_api._internal import mock_random
from moto.utilities.tagging_service import TaggingService
from .exceptions import (
EcsClientException,
@@ -243,7 +242,7 @@ class TaskDefinition(BaseObject, CloudFormationModel):
properties = cloudformation_json["Properties"]
family = properties.get(
- "Family", "task-definition-{0}".format(int(random() * 10**6))
+ "Family", "task-definition-{0}".format(int(mock_random.random() * 10**6))
)
container_definitions = remap_nested_keys(
properties.get("ContainerDefinitions", []), pascal_to_camelcase
@@ -266,7 +265,7 @@ class TaskDefinition(BaseObject, CloudFormationModel):
):
properties = cloudformation_json["Properties"]
family = properties.get(
- "Family", "task-definition-{0}".format(int(random() * 10**6))
+ "Family", "task-definition-{0}".format(int(mock_random.random() * 10**6))
)
container_definitions = properties["ContainerDefinitions"]
volumes = properties.get("Volumes")
@@ -302,7 +301,7 @@ class Task(BaseObject):
started_by="",
tags=None,
):
- self.id = str(uuid.uuid4())
+ self.id = str(mock_random.uuid4())
self.cluster_name = cluster.name
self.cluster_arn = cluster.arn
self.container_instance_arn = container_instance_arn
@@ -335,7 +334,7 @@ class Task(BaseObject):
class CapacityProvider(BaseObject):
def __init__(self, account_id, region_name, name, asg_details, tags):
- self._id = str(uuid.uuid4())
+ self._id = str(mock_random.uuid4())
self.capacity_provider_arn = f"arn:aws:ecs:{region_name}:{account_id}:capacity_provider/{name}/{self._id}"
self.name = name
self.status = "ACTIVE"
@@ -391,7 +390,7 @@ class Service(BaseObject, CloudFormationModel):
{
"createdAt": datetime.now(pytz.utc),
"desiredCount": self.desired_count,
- "id": "ecs-svc/{}".format(randint(0, 32**12)),
+ "id": "ecs-svc/{}".format(mock_random.randint(0, 32**12)),
"launchType": self.launch_type,
"pendingCount": self.desired_count,
"runningCount": 0,
@@ -620,7 +619,7 @@ class ContainerInstance(BaseObject):
}
self.registered_at = datetime.now(pytz.utc)
self.region_name = region_name
- self.id = str(uuid.uuid4())
+ self.id = str(mock_random.uuid4())
self.cluster_name = cluster_name
self._account_id = backend.account_id
self._backend = backend
@@ -718,7 +717,7 @@ class TaskSet(BaseObject):
self.createdAt = datetime.now(pytz.utc)
self.updatedAt = datetime.now(pytz.utc)
self.stabilityStatusAt = datetime.now(pytz.utc)
- self.id = "ecs-svc/{}".format(randint(0, 32**12))
+ self.id = "ecs-svc/{}".format(mock_random.randint(0, 32**12))
self.service_arn = ""
self.cluster_arn = ""
diff --git a/moto/efs/models.py b/moto/efs/models.py
index 3fc04ff51..f1d170ce5 100644
--- a/moto/efs/models.py
+++ b/moto/efs/models.py
@@ -11,7 +11,6 @@ from copy import deepcopy
from moto.core import BaseBackend, BaseModel, CloudFormationModel
from moto.core.utils import (
camelcase_to_underscores,
- get_random_hex,
underscores_to_camelcase,
BackendDict,
)
@@ -30,6 +29,7 @@ from moto.efs.exceptions import (
SecurityGroupNotFound,
SecurityGroupLimitExceeded,
)
+from moto.moto_api._internal import mock_random
from moto.utilities.tagging_service import TaggingService
from moto.utilities.utils import md5_hash
@@ -54,7 +54,7 @@ class AccessPoint(BaseModel):
root_directory,
context,
):
- self.access_point_id = get_random_hex(8)
+ self.access_point_id = mock_random.get_random_hex(8)
self.access_point_arn = f"arn:aws:elasticfilesystem:{region_name}:{account_id}:access-point/fsap-{self.access_point_id}"
self.client_token = client_token
self.file_system_id = file_system_id
@@ -297,7 +297,7 @@ class MountTarget(CloudFormationModel):
# Init non-user-assigned values.
self.owner_id = account_id
- self.mount_target_id = "fsmt-{}".format(get_random_hex())
+ self.mount_target_id = "fsmt-{}".format(mock_random.get_random_hex())
self.life_cycle_state = "available"
self.network_interface_id = None
self.availability_zone_id = subnet.availability_zone_id
@@ -418,7 +418,7 @@ class EFSBackend(BaseBackend):
# Create a new file system ID:
def make_id():
- return "fs-{}".format(get_random_hex())
+ return "fs-{}".format(mock_random.get_random_hex())
fsid = make_id()
while fsid in self.file_systems_by_id:
diff --git a/moto/eks/models.py b/moto/eks/models.py
index 9b58aab70..d9e842f58 100644
--- a/moto/eks/models.py
+++ b/moto/eks/models.py
@@ -1,10 +1,9 @@
from datetime import datetime
-from uuid import uuid4
from moto.core import BaseBackend
from moto.core.utils import iso_8601_datetime_without_milliseconds, BackendDict
+from moto.moto_api._internal import mock_random as random
-from ..utilities.utils import random_string
from .exceptions import (
InvalidParameterException,
InvalidRequestException,
@@ -17,12 +16,14 @@ from .utils import get_partition, validate_role_arn
CLUSTER_ARN_TEMPLATE = "arn:{partition}:eks:{region}:{account_id}:cluster/{name}"
FARGATE_PROFILE_ARN_TEMPLATE = "arn:{partition}:eks:{region}:{account_id}:fargateprofile/{cluster_name}/{fargate_profile_name}/{uuid}"
NODEGROUP_ARN_TEMPLATE = "arn:{partition}:eks:{region}:{account_id}:nodegroup/{cluster_name}/{nodegroup_name}/{uuid}"
-ISSUER_TEMPLATE = "https://oidc.eks.{region}.amazonaws.com/id/" + random_string(10)
+ISSUER_TEMPLATE = (
+ "https://oidc.eks.{region}.amazonaws.com/id/" + random.get_random_string(length=10)
+)
ENDPOINT_TEMPLATE = (
"https://"
- + random_string()
+ + random.get_random_string()
+ "."
- + random_string(3)
+ + random.get_random_string(3)
+ ".{region}.eks.amazonaws.com/"
)
@@ -120,7 +121,7 @@ class Cluster:
region=region_name,
name=name,
)
- self.certificateAuthority = {"data": random_string(1400)}
+ self.certificateAuthority = {"data": random.get_random_string(1400)}
self.creation_date = iso_8601_datetime_without_milliseconds(datetime.now())
self.identity = {"oidc": {"issuer": ISSUER_TEMPLATE.format(region=region_name)}}
self.endpoint = ENDPOINT_TEMPLATE.format(region=region_name)
@@ -182,7 +183,7 @@ class FargateProfile:
tags = dict()
self.created_at = iso_8601_datetime_without_milliseconds(datetime.now())
- self.uuid = str(uuid4())
+ self.uuid = str(random.uuid4())
self.fargate_profile_arn = FARGATE_PROFILE_ARN_TEMPLATE.format(
partition=aws_partition,
account_id=account_id,
@@ -244,7 +245,7 @@ class ManagedNodegroup:
if taints is None:
taints = dict()
- self.uuid = str(uuid4())
+ self.uuid = str(random.uuid4())
self.arn = NODEGROUP_ARN_TEMPLATE.format(
partition=aws_partition,
account_id=account_id,
@@ -258,7 +259,7 @@ class ManagedNodegroup:
self.health = DEFAULT_NODEGROUP_HEALTH
self.resources = {
"autoScalingGroups": [{"name": "eks-" + self.uuid}],
- "remoteAccessSecurityGroup": "sg-" + random_string(17).lower(),
+ "remoteAccessSecurityGroup": "sg-" + random.get_random_string(17).lower(),
}
self.ami_type = ami_type or DEFAULT_AMI_TYPE
diff --git a/moto/elastictranscoder/models.py b/moto/elastictranscoder/models.py
index 01ab2d740..f0aadd1f1 100644
--- a/moto/elastictranscoder/models.py
+++ b/moto/elastictranscoder/models.py
@@ -1,6 +1,6 @@
from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict
-import random
+from moto.moto_api._internal import mock_random as random
import string
diff --git a/moto/elb/models.py b/moto/elb/models.py
index f5487860d..1b9810c29 100644
--- a/moto/elb/models.py
+++ b/moto/elb/models.py
@@ -7,7 +7,7 @@ from moto.core import BaseBackend, BaseModel, CloudFormationModel
from moto.core.utils import BackendDict
from moto.ec2.models import ec2_backends
from moto.ec2.exceptions import InvalidInstanceIdError
-from uuid import uuid4
+from moto.moto_api._internal import mock_random
from .exceptions import (
BadHealthCheckDefinition,
DuplicateLoadBalancerName,
@@ -306,7 +306,7 @@ class ELBBackend(BaseBackend):
raise EmptyListenersError()
if not security_groups:
sg = ec2_backend.create_security_group(
- name=f"default_elb_{uuid4()}",
+ name=f"default_elb_{mock_random.uuid4()}",
description="ELB created security group used when no security group is specified during ELB creation - modifications could impact traffic to future ELBs",
vpc_id=vpc_id,
)
diff --git a/moto/elbv2/models.py b/moto/elbv2/models.py
index 2b30c3fa8..ad0a92157 100644
--- a/moto/elbv2/models.py
+++ b/moto/elbv2/models.py
@@ -7,10 +7,10 @@ from moto.core.exceptions import RESTError
from moto.core import BaseBackend, BaseModel, CloudFormationModel
from moto.core.utils import (
iso_8601_datetime_with_milliseconds,
- get_random_hex,
BackendDict,
)
from moto.ec2.models import ec2_backends
+from moto.moto_api._internal import mock_random
from moto.utilities.tagging_service import TaggingService
from .utils import make_arn_for_target_group
from .utils import make_arn_for_load_balancer
@@ -757,7 +757,7 @@ class ELBv2Backend(BaseBackend):
self._validate_actions(actions)
arn = listener_arn.replace(":listener/", ":listener-rule/")
- arn += "/%s" % (get_random_hex(16))
+ arn += f"/{mock_random.get_random_hex(16)}"
# TODO: check for error 'TooManyRegistrationsForTargetId'
# TODO: check for error 'TooManyRules'
diff --git a/moto/elbv2/responses.py b/moto/elbv2/responses.py
index c03b23395..1ade5f956 100644
--- a/moto/elbv2/responses.py
+++ b/moto/elbv2/responses.py
@@ -1,6 +1,6 @@
from moto.core.exceptions import RESTError
-from moto.core.utils import amzn_request_id
from moto.core.responses import BaseResponse
+from moto.utilities.aws_headers import amzn_request_id
from .models import elbv2_backends
from .exceptions import TargetGroupNotFoundError
from .exceptions import ListenerOrBalancerMissingError
diff --git a/moto/emr/utils.py b/moto/emr/utils.py
index b0746ece5..b9af693d0 100644
--- a/moto/emr/utils.py
+++ b/moto/emr/utils.py
@@ -1,12 +1,12 @@
import copy
import datetime
-import random
import re
import string
from moto.core.utils import (
camelcase_to_underscores,
iso_8601_datetime_with_milliseconds,
)
+from moto.moto_api._internal import mock_random as random
def random_id(size=13):
diff --git a/moto/emrcontainers/utils.py b/moto/emrcontainers/utils.py
index 07276318a..09c3cc600 100644
--- a/moto/emrcontainers/utils.py
+++ b/moto/emrcontainers/utils.py
@@ -1,6 +1,6 @@
# import json
import string
-import random
+from moto.moto_api._internal import mock_random as random
def get_partition(region):
diff --git a/moto/emrserverless/utils.py b/moto/emrserverless/utils.py
index 51f3839b5..afa8153aa 100644
--- a/moto/emrserverless/utils.py
+++ b/moto/emrserverless/utils.py
@@ -1,5 +1,4 @@
-# import json
-import random
+from moto.moto_api._internal import mock_random as random
import string
diff --git a/moto/es/models.py b/moto/es/models.py
index a790638a2..c7dbd5236 100644
--- a/moto/es/models.py
+++ b/moto/es/models.py
@@ -1,5 +1,6 @@
from moto.core import BaseBackend, BaseModel
-from moto.core.utils import get_random_hex, BackendDict
+from moto.core.utils import BackendDict
+from moto.moto_api._internal import mock_random
from .exceptions import DomainNotFound
@@ -23,7 +24,7 @@ class Domain(BaseModel):
advanced_security_options,
auto_tune_options,
):
- self.domain_id = get_random_hex(8)
+ self.domain_id = mock_random.get_random_hex(8)
self.region_name = region_name
self.domain_name = domain_name
self.es_version = es_version
diff --git a/moto/events/models.py b/moto/events/models.py
index 8fade1e07..77ec21f9a 100644
--- a/moto/events/models.py
+++ b/moto/events/models.py
@@ -26,11 +26,10 @@ from moto.events.exceptions import (
InvalidEventPatternException,
IllegalStatusException,
)
+from moto.moto_api._internal import mock_random as random
from moto.utilities.paginator import paginate
from moto.utilities.tagging_service import TaggingService
-from uuid import uuid4
-
from .utils import PAGINATION_MODEL
# Sentinel to signal the absence of a field for `Exists` pattern matching
@@ -183,12 +182,9 @@ class Rule(CloudFormationModel):
datetime.utcfromtimestamp(event_copy["time"])
)
- log_stream_name = str(uuid4())
+ log_stream_name = str(random.uuid4())
log_events = [
- {
- "timestamp": unix_time_millis(datetime.utcnow()),
- "message": json.dumps(event_copy),
- }
+ {"timestamp": unix_time_millis(), "message": json.dumps(event_copy)}
]
log_backend = logs_backends[self.account_id][self.region_name]
@@ -521,7 +517,7 @@ class Archive(CloudFormationModel):
self.arn = f"arn:aws:events:{region_name}:{account_id}:archive/{name}"
self.creation_time = unix_time(datetime.utcnow())
self.state = "ENABLED"
- self.uuid = str(uuid4())
+ self.uuid = str(random.uuid4())
self.events = []
self.event_bus_name = source_arn.split("/")[-1]
@@ -691,7 +687,9 @@ class Replay(BaseModel):
for rule in event_backend.rules.values():
rule.send_to_targets(
event_bus_name,
- dict(event, **{"id": str(uuid4()), "replay-name": self.name}),
+ dict(
+ event, **{"id": str(random.uuid4()), "replay-name": self.name}
+ ),
)
self.state = ReplayState.COMPLETED
@@ -708,7 +706,7 @@ class Connection(BaseModel):
authorization_type,
auth_parameters,
):
- self.uuid = uuid4()
+ self.uuid = random.uuid4()
self.name = name
self.region = region_name
self.description = description
@@ -784,7 +782,7 @@ class Destination(BaseModel):
invocation_rate_limit_per_second,
http_method,
):
- self.uuid = uuid4()
+ self.uuid = random.uuid4()
self.name = name
self.region = region_name
self.description = description
@@ -1234,7 +1232,7 @@ class EventsBackend(BaseBackend):
)
continue
- event_id = str(uuid4())
+ event_id = str(random.uuid4())
entries.append({"EventId": event_id})
# if 'EventBusName' is not especially set, it will be sent to the default one
diff --git a/moto/firehose/models.py b/moto/firehose/models.py
index 75e28961e..37bd35448 100644
--- a/moto/firehose/models.py
+++ b/moto/firehose/models.py
@@ -21,7 +21,6 @@ from gzip import GzipFile
import io
import json
from time import time
-from uuid import uuid4
import warnings
import requests
@@ -36,6 +35,7 @@ from moto.firehose.exceptions import (
ResourceNotFoundException,
ValidationException,
)
+from moto.moto_api._internal import mock_random
from moto.s3.models import s3_backends
from moto.utilities.tagging_service import TaggingService
@@ -407,7 +407,7 @@ class FirehoseBackend(BaseBackend):
url = http_destination["EndpointConfiguration"]["Url"]
headers = {"Content-Type": "application/json"}
record_to_send = {
- "requestId": str(uuid4()),
+ "requestId": str(mock_random.uuid4()),
"timestamp": int(time()),
"records": [{"data": record["Data"]} for record in records],
}
@@ -418,7 +418,7 @@ class FirehoseBackend(BaseBackend):
raise RuntimeError(
"Firehose PutRecord(Batch) to HTTP destination failed"
) from exc
- return [{"RecordId": str(uuid4())} for _ in range(len(records))]
+ return [{"RecordId": str(mock_random.uuid4())} for _ in range(len(records))]
@staticmethod
def _format_s3_object_path(delivery_stream_name, version_id, prefix):
@@ -433,7 +433,7 @@ class FirehoseBackend(BaseBackend):
return (
f"{prefix}{now.strftime('%Y/%m/%d/%H')}/"
f"{delivery_stream_name}-{version_id}-"
- f"{now.strftime('%Y-%m-%d-%H-%M-%S')}-{str(uuid4())}"
+ f"{now.strftime('%Y-%m-%d-%H-%M-%S')}-{str(mock_random.uuid4())}"
)
def put_s3_records(self, delivery_stream_name, version_id, s3_destination, records):
@@ -455,7 +455,7 @@ class FirehoseBackend(BaseBackend):
raise RuntimeError(
"Firehose PutRecord(Batch to S3 destination failed"
) from exc
- return [{"RecordId": str(uuid4())} for _ in range(len(records))]
+ return [{"RecordId": str(mock_random.uuid4())} for _ in range(len(records))]
def put_record_batch(self, delivery_stream_name, records):
"""Write multiple data records into a Kinesis Data firehose stream."""
@@ -494,7 +494,7 @@ class FirehoseBackend(BaseBackend):
# This isn't implmented as these services aren't implemented,
# so ignore the data, but return a "proper" response.
request_responses = [
- {"RecordId": str(uuid4())} for _ in range(len(records))
+ {"RecordId": str(mock_random.uuid4())} for _ in range(len(records))
]
return {
diff --git a/moto/forecast/responses.py b/moto/forecast/responses.py
index bee513d9a..55a830265 100644
--- a/moto/forecast/responses.py
+++ b/moto/forecast/responses.py
@@ -1,7 +1,7 @@
import json
from moto.core.responses import BaseResponse
-from moto.core.utils import amzn_request_id
+from moto.utilities.aws_headers import amzn_request_id
from .models import forecast_backends
diff --git a/moto/glacier/utils.py b/moto/glacier/utils.py
index 8c1ec9db3..813945b5f 100644
--- a/moto/glacier/utils.py
+++ b/moto/glacier/utils.py
@@ -1,4 +1,4 @@
-import random
+from moto.moto_api._internal import mock_random as random
import string
diff --git a/moto/glue/models.py b/moto/glue/models.py
index fdb0d9dc1..a2afeac2d 100644
--- a/moto/glue/models.py
+++ b/moto/glue/models.py
@@ -2,11 +2,11 @@ import time
from collections import OrderedDict
from datetime import datetime
from typing import List
-from uuid import uuid4
from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict
from moto.moto_api import state_manager
+from moto.moto_api._internal import mock_random
from moto.moto_api._internal.managed_state_model import ManagedState
from .exceptions import (
JsonRESTError,
@@ -1072,7 +1072,7 @@ class FakeSchemaVersion(BaseModel):
self.schema_definition = schema_definition
self.schema_version_status = AVAILABLE_STATUS
self.version_number = version_number
- self.schema_version_id = str(uuid4())
+ self.schema_version_id = str(mock_random.uuid4())
self.created_time = datetime.utcnow()
self.updated_time = datetime.utcnow()
self.metadata = OrderedDict()
diff --git a/moto/greengrass/models.py b/moto/greengrass/models.py
index f54892aa0..b653ec037 100644
--- a/moto/greengrass/models.py
+++ b/moto/greengrass/models.py
@@ -1,11 +1,11 @@
import json
-import uuid
from collections import OrderedDict
from datetime import datetime
import re
from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict, iso_8601_datetime_with_milliseconds
+from moto.moto_api._internal import mock_random
from .exceptions import (
GreengrassClientError,
IdNotFoundException,
@@ -21,7 +21,7 @@ class FakeCoreDefinition(BaseModel):
def __init__(self, account_id, region_name, name):
self.region_name = region_name
self.name = name
- self.id = str(uuid.uuid4())
+ self.id = str(mock_random.uuid4())
self.arn = f"arn:aws:greengrass:{region_name}:{account_id}:greengrass/definition/cores/{self.id}"
self.created_at_datetime = datetime.utcnow()
self.latest_version = ""
@@ -48,7 +48,7 @@ class FakeCoreDefinitionVersion(BaseModel):
self.region_name = region_name
self.core_definition_id = core_definition_id
self.definition = definition
- self.version = str(uuid.uuid4())
+ self.version = str(mock_random.uuid4())
self.arn = f"arn:aws:greengrass:{region_name}:{account_id}:greengrass/definition/cores/{self.core_definition_id}/versions/{self.version}"
self.created_at_datetime = datetime.utcnow()
@@ -71,7 +71,7 @@ class FakeCoreDefinitionVersion(BaseModel):
class FakeDeviceDefinition(BaseModel):
def __init__(self, account_id, region_name, name, initial_version):
self.region_name = region_name
- self.id = str(uuid.uuid4())
+ self.id = str(mock_random.uuid4())
self.arn = f"arn:aws:greengrass:{region_name}:{account_id}:greengrass/definition/devices/{self.id}"
self.created_at_datetime = datetime.utcnow()
self.update_at_datetime = datetime.utcnow()
@@ -103,7 +103,7 @@ class FakeDeviceDefinitionVersion(BaseModel):
self.region_name = region_name
self.device_definition_id = device_definition_id
self.devices = devices
- self.version = str(uuid.uuid4())
+ self.version = str(mock_random.uuid4())
self.arn = f"arn:aws:greengrass:{region_name}:{account_id}:greengrass/definition/devices/{self.device_definition_id}/versions/{self.version}"
self.created_at_datetime = datetime.utcnow()
@@ -126,7 +126,7 @@ class FakeDeviceDefinitionVersion(BaseModel):
class FakeResourceDefinition(BaseModel):
def __init__(self, account_id, region_name, name, initial_version):
self.region_name = region_name
- self.id = str(uuid.uuid4())
+ self.id = str(mock_random.uuid4())
self.arn = f"arn:aws:greengrass:{region_name}:{account_id}:greengrass/definition/resources/{self.id}"
self.created_at_datetime = datetime.utcnow()
self.update_at_datetime = datetime.utcnow()
@@ -156,7 +156,7 @@ class FakeResourceDefinitionVersion(BaseModel):
self.region_name = region_name
self.resource_definition_id = resource_definition_id
self.resources = resources
- self.version = str(uuid.uuid4())
+ self.version = str(mock_random.uuid4())
self.arn = f"arn:aws:greengrass:{region_name}:{account_id}:greengrass/definition/resources/{self.resource_definition_id}/versions/{self.version}"
self.created_at_datetime = datetime.utcnow()
@@ -175,7 +175,7 @@ class FakeResourceDefinitionVersion(BaseModel):
class FakeFunctionDefinition(BaseModel):
def __init__(self, account_id, region_name, name, initial_version):
self.region_name = region_name
- self.id = str(uuid.uuid4())
+ self.id = str(mock_random.uuid4())
self.arn = f"arn:aws:greengrass:{self.region_name}:{account_id}:greengrass/definition/functions/{self.id}"
self.created_at_datetime = datetime.utcnow()
self.update_at_datetime = datetime.utcnow()
@@ -210,7 +210,7 @@ class FakeFunctionDefinitionVersion(BaseModel):
self.function_definition_id = function_definition_id
self.functions = functions
self.default_config = default_config
- self.version = str(uuid.uuid4())
+ self.version = str(mock_random.uuid4())
self.arn = f"arn:aws:greengrass:{self.region_name}:{account_id}:greengrass/definition/functions/{self.function_definition_id}/versions/{self.version}"
self.created_at_datetime = datetime.utcnow()
@@ -229,7 +229,7 @@ class FakeFunctionDefinitionVersion(BaseModel):
class FakeSubscriptionDefinition(BaseModel):
def __init__(self, account_id, region_name, name, initial_version):
self.region_name = region_name
- self.id = str(uuid.uuid4())
+ self.id = str(mock_random.uuid4())
self.arn = f"arn:aws:greengrass:{self.region_name}:{account_id}:greengrass/definition/subscriptions/{self.id}"
self.created_at_datetime = datetime.utcnow()
self.update_at_datetime = datetime.utcnow()
@@ -261,7 +261,7 @@ class FakeSubscriptionDefinitionVersion(BaseModel):
self.region_name = region_name
self.subscription_definition_id = subscription_definition_id
self.subscriptions = subscriptions
- self.version = str(uuid.uuid4())
+ self.version = str(mock_random.uuid4())
self.arn = f"arn:aws:greengrass:{self.region_name}:{account_id}:greengrass/definition/subscriptions/{self.subscription_definition_id}/versions/{self.version}"
self.created_at_datetime = datetime.utcnow()
@@ -280,7 +280,7 @@ class FakeSubscriptionDefinitionVersion(BaseModel):
class FakeGroup(BaseModel):
def __init__(self, account_id, region_name, name):
self.region_name = region_name
- self.group_id = str(uuid.uuid4())
+ self.group_id = str(mock_random.uuid4())
self.name = name
self.arn = f"arn:aws:greengrass:{self.region_name}:{account_id}:greengrass/groups/{self.group_id}"
self.created_at_datetime = datetime.utcnow()
@@ -319,7 +319,7 @@ class FakeGroupVersion(BaseModel):
):
self.region_name = region_name
self.group_id = group_id
- self.version = str(uuid.uuid4())
+ self.version = str(mock_random.uuid4())
self.arn = f"arn:aws:greengrass:{self.region_name}:{account_id}:greengrass/groups/{self.group_id}/versions/{self.version}"
self.created_at_datetime = datetime.utcnow()
self.core_definition_version_arn = core_definition_version_arn
@@ -372,7 +372,7 @@ class FakeGroupVersion(BaseModel):
class FakeDeployment(BaseModel):
def __init__(self, account_id, region_name, group_id, group_arn, deployment_type):
self.region_name = region_name
- self.id = str(uuid.uuid4())
+ self.id = str(mock_random.uuid4())
self.group_id = group_id
self.group_arn = group_arn
self.created_at_datetime = datetime.utcnow()
diff --git a/moto/guardduty/models.py b/moto/guardduty/models.py
index fcdf53dd3..afddd0403 100644
--- a/moto/guardduty/models.py
+++ b/moto/guardduty/models.py
@@ -1,6 +1,7 @@
from __future__ import unicode_literals
from moto.core import BaseBackend, BaseModel
-from moto.core.utils import BackendDict, get_random_hex
+from moto.core.utils import BackendDict
+from moto.moto_api._internal import mock_random
from datetime import datetime
from .exceptions import DetectorNotFoundException, FilterNotFoundException
@@ -129,7 +130,7 @@ class Detector(BaseModel):
datasources,
tags,
):
- self.id = get_random_hex(length=32)
+ self.id = mock_random.get_random_hex(length=32)
self.created_at = created_at
self.finding_publish_freq = finding_publish_freq
self.service_role = f"arn:aws:iam::{account_id}:role/aws-service-role/guardduty.amazonaws.com/AWSServiceRoleForAmazonGuardDuty"
diff --git a/moto/iam/models.py b/moto/iam/models.py
index 4bf5323b5..bef9c3961 100644
--- a/moto/iam/models.py
+++ b/moto/iam/models.py
@@ -1,9 +1,7 @@
import base64
import os
-import random
import string
import sys
-import uuid
from datetime import datetime
import json
import re
@@ -26,6 +24,7 @@ from moto.iam.policy_validation import (
IAMPolicyDocumentValidator,
IAMTrustPolicyDocumentValidator,
)
+from moto.moto_api._internal import mock_random as random
from moto.utilities.utils import md5_hash
from .aws_managed_policies import aws_managed_policies_data
@@ -3029,7 +3028,7 @@ class IAMBackend(BaseBackend):
def delete_service_linked_role(self, role_name):
self.delete_role(role_name)
- deletion_task_id = str(uuid.uuid4())
+ deletion_task_id = str(random.uuid4())
return deletion_task_id
def get_service_linked_role_deletion_status(self):
diff --git a/moto/iam/utils.py b/moto/iam/utils.py
index 42ca109bf..76743751d 100644
--- a/moto/iam/utils.py
+++ b/moto/iam/utils.py
@@ -1,4 +1,4 @@
-import random
+from moto.moto_api._internal import mock_random as random
import string
diff --git a/moto/iot/models.py b/moto/iot/models.py
index fd01b31bb..a291aec34 100644
--- a/moto/iot/models.py
+++ b/moto/iot/models.py
@@ -1,9 +1,6 @@
import hashlib
-import random
import re
-import string
import time
-import uuid
from collections import OrderedDict
from cryptography import x509
from cryptography.hazmat.backends import default_backend
@@ -16,7 +13,7 @@ from .utils import PAGINATION_MODEL
from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict
-from moto.utilities.utils import random_string
+from moto.moto_api._internal import mock_random as random
from moto.utilities.paginator import paginate
from .exceptions import (
CertificateStateException,
@@ -74,7 +71,7 @@ class FakeThingType(BaseModel):
self.region_name = region_name
self.thing_type_name = thing_type_name
self.thing_type_properties = thing_type_properties
- self.thing_type_id = str(uuid.uuid4()) # I don't know the rule of id
+ self.thing_type_id = str(random.uuid4()) # I don't know the rule of id
t = time.time()
self.metadata = {"deprecated": False, "creationDate": int(t * 1000) / 1000.0}
self.arn = "arn:aws:iot:%s:1:thingtype/%s" % (self.region_name, thing_type_name)
@@ -100,7 +97,7 @@ class FakeThingGroup(BaseModel):
):
self.region_name = region_name
self.thing_group_name = thing_group_name
- self.thing_group_id = str(uuid.uuid4()) # I don't know the rule of id
+ self.thing_group_id = str(random.uuid4()) # I don't know the rule of id
self.version = 1 # TODO: tmp
self.parent_group_name = parent_group_name
self.thing_group_properties = thing_group_properties or {}
@@ -434,7 +431,7 @@ class FakeEndpoint(BaseModel):
"operation: Endpoint type %s not recognized." % endpoint_type
)
self.region_name = region_name
- identifier = random_string(14).lower()
+ identifier = random.get_random_string(length=14, lower_case=True)
if endpoint_type == "iot:Data":
self.endpoint = "{i}.iot.{r}.amazonaws.com".format(
i=identifier, r=self.region_name
@@ -540,7 +537,7 @@ class FakeDomainConfiguration(BaseModel):
self.domain_configuration_arn = "arn:aws:iot:%s:1:domainconfiguration/%s/%s" % (
region_name,
domain_configuration_name,
- random_string(5),
+ random.get_random_string(length=5),
)
self.domain_name = domain_name
self.server_certificates = []
@@ -836,21 +833,14 @@ class IoTBackend(BaseBackend):
else:
thing.attributes.update(attributes)
- def _random_string(self):
- n = 20
- random_str = "".join(
- [random.choice(string.ascii_letters + string.digits) for i in range(n)]
- )
- return random_str
-
def create_keys_and_certificate(self, set_as_active):
# implement here
# caCertificate can be blank
key_pair = {
- "PublicKey": self._random_string(),
- "PrivateKey": self._random_string(),
+ "PublicKey": random.get_random_string(),
+ "PrivateKey": random.get_random_string(),
}
- certificate_pem = self._random_string()
+ certificate_pem = random.get_random_string()
status = "ACTIVE" if set_as_active else "INACTIVE"
certificate = FakeCertificate(
certificate_pem, status, self.account_id, self.region_name
@@ -910,7 +900,7 @@ class IoTBackend(BaseBackend):
return certs[0]
def get_registration_code(self):
- return str(uuid.uuid4())
+ return str(random.uuid4())
def list_certificates(self):
"""
diff --git a/moto/kinesisvideo/models.py b/moto/kinesisvideo/models.py
index ba2fc3779..221d7d1aa 100644
--- a/moto/kinesisvideo/models.py
+++ b/moto/kinesisvideo/models.py
@@ -1,9 +1,8 @@
from moto.core import BaseBackend, BaseModel
from datetime import datetime
from .exceptions import ResourceNotFoundException, ResourceInUseException
-import random
-import string
-from moto.core.utils import get_random_hex, BackendDict
+from moto.core.utils import BackendDict
+from moto.moto_api._internal import mock_random as random
class Stream(BaseModel):
@@ -26,17 +25,12 @@ class Stream(BaseModel):
self.data_retention_in_hours = data_retention_in_hours
self.tags = tags
self.status = "ACTIVE"
- self.version = self._get_random_string()
+ self.version = random.get_random_string(include_digits=False, lower_case=True)
self.creation_time = datetime.utcnow()
stream_arn = f"arn:aws:kinesisvideo:{region_name}:{account_id}:stream/{stream_name}/1598784211076"
- self.data_endpoint_number = get_random_hex()
+ self.data_endpoint_number = random.get_random_hex()
self.arn = stream_arn
- def _get_random_string(self, length=20):
- letters = string.ascii_lowercase
- result_str = "".join([random.choice(letters) for _ in range(length)])
- return result_str
-
def get_data_endpoint(self, api_name):
data_endpoint_prefix = "s-" if api_name in ("PUT_MEDIA", "GET_MEDIA") else "b-"
return "https://{}{}.kinesisvideo.{}.amazonaws.com".format(
diff --git a/moto/kms/models.py b/moto/kms/models.py
index 0a4120654..5953d4ae0 100644
--- a/moto/kms/models.py
+++ b/moto/kms/models.py
@@ -9,7 +9,8 @@ from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from moto.core import BaseBackend, BaseModel, CloudFormationModel
-from moto.core.utils import get_random_hex, unix_time, BackendDict
+from moto.core.utils import unix_time, BackendDict
+from moto.moto_api._internal import mock_random
from moto.utilities.tagging_service import TaggingService
from moto.core.exceptions import JsonRESTError
@@ -40,8 +41,8 @@ class Grant(BaseModel):
self.retiring_principal = retiring_principal
self.operations = operations
self.constraints = constraints
- self.id = get_random_hex()
- self.token = get_random_hex()
+ self.id = mock_random.get_random_hex()
+ self.token = mock_random.get_random_hex()
def to_json(self):
return {
diff --git a/moto/kms/utils.py b/moto/kms/utils.py
index 1173a1592..c7fc27409 100644
--- a/moto/kms/utils.py
+++ b/moto/kms/utils.py
@@ -2,7 +2,7 @@ from collections import namedtuple
import io
import os
import struct
-import uuid
+from moto.moto_api._internal import mock_random
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.ciphers import algorithms, Cipher, modes
@@ -46,7 +46,7 @@ RESERVED_ALIASES = [
def generate_key_id(multi_region=False):
- key = str(uuid.uuid4())
+ key = str(mock_random.uuid4())
# https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html
# "Notice that multi-Region keys have a distinctive key ID that begins with mrk-. You can use the mrk- prefix to
# identify MRKs programmatically."
diff --git a/moto/logs/models.py b/moto/logs/models.py
index c979f960c..e5ce29d60 100644
--- a/moto/logs/models.py
+++ b/moto/logs/models.py
@@ -1,11 +1,8 @@
-import uuid
-
from datetime import datetime, timedelta
from moto.core import BaseBackend, BaseModel
from moto.core import CloudFormationModel
from moto.core.utils import unix_time_millis, BackendDict
-from moto.utilities.paginator import paginate
from moto.logs.metric_filters import MetricFilters
from moto.logs.exceptions import (
ResourceNotFoundException,
@@ -13,7 +10,9 @@ from moto.logs.exceptions import (
InvalidParameterException,
LimitExceededException,
)
+from moto.moto_api._internal import mock_random
from moto.s3.models import s3_backends
+from moto.utilities.paginator import paginate
from .utils import PAGINATION_MODEL, EventMessageFilter
MAX_RESOURCE_POLICIES_PER_REGION = 10
@@ -943,7 +942,7 @@ class LogsBackend(BaseBackend):
if log_group_name not in self.groups:
raise ResourceNotFoundException()
- query_id = uuid.uuid1()
+ query_id = mock_random.uuid1()
self.queries[query_id] = LogQuery(query_id, start_time, end_time, query_string)
return query_id
@@ -951,7 +950,7 @@ class LogsBackend(BaseBackend):
s3_backends[self.account_id]["global"].get_bucket(destination)
if log_group_name not in self.groups:
raise ResourceNotFoundException()
- task_id = uuid.uuid4()
+ task_id = mock_random.uuid4()
return task_id
diff --git a/moto/managedblockchain/utils.py b/moto/managedblockchain/utils.py
index 280f108fc..710939c31 100644
--- a/moto/managedblockchain/utils.py
+++ b/moto/managedblockchain/utils.py
@@ -1,8 +1,7 @@
import json
-import random
import re
import string
-
+from moto.moto_api._internal import mock_random as random
from urllib.parse import parse_qs, urlparse
diff --git a/moto/mediaconnect/models.py b/moto/mediaconnect/models.py
index 574fdfd3b..d8e269a43 100644
--- a/moto/mediaconnect/models.py
+++ b/moto/mediaconnect/models.py
@@ -1,9 +1,9 @@
from collections import OrderedDict
-from uuid import uuid4
from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict
from moto.mediaconnect.exceptions import NotFoundException
+from moto.moto_api._internal import mock_random as random
class Flow(BaseModel):
@@ -87,7 +87,7 @@ class MediaConnectBackend(BaseBackend):
source["ingestIp"] = ingest_ip
def _create_flow_add_details(self, flow):
- flow_id = uuid4().hex
+ flow_id = random.uuid4().hex
flow.description = "A Moto test flow"
flow.egress_ip = "127.0.0.1"
@@ -248,7 +248,7 @@ class MediaConnectBackend(BaseBackend):
)
flow = self._flows[flow_arn]
for source in sources:
- source_id = uuid4().hex
+ source_id = random.uuid4().hex
name = source["name"]
arn = f"arn:aws:mediaconnect:{self.region_name}:{self.account_id}:source:{source_id}:{name}"
source["sourceArn"] = arn
diff --git a/moto/medialive/models.py b/moto/medialive/models.py
index 7a83e6785..e75383b7e 100644
--- a/moto/medialive/models.py
+++ b/moto/medialive/models.py
@@ -1,8 +1,8 @@
from collections import OrderedDict
-from uuid import uuid4
from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict
+from moto.moto_api._internal import mock_random
class Input(BaseModel):
@@ -134,7 +134,7 @@ class MediaLiveBackend(BaseBackend):
"""
The RequestID and Reserved parameters are not yet implemented
"""
- channel_id = uuid4().hex
+ channel_id = mock_random.uuid4().hex
arn = "arn:aws:medialive:channel:{}".format(channel_id)
channel = Channel(
arn=arn,
@@ -228,7 +228,7 @@ class MediaLiveBackend(BaseBackend):
"""
The VPC and RequestId parameters are not yet implemented
"""
- input_id = uuid4().hex
+ input_id = mock_random.uuid4().hex
arn = "arn:aws:medialive:input:{}".format(input_id)
a_input = Input(
arn=arn,
diff --git a/moto/moto_api/_internal/__init__.py b/moto/moto_api/_internal/__init__.py
index d12ac2556..5deee67be 100644
--- a/moto/moto_api/_internal/__init__.py
+++ b/moto/moto_api/_internal/__init__.py
@@ -1,6 +1,12 @@
from .models import moto_api_backend
from .state_manager import StateManager # noqa
from .recorder.models import Recorder # noqa
+from .moto_random import MotoRandom
moto_api_backends = {"global": moto_api_backend}
+
+"""
+Random-object used throughout Moto. Can be seeded to make identifiers deterministic.
+"""
+mock_random = MotoRandom()
diff --git a/moto/moto_api/_internal/moto_random.py b/moto/moto_api/_internal/moto_random.py
new file mode 100644
index 000000000..f27580525
--- /dev/null
+++ b/moto/moto_api/_internal/moto_random.py
@@ -0,0 +1,30 @@
+from random import Random
+import string
+import uuid
+
+
+HEX_CHARS = list(range(10)) + ["a", "b", "c", "d", "e", "f"]
+
+
+class MotoRandom(Random):
+ """
+ Class used for all sources of random-ness in Moto.
+ Used as a singleton, which is exposed in `moto/moto_api/_internal`.
+ This Singleton can be seeded to make identifiers deterministic.
+ """
+
+ def uuid1(self):
+ return uuid.UUID(int=self.getrandbits(128), version=1)
+
+ def uuid4(self):
+ return uuid.UUID(int=self.getrandbits(128), version=4)
+
+ def get_random_hex(self, length=8):
+ return "".join(str(self.choice(HEX_CHARS)) for _ in range(length))
+
+ def get_random_string(self, length=20, include_digits=True, lower_case=False):
+ pool = string.ascii_letters
+ if include_digits:
+ pool += string.digits
+ random_str = "".join([self.choice(pool) for i in range(length)])
+ return random_str.lower() if lower_case else random_str
diff --git a/moto/moto_api/_internal/recorder/models.py b/moto/moto_api/_internal/recorder/models.py
index 5d351d4ed..2c053a56d 100644
--- a/moto/moto_api/_internal/recorder/models.py
+++ b/moto/moto_api/_internal/recorder/models.py
@@ -44,9 +44,9 @@ class Recorder:
body_encoded = False
finally:
if request_body is not None:
- if isinstance(request_body, bytes):
- request_body = request_body.decode("utf-8")
- request.environ["wsgi.input"] = io.StringIO(request_body)
+ if isinstance(request_body, str):
+ request_body = request_body.encode("utf-8")
+ request.environ["wsgi.input"] = io.BytesIO(request_body)
else:
body, body_encoded = self._encode_body(body)
entry.update({"body": body, "body_encoded": body_encoded})
@@ -87,9 +87,11 @@ class Recorder:
def upload_recording(self, data):
"""
- Replace the current log. Remember to replay the recording afterwards.
+ Replaces the current log. Remember to replay the recording afterwards.
"""
filepath = self._location
+ if isinstance(data, str):
+ data = data.encode("utf-8")
with open(filepath, "bw") as file:
file.write(data)
diff --git a/moto/moto_api/_internal/responses.py b/moto/moto_api/_internal/responses.py
index b452d990b..eba77ae47 100644
--- a/moto/moto_api/_internal/responses.py
+++ b/moto/moto_api/_internal/responses.py
@@ -106,3 +106,11 @@ class MotoAPIResponse(BaseResponse):
moto_api_backend.unset_transition(model_name)
return 201, {}, ""
+
+ def seed(self, req, full_url, headers):
+ self.setup_class(req, full_url, headers)
+ from . import mock_random
+
+ a = self._get_param("a")
+ mock_random.seed(int(a))
+ return 200, {}, ""
diff --git a/moto/moto_api/_internal/urls.py b/moto/moto_api/_internal/urls.py
index 1f433d470..da5ea6cef 100644
--- a/moto/moto_api/_internal/urls.py
+++ b/moto/moto_api/_internal/urls.py
@@ -11,6 +11,7 @@ url_paths = {
"{0}/moto-api/data.json": response_instance.model_data,
"{0}/moto-api/reset": response_instance.reset_response,
"{0}/moto-api/reset-auth": response_instance.reset_auth_response,
+ "{0}/moto-api/seed": response_instance.seed,
"{0}/moto-api/state-manager/get-transition": response_instance.get_transition,
"{0}/moto-api/state-manager/set-transition": response_instance.set_transition,
"{0}/moto-api/state-manager/unset-transition": response_instance.unset_transition,
diff --git a/moto/mq/models.py b/moto/mq/models.py
index 82626f12a..f80c9f76b 100644
--- a/moto/mq/models.py
+++ b/moto/mq/models.py
@@ -2,7 +2,8 @@ import base64
import xmltodict
from moto.core import BaseBackend, BaseModel
-from moto.core.utils import BackendDict, get_random_hex, unix_time
+from moto.core.utils import BackendDict, unix_time
+from moto.moto_api._internal import mock_random
from moto.utilities.tagging_service import TaggingService
from .configuration import DEFAULT_CONFIGURATION_DATA
@@ -58,7 +59,7 @@ class ConfigurationRevision(BaseModel):
class Configuration(BaseModel):
def __init__(self, account_id, region, name, engine_type, engine_version):
- self.id = f"c-{get_random_hex(6)}"
+ self.id = f"c-{mock_random.get_random_hex(6)}"
self.arn = f"arn:aws:mq:{region}:{account_id}:configuration:{self.id}"
self.created = unix_time()
@@ -160,7 +161,7 @@ class Broker(BaseModel):
users,
):
self.name = name
- self.id = get_random_hex(6)
+ self.id = mock_random.get_random_hex(6)
self.arn = f"arn:aws:mq:{region}:{account_id}:broker:{self.id}"
self.state = "RUNNING"
self.created = unix_time()
@@ -217,7 +218,7 @@ class Broker(BaseModel):
self.configurations = None
else:
current_config = configuration or {
- "id": f"c-{get_random_hex(6)}",
+ "id": f"c-{mock_random.get_random_hex(6)}",
"revision": 1,
}
self.configurations = {
diff --git a/moto/opsworks/models.py b/moto/opsworks/models.py
index 8a22f2b72..ea6500a93 100644
--- a/moto/opsworks/models.py
+++ b/moto/opsworks/models.py
@@ -1,9 +1,8 @@
from moto.core import BaseBackend, BaseModel
from moto.ec2 import ec2_backends
from moto.core.utils import BackendDict
-import uuid
+from moto.moto_api._internal import mock_random as random
import datetime
-from random import choice
from .exceptions import ResourceNotFoundException, ValidationException
@@ -83,7 +82,7 @@ class OpsworkInstance(BaseModel):
self.infrastructure_class = "ec2 (fixed)"
self.platform = "linux (fixed)"
- self.id = "{0}".format(uuid.uuid4())
+ self.id = "{0}".format(random.uuid4())
self.created_at = datetime.datetime.utcnow()
def start(self):
@@ -273,7 +272,7 @@ class Layer(BaseModel):
self.install_updates_on_boot = install_updates_on_boot
self.use_ebs_optimized_instances = use_ebs_optimized_instances
- self.id = "{0}".format(uuid.uuid4())
+ self.id = "{0}".format(random.uuid4())
self.created_at = datetime.datetime.utcnow()
def __eq__(self, other):
@@ -369,7 +368,7 @@ class Stack(BaseModel):
self.default_root_device_type = default_root_device_type
self.agent_version = agent_version
- self.id = "{0}".format(uuid.uuid4())
+ self.id = "{0}".format(random.uuid4())
self.layers = []
self.apps = []
self.account_number = account_id
@@ -381,7 +380,8 @@ class Stack(BaseModel):
def generate_hostname(self):
# this doesn't match amazon's implementation
return "{theme}-{rand}-(moto)".format(
- theme=self.hostname_theme, rand=[choice("abcdefghijhk") for _ in range(4)]
+ theme=self.hostname_theme,
+ rand=[random.choice("abcdefghijhk") for _ in range(4)],
)
@property
@@ -469,7 +469,7 @@ class App(BaseModel):
if environment is None:
self.environment = {}
- self.id = "{0}".format(uuid.uuid4())
+ self.id = "{0}".format(random.uuid4())
self.created_at = datetime.datetime.utcnow()
def __eq__(self, other):
diff --git a/moto/organizations/utils.py b/moto/organizations/utils.py
index f328889cb..1f56242e1 100644
--- a/moto/organizations/utils.py
+++ b/moto/organizations/utils.py
@@ -1,6 +1,6 @@
-import random
import re
import string
+from moto.moto_api._internal import mock_random as random
MASTER_ACCOUNT_EMAIL = "master@example.com"
diff --git a/moto/pinpoint/models.py b/moto/pinpoint/models.py
index a2e82d004..1ba47efa3 100644
--- a/moto/pinpoint/models.py
+++ b/moto/pinpoint/models.py
@@ -1,15 +1,15 @@
from datetime import datetime
from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict, unix_time
+from moto.moto_api._internal import mock_random
from moto.utilities.tagging_service import TaggingService
-from uuid import uuid4
from .exceptions import ApplicationNotFound, EventStreamNotFound
class App(BaseModel):
def __init__(self, account_id, name):
- self.application_id = str(uuid4()).replace("-", "")
+ self.application_id = str(mock_random.uuid4()).replace("-", "")
self.arn = (
f"arn:aws:mobiletargeting:us-east-1:{account_id}:apps/{self.application_id}"
)
diff --git a/moto/ram/models.py b/moto/ram/models.py
index eefc7f6ec..4b90304cf 100644
--- a/moto/ram/models.py
+++ b/moto/ram/models.py
@@ -1,11 +1,10 @@
import re
import string
from datetime import datetime
-import random
-from uuid import uuid4
from moto.core import BaseBackend, BaseModel
from moto.core.utils import unix_time, BackendDict
+from moto.moto_api._internal import mock_random as random
from moto.organizations import organizations_backends
from moto.ram.exceptions import (
MalformedArnException,
@@ -43,7 +42,9 @@ class ResourceShare(BaseModel):
self.region = region
self.allow_external_principals = kwargs.get("allowExternalPrincipals", True)
- self.arn = f"arn:aws:ram:{self.region}:{account_id}:resource-share/{uuid4()}"
+ self.arn = (
+ f"arn:aws:ram:{self.region}:{account_id}:resource-share/{random.uuid4()}"
+ )
self.creation_time = datetime.utcnow()
self.feature_set = "STANDARD"
self.last_updated_time = datetime.utcnow()
diff --git a/moto/rds/models.py b/moto/rds/models.py
index a30d36a4e..744b35a11 100644
--- a/moto/rds/models.py
+++ b/moto/rds/models.py
@@ -1,7 +1,6 @@
import copy
import datetime
import os
-import random
import string
from collections import defaultdict
@@ -9,9 +8,9 @@ from jinja2 import Template
from re import compile as re_compile
from collections import OrderedDict
from moto.core import BaseBackend, BaseModel, CloudFormationModel
-
from moto.core.utils import iso_8601_datetime_with_milliseconds, BackendDict
from moto.ec2.models import ec2_backends
+from moto.moto_api._internal import mock_random as random
from .exceptions import (
RDSClientError,
DBClusterNotFoundError,
diff --git a/moto/redshift/models.py b/moto/redshift/models.py
index 98f48389e..a30c5fbf2 100644
--- a/moto/redshift/models.py
+++ b/moto/redshift/models.py
@@ -4,8 +4,8 @@ import datetime
from collections import OrderedDict
from moto.core import BaseBackend, BaseModel, CloudFormationModel
from moto.core.utils import iso_8601_datetime_with_milliseconds, BackendDict
-from moto.utilities.utils import random_string
from moto.ec2 import ec2_backends
+from moto.moto_api._internal import mock_random
from .exceptions import (
ClusterAlreadyExistsFaultError,
ClusterNotFoundError,
@@ -1050,7 +1050,7 @@ class RedshiftBackend(BaseBackend):
db_user = user_prefix + db_user
return {
"DbUser": db_user,
- "DbPassword": random_string(32),
+ "DbPassword": mock_random.get_random_string(32),
"Expiration": expiration,
}
else:
diff --git a/moto/redshiftdata/models.py b/moto/redshiftdata/models.py
index 30a9ea170..abda501b7 100644
--- a/moto/redshiftdata/models.py
+++ b/moto/redshiftdata/models.py
@@ -1,10 +1,9 @@
import re
-import uuid
from datetime import datetime
-import random
from moto.core import BaseBackend
from moto.core.utils import BackendDict, iso_8601_datetime_without_milliseconds
+from moto.moto_api._internal import mock_random as random
from moto.redshiftdata.exceptions import ValidationException, ResourceNotFoundException
@@ -20,7 +19,7 @@ class Statement:
):
now = iso_8601_datetime_without_milliseconds(datetime.now())
- self.id = str(uuid.uuid4())
+ self.id = str(random.uuid4())
self.cluster_identifier = cluster_identifier
self.created_at = now
self.database = database
diff --git a/moto/rekognition/models.py b/moto/rekognition/models.py
index 59e8fe5d5..d49155889 100644
--- a/moto/rekognition/models.py
+++ b/moto/rekognition/models.py
@@ -1,10 +1,10 @@
"""RekognitionBackend class with methods for supported APIs."""
-import random
import string
from moto.core import BaseBackend
from moto.core.utils import BackendDict
+from moto.moto_api._internal import mock_random as random
class RekognitionBackend(BaseBackend):
diff --git a/moto/resourcegroupstaggingapi/models.py b/moto/resourcegroupstaggingapi/models.py
index 369858033..92d4a0cff 100644
--- a/moto/resourcegroupstaggingapi/models.py
+++ b/moto/resourcegroupstaggingapi/models.py
@@ -1,8 +1,7 @@
-import uuid
-
from moto.core import BaseBackend
from moto.core.exceptions import RESTError
from moto.core.utils import BackendDict
+from moto.moto_api._internal import mock_random
from moto.s3 import s3_backends
from moto.ec2 import ec2_backends
@@ -612,7 +611,7 @@ class ResourceGroupsTaggingAPIBackend(BaseBackend):
return None, result
# Didn't hit StopIteration so there's stuff left in generator
- new_token = str(uuid.uuid4())
+ new_token = str(mock_random.uuid4())
self._pages[new_token] = {"gen": generator, "misc": next_item}
# Token used up, might as well bin now, if you call it again your an idiot
@@ -658,7 +657,7 @@ class ResourceGroupsTaggingAPIBackend(BaseBackend):
return None, result
# Didn't hit StopIteration so there's stuff left in generator
- new_token = str(uuid.uuid4())
+ new_token = str(mock_random.uuid4())
self._pages[new_token] = {"gen": generator, "misc": next_item}
# Token used up, might as well bin now, if you call it again your an idiot
@@ -704,7 +703,7 @@ class ResourceGroupsTaggingAPIBackend(BaseBackend):
return None, result
# Didn't hit StopIteration so there's stuff left in generator
- new_token = str(uuid.uuid4())
+ new_token = str(mock_random.uuid4())
self._pages[new_token] = {"gen": generator, "misc": next_item}
# Token used up, might as well bin now, if you call it again your an idiot
diff --git a/moto/route53/models.py b/moto/route53/models.py
index e568d8ff6..c854c166a 100644
--- a/moto/route53/models.py
+++ b/moto/route53/models.py
@@ -1,11 +1,8 @@
"""Route53Backend class with methods for supported APIs."""
import itertools
-from collections import defaultdict
import re
-
import string
-import random
-import uuid
+from collections import defaultdict
from jinja2 import Template
from moto.route53.exceptions import (
@@ -23,6 +20,7 @@ from moto.route53.exceptions import (
)
from moto.core import BaseBackend, BaseModel, CloudFormationModel
from moto.core.utils import BackendDict
+from moto.moto_api._internal import mock_random as random
from moto.utilities.paginator import paginate
from .utils import PAGINATION_MODEL
@@ -645,7 +643,7 @@ class Route53Backend(BaseBackend):
return zone
def create_health_check(self, caller_reference, health_check_args):
- health_check_id = str(uuid.uuid4())
+ health_check_id = str(random.uuid4())
health_check = HealthCheck(health_check_id, caller_reference, health_check_args)
health_check.set_children(health_check_args.get("children"))
health_check.set_regions(health_check_args.get("regions"))
@@ -749,7 +747,7 @@ class Route53Backend(BaseBackend):
raise QueryLoggingConfigAlreadyExists()
# Create an instance of the query logging config.
- query_logging_config_id = str(uuid.uuid4())
+ query_logging_config_id = str(random.uuid4())
query_logging_config = QueryLoggingConfig(
query_logging_config_id, hosted_zone_id, log_group_arn
)
diff --git a/moto/route53resolver/models.py b/moto/route53resolver/models.py
index 7ae1158a5..4017efc50 100644
--- a/moto/route53resolver/models.py
+++ b/moto/route53resolver/models.py
@@ -5,10 +5,11 @@ from ipaddress import ip_address, ip_network, IPv4Address
import re
from moto.core import BaseBackend, BaseModel
-from moto.core.utils import get_random_hex, BackendDict
+from moto.core.utils import BackendDict
from moto.ec2 import ec2_backends
from moto.ec2.exceptions import InvalidSubnetIdError
from moto.ec2.exceptions import InvalidSecurityGroupNotFoundError
+from moto.moto_api._internal import mock_random
from moto.route53resolver.exceptions import (
InvalidParameterException,
InvalidRequestException,
@@ -114,7 +115,7 @@ class ResolverRule(BaseModel): # pylint: disable=too-many-instance-attributes
# of X-Amzn-Trace-Id. We don't have that info, so a random number
# of similar format and length will be used.
self.status_message = (
- f"[Trace id: 1-{get_random_hex(8)}-{get_random_hex(24)}] "
+ f"[Trace id: 1-{mock_random.get_random_hex(8)}-{mock_random.get_random_hex(24)}] "
f"Successfully created Resolver Rule"
)
self.share_status = "SHARED_WITH_ME"
@@ -199,7 +200,7 @@ class ResolverEndpoint(BaseModel): # pylint: disable=too-many-instance-attribut
# of X-Amzn-Trace-Id. We don't have that info, so a random number
# of similar format and length will be used.
self.status_message = (
- f"[Trace id: 1-{get_random_hex(8)}-{get_random_hex(24)}] "
+ f"[Trace id: 1-{mock_random.get_random_hex(8)}-{mock_random.get_random_hex(24)}] "
f"Successfully created Resolver Endpoint"
)
self.creation_time = datetime.now(timezone.utc).isoformat()
@@ -228,7 +229,9 @@ class ResolverEndpoint(BaseModel): # pylint: disable=too-many-instance-attribut
"""
subnets = defaultdict(dict)
for entry in self.ip_addresses:
- subnets[entry["SubnetId"]][entry["Ip"]] = f"rni-{get_random_hex(17)}"
+ subnets[entry["SubnetId"]][
+ entry["Ip"]
+ ] = f"rni-{mock_random.get_random_hex(17)}"
return subnets
def create_eni(self):
@@ -298,7 +301,7 @@ class ResolverEndpoint(BaseModel): # pylint: disable=too-many-instance-attribut
self.ip_addresses.append(ip_address)
self.ip_address_count = len(self.ip_addresses)
- eni_id = f"rni-{get_random_hex(17)}"
+ eni_id = f"rni-{mock_random.get_random_hex(17)}"
self.subnets[ip_address["SubnetId"]][ip_address["Ip"]] = eni_id
eni_info = self.ec2_backend.create_network_interface(
@@ -390,7 +393,7 @@ class Route53ResolverBackend(BaseBackend):
f"VPC. Conflict with resolver rule '{resolver_rule_id}'"
)
- rule_association_id = f"rslvr-rrassoc-{get_random_hex(17)}"
+ rule_association_id = f"rslvr-rrassoc-{mock_random.get_random_hex(17)}"
rule_association = ResolverRuleAssociation(
self.region_name, rule_association_id, resolver_rule_id, vpc_id, name
)
@@ -509,9 +512,7 @@ class Route53ResolverBackend(BaseBackend):
f"'{creator_request_id}' already exists"
)
- endpoint_id = (
- f"rslvr-{'in' if direction == 'INBOUND' else 'out'}-{get_random_hex(17)}"
- )
+ endpoint_id = f"rslvr-{'in' if direction == 'INBOUND' else 'out'}-{mock_random.get_random_hex(17)}"
resolver_endpoint = ResolverEndpoint(
self.account_id,
region,
@@ -605,7 +606,7 @@ class Route53ResolverBackend(BaseBackend):
f"'{creator_request_id}' already exists"
)
- rule_id = f"rslvr-rr-{get_random_hex(17)}"
+ rule_id = f"rslvr-rr-{mock_random.get_random_hex(17)}"
resolver_rule = ResolverRule(
self.account_id,
region,
diff --git a/moto/s3/models.py b/moto/s3/models.py
index 77bfa0953..33b5c503b 100644
--- a/moto/s3/models.py
+++ b/moto/s3/models.py
@@ -5,20 +5,17 @@ import datetime
import copy
import itertools
import codecs
-import random
import string
import tempfile
import threading
import pytz
import sys
-import uuid
import urllib.parse
from bisect import insort
from importlib import reload
from moto.core import BaseBackend, BaseModel, CloudFormationModel
from moto.core import CloudWatchMetricProvider
-
from moto.core.utils import (
iso_8601_datetime_without_milliseconds_s3,
rfc_1123_datetime,
@@ -28,6 +25,7 @@ from moto.core.utils import (
)
from moto.cloudwatch.models import MetricDatum
from moto.moto_api import state_manager
+from moto.moto_api._internal import mock_random as random
from moto.moto_api._internal.managed_state_model import ManagedState
from moto.utilities.tagging_service import TaggingService
from moto.utilities.utils import LowercaseDict, md5_hash
@@ -80,7 +78,7 @@ class FakeDeleteMarker(BaseModel):
self.key = key
self.name = key.name
self.last_modified = datetime.datetime.utcnow()
- self._version_id = str(uuid.uuid4())
+ self._version_id = str(random.uuid4())
@property
def last_modified_ISO8601(self):
@@ -1728,7 +1726,7 @@ class S3Backend(BaseBackend, CloudWatchMetricProvider):
storage=storage,
etag=etag,
is_versioned=bucket.is_versioned,
- version_id=str(uuid.uuid4()) if bucket.is_versioned else "null",
+ version_id=str(random.uuid4()) if bucket.is_versioned else "null",
multipart=multipart,
encryption=encryption,
kms_key_id=kms_key_id,
diff --git a/moto/s3/responses.py b/moto/s3/responses.py
index 49221db9c..56f380872 100644
--- a/moto/s3/responses.py
+++ b/moto/s3/responses.py
@@ -7,7 +7,6 @@ import urllib.parse
from moto import settings
from moto.core.utils import (
- amzn_request_id,
extract_region_from_aws_authorization,
str_to_rfc_1123_datetime,
)
@@ -23,6 +22,7 @@ from moto.s3bucket_path.utils import (
parse_key_name as bucketpath_parse_key_name,
is_delete_keys as bucketpath_is_delete_keys,
)
+from moto.utilities.aws_headers import amzn_request_id
from .exceptions import (
BucketAlreadyExists,
diff --git a/moto/s3control/models.py b/moto/s3control/models.py
index f8b0951d8..ba573f4f4 100644
--- a/moto/s3control/models.py
+++ b/moto/s3control/models.py
@@ -1,7 +1,8 @@
from collections import defaultdict
from datetime import datetime
from moto.core import BaseBackend, BaseModel
-from moto.core.utils import get_random_hex, BackendDict
+from moto.core.utils import BackendDict
+from moto.moto_api._internal import mock_random
from moto.s3.exceptions import (
WrongPublicAccessBlockAccountIdError,
NoSuchPublicAccessBlockConfiguration,
@@ -22,7 +23,7 @@ class AccessPoint(BaseModel):
public_access_block_configuration,
):
self.name = name
- self.alias = f"{name}-{get_random_hex(34)}-s3alias"
+ self.alias = f"{name}-{mock_random.get_random_hex(34)}-s3alias"
self.bucket = bucket
self.created = datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")
self.arn = f"arn:aws:s3:us-east-1:{account_id}:accesspoint/{name}"
diff --git a/moto/s3control/responses.py b/moto/s3control/responses.py
index 1c166d478..18c7231d0 100644
--- a/moto/s3control/responses.py
+++ b/moto/s3control/responses.py
@@ -2,9 +2,9 @@ import json
import xmltodict
from moto.core.responses import BaseResponse
-from moto.core.utils import amzn_request_id
from moto.s3.exceptions import S3ClientError
from moto.s3.responses import S3_PUBLIC_ACCESS_BLOCK_CONFIGURATION
+from moto.utilities.aws_headers import amzn_request_id
from .models import s3control_backends
diff --git a/moto/sagemaker/responses.py b/moto/sagemaker/responses.py
index 195678502..a2bcbdff5 100644
--- a/moto/sagemaker/responses.py
+++ b/moto/sagemaker/responses.py
@@ -3,7 +3,7 @@ import json
from moto.sagemaker.exceptions import AWSValidationException
from moto.core.responses import BaseResponse
-from moto.core.utils import amzn_request_id
+from moto.utilities.aws_headers import amzn_request_id
from .models import sagemaker_backends
diff --git a/moto/secretsmanager/models.py b/moto/secretsmanager/models.py
index 91ff04760..dd1e7d66c 100644
--- a/moto/secretsmanager/models.py
+++ b/moto/secretsmanager/models.py
@@ -1,12 +1,12 @@
import time
import json
-import uuid
import datetime
from typing import List, Tuple
from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict
+from moto.moto_api._internal import mock_random
from .exceptions import (
SecretNotFoundException,
SecretHasNoValueException,
@@ -221,7 +221,7 @@ class SecretsManagerBackend(BaseBackend):
if version_id:
self._client_request_token_validator(version_id)
else:
- version_id = str(uuid.uuid4())
+ version_id = str(mock_random.uuid4())
return version_id
def get_secret_value(self, secret_id, version_id, version_stage):
@@ -512,7 +512,7 @@ class SecretsManagerBackend(BaseBackend):
self._client_request_token_validator(client_request_token)
new_version_id = client_request_token
else:
- new_version_id = str(uuid.uuid4())
+ new_version_id = str(mock_random.uuid4())
# We add the new secret version as "pending". The previous version remains
# as "current" for now. Once we've passed the new secret through the lambda
diff --git a/moto/secretsmanager/utils.py b/moto/secretsmanager/utils.py
index e46b36717..684e0c337 100644
--- a/moto/secretsmanager/utils.py
+++ b/moto/secretsmanager/utils.py
@@ -1,6 +1,6 @@
-import random
import string
import re
+from moto.moto_api._internal import mock_random as random
def random_password(
diff --git a/moto/servicediscovery/models.py b/moto/servicediscovery/models.py
index 2753d79e0..1c8a5ce7f 100644
--- a/moto/servicediscovery/models.py
+++ b/moto/servicediscovery/models.py
@@ -1,8 +1,8 @@
-import random
import string
from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict, unix_time
+from moto.moto_api._internal import mock_random as random
from moto.utilities.tagging_service import TaggingService
from .exceptions import (
diff --git a/moto/ses/utils.py b/moto/ses/utils.py
index 96445ad5f..5f40f8f4b 100644
--- a/moto/ses/utils.py
+++ b/moto/ses/utils.py
@@ -1,6 +1,6 @@
-import random
import string
from email.utils import parseaddr
+from moto.moto_api._internal import mock_random as random
def random_hex(length):
diff --git a/moto/signer/models.py b/moto/signer/models.py
index 85d974cb2..323c0320c 100644
--- a/moto/signer/models.py
+++ b/moto/signer/models.py
@@ -1,5 +1,6 @@
from moto.core import BaseBackend, BaseModel
-from moto.core.utils import BackendDict, get_random_hex
+from moto.core.utils import BackendDict
+from moto.moto_api._internal import mock_random
class SigningProfile(BaseModel):
@@ -16,7 +17,7 @@ class SigningProfile(BaseModel):
self.status = "Active"
self.arn = f"arn:aws:signer:{region}:{account_id}:/signing-profiles/{name}"
- self.profile_version = get_random_hex(10)
+ self.profile_version = mock_random.get_random_hex(10)
self.profile_version_arn = f"{self.arn}/{self.profile_version}"
def cancel(self):
diff --git a/moto/sns/models.py b/moto/sns/models.py
index 3af72f86c..2279f33d6 100644
--- a/moto/sns/models.py
+++ b/moto/sns/models.py
@@ -1,5 +1,4 @@
import datetime
-import uuid
import json
import requests
@@ -12,6 +11,7 @@ from moto.core.utils import (
camelcase_to_underscores,
BackendDict,
)
+from moto.moto_api._internal import mock_random
from moto.sqs import sqs_backends
from moto.sqs.exceptions import MissingParameter
@@ -60,7 +60,7 @@ class Topic(CloudFormationModel):
self.content_based_deduplication = "false"
def publish(self, message, subject=None, message_attributes=None, group_id=None):
- message_id = str(uuid.uuid4())
+ message_id = str(mock_random.uuid4())
subscriptions, _ = self.sns_backend.list_subscriptions(self.arn)
for subscription in subscriptions:
subscription.publish(
@@ -424,7 +424,7 @@ class PlatformEndpoint(BaseModel):
self.custom_user_data = custom_user_data
self.token = token
self.attributes = attributes
- self.id = uuid.uuid4()
+ self.id = mock_random.uuid4()
self.arn = f"arn:aws:sns:{region}:{account_id}:endpoint/{self.application.platform}/{self.application.name}/{self.id}"
self.messages = OrderedDict()
self.__fixup_attributes()
@@ -449,7 +449,7 @@ class PlatformEndpoint(BaseModel):
raise SnsEndpointDisabled("Endpoint %s disabled" % self.id)
# This is where we would actually send a message
- message_id = str(uuid.uuid4())
+ message_id = str(mock_random.uuid4())
self.messages[message_id] = message
return message_id
@@ -651,7 +651,7 @@ class SNSBackend(BaseBackend):
if len(message) > MAXIMUM_SMS_MESSAGE_BYTES:
raise ValueError("SMS message must be less than 1600 bytes")
- message_id = str(uuid.uuid4())
+ message_id = str(mock_random.uuid4())
self.sms_messages[message_id] = (phone_number, message)
return message_id
diff --git a/moto/sns/utils.py b/moto/sns/utils.py
index 41839c372..d2bee67b7 100644
--- a/moto/sns/utils.py
+++ b/moto/sns/utils.py
@@ -1,5 +1,5 @@
import re
-import uuid
+from moto.moto_api._internal import mock_random
E164_REGEX = re.compile(r"^\+?[1-9]\d{1,14}$")
@@ -9,7 +9,7 @@ def make_arn_for_topic(account_id, name, region_name):
def make_arn_for_subscription(topic_arn):
- subscription_id = uuid.uuid4()
+ subscription_id = mock_random.uuid4()
return "{0}:{1}".format(topic_arn, subscription_id)
diff --git a/moto/sqs/models.py b/moto/sqs/models.py
index 32abbb1df..c3666befb 100644
--- a/moto/sqs/models.py
+++ b/moto/sqs/models.py
@@ -1,7 +1,6 @@
import base64
import hashlib
import json
-import random
import re
import string
@@ -14,12 +13,12 @@ from moto.core.exceptions import RESTError
from moto.core import BaseBackend, BaseModel, CloudFormationModel
from moto.core.utils import (
camelcase_to_underscores,
- get_random_message_id,
unix_time,
unix_time_millis,
tags_from_cloudformation_tags_list,
BackendDict,
)
+from moto.moto_api._internal import mock_random as random
from moto.utilities.utils import md5_hash
from .utils import generate_receipt_handle
from .exceptions import (
@@ -763,7 +762,7 @@ class SQSBackend(BaseBackend):
else:
delay_seconds = queue.delay_seconds
- message_id = get_random_message_id()
+ message_id = str(random.uuid4())
message = Message(message_id, message_body, system_attributes)
# if content based deduplication is set then set sha256 hash of the message
diff --git a/moto/sqs/responses.py b/moto/sqs/responses.py
index 28fd57e85..0877c43ee 100644
--- a/moto/sqs/responses.py
+++ b/moto/sqs/responses.py
@@ -2,12 +2,8 @@ import re
from moto.core.exceptions import RESTError
from moto.core.responses import BaseResponse
-from moto.core.utils import (
- amz_crc32,
- amzn_request_id,
- underscores_to_camelcase,
- camelcase_to_pascal,
-)
+from moto.core.utils import underscores_to_camelcase, camelcase_to_pascal
+from moto.utilities.aws_headers import amz_crc32, amzn_request_id
from urllib.parse import urlparse
from .exceptions import (
diff --git a/moto/sqs/utils.py b/moto/sqs/utils.py
index 24d374248..fde3dab39 100644
--- a/moto/sqs/utils.py
+++ b/moto/sqs/utils.py
@@ -1,6 +1,5 @@
-import random
import string
-
+from moto.moto_api._internal import mock_random as random
from .exceptions import MessageAttributesInvalid
diff --git a/moto/ssm/models.py b/moto/ssm/models.py
index d29aad2ac..6f8f43601 100644
--- a/moto/ssm/models.py
+++ b/moto/ssm/models.py
@@ -14,12 +14,10 @@ from moto.utilities.utils import load_resource
import datetime
import time
-import uuid
import json
import yaml
import hashlib
-import random
-
+from moto.moto_api._internal import mock_random as random
from .utils import parameter_arn, convert_to_params
from .exceptions import (
ValidationException,
@@ -576,7 +574,7 @@ class Command(BaseModel):
if targets is None:
targets = []
- self.command_id = str(uuid.uuid4())
+ self.command_id = str(random.uuid4())
self.status = "Success"
self.status_details = "Details placeholder"
self.account_id = account_id
diff --git a/moto/ssoadmin/models.py b/moto/ssoadmin/models.py
index 26a743c34..abe79d11b 100644
--- a/moto/ssoadmin/models.py
+++ b/moto/ssoadmin/models.py
@@ -2,8 +2,7 @@ from .exceptions import ResourceNotFound
from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict, unix_time
-from uuid import uuid4
-import random
+from moto.moto_api._internal import mock_random as random
from moto.utilities.paginator import paginate
from .utils import PAGINATION_MODEL
@@ -18,7 +17,7 @@ class AccountAssignment(BaseModel):
principal_type,
principal_id,
):
- self.request_id = str(uuid4())
+ self.request_id = str(random.uuid4())
self.instance_arn = instance_arn
self.target_id = target_id
self.target_type = target_type
diff --git a/moto/ssoadmin/responses.py b/moto/ssoadmin/responses.py
index e5a70a9be..83ad84388 100644
--- a/moto/ssoadmin/responses.py
+++ b/moto/ssoadmin/responses.py
@@ -1,7 +1,7 @@
import json
from moto.core.responses import BaseResponse
-from uuid import uuid4
+from moto.moto_api._internal import mock_random
from .models import ssoadmin_backends
@@ -34,7 +34,7 @@ class SSOAdminResponse(BaseResponse):
principal_id=principal_id,
)
summary["Status"] = "SUCCEEDED"
- summary["RequestId"] = str(uuid4())
+ summary["RequestId"] = str(mock_random.uuid4())
return json.dumps({"AccountAssignmentCreationStatus": summary})
def delete_account_assignment(self):
@@ -54,7 +54,7 @@ class SSOAdminResponse(BaseResponse):
principal_id=principal_id,
)
summary["Status"] = "SUCCEEDED"
- summary["RequestId"] = str(uuid4())
+ summary["RequestId"] = str(mock_random.uuid4())
return json.dumps({"AccountAssignmentDeletionStatus": summary})
def list_account_assignments(self):
diff --git a/moto/stepfunctions/models.py b/moto/stepfunctions/models.py
index aebf5c18a..54da2cbf6 100644
--- a/moto/stepfunctions/models.py
+++ b/moto/stepfunctions/models.py
@@ -5,7 +5,7 @@ from dateutil.tz import tzlocal
from moto.core import BaseBackend, CloudFormationModel
from moto.core.utils import iso_8601_datetime_with_milliseconds, BackendDict
-from uuid import uuid4
+from moto.moto_api._internal import mock_random
from .exceptions import (
ExecutionAlreadyExists,
ExecutionDoesNotExist,
@@ -498,7 +498,7 @@ class StepFunctionBackend(BaseBackend):
execution = state_machine.start_execution(
region_name=self.region_name,
account_id=self.account_id,
- execution_name=name or str(uuid4()),
+ execution_name=name or str(mock_random.uuid4()),
execution_input=execution_input,
)
return execution
diff --git a/moto/stepfunctions/responses.py b/moto/stepfunctions/responses.py
index 540a38d06..d13b14ee5 100644
--- a/moto/stepfunctions/responses.py
+++ b/moto/stepfunctions/responses.py
@@ -1,7 +1,7 @@
import json
from moto.core.responses import BaseResponse
-from moto.core.utils import amzn_request_id
+from moto.utilities.aws_headers import amzn_request_id
from .models import stepfunction_backends
diff --git a/moto/sts/utils.py b/moto/sts/utils.py
index fd3f2ac87..eda8ed851 100644
--- a/moto/sts/utils.py
+++ b/moto/sts/utils.py
@@ -1,7 +1,7 @@
import base64
import os
-import random
import string
+from moto.moto_api._internal import mock_random as random
ACCOUNT_SPECIFIC_ACCESS_KEY_PREFIX = "8NWMTLYQ"
ACCOUNT_SPECIFIC_ASSUMED_ROLE_ID_PREFIX = "3X42LBCD"
diff --git a/moto/support/models.py b/moto/support/models.py
index b65ef0069..6533e9add 100644
--- a/moto/support/models.py
+++ b/moto/support/models.py
@@ -2,9 +2,9 @@ from moto.core import BaseBackend
from moto.core.utils import BackendDict
from moto.moto_api import state_manager
from moto.moto_api._internal.managed_state_model import ManagedState
+from moto.moto_api._internal import mock_random as random
from moto.utilities.utils import load_resource
import datetime
-import random
checks_json = "resources/describe_trusted_advisor_checks.json"
diff --git a/moto/swf/models/activity_task.py b/moto/swf/models/activity_task.py
index 8d3ce0c4b..2119188fa 100644
--- a/moto/swf/models/activity_task.py
+++ b/moto/swf/models/activity_task.py
@@ -1,8 +1,8 @@
from datetime import datetime
-import uuid
from moto.core import BaseModel
from moto.core.utils import unix_time
+from moto.moto_api._internal import mock_random
from ..exceptions import SWFWorkflowExecutionClosedError
from .timeout import Timeout
@@ -26,7 +26,7 @@ class ActivityTask(BaseModel):
self.scheduled_event_id = scheduled_event_id
self.started_event_id = None
self.state = "SCHEDULED"
- self.task_token = str(uuid.uuid4())
+ self.task_token = str(mock_random.uuid4())
self.timeouts = timeouts
self.timeout_type = None
self.workflow_execution = workflow_execution
diff --git a/moto/swf/models/decision_task.py b/moto/swf/models/decision_task.py
index 980d5c12f..ead089c5f 100644
--- a/moto/swf/models/decision_task.py
+++ b/moto/swf/models/decision_task.py
@@ -1,8 +1,8 @@
from datetime import datetime
-import uuid
from moto.core import BaseModel
from moto.core.utils import unix_time
+from moto.moto_api._internal import mock_random
from ..exceptions import SWFWorkflowExecutionClosedError
from .timeout import Timeout
@@ -12,7 +12,7 @@ class DecisionTask(BaseModel):
def __init__(self, workflow_execution, scheduled_event_id):
self.workflow_execution = workflow_execution
self.workflow_type = workflow_execution.workflow_type
- self.task_token = str(uuid.uuid4())
+ self.task_token = str(mock_random.uuid4())
self.scheduled_event_id = scheduled_event_id
self.previous_started_event_id = None
self.started_event_id = None
diff --git a/moto/swf/models/workflow_execution.py b/moto/swf/models/workflow_execution.py
index 4cbeee7e6..b02a8cd15 100644
--- a/moto/swf/models/workflow_execution.py
+++ b/moto/swf/models/workflow_execution.py
@@ -1,8 +1,8 @@
-import uuid
from threading import Timer as ThreadingTimer, Lock
from moto.core import BaseModel
from moto.core.utils import camelcase_to_underscores, unix_time
+from moto.moto_api._internal import mock_random
from ..constants import DECISIONS_FIELDS
from ..exceptions import (
@@ -43,7 +43,7 @@ class WorkflowExecution(BaseModel):
def __init__(self, domain, workflow_type, workflow_id, **kwargs):
self.domain = domain
self.workflow_id = workflow_id
- self.run_id = uuid.uuid4().hex
+ self.run_id = mock_random.uuid4().hex
# WorkflowExecutionInfo
self.cancel_requested = False
# TODO: check valid values among:
diff --git a/moto/textract/models.py b/moto/textract/models.py
index de5055738..93e25a095 100644
--- a/moto/textract/models.py
+++ b/moto/textract/models.py
@@ -1,11 +1,10 @@
"""TextractBackend class with methods for supported APIs."""
-import uuid
-from random import randint
from collections import defaultdict
from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict
+from moto.moto_api._internal import mock_random
from .exceptions import InvalidParameterException, InvalidJobIdException
@@ -29,7 +28,7 @@ class TextractBackend(BaseBackend):
"""Implementation of Textract APIs."""
JOB_STATUS = TextractJobStatus.succeeded
- PAGES = {"Pages": randint(5, 500)}
+ PAGES = {"Pages": mock_random.randint(5, 500)}
BLOCKS = []
def __init__(self, region_name, account_id):
@@ -51,7 +50,7 @@ class TextractBackend(BaseBackend):
"""
if not document_location:
raise InvalidParameterException()
- job_id = str(uuid.uuid4())
+ job_id = str(mock_random.uuid4())
self.async_text_detection_jobs[job_id] = TextractJob(
{
"Blocks": TextractBackend.BLOCKS,
diff --git a/moto/transcribe/models.py b/moto/transcribe/models.py
index 79fd4b1d9..7e44f6c81 100644
--- a/moto/transcribe/models.py
+++ b/moto/transcribe/models.py
@@ -1,8 +1,8 @@
-import uuid
from datetime import datetime, timedelta
from moto.core import BaseBackend, BaseModel
from moto.core.utils import BackendDict
from moto.moto_api import state_manager
+from moto.moto_api._internal import mock_random
from moto.moto_api._internal.managed_state_model import ManagedState
from .exceptions import ConflictException, BadRequestException
@@ -204,7 +204,7 @@ class FakeTranscriptionJob(BaseObject, ManagedState):
self._region_name,
self._account_id,
self.transcription_job_name,
- uuid.uuid4(),
+ mock_random.uuid4(),
)
self.output_location_type = "SERVICE_BUCKET"
self.transcript = {"TranscriptFileUri": transcript_file_uri}
@@ -234,7 +234,7 @@ class FakeVocabulary(BaseObject, ManagedState):
self.last_modified_time = None
self.failure_reason = None
self.download_uri = "https://s3.{0}.amazonaws.com/aws-transcribe-dictionary-model-{0}-prod/{1}/{2}/{3}/input.txt".format( # noqa: E501
- region_name, account_id, vocabulary_name, uuid
+ region_name, account_id, vocabulary_name, mock_random.uuid4()
)
def response_object(self, response_type):
@@ -437,7 +437,7 @@ class FakeMedicalVocabulary(FakeVocabulary):
self.last_modified_time = None
self.failure_reason = None
self.download_uri = "https://s3.us-east-1.amazonaws.com/aws-transcribe-dictionary-model-{}-prod/{}/medical/{}/{}/input.txt".format( # noqa: E501
- region_name, account_id, self.vocabulary_name, uuid.uuid4()
+ region_name, account_id, self.vocabulary_name, mock_random.uuid4()
)
diff --git a/moto/transcribe/responses.py b/moto/transcribe/responses.py
index 05e06bab7..ba9f52a01 100644
--- a/moto/transcribe/responses.py
+++ b/moto/transcribe/responses.py
@@ -1,7 +1,7 @@
import json
from moto.core.responses import BaseResponse
-from moto.core.utils import amzn_request_id
+from moto.utilities.aws_headers import amzn_request_id
from .models import transcribe_backends
diff --git a/moto/utilities/aws_headers.py b/moto/utilities/aws_headers.py
new file mode 100644
index 000000000..29b817fac
--- /dev/null
+++ b/moto/utilities/aws_headers.py
@@ -0,0 +1,85 @@
+from functools import wraps
+
+import binascii
+import re
+from moto.moto_api._internal import mock_random as random
+
+
+def gen_amz_crc32(response, headerdict=None):
+ if not isinstance(response, bytes):
+ response = response.encode("utf-8")
+
+ crc = binascii.crc32(response)
+
+ if headerdict is not None and isinstance(headerdict, dict):
+ headerdict.update({"x-amz-crc32": str(crc)})
+
+ return crc
+
+
+def gen_amzn_requestid_long(headerdict=None):
+ req_id = random.get_random_string(length=52)
+
+ if headerdict is not None and isinstance(headerdict, dict):
+ headerdict.update({"x-amzn-requestid": req_id})
+
+ return req_id
+
+
+def amz_crc32(f):
+ @wraps(f)
+ def _wrapper(*args, **kwargs):
+ response = f(*args, **kwargs)
+
+ headers = {}
+ status = 200
+
+ if isinstance(response, str):
+ body = response
+ else:
+ if len(response) == 2:
+ body, new_headers = response
+ status = new_headers.get("status", 200)
+ else:
+ status, new_headers, body = response
+ headers.update(new_headers)
+ # Cast status to string
+ if "status" in headers:
+ headers["status"] = str(headers["status"])
+
+ gen_amz_crc32(body, headers)
+
+ return status, headers, body
+
+ return _wrapper
+
+
+def amzn_request_id(f):
+ @wraps(f)
+ def _wrapper(*args, **kwargs):
+ response = f(*args, **kwargs)
+
+ headers = {}
+ status = 200
+
+ if isinstance(response, str):
+ body = response
+ else:
+ if len(response) == 2:
+ body, new_headers = response
+ status = new_headers.get("status", 200)
+ else:
+ status, new_headers, body = response
+ headers.update(new_headers)
+
+ request_id = gen_amzn_requestid_long(headers)
+
+ # Update request ID in XML
+ try:
+ body = re.sub(r"(?<=).*(?=<\/RequestId>)", request_id, body)
+ except Exception: # Will just ignore if it cant work
+ pass
+
+ return status, headers, body
+
+ return _wrapper
diff --git a/moto/utilities/utils.py b/moto/utilities/utils.py
index 636e71e1e..878642711 100644
--- a/moto/utilities/utils.py
+++ b/moto/utilities/utils.py
@@ -1,7 +1,5 @@
import json
import hashlib
-import random
-import string
import pkgutil
@@ -15,14 +13,6 @@ def str2bool(v):
return False
-def random_string(length=None):
- n = length or 20
- random_str = "".join(
- [random.choice(string.ascii_letters + string.digits) for i in range(n)]
- )
- return random_str
-
-
def load_resource(package, resource, as_json=True):
"""
Open a file, and return the contents as JSON.
diff --git a/moto/wafv2/models.py b/moto/wafv2/models.py
index 18086999b..2432ac731 100644
--- a/moto/wafv2/models.py
+++ b/moto/wafv2/models.py
@@ -1,12 +1,12 @@
import datetime
import re
from typing import Dict
-from uuid import uuid4
from moto.core import BaseBackend, BaseModel
from .utils import make_arn_for_wacl
from .exceptions import WAFV2DuplicateItemException, WAFNonexistentItemException
from moto.core.utils import iso_8601_datetime_with_milliseconds, BackendDict
+from moto.moto_api._internal import mock_random
from moto.utilities.tagging_service import TaggingService
from collections import OrderedDict
@@ -36,7 +36,7 @@ class FakeWebACL(BaseModel):
self.rules = rules
self.visibility_config = visibility_config
self.default_action = default_action
- self.lock_token = str(uuid4())[0:6]
+ self.lock_token = str(mock_random.uuid4())[0:6]
def update(self, default_action, rules, description, visibility_config):
if default_action is not None:
@@ -47,7 +47,7 @@ class FakeWebACL(BaseModel):
self.description = description
if visibility_config is not None:
self.visibility_config = visibility_config
- self.lock_token = str(uuid4())[0:6]
+ self.lock_token = str(mock_random.uuid4())[0:6]
def to_dict(self):
# Format for summary https://docs.aws.amazon.com/waf/latest/APIReference/API_CreateWebACL.html (response syntax section)
@@ -115,7 +115,7 @@ class WAFV2Backend(BaseBackend):
"""
The following parameters are not yet implemented: CustomResponseBodies, CaptchaConfig
"""
- wacl_id = str(uuid4())
+ wacl_id = str(mock_random.uuid4())
arn = make_arn_for_wacl(
name=name,
account_id=self.account_id,
diff --git a/moto/wafv2/responses.py b/moto/wafv2/responses.py
index 68bcce7ac..be327ea94 100644
--- a/moto/wafv2/responses.py
+++ b/moto/wafv2/responses.py
@@ -1,7 +1,6 @@
import json
-from moto.core.utils import amzn_request_id
-
from moto.core.responses import BaseResponse
+from moto.utilities.aws_headers import amzn_request_id
from .models import GLOBAL_REGION, wafv2_backends
diff --git a/tests/test_cognitoidp/test_cognitoidp_replay.py b/tests/test_cognitoidp/test_cognitoidp_replay.py
new file mode 100644
index 000000000..0dbc71739
--- /dev/null
+++ b/tests/test_cognitoidp/test_cognitoidp_replay.py
@@ -0,0 +1,114 @@
+import os
+
+import boto3
+import uuid
+import sure # noqa # pylint: disable=unused-import
+import pytest
+import requests
+
+from botocore.exceptions import ClientError
+from moto import mock_cognitoidp, settings
+from moto.moto_api import recorder
+from unittest import TestCase
+
+
+@mock_cognitoidp
+class TestCreateUserPoolWithPredeterminedID(TestCase):
+ def _reset_recording(self):
+ if settings.TEST_SERVER_MODE:
+ requests.post("http://localhost:5000/moto-api/recorder/reset-recording")
+ else:
+ recorder.reset_recording()
+
+ def _start_recording(self):
+ if settings.TEST_SERVER_MODE:
+ requests.post("http://localhost:5000/moto-api/recorder/start-recording")
+ else:
+ recorder.start_recording()
+
+ def _stop_recording(self):
+ if settings.TEST_SERVER_MODE:
+ requests.post("http://localhost:5000/moto-api/recorder/stop-recording")
+ else:
+ recorder.stop_recording()
+
+ def _download_recording(self):
+ if settings.TEST_SERVER_MODE:
+ resp = requests.get(
+ "http://localhost:5000/moto-api/recorder/download-recording"
+ )
+ resp.status_code.should.equal(200)
+ return resp.content.decode("utf-8")
+ else:
+ return recorder.download_recording()
+
+ def _upload_recording(self, logs):
+ if settings.TEST_SERVER_MODE:
+ requests.post(
+ "http://localhost:5000/moto-api/recorder/upload-recording", data=logs
+ )
+ else:
+ recorder.upload_recording(logs)
+
+ def _replay_recording(self):
+ if settings.TEST_SERVER_MODE:
+ requests.post("http://localhost:5000/moto-api/recorder/replay-recording")
+ else:
+ recorder.replay_recording()
+
+ def _set_seed(self, a):
+ if settings.TEST_SERVER_MODE:
+ requests.post(f"http://localhost:5000/moto-api/seed?a={a}")
+ else:
+ requests.post(f"http://motoapi.amazonaws.com/moto-api/seed?a={a}")
+
+ def setUp(self) -> None:
+ self.client = boto3.client("cognito-idp", "us-west-2")
+ self.random_seed = 42
+
+ # start recording
+ self._reset_recording()
+ self._start_recording()
+ # Create UserPool
+ name = str(uuid.uuid4())
+ value = str(uuid.uuid4())
+ self._set_seed(self.random_seed)
+ resp = self.client.create_user_pool(
+ PoolName=name, LambdaConfig={"PreSignUp": value}
+ )
+ self.pool_id = resp["UserPool"]["Id"]
+
+ # stop recording
+ self._stop_recording()
+ # delete user pool
+ self.client.delete_user_pool(UserPoolId=self.pool_id)
+
+ def tearDown(self) -> None:
+ self._stop_recording()
+ try:
+ os.remove("moto_recording")
+ except: # noqa: E722 Do not use bare except
+ pass
+
+ def test_same_seed(self):
+ # replay recording
+ self._replay_recording()
+ # assert userpool is is the same - it will throw an error if it doesn't exist
+ self.client.describe_user_pool(UserPoolId=self.pool_id)
+
+ def test_different_seed(self):
+ # set seed to different number
+ logs = self._download_recording()
+ logs = logs.replace("/seed?a=42", "/seed?a=43")
+ self._upload_recording(logs)
+ # replay recording, and recreate a userpool
+ self._replay_recording()
+ # assert the ID of this userpool is now different
+ with pytest.raises(ClientError) as exc:
+ self.client.describe_user_pool(UserPoolId=self.pool_id)
+ err = exc.value.response["Error"]
+ err["Code"].should.equal("ResourceNotFoundException")
+
+ # It is created - just with a different ID
+ all_pools = self.client.list_user_pools(MaxResults=5)["UserPools"]
+ all_pools.should.have.length_of(1)
diff --git a/tests/test_config/test_config_rules.py b/tests/test_config/test_config_rules.py
index 12e752b6a..35dba4b11 100644
--- a/tests/test_config/test_config_rules.py
+++ b/tests/test_config/test_config_rules.py
@@ -13,9 +13,9 @@ from botocore.exceptions import ClientError
import pytest
from moto.config import mock_config
-from moto.config.models import random_string
from moto.config.models import ConfigRule, CONFIG_RULE_PAGE_SIZE
from moto import settings
+from moto.moto_api._internal import mock_random
TEST_REGION = "us-east-1" if settings.TEST_SERVER_MODE else "us-west-2"
@@ -23,7 +23,7 @@ TEST_REGION = "us-east-1" if settings.TEST_SERVER_MODE else "us-west-2"
def managed_config_rule():
"""Return a valid managed AWS Config Rule."""
return {
- "ConfigRuleName": f"managed_rule_{random_string()}",
+ "ConfigRuleName": f"managed_rule_{mock_random.get_random_string()}",
"Description": "Managed S3 Public Read Prohibited Bucket Rule",
"Scope": {"ComplianceResourceTypes": ["AWS::S3::Bucket", "AWS::IAM::Group"]},
"Source": {
@@ -220,7 +220,7 @@ def test_aws_managed_rule_errors():
)
# If no MaxExecutionFrequency specified, set it to the default.
- # rule_name = f"managed_rule_{random_string()}"
+ # rule_name = f"managed_rule_{mock_random.get_random_string()}"
# managed_rule = {
# "ConfigRuleName": rule_name,
# "Description": "Managed S3 Public Read Prohibited Bucket Rule",
@@ -348,7 +348,7 @@ def test_valid_put_config_managed_rule():
# Valid InputParameters.
managed_rule = {
- "ConfigRuleName": f"input_param_test_{random_string()}",
+ "ConfigRuleName": f"input_param_test_{mock_random.get_random_string()}",
"Description": "Provide subset of allowed input parameters",
"InputParameters": '{"blockedPort1":"22","blockedPort2":"3389"}',
"Scope": {"ComplianceResourceTypes": ["AWS::IAM::SecurityGroup"]},
diff --git a/tests/test_config/test_config_tags.py b/tests/test_config/test_config_tags.py
index b7257ec0e..67297fb90 100644
--- a/tests/test_config/test_config_tags.py
+++ b/tests/test_config/test_config_tags.py
@@ -13,8 +13,8 @@ import pytest
from moto.config import mock_config
from moto.config.models import MAX_TAGS_IN_ARG
-from moto.config.models import random_string
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
+from moto.moto_api._internal import mock_random
TEST_REGION = "us-east-1"
@@ -31,7 +31,7 @@ def config_aggregators_info(client):
{"Key": f"{x}", "Value": f"{x}"} for x in range(idx * 10, idx * 10 + 10)
]
response = client.put_configuration_aggregator(
- ConfigurationAggregatorName=f"testing_{idx}_{random_string()}",
+ ConfigurationAggregatorName=f"testing_{idx}_{mock_random.get_random_string()}",
AccountAggregationSources=[
{"AccountIds": [ACCOUNT_ID], "AllAwsRegions": True}
],
@@ -126,7 +126,7 @@ def test_tag_resource():
assert tags == updated_rsp["Tags"]
# Verify keys added to ConfigRule.
- config_rule_name = f"config-rule-test-{random_string()}"
+ config_rule_name = f"config-rule-test-{mock_random.get_random_string()}"
client.put_config_rule(
ConfigRule={
"ConfigRuleName": config_rule_name,
@@ -248,7 +248,7 @@ def test_untag_resource():
# Verify keys removed from ConfigRule. Add a new tag to the current set
# of tags, then delete the new tag. The original set of tags should remain.
- rule_name = f"config-rule-delete-tags-test-{random_string()}"
+ rule_name = f"config-rule-delete-tags-test-{mock_random.get_random_string()}"
client.put_config_rule(
ConfigRule={
"ConfigRuleName": rule_name,
diff --git a/tests/test_ds/test_ds.py b/tests/test_ds/test_ds.py
index cb50136c9..a8c772862 100644
--- a/tests/test_ds/test_ds.py
+++ b/tests/test_ds/test_ds.py
@@ -10,8 +10,8 @@ from botocore.exceptions import ClientError
import pytest
from moto import mock_ds
-from moto.core.utils import get_random_hex
from moto.ec2 import mock_ec2
+from moto.moto_api._internal import mock_random
from .test_ds_simple_ad_directory import create_test_directory, TEST_REGION
@@ -23,7 +23,7 @@ def test_ds_delete_directory():
client = boto3.client("ds", region_name=TEST_REGION)
# Delete a directory when there are none.
- random_directory_id = f"d-{get_random_hex(10)}"
+ random_directory_id = f"d-{mock_random.get_random_hex(10)}"
with pytest.raises(ClientError) as exc:
client.delete_directory(DirectoryId=random_directory_id)
err = exc.value.response["Error"]
@@ -47,7 +47,7 @@ def test_ds_delete_directory():
assert "directory controllers" not in group["Description"]
# Attempt to delete a non-existent directory.
- nonexistent_id = f"d-{get_random_hex(10)}"
+ nonexistent_id = f"d-{mock_random.get_random_hex(10)}"
with pytest.raises(ClientError) as exc:
client.delete_directory(DirectoryId=nonexistent_id)
err = exc.value.response["Error"]
@@ -55,7 +55,7 @@ def test_ds_delete_directory():
assert f"Directory {nonexistent_id} does not exist" in err["Message"]
# Attempt to use an invalid directory ID.
- bad_id = get_random_hex(3)
+ bad_id = mock_random.get_random_hex(3)
with pytest.raises(ClientError) as exc:
client.delete_directory(DirectoryId=bad_id)
err = exc.value.response["Error"]
@@ -136,7 +136,7 @@ def test_ds_describe_directories():
assert result["DirectoryDescriptions"][0]["DirectoryId"] == directory_ids[5]
# Test with a bad directory ID.
- bad_id = get_random_hex(3)
+ bad_id = mock_random.get_random_hex(3)
with pytest.raises(ClientError) as exc:
client.describe_directories(DirectoryIds=[bad_id])
err = exc.value.response["Error"]
@@ -177,7 +177,7 @@ def test_ds_create_alias():
directory_id = create_test_directory(client, ec2_client)
# Bad format.
- bad_alias = f"d-{get_random_hex(10)}"
+ bad_alias = f"d-{mock_random.get_random_hex(10)}"
with pytest.raises(ClientError) as exc:
client.create_alias(DirectoryId=directory_id, Alias=bad_alias)
err = exc.value.response["Error"]
@@ -189,7 +189,7 @@ def test_ds_create_alias():
) in err["Message"]
# Too long.
- bad_alias = f"d-{get_random_hex(62)}"
+ bad_alias = f"d-{mock_random.get_random_hex(62)}"
with pytest.raises(ClientError) as exc:
client.create_alias(DirectoryId=directory_id, Alias=bad_alias)
err = exc.value.response["Error"]
@@ -200,7 +200,7 @@ def test_ds_create_alias():
) in err["Message"]
# Just right.
- good_alias = f"{get_random_hex(10)}"
+ good_alias = f"{mock_random.get_random_hex(10)}"
result = client.create_alias(DirectoryId=directory_id, Alias=good_alias)
assert result["DirectoryId"] == directory_id
assert result["Alias"] == good_alias
@@ -210,7 +210,7 @@ def test_ds_create_alias():
assert directory["AccessUrl"] == f"{good_alias}.awsapps.com"
# Attempt to create another alias for the same directory.
- another_good_alias = f"{get_random_hex(10)}"
+ another_good_alias = f"{mock_random.get_random_hex(10)}"
with pytest.raises(ClientError) as exc:
client.create_alias(DirectoryId=directory_id, Alias=another_good_alias)
err = exc.value.response["Error"]
@@ -253,7 +253,7 @@ def test_ds_enable_sso():
# Password must be less than 128 chars in length.
good_username = "test"
- bad_password = f"bad_password{get_random_hex(128)}"
+ bad_password = f"bad_password{mock_random.get_random_hex(128)}"
with pytest.raises(ClientError) as exc:
client.enable_sso(
DirectoryId=directory_id, UserName=good_username, Password=bad_password
@@ -298,7 +298,7 @@ def test_ds_disable_sso():
# Password must be less than 128 chars in length.
good_username = "test"
- bad_password = f"bad_password{get_random_hex(128)}"
+ bad_password = f"bad_password{mock_random.get_random_hex(128)}"
with pytest.raises(ClientError) as exc:
client.disable_sso(
DirectoryId=directory_id, UserName=good_username, Password=bad_password
diff --git a/tests/test_ds/test_ds_ad_connect.py b/tests/test_ds/test_ds_ad_connect.py
index 5ce3e3a32..c2fd33c2e 100644
--- a/tests/test_ds/test_ds_ad_connect.py
+++ b/tests/test_ds/test_ds_ad_connect.py
@@ -10,8 +10,8 @@ from botocore.exceptions import ClientError
import pytest
from moto import mock_ds
-from moto.core.utils import get_random_hex
from moto.ec2 import mock_ec2
+from moto.moto_api._internal import mock_random
from .test_ds_simple_ad_directory import TEST_REGION, create_vpc, create_subnets
@@ -37,7 +37,7 @@ def create_test_ad_connector(
tags = []
result = ds_client.connect_directory(
- Name=f"test-{get_random_hex(6)}.test",
+ Name=f"test-{mock_random.get_random_hex(6)}.test",
Password="4ADConnectPassword",
Size="Small",
ConnectSettings={
@@ -59,7 +59,7 @@ def test_ds_connect_directory_validations():
this verifies that it is invoked from connect_directory().
"""
client = boto3.client("ds", region_name=TEST_REGION)
- random_num = get_random_hex(6)
+ random_num = mock_random.get_random_hex(6)
# Verify ValidationException error messages are accumulated properly.
bad_name = f"bad_name_{random_num}"
diff --git a/tests/test_ds/test_ds_microsoft_ad.py b/tests/test_ds/test_ds_microsoft_ad.py
index 2de06b6d6..ff28362fe 100644
--- a/tests/test_ds/test_ds_microsoft_ad.py
+++ b/tests/test_ds/test_ds_microsoft_ad.py
@@ -10,8 +10,8 @@ from botocore.exceptions import ClientError
import pytest
from moto import mock_ds
-from moto.core.utils import get_random_hex
from moto.ec2 import mock_ec2
+from moto.moto_api._internal import mock_random
from .test_ds_simple_ad_directory import TEST_REGION, create_vpc, create_subnets
@@ -27,7 +27,7 @@ def create_test_microsoft_ad(ds_client, ec2_client, vpc_settings=None, tags=None
tags = []
result = ds_client.create_microsoft_ad(
- Name=f"test-{get_random_hex(6)}.test",
+ Name=f"test-{mock_random.get_random_hex(6)}.test",
Password="4MicrosoftADPassword",
VpcSettings=vpc_settings,
Tags=tags,
@@ -44,7 +44,7 @@ def test_ds_create_microsoft_ad_validations():
this verifies that it is invoked from create_microsoft_ad().
"""
client = boto3.client("ds", region_name=TEST_REGION)
- random_num = get_random_hex(6)
+ random_num = mock_random.get_random_hex(6)
# Verify ValidationException error messages are accumulated properly.
bad_name = f"bad_name_{random_num}"
diff --git a/tests/test_ds/test_ds_simple_ad_directory.py b/tests/test_ds/test_ds_simple_ad_directory.py
index e87d06c6d..8ac856bce 100644
--- a/tests/test_ds/test_ds_simple_ad_directory.py
+++ b/tests/test_ds/test_ds_simple_ad_directory.py
@@ -5,8 +5,8 @@ import pytest
from moto import mock_ds
from moto import settings
-from moto.core.utils import get_random_hex
from moto.ec2 import mock_ec2
+from moto.moto_api._internal import mock_random
TEST_REGION = "us-east-1" if settings.TEST_SERVER_MODE else "us-west-2"
@@ -41,7 +41,7 @@ def create_test_directory(ds_client, ec2_client, vpc_settings=None, tags=None):
tags = []
result = ds_client.create_directory(
- Name=f"test-{get_random_hex(6)}.test",
+ Name=f"test-{mock_random.get_random_hex(6)}.test",
Password="Password4TheAges",
Size="Large",
VpcSettings=vpc_settings,
@@ -54,7 +54,7 @@ def create_test_directory(ds_client, ec2_client, vpc_settings=None, tags=None):
def test_ds_create_directory_validations():
"""Test validation errs that aren't caught by botocore."""
client = boto3.client("ds", region_name=TEST_REGION)
- random_num = get_random_hex(6)
+ random_num = mock_random.get_random_hex(6)
# Verify ValidationException error messages are accumulated properly.
bad_name = f"bad_name_{random_num}"
@@ -148,7 +148,9 @@ def test_ds_create_directory_bad_vpc_settings():
# Error if no VpcSettings argument.
with pytest.raises(ClientError) as exc:
client.create_directory(
- Name=f"test-{get_random_hex(6)}.test", Password="TESTfoobar1", Size="Small"
+ Name=f"test-{mock_random.get_random_hex(6)}.test",
+ Password="TESTfoobar1",
+ Size="Small",
)
err = exc.value.response["Error"]
assert err["Code"] == "InvalidParameterException"
diff --git a/tests/test_ec2/test_vpc_service_configuration.py b/tests/test_ec2/test_vpc_service_configuration.py
index 5192d7a25..77dfcfe35 100644
--- a/tests/test_ec2/test_vpc_service_configuration.py
+++ b/tests/test_ec2/test_vpc_service_configuration.py
@@ -4,7 +4,7 @@ import sure # noqa # pylint: disable=unused-import
from botocore.exceptions import ClientError
from moto import mock_ec2, mock_elbv2
-from moto.core.utils import get_random_hex
+from moto.moto_api._internal import mock_random
# See our Development Tips on writing tests for hints on how to write good tests:
# http://docs.getmoto.org/en/latest/docs/contributing/development_tips/tests.html
@@ -390,7 +390,7 @@ def create_load_balancer(region_name, zone, lb_type):
subnet = ec2.create_subnet(
VpcId=vpc.id, CidrBlock="172.28.7.192/26", AvailabilityZone=zone
)
- lb_name = f"lb_vpce-{get_random_hex(length=10)}"
+ lb_name = f"lb_vpce-{mock_random.get_random_hex(length=10)}"
response = elbv2.create_load_balancer(
Name=lb_name, Subnets=[subnet.id], Scheme="internal", Type=lb_type
)
diff --git a/tests/test_eks/test_eks.py b/tests/test_eks/test_eks.py
index 1cedb9e3a..1f6d96275 100644
--- a/tests/test_eks/test_eks.py
+++ b/tests/test_eks/test_eks.py
@@ -33,7 +33,7 @@ from moto.eks.models import (
NODEGROUP_NOT_FOUND_MSG,
)
from moto.eks.responses import DEFAULT_MAX_RESULTS
-from moto.utilities.utils import random_string
+from moto.moto_api._internal import mock_random
from .test_eks_constants import (
BatchCountSize,
@@ -516,14 +516,14 @@ def test_list_nodegroups_returns_custom_second_page_results(NodegroupBuilder):
@mock_eks
def test_create_nodegroup_throws_exception_when_cluster_not_found():
client = boto3.client(SERVICE, region_name=REGION)
- non_existent_cluster_name = random_string()
+ non_existent_cluster_name = mock_random.get_random_string()
expected_exception = ResourceNotFoundException
expected_msg = CLUSTER_NOT_FOUND_MSG.format(clusterName=non_existent_cluster_name)
with pytest.raises(ClientError) as raised_exception:
client.create_nodegroup(
clusterName=non_existent_cluster_name,
- nodegroupName=random_string(),
+ nodegroupName=mock_random.get_random_string(),
**dict(NodegroupInputs.REQUIRED)
)
@@ -571,7 +571,7 @@ def test_create_nodegroup_throws_exception_when_cluster_not_active(NodegroupBuil
with pytest.raises(ClientError) as raised_exception:
client.create_nodegroup(
clusterName=generated_test_data.cluster_name,
- nodegroupName=random_string(),
+ nodegroupName=mock_random.get_random_string(),
**dict(NodegroupInputs.REQUIRED)
)
count_nodegroups_after_test = len(
@@ -827,7 +827,7 @@ def test_create_nodegroup_handles_launch_template_combinations(
expected_result,
):
client, generated_test_data = ClusterBuilder()
- nodegroup_name = random_string()
+ nodegroup_name = mock_random.get_random_string()
expected_exception = InvalidParameterException
expected_msg = None
@@ -966,14 +966,14 @@ def test_list_fargate_profile_returns_custom_second_page_results(FargateProfileB
@mock_eks
def test_create_fargate_profile_throws_exception_when_cluster_not_found():
client = boto3.client(SERVICE, region_name=REGION)
- non_existent_cluster_name = random_string()
+ non_existent_cluster_name = mock_random.get_random_string()
expected_exception = ResourceNotFoundException
expected_msg = CLUSTER_NOT_FOUND_MSG.format(clusterName=non_existent_cluster_name)
with pytest.raises(ClientError) as raised_exception:
client.create_fargate_profile(
clusterName=non_existent_cluster_name,
- fargateProfileName=random_string(),
+ fargateProfileName=mock_random.get_random_string(),
**dict(FargateProfileInputs.REQUIRED)
)
@@ -1020,7 +1020,7 @@ def test_create_fargate_profile_throws_exception_when_cluster_not_active(
with pytest.raises(ClientError) as raised_exception:
client.create_fargate_profile(
clusterName=generated_test_data.cluster_name,
- fargateProfileName=random_string(),
+ fargateProfileName=mock_random.get_random_string(),
**dict(FargateProfileInputs.REQUIRED)
)
count_fargate_profiles_after_test = len(
@@ -1188,7 +1188,7 @@ def test_delete_fargate_profile_throws_exception_when_fargate_profile_not_found(
def test_create_fargate_throws_exception_when_no_selectors_provided(ClusterBuilder):
client, generated_test_data = ClusterBuilder()
cluster_name = generated_test_data.existing_cluster_name
- fargate_profile_name = random_string()
+ fargate_profile_name = mock_random.get_random_string()
expected_exception = InvalidParameterException
expected_msg = FARGATE_PROFILE_NEEDS_SELECTOR_MSG
@@ -1327,7 +1327,7 @@ def test_create_fargate_selectors(
):
client, generated_test_data = ClusterBuilder()
cluster_name = generated_test_data.existing_cluster_name
- fargate_profile_name = random_string()
+ fargate_profile_name = mock_random.get_random_string()
expected_exception = InvalidParameterException
test_inputs = dict(
@@ -1392,7 +1392,7 @@ def assert_result_matches_expected_list(result, expected_result, expected_len):
def assert_valid_selectors(ClusterBuilder, expected_msg, expected_result, selectors):
client, generated_test_data = ClusterBuilder()
cluster_name = generated_test_data.existing_cluster_name
- fargate_profile_name = random_string()
+ fargate_profile_name = mock_random.get_random_string()
expected_exception = InvalidParameterException
test_inputs = dict(
diff --git a/tests/test_eks/test_eks_utils.py b/tests/test_eks/test_eks_utils.py
index 9ba361c05..6354c9ddb 100644
--- a/tests/test_eks/test_eks_utils.py
+++ b/tests/test_eks/test_eks_utils.py
@@ -6,7 +6,7 @@ try:
except ImportError:
from urlparse import urlparse
-from moto.utilities.utils import random_string as generate_random_name
+from moto.moto_api._internal import mock_random
from tests.test_eks.test_eks_constants import (
ClusterAttributes,
ClusterInputs,
@@ -19,6 +19,9 @@ from tests.test_eks.test_eks_constants import (
)
+generate_random_name = mock_random.get_random_string
+
+
def attributes_to_test(inputs, name):
"""
Assembles the list of tuples which will be used to validate test results.
diff --git a/tests/test_firehose/test_firehose.py b/tests/test_firehose/test_firehose.py
index ffcfd15d2..223d9baeb 100644
--- a/tests/test_firehose/test_firehose.py
+++ b/tests/test_firehose/test_firehose.py
@@ -9,8 +9,8 @@ import pytest
from moto import mock_firehose
from moto import settings
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
-from moto.core.utils import get_random_hex
from moto.firehose.models import DeliveryStream
+from moto.moto_api._internal import mock_random
TEST_REGION = "us-east-1" if settings.TEST_SERVER_MODE else "us-west-2"
@@ -33,7 +33,7 @@ def test_warnings():
s3_dest_config = sample_s3_dest_config()
# DeliveryStreamEncryption is not supported.
- stream_name = f"test_warning_{get_random_hex(6)}"
+ stream_name = f"test_warning_{mock_random.get_random_hex(6)}"
with warnings.catch_warnings(record=True) as warn_msg:
client.create_delivery_stream(
DeliveryStreamName=stream_name,
@@ -45,7 +45,7 @@ def test_warnings():
)
# Can't create a delivery stream for Splunk as it's unimplemented.
- stream_name = f"test_splunk_destination_{get_random_hex(6)}"
+ stream_name = f"test_splunk_destination_{mock_random.get_random_hex(6)}"
with warnings.catch_warnings(record=True) as warn_msg:
client.create_delivery_stream(
DeliveryStreamName=stream_name,
@@ -61,7 +61,7 @@ def test_warnings():
)
# Can't update a delivery stream to Splunk as it's unimplemented.
- stream_name = f"test_update_splunk_destination_{get_random_hex(6)}"
+ stream_name = f"test_update_splunk_destination_{mock_random.get_random_hex(6)}"
client.create_delivery_stream(
DeliveryStreamName=stream_name, S3DestinationConfiguration=s3_dest_config
)
@@ -87,7 +87,7 @@ def test_create_delivery_stream_failures():
"""Test errors invoking create_delivery_stream()."""
client = boto3.client("firehose", region_name=TEST_REGION)
s3_dest_config = sample_s3_dest_config()
- failure_name = f"test_failure_{get_random_hex(6)}"
+ failure_name = f"test_failure_{mock_random.get_random_hex(6)}"
# Create too many streams.
for idx in range(DeliveryStream.MAX_STREAMS_PER_REGION):
@@ -177,7 +177,7 @@ def test_delete_delivery_stream():
"""Test successful and failed invocations of delete_delivery_stream()."""
client = boto3.client("firehose", region_name=TEST_REGION)
s3_dest_config = sample_s3_dest_config()
- stream_name = f"test_delete_{get_random_hex(6)}"
+ stream_name = f"test_delete_{mock_random.get_random_hex(6)}"
# Create a couple of streams to test with.
for idx in range(5):
@@ -213,7 +213,7 @@ def test_describe_delivery_stream():
"""Test successful, failed invocations of describe_delivery_stream()."""
client = boto3.client("firehose", region_name=TEST_REGION)
s3_dest_config = sample_s3_dest_config()
- stream_name = f"test_describe_{get_random_hex(6)}"
+ stream_name = f"test_describe_{mock_random.get_random_hex(6)}"
role_arn = f"arn:aws:iam::{ACCOUNT_ID}:role/testrole"
# Create delivery stream with S3 destination, kinesis type and source
@@ -371,7 +371,7 @@ def test_list_delivery_streams():
"""Test successful and failed invocations of list_delivery_streams()."""
client = boto3.client("firehose", region_name=TEST_REGION)
s3_dest_config = sample_s3_dest_config()
- stream_name = f"test_list_{get_random_hex(6)}"
+ stream_name = f"test_list_{mock_random.get_random_hex(6)}"
# Create a couple of streams of both types to test with.
for idx in range(5):
@@ -463,7 +463,7 @@ def test_update_destination():
assert f"Firehose foo under accountId {ACCOUNT_ID} not found" in err["Message"]
# Create a delivery stream for testing purposes.
- stream_name = f"test_update_{get_random_hex(6)}"
+ stream_name = f"test_update_{mock_random.get_random_hex(6)}"
client.create_delivery_stream(
DeliveryStreamName=stream_name,
DeliveryStreamType="DirectPut",
diff --git a/tests/test_firehose/test_firehose_destination_types.py b/tests/test_firehose/test_firehose_destination_types.py
index 05f83a748..2f8b7599e 100644
--- a/tests/test_firehose/test_firehose_destination_types.py
+++ b/tests/test_firehose/test_firehose_destination_types.py
@@ -5,7 +5,7 @@ import sure # noqa # pylint: disable=unused-import
from moto import mock_firehose
from moto import settings
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
-from moto.core.utils import get_random_hex
+from moto.moto_api._internal import mock_random
TEST_REGION = "us-east-1" if settings.TEST_SERVER_MODE else "us-west-2"
@@ -118,7 +118,7 @@ def test_create_redshift_delivery_stream():
"""Verify fields of a Redshift delivery stream."""
client = boto3.client("firehose", region_name=TEST_REGION)
- stream_name = f"stream_{get_random_hex(6)}"
+ stream_name = f"stream_{mock_random.get_random_hex(6)}"
response = create_redshift_delivery_stream(client, stream_name)
stream_arn = response["DeliveryStreamARN"]
@@ -174,7 +174,7 @@ def test_create_extended_s3_delivery_stream():
"""Verify fields of a S3 delivery stream."""
client = boto3.client("firehose", region_name=TEST_REGION)
- stream_name = f"stream_{get_random_hex(6)}"
+ stream_name = f"stream_{mock_random.get_random_hex(6)}"
response = create_extended_s3_delivery_stream(client, stream_name)
stream_arn = response["DeliveryStreamARN"]
@@ -241,7 +241,7 @@ def test_create_elasticsearch_delivery_stream():
"""Verify fields of an Elasticsearch delivery stream."""
client = boto3.client("firehose", region_name=TEST_REGION)
- stream_name = f"stream_{get_random_hex(6)}"
+ stream_name = f"stream_{mock_random.get_random_hex(6)}"
response = create_elasticsearch_delivery_stream(client, stream_name)
stream_arn = response["DeliveryStreamARN"]
@@ -297,7 +297,7 @@ def test_create_s3_delivery_stream():
"""Verify fields of an S3 delivery stream."""
client = boto3.client("firehose", region_name=TEST_REGION)
- stream_name = f"stream_{get_random_hex(6)}"
+ stream_name = f"stream_{mock_random.get_random_hex(6)}"
response = client.create_delivery_stream(
DeliveryStreamName=stream_name,
S3DestinationConfiguration={
@@ -348,7 +348,7 @@ def test_create_http_stream():
"""Verify fields of a HTTP delivery stream."""
client = boto3.client("firehose", region_name=TEST_REGION)
- stream_name = f"stream_{get_random_hex(6)}"
+ stream_name = f"stream_{mock_random.get_random_hex(6)}"
response = create_http_delivery_stream(client, stream_name)
stream_arn = response["DeliveryStreamARN"]
diff --git a/tests/test_firehose/test_firehose_put.py b/tests/test_firehose/test_firehose_put.py
index 5704f0a06..f3473e3ca 100644
--- a/tests/test_firehose/test_firehose_put.py
+++ b/tests/test_firehose/test_firehose_put.py
@@ -5,7 +5,7 @@ import sure # noqa pylint: disable=unused-import
from moto import mock_firehose
from moto import mock_s3
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
-from moto.core.utils import get_random_hex
+from moto.moto_api._internal import mock_random
from tests.test_firehose.test_firehose import TEST_REGION
from tests.test_firehose.test_firehose import sample_s3_dest_config
from tests.test_firehose.test_firehose_destination_types import (
@@ -24,7 +24,7 @@ def test_put_record_redshift_destination():
"""
client = boto3.client("firehose", region_name=TEST_REGION)
- stream_name = f"test_put_record_{get_random_hex(6)}"
+ stream_name = f"test_put_record_{mock_random.get_random_hex(6)}"
create_redshift_delivery_stream(client, stream_name)
result = client.put_record(
DeliveryStreamName=stream_name, Record={"Data": "some test data"}
@@ -41,7 +41,7 @@ def test_put_record_batch_redshift_destination():
"""
client = boto3.client("firehose", region_name=TEST_REGION)
- stream_name = f"test_put_record_{get_random_hex(6)}"
+ stream_name = f"test_put_record_{mock_random.get_random_hex(6)}"
create_redshift_delivery_stream(client, stream_name)
records = [{"Data": "one"}, {"Data": "two"}, {"Data": "three"}]
result = client.put_record_batch(DeliveryStreamName=stream_name, Records=records)
@@ -63,7 +63,7 @@ def test_put_record_http_destination():
client = boto3.client("firehose", region_name=TEST_REGION)
s3_dest_config = sample_s3_dest_config()
- stream_name = f"test_put_record_{get_random_hex(6)}"
+ stream_name = f"test_put_record_{mock_random.get_random_hex(6)}"
client.create_delivery_stream(
DeliveryStreamName=stream_name,
HttpEndpointDestinationConfiguration={
@@ -83,7 +83,7 @@ def test_put_record_batch_http_destination():
client = boto3.client("firehose", region_name=TEST_REGION)
s3_dest_config = sample_s3_dest_config()
- stream_name = f"test_put_record_{get_random_hex(6)}"
+ stream_name = f"test_put_record_{mock_random.get_random_hex(6)}"
client.create_delivery_stream(
DeliveryStreamName=stream_name,
HttpEndpointDestinationConfiguration={
@@ -119,7 +119,7 @@ def test_put_record_batch_extended_s3_destination():
CreateBucketConfiguration={"LocationConstraint": S3_LOCATION_CONSTRAINT},
)
- stream_name = f"test_put_record_{get_random_hex(6)}"
+ stream_name = f"test_put_record_{mock_random.get_random_hex(6)}"
client.create_delivery_stream(
DeliveryStreamName=stream_name,
ExtendedS3DestinationConfiguration={
diff --git a/tests/test_firehose/test_firehose_tags.py b/tests/test_firehose/test_firehose_tags.py
index 010ae3f71..3c30dc6af 100644
--- a/tests/test_firehose/test_firehose_tags.py
+++ b/tests/test_firehose/test_firehose_tags.py
@@ -5,8 +5,8 @@ import pytest
from moto import mock_firehose
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
-from moto.core.utils import get_random_hex
from moto.firehose.models import MAX_TAGS_PER_DELIVERY_STREAM
+from moto.moto_api._internal import mock_random
from tests.test_firehose.test_firehose import TEST_REGION
from tests.test_firehose.test_firehose import sample_s3_dest_config
@@ -15,7 +15,7 @@ from tests.test_firehose.test_firehose import sample_s3_dest_config
def test_list_tags_for_delivery_stream():
"""Test invocations of list_tags_for_delivery_stream()."""
client = boto3.client("firehose", region_name=TEST_REGION)
- stream_name = f"test_list_tags_{get_random_hex(6)}"
+ stream_name = f"test_list_tags_{mock_random.get_random_hex(6)}"
number_of_tags = 50
tags = [{"Key": f"{x}_k", "Value": f"{x}_v"} for x in range(1, number_of_tags + 1)]
@@ -79,7 +79,7 @@ def test_tag_delivery_stream():
client = boto3.client("firehose", region_name=TEST_REGION)
# Create a delivery stream for testing purposes.
- stream_name = f"test_tags_{get_random_hex(6)}"
+ stream_name = f"test_tags_{mock_random.get_random_hex(6)}"
client.create_delivery_stream(
DeliveryStreamName=stream_name,
ExtendedS3DestinationConfiguration=sample_s3_dest_config(),
@@ -140,7 +140,7 @@ def test_untag_delivery_stream():
client = boto3.client("firehose", region_name=TEST_REGION)
# Create a delivery stream for testing purposes.
- stream_name = f"test_untag_{get_random_hex(6)}"
+ stream_name = f"test_untag_{mock_random.get_random_hex(6)}"
tag_list = [
{"Key": "one", "Value": "1"},
{"Key": "two", "Value": "2"},
diff --git a/tests/test_moto_api/mock_random/test_mock_random.py b/tests/test_moto_api/mock_random/test_mock_random.py
new file mode 100644
index 000000000..814abcd84
--- /dev/null
+++ b/tests/test_moto_api/mock_random/test_mock_random.py
@@ -0,0 +1,38 @@
+import sure # noqa # pylint: disable=unused-import
+from moto.moto_api._internal import mock_random
+
+
+def test_semi_random_uuids():
+ # Create random UUID first
+ random_uuid = str(mock_random.uuid4())
+
+ # Seed our generator - the next generation should be predetermined
+ mock_random.seed(42)
+ fixed_uuid = str(mock_random.uuid4())
+ fixed_uuid.should.equal("bdd640fb-0667-4ad1-9c80-317fa3b1799d")
+
+ # Ensure they are different
+ fixed_uuid.shouldnt.equal(random_uuid)
+
+ # Retrieving another 'fixed' UUID should not return a known UUID
+ second_fixed = str(mock_random.uuid4())
+ second_fixed.shouldnt.equal(random_uuid)
+ second_fixed.shouldnt.equal(fixed_uuid)
+
+
+def test_semi_random_hex_strings():
+ # Create random HEX first
+ random_hex = mock_random.get_random_hex()
+
+ # Seed our generator - the next generation should be predetermined
+ mock_random.seed(42)
+ fixed_hex = mock_random.get_random_hex()
+ fixed_hex.should.equal("30877432")
+
+ # Ensure they are different
+ fixed_hex.shouldnt.equal(random_hex)
+
+ # Retrieving another 'fixed' UUID should not return a known UUID
+ second_hex = mock_random.uuid4()
+ second_hex.shouldnt.equal(random_hex)
+ second_hex.shouldnt.equal(fixed_hex)
diff --git a/tests/test_route53/test_route53_query_logging_config.py b/tests/test_route53/test_route53_query_logging_config.py
index 641bda0f6..25afd5e1d 100644
--- a/tests/test_route53/test_route53_query_logging_config.py
+++ b/tests/test_route53/test_route53_query_logging_config.py
@@ -7,7 +7,7 @@ from botocore.exceptions import ClientError
from moto import mock_logs
from moto import mock_route53
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
-from moto.core.utils import get_random_hex
+from moto.moto_api._internal import mock_random
# The log group must be in the us-east-1 region.
TEST_REGION = "us-east-1"
@@ -17,7 +17,7 @@ def create_hosted_zone_id(route53_client, hosted_zone_test_name):
"""Return ID of a newly created Route53 public hosted zone"""
response = route53_client.create_hosted_zone(
Name=hosted_zone_test_name,
- CallerReference=f"test_caller_ref_{get_random_hex(6)}",
+ CallerReference=f"test_caller_ref_{mock_random.get_random_hex(6)}",
)
assert response["ResponseMetadata"]["HTTPStatusCode"] == 201
assert "HostedZone" in response and response["HostedZone"]["Id"]
@@ -46,7 +46,7 @@ def test_create_query_logging_config_bad_args():
client = boto3.client("route53", region_name=TEST_REGION)
logs_client = boto3.client("logs", region_name=TEST_REGION)
- hosted_zone_test_name = f"route53_query_log_{get_random_hex(6)}.test"
+ hosted_zone_test_name = f"route53_query_log_{mock_random.get_random_hex(6)}.test"
hosted_zone_id = create_hosted_zone_id(client, hosted_zone_test_name)
log_group_arn = create_log_group_arn(logs_client, hosted_zone_test_name)
@@ -114,7 +114,7 @@ def test_create_query_logging_config_good_args():
client = boto3.client("route53", region_name=TEST_REGION)
logs_client = boto3.client("logs", region_name=TEST_REGION)
- hosted_zone_test_name = f"route53_query_log_{get_random_hex(6)}.test"
+ hosted_zone_test_name = f"route53_query_log_{mock_random.get_random_hex(6)}.test"
hosted_zone_id = create_hosted_zone_id(client, hosted_zone_test_name)
log_group_arn = create_log_group_arn(logs_client, hosted_zone_test_name)
@@ -141,7 +141,7 @@ def test_delete_query_logging_config():
logs_client = boto3.client("logs", region_name=TEST_REGION)
# Create a query logging config that can then be deleted.
- hosted_zone_test_name = f"route53_query_log_{get_random_hex(6)}.test"
+ hosted_zone_test_name = f"route53_query_log_{mock_random.get_random_hex(6)}.test"
hosted_zone_id = create_hosted_zone_id(client, hosted_zone_test_name)
log_group_arn = create_log_group_arn(logs_client, hosted_zone_test_name)
@@ -172,7 +172,7 @@ def test_get_query_logging_config():
logs_client = boto3.client("logs", region_name=TEST_REGION)
# Create a query logging config that can then be retrieved.
- hosted_zone_test_name = f"route53_query_log_{get_random_hex(6)}.test"
+ hosted_zone_test_name = f"route53_query_log_{mock_random.get_random_hex(6)}.test"
hosted_zone_id = create_hosted_zone_id(client, hosted_zone_test_name)
log_group_arn = create_log_group_arn(logs_client, hosted_zone_test_name)
@@ -212,7 +212,9 @@ def test_list_query_logging_configs_bad_args():
# Create a couple of query logging configs to work with.
for _ in range(3):
- hosted_zone_test_name = f"route53_query_log_{get_random_hex(6)}.test"
+ hosted_zone_test_name = (
+ f"route53_query_log_{mock_random.get_random_hex(6)}.test"
+ )
hosted_zone_id = create_hosted_zone_id(client, hosted_zone_test_name)
log_group_arn = create_log_group_arn(logs_client, hosted_zone_test_name)
client.create_query_logging_config(
@@ -246,7 +248,9 @@ def test_list_query_logging_configs_good_args():
# Create a couple of query logging configs to work with.
zone_ids = []
for _ in range(10):
- hosted_zone_test_name = f"route53_query_log_{get_random_hex(6)}.test"
+ hosted_zone_test_name = (
+ f"route53_query_log_{mock_random.get_random_hex(6)}.test"
+ )
hosted_zone_id = create_hosted_zone_id(client, hosted_zone_test_name)
zone_ids.append(hosted_zone_id)
diff --git a/tests/test_route53resolver/test_route53resolver_endpoint.py b/tests/test_route53resolver/test_route53resolver_endpoint.py
index 172c293d3..4a5d72382 100644
--- a/tests/test_route53resolver/test_route53resolver_endpoint.py
+++ b/tests/test_route53resolver/test_route53resolver_endpoint.py
@@ -9,8 +9,8 @@ import pytest
from moto import mock_route53resolver
from moto import settings
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
-from moto.core.utils import get_random_hex
from moto.ec2 import mock_ec2
+from moto.moto_api._internal import mock_random
TEST_REGION = "us-east-1" if settings.TEST_SERVER_MODE else "us-west-2"
@@ -58,7 +58,7 @@ def create_test_endpoint(client, ec2_client, name=None, tags=None):
"""
if not tags:
tags = []
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
subnet_ids = create_subnets(ec2_client, create_vpc(ec2_client))
resolver_endpoint = client.create_resolver_endpoint(
CreatorRequestId=random_num,
@@ -78,7 +78,7 @@ def create_test_endpoint(client, ec2_client, name=None, tags=None):
def test_route53resolver_invalid_create_endpoint_args():
"""Test invalid arguments to the create_resolver_endpoint API."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
# Verify ValidationException error messages are accumulated properly:
# - creator requestor ID that exceeds the allowed length of 255.
@@ -88,7 +88,7 @@ def test_route53resolver_invalid_create_endpoint_args():
# - too many security group IDs.
long_id = random_num * 25 + "123456"
long_name = random_num * 6 + "abcde"
- too_many_security_groups = ["sg-" + get_random_hex(63)]
+ too_many_security_groups = ["sg-" + mock_random.get_random_hex(63)]
bad_direction = "foo"
too_many_ip_addresses = [{"SubnetId": f"{x}", "Ip": f"{x}" * 7} for x in range(11)]
with pytest.raises(ClientError) as exc:
@@ -168,7 +168,7 @@ def test_route53resolver_bad_create_endpoint_subnets():
"""Test bad subnet scenarios for create_resolver_endpoint API."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
ec2_client = boto3.client("ec2", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
# Need 2 IP addresses at the minimum.
subnet_ids = create_subnets(ec2_client, create_vpc(ec2_client))
@@ -246,7 +246,7 @@ def test_route53resolver_bad_create_endpoint_security_groups():
"""Test bad security group scenarios for create_resolver_endpoint API."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
ec2_client = boto3.client("ec2", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
subnet_ids = create_subnets(ec2_client, create_vpc(ec2_client))
ip_addrs = [
@@ -302,7 +302,7 @@ def test_route53resolver_create_resolver_endpoint(): # pylint: disable=too-many
"""Test good create_resolver_endpoint API calls."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
ec2_client = boto3.client("ec2", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
vpc_id = create_vpc(ec2_client)
subnet_ids = create_subnets(ec2_client, vpc_id)
@@ -365,7 +365,7 @@ def test_route53resolver_other_create_resolver_endpoint_errors():
with pytest.raises(ClientError) as exc:
client.create_resolver_endpoint(
CreatorRequestId=created_endpoint["CreatorRequestId"],
- Name="X" + get_random_hex(10),
+ Name="X" + mock_random.get_random_hex(10),
SecurityGroupIds=created_endpoint["SecurityGroupIds"],
Direction="INBOUND",
IpAddresses=[
@@ -380,7 +380,7 @@ def test_route53resolver_other_create_resolver_endpoint_errors():
) in err["Message"]
# Too many endpoints.
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
for idx in range(4):
create_test_endpoint(client, ec2_client, name=f"A{idx}-{random_num}")
with pytest.raises(ClientError) as exc:
@@ -428,7 +428,7 @@ def test_route53resolver_bad_delete_resolver_endpoint():
"""Test delete_resolver_endpoint API calls with a bad ID."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
ec2_client = boto3.client("ec2", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
# Use a resolver endpoint id that is too long.
long_id = "0123456789" * 6 + "xxxxx"
@@ -498,7 +498,7 @@ def test_route53resolver_get_resolver_endpoint():
def test_route53resolver_bad_get_resolver_endpoint():
"""Test get_resolver_endpoint API calls with a bad ID."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
# Use a resolver endpoint id that is too long.
long_id = "0123456789" * 6 + "xxxxx"
@@ -529,7 +529,7 @@ def test_route53resolver_update_resolver_endpoint():
created_endpoint = create_test_endpoint(client, ec2_client)
# Now update the resolver endpoint name and verify the response.
- new_name = "NewName" + get_random_hex(6)
+ new_name = "NewName" + mock_random.get_random_hex(6)
response = client.update_resolver_endpoint(
ResolverEndpointId=created_endpoint["Id"], Name=new_name
)
@@ -552,8 +552,8 @@ def test_route53resolver_update_resolver_endpoint():
def test_route53resolver_bad_update_resolver_endpoint():
"""Test update_resolver_endpoint API calls with a bad ID."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
- random_num = get_random_hex(10)
- random_name = "Z" + get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
+ random_name = "Z" + mock_random.get_random_hex(10)
# Use a resolver endpoint id that is too long.
long_id = "0123456789" * 6 + "xxxxx"
@@ -581,7 +581,7 @@ def test_route53resolver_list_resolver_endpoint_ip_addresses():
"""Test good list_resolver_endpoint_ip_addresses API calls."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
ec2_client = boto3.client("ec2", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
subnet_ids = create_subnets(ec2_client, create_vpc(ec2_client))
response = client.create_resolver_endpoint(
@@ -641,7 +641,7 @@ def test_route53resolver_bad_list_resolver_endpoint_ip_addresses():
assert "Resolver endpoint with ID 'foo' does not exist" in err["Message"]
# Good endpoint id, but bad max_results.
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
response = create_test_endpoint(client, ec2_client, name=f"A-{random_num}")
with pytest.raises(ClientError) as exc:
client.list_resolver_endpoint_ip_addresses(
@@ -662,7 +662,7 @@ def test_route53resolver_list_resolver_endpoints():
"""Test good list_resolver_endpoints API calls."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
ec2_client = boto3.client("ec2", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
# List endpoints when there are none.
response = client.list_resolver_endpoints()
@@ -703,7 +703,7 @@ def test_route53resolver_list_resolver_endpoints_filters():
"""Test good list_resolver_endpoints API calls that use filters."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
ec2_client = boto3.client("ec2", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
# Create some endpoints for testing purposes
security_group_id = create_security_group(ec2_client)
@@ -832,7 +832,7 @@ def test_route53resolver_bad_list_resolver_endpoints():
ec2_client = boto3.client("ec2", region_name=TEST_REGION)
# Bad max_results.
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
create_test_endpoint(client, ec2_client, name=f"A-{random_num}")
with pytest.raises(ClientError) as exc:
client.list_resolver_endpoints(MaxResults=250)
@@ -856,7 +856,7 @@ def test_associate_resolver_endpoint_ip_address():
VpcId=vpc_id, CidrBlock="10.0.2.0/24", AvailabilityZone=f"{TEST_REGION}a"
)["Subnet"]
# create resolver
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
resolver = create_test_endpoint(client, ec2_client, name=f"A-{random_num}")
resolver.should.have.key("IpAddressCount").equals(2)
# associate
@@ -897,7 +897,7 @@ def test_disassociate_resolver_endpoint_ip_address__using_ip():
VpcId=vpc_id, CidrBlock="10.0.2.0/24", AvailabilityZone=f"{TEST_REGION}a"
)["Subnet"]["SubnetId"]
# create resolver
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
resolver = create_test_endpoint(client, ec2_client, name=f"A-{random_num}")
# associate
client.associate_resolver_endpoint_ip_address(
@@ -926,7 +926,7 @@ def test_disassociate_resolver_endpoint_ip_address__using_ipid_and_subnet():
VpcId=vpc_id, CidrBlock="10.0.2.0/24", AvailabilityZone=f"{TEST_REGION}a"
)["Subnet"]["SubnetId"]
# create resolver
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
resolver = create_test_endpoint(client, ec2_client, name=f"A-{random_num}")
# associate
client.associate_resolver_endpoint_ip_address(
@@ -957,7 +957,7 @@ def test_disassociate_resolver_endpoint_ip_address__using_subnet_alone():
VpcId=vpc_id, CidrBlock="10.0.2.0/24", AvailabilityZone=f"{TEST_REGION}a"
)["Subnet"]["SubnetId"]
# create resolver
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
resolver = create_test_endpoint(client, ec2_client, name=f"A-{random_num}")
# associate
client.associate_resolver_endpoint_ip_address(
diff --git a/tests/test_route53resolver/test_route53resolver_rule.py b/tests/test_route53resolver/test_route53resolver_rule.py
index acdc100d9..2801f4008 100644
--- a/tests/test_route53resolver/test_route53resolver_rule.py
+++ b/tests/test_route53resolver/test_route53resolver_rule.py
@@ -8,8 +8,8 @@ import pytest
from moto import mock_route53resolver
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
-from moto.core.utils import get_random_hex
from moto.ec2 import mock_ec2
+from moto.moto_api._internal import mock_random
from .test_route53resolver_endpoint import TEST_REGION, create_test_endpoint, create_vpc
@@ -21,7 +21,7 @@ def create_test_rule(client, name=None, tags=None):
"""
if not tags:
tags = []
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
resolver_rule = client.create_resolver_rule(
CreatorRequestId=random_num,
@@ -42,7 +42,7 @@ def create_test_rule(client, name=None, tags=None):
def test_route53resolver_invalid_create_rule_args():
"""Test invalid arguments to the create_resolver_rule API."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
# Verify ValidationException error messages are accumulated properly:
# - creator requestor ID that exceeds the allowed length of 255.
@@ -128,7 +128,7 @@ def test_route53resolver_create_resolver_rule(): # pylint: disable=too-many-loc
"""Test good create_resolver_rule API calls."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
ec2_client = boto3.client("ec2", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
# Create a good endpoint that we can use to test.
created_endpoint = create_test_endpoint(client, ec2_client)
@@ -183,7 +183,7 @@ def test_route53resolver_bad_create_resolver_rule():
"""Test error scenarios for create_resolver_rule API calls."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
ec2_client = boto3.client("ec2", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
# Create a good endpoint and rule that we can use to test.
created_endpoint = create_test_endpoint(client, ec2_client)
@@ -210,7 +210,7 @@ def test_route53resolver_bad_create_resolver_rule():
# Attempt to create a rule with a IPv6 address.
with pytest.raises(ClientError) as exc:
client.create_resolver_rule(
- CreatorRequestId=get_random_hex(10),
+ CreatorRequestId=mock_random.get_random_hex(10),
Name="B" + random_num,
RuleType="FORWARD",
DomainName=f"{random_num}.test",
@@ -224,7 +224,7 @@ def test_route53resolver_bad_create_resolver_rule():
# Attempt to create a rule with an invalid IPv4 address.
with pytest.raises(ClientError) as exc:
client.create_resolver_rule(
- CreatorRequestId=get_random_hex(10),
+ CreatorRequestId=mock_random.get_random_hex(10),
Name="B" + random_num,
RuleType="FORWARD",
DomainName=f"{random_num}.test",
@@ -238,7 +238,7 @@ def test_route53resolver_bad_create_resolver_rule():
# Attempt to create a rule with a non-existent resolver endpoint id.
with pytest.raises(ClientError) as exc:
client.create_resolver_rule(
- CreatorRequestId=get_random_hex(10),
+ CreatorRequestId=mock_random.get_random_hex(10),
Name="B" + random_num,
RuleType="FORWARD",
DomainName=f"{random_num}.test",
@@ -252,7 +252,7 @@ def test_route53resolver_bad_create_resolver_rule():
# Create a rule with a resolver endpoint id and a rule type of SYSTEM.
with pytest.raises(ClientError) as exc:
client.create_resolver_rule(
- CreatorRequestId=get_random_hex(10),
+ CreatorRequestId=mock_random.get_random_hex(10),
Name="B" + random_num,
RuleType="SYSTEM",
DomainName=f"{random_num}.test",
@@ -305,7 +305,7 @@ def test_route53resolver_bad_delete_resolver_rule():
"""Test delete_resolver_rule API calls with a bad ID."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
ec2_client = boto3.client("ec2", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
# Use a resolver rule id that is too long.
long_id = "0123456789" * 6 + "xxxxx"
@@ -367,7 +367,7 @@ def test_route53resolver_get_resolver_rule():
def test_route53resolver_bad_get_resolver_rule():
"""Test get_resolver_rule API calls with a bad ID."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
# Use a resolver rule id that is too long.
long_id = "0123456789" * 6 + "xxxxx"
@@ -393,7 +393,7 @@ def test_route53resolver_bad_get_resolver_rule():
def test_route53resolver_list_resolver_rules():
"""Test good list_resolver_rules API calls."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
# List rules when there are none.
response = client.list_resolver_rules()
@@ -434,7 +434,7 @@ def test_route53resolver_list_resolver_rules_filters():
"""Test good list_resolver_rules API calls that use filters."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
ec2_client = boto3.client("ec2", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
# Create some endpoints and rules for testing purposes.
endpoint1 = create_test_endpoint(client, ec2_client)["Id"]
@@ -533,7 +533,7 @@ def test_route53resolver_bad_list_resolver_rules():
client = boto3.client("route53resolver", region_name=TEST_REGION)
# Bad max_results.
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
create_test_rule(client, name=f"A-{random_num}")
with pytest.raises(ClientError) as exc:
client.list_resolver_rules(MaxResults=250)
diff --git a/tests/test_route53resolver/test_route53resolver_rule_associations.py b/tests/test_route53resolver/test_route53resolver_rule_associations.py
index 595978bca..6a580bd9e 100644
--- a/tests/test_route53resolver/test_route53resolver_rule_associations.py
+++ b/tests/test_route53resolver/test_route53resolver_rule_associations.py
@@ -5,8 +5,8 @@ from botocore.exceptions import ClientError
import pytest
from moto import mock_route53resolver
-from moto.core.utils import get_random_hex
from moto.ec2 import mock_ec2
+from moto.moto_api._internal import mock_random
from .test_route53resolver_endpoint import TEST_REGION, create_vpc
from .test_route53resolver_rule import create_test_rule
@@ -18,7 +18,7 @@ def create_test_rule_association(
"""Create a Resolver Rule Association for testing purposes."""
if not resolver_rule_id:
resolver_rule_id = create_test_rule(client)["Id"]
- name = name if name else "R" + get_random_hex(10)
+ name = name if name else "R" + mock_random.get_random_hex(10)
if not vpc_id:
vpc_id = create_vpc(ec2_client)
return client.associate_resolver_rule(
@@ -30,7 +30,7 @@ def create_test_rule_association(
def test_route53resolver_invalid_associate_resolver_rule_args():
"""Test invalid arguments to the associate_resolver_rule API."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
# Verify ValidationException error messages are accumulated properly:
# - resolver rule ID that exceeds the allowed length of 64.
@@ -68,7 +68,7 @@ def test_route53resolver_associate_resolver_rule():
ec2_client = boto3.client("ec2", region_name=TEST_REGION)
resolver_rule_id = create_test_rule(client)["Id"]
- name = "X" + get_random_hex(10)
+ name = "X" + mock_random.get_random_hex(10)
vpc_id = create_vpc(ec2_client)
rule_association = client.associate_resolver_rule(
ResolverRuleId=resolver_rule_id, Name=name, VPCId=vpc_id
@@ -151,7 +151,7 @@ def test_route53resolver_bad_disassociate_resolver_rule():
"""Test disassociate_resolver_rule API calls with a bad ID."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
ec2_client = boto3.client("ec2", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
# Use a resolver rule id and vpc id that is too long.
long_id = "0123456789" * 6 + "xxxxx"
@@ -234,7 +234,7 @@ def test_route53resolver_get_resolver_rule_association():
def test_route53resolver_bad_get_resolver_rule_association():
"""Test get_resolver_rule_association API calls with a bad ID."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
# Use a resolver rule association id that is too long.
long_id = "0123456789" * 6 + "xxxxx"
@@ -262,7 +262,7 @@ def test_route53resolver_list_resolver_rule_associations():
"""Test good list_resolver_rule_associations API calls."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
ec2_client = boto3.client("ec2", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
# List rule associations when there are none.
response = client.list_resolver_rule_associations()
@@ -304,7 +304,7 @@ def test_route53resolver_list_resolver_rule_associations_filters():
"""Test good list_resolver_rule_associations API calls that use filters."""
client = boto3.client("route53resolver", region_name=TEST_REGION)
ec2_client = boto3.client("ec2", region_name=TEST_REGION)
- random_num = get_random_hex(10)
+ random_num = mock_random.get_random_hex(10)
# Create some rule associations for testing purposes
vpc_id1 = create_vpc(ec2_client)