added IoT job_execution and job mocks
This commit is contained in:
parent
3ea673b3d0
commit
cfd12b6d19
File diff suppressed because it is too large
Load Diff
@ -1,33 +1,42 @@
|
||||
from __future__ import unicode_literals
|
||||
from moto.core.exceptions import JsonRESTError
|
||||
|
||||
|
||||
class IoTClientError(JsonRESTError):
|
||||
code = 400
|
||||
|
||||
|
||||
class ResourceNotFoundException(IoTClientError):
|
||||
def __init__(self):
|
||||
self.code = 404
|
||||
super(ResourceNotFoundException, self).__init__(
|
||||
"ResourceNotFoundException",
|
||||
"The specified resource does not exist"
|
||||
)
|
||||
|
||||
|
||||
class InvalidRequestException(IoTClientError):
|
||||
def __init__(self, msg=None):
|
||||
self.code = 400
|
||||
super(InvalidRequestException, self).__init__(
|
||||
"InvalidRequestException",
|
||||
msg or "The request is not valid."
|
||||
)
|
||||
|
||||
|
||||
class VersionConflictException(IoTClientError):
|
||||
def __init__(self, name):
|
||||
self.code = 409
|
||||
super(VersionConflictException, self).__init__(
|
||||
'VersionConflictException',
|
||||
'The version for thing %s does not match the expected version.' % name
|
||||
)
|
||||
from __future__ import unicode_literals
|
||||
from moto.core.exceptions import JsonRESTError
|
||||
|
||||
|
||||
class IoTClientError(JsonRESTError):
|
||||
code = 400
|
||||
|
||||
|
||||
class ResourceNotFoundException(IoTClientError):
|
||||
def __init__(self):
|
||||
self.code = 404
|
||||
super(ResourceNotFoundException, self).__init__(
|
||||
"ResourceNotFoundException",
|
||||
"The specified resource does not exist"
|
||||
)
|
||||
|
||||
|
||||
class InvalidRequestException(IoTClientError):
|
||||
def __init__(self, msg=None):
|
||||
self.code = 400
|
||||
super(InvalidRequestException, self).__init__(
|
||||
"InvalidRequestException",
|
||||
msg or "The request is not valid."
|
||||
)
|
||||
|
||||
|
||||
class InvalidStateTransitionException(IoTClientError):
|
||||
def __init__(self, msg=None):
|
||||
self.code = 409
|
||||
super(InvalidStateTransitionException, self).__init__(
|
||||
"InvalidStateTransitionException",
|
||||
msg or "An attempt was made to change to an invalid state."
|
||||
)
|
||||
|
||||
|
||||
class VersionConflictException(IoTClientError):
|
||||
def __init__(self, name):
|
||||
self.code = 409
|
||||
super(VersionConflictException, self).__init__(
|
||||
'VersionConflictException',
|
||||
'The version for thing %s does not match the expected version.' % name
|
||||
)
|
||||
|
@ -15,6 +15,7 @@ from moto.core import BaseBackend, BaseModel
|
||||
from .exceptions import (
|
||||
ResourceNotFoundException,
|
||||
InvalidRequestException,
|
||||
InvalidStateTransitionException,
|
||||
VersionConflictException
|
||||
)
|
||||
|
||||
@ -247,7 +248,6 @@ class FakeJob(BaseModel):
|
||||
self.document_parameters = document_parameters
|
||||
|
||||
def to_dict(self):
|
||||
|
||||
obj = {
|
||||
'jobArn': self.job_arn,
|
||||
'jobId': self.job_id,
|
||||
@ -260,7 +260,7 @@ class FakeJob(BaseModel):
|
||||
'comment': self.comment,
|
||||
'createdAt': self.created_at,
|
||||
'lastUpdatedAt': self.last_updated_at,
|
||||
'completedAt': self.completedAt,
|
||||
'completedAt': self.completed_at,
|
||||
'jobProcessDetails': self.job_process_details,
|
||||
'documentParameters': self.document_parameters,
|
||||
'document': self.document,
|
||||
@ -290,13 +290,13 @@ class FakeJobExecution(BaseModel):
|
||||
self.version_number = 123
|
||||
self.approximate_seconds_before_time_out = 123
|
||||
|
||||
def to_dict(self):
|
||||
def to_get_dict(self):
|
||||
obj = {
|
||||
'jobId': self.job_id,
|
||||
'status': self.status,
|
||||
'forceCancel': self.force_canceled,
|
||||
'forceCanceled': self.force_canceled,
|
||||
'statusDetails': {'detailsMap': self.status_details_map},
|
||||
'thing_arn': self.thing_arn,
|
||||
'thingArn': self.thing_arn,
|
||||
'queuedAt': self.queued_at,
|
||||
'startedAt': self.started_at,
|
||||
'lastUpdatedAt': self.last_updated_at,
|
||||
@ -307,6 +307,21 @@ class FakeJobExecution(BaseModel):
|
||||
|
||||
return obj
|
||||
|
||||
def to_dict(self):
|
||||
obj = {
|
||||
'jobId': self.job_id,
|
||||
'thingArn': self.thing_arn,
|
||||
'jobExecutionSummary': {
|
||||
'status': self.status,
|
||||
'queuedAt': self.queued_at,
|
||||
'startedAt': self.started_at,
|
||||
'lastUpdatedAt': self.last_updated_at,
|
||||
'executionNumber': self.execution_number,
|
||||
}
|
||||
}
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
class IoTBackend(BaseBackend):
|
||||
def __init__(self, region_name=None):
|
||||
@ -760,24 +775,114 @@ class IoTBackend(BaseBackend):
|
||||
self.jobs[job_id] = job
|
||||
|
||||
for thing_arn in targets:
|
||||
thing_name = thing_arn.split(':')[-1]
|
||||
thing_name = thing_arn.split(':')[-1].split('/')[-1]
|
||||
job_execution = FakeJobExecution(job_id, thing_arn)
|
||||
self.job_executions[(job_id, thing_name)] = job_execution
|
||||
return job.job_arn, job_id, description
|
||||
|
||||
def describe_job(self, job_id):
|
||||
return self.jobs[job_id]
|
||||
jobs = [_ for _ in self.jobs.values() if _.job_id == job_id]
|
||||
if len(jobs) == 0:
|
||||
raise ResourceNotFoundException()
|
||||
return jobs[0]
|
||||
|
||||
def get_job_document(self, job_id):
|
||||
return self.jobs[job_id]
|
||||
|
||||
def list_jobs(self, status, target_selection, max_results, token, thing_group_name, thing_group_id):
|
||||
# TODO: implement filters
|
||||
all_jobs = [_.to_dict() for _ in self.jobs.values()]
|
||||
filtered_jobs = all_jobs
|
||||
|
||||
if token is None:
|
||||
jobs = filtered_jobs[0:max_results]
|
||||
next_token = str(max_results) if len(filtered_jobs) > max_results else None
|
||||
else:
|
||||
token = int(token)
|
||||
jobs = filtered_jobs[token:token + max_results]
|
||||
next_token = str(token + max_results) if len(filtered_jobs) > token + max_results else None
|
||||
|
||||
return jobs, next_token
|
||||
|
||||
def describe_job_execution(self, job_id, thing_name, execution_number):
|
||||
# TODO filter with execution number
|
||||
return self.job_executions[(job_id, thing_name)]
|
||||
try:
|
||||
job_execution = self.job_executions[(job_id, thing_name)]
|
||||
except KeyError:
|
||||
raise ResourceNotFoundException()
|
||||
|
||||
if job_execution is None or \
|
||||
(execution_number is not None and job_execution.execution_number != execution_number):
|
||||
raise ResourceNotFoundException()
|
||||
|
||||
return job_execution
|
||||
|
||||
def cancel_job_execution(self, job_id, thing_name, force, expected_version, status_details):
|
||||
job_execution = self.job_executions[(job_id, thing_name)]
|
||||
|
||||
if job_execution is None:
|
||||
raise ResourceNotFoundException()
|
||||
|
||||
job_execution.force_canceled = force if force is not None else job_execution.force_canceled
|
||||
# TODO: implement expected_version and status_details (at most 10 can be specified)
|
||||
|
||||
if job_execution.status == 'IN_PROGRESS' and force:
|
||||
job_execution.status = 'CANCELED'
|
||||
self.job_executions[(job_id, thing_name)] = job_execution
|
||||
elif job_execution.status != 'IN_PROGRESS':
|
||||
job_execution.status = 'CANCELED'
|
||||
self.job_executions[(job_id, thing_name)] = job_execution
|
||||
else:
|
||||
raise InvalidStateTransitionException()
|
||||
|
||||
def delete_job_execution(self, job_id, thing_name, execution_number, force):
|
||||
job_execution = self.job_executions[(job_id, thing_name)]
|
||||
|
||||
if job_execution.execution_number != execution_number:
|
||||
raise ResourceNotFoundException()
|
||||
|
||||
if job_execution.status == 'IN_PROGRESS' and force:
|
||||
del self.job_executions[(job_id, thing_name)]
|
||||
elif job_execution.status != 'IN_PROGRESS':
|
||||
del self.job_executions[(job_id, thing_name)]
|
||||
else:
|
||||
raise InvalidStateTransitionException()
|
||||
|
||||
def list_job_executions_for_job(self, job_id, status, max_results, next_token):
|
||||
job_executions = [self.job_executions[je] for je in self.job_executions if je[0] == job_id]
|
||||
# TODO: implement filters
|
||||
job_executions = [self.job_executions[je].to_dict() for je in self.job_executions if je[0] == job_id]
|
||||
|
||||
if status is not None:
|
||||
job_executions = list(filter(lambda elem:
|
||||
status in elem["status"] and
|
||||
elem["status"] == status, job_executions))
|
||||
|
||||
token = next_token
|
||||
if token is None:
|
||||
job_executions = job_executions[0:max_results]
|
||||
next_token = str(max_results) if len(job_executions) > max_results else None
|
||||
else:
|
||||
token = int(token)
|
||||
job_executions = job_executions[token:token + max_results]
|
||||
next_token = str(token + max_results) if len(job_executions) > token + max_results else None
|
||||
|
||||
return job_executions, next_token
|
||||
|
||||
def list_job_executions_for_thing(self, thing_name, status, max_results, next_token):
|
||||
job_executions = [self.job_executions[je].to_dict() for je in self.job_executions if je[1] == thing_name]
|
||||
|
||||
if status is not None:
|
||||
job_executions = list(filter(lambda elem:
|
||||
status in elem["status"] and
|
||||
elem["status"] == status, job_executions))
|
||||
|
||||
token = next_token
|
||||
if token is None:
|
||||
job_executions = job_executions[0:max_results]
|
||||
next_token = str(max_results) if len(job_executions) > max_results else None
|
||||
else:
|
||||
token = int(token)
|
||||
job_executions = job_executions[token:token + max_results]
|
||||
next_token = str(token + max_results) if len(job_executions) > token + max_results else None
|
||||
|
||||
return job_executions, next_token
|
||||
|
||||
|
||||
|
@ -160,15 +160,83 @@ class IoTResponse(BaseResponse):
|
||||
# TODO: needs to be implemented to get document_source's content from S3
|
||||
return json.dumps({'document': ''})
|
||||
|
||||
def list_job_executions_for_job(self):
|
||||
job_executions, next_token = self.iot_backend.list_job_executions_for_job(job_id=self._get_param("jobId"),
|
||||
status=self._get_param("status"),
|
||||
max_results=self._get_param(
|
||||
"maxResults"),
|
||||
next_token=self._get_param(
|
||||
"nextToken"))
|
||||
def list_jobs(self):
|
||||
status = self._get_param("status"),
|
||||
target_selection = self._get_param("targetSelection"),
|
||||
max_results = self._get_int_param("maxResults", 50) # not the default, but makes testing easier
|
||||
previous_next_token = self._get_param("nextToken")
|
||||
thing_group_name = self._get_param("thingGroupName"),
|
||||
thing_group_id = self._get_param("thingGroupId")
|
||||
jobs, next_token = self.iot_backend.list_jobs(status=status,
|
||||
target_selection=target_selection,
|
||||
max_results=max_results,
|
||||
token=previous_next_token,
|
||||
thing_group_name=thing_group_name,
|
||||
thing_group_id=thing_group_id)
|
||||
|
||||
return json.dumps(dict(executionSummaries=[_.to_dict() for _ in job_executions], nextToken=next_token))
|
||||
return json.dumps(dict(jobs=jobs, nextToken=next_token))
|
||||
|
||||
def describe_job_execution(self):
|
||||
job_id = self._get_param("jobId")
|
||||
thing_name = self._get_param("thingName")
|
||||
execution_number = self._get_int_param("executionNumber")
|
||||
job_execution = self.iot_backend.describe_job_execution(job_id=job_id,
|
||||
thing_name=thing_name,
|
||||
execution_number=execution_number)
|
||||
|
||||
return json.dumps(dict(execution=job_execution.to_get_dict()))
|
||||
|
||||
def cancel_job_execution(self):
|
||||
job_id = self._get_param("jobId")
|
||||
thing_name = self._get_param("thingName")
|
||||
force = self._get_bool_param("force")
|
||||
expected_version = self._get_int_param("expectedVersion")
|
||||
status_details = self._get_param("statusDetails")
|
||||
|
||||
self.iot_backend.cancel_job_execution(job_id=job_id,
|
||||
thing_name=thing_name,
|
||||
force=force,
|
||||
expected_version=expected_version,
|
||||
status_details=status_details)
|
||||
|
||||
return json.dumps(dict())
|
||||
|
||||
def delete_job_execution(self):
|
||||
job_id = self._get_param("jobId")
|
||||
thing_name = self._get_param("thingName")
|
||||
execution_number = self._get_int_param("executionNumber")
|
||||
force = self._get_bool_param("force")
|
||||
|
||||
self.iot_backend.delete_job_execution(job_id=job_id,
|
||||
thing_name=thing_name,
|
||||
execution_number=execution_number,
|
||||
force=force)
|
||||
|
||||
return json.dumps(dict())
|
||||
|
||||
def list_job_executions_for_job(self):
|
||||
job_id = self._get_param("jobId")
|
||||
status = self._get_param("status")
|
||||
max_results = self._get_int_param("maxResults", 50) # not the default, but makes testing easier
|
||||
next_token = self._get_param("nextToken")
|
||||
job_executions, next_token = self.iot_backend.list_job_executions_for_job(job_id=job_id,
|
||||
status=status,
|
||||
max_results=max_results,
|
||||
next_token=next_token)
|
||||
|
||||
return json.dumps(dict(executionSummaries=job_executions, nextToken=next_token))
|
||||
|
||||
def list_job_executions_for_thing(self):
|
||||
thing_name = self._get_param("thingName")
|
||||
status = self._get_param("status")
|
||||
max_results = self._get_int_param("maxResults", 50) # not the default, but makes testing easier
|
||||
next_token = self._get_param("nextToken")
|
||||
job_executions, next_token = self.iot_backend.list_job_executions_for_thing(thing_name=thing_name,
|
||||
status=status,
|
||||
max_results=max_results,
|
||||
next_token=next_token)
|
||||
|
||||
return json.dumps(dict(executionSummaries=job_executions, nextToken=next_token))
|
||||
|
||||
def create_keys_and_certificate(self):
|
||||
set_as_active = self._get_bool_param("setAsActive")
|
||||
|
@ -4,9 +4,9 @@ import json
|
||||
import sure #noqa
|
||||
import boto3
|
||||
|
||||
from botocore.exceptions import ClientError
|
||||
from moto import mock_iot
|
||||
|
||||
|
||||
@mock_iot
|
||||
def test_attach_policy():
|
||||
client = boto3.client('iot', region_name='ap-northeast-1')
|
||||
@ -711,6 +711,69 @@ def test_create_job():
|
||||
job.should.have.key('description')
|
||||
|
||||
|
||||
@mock_iot
|
||||
def test_list_jobs():
|
||||
client = boto3.client('iot', region_name='eu-west-1')
|
||||
name = "my-thing"
|
||||
job_id = "TestJob"
|
||||
# thing# job document
|
||||
# job_document = {
|
||||
# "field": "value"
|
||||
# }
|
||||
thing = client.create_thing(thingName=name)
|
||||
thing.should.have.key('thingName').which.should.equal(name)
|
||||
thing.should.have.key('thingArn')
|
||||
|
||||
# job document
|
||||
job_document = {
|
||||
"field": "value"
|
||||
}
|
||||
|
||||
job1 = client.create_job(
|
||||
jobId=job_id,
|
||||
targets=[thing["thingArn"]],
|
||||
document=json.dumps(job_document),
|
||||
description="Description",
|
||||
presignedUrlConfig={
|
||||
'roleArn': 'arn:aws:iam::1:role/service-role/iot_job_role',
|
||||
'expiresInSec': 123
|
||||
},
|
||||
targetSelection="CONTINUOUS",
|
||||
jobExecutionsRolloutConfig={
|
||||
'maximumPerMinute': 10
|
||||
}
|
||||
)
|
||||
|
||||
job1.should.have.key('jobId').which.should.equal(job_id)
|
||||
job1.should.have.key('jobArn')
|
||||
job1.should.have.key('description')
|
||||
|
||||
job2 = client.create_job(
|
||||
jobId=job_id+"1",
|
||||
targets=[thing["thingArn"]],
|
||||
document=json.dumps(job_document),
|
||||
description="Description",
|
||||
presignedUrlConfig={
|
||||
'roleArn': 'arn:aws:iam::1:role/service-role/iot_job_role',
|
||||
'expiresInSec': 123
|
||||
},
|
||||
targetSelection="CONTINUOUS",
|
||||
jobExecutionsRolloutConfig={
|
||||
'maximumPerMinute': 10
|
||||
}
|
||||
)
|
||||
|
||||
job2.should.have.key('jobId').which.should.equal(job_id+"1")
|
||||
job2.should.have.key('jobArn')
|
||||
job2.should.have.key('description')
|
||||
|
||||
jobs = client.list_jobs()
|
||||
jobs.should.have.key('jobs')
|
||||
jobs.should_not.have.key('nextToken')
|
||||
jobs['jobs'][0].should.have.key('jobId').which.should.equal(job_id)
|
||||
jobs['jobs'][1].should.have.key('jobId').which.should.equal(job_id+"1")
|
||||
|
||||
|
||||
@mock_iot
|
||||
def test_describe_job():
|
||||
client = boto3.client('iot', region_name='eu-west-1')
|
||||
@ -875,6 +938,162 @@ def test_get_job_document_with_document():
|
||||
job_document = client.get_job_document(jobId=job_id)
|
||||
job_document.should.have.key('document').which.should.equal("{\"field\": \"value\"}")
|
||||
|
||||
|
||||
@mock_iot
|
||||
def test_describe_job_execution():
|
||||
client = boto3.client('iot', region_name='eu-west-1')
|
||||
name = "my-thing"
|
||||
job_id = "TestJob"
|
||||
# thing
|
||||
thing = client.create_thing(thingName=name)
|
||||
thing.should.have.key('thingName').which.should.equal(name)
|
||||
thing.should.have.key('thingArn')
|
||||
|
||||
# job document
|
||||
job_document = {
|
||||
"field": "value"
|
||||
}
|
||||
|
||||
job = client.create_job(
|
||||
jobId=job_id,
|
||||
targets=[thing["thingArn"]],
|
||||
document=json.dumps(job_document),
|
||||
description="Description",
|
||||
presignedUrlConfig={
|
||||
'roleArn': 'arn:aws:iam::1:role/service-role/iot_job_role',
|
||||
'expiresInSec': 123
|
||||
},
|
||||
targetSelection="CONTINUOUS",
|
||||
jobExecutionsRolloutConfig={
|
||||
'maximumPerMinute': 10
|
||||
}
|
||||
)
|
||||
|
||||
job.should.have.key('jobId').which.should.equal(job_id)
|
||||
job.should.have.key('jobArn')
|
||||
job.should.have.key('description')
|
||||
|
||||
job_execution = client.describe_job_execution(jobId=job_id, thingName=name)
|
||||
job_execution.should.have.key('execution')
|
||||
job_execution['execution'].should.have.key('jobId').which.should.equal(job_id)
|
||||
job_execution['execution'].should.have.key('status').which.should.equal('QUEUED')
|
||||
job_execution['execution'].should.have.key('forceCanceled').which.should.equal(False)
|
||||
job_execution['execution'].should.have.key('statusDetails').which.should.equal({'detailsMap': {}})
|
||||
job_execution['execution'].should.have.key('thingArn').which.should.equal(thing["thingArn"])
|
||||
job_execution['execution'].should.have.key('queuedAt')
|
||||
job_execution['execution'].should.have.key('startedAt')
|
||||
job_execution['execution'].should.have.key('lastUpdatedAt')
|
||||
job_execution['execution'].should.have.key('executionNumber').which.should.equal(123)
|
||||
job_execution['execution'].should.have.key('versionNumber').which.should.equal(123)
|
||||
job_execution['execution'].should.have.key('approximateSecondsBeforeTimedOut').which.should.equal(123)
|
||||
|
||||
job_execution = client.describe_job_execution(jobId=job_id, thingName=name, executionNumber=123)
|
||||
job_execution.should.have.key('execution')
|
||||
job_execution['execution'].should.have.key('jobId').which.should.equal(job_id)
|
||||
job_execution['execution'].should.have.key('status').which.should.equal('QUEUED')
|
||||
job_execution['execution'].should.have.key('forceCanceled').which.should.equal(False)
|
||||
job_execution['execution'].should.have.key('statusDetails').which.should.equal({'detailsMap': {}})
|
||||
job_execution['execution'].should.have.key('thingArn').which.should.equal(thing["thingArn"])
|
||||
job_execution['execution'].should.have.key('queuedAt')
|
||||
job_execution['execution'].should.have.key('startedAt')
|
||||
job_execution['execution'].should.have.key('lastUpdatedAt')
|
||||
job_execution['execution'].should.have.key('executionNumber').which.should.equal(123)
|
||||
job_execution['execution'].should.have.key('versionNumber').which.should.equal(123)
|
||||
job_execution['execution'].should.have.key('approximateSecondsBeforeTimedOut').which.should.equal(123)
|
||||
|
||||
try:
|
||||
client.describe_job_execution(jobId=job_id, thingName=name, executionNumber=456)
|
||||
except ClientError as exc:
|
||||
error_code = exc.response['Error']['Code']
|
||||
error_code.should.equal('ResourceNotFoundException')
|
||||
else:
|
||||
raise Exception("Should have raised error")
|
||||
|
||||
|
||||
@mock_iot
|
||||
def test_cancel_job_execution():
|
||||
client = boto3.client('iot', region_name='eu-west-1')
|
||||
name = "my-thing"
|
||||
job_id = "TestJob"
|
||||
# thing
|
||||
thing = client.create_thing(thingName=name)
|
||||
thing.should.have.key('thingName').which.should.equal(name)
|
||||
thing.should.have.key('thingArn')
|
||||
|
||||
# job document
|
||||
job_document = {
|
||||
"field": "value"
|
||||
}
|
||||
|
||||
job = client.create_job(
|
||||
jobId=job_id,
|
||||
targets=[thing["thingArn"]],
|
||||
document=json.dumps(job_document),
|
||||
description="Description",
|
||||
presignedUrlConfig={
|
||||
'roleArn': 'arn:aws:iam::1:role/service-role/iot_job_role',
|
||||
'expiresInSec': 123
|
||||
},
|
||||
targetSelection="CONTINUOUS",
|
||||
jobExecutionsRolloutConfig={
|
||||
'maximumPerMinute': 10
|
||||
}
|
||||
)
|
||||
|
||||
job.should.have.key('jobId').which.should.equal(job_id)
|
||||
job.should.have.key('jobArn')
|
||||
job.should.have.key('description')
|
||||
|
||||
client.cancel_job_execution(jobId=job_id, thingName=name)
|
||||
job_execution = client.describe_job_execution(jobId=job_id, thingName=name)
|
||||
job_execution.should.have.key('execution')
|
||||
job_execution['execution'].should.have.key('status').which.should.equal('CANCELED')
|
||||
|
||||
|
||||
@mock_iot
|
||||
def test_delete_job_execution():
|
||||
client = boto3.client('iot', region_name='eu-west-1')
|
||||
name = "my-thing"
|
||||
job_id = "TestJob"
|
||||
# thing
|
||||
thing = client.create_thing(thingName=name)
|
||||
thing.should.have.key('thingName').which.should.equal(name)
|
||||
thing.should.have.key('thingArn')
|
||||
|
||||
# job document
|
||||
job_document = {
|
||||
"field": "value"
|
||||
}
|
||||
|
||||
job = client.create_job(
|
||||
jobId=job_id,
|
||||
targets=[thing["thingArn"]],
|
||||
document=json.dumps(job_document),
|
||||
description="Description",
|
||||
presignedUrlConfig={
|
||||
'roleArn': 'arn:aws:iam::1:role/service-role/iot_job_role',
|
||||
'expiresInSec': 123
|
||||
},
|
||||
targetSelection="CONTINUOUS",
|
||||
jobExecutionsRolloutConfig={
|
||||
'maximumPerMinute': 10
|
||||
}
|
||||
)
|
||||
|
||||
job.should.have.key('jobId').which.should.equal(job_id)
|
||||
job.should.have.key('jobArn')
|
||||
job.should.have.key('description')
|
||||
|
||||
client.delete_job_execution(jobId=job_id, thingName=name, executionNumber=123)
|
||||
try:
|
||||
client.describe_job_execution(jobId=job_id, thingName=name, executionNumber=123)
|
||||
except ClientError as exc:
|
||||
error_code = exc.response['Error']['Code']
|
||||
error_code.should.equal('ResourceNotFoundException')
|
||||
else:
|
||||
raise Exception("Should have raised error")
|
||||
|
||||
|
||||
@mock_iot
|
||||
def test_list_job_executions_for_job():
|
||||
client = boto3.client('iot', region_name='eu-west-1')
|
||||
@ -911,5 +1130,44 @@ def test_list_job_executions_for_job():
|
||||
|
||||
job_execution = client.list_job_executions_for_job(jobId=job_id)
|
||||
job_execution.should.have.key('executionSummaries')
|
||||
job_execution['executionSummaries'][0].should.have.key('thingArn').which.should.equal(thing["thingArn"])
|
||||
|
||||
|
||||
@mock_iot
|
||||
def test_list_job_executions_for_thing():
|
||||
client = boto3.client('iot', region_name='eu-west-1')
|
||||
name = "my-thing"
|
||||
job_id = "TestJob"
|
||||
# thing
|
||||
thing = client.create_thing(thingName=name)
|
||||
thing.should.have.key('thingName').which.should.equal(name)
|
||||
thing.should.have.key('thingArn')
|
||||
|
||||
# job document
|
||||
job_document = {
|
||||
"field": "value"
|
||||
}
|
||||
|
||||
job = client.create_job(
|
||||
jobId=job_id,
|
||||
targets=[thing["thingArn"]],
|
||||
document=json.dumps(job_document),
|
||||
description="Description",
|
||||
presignedUrlConfig={
|
||||
'roleArn': 'arn:aws:iam::1:role/service-role/iot_job_role',
|
||||
'expiresInSec': 123
|
||||
},
|
||||
targetSelection="CONTINUOUS",
|
||||
jobExecutionsRolloutConfig={
|
||||
'maximumPerMinute': 10
|
||||
}
|
||||
)
|
||||
|
||||
job.should.have.key('jobId').which.should.equal(job_id)
|
||||
job.should.have.key('jobArn')
|
||||
job.should.have.key('description')
|
||||
|
||||
job_execution = client.list_job_executions_for_thing(thingName=name)
|
||||
job_execution.should.have.key('executionSummaries')
|
||||
job_execution['executionSummaries'][0].should.have.key('jobId').which.should.equal(job_id)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user