Skip to content

Commit

Permalink
remove crhelper polllers and improve exception handling
Browse files Browse the repository at this point in the history
- removed crhelper pollers when creating and updating to wor around
  issue with CloudWatch event payload limit. Build polling is now
  done in the regular create/update handlers

- improved exception handling of subresources to allow cleaner
  rollbacks after a bot is created but something goes wrong with
  the locales, intents, slot types, slots
  • Loading branch information
atoa committed Jun 24, 2021
1 parent 6612b29 commit ad497ce
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 64 deletions.
90 changes: 38 additions & 52 deletions src/lambda_functions/lex_v2_cfn_cr/lambda_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,30 +47,20 @@
HELPER.init_failure(exception)


@HELPER.poll_create
def poll_create(event, _):
"""Poll Create"""
resource_type = event["ResourceType"]
helper_data = event["CrHelperData"]

if resource_type == "Custom::LexBot":
bot_id = helper_data["botId"]
bot_locale_ids = helper_data["botLocaleIds"]
LEX_CUSTOM_RESOURCE.build_bot_locales(bot_id=bot_id, bot_locale_ids=bot_locale_ids)

return bot_id

if resource_type == "Custom::LexBotVersion":
bot_version = helper_data["botVersion"]

return bot_version

if resource_type == "Custom::LexBotAlias":
bot_alias_id = helper_data["botAliasId"]

return bot_alias_id

raise RuntimeError(f"Invalid resource type: {resource_type}")
def wait_for_bot_locales_build(bot_id, bot_locale_ids):
"""Waits for bot locales build"""
# NOTE: not using the cr helper poller functionality since there's a 8K limit
# in the CloudWatch Event input that it uses and medium size bots may trigger
# it during updates as the payload includes JSON encoded current and old
# resource properties
try:
LEX_CUSTOM_RESOURCE.build_bot_locales(
bot_id=bot_id,
bot_locale_ids=bot_locale_ids,
)
except Exception as exception: # pylint: disable=broad-except
HELPER.Status = "FAILED"
HELPER.Reason = str(exception)


@HELPER.create
Expand All @@ -83,7 +73,18 @@ def create_resource(event, _):
response = LEX_CUSTOM_RESOURCE.create_bot(resource_properties=resource_properties)
HELPER.Data = response

return response["botId"]
bot_id = response.get("botId")
bot_locale_ids = response.get("botLocaleIds")
_exception = response.get("_exception")
if bot_id and _exception:
# This allows to delete the bot if an exception was raised after
# the bot was created. E.g. while creating the locale, intents, slot, etc.
HELPER.Status = "FAILED"
HELPER.Reason = _exception
else:
wait_for_bot_locales_build(bot_id=bot_id, bot_locale_ids=bot_locale_ids)

return bot_id

if resource_type == "Custom::LexBotVersion":
response = LEX_CUSTOM_RESOURCE.create_bot_version(resource_properties=resource_properties)
Expand Down Expand Up @@ -173,32 +174,6 @@ def delete_resource(event, _):
raise RuntimeError(f"Invalid resource type: {resource_type}")


@HELPER.poll_update
def poll_update(event, _):
"""Poll Update"""
resource_type = event["ResourceType"]
helper_data = event["CrHelperData"]

if resource_type == "Custom::LexBot":
bot_id = helper_data["botId"]
bot_locale_ids = helper_data["botLocaleIds"]
LEX_CUSTOM_RESOURCE.build_bot_locales(bot_id=bot_id, bot_locale_ids=bot_locale_ids)

return bot_id

if resource_type == "Custom::LexBotVersion":
bot_version = helper_data["botVersion"]

return bot_version

if resource_type == "Custom::LexBotAlias":
bot_alias_id = helper_data["botAliasId"]

return bot_alias_id

raise RuntimeError(f"Invalid resource type: {resource_type}")


@HELPER.update
def update_resource(event, _):
"""Update Resource"""
Expand All @@ -215,7 +190,18 @@ def update_resource(event, _):
)
HELPER.Data = response

return response["botId"]
bot_id = response.get("botId")
bot_locale_ids = response.get("botLocaleIds")
_exception = response.get("_exception")
if bot_id and _exception:
# This allows to delete the bot if an exception was raised after
# the bot was created. E.g. while creating the locale, intents, slot, etc.
HELPER.Status = "FAILED"
HELPER.Reason = _exception
else:
wait_for_bot_locales_build(bot_id=bot_id, bot_locale_ids=bot_locale_ids)

return bot_id

if resource_type == "Custom::LexBotVersion":
# versions are immutable - a new one is created
Expand Down
37 changes: 25 additions & 12 deletions src/lambda_functions/lex_v2_cfn_cr/lex_v2_cfn_cr/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,19 +358,25 @@ def build_bot_locales(
def create_bot(self, resource_properties: Dict[str, Any]) -> Dict[str, Any]:
"""Create Lex V2 Bot"""
bot_id = self._create_bot(resource_properties=resource_properties)
bot_locales = resource_properties[CUSTOM_ATTRIBUTES["botLocales"]]

self._create_bot_locales(
bot_id=bot_id,
bot_locales=bot_locales,
)

bot_locale_ids = [locale["localeId"] for locale in bot_locales]
locale_exeption = {"_exception": ""}
bot_locale_ids = []
try:
bot_locales = resource_properties[CUSTOM_ATTRIBUTES["botLocales"]]
self._create_bot_locales(
bot_id=bot_id,
bot_locales=bot_locales,
)
bot_locale_ids = [locale["localeId"] for locale in bot_locales]
except Exception as exception: # pylint: disable=broad-except
self._logger.error("failed to create locale: %s", exception)
locale_exeption["_exception"] = str(exception)

return {
"botId": bot_id,
"botLocaleIds": bot_locale_ids,
"lastUpdatedDateTime": datetime.now().isoformat(),
**locale_exeption,
}

def delete_bot(self, bot_id: str) -> None:
Expand Down Expand Up @@ -403,16 +409,23 @@ def update_bot(
old_resource_properties=old_resource_properties,
)

bot_locale_ids = self._update_bot_locales(
bot_id=_bot_id,
resource_properties=resource_properties,
old_resource_properties=old_resource_properties,
)
locale_exeption = {"_exception": ""}
bot_locale_ids = []
try:
bot_locale_ids = self._update_bot_locales(
bot_id=_bot_id,
resource_properties=resource_properties,
old_resource_properties=old_resource_properties,
)
except Exception as exception: # pylint: disable=broad-except
self._logger.error("failed to create locale: %s", exception)
locale_exeption["_exception"] = str(exception)

return {
"botId": _bot_id,
"botLocaleIds": bot_locale_ids,
"lastUpdatedDateTime": datetime.now().isoformat(),
**locale_exeption,
}

def wait_for_delete_bot(
Expand Down

0 comments on commit ad497ce

Please sign in to comment.