Skip to content

Commit b87066d

Browse files
committed
test adjustments and refactor thing creation routine
1 parent dd41cd9 commit b87066d

File tree

7 files changed

+158
-45
lines changed

7 files changed

+158
-45
lines changed

src/bulk_importer/main.py

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -57,35 +57,43 @@ def process_policy(policy_name, certificate_id):
5757

5858
def process_thing(thing_name, certificate_id, thing_type_name=None):
5959
"""Creates the IoT Thing if it does not already exist"""
60+
logger.info("Processing thing %s.", thing_name)
6061
iot_client = boto3client('iot')
6162
certificate_arn = get_certificate_arn(certificate_id)
6263
try:
6364
iot_client.describe_thing(thingName=thing_name)
64-
return None
65-
except ClientError as error:
66-
error_code = error.response['Error']['Code'] # pylint: disable=unused-variable
67-
logger.info("Thing not found {error_code}. Creating.")
68-
69-
# Create thing
70-
try:
71-
if thing_type_name is None:
65+
return True
66+
except ClientError as err_describe:
67+
error_code = err_describe.response['Error']['Code']
68+
logger.info("Thing not found: %s. Creating.", error_code)
69+
try:
7270
iot_client.create_thing(thingName=thing_name)
73-
else:
74-
iot_client.create_thing(thingName=thing_name,
75-
thingTypeName=thing_type_name)
76-
77-
except ClientError as error:
78-
error_code = error.response['Error']['Code']
79-
logger.error("ERROR Thing creation failed: {error_code}")
80-
return None
71+
except ClientError as err_create:
72+
error_code = err_create.response['Error']['Code']
73+
error_message = err_create.response['Error']['Message']
74+
logger.error("ERROR Thing creation failed: %s: %s", error_code, error_message)
75+
return False
8176

8277
try:
8378
iot_client.attach_thing_principal(thingName=thing_name,
8479
principal=certificate_arn)
8580
except ClientError as error:
86-
print("ERROR Certificate attachment failed.")
87-
print(error)
88-
return None
81+
error_code = error.response['Error']['Code']
82+
error_message = error.response['Error']['Message']
83+
logger.error("Certificate attachment failed: %s: %s", error_code, error_message)
84+
85+
if thing_type_name is not None:
86+
try:
87+
logger.info("Upating thing %s to apply thing type %s.", thing_name, thing_type_name)
88+
iot_client.update_thing(thingName=thing_name,
89+
thingTypeName=thing_type_name,
90+
removeThingType=False)
91+
except ClientError as error:
92+
error_code = error.response['Error']['Code']
93+
error_message = error.response['Error']['Message']
94+
logger.error("Thing type not found: %s: %s.", error_code, error_message)
95+
return False
96+
return True
8997

