Upgrade to Pro — share decks privately, control downloads, hide ads and more …

サーバーレスシステムの複雑化に立ち向かう - IoTを例にみるAWSとDDDを駆使したアプリケーション設計 #serverlesstokyo / Coding, testing, logging pattern for get along with complicated buisiness in serverless application.

Yusuke Wada
September 29, 2018

サーバーレスシステムの複雑化に立ち向かう - IoTを例にみるAWSとDDDを駆使したアプリケーション設計 #serverlesstokyo / Coding, testing, logging pattern for get along with complicated buisiness in serverless application.

サーバーレスの仕組みにより、私たちは手軽にシステムのスケーラビリティを得られるようになりました。嬉しいことです。ですが、ビジネスの成長に伴って考慮することは、負荷だけではありません。ビジネスロジックの変化と拡張です。本セッションでは、サーバーレスのアプリケーションとしての側面に注目して、DDDを取り入れた設計、AWS IoTを使う状況でのテスト、そしてロギングについて議論します。

Yusuke Wada

September 29, 2018
Tweet

More Decks by Yusuke Wada

Other Decks in Technology

Transcript

  1. αʔόʔϨεͱ͔"84ͷ࿩ͰΑ͘ग़Δ͜͏͍͏ߏ੒ਤ   HUB-Device table Amazon DynamoDB media- bucket 

     LIXIL workers $,&)  Browser 3rd party users Lambda function $,&)    pre-signed URL Amazon API Gateway* HUB  mobile client %$ IoT certificate HUB  IoT policy Thing Registry IoT topic Amazon Kinesis Streams Event Table #+  ( +&  IoT HTTP protocol IoT shadow  "*, $,&)  BOX  media- bucket backup Amazon Kinesis Firehose ', !" Amazon API Gateway*       API device- manage-SPA Amazon CloudFront Cognito *+     IoT         
  2.    "84-BNCEBͷϩδοΫ ΛϨΠϠԽ͢Δ  "84؀ڥͰ&&ςετΛ࣮ ߦ͢Δ  -BNCEB'VODUJPOͷϩ

    άΛ"84"UIFOBͰݟΒ ΕΔΑ͏ʹ͢Δ ҭ͍ͯͯͨ͘Ίʹ ௥Ճมߋ͕ා͘ͳ͍"84αʔόʔϨεΞϓϦέʔγϣϯཁૉ
  3. ͜ͷཁૉΛຬͨ͢ͱ   ۀ຿ͷ৔ॴΛ໌֬ʹ͢Δ
 ۀ຿͕ୡ੒Ͱ͖Δ͜ͱΛࣔ͢
 ۀ຿ͷྲྀΕΛ௥͑ΔΑ͏ʹ͢Δ ௥ՃมߋՄೳ ΞϓϦέʔγϣϯ։ൃαΠΫϧ ͷεϐʔυΞοϓ ϓϩδΣΫτ։࢝࣌ͷ΢ΥʔϜ

    Ξοϓ࣌ؒ୹ॖ ͋ͱͰ΋Θ͔ΔɾҾ͖ܧ͛Δ ௥Ճมߋ͕ා͘ͳ͍"84αʔόʔϨεΞϓϦέʔγϣϯ ͜ΕΛظ଴ͯ͠ ͬͪ͜Λ࣮ફͯ͠Έͨ࿩
  4. ࿩͢಺༰ w αʔόʔϨεΞϓϦέʔγϣϯ͸ෳࡶԽʹڧ͘ͳ͍ w ղܾ΁ͷΞϓϩʔνɿϩδοΫΛϨΠϠԽ͢Δ w ΞϓϦ঺հɿ"84*P5ͱܨ͕ΔεϚʔτ୐഑ϙετ w "84-BNCEBͷϨΠϠʔԽ w

    αʔόʔϨεͷςετΛ&&ςετʹৼΓ͖Δ w "84-BNCEBͷϩάΛ"84"UIFOBͰݟΔ w ૯ׅ   NJO NJO NJO NJO NJO NJO NJO
  5. ࿩͢಺༰ w αʔόʔϨεΞϓϦέʔγϣϯ͸ෳࡶԽʹڧ͘ͳ͍ w ղܾ΁ͷΞϓϩʔνɿϩδοΫΛϨΠϠԽ͢Δ w ΞϓϦ঺հɿ"84*P5ͱܨ͕ΔεϚʔτ୐഑ϙετ w "84-BNCEBͷϨΠϠʔԽ w

    αʔόʔϨεͷςετΛ&&ςετʹৼΓ͖Δ w "84-BNCEBͷϩάΛ"84"UIFOBͰݟΔ w ૯ׅ   NJO NJO NJO NJO NJO NJO NJO ཧ࿦తͳ࿩
  6. ࿩͢಺༰ w αʔόʔϨεΞϓϦέʔγϣϯ͸ෳࡶԽʹڧ͘ͳ͍ w ղܾ΁ͷΞϓϩʔνɿϩδοΫΛϨΠϠԽ͢Δ w ΞϓϦ঺հɿ"84*P5ͱܨ͕ΔεϚʔτ୐഑ϙετ w "84-BNCEBͷϨΠϠʔԽ w

    αʔόʔϨεͷςετΛ&&ςετʹৼΓ͖Δ w "84-BNCEBͷϩάΛ"84"UIFOBͰݟΔ w ૯ׅ   NJO NJO NJO NJO NJO NJO NJO ࣮ફతͳ࿩
  7. ࿩͢಺༰ w αʔόʔϨεΞϓϦέʔγϣϯ͸ෳࡶԽʹڧ͘ͳ͍ w ղܾ΁ͷΞϓϩʔνɿϩδοΫΛϨΠϠԽ͢Δ w ΞϓϦ঺հɿ"84*P5ͱܨ͕ΔεϚʔτ୐഑ϙετ w "84-BNCEBͷϨΠϠʔԽ w

    αʔόʔϨεͷςετΛ&&ςετʹৼΓ͖Δ w "84-BNCEBͷϩάΛ"84"UIFOBͰݟΔ w ૯ׅ   NJO NJO NJO NJO NJO NJO NJO
  8. גࣜձࣾ-*9*-༷εϚʔτΤΫεςϦΞ*P5αʔόʔ   HUB-Device table Amazon DynamoDB media- bucket 

     LIXIL workers $,&)  Browser 3rd party users Lambda function $,&)    pre-signed URL Amazon API Gateway* HUB  mobile client %$ IoT certificate HUB  IoT policy Thing Registry IoT topic Amazon Kinesis Streams Event Table #+  ( +&  IoT HTTP protocol IoT shadow  "*, $,&)  BOX  media- bucket backup Amazon Kinesis Firehose ', !" Amazon API Gateway*       API device- manage-SPA Amazon CloudFront Cognito *+     IoT         
  9. Ұൠతͳ8FCΞϓϦέʔγϣϯͷ৔߹   γεςϜશମ OS ϛυϧ΢ΣΞ ΞϓϦέʔγϣϯ 1SPT Ұ౓؀ڥ͕ܾ·ΓσϓϩΠ͠ ͑͢͞Ε͹ɺ͋ͱ͸ΞϓϦέʔ

    γϣϯͱσʔλϕʔεΛҭͯͯ ͍͚͹ྑ͍ $POT ͨͱ͑γϯϓϧͳػೳͰ͋ͬͯ ΋࣮ݱ͢ΔͨΊʹ͸ࠨهͷߏ ੒ΛσϓϩΠ͢Δඞཁ͕͋Δ
  10. αʔόʔϨεΞϓϦέʔγϣϯͷ৔߹   γεςϜશମ . . . 1SPT ͻͱͭͷػೳΛσϓϩΠͯ͠ ར༻Ͱ͖ΔΑ͏ʹͳΔ·Ͱ௒

    ߴ଎ $POT ϩδοΫ͕෺ཧతʹ཭Ε͍ͯ ΔͷͰɺԿ΋ߟ͑ͣʹػೳΛ ૿΍͢ͱϝϯςίετ͕ઇͩ Δ·ࣜʹ૿͍͑ͯ͘
  11. αʔόʔϨεΞϓϦέʔγϣϯͷ৔߹   γεςϜશମ . . . 1SPT ͻͱͭͷػೳΛσϓϩΠͯ͠ ར༻Ͱ͖ΔΑ͏ʹͳΔ·Ͱ௒

    ߴ଎ $POT ϩδοΫ͕෺ཧతʹ཭Ε͍ͯ ΔͷͰɺԿ΋ߟ͑ͣʹػೳɾ ۀ຿Λ૿΍͢ͱϝϯςίετ ͕ઇͩΔ·ࣜʹ૿͍͑ͯ͘ Ͳͷίʔυ͕Կͷۀ຿Λୡ੒͢Δͷ͔ ϩδοΫ͸Ͳ͜ʹ͋Δͷ͔ ໎ࢠʹͳͬͯ͠·͏ ෳࡶͳཁ݅͸ۤख
  12. ࿩͢಺༰ w αʔόʔϨεΞϓϦέʔγϣϯ͸ෳࡶԽʹڧ͘ͳ͍ w ղܾ΁ͷΞϓϩʔνɿϩδοΫΛϨΠϠԽ͢Δ w ΞϓϦ঺հɿ"84*P5ͱܨ͕ΔεϚʔτ୐഑ϙετ w "84-BNCEBͷϨΠϠʔԽ w

    αʔόʔϨεͷςετΛ&&ςετʹৼΓ͖Δ w "84-BNCEBͷϩάΛ"84"UIFOBͰݟΔ w ૯ׅ   NJO NJO NJO NJO NJO NJO NJO
  13. -BNCEB'VODUJPOͷίʔυΛ૚ʹ͢Δ   FOWJSPONFOUT JUFTU TSD UFNQMBUFT .BLFpMF IBOEMFST EPNBJOT

    JOGSBTUSVDUVSFT w 'VODUJPOͷೖΓޱ w ҙࢥܾఆࢧԉ w EPNBJOTͷར༻खॱΛ ஌Δ
  14. -BNCEB'VODUJPOͷίʔυΛ૚ʹ͢Δ   FOWJSPONFOUT JUFTU TSD UFNQMBUFT .BLFpMF IBOEMFST EPNBJOT

    JOGSBTUSVDUVSFT w ΞϓϦͷத֩ͱͳΔΫϥε܈ w ۀ຿ w ্Լ૚͔Βੜ੒ɾར༻͞ΕΔ
  15. -BNCEB'VODUJPOͷίʔυΛ૚ʹ͢Δ   FOWJSPONFOUT JUFTU TSD UFNQMBUFT .BLFpMF IBOEMFST EPNBJOT

    JOGSBTUSVDUVSFT w "84ϦιʔεΞΫηε w ೳྗ w EPNBJOT͔Βݺ͹ΕΔ
  16. lམͱ͠ॴzͷߟ࡯   FOWJSPONFOUT JUFTU TSD UFNQMBUFT .BLFpMF IBOEMFST EPNBJOT

    JOGSBTUSVDUVSFT ύϥϝʔλͷύʔε ۀ຿ϑϩʔఆٛ Ϩεϙϯεੜ੒ɹ͸͜͜ ۀ຿ϩδοΫ͸͜͜ CPUP͕ඞཁͳॲཧ͸͜͜
  17. lམͱ͠ॴzͷߟ࡯   FOWJSPONFOUT JUFTU TSD UFNQMBUFT .BLFpMF IBOEMFST EPNBJOT

    JOGSBTUSVDUVSFT ύϥϝʔλͷύʔε ۀ຿ϑϩʔఆٛ Ϩεϙϯεੜ੒ɹ͸͜͜ ۀ຿ϩδοΫ͸͜͜ CPUP͕ඞཁͳॲཧ͸͜͜ ԿΑΓ΋ʮ෼ྨΛ͕Μ͹Γ͗͢ͳ͍ʯ͜ͱ
  18. ྫɿϢʔβʔ৘ใΛ$SFBUF͢Δ-BNCEB'VODUJPO   IBOEMFST EPNBJOT JOGSBTUSVDUVSFT VTFS create_user.py get_users.py def

    lambda_handler(event, context): try: email = event['email'] company = event['company'] display_user_name = event['display_user_name'] user_level = event['user_level'] except Exception as e: logger.exception(str(e)) raise invalid_request_response(e) try: user = CreateUser( email=email, company=company, display_user_name=display_user_name, user_level=user_level ) user.insert() except Exception as e: logger.exception(str(e)) if type(e) == UserAlreadyExistsException: raise conflict_response(e) else: raise server_error(e) create_user.py
  19. ྫɿϢʔβʔ৘ใΛ$SFBUF͢Δ-BNCEB'VODUJPO   IBOEMFST EPNBJOT JOGSBTUSVDUVSFT VTFS create_user.py get_users.py def

    lambda_handler(event, context): try: email = event['email'] company = event['company'] display_user_name = event['display_user_name'] user_level = event['user_level'] except Exception as e: logger.exception(str(e)) raise invalid_request_response(e) try: user = CreateUser( email=email, company=company, display_user_name=display_user_name, user_level=user_level ) user.insert() except Exception as e: logger.exception(str(e)) if type(e) == UserAlreadyExistsException: raise conflict_response(e) else: raise server_error(e) create_user.py ԿΛ΍Δ΂͖͔͸஌ͬͯΔ͚Ͳ ۩ମతͳ࡞ۀ͸EPNBJOTʹ೚ͤΔ
  20. ྫɿϢʔβʔ৘ใΛ$SFBUF͢Δ-BNCEB'VODUJPO   IBOEMFST EPNBJOT JOGSBTUSVDUVSFT VTFS user.py class CreateUser:

    def __init__(self, email, company, display_user_name, user_level): self.user_uuid = str(uuid.uuid4()) self.email = email self.company = company self.display_user_name = display_user_name self.user_level = user_level def insert(self): import infrastructures.user.user_repository as user_repository import infrastructures.user.auth_repository as auth_repository auth_repository.admin_create_user(self.user_uuid, self.email) user_repository.create(self) user.py
  21. ྫɿϢʔβʔ৘ใΛ$SFBUF͢Δ-BNCEB'VODUJPO   IBOEMFST EPNBJOT JOGSBTUSVDUVSFT VTFS user.py class CreateUser:

    def __init__(self, email, company, display_user_name, user_level): self.user_uuid = str(uuid.uuid4()) self.email = email self.company = company self.display_user_name = display_user_name self.user_level = user_level def insert(self): import infrastructures.user.user_repository as user_repository import infrastructures.user.auth_repository as auth_repository auth_repository.admin_create_user(self.user_uuid, self.email) user_repository.create(self) user.py Ϣʔβʔ*%66**%Λ࢖͏
  22. ྫɿϢʔβʔ৘ใΛ$SFBUF͢Δ-BNCEB'VODUJPO   IBOEMFST EPNBJOT JOGSBTUSVDUVSFT VTFS user.py class CreateUser:

    def __init__(self, email, company, display_user_name, user_level): self.user_uuid = str(uuid.uuid4()) self.email = email self.company = company self.display_user_name = display_user_name self.user_level = user_level def insert(self): import infrastructures.user.user_repository as user_repository import infrastructures.user.auth_repository as auth_repository auth_repository.admin_create_user(self.user_uuid, self.email) user_repository.create(self) user.py ೝূϦϙδτϦͱ ϢʔβʔϦϙδτϦʹ σʔλΛ࡞Δ
  23. ྫɿϢʔβʔ৘ใΛ$36%͢Δ-BNCEB'VODUJPO   IBOEMFST EPNBJOT JOGSBTUSVDUVSFT VTFS user_repository.py auth_repository.py def

    create(user: CreateUser): updated_at = epoc_second_now() try: DYNAMODB_TABLE.put_item( Item={ 'user_uuid': user.user_uuid, 'email': user.email, 'company': user.company, 'display_user_name': user.display_user_name, 'created_at': updated_at, 'updated_at': updated_at }, ConditionExpression='attribute_not_exists(user_uuid)' ) except ClientError as error: if error.response['Error']['Code'] == 'ConditionalCheckFailedException': raise UserAlreadyExistsException(user.user_uuid, error) else: raise error user_repository.py
  24. ྫɿϢʔβʔ৘ใΛ$36%͢Δ-BNCEB'VODUJPO   IBOEMFST EPNBJOT JOGSBTUSVDUVSFT VTFS user_repository.py auth_repository.py def

    create(user: CreateUser): updated_at = epoc_second_now() try: DYNAMODB_TABLE.put_item( Item={ 'user_uuid': user.user_uuid, 'email': user.email, 'company': user.company, 'display_user_name': user.display_user_name, 'created_at': updated_at, 'updated_at': updated_at }, ConditionExpression='attribute_not_exists(user_uuid)' ) except ClientError as error: if error.response['Error']['Code'] == 'ConditionalCheckFailedException': raise UserAlreadyExistsException(user.user_uuid, error) else: raise error υϝΠϯΦϒδΣΫτΛ࢖ͬͯ %ZOBNP%#ʹอଘ͢Δ CPUPΛ࢖͍͍ͬͯͷ͸͚ͩ͜͜ user_repository.py
  25. ࿩͢಺༰   NJO NJO NJO NJO NJO NJO NJO

    w αʔόʔϨεΞϓϦέʔγϣϯ͸ෳࡶԽʹڧ͘ͳ͍ w ղܾ΁ͷΞϓϩʔνɿϩδοΫΛϨΠϠԽ͢Δ w ΞϓϦ঺հɿ"84*P5ͱܨ͕ΔεϚʔτ୐഑ϙετ w "84-BNCEBͷϨΠϠʔԽ w αʔόʔϨεͷςετΛ&&ςετʹৼΓ͖Δ w "84-BNCEBͷϩάΛ"84"UIFOBͰݟΔ w ૯ׅ
  26. εϚʔτ୐഑ϙετొ࿥ϑϩʔ  %ZOBNP%#΁ࣄલొ࿥  ূ໌ॻͷ
 δϟετΠϯλΠϜొ࿥  ϗʔϜϢχοτొ࿥  ୐഑ϙετొ࿥

     ҎޙɺΠϕϯτ௨৴   Device table Amazon DynamoDB  Lambda function Amazon API Gateway* HUB mobile client   IoT certificate HUB IoT policy Thing Registry IoT topic Amazon Kinesis Streams Event Table IoT HTTP protocol
  27. εϚʔτ୐഑ϙετొ࿥ϑϩʔ  %ZOBNP%#΁ࣄલొ࿥  ূ໌ॻͷ
 δϟετΠϯλΠϜొ࿥  ϗʔϜϢχοτొ࿥  ୐഑ϙετొ࿥

     ҎޙɺΠϕϯτ௨৴   Device table Amazon DynamoDB  Lambda function Amazon API Gateway* HUB mobile client   IoT certificate HUB IoT policy Thing Registry IoT topic Amazon Kinesis Streams Event Table IoT HTTP protocol
  28. εϚʔτ୐഑ϙετొ࿥ϑϩʔ  %ZOBNP%#΁ࣄલొ࿥  ূ໌ॻͷ
 δϟετΠϯλΠϜొ࿥  ϗʔϜϢχοτొ࿥  ୐഑ϙετొ࿥

     ҎޙɺΠϕϯτ௨৴   Device table Amazon DynamoDB  Lambda function Amazon API Gateway* HUB mobile client   IoT certificate HUB IoT policy Thing Registry IoT topic Amazon Kinesis Streams Event Table IoT HTTP protocol
  29. εϚʔτ୐഑ϙετొ࿥ϑϩʔ  %ZOBNP%#΁ࣄલొ࿥  ূ໌ॻͷ
 δϟετΠϯλΠϜొ࿥  ϗʔϜϢχοτొ࿥  ୐഑ϙετొ࿥

     ҎޙɺΠϕϯτ௨৴   Device table Amazon DynamoDB  Lambda function Amazon API Gateway* HUB mobile client   IoT certificate HUB IoT policy Thing Registry IoT topic Amazon Kinesis Streams Event Table IoT HTTP protocol
  30. εϚʔτ୐഑ϙετొ࿥ϑϩʔ  %ZOBNP%#΁ࣄલొ࿥  ূ໌ॻͷ
 δϟετΠϯλΠϜొ࿥  ϗʔϜϢχοτొ࿥  ୐഑ϙετొ࿥

     ҎޙɺΠϕϯτ௨৴   Device table Amazon DynamoDB  Lambda function Amazon API Gateway* HUB mobile client   IoT certificate HUB IoT policy Thing Registry IoT topic Amazon Kinesis Streams Event Table IoT HTTP protocol
  31. ࿩͢಺༰ w αʔόʔϨεΞϓϦέʔγϣϯ͸ෳࡶԽʹڧ͘ͳ͍ w ղܾ΁ͷΞϓϩʔνɿϩδοΫΛϨΠϠԽ͢Δ w ΞϓϦ঺հɿ"84*P5ͱܨ͕ΔεϚʔτ୐഑ϙετ w "84-BNCEBͷϨΠϠʔԽ w

    αʔόʔϨεͷςετΛ&&ςετʹৼΓ͖Δ w "84-BNCEBͷϩάΛ"84"UIFOBͰݟΔ w ૯ׅ   NJO NJO NJO NJO NJO NJO NJO
  32. εϚʔτ୐഑ϙετొ࿥ϑϩʔ  %ZOBNP%#΁ࣄલొ࿥  ূ໌ॻͷ
 δϟετΠϯλΠϜొ࿥  ϗʔϜϢχοτొ࿥  ୐഑ϙετొ࿥

     ҎޙɺΠϕϯτ௨৴   Device table Amazon DynamoDB  Lambda function Amazon API Gateway* HUB mobile client   IoT certificate HUB IoT policy Thing Registry IoT topic Amazon Kinesis Streams Event Table IoT HTTP protocol
  33. εϚʔτ୐഑ϙετొ࿥ϑϩʔ  %ZOBNP%#΁ࣄલొ࿥  ূ໌ॻͷ
 δϟετΠϯλΠϜొ࿥  ϗʔϜϢχοτొ࿥  ୐഑ϙετొ࿥

     ҎޙɺΠϕϯτ௨৴   Device table Amazon DynamoDB  Lambda function Amazon API Gateway* HUB mobile client   IoT certificate HUB IoT policy Thing Registry IoT topic Amazon Kinesis Streams Event Table IoT HTTP protocol ϐοΫΞοϓ
  34. ୐഑ϙετొ࿥ॲཧͷϨΠϠʔԽ  %ZOBNP%#΁ࣄલొ࿥  ূ໌ॻͷ
 δϟετΠϯλΠϜొ࿥  ϗʔϜϢχοτొ࿥  ୐഑ϙετొ࿥

     ҎޙɺΠϕϯτ௨৴   B %ZOBNP%#νΣοΫ C ొ࿥ঢ়گͷه࿥ D *P55IJOH3FHJTUSZొ ࿥ E 5IJOH(SPVQ΁ࢀՃ F 1PMJDZͷߋ৽ G ొ࿥ঢ়گͷه࿥
  35. ୐഑ϙετొ࿥ॲཧͷϨΠϠʔԽ  %ZOBNP%#΁ࣄલొ࿥  ূ໌ॻͷ
 δϟετΠϯλΠϜొ࿥  ϗʔϜϢχοτొ࿥  ୐഑ϙετొ࿥

     ҎޙɺΠϕϯτ௨৴   B %ZOBNP%#νΣοΫ C ొ࿥ঢ়گͷه࿥ D *P55IJOH3FHJTUSZొ ࿥ E 5IJOH(SPVQ΁ࢀՃ F 1PMJDZͷߋ৽ G ొ࿥ঢ়گͷه࿥ 1 Function Ͱ΍ͬͯΈΔ͜ͱʹͨ͠
  36. ϨΠϠʔԽલʢҰ෦ʣ   def lambda_handler(event, context): device_id = event[‘device_id’] uuid

    = event['uuid'] nodes = event['nodes'] types = get_device_types() groups = list_thing_groups_for_hub(uuid) group_name = groups['thingGroups'][0]['groupName'] if check_device(device_id, uuid): for node in nodes: # create thing created_node = create_node(node, types) # add thing to the group node_uuid = created_node['thingName'] add_node_to_thing_group(group_name, node_uuid) else: return nodes = list_nodes_in_hub_group(group_name) update_hub_attribute_nodes(uuid, len(nodes))
  37. ϨΠϠʔԽલʢҰ෦ʣ   def lambda_handler(event, context): device_id = event[‘device_id’] uuid

    = event['uuid'] nodes = event['nodes'] types = get_device_types() groups = list_thing_groups_for_hub(uuid) group_name = groups['thingGroups'][0]['groupName'] if check_device(device_id, uuid): for node in nodes: # create thing created_node = create_node(node, types) # add thing to the group node_uuid = created_node['thingName'] add_node_to_thing_group(group_name, node_uuid) else: return nodes = list_nodes_in_hub_group(group_name) update_hub_attribute_nodes(uuid, len(nodes)) ϋϯυϥͷΠϕϯτΛ ஌͍ͬͯΔ
  38. ϨΠϠʔԽલʢҰ෦ʣ   def lambda_handler(event, context): device_id = event[‘device_id’] uuid

    = event['uuid'] nodes = event['nodes'] types = get_device_types() groups = list_thing_groups_for_hub(uuid) group_name = groups['thingGroups'][0]['groupName'] if check_device(device_id, uuid): for node in nodes: # create thing created_node = create_node(node, types) # add thing to the group node_uuid = created_node['thingName'] add_node_to_thing_group(group_name, node_uuid) else: return nodes = list_nodes_in_hub_group(group_name) update_hub_attribute_nodes(uuid, len(nodes)) *P5ͷ࢓༷΋஌ͬͯΔ
  39. ϨΠϠʔԽલʢҰ෦ʣ   def lambda_handler(event, context): device_id = event[‘device_id’] uuid

    = event['uuid'] nodes = event['nodes'] types = get_device_types() groups = list_thing_groups_for_hub(uuid) group_name = groups['thingGroups'][0]['groupName'] if check_device(device_id, uuid): for node in nodes: # create thing created_node = create_node(node, types) # add thing to the group node_uuid = created_node['thingName'] add_node_to_thing_group(group_name, node_uuid) else: return nodes = list_nodes_in_hub_group(group_name) update_hub_attribute_nodes(uuid, len(nodes)) ϩδοΫʁ Կ͔νΣοΫͯ͠ ʜԿΛ܁Γฦ͍ͯ͠Δͷʁ
  40. ϨΠϠʔԽલʢҰ෦ʣ   def lambda_handler(event, context): device_id = event[‘device_id’] uuid

    = event['uuid'] nodes = event['nodes'] types = get_device_types() groups = list_thing_groups_for_hub(uuid) group_name = groups['thingGroups'][0]['groupName'] if check_device(device_id, uuid): for node in nodes: # create thing created_node = create_node(node, types) # add thing to the group node_uuid = created_node['thingName'] add_node_to_thing_group(group_name, node_uuid) else: return nodes = list_nodes_in_hub_group(group_name) update_hub_attribute_nodes(uuid, len(nodes)) ϩδοΫʁ Կ͔νΣοΫͯ͠ ʜԿΛ܁Γฦ͍ͯ͠Δͷʁ Կ͕͍ͨ͠ͷ͔͕ݟ͑ͳ͍ ػೳ௥Ճ͕೉͍͠
  41. ϨΠϠʔԽޙʢҰ෦ʣ   IBOEMFST EPNBJOT JOGSBTUSVDUVSFT SFHJTUSZ nodes_register_handler.py def lambda_handler(event,

    context): try: #ύϥϝʔλऔಘ nodes = NodeFactory.nodes_provider(param_hub_uuid, param_nodes) except Exception as e: # handle return try: task_manager = TaskManager(task_uuid, param_hub_uuid) task_manager.start() signin = SignIn(device_id, certificate_id) hub_uuid = signin.signin() service = NodeRegisterService(hub_uuid, account_id, certificate_id, nodes) node_things = service.node_register() reason = 'NodeRegisterFinished' task_manager.finish(reason) InfoLogger(node_things).log() except Exception as e: # handle return
  42. ϨΠϠʔԽޙʢҰ෦ʣ   IBOEMFST EPNBJOT JOGSBTUSVDUVSFT SFHJTUSZ nodes_register_handler.py def lambda_handler(event,

    context): try: #ύϥϝʔλऔಘ nodes = NodeFactory.nodes_provider(param_hub_uuid, param_nodes) except Exception as e: # handle return try: task_manager = TaskManager(task_uuid, param_hub_uuid) task_manager.start() signin = SignIn(device_id, certificate_id) hub_uuid = signin.signin() service = NodeRegisterService(hub_uuid, account_id, certificate_id, nodes) node_things = service.node_register() reason = 'NodeRegisterFinished' task_manager.finish(reason) InfoLogger(node_things).log() except Exception as e: # handle return λεΫ؅ཧ
  43. ϨΠϠʔԽޙʢҰ෦ʣ   IBOEMFST EPNBJOT JOGSBTUSVDUVSFT SFHJTUSZ nodes_register_handler.py def lambda_handler(event,

    context): try: #ύϥϝʔλऔಘ nodes = NodeFactory.nodes_provider(param_hub_uuid, param_nodes) except Exception as e: # handle return try: task_manager = TaskManager(task_uuid, param_hub_uuid) task_manager.start() signin = SignIn(device_id, certificate_id) hub_uuid = signin.signin() service = NodeRegisterService(hub_uuid, account_id, certificate_id, nodes) node_things = service.node_register() reason = 'NodeRegisterFinished' task_manager.finish(reason) InfoLogger(node_things).log() except Exception as e: # handle return ΫϥΠΞϯτ νΣοΫ
  44. ϨΠϠʔԽޙʢҰ෦ʣ   IBOEMFST EPNBJOT JOGSBTUSVDUVSFT SFHJTUSZ nodes_register_handler.py def lambda_handler(event,

    context): try: #ύϥϝʔλऔಘ nodes = NodeFactory.nodes_provider(param_hub_uuid, param_nodes) except Exception as e: # handle return try: task_manager = TaskManager(task_uuid, param_hub_uuid) task_manager.start() signin = SignIn(device_id, certificate_id) hub_uuid = signin.signin() service = NodeRegisterService(hub_uuid, account_id, certificate_id, nodes) node_things = service.node_register() reason = 'NodeRegisterFinished' task_manager.finish(reason) InfoLogger(node_things).log() except Exception as e: # handle return ୐഑ϙετొ࿥
  45. ϨΠϠʔԽޙʢҰ෦ʣ   IBOEMFST EPNBJOT JOGSBTUSVDUVSFT SFHJTUSZ nodes_register_handler.py def lambda_handler(event,

    context): try: #ύϥϝʔλऔಘ nodes = NodeFactory.nodes_provider(param_hub_uuid, param_nodes) except Exception as e: # handle return try: task_manager = TaskManager(task_uuid, param_hub_uuid) task_manager.start() signin = SignIn(device_id, code, param_hub_uuid, certificate_id) hub_uuid = signin.signin() service = NodeRegisterService(hub_uuid, account_id, certificate_id, nodes) node_things = service.node_register() reason = 'NodeRegisterFinished' task_manager.finish(reason) InfoLogger(node_things).log() except Exception as e: # handle return ୐഑ϙετొ࿥ ۩ମతͳ࡞ۀ͸ߦ͍ͬͯͳ͍͕ ॲཧͷॱংΛ஌͍ͬͯΔ ॱং͕ݟͯΘ͔Δ
  46. ϨΠϠʔԽޙυϝΠϯ   IBOEMFST EPNBJOT JOGSBTUSVDUVSFT SFHJTUSZ nodes_register.py TJHOVQ device_checker.py

    UBTL task_manager.py ϋϯυϥʔ͔Βར༻͞ΕΔ ֤ΫϥεΛఏڙ class NodeThings: def __init__(self, aws_account_id, certificate_id, hub_uuid, node_thing_list: List[NodeThing]): self.aws_account_id = aws_account_id self.certificate_id = certificate_id self.policy_name = get_nodes_policy_name(certificate_id) self.hub_uuid = hub_uuid self.node_thing_list = node_thing_list def update_policy(self): import infrastructures.registry.node_policy_repository as repository repository.create_policy_for_nodes(self) repository.attach_policy(self) node_things_register.py
  47. ϨΠϠʔԽޙυϝΠϯ   IBOEMFST EPNBJOT JOGSBTUSVDUVSFT SFHJTUSZ nodes_register.py TJHOVQ device_checker.py

    UBTL task_manager.py ϋϯυϥʔ͔Βར༻͞ΕΔ ֤ΫϥεΛఏڙ class NodeThings: def __init__(self, aws_account_id, certificate_id, hub_uuid, node_thing_list: List[NodeThing]): self.aws_account_id = aws_account_id self.certificate_id = certificate_id self.policy_name = get_nodes_policy_name(certificate_id) self.hub_uuid = hub_uuid self.node_thing_list = node_thing_list def update_policy(self): import infrastructures.registry.node_policy_repository as repository repository.create_policy_for_nodes(self) repository.attach_policy(self) ඞཁͳૉࡐΛ࢖ͬͯ node_things_register.py
  48. ϨΠϠʔԽޙυϝΠϯ   IBOEMFST EPNBJOT JOGSBTUSVDUVSFT SFHJTUSZ nodes_register.py TJHOVQ device_checker.py

    UBTL task_manager.py ϋϯυϥʔ͔Βར༻͞ΕΔ ֤ΫϥεΛఏڙ class NodeThings: def __init__(self, aws_account_id, certificate_id, hub_uuid, node_thing_list: List[NodeThing]): self.aws_account_id = aws_account_id self.certificate_id = certificate_id self.policy_name = get_nodes_policy_name(certificate_id) self.hub_uuid = hub_uuid self.node_thing_list = node_thing_list def update_policy(self): import infrastructures.registry.node_policy_repository as repository repository.create_policy_for_nodes(self) repository.attach_policy(self) ۀ຿Λ࣮ߦ͢Δ
  49. ࿩͢಺༰ w αʔόʔϨεΞϓϦέʔγϣϯ͸ෳࡶԽʹڧ͘ͳ͍ w ղܾ΁ͷΞϓϩʔνɿϩδοΫΛϨΠϠԽ͢Δ w ΞϓϦ঺հɿ"84*P5ͱܨ͕ΔεϚʔτ୐഑ϙετ w "84-BNCEBͷϨΠϠʔԽ w

    αʔόʔϨεͷςετΛ&&ςετʹৼΓ͖Δ w "84-BNCEBͷϩάΛ"84"UIFOBͰݟΔ w ૯ׅ   NJO NJO NJO NJO NJO NJO NJO
  50. αʔόʔϨεΞϓϦέʔγϣϯͷςετ   ϩδοΫͷςετΛ͢Δͱͨ͠Βʜ γεςϜશମ . . . SAM Localʁ

    localstack ϩʔΧϧʹ্ཱͪ͛Δʁ AWS IoT ͸Ͳ͏͢Δʁ Kinesis Streams͸ʁ
  51. αʔόʔϨεΞϓϦέʔγϣϯͷςετ   ϩδοΫͷςετΛ͢Δͱͨ͠Βʜ γεςϜશମ . . . SAM Localʁ

    localstack ϩʔΧϧʹ্ཱͪ͛Δʁ AWS IoT ͸Ͳ͏͢Δʁ Kinesis Streams͸ʁ ࿑ྗʹݟ߹͏ͷ͔ʁ
  52. -BNCEB'VODUJPOͱڞ௨ͷઃఆΛ࢖͏   "844ZTUFNT.BOBHFSͷ1BSBNFUFS4UPSFΛ ׆༻͢Δ -BNCEB'VODUJPO 4".ςϯϓϨʔτྫ AWSTemplateFormatVersion: '2010-09-09' Transform:

    AWS::Serverless-2016-10-31 Parameters: AwsIotHttpEndpoint: Default: /prd/lambda/AwsIotHttpEndpoint Type: AWS::SSM::Parameter::Value<String> CommitId: Default: '000000000' Type: String DynamoDBEndpoint: Default: /prd/lambda/DynamoDBEndpoint Type: AWS::SSM::Parameter::Value<String> Env: Default: /prd/lambda/Env Type: AWS::SSM::Parameter::Value<String> Resources: NodesRegistry: Type: AWS::Serverless::Function Properties: FunctionName: !Sub ${Env}-iot_nodes_thing_registry …
  53. -BNCEB'VODUJPOͱڞ௨ͷઃఆΛ࢖͏   "844ZTUFNT.BOBHFSͷ1BSBNFUFS4UPSFΛ ׆༻͢Δ -BNCEB'VODUJPO 4".ςϯϓϨʔτྫ AWSTemplateFormatVersion: '2010-09-09' Transform:

    AWS::Serverless-2016-10-31 Parameters: AwsIotHttpEndpoint: Default: /prd/lambda/AwsIotHttpEndpoint Type: AWS::SSM::Parameter::Value<String> CommitId: Default: '000000000' Type: String DynamoDBEndpoint: Default: /prd/lambda/DynamoDBEndpoint Type: AWS::SSM::Parameter::Value<String> Env: Default: /prd/lambda/Env Type: AWS::SSM::Parameter::Value<String> Resources: NodesRegistry: Type: AWS::Serverless::Function Properties: FunctionName: !Sub ${Env}-iot_nodes_thing_registry … ؀ڥม਺ͷઃఆ ྫɿ%ZOBNP%#ςʔϒϧ໊
  54. -BNCEB'VODUJPOͱڞ௨ͷઃఆΛ࢖͏   "844ZTUFNT.BOBHFSͷ1BSBNFUFS4UPSFΛ ׆༻͢Δ &&ςετ
 pYUVSFྫ @pytest.fixture(scope='session', autouse=False) def

    ssm_parameters(request) -> SsmParameters: env = request.config.getoption('--env') yield make_parameters(env) def make_parameters(env) -> SsmParameters: # from SSM function_args = { 'Path': f'/{env}', 'Recursive': True, 'WithDecryption': True, 'MaxResults': 10, } response = SSM.get_parameters_by_path(**function_args) current_batch, next_token = extract_result(response) result = current_batch while next_token is not None: #࠶औಘ parameters_from_ssm = \ {extract_parameter_name(parameter): parameter['Value'] for parameter in result} ssm_parameters = SsmParameters(parameters_from_ssm) return ssm_parameters
  55. -BNCEB'VODUJPOͱڞ௨ͷઃఆΛ࢖͏   "844ZTUFNT.BOBHFSͷ1BSBNFUFS4UPSFΛ ׆༻͢Δ &&ςετ
 pYUVSFྫ @pytest.fixture(scope='session', autouse=False) def

    ssm_parameters(request) -> SsmParameters: env = request.config.getoption('--env') yield make_parameters(env) def make_parameters(env) -> SsmParameters: # from SSM function_args = { 'Path': f'/{env}', 'Recursive': True, 'WithDecryption': True, 'MaxResults': 10, } response = SSM.get_parameters_by_path(**function_args) current_batch, next_token = extract_result(response) result = current_batch while next_token is not None: #࠶औಘ parameters_from_ssm = \ {extract_parameter_name(parameter): parameter['Value'] for parameter in result} ssm_parameters = SsmParameters(parameters_from_ssm) return ssm_parameters ύϥϝʔλετΞ͔ΒσʔλΛऔ ಘ͠ΦϒδΣΫτੜ੒ ֤ςετͰύϥϝʔλ͕ར༻Ͱ͖Δ
  56. ࣄલ৚݅ͱͳΔۀ຿Λ͋Β͔͡Ίୡ੒͓ͯ͘͠   1.DynamoDB΁ࣄલొ࿥ 2.ূ໌ॻͷδϟετΠϯλΠϜొ࿥ 3.ϗʔϜϢχοτొ࿥ 4.୐഑ϙετొ࿥ 5.ҎޙɺΠϕϯτ௨৴ ͜Ε͸ऴΘ͍ͬͯΔඞ ཁ͕͋Δ

    @pytest.mark.usefixtures('download_cert_fixture', 'signup_fixture', 'task_fixture', 'jit_second_fixture', 'iot_thing_hub_register_fixture', 'iot_thing_nodes_register_fixture') def test_iot_nodes_register_finished( self, ssm_parameters: SsmParameters, signup_fixture: SignUpFixture, task_fixture: TaskFixture, jit_second_fixture: JitFixture, iot_thing_nodes_register_fixture: List[IotThingNodeRegisterFixture]):
  57. ࣄલ৚݅ͱͳΔۀ຿Λ͋Β͔͡Ίୡ੒͓ͯ͘͠   1.DynamoDB΁ࣄલొ࿥ 2.ূ໌ॻͷδϟετΠϯλΠϜొ࿥ 3.ϗʔϜϢχοτొ࿥ 4.୐഑ϙετొ࿥ 5.ҎޙɺΠϕϯτ௨৴ ͜Ε͸ऴΘ͍ͬͯΔඞ ཁ͕͋Δ

    @pytest.mark.usefixtures('download_cert_fixture', 'signup_fixture', 'task_fixture', 'jit_second_fixture', 'iot_thing_hub_register_fixture', 'iot_thing_nodes_register_fixture') def test_iot_nodes_register_finished( self, ssm_parameters: SsmParameters, signup_fixture: SignUpFixture, task_fixture: TaskFixture, jit_second_fixture: JitFixture, iot_thing_nodes_register_fixture: List[IotThingNodeRegisterFixture]): ࣄલॲཧ͕ऴΘͬͨঢ়ଶͰ୐഑ ϙετొ࿥ςετΛ։࢝Ͱ͖Δ
  58. ࿩͢಺༰ w αʔόʔϨεΞϓϦέʔγϣϯ͸ෳࡶԽʹڧ͘ͳ͍ w ղܾ΁ͷΞϓϩʔνɿϩδοΫΛϨΠϠԽ͢Δ w ΞϓϦ঺հɿ"84*P5ͱܨ͕ΔεϚʔτ୐഑ϙετ w "84-BNCEBͷϨΠϠʔԽ w

    αʔόʔϨεͷςετΛ&&ςετʹৼΓ͖Δ w "84-BNCEBͷϩάΛ"84"UIFOBͰݟΔ w ૯ׅ   NJO NJO NJO NJO NJO NJO NJO
  59. ϩάΛग़͢໨తΛ੔ཧ͢Δ   ΰʔϧɿྲྀΕΛ௥͑ΔΑ͏ʹ͢ΔɹͨΊͷཁ݅ w UBTL@VVJE
 ϦΫΤετΛ௥੻Ͱ͖Δ*% w MBNCEB@SFRVFTU@JE
 -BNCEBͷϦΫΤετ*%

    w EFWJDF@JE
 ΫϥΠΞϯτݻ༗ͷ*% ੒ޭͨ͜͠ͱ͕Θ͔Δ
 ࣦഊͨ͜͠ͱ͕Θ͔Δ ɾͲͷϦΫΤετͰ
 ɾԿͷॲཧ͕
 ɾ͍ͭ
 ɾͳͥ
  60. ϩάΛग़͢໨తΛ੔ཧ͢Δ   ΰʔϧɿྲྀΕΛ௥͑ΔΑ͏ʹ͢ΔɹͨΊͷཁ݅ w MBNCEB@IBOEMFS
 'VODUJPO໊ w MPH@FWFOU
 ۀ຿Λ۠ผ͢Δ໊લ

    ੒ޭͨ͜͠ͱ͕Θ͔Δ
 ࣦഊͨ͜͠ͱ͕Θ͔Δ ɾͲͷϦΫΤετͰ
 ɾԿͷॲཧ͕
 ɾ͍ͭ
 ɾͳͥ
  61. ϩάΛग़͢໨తΛ੔ཧ͢Δ   ΰʔϧɿྲྀΕΛ௥͑ΔΑ͏ʹ͢ΔɹͨΊͷཁ݅ w UJNFTUBNQ
 VOJYUJNFɻιʔτͰ౎߹͕ ྑ͍ w UJNFTUBNQ@KTU


    ਓ͕ؒݟΔ༻ ੒ޭͨ͜͠ͱ͕Θ͔Δ
 ࣦഊͨ͜͠ͱ͕Θ͔Δ ɾͲͷϦΫΤετͰ
 ɾԿͷॲཧ͕
 ɾ͍ͭ
 ɾͳͥ
  62. ϩάग़ྗج൫      Lambda Amazon SNS Amazon

    Kinesis Firehose Amazon Athena alarm Amazon CloudWatch      Amazon Kinesis Streams
  63. ϩάग़ྗج൫      Lambda Amazon SNS Amazon

    Kinesis Firehose Amazon Athena alarm Amazon CloudWatch      Amazon Kinesis Streams try: … except Exception as e: ErrorLogger( lambda_event=event, lambda_context=context, commit_id=variables.get_commit_id(), param_hub_uuid=None, error=e, traceback=traceback.format_exc() ).log() raise e -BNCEB'VODUJPOͰϩά༻ΦϒδΣΫτΛ࡞ͬͯग़ྗ࣮ߦ
  64. ϩάग़ྗج൫      Lambda Amazon SNS Amazon

    Kinesis Firehose Amazon Athena alarm Amazon CloudWatch      Amazon Kinesis Streams try: … except Exception as e: ErrorLogger( lambda_event=event, lambda_context=context, commit_id=variables.get_commit_id(), param_hub_uuid=None, error=e, traceback=traceback.format_exc() ).log() raise e ,JOFTJT4USFBNT΁ϩά౤ೖ -BNCEB'VODUJPOͰϩά༻ΦϒδΣΫτΛ࡞ͬͯग़ྗ࣮ߦ
  65. ྲྀΕΛ௥͑Δϩάج൫       Lambda Amazon SNS

    Amazon Kinesis Firehose Amazon Athena alarm Amazon CloudWatch Amazon Kinesis Streams w ϦΫΤετΛಛఆͰ͖ Δ*% w ॲཧΛಛఆͰ͖Δ৘ใ w ೔࣌৘ใ w पลίϯςΩετ৘ใ
  66. ྲྀΕΛ௥͑Δϩάج൫       Lambda Amazon SNS

    Amazon Kinesis Firehose Amazon Athena alarm Amazon CloudWatch Amazon Kinesis Streams w ϦΫΤετΛಛఆͰ͖ Δ*% w ॲཧΛಛఆͰ͖Δ৘ใ w ೔࣌৘ใ w पลίϯςΩετ৘ใ ͜ΕΛ
  67. ྲྀΕΛ௥͑Δϩάج൫       Lambda Amazon SNS

    Amazon Kinesis Firehose Amazon Athena alarm Amazon CloudWatch Amazon Kinesis Streams w ϦΫΤετΛಛఆͰ͖ Δ*% w ॲཧΛಛఆͰ͖Δ৘ใ w ೔࣌৘ใ w पลίϯςΩετ৘ใ ͜͏΍ͬͯग़͢
  68. ϩάग़ྗج൫      Lambda Amazon SNS Amazon

    Kinesis Firehose Amazon Athena alarm Amazon CloudWatch      Amazon Kinesis Streams "NB[PO"UIFOBͰͷ ݟ͑ํͲΜͳײ͡ʁ ͅ
  69. "84"UIFOBͰݟͯΈΔ   ಛఆͷΫϥΠΞϯτ*%ͷྲྀΕΛ௥͍͍ͨ৔߹ SELECT level, log_event, lambda_handler, lambda_commit_id, timestamp_jst

    FROM application WHERE device_id = ‘123456789’ and timestamp >= 1527744698 ORDER BY timestamp desc
  70. "84"UIFOBͰݟͯΈΔ   SELECT level, log_event, lambda_handler, lambda_commit_id, timestamp_jst FROM

    application WHERE device_id = ‘123456789’ and timestamp >= 1527744698 ORDER BY timestamp desc ༨ஊɿ-BNCEB 'VDOUJPO͕ͲͷόʔδϣϯͰಈ͍ͯ ͍Δ͔Θ͔ΔͷͰ $PNNJU*E͓͢͢Ί ಛఆͷΫϥΠΞϯτ*%ͷྲྀΕΛ௥͍͍ͨ৔߹
  71. ϩάग़ྗج൫      Lambda Amazon SNS Amazon

    Kinesis Firehose Amazon Athena alarm Amazon CloudWatch      Amazon Kinesis Streams $MPVE8BUDI-PHTʹ ྲྀΕΔϩάΛݟ͍ͨ
  72. TBXͰݟͯΈΔ   TylerBrock/saw: Fast, multi-purpose tool for AWS CloudWatch

    Logs https://github.com/TylerBrock/saw/releases $MPVE8BUDI-PHTͷ ϩάάϧʔϓΛ λʔϛφϧͰετϦʔϛϯάͰ͖Δπʔϧ
  73. ࿩͢಺༰ w αʔόʔϨεΞϓϦέʔγϣϯ͸ෳࡶԽʹڧ͘ͳ͍ w ղܾ΁ͷΞϓϩʔνɿϩδοΫΛϨΠϠԽ͢Δ w ΞϓϦ঺հɿ"84*P5ͱܨ͕ΔεϚʔτ୐഑ϙετ w "84-BNCEBͷϨΠϠʔԽ w

    αʔόʔϨεͷςετΛ&&ςετʹৼΓ͖Δ w "84-BNCEBͷϩάΛ"84"UIFOBͰݟΔ w ૯ׅ   NJO NJO NJO NJO NJO NJO NJO