diff --git a/docs/_build/html/_sources/index.rst.txt b/docs/_build/html/_sources/index.rst.txt index bd2f0aac8..fc5ed7652 100644 --- a/docs/_build/html/_sources/index.rst.txt +++ b/docs/_build/html/_sources/index.rst.txt @@ -30,7 +30,7 @@ Currently implemented Services: +-----------------------+---------------------+-----------------------------------+ | Data Pipeline | @mock_datapipeline | basic endpoints done | +-----------------------+---------------------+-----------------------------------+ -| DataSync | @mock_datasync | basic endpoints done | +| DataSync | @mock_datasync | some endpoints done | +-----------------------+---------------------+-----------------------------------+ | - DynamoDB | - @mock_dynamodb | - core endpoints done | | - DynamoDB2 | - @mock_dynamodb2 | - core endpoints + partial indexes| diff --git a/file.tmp b/file.tmp deleted file mode 100644 index 80053c647..000000000 --- a/file.tmp +++ /dev/null @@ -1,9 +0,0 @@ - - AWSTemplateFormatVersion: '2010-09-09' - Description: Simple CloudFormation Test Template - Resources: - S3Bucket: - Type: AWS::S3::Bucket - Properties: - AccessControl: PublicRead - BucketName: cf-test-bucket-1 diff --git a/moto/__init__.py b/moto/__init__.py index 4b6c3fddd..cbca726d0 100644 --- a/moto/__init__.py +++ b/moto/__init__.py @@ -7,14 +7,14 @@ from .autoscaling import mock_autoscaling, mock_autoscaling_deprecated # noqa from .awslambda import mock_lambda, mock_lambda_deprecated # noqa from .batch import mock_batch # noqa from .cloudformation import mock_cloudformation # noqa -from .cloudformation import mock_cloudformation_deprecated +from .cloudformation import mock_cloudformation_deprecated # noqa from .cloudwatch import mock_cloudwatch, mock_cloudwatch_deprecated # noqa from .cognitoidentity import mock_cognitoidentity # noqa -from .cognitoidentity import mock_cognitoidentity_deprecated +from .cognitoidentity import mock_cognitoidentity_deprecated # noqa from .cognitoidp import mock_cognitoidp, mock_cognitoidp_deprecated # noqa from .config import mock_config # noqa from .datapipeline import mock_datapipeline # noqa -from .datapipeline import mock_datapipeline_deprecated +from .datapipeline import mock_datapipeline_deprecated # noqa from .datasync import mock_datasync # noqa from .dynamodb import mock_dynamodb, mock_dynamodb_deprecated # noqa from .dynamodb2 import mock_dynamodb2, mock_dynamodb2_deprecated # noqa @@ -61,7 +61,6 @@ __title__ = "moto" __version__ = "1.3.14.dev" - try: # Need to monkey-patch botocore requests back to underlying urllib3 classes from botocore.awsrequest import ( diff --git a/moto/datasync/exceptions.py b/moto/datasync/exceptions.py new file mode 100644 index 000000000..b0f2d8f0f --- /dev/null +++ b/moto/datasync/exceptions.py @@ -0,0 +1,15 @@ +from __future__ import unicode_literals + +from moto.core.exceptions import JsonRESTError + + +class DataSyncClientError(JsonRESTError): + code = 400 + + +class InvalidRequestException(DataSyncClientError): + def __init__(self, msg=None): + self.code = 400 + super(InvalidRequestException, self).__init__( + "InvalidRequestException", msg or "The request is not valid." + ) diff --git a/moto/datasync/models.py b/moto/datasync/models.py index 7eb839a82..42626cceb 100644 --- a/moto/datasync/models.py +++ b/moto/datasync/models.py @@ -1,95 +1,177 @@ -import json -import logging -import random -import string - import boto3 from moto.compat import OrderedDict from moto.core import BaseBackend, BaseModel +from .exceptions import InvalidRequestException + class Location(BaseModel): - - def __init__(self, - location_uri, - region_name, - arn_counter=0): + def __init__( + self, location_uri, region_name=None, typ=None, metadata=None, arn_counter=0 + ): self.uri = location_uri self.region_name = region_name + self.metadata = metadata + self.typ = typ # Generate ARN - self.arn = 'arn:aws:datasync:{0}:111222333444:location/loc-{1}'.format(region_name, str(arn_counter).zfill(17)) + self.arn = "arn:aws:datasync:{0}:111222333444:location/loc-{1}".format( + region_name, str(arn_counter).zfill(17) + ) class Task(BaseModel): - def __init__(self, - source_location_arn, - destination_location_arn, - name, - region_name, - arn_counter=0): + def __init__( + self, + source_location_arn, + destination_location_arn, + name, + region_name, + arn_counter=0, + ): self.source_location_arn = source_location_arn self.destination_location_arn = destination_location_arn - self.status = 'AVAILABLE' + # For simplicity Tasks are either available or running + self.status = "AVAILABLE" self.name = name + self.current_task_execution_arn = None # Generate ARN - self.arn = 'arn:aws:datasync:{0}:111222333444:task/task-{1}'.format(region_name, str(arn_counter).zfill(17)) + self.arn = "arn:aws:datasync:{0}:111222333444:task/task-{1}".format( + region_name, str(arn_counter).zfill(17) + ) + class TaskExecution(BaseModel): - def __init__(self, - task_arn, - arn_counter=0): + + # For simplicity, task_execution can never fail + # Some documentation refers to this list: + # 'Status': 'QUEUED'|'LAUNCHING'|'PREPARING'|'TRANSFERRING'|'VERIFYING'|'SUCCESS'|'ERROR' + # Others refers to this list: + # INITIALIZING | PREPARING | TRANSFERRING | VERIFYING | SUCCESS/FAILURE + # Checking with AWS Support... + TASK_EXECUTION_INTERMEDIATE_STATES = ( + "INITIALIZING", + # 'QUEUED', 'LAUNCHING', + "PREPARING", + "TRANSFERRING", + "VERIFYING", + ) + + TASK_EXECUTION_FAILURE_STATES = ("ERROR",) + TASK_EXECUTION_SUCCESS_STATES = ("SUCCESS",) + # Also COMPLETED state? + + def __init__(self, task_arn, arn_counter=0): self.task_arn = task_arn - self.arn = '{0}/execution/exec-{1}'.format(task_arn, str(arn_counter).zfill(17)) + self.arn = "{0}/execution/exec-{1}".format(task_arn, str(arn_counter).zfill(17)) + self.status = self.TASK_EXECUTION_INTERMEDIATE_STATES[0] + + # Simulate a task execution + def iterate_status(self): + if self.status in self.TASK_EXECUTION_FAILURE_STATES: + return + if self.status in self.TASK_EXECUTION_SUCCESS_STATES: + return + if self.status in self.TASK_EXECUTION_INTERMEDIATE_STATES: + for i, status in enumerate(self.TASK_EXECUTION_INTERMEDIATE_STATES): + if status == self.status: + if i < len(self.TASK_EXECUTION_INTERMEDIATE_STATES) - 1: + self.status = self.TASK_EXECUTION_INTERMEDIATE_STATES[i + 1] + else: + self.status = self.TASK_EXECUTION_SUCCESS_STATES[0] + return + raise Exception( + "TaskExecution.iterate_status: Unknown status={0}".format(self.status) + ) + + def cancel(self): + if self.status not in self.TASK_EXECUTION_INTERMEDIATE_STATES: + raise InvalidRequestException( + "Sync task cannot be cancelled in its current status: {0}".format( + self.status + ) + ) + self.status = "ERROR" + class DataSyncBackend(BaseBackend): def __init__(self, region_name): self.region_name = region_name # Always increase when new things are created # This ensures uniqueness - self.arn_counter = 0 - self.locations = dict() - self.tasks = dict() - self.task_executions = dict() - + self.arn_counter = 0 + self.locations = OrderedDict() + self.tasks = OrderedDict() + self.task_executions = 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): - # TODO BJORN figure out exception - # TODO BJORN test for exception + def create_location(self, location_uri, typ=None, metadata=None): + """ + # AWS DataSync allows for duplicate LocationUris for arn, location in self.locations.items(): if location.uri == location_uri: raise Exception('Location already exists') + """ + if not typ: + raise Exception("Location type must be specified") self.arn_counter = self.arn_counter + 1 - location = Location(location_uri, - region_name=self.region_name, - arn_counter=self.arn_counter) + location = Location( + location_uri, + region_name=self.region_name, + arn_counter=self.arn_counter, + metadata=metadata, + typ=typ, + ) self.locations[location.arn] = location return location.arn - def create_task(self, - source_location_arn, - destination_location_arn, - name): + def create_task(self, source_location_arn, destination_location_arn, name): + if source_location_arn not in self.locations: + raise InvalidRequestException( + "Location {0} not found.".format(source_location_arn) + ) + if destination_location_arn not in self.locations: + raise InvalidRequestException( + "Location {0} not found.".format(destination_location_arn) + ) self.arn_counter = self.arn_counter + 1 - task = Task(source_location_arn, - destination_location_arn, - name, - region_name=self.region_name, - arn_counter=self.arn_counter - ) + task = Task( + source_location_arn, + destination_location_arn, + name, + region_name=self.region_name, + arn_counter=self.arn_counter, + ) self.tasks[task.arn] = task return task.arn def start_task_execution(self, task_arn): self.arn_counter = self.arn_counter + 1 - task_execution = TaskExecution(task_arn, - arn_counter=self.arn_counter) - self.task_executions[task_execution.arn] = task_execution - return task_execution.arn + if task_arn in self.tasks: + task = self.tasks[task_arn] + if task.status == "AVAILABLE": + task_execution = TaskExecution(task_arn, arn_counter=self.arn_counter) + self.task_executions[task_execution.arn] = task_execution + self.tasks[task_arn].current_task_execution_arn = task_execution.arn + self.tasks[task_arn].status = "RUNNING" + return task_execution.arn + raise InvalidRequestException("Invalid request.") + + def cancel_task_execution(self, task_execution_arn): + if task_execution_arn in self.task_executions: + task_execution = self.task_executions[task_execution_arn] + task_execution.cancel() + task_arn = task_execution.task_arn + self.tasks[task_arn].current_task_execution_arn = None + return + raise InvalidRequestException( + "Sync task {0} is not found.".format(task_execution_arn) + ) + datasync_backends = {} for region in boto3.Session().get_available_regions("datasync"): diff --git a/moto/datasync/responses.py b/moto/datasync/responses.py index e2f6e2f77..30b906d44 100644 --- a/moto/datasync/responses.py +++ b/moto/datasync/responses.py @@ -1,18 +1,12 @@ import json -import logging -import re from moto.core.responses import BaseResponse -from six.moves.urllib.parse import urlparse +from .exceptions import InvalidRequestException from .models import datasync_backends class DataSyncResponse(BaseResponse): - - # TODO BJORN check datasync rege - region_regex = re.compile(r"://(.+?)\.datasync\.amazonaws\.com") - @property def datasync_backend(self): return datasync_backends[self.region] @@ -20,37 +14,77 @@ class DataSyncResponse(BaseResponse): def list_locations(self): locations = list() for arn, location in self.datasync_backend.locations.items(): - locations.append( { - 'LocationArn': location.arn, - 'LocationUri': location.uri - }) - + locations.append({"LocationArn": location.arn, "LocationUri": location.uri}) return json.dumps({"Locations": locations}) - + + def _get_location(self, location_arn, typ): + location_arn = self._get_param("LocationArn") + if location_arn not in self.datasync_backend.locations: + raise InvalidRequestException( + "Location {0} is not found.".format(location_arn) + ) + location = self.datasync_backend.locations[location_arn] + if location.typ != typ: + raise InvalidRequestException( + "Invalid Location type: {0}".format(location.typ) + ) + return location + def create_location_s3(self): # s3://bucket_name/folder/ s3_bucket_arn = self._get_param("S3BucketArn") subdirectory = self._get_param("Subdirectory") - - location_uri_elts = ['s3:/', s3_bucket_arn.split(':')[-1]] + metadata = {"S3Config": self._get_param("S3Config")} + location_uri_elts = ["s3:/", s3_bucket_arn.split(":")[-1]] if subdirectory: location_uri_elts.append(subdirectory) - location_uri='/'.join(location_uri_elts) - arn = self.datasync_backend.create_location(location_uri) - - return json.dumps({'LocationArn':arn}) + location_uri = "/".join(location_uri_elts) + arn = self.datasync_backend.create_location( + location_uri, metadata=metadata, typ="S3" + ) + return json.dumps({"LocationArn": arn}) + def describe_location_s3(self): + location_arn = self._get_param("LocationArn") + location = self._get_location(location_arn, typ="S3") + return json.dumps( + { + "LocationArn": location.arn, + "LocationUri": location.uri, + "S3Config": location.metadata["S3Config"], + } + ) def create_location_smb(self): # smb://smb.share.fqdn/AWS_Test/ subdirectory = self._get_param("Subdirectory") server_hostname = self._get_param("ServerHostname") + metadata = { + "AgentArns": self._get_param("AgentArns"), + "User": self._get_param("User"), + "Domain": self._get_param("Domain"), + "MountOptions": self._get_param("MountOptions"), + } - location_uri = '/'.join(['smb:/', server_hostname, subdirectory]) - arn = self.datasync_backend.create_location(location_uri) - - return json.dumps({'LocationArn':arn}) + location_uri = "/".join(["smb:/", server_hostname, subdirectory]) + arn = self.datasync_backend.create_location( + location_uri, metadata=metadata, typ="SMB" + ) + return json.dumps({"LocationArn": arn}) + def describe_location_smb(self): + location_arn = self._get_param("LocationArn") + location = self._get_location(location_arn, typ="SMB") + return json.dumps( + { + "LocationArn": location.arn, + "LocationUri": location.uri, + "AgentArns": location.metadata["AgentArns"], + "User": location.metadata["User"], + "Domain": location.metadata["Domain"], + "MountOptions": location.metadata["MountOptions"], + } + ) def create_task(self): destination_location_arn = self._get_param("DestinationLocationArn") @@ -58,45 +92,64 @@ class DataSyncResponse(BaseResponse): name = self._get_param("Name") arn = self.datasync_backend.create_task( - source_location_arn, - destination_location_arn, - name + source_location_arn, destination_location_arn, name ) - - return json.dumps({'TaskArn':arn}) + return json.dumps({"TaskArn": arn}) def list_tasks(self): tasks = list() for arn, task in self.datasync_backend.tasks.items(): - tasks.append( { - 'Name': task.name, - 'Status': task.status, - 'TaskArn': task.arn - }) - + tasks.append( + {"Name": task.name, "Status": task.status, "TaskArn": task.arn} + ) return json.dumps({"Tasks": tasks}) def describe_task(self): task_arn = self._get_param("TaskArn") if task_arn in self.datasync_backend.tasks: task = self.datasync_backend.tasks[task_arn] - return json.dumps({ - 'TaskArn': task.arn, - 'Name': task.name, - 'Status': task.status, - 'SourceLocationArn': task.source_location_arn, - 'DestinationLocationArn': task.destination_location_arn - }) - # TODO BJORN exception if task_arn not found? - return None + return json.dumps( + { + "TaskArn": task.arn, + "Name": task.name, + "CurrentTaskExecutionArn": task.current_task_execution_arn, + "Status": task.status, + "SourceLocationArn": task.source_location_arn, + "DestinationLocationArn": task.destination_location_arn, + } + ) + raise InvalidRequestException def start_task_execution(self): task_arn = self._get_param("TaskArn") if task_arn in self.datasync_backend.tasks: - arn = self.datasync_backend.start_task_execution( - task_arn - ) - return json.dumps({'TaskExecutionArn':arn}) + arn = self.datasync_backend.start_task_execution(task_arn) + if arn: + return json.dumps({"TaskExecutionArn": arn}) + raise InvalidRequestException("Invalid request.") - # TODO BJORN exception if task_arn not found? - return None + def cancel_task_execution(self): + task_execution_arn = self._get_param("TaskExecutionArn") + self.datasync_backend.cancel_task_execution(task_execution_arn) + return json.dumps({}) + + def describe_task_execution(self): + task_execution_arn = self._get_param("TaskExecutionArn") + + if task_execution_arn in self.datasync_backend.task_executions: + task_execution = self.datasync_backend.task_executions[task_execution_arn] + if task_execution: + result = json.dumps( + { + "TaskExecutionArn": task_execution.arn, + "Status": task_execution.status, + } + ) + if task_execution.status == "SUCCESS": + self.datasync_backend.tasks[ + task_execution.task_arn + ].status = "AVAILABLE" + # Simulate task being executed + task_execution.iterate_status() + return result + raise InvalidRequestException diff --git a/moto/sqs/responses.py b/moto/sqs/responses.py index 8bc6b297a..8acea0799 100644 --- a/moto/sqs/responses.py +++ b/moto/sqs/responses.py @@ -6,9 +6,13 @@ from moto.core.responses import BaseResponse from moto.core.utils import amz_crc32, amzn_request_id from six.moves.urllib.parse import urlparse -from .exceptions import (EmptyBatchRequest, InvalidAttributeName, - MessageAttributesInvalid, MessageNotInflight, - ReceiptHandleIsInvalid) +from .exceptions import ( + EmptyBatchRequest, + InvalidAttributeName, + MessageAttributesInvalid, + MessageNotInflight, + ReceiptHandleIsInvalid, +) from .models import sqs_backends from .utils import parse_message_attributes diff --git a/setup.cfg b/setup.cfg index fe6427c1d..fb04c16a8 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,7 @@ [nosetests] verbosity=1 detailed-errors=1 +with-coverage=1 cover-package=moto [bdist_wheel] diff --git a/tests/test_datasync/test_datasync.py b/tests/test_datasync/test_datasync.py index 280434791..825eb7fba 100644 --- a/tests/test_datasync/test_datasync.py +++ b/tests/test_datasync/test_datasync.py @@ -2,134 +2,326 @@ import logging import boto import boto3 +from botocore.exceptions import ClientError from moto import mock_datasync +from nose.tools import assert_raises -''' -Endpoints I need to test: -start_task_execution -cancel_task_execution -describe_task_execution -''' - +def create_locations(client, create_smb=False, create_s3=False): + """ + Convenience function for creating locations. + Locations must exist before tasks can be created. + """ + smb_arn = None + s3_arn = None + if create_smb: + response = client.create_location_smb( + ServerHostname="host", + Subdirectory="somewhere", + User="", + Password="", + AgentArns=["stuff"], + ) + smb_arn = response["LocationArn"] + if create_s3: + response = client.create_location_s3( + S3BucketArn="arn:aws:s3:::my_bucket", + Subdirectory="dir", + S3Config={"BucketAccessRoleArn": "role"}, + ) + s3_arn = response["LocationArn"] + return {"smb_arn": smb_arn, "s3_arn": s3_arn} @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 + response = client.create_location_smb( + ServerHostname="host", + Subdirectory="somewhere", + User="", + Password="", + AgentArns=["stuff"], + ) + assert "LocationArn" in response + + +@mock_datasync +def test_describe_location_smb(): + client = boto3.client("datasync", region_name="us-east-1") + agent_arns = ["stuff"] + user = "user" + response = client.create_location_smb( + ServerHostname="host", + Subdirectory="somewhere", + User=user, + Password="", + AgentArns=agent_arns, + ) + response = client.describe_location_smb(LocationArn=response["LocationArn"]) + assert "LocationArn" in response + assert "LocationUri" in response + assert response["User"] == user + assert response["AgentArns"] == agent_arns @mock_datasync def test_create_location_s3(): client = boto3.client("datasync", region_name="us-east-1") - response = client.create_location_s3(S3BucketArn='arn:aws:s3:::my_bucket', - Subdirectory='dir', - S3Config={'BucketAccessRoleArn':'role'}) - assert 'LocationArn' in response + response = client.create_location_s3( + S3BucketArn="arn:aws:s3:::my_bucket", + Subdirectory="dir", + S3Config={"BucketAccessRoleArn": "role"}, + ) + assert "LocationArn" in response + + +@mock_datasync +def test_describe_location_s3(): + client = boto3.client("datasync", region_name="us-east-1") + s3_config = {"BucketAccessRoleArn": "role"} + response = client.create_location_s3( + S3BucketArn="arn:aws:s3:::my_bucket", Subdirectory="dir", S3Config=s3_config + ) + response = client.describe_location_s3(LocationArn=response["LocationArn"]) + assert "LocationArn" in response + assert "LocationUri" in response + assert response["S3Config"] == s3_config + + +@mock_datasync +def test_describe_location_wrong(): + client = boto3.client("datasync", region_name="us-east-1") + agent_arns = ["stuff"] + user = "user" + response = client.create_location_smb( + ServerHostname="host", + Subdirectory="somewhere", + User=user, + Password="", + AgentArns=agent_arns, + ) + with assert_raises(ClientError) as e: + response = client.describe_location_s3(LocationArn=response["LocationArn"]) + @mock_datasync def test_list_locations(): client = boto3.client("datasync", region_name="us-east-1") response = client.list_locations() - # TODO BJORN check if Locations exists when there are none - assert len(response['Locations']) == 0 + assert len(response["Locations"]) == 0 - response = client.create_location_smb(ServerHostname='host', - Subdirectory='somewhere', - User='', - Password='', - AgentArns=['stuff']) + create_locations(client, create_smb=True) response = client.list_locations() - assert len(response['Locations']) == 1 - assert response['Locations'][0]['LocationUri'] == 'smb://host/somewhere' - - response = client.create_location_s3(S3BucketArn='arn:aws:s3:::my_bucket', - S3Config={'BucketAccessRoleArn':'role'}) + assert len(response["Locations"]) == 1 + assert response["Locations"][0]["LocationUri"] == "smb://host/somewhere" + create_locations(client, create_s3=True) response = client.list_locations() - assert len(response['Locations']) == 2 - assert response['Locations'][1]['LocationUri'] == 's3://my_bucket' - - response = client.create_location_s3(S3BucketArn='arn:aws:s3:::my_bucket', - Subdirectory='subdir', - S3Config={'BucketAccessRoleArn':'role'}) + assert len(response["Locations"]) == 2 + assert response["Locations"][1]["LocationUri"] == "s3://my_bucket/dir" + create_locations(client, create_s3=True) response = client.list_locations() - assert len(response['Locations']) == 3 - assert response['Locations'][2]['LocationUri'] == 's3://my_bucket/subdir' + assert len(response["Locations"]) == 3 + assert response["Locations"][2]["LocationUri"] == "s3://my_bucket/dir" + @mock_datasync def test_create_task(): client = boto3.client("datasync", region_name="us-east-1") - # TODO BJORN check if task can be created when there are no locations + locations = create_locations(client, create_smb=True, create_s3=True) response = client.create_task( - SourceLocationArn='1', - DestinationLocationArn='2' + SourceLocationArn=locations["smb_arn"], + DestinationLocationArn=locations["s3_arn"], ) - assert 'TaskArn' in response + assert "TaskArn" in response + + +@mock_datasync +def test_create_task_fail(): + """ Test that Locations must exist before a Task can be created """ + client = boto3.client("datasync", region_name="us-east-1") + locations = create_locations(client, create_smb=True, create_s3=True) + with assert_raises(ClientError) as e: + response = client.create_task( + SourceLocationArn="1", DestinationLocationArn=locations["s3_arn"] + ) + with assert_raises(ClientError) as e: + response = client.create_task( + SourceLocationArn=locations["smb_arn"], DestinationLocationArn="2" + ) + @mock_datasync def test_list_tasks(): client = boto3.client("datasync", region_name="us-east-1") + locations = create_locations(client, create_s3=True, create_smb=True) + response = client.create_task( - SourceLocationArn='1', - DestinationLocationArn='2', + SourceLocationArn=locations["smb_arn"], + DestinationLocationArn=locations["s3_arn"], ) response = client.create_task( - SourceLocationArn='3', - DestinationLocationArn='4', - Name='task_name' + SourceLocationArn=locations["s3_arn"], + DestinationLocationArn=locations["smb_arn"], + Name="task_name", ) response = client.list_tasks() - tasks = response['Tasks'] + tasks = response["Tasks"] assert len(tasks) == 2 task = tasks[0] - assert task['Status'] == 'AVAILABLE' - assert 'Name' not in task + assert task["Status"] == "AVAILABLE" + assert "Name" not in task task = tasks[1] - assert task['Status'] == 'AVAILABLE' - assert task['Name'] == 'task_name' + assert task["Status"] == "AVAILABLE" + assert task["Name"] == "task_name" + @mock_datasync def test_describe_task(): client = boto3.client("datasync", region_name="us-east-1") - - response = client.create_task( - SourceLocationArn='3', - DestinationLocationArn='4', - Name='task_name' - ) - task_arn = response['TaskArn'] + locations = create_locations(client, create_s3=True, create_smb=True) - response = client.describe_task( - TaskArn=task_arn + response = client.create_task( + SourceLocationArn=locations["smb_arn"], + DestinationLocationArn=locations["s3_arn"], + Name="task_name", ) - - assert 'TaskArn' in response - assert 'Status' in response - assert 'SourceLocationArn' in response - assert 'DestinationLocationArn' in response + task_arn = response["TaskArn"] + + response = client.describe_task(TaskArn=task_arn) + + assert "TaskArn" in response + assert "Status" in response + assert "SourceLocationArn" in response + assert "DestinationLocationArn" in response + + +@mock_datasync +def test_describe_task_not_exist(): + client = boto3.client("datasync", region_name="us-east-1") + + with assert_raises(ClientError) as e: + client.describe_task(TaskArn="abc") + @mock_datasync def test_start_task_execution(): client = boto3.client("datasync", region_name="us-east-1") - + locations = create_locations(client, create_s3=True, create_smb=True) + response = client.create_task( - SourceLocationArn='3', - DestinationLocationArn='4', - Name='task_name' - ) - task_arn = response['TaskArn'] - - response = client.start_task_execution( - TaskArn=task_arn + SourceLocationArn=locations["smb_arn"], + DestinationLocationArn=locations["s3_arn"], + Name="task_name", ) - assert 'TaskExecutionArn' in response + task_arn = response["TaskArn"] + response = client.describe_task(TaskArn=task_arn) + assert "CurrentTaskExecutionArn" not in response + + response = client.start_task_execution(TaskArn=task_arn) + assert "TaskExecutionArn" in response + task_execution_arn = response["TaskExecutionArn"] + + response = client.describe_task(TaskArn=task_arn) + assert response["CurrentTaskExecutionArn"] == task_execution_arn + + +@mock_datasync +def test_start_task_execution_twice(): + client = boto3.client("datasync", region_name="us-east-1") + locations = create_locations(client, create_s3=True, create_smb=True) + + response = client.create_task( + SourceLocationArn=locations["smb_arn"], + DestinationLocationArn=locations["s3_arn"], + Name="task_name", + ) + task_arn = response["TaskArn"] + + response = client.start_task_execution(TaskArn=task_arn) + assert "TaskExecutionArn" in response + task_execution_arn = response["TaskExecutionArn"] + + with assert_raises(ClientError) as e: + response = client.start_task_execution(TaskArn=task_arn) + + +@mock_datasync +def test_describe_task_execution(): + client = boto3.client("datasync", region_name="us-east-1") + locations = create_locations(client, create_s3=True, create_smb=True) + + response = client.create_task( + SourceLocationArn=locations["smb_arn"], + DestinationLocationArn=locations["s3_arn"], + Name="task_name", + ) + task_arn = response["TaskArn"] + + response = client.start_task_execution(TaskArn=task_arn) + task_execution_arn = response["TaskExecutionArn"] + + # Each time task_execution is described the Status will increment + # This is a simple way to simulate a task being executed + response = client.describe_task_execution(TaskExecutionArn=task_execution_arn) + assert response["TaskExecutionArn"] == task_execution_arn + assert response["Status"] == "INITIALIZING" + + response = client.describe_task_execution(TaskExecutionArn=task_execution_arn) + assert response["TaskExecutionArn"] == task_execution_arn + assert response["Status"] == "PREPARING" + + response = client.describe_task_execution(TaskExecutionArn=task_execution_arn) + assert response["TaskExecutionArn"] == task_execution_arn + assert response["Status"] == "TRANSFERRING" + + response = client.describe_task_execution(TaskExecutionArn=task_execution_arn) + assert response["TaskExecutionArn"] == task_execution_arn + assert response["Status"] == "VERIFYING" + + response = client.describe_task_execution(TaskExecutionArn=task_execution_arn) + assert response["TaskExecutionArn"] == task_execution_arn + assert response["Status"] == "SUCCESS" + + response = client.describe_task_execution(TaskExecutionArn=task_execution_arn) + assert response["TaskExecutionArn"] == task_execution_arn + assert response["Status"] == "SUCCESS" + + +@mock_datasync +def test_describe_task_execution_not_exist(): + client = boto3.client("datasync", region_name="us-east-1") + + with assert_raises(ClientError) as e: + client.describe_task_execution(TaskExecutionArn="abc") + + +@mock_datasync +def test_cancel_task_execution(): + client = boto3.client("datasync", region_name="us-east-1") + locations = create_locations(client, create_s3=True, create_smb=True) + + response = client.create_task( + SourceLocationArn=locations["smb_arn"], + DestinationLocationArn=locations["s3_arn"], + Name="task_name", + ) + task_arn = response["TaskArn"] + + response = client.start_task_execution(TaskArn=task_arn) + task_execution_arn = response["TaskExecutionArn"] + + response = client.describe_task(TaskArn=task_arn) + assert response["CurrentTaskExecutionArn"] == task_execution_arn + + response = client.cancel_task_execution(TaskExecutionArn=task_execution_arn) + + response = client.describe_task(TaskArn=task_arn) + assert "CurrentTaskExecutionArn" not in response + + response = client.describe_task_execution(TaskExecutionArn=task_execution_arn) + assert response["Status"] == "ERROR" diff --git a/tests/test_sqs/test_sqs.py b/tests/test_sqs/test_sqs.py index 8cf56e8cc..2af94c5fd 100644 --- a/tests/test_sqs/test_sqs.py +++ b/tests/test_sqs/test_sqs.py @@ -1,27 +1,26 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals + +import base64 +import json import os +import time +import uuid import boto import boto3 import botocore.exceptions import six -from botocore.exceptions import ClientError -from boto.exception import SQSError -from boto.sqs.message import RawMessage, Message - -from freezegun import freeze_time -import base64 -import json import sure # noqa -import time -import uuid - -from moto import settings, mock_sqs, mock_sqs_deprecated -from tests.helpers import requires_boto_gte import tests.backport_assert_raises # noqa -from nose.tools import assert_raises +from boto.exception import SQSError +from boto.sqs.message import Message, RawMessage +from botocore.exceptions import ClientError +from freezegun import freeze_time +from moto import mock_sqs, mock_sqs_deprecated, settings from nose import SkipTest +from nose.tools import assert_raises +from tests.helpers import requires_boto_gte @mock_sqs @@ -33,7 +32,7 @@ def test_create_fifo_queue_fail(): except botocore.exceptions.ClientError as err: err.response["Error"]["Code"].should.equal("InvalidParameterValue") else: - raise RuntimeError("Should of raised InvalidParameterValue Exception")z + raise RuntimeError("Should of raised InvalidParameterValue Exception") @mock_sqs