9098
def requeue(config):
9199
"""
@@ -151,8 +159,8 @@ def process_sqs(config):
151159
certificate_id = process_certificate(config, requeue)
152160
process_thing(config.get('thing'),
153161
certificate_id,
154-
config.get('thing_type_arn'))
155-
process_policy(config.get('policy_arn'),
162+
config.get('thing_type_name'))
163+
process_policy(config.get('policy_name'),
156164
certificate_id)
157165
process_thing_group(config.get('thing_group_arn'),
158166
config.get('thing'))

src/product_provider/main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ def lambda_handler(event: S3Event,
6767
return None
6868

6969
config = {
70-
'policy_arn': os.environ.get('POLICY_NAME'),
70+
'policy_name': os.environ.get('POLICY_NAME'),
7171
'thing_group_arn': v_thing_group,
72-
'thing_type_arn': v_thing_type,
72+
'thing_type_name': os.environ.get('THING_TYPE_NAME'),
7373
'bucket': s3_event.bucket_name
7474
}
7575

src/provider_infineon/provider_infineon/main.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import os
99
import json
1010
import logging
11+
from botocore.exceptions import ClientError
1112
from aws_lambda_powertools.utilities.typing import LambdaContext
1213
from aws_lambda_powertools.utilities.data_classes import SQSEvent
1314
from aws_utils import verify_queue
@@ -20,17 +21,21 @@ def lambda_handler(event: dict, context: LambdaContext) -> dict: # pylint: disab
2021
"""Lambda function main entry point"""
2122
sqs_event = SQSEvent(event)
2223
queue_url = os.environ['QUEUE_TARGET']
23-
if not verify_queue(queue_url=queue_url):
24-
logger.error("Queue {queue_url} is not available. ")
25-
return None
26-
2724
cert_type = os.environ['CERT_TYPE']
28-
if not verify_certtype(cert_type):
29-
logger.error("Certificate type not valid. Must be E0E0, E0E1, or E0E2.")
30-
return None
3125

26+
try:
27+
verify_queue(queue_url=queue_url)
28+
except ClientError as error:
29+
error_code = error.response['Error']['Code']
30+
error_message = error.response['Error']['Message']
31+
logger.error("Queue %s is not available. %s: %s", queue_url, error_code, error_message)
32+
return None
3233

33-
queue_url = os.environ['QUEUE_TARGET']
34+
try:
35+
verify_certtype(cert_type)
36+
except ValueError as error:
37+
logger.error("Certificate type %s did not verify: %s", queue_url, str(error))
38+
return None
3439

3540
for record in sqs_event.records:
3641
config = json.loads(record["body"])

src/provider_infineon/provider_infineon/manifest_handler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def verify_certtype(option: str) -> bool:
1818
case "E0E2":
1919
return True
2020
case _:
21-
return False
21+
raise ValueError("Bad cert type code.")
2222

2323
def verify_certificate_set(files: list[py7zr.FileInfo], option: str) -> str:
2424
"""Ensure that the bundlke exists in the payload"""

test/unit/src/model_product_provider.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class LambdaSQSClass:
1212
"""
1313
AWS SQS Resource Class
1414
"""
15-
def __init__(self, lambda_sqs_resource):
15+
def __init__(self, lambda_sqs_resource):
1616
"""
1717
Initialize an SQS Resource
1818
"""
@@ -24,7 +24,7 @@ class LambdaS3Class:
2424
"""
2525
AWS S3 Resource Class
2626
"""
27-
def __init__(self, lambda_s3_resource):
27+
def __init__(self, lambda_s3_resource):
2828
"""
2929
Initialize an S3 Resource
3030
"""

test/unit/src/test_bulk_importer.py

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ def setUp(self):
5555
"queue_name" : self.test_sqs_queue_name }
5656
self.mocked_sqs_class = LambdaSQSClass(mocked_sqs_resource)
5757

58+
iot_client = client('iot')
59+
self.thing_group_arn_solo = (iot_client.create_thing_group(thingGroupName="Thing Group Solo"))['thingGroupArn']
60+
self.thing_group_arn_parent = (iot_client.create_thing_group(thingGroupName="Thing Group Parent"))['thingGroupArn']
61+
self.thing_group_arn_child = (iot_client.create_thing_group(thingGroupName="Thing Group Child", parentGroupName="Thing Group Parent"))['thingGroupArn']
62+
self.thing_type_name = "Thingpress Thing Type"
63+
self.thing_type_arn = (iot_client.create_thing_type(thingTypeName=self.thing_type_name))['thingTypeArn']
64+
5865
def test_pos_process_certificate(self):
5966
"""Positive test case for processing certificate"""
6067
with open('./test/artifacts/single.pem', 'rb') as data:
@@ -113,7 +120,53 @@ def test_pos_process_thing(self):
113120
cr = process_certificate(c, requeue)
114121
n = "process_thing"
115122
iot_client.create_thing(thingName=n)
116-
process_thing(n, cr)
123+
x = process_thing(n, cr)
124+
assert x is True
125+
126+
def test_pos_process_thing_with_type(self):
127+
"""Positive test case for attaching policy to certificate"""
128+
iot_client = client('iot')
129+
with open('./test/artifacts/single.pem', 'rb') as data:
130+
pem_obj = x509.load_pem_x509_certificate(data.read(),
131+
backend=default_backend())
132+
block = pem_obj.public_bytes(encoding=serialization.Encoding.PEM).decode('ascii')
133+
cert = str(base64.b64encode(block.encode('ascii')))
134+
c = {'certificate': cert}
135+
cr = process_certificate(c, requeue)
136+
n = "process_thing"
137+
iot_client.create_thing(thingName=n)
138+
x = process_thing(n, cr, self.thing_type_name)
139+
assert x is True
140+
141+
def test_pos_process_thing_no_prev_thing(self):
142+
"""Positive test case for attaching policy to certificate"""
143+
with open('./test/artifacts/single.pem', 'rb') as data:
144+
pem_obj = x509.load_pem_x509_certificate(data.read(),
145+
backend=default_backend())
146+
block = pem_obj.public_bytes(encoding=serialization.Encoding.PEM).decode('ascii')
147+
cert = str(base64.b64encode(block.encode('ascii')))
148+
c = {'certificate': cert}
149+
cr = process_certificate(c, requeue)
150+
n = "process_thing"
151+
x = process_thing(n, cr)
152+
assert x is True
153+
154+
def test_pos_process_thing_with_type_no_prev_thing(self):
155+
"""Positive test case for attaching policy to certificate"""
156+
iot_client = client('iot')
157+
ttn = "ThingpressThingType2"
158+
tta = (iot_client.create_thing_type(thingTypeName=ttn))['thingTypeArn']
159+
160+
with open('./test/artifacts/single.pem', 'rb') as data:
161+
pem_obj = x509.load_pem_x509_certificate(data.read(),
162+
backend=default_backend())
163+
block = pem_obj.public_bytes(encoding=serialization.Encoding.PEM).decode('ascii')
164+
cert = str(base64.b64encode(block.encode('ascii')))
165+
c = {'certificate': cert}
166+
cr = process_certificate(c, requeue)
167+
n = "process_thing"
168+
x = process_thing(n, cr, ttn)
169+
assert x is True
117170

118171
def test_pos_requeue(self):
119172
pass

test/unit/src/test_provider_infineon.py

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#from moto import mock_aws, settings
2020
#from unittest.mock import MagicMock, patch
2121
from py7zr import FileInfo
22-
22+
from pytest import raises
2323
from src.layer_utils.aws_utils import s3_object_bytes
2424
from src.provider_infineon.provider_infineon.main import lambda_handler
2525
from src.provider_infineon.provider_infineon.manifest_handler import verify_certtype, select_certificate_set, verify_certificate_set, send_certificates
@@ -75,7 +75,8 @@ def test_verify_certtype(self):
7575
assert verify_certtype("E0E0") is True
7676
assert verify_certtype("E0E1") is True
7777
assert verify_certtype("E0E2") is True
78-
assert verify_certtype("XXXX") is False
78+
with raises(ValueError) as exc:
79+
verify_certtype("XXXX")
7980

8081

8182
def test_verify_certificate_set(self):
@@ -91,11 +92,17 @@ def test_verify_certificate_set(self):
9192
assert verify_certificate_set(l1, v2) == "xxx_E0E1_Certs.7z"
9293
assert verify_certificate_set(l1, v3) == "xxx_E0E2_Certs.7z"
9394
assert verify_certificate_set(l2, v1) == "xxx_E0E0_Certs.7z"
94-
assert verify_certificate_set(l2, v4) is None
95-
assert verify_certificate_set(l2, v5) is None
95+
with raises(ValueError) as exc:
96+
verify_certificate_set(l2, v4)
97+
with raises(ValueError) as exc:
98+
verify_certificate_set(l2, v5)
99+
with raises(ValueError) as exc:
100+
verify_certificate_set(l2, v4)
96101
assert verify_certificate_set(l3, v1) is None
97-
assert verify_certificate_set(l3, v4) is None
98-
assert verify_certificate_set(l3, v5) is None
102+
with raises(ValueError) as exc:
103+
verify_certificate_set(l3, v4)
104+
with raises(ValueError) as exc:
105+
verify_certificate_set(l3, v5)
99106

100107
def test_select_certificate_bundle(self):
101108
""" Test file selection of single bundle """
@@ -106,10 +113,9 @@ def test_select_certificate_bundle(self):
106113
@pytest.mark.xfail(raises=FileNotFoundError)
107114
def test_select_certificate_bundle_bad_bundle_name(self):
108115
""" Test file selection of single bundle """
109-
select_certificate_set(io.BytesIO(self.test_s3_object_content.read()),
110-
"E0E5")
111-
#err = exc.value.errno
112-
#assert err == 'FileNotFoundError'
116+
with raises(ValueError) as exc:
117+
select_certificate_set(io.BytesIO(self.test_s3_object_content.read()),
118+
"E0E5")
113119

114120
def test_invoke_export(self):
115121
o = s3_object_bytes(self.test_s3_bucket_name, self.artifact, False)
@@ -142,6 +148,47 @@ def test_pos_lambda_handler_1(self):
142148
os.environ['CERT_TYPE']=""
143149
assert v == e
144150

151+
152+
def test_pos_lambda_handler_2(self):
153+
"""Invoke the main handler with one file"""
154+
r1 = {
155+
'policy_arn': 'dev_policy',
156+
'bucket': self.test_s3_bucket_name,
157+
'key': self.artifact
158+
}
159+
160+
e = { "Records": [{
161+
'eventSource': 'aws:sqs',
162+
'body': json.dumps(r1)
163+
}]
164+
}
165+
os.environ['CERT_TYPE']="E0E0"
166+
c = None
167+
v = lambda_handler(e, c)
168+
os.environ['QUEUE_TARGET']=""
169+
os.environ['CERT_TYPE']=""
170+
assert v is None
171+
172+
def test_pos_lambda_handler_3(self):
173+
"""Invoke the main handler with one file"""
174+
r1 = {
175+
'policy_arn': 'dev_policy',
176+
'bucket': self.test_s3_bucket_name,
177+
'key': self.artifact
178+
}
179+
180+
e = { "Records": [{
181+
'eventSource': 'aws:sqs',
182+
'body': json.dumps(r1)
183+
}]
184+
}
185+
os.environ['QUEUE_TARGET']=self.test_sqs_queue_name
186+
c = None
187+
v = lambda_handler(e, c)
188+
os.environ['QUEUE_TARGET']=""
189+
os.environ['CERT_TYPE']=""
190+
assert v is None
191+
145192
def tearDown(self):
146193
s3_resource = resource("s3",region_name="us-east-1")
147194
s3_bucket = s3_resource.Bucket( self.test_s3_bucket_name )

0 commit comments

Comments
 (0)