list_thing_types and list_things now uses pagination
This commit is contained in:
parent
56ff66394d
commit
db3593575f
@ -1,14 +1,17 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import time
|
|
||||||
import boto3
|
|
||||||
import string
|
|
||||||
import random
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import uuid
|
import random
|
||||||
import re
|
import re
|
||||||
from datetime import datetime
|
import string
|
||||||
from moto.core import BaseBackend, BaseModel
|
import time
|
||||||
|
import uuid
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
from moto.core import BaseBackend, BaseModel
|
||||||
from .exceptions import (
|
from .exceptions import (
|
||||||
ResourceNotFoundException,
|
ResourceNotFoundException,
|
||||||
InvalidRequestException,
|
InvalidRequestException,
|
||||||
@ -271,15 +274,36 @@ class IoTBackend(BaseBackend):
|
|||||||
|
|
||||||
def list_thing_types(self, thing_type_name=None):
|
def list_thing_types(self, thing_type_name=None):
|
||||||
if thing_type_name:
|
if thing_type_name:
|
||||||
# It's wierd but thing_type_name is filterd by forward match, not complete match
|
# It's weird but thing_type_name is filtered by forward match, not complete match
|
||||||
return [_ for _ in self.thing_types.values() if _.thing_type_name.startswith(thing_type_name)]
|
return [_ for _ in self.thing_types.values() if _.thing_type_name.startswith(thing_type_name)]
|
||||||
thing_types = self.thing_types.values()
|
return self.thing_types.values()
|
||||||
return thing_types
|
|
||||||
|
|
||||||
def list_things(self, attribute_name, attribute_value, thing_type_name):
|
def list_things(self, attribute_name, attribute_value, thing_type_name, max_results, token):
|
||||||
# TODO: filter by attributess or thing_type
|
all_things = [_.to_dict() for _ in self.things.values()]
|
||||||
things = self.things.values()
|
if attribute_name is not None and thing_type_name is not None:
|
||||||
return things
|
filtered_things = list(
|
||||||
|
filter(
|
||||||
|
lambda elem: attribute_name in elem["attributes"] and elem["attributes"][
|
||||||
|
attribute_name] == attribute_value and "thingTypeName" in elem and elem[
|
||||||
|
"thingTypeName"] == thing_type_name, all_things))
|
||||||
|
elif attribute_name is not None and thing_type_name is None:
|
||||||
|
filtered_things = list(filter(lambda elem: attribute_name in elem["attributes"] and elem["attributes"][
|
||||||
|
attribute_name] == attribute_value, all_things))
|
||||||
|
elif attribute_name is None and thing_type_name is not None:
|
||||||
|
filtered_things = list(
|
||||||
|
filter(lambda elem: "thingTypeName" in elem and elem["thingTypeName"] == thing_type_name, all_things))
|
||||||
|
else:
|
||||||
|
filtered_things = all_things
|
||||||
|
|
||||||
|
if token is None:
|
||||||
|
things = filtered_things[0:max_results]
|
||||||
|
next_token = str(max_results) if len(filtered_things) > max_results else None
|
||||||
|
else:
|
||||||
|
token = int(token)
|
||||||
|
things = filtered_things[token:token + max_results]
|
||||||
|
next_token = str(token + max_results) if len(filtered_things) > token + max_results else None
|
||||||
|
|
||||||
|
return things, next_token
|
||||||
|
|
||||||
def describe_thing(self, thing_name):
|
def describe_thing(self, thing_name):
|
||||||
things = [_ for _ in self.things.values() if _.thing_name == thing_name]
|
things = [_ for _ in self.things.values() if _.thing_name == thing_name]
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
from moto.core.responses import BaseResponse
|
from moto.core.responses import BaseResponse
|
||||||
from .models import iot_backends
|
from .models import iot_backends
|
||||||
import json
|
|
||||||
|
|
||||||
|
|
||||||
class IoTResponse(BaseResponse):
|
class IoTResponse(BaseResponse):
|
||||||
@ -32,30 +34,39 @@ class IoTResponse(BaseResponse):
|
|||||||
return json.dumps(dict(thingTypeName=thing_type_name, thingTypeArn=thing_type_arn))
|
return json.dumps(dict(thingTypeName=thing_type_name, thingTypeArn=thing_type_arn))
|
||||||
|
|
||||||
def list_thing_types(self):
|
def list_thing_types(self):
|
||||||
# previous_next_token = self._get_param("nextToken")
|
previous_next_token = self._get_param("nextToken")
|
||||||
# max_results = self._get_int_param("maxResults")
|
max_results = self._get_int_param("maxResults", 50) # not the default, but makes testing easier
|
||||||
thing_type_name = self._get_param("thingTypeName")
|
thing_type_name = self._get_param("thingTypeName")
|
||||||
thing_types = self.iot_backend.list_thing_types(
|
thing_types = self.iot_backend.list_thing_types(
|
||||||
thing_type_name=thing_type_name
|
thing_type_name=thing_type_name
|
||||||
)
|
)
|
||||||
# TODO: implement pagination in the future
|
|
||||||
next_token = None
|
thing_types = [_.to_dict() for _ in thing_types]
|
||||||
return json.dumps(dict(thingTypes=[_.to_dict() for _ in thing_types], nextToken=next_token))
|
if previous_next_token is None:
|
||||||
|
result = thing_types[0:max_results]
|
||||||
|
next_token = str(max_results) if len(thing_types) > max_results else None
|
||||||
|
else:
|
||||||
|
token = int(previous_next_token)
|
||||||
|
result = thing_types[token:token + max_results]
|
||||||
|
next_token = str(token + max_results) if len(thing_types) > token + max_results else None
|
||||||
|
|
||||||
|
return json.dumps(dict(thingTypes=result, nextToken=next_token))
|
||||||
|
|
||||||
def list_things(self):
|
def list_things(self):
|
||||||
# previous_next_token = self._get_param("nextToken")
|
previous_next_token = self._get_param("nextToken")
|
||||||
# max_results = self._get_int_param("maxResults")
|
max_results = self._get_int_param("maxResults", 50) # not the default, but makes testing easier
|
||||||
attribute_name = self._get_param("attributeName")
|
attribute_name = self._get_param("attributeName")
|
||||||
attribute_value = self._get_param("attributeValue")
|
attribute_value = self._get_param("attributeValue")
|
||||||
thing_type_name = self._get_param("thingTypeName")
|
thing_type_name = self._get_param("thingTypeName")
|
||||||
things = self.iot_backend.list_things(
|
things, next_token = self.iot_backend.list_things(
|
||||||
attribute_name=attribute_name,
|
attribute_name=attribute_name,
|
||||||
attribute_value=attribute_value,
|
attribute_value=attribute_value,
|
||||||
thing_type_name=thing_type_name,
|
thing_type_name=thing_type_name,
|
||||||
|
max_results=max_results,
|
||||||
|
token=previous_next_token
|
||||||
)
|
)
|
||||||
# TODO: implement pagination in the future
|
|
||||||
next_token = None
|
return json.dumps(dict(things=things, nextToken=next_token))
|
||||||
return json.dumps(dict(things=[_.to_dict() for _ in things], nextToken=next_token))
|
|
||||||
|
|
||||||
def describe_thing(self):
|
def describe_thing(self):
|
||||||
thing_name = self._get_param("thingName")
|
thing_name = self._get_param("thingName")
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import boto3
|
|
||||||
import sure # noqa
|
|
||||||
import json
|
import json
|
||||||
|
import sure # noqa
|
||||||
|
import boto3
|
||||||
|
|
||||||
from moto import mock_iot
|
from moto import mock_iot
|
||||||
|
|
||||||
|
|
||||||
@ -63,6 +64,143 @@ def test_things():
|
|||||||
res.should.have.key('thingTypes').which.should.have.length_of(0)
|
res.should.have.key('thingTypes').which.should.have.length_of(0)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_iot
|
||||||
|
def test_list_thing_types():
|
||||||
|
client = boto3.client('iot', region_name='ap-northeast-1')
|
||||||
|
|
||||||
|
for i in range(0, 100):
|
||||||
|
client.create_thing_type(thingTypeName=str(i + 1))
|
||||||
|
|
||||||
|
thing_types = client.list_thing_types()
|
||||||
|
thing_types.should.have.key('nextToken')
|
||||||
|
thing_types.should.have.key('thingTypes').which.should.have.length_of(50)
|
||||||
|
thing_types['thingTypes'][0]['thingTypeName'].should.equal('1')
|
||||||
|
thing_types['thingTypes'][-1]['thingTypeName'].should.equal('50')
|
||||||
|
|
||||||
|
thing_types = client.list_thing_types(nextToken=thing_types['nextToken'])
|
||||||
|
thing_types.should.have.key('thingTypes').which.should.have.length_of(50)
|
||||||
|
thing_types.should_not.have.key('nextToken')
|
||||||
|
thing_types['thingTypes'][0]['thingTypeName'].should.equal('51')
|
||||||
|
thing_types['thingTypes'][-1]['thingTypeName'].should.equal('100')
|
||||||
|
# TODO test list_thing_types with filters
|
||||||
|
|
||||||
|
|
||||||
|
@mock_iot
|
||||||
|
def test_list_things_with_next_token():
|
||||||
|
client = boto3.client('iot', region_name='ap-northeast-1')
|
||||||
|
|
||||||
|
for i in range(0, 200):
|
||||||
|
client.create_thing(thingName=str(i + 1))
|
||||||
|
|
||||||
|
things = client.list_things()
|
||||||
|
things.should.have.key('nextToken')
|
||||||
|
things.should.have.key('things').which.should.have.length_of(50)
|
||||||
|
things['things'][0]['thingName'].should.equal('1')
|
||||||
|
things['things'][0]['thingArn'].should.equal('arn:aws:iot:ap-northeast-1:1:thing/1')
|
||||||
|
things['things'][-1]['thingName'].should.equal('50')
|
||||||
|
things['things'][-1]['thingArn'].should.equal('arn:aws:iot:ap-northeast-1:1:thing/50')
|
||||||
|
|
||||||
|
things = client.list_things(nextToken=things['nextToken'])
|
||||||
|
things.should.have.key('nextToken')
|
||||||
|
things.should.have.key('things').which.should.have.length_of(50)
|
||||||
|
things['things'][0]['thingName'].should.equal('51')
|
||||||
|
things['things'][0]['thingArn'].should.equal('arn:aws:iot:ap-northeast-1:1:thing/51')
|
||||||
|
things['things'][-1]['thingName'].should.equal('100')
|
||||||
|
things['things'][-1]['thingArn'].should.equal('arn:aws:iot:ap-northeast-1:1:thing/100')
|
||||||
|
|
||||||
|
things = client.list_things(nextToken=things['nextToken'])
|
||||||
|
things.should.have.key('nextToken')
|
||||||
|
things.should.have.key('things').which.should.have.length_of(50)
|
||||||
|
things['things'][0]['thingName'].should.equal('101')
|
||||||
|
things['things'][0]['thingArn'].should.equal('arn:aws:iot:ap-northeast-1:1:thing/101')
|
||||||
|
things['things'][-1]['thingName'].should.equal('150')
|
||||||
|
things['things'][-1]['thingArn'].should.equal('arn:aws:iot:ap-northeast-1:1:thing/150')
|
||||||
|
|
||||||
|
things = client.list_things(nextToken=things['nextToken'])
|
||||||
|
things.should_not.have.key('nextToken')
|
||||||
|
things.should.have.key('things').which.should.have.length_of(50)
|
||||||
|
things['things'][0]['thingName'].should.equal('151')
|
||||||
|
things['things'][0]['thingArn'].should.equal('arn:aws:iot:ap-northeast-1:1:thing/151')
|
||||||
|
things['things'][-1]['thingName'].should.equal('200')
|
||||||
|
things['things'][-1]['thingArn'].should.equal('arn:aws:iot:ap-northeast-1:1:thing/200')
|
||||||
|
|
||||||
|
|
||||||
|
@mock_iot
|
||||||
|
def test_list_things_with_attribute_and_thing_type_filter_and_next_token():
|
||||||
|
client = boto3.client('iot', region_name='ap-northeast-1')
|
||||||
|
client.create_thing_type(thingTypeName='my-thing-type')
|
||||||
|
|
||||||
|
for i in range(0, 200):
|
||||||
|
if not (i + 1) % 3:
|
||||||
|
attribute_payload = {
|
||||||
|
'attributes': {
|
||||||
|
'foo': 'bar'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elif not (i + 1) % 5:
|
||||||
|
attribute_payload = {
|
||||||
|
'attributes': {
|
||||||
|
'bar': 'foo'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
attribute_payload = {}
|
||||||
|
|
||||||
|
if not (i + 1) % 2:
|
||||||
|
thing_type_name = 'my-thing-type'
|
||||||
|
client.create_thing(thingName=str(i + 1), thingTypeName=thing_type_name, attributePayload=attribute_payload)
|
||||||
|
else:
|
||||||
|
client.create_thing(thingName=str(i + 1), attributePayload=attribute_payload)
|
||||||
|
|
||||||
|
# Test filter for thingTypeName
|
||||||
|
things = client.list_things(thingTypeName=thing_type_name)
|
||||||
|
things.should.have.key('nextToken')
|
||||||
|
things.should.have.key('things').which.should.have.length_of(50)
|
||||||
|
things['things'][0]['thingName'].should.equal('2')
|
||||||
|
things['things'][0]['thingArn'].should.equal('arn:aws:iot:ap-northeast-1:1:thing/2')
|
||||||
|
things['things'][-1]['thingName'].should.equal('100')
|
||||||
|
things['things'][-1]['thingArn'].should.equal('arn:aws:iot:ap-northeast-1:1:thing/100')
|
||||||
|
all(item['thingTypeName'] == thing_type_name for item in things['things'])
|
||||||
|
|
||||||
|
things = client.list_things(nextToken=things['nextToken'], thingTypeName=thing_type_name)
|
||||||
|
things.should_not.have.key('nextToken')
|
||||||
|
things.should.have.key('things').which.should.have.length_of(50)
|
||||||
|
things['things'][0]['thingName'].should.equal('102')
|
||||||
|
things['things'][0]['thingArn'].should.equal('arn:aws:iot:ap-northeast-1:1:thing/102')
|
||||||
|
things['things'][-1]['thingName'].should.equal('200')
|
||||||
|
things['things'][-1]['thingArn'].should.equal('arn:aws:iot:ap-northeast-1:1:thing/200')
|
||||||
|
all(item['thingTypeName'] == thing_type_name for item in things['things'])
|
||||||
|
|
||||||
|
# Test filter for attributes
|
||||||
|
things = client.list_things(attributeName='foo', attributeValue='bar')
|
||||||
|
things.should.have.key('nextToken')
|
||||||
|
things.should.have.key('things').which.should.have.length_of(50)
|
||||||
|
things['things'][0]['thingName'].should.equal('3')
|
||||||
|
things['things'][0]['thingArn'].should.equal('arn:aws:iot:ap-northeast-1:1:thing/3')
|
||||||
|
things['things'][-1]['thingName'].should.equal('150')
|
||||||
|
things['things'][-1]['thingArn'].should.equal('arn:aws:iot:ap-northeast-1:1:thing/150')
|
||||||
|
all(item['attributes'] == {'foo': 'bar'} for item in things['things'])
|
||||||
|
|
||||||
|
things = client.list_things(nextToken=things['nextToken'], attributeName='foo', attributeValue='bar')
|
||||||
|
things.should_not.have.key('nextToken')
|
||||||
|
things.should.have.key('things').which.should.have.length_of(16)
|
||||||
|
things['things'][0]['thingName'].should.equal('153')
|
||||||
|
things['things'][0]['thingArn'].should.equal('arn:aws:iot:ap-northeast-1:1:thing/153')
|
||||||
|
things['things'][-1]['thingName'].should.equal('198')
|
||||||
|
things['things'][-1]['thingArn'].should.equal('arn:aws:iot:ap-northeast-1:1:thing/198')
|
||||||
|
all(item['attributes'] == {'foo': 'bar'} for item in things['things'])
|
||||||
|
|
||||||
|
# Test filter for attributes and thingTypeName
|
||||||
|
things = client.list_things(thingTypeName=thing_type_name, attributeName='foo', attributeValue='bar')
|
||||||
|
things.should_not.have.key('nextToken')
|
||||||
|
things.should.have.key('things').which.should.have.length_of(33)
|
||||||
|
things['things'][0]['thingName'].should.equal('6')
|
||||||
|
things['things'][0]['thingArn'].should.equal('arn:aws:iot:ap-northeast-1:1:thing/6')
|
||||||
|
things['things'][-1]['thingName'].should.equal('198')
|
||||||
|
things['things'][-1]['thingArn'].should.equal('arn:aws:iot:ap-northeast-1:1:thing/198')
|
||||||
|
all(item['attributes'] == {'foo': 'bar'} and item['thingTypeName'] == thing_type_name for item in things['things'])
|
||||||
|
|
||||||
|
|
||||||
@mock_iot
|
@mock_iot
|
||||||
def test_certs():
|
def test_certs():
|
||||||
client = boto3.client('iot', region_name='ap-northeast-1')
|
client = boto3.client('iot', region_name='ap-northeast-1')
|
||||||
@ -204,7 +342,6 @@ def test_principal_thing():
|
|||||||
@mock_iot
|
@mock_iot
|
||||||
def test_thing_groups():
|
def test_thing_groups():
|
||||||
client = boto3.client('iot', region_name='ap-northeast-1')
|
client = boto3.client('iot', region_name='ap-northeast-1')
|
||||||
name = 'my-thing'
|
|
||||||
group_name = 'my-group-name'
|
group_name = 'my-group-name'
|
||||||
|
|
||||||
# thing group
|
# thing group
|
||||||
@ -424,6 +561,7 @@ def test_create_job():
|
|||||||
job.should.have.key('jobArn')
|
job.should.have.key('jobArn')
|
||||||
job.should.have.key('description')
|
job.should.have.key('description')
|
||||||
|
|
||||||
|
|
||||||
@mock_iot
|
@mock_iot
|
||||||
def test_describe_job():
|
def test_describe_job():
|
||||||
client = boto3.client('iot', region_name='eu-west-1')
|
client = boto3.client('iot', region_name='eu-west-1')
|
||||||
|
Loading…
Reference in New Issue
Block a user