First working tests!
This commit is contained in:
parent
e00af2f73c
commit
9c00f572d6
2
docs/_build/html/_sources/index.rst.txt
vendored
2
docs/_build/html/_sources/index.rst.txt
vendored
@ -30,6 +30,8 @@ Currently implemented Services:
|
|||||||
+-----------------------+---------------------+-----------------------------------+
|
+-----------------------+---------------------+-----------------------------------+
|
||||||
| Data Pipeline | @mock_datapipeline | basic endpoints done |
|
| Data Pipeline | @mock_datapipeline | basic endpoints done |
|
||||||
+-----------------------+---------------------+-----------------------------------+
|
+-----------------------+---------------------+-----------------------------------+
|
||||||
|
| DataSync | @mock_datasync | basic endpoints done |
|
||||||
|
+-----------------------+---------------------+-----------------------------------+
|
||||||
| - DynamoDB | - @mock_dynamodb | - core endpoints done |
|
| - DynamoDB | - @mock_dynamodb | - core endpoints done |
|
||||||
| - DynamoDB2 | - @mock_dynamodb2 | - core endpoints + partial indexes|
|
| - DynamoDB2 | - @mock_dynamodb2 | - core endpoints + partial indexes|
|
||||||
+-----------------------+---------------------+-----------------------------------+
|
+-----------------------+---------------------+-----------------------------------+
|
||||||
|
9
file.tmp
Normal file
9
file.tmp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
AWSTemplateFormatVersion: '2010-09-09'
|
||||||
|
Description: Simple CloudFormation Test Template
|
||||||
|
Resources:
|
||||||
|
S3Bucket:
|
||||||
|
Type: AWS::S3::Bucket
|
||||||
|
Properties:
|
||||||
|
AccessControl: PublicRead
|
||||||
|
BucketName: cf-test-bucket-1
|
@ -1,25 +1,21 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
# import logging
|
|
||||||
# logging.getLogger('boto').setLevel(logging.CRITICAL)
|
|
||||||
|
|
||||||
__title__ = "moto"
|
|
||||||
__version__ = "1.3.14.dev"
|
|
||||||
|
|
||||||
from .acm import mock_acm # noqa
|
from .acm import mock_acm # noqa
|
||||||
from .apigateway import mock_apigateway, mock_apigateway_deprecated # noqa
|
from .apigateway import mock_apigateway, mock_apigateway_deprecated # noqa
|
||||||
from .athena import mock_athena # noqa
|
from .athena import mock_athena # noqa
|
||||||
from .autoscaling import mock_autoscaling, mock_autoscaling_deprecated # noqa
|
from .autoscaling import mock_autoscaling, mock_autoscaling_deprecated # noqa
|
||||||
from .awslambda import mock_lambda, mock_lambda_deprecated # noqa
|
from .awslambda import mock_lambda, mock_lambda_deprecated # noqa
|
||||||
from .cloudformation import mock_cloudformation, mock_cloudformation_deprecated # noqa
|
from .batch import mock_batch # noqa
|
||||||
|
from .cloudformation import mock_cloudformation # noqa
|
||||||
|
from .cloudformation import mock_cloudformation_deprecated
|
||||||
from .cloudwatch import mock_cloudwatch, mock_cloudwatch_deprecated # noqa
|
from .cloudwatch import mock_cloudwatch, mock_cloudwatch_deprecated # noqa
|
||||||
from .cognitoidentity import ( # noqa
|
from .cognitoidentity import mock_cognitoidentity # noqa
|
||||||
mock_cognitoidentity,
|
from .cognitoidentity import mock_cognitoidentity_deprecated
|
||||||
mock_cognitoidentity_deprecated,
|
|
||||||
)
|
|
||||||
from .cognitoidp import mock_cognitoidp, mock_cognitoidp_deprecated # noqa
|
from .cognitoidp import mock_cognitoidp, mock_cognitoidp_deprecated # noqa
|
||||||
from .config import mock_config # noqa
|
from .config import mock_config # noqa
|
||||||
from .datapipeline import mock_datapipeline, mock_datapipeline_deprecated # noqa
|
from .datapipeline import mock_datapipeline # noqa
|
||||||
|
from .datapipeline import mock_datapipeline_deprecated
|
||||||
|
from .datasync import mock_datasync # noqa
|
||||||
from .dynamodb import mock_dynamodb, mock_dynamodb_deprecated # noqa
|
from .dynamodb import mock_dynamodb, mock_dynamodb_deprecated # noqa
|
||||||
from .dynamodb2 import mock_dynamodb2, mock_dynamodb2_deprecated # noqa
|
from .dynamodb2 import mock_dynamodb2, mock_dynamodb2_deprecated # noqa
|
||||||
from .dynamodbstreams import mock_dynamodbstreams # noqa
|
from .dynamodbstreams import mock_dynamodbstreams # noqa
|
||||||
@ -33,31 +29,37 @@ from .events import mock_events # noqa
|
|||||||
from .glacier import mock_glacier, mock_glacier_deprecated # noqa
|
from .glacier import mock_glacier, mock_glacier_deprecated # noqa
|
||||||
from .glue import mock_glue # noqa
|
from .glue import mock_glue # noqa
|
||||||
from .iam import mock_iam, mock_iam_deprecated # noqa
|
from .iam import mock_iam, mock_iam_deprecated # noqa
|
||||||
|
from .iot import mock_iot # noqa
|
||||||
|
from .iotdata import mock_iotdata # noqa
|
||||||
from .kinesis import mock_kinesis, mock_kinesis_deprecated # noqa
|
from .kinesis import mock_kinesis, mock_kinesis_deprecated # noqa
|
||||||
from .kms import mock_kms, mock_kms_deprecated # noqa
|
from .kms import mock_kms, mock_kms_deprecated # noqa
|
||||||
from .organizations import mock_organizations # noqa
|
from .logs import mock_logs, mock_logs_deprecated # noqa
|
||||||
from .opsworks import mock_opsworks, mock_opsworks_deprecated # noqa
|
from .opsworks import mock_opsworks, mock_opsworks_deprecated # noqa
|
||||||
|
from .organizations import mock_organizations # noqa
|
||||||
from .polly import mock_polly # noqa
|
from .polly import mock_polly # noqa
|
||||||
from .rds import mock_rds, mock_rds_deprecated # noqa
|
from .rds import mock_rds, mock_rds_deprecated # noqa
|
||||||
from .rds2 import mock_rds2, mock_rds2_deprecated # noqa
|
from .rds2 import mock_rds2, mock_rds2_deprecated # noqa
|
||||||
from .redshift import mock_redshift, mock_redshift_deprecated # noqa
|
from .redshift import mock_redshift, mock_redshift_deprecated # noqa
|
||||||
from .resourcegroups import mock_resourcegroups # noqa
|
from .resourcegroups import mock_resourcegroups # noqa
|
||||||
|
from .resourcegroupstaggingapi import mock_resourcegroupstaggingapi # noqa
|
||||||
|
from .route53 import mock_route53, mock_route53_deprecated # noqa
|
||||||
from .s3 import mock_s3, mock_s3_deprecated # noqa
|
from .s3 import mock_s3, mock_s3_deprecated # noqa
|
||||||
from .ses import mock_ses, mock_ses_deprecated # noqa
|
|
||||||
from .secretsmanager import mock_secretsmanager # noqa
|
from .secretsmanager import mock_secretsmanager # noqa
|
||||||
|
from .ses import mock_ses, mock_ses_deprecated # noqa
|
||||||
from .sns import mock_sns, mock_sns_deprecated # noqa
|
from .sns import mock_sns, mock_sns_deprecated # noqa
|
||||||
from .sqs import mock_sqs, mock_sqs_deprecated # noqa
|
from .sqs import mock_sqs, mock_sqs_deprecated # noqa
|
||||||
|
from .ssm import mock_ssm # noqa
|
||||||
from .stepfunctions import mock_stepfunctions # noqa
|
from .stepfunctions import mock_stepfunctions # noqa
|
||||||
from .sts import mock_sts, mock_sts_deprecated # noqa
|
from .sts import mock_sts, mock_sts_deprecated # noqa
|
||||||
from .ssm import mock_ssm # noqa
|
|
||||||
from .route53 import mock_route53, mock_route53_deprecated # noqa
|
|
||||||
from .swf import mock_swf, mock_swf_deprecated # noqa
|
from .swf import mock_swf, mock_swf_deprecated # noqa
|
||||||
from .xray import mock_xray, mock_xray_client, XRaySegment # noqa
|
from .xray import XRaySegment, mock_xray, mock_xray_client # noqa
|
||||||
from .logs import mock_logs, mock_logs_deprecated # noqa
|
|
||||||
from .batch import mock_batch # noqa
|
# import logging
|
||||||
from .resourcegroupstaggingapi import mock_resourcegroupstaggingapi # noqa
|
# logging.getLogger('boto').setLevel(logging.CRITICAL)
|
||||||
from .iot import mock_iot # noqa
|
|
||||||
from .iotdata import mock_iotdata # noqa
|
__title__ = "moto"
|
||||||
|
__version__ = "1.3.14.dev"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -5,12 +5,15 @@ from moto.apigateway import apigateway_backends
|
|||||||
from moto.athena import athena_backends
|
from moto.athena import athena_backends
|
||||||
from moto.autoscaling import autoscaling_backends
|
from moto.autoscaling import autoscaling_backends
|
||||||
from moto.awslambda import lambda_backends
|
from moto.awslambda import lambda_backends
|
||||||
|
from moto.batch import batch_backends
|
||||||
from moto.cloudformation import cloudformation_backends
|
from moto.cloudformation import cloudformation_backends
|
||||||
from moto.cloudwatch import cloudwatch_backends
|
from moto.cloudwatch import cloudwatch_backends
|
||||||
from moto.cognitoidentity import cognitoidentity_backends
|
from moto.cognitoidentity import cognitoidentity_backends
|
||||||
from moto.cognitoidp import cognitoidp_backends
|
from moto.cognitoidp import cognitoidp_backends
|
||||||
|
from moto.config import config_backends
|
||||||
from moto.core import moto_api_backends
|
from moto.core import moto_api_backends
|
||||||
from moto.datapipeline import datapipeline_backends
|
from moto.datapipeline import datapipeline_backends
|
||||||
|
from moto.datasync import datasync_backends
|
||||||
from moto.dynamodb import dynamodb_backends
|
from moto.dynamodb import dynamodb_backends
|
||||||
from moto.dynamodb2 import dynamodb_backends2
|
from moto.dynamodb2 import dynamodb_backends2
|
||||||
from moto.dynamodbstreams import dynamodbstreams_backends
|
from moto.dynamodbstreams import dynamodbstreams_backends
|
||||||
@ -25,6 +28,8 @@ from moto.glacier import glacier_backends
|
|||||||
from moto.glue import glue_backends
|
from moto.glue import glue_backends
|
||||||
from moto.iam import iam_backends
|
from moto.iam import iam_backends
|
||||||
from moto.instance_metadata import instance_metadata_backends
|
from moto.instance_metadata import instance_metadata_backends
|
||||||
|
from moto.iot import iot_backends
|
||||||
|
from moto.iotdata import iotdata_backends
|
||||||
from moto.kinesis import kinesis_backends
|
from moto.kinesis import kinesis_backends
|
||||||
from moto.kms import kms_backends
|
from moto.kms import kms_backends
|
||||||
from moto.logs import logs_backends
|
from moto.logs import logs_backends
|
||||||
@ -34,6 +39,7 @@ from moto.polly import polly_backends
|
|||||||
from moto.rds2 import rds2_backends
|
from moto.rds2 import rds2_backends
|
||||||
from moto.redshift import redshift_backends
|
from moto.redshift import redshift_backends
|
||||||
from moto.resourcegroups import resourcegroups_backends
|
from moto.resourcegroups import resourcegroups_backends
|
||||||
|
from moto.resourcegroupstaggingapi import resourcegroupstaggingapi_backends
|
||||||
from moto.route53 import route53_backends
|
from moto.route53 import route53_backends
|
||||||
from moto.s3 import s3_backends
|
from moto.s3 import s3_backends
|
||||||
from moto.secretsmanager import secretsmanager_backends
|
from moto.secretsmanager import secretsmanager_backends
|
||||||
@ -45,11 +51,6 @@ from moto.stepfunctions import stepfunction_backends
|
|||||||
from moto.sts import sts_backends
|
from moto.sts import sts_backends
|
||||||
from moto.swf import swf_backends
|
from moto.swf import swf_backends
|
||||||
from moto.xray import xray_backends
|
from moto.xray import xray_backends
|
||||||
from moto.iot import iot_backends
|
|
||||||
from moto.iotdata import iotdata_backends
|
|
||||||
from moto.batch import batch_backends
|
|
||||||
from moto.resourcegroupstaggingapi import resourcegroupstaggingapi_backends
|
|
||||||
from moto.config import config_backends
|
|
||||||
|
|
||||||
BACKENDS = {
|
BACKENDS = {
|
||||||
"acm": acm_backends,
|
"acm": acm_backends,
|
||||||
@ -63,6 +64,7 @@ BACKENDS = {
|
|||||||
"cognito-idp": cognitoidp_backends,
|
"cognito-idp": cognitoidp_backends,
|
||||||
"config": config_backends,
|
"config": config_backends,
|
||||||
"datapipeline": datapipeline_backends,
|
"datapipeline": datapipeline_backends,
|
||||||
|
"datasync": datasync_backends,
|
||||||
"dynamodb": dynamodb_backends,
|
"dynamodb": dynamodb_backends,
|
||||||
"dynamodb2": dynamodb_backends2,
|
"dynamodb2": dynamodb_backends2,
|
||||||
"dynamodbstreams": dynamodbstreams_backends,
|
"dynamodbstreams": dynamodbstreams_backends,
|
||||||
|
8
moto/datasync/__init__.py
Normal file
8
moto/datasync/__init__.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from ..core.models import base_decorator, deprecated_base_decorator
|
||||||
|
from .models import datasync_backends
|
||||||
|
|
||||||
|
datasync_backend = datasync_backends["us-east-1"]
|
||||||
|
mock_datasync = base_decorator(datasync_backends)
|
||||||
|
mock_datasync_deprecated = deprecated_base_decorator(datasync_backends)
|
56
moto/datasync/models.py
Normal file
56
moto/datasync/models.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
|
||||||
|
import boto3
|
||||||
|
from moto.compat import OrderedDict
|
||||||
|
from moto.core import BaseBackend, BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
Endpoints I need to test:
|
||||||
|
|
||||||
|
list_locations
|
||||||
|
list_tasks
|
||||||
|
start_task_execution
|
||||||
|
cancel_task_execution
|
||||||
|
describe_task
|
||||||
|
describe_task_execution
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
def datasync_json_dump(datasync_object):
|
||||||
|
return json.dumps(datasync_object)
|
||||||
|
|
||||||
|
class Location(BaseModel):
|
||||||
|
def __init__(self, location_uri, region_name):
|
||||||
|
self.location_uri = location_uri
|
||||||
|
self.region_name = region_name
|
||||||
|
loc = ''.join([random.choice(string.ascii_lowercase + string.digits) for _ in range(17)])
|
||||||
|
self.arn = 'arn:aws:datasync:{0}:111222333444:location/loc-{1}'.format(region_name, loc)
|
||||||
|
|
||||||
|
|
||||||
|
class DataSyncBackend(BaseBackend):
|
||||||
|
def __init__(self, region_name):
|
||||||
|
self.region_name = region_name
|
||||||
|
self.locations = OrderedDict()
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
region_name = self.region_name
|
||||||
|
self._reset_model_refs()
|
||||||
|
self.__dict__ = {}
|
||||||
|
self.__init__(region_name)
|
||||||
|
|
||||||
|
def create_location(self, location_uri):
|
||||||
|
if location_uri in self.locations:
|
||||||
|
raise Exception('Location already exists')
|
||||||
|
|
||||||
|
location = Location(location_uri, region_name=self.region_name)
|
||||||
|
self.locations['location_uri'] = location
|
||||||
|
return location.arn
|
||||||
|
|
||||||
|
|
||||||
|
datasync_backends = {}
|
||||||
|
for region in boto3.Session().get_available_regions("datasync"):
|
||||||
|
datasync_backends[region] = DataSyncBackend(region_name=region)
|
49
moto/datasync/responses.py
Normal file
49
moto/datasync/responses.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import re
|
||||||
|
|
||||||
|
from moto.core.responses import BaseResponse
|
||||||
|
from six.moves.urllib.parse import urlparse
|
||||||
|
|
||||||
|
from .models import datasync_backends
|
||||||
|
|
||||||
|
|
||||||
|
class DataSyncResponse(BaseResponse):
|
||||||
|
|
||||||
|
region_regex = re.compile(r"://(.+?)\.datasync\.amazonaws\.com")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def datasync_backend(self):
|
||||||
|
return datasync_backends[self.region]
|
||||||
|
|
||||||
|
def list_locations(self):
|
||||||
|
locations = self.datasync_backend.locations
|
||||||
|
logging.info('FOUND SOME SHIT {0}'.format(locations))
|
||||||
|
|
||||||
|
template = self.response_template(LIST_LOCATIONS_RESPONSE)
|
||||||
|
r = template.render(locations=locations)
|
||||||
|
logging.info('list_locations r={0}'.format(r))
|
||||||
|
return 'GARBAGE'
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def create_location_s3(self):
|
||||||
|
# s3://bucket_name/folder/
|
||||||
|
s3_bucket_arn = self._get_param("S3BucketArn")
|
||||||
|
|
||||||
|
bucket_and_path = s3_bucket_arn.split(':')[-1]
|
||||||
|
location_uri='/'.join(['s3:/', bucket_and_path])
|
||||||
|
location = self.datasync_backend.create_location(location_uri)
|
||||||
|
|
||||||
|
return json.dumps({'LocationArn':location})
|
||||||
|
|
||||||
|
|
||||||
|
def create_location_smb(self):
|
||||||
|
# smb://smb.share.fqdn/AWS_Test/
|
||||||
|
subdirectory = self._get_param("Subdirectory")
|
||||||
|
server_hostname = self._get_param("ServerHostname")
|
||||||
|
|
||||||
|
location_uri = '/'.join(['smb:/', server_hostname, subdirectory])
|
||||||
|
location = self.datasync_backend.create_location(location_uri)
|
||||||
|
|
||||||
|
return json.dumps({'LocationArn':location})
|
9
moto/datasync/urls.py
Normal file
9
moto/datasync/urls.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from .responses import DataSyncResponse
|
||||||
|
|
||||||
|
url_bases = ["https?://(.*?)(datasync)(.*?).amazonaws.com"]
|
||||||
|
|
||||||
|
url_paths = {
|
||||||
|
"{0}/$": DataSyncResponse.dispatch,
|
||||||
|
}
|
@ -1,19 +1,16 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from six.moves.urllib.parse import urlparse
|
|
||||||
|
|
||||||
from moto.core.responses import BaseResponse
|
from moto.core.responses import BaseResponse
|
||||||
from moto.core.utils import amz_crc32, amzn_request_id
|
from moto.core.utils import amz_crc32, amzn_request_id
|
||||||
from .utils import parse_message_attributes
|
from six.moves.urllib.parse import urlparse
|
||||||
|
|
||||||
|
from .exceptions import (EmptyBatchRequest, InvalidAttributeName,
|
||||||
|
MessageAttributesInvalid, MessageNotInflight,
|
||||||
|
ReceiptHandleIsInvalid)
|
||||||
from .models import sqs_backends
|
from .models import sqs_backends
|
||||||
from .exceptions import (
|
from .utils import parse_message_attributes
|
||||||
MessageAttributesInvalid,
|
|
||||||
MessageNotInflight,
|
|
||||||
ReceiptHandleIsInvalid,
|
|
||||||
EmptyBatchRequest,
|
|
||||||
InvalidAttributeName,
|
|
||||||
)
|
|
||||||
|
|
||||||
MAXIMUM_VISIBILTY_TIMEOUT = 43200
|
MAXIMUM_VISIBILTY_TIMEOUT = 43200
|
||||||
MAXIMUM_MESSAGE_LENGTH = 262144 # 256 KiB
|
MAXIMUM_MESSAGE_LENGTH = 262144 # 256 KiB
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
[nosetests]
|
[nosetests]
|
||||||
verbosity=1
|
verbosity=1
|
||||||
detailed-errors=1
|
detailed-errors=1
|
||||||
with-coverage=1
|
|
||||||
cover-package=moto
|
cover-package=moto
|
||||||
|
|
||||||
[bdist_wheel]
|
[bdist_wheel]
|
||||||
|
0
tests/test_datasync/__init__.py
Normal file
0
tests/test_datasync/__init__.py
Normal file
45
tests/test_datasync/test_datasync.py
Normal file
45
tests/test_datasync/test_datasync.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import logging
|
||||||
|
|
||||||
|
import boto
|
||||||
|
import boto3
|
||||||
|
from moto import mock_datasync
|
||||||
|
|
||||||
|
|
||||||
|
@mock_datasync
|
||||||
|
def test_create_location_smb():
|
||||||
|
client = boto3.client("datasync", region_name="us-east-1")
|
||||||
|
response = client.create_location_smb(ServerHostname='host',
|
||||||
|
Subdirectory='somewhere',
|
||||||
|
User='',
|
||||||
|
Password='',
|
||||||
|
AgentArns=['stuff'])
|
||||||
|
assert 'LocationArn' in response
|
||||||
|
|
||||||
|
|
||||||
|
@mock_datasync
|
||||||
|
def test_create_location_s3():
|
||||||
|
client = boto3.client("datasync", region_name="us-east-1")
|
||||||
|
response = client.create_location_s3(S3BucketArn='my_bucket',
|
||||||
|
Subdirectory='dir',
|
||||||
|
S3Config={'BucketAccessRoleArn':'role'})
|
||||||
|
assert 'LocationArn' in response
|
||||||
|
|
||||||
|
'''
|
||||||
|
@mock_datasync
|
||||||
|
def test_list_locations():
|
||||||
|
client = boto3.client("datasync", region_name="us-east-1")
|
||||||
|
response = client.list_locations()
|
||||||
|
logging.info ('No locations: {0}'.format(response))
|
||||||
|
|
||||||
|
response = client.create_location_smb(ServerHostname='host',
|
||||||
|
Subdirectory='somewhere',
|
||||||
|
User='',
|
||||||
|
Password='',
|
||||||
|
AgentArns=['stuff'])
|
||||||
|
logging.info ('A location 1 : {0}'.format(response))
|
||||||
|
response = client.list_locations()
|
||||||
|
logging.info ('A location 2 : {0}'.format(response))
|
||||||
|
|
||||||
|
assert 1 == 0
|
||||||
|
#assert response == ["TestLocation"]
|
||||||
|
'''
|
@ -33,7 +33,7 @@ def test_create_fifo_queue_fail():
|
|||||||
except botocore.exceptions.ClientError as err:
|
except botocore.exceptions.ClientError as err:
|
||||||
err.response["Error"]["Code"].should.equal("InvalidParameterValue")
|
err.response["Error"]["Code"].should.equal("InvalidParameterValue")
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("Should of raised InvalidParameterValue Exception")
|
raise RuntimeError("Should of raised InvalidParameterValue Exception")z
|
||||||
|
|
||||||
|
|
||||||
@mock_sqs
|
@mock_sqs
|
||||||
|
Loading…
Reference in New Issue
Block a user