"""State module for managing Amazon Elasticache Subnet Groups."""
import copy
from dataclasses import field
from dataclasses import make_dataclass
from typing import Any
from typing import Dict
from typing import List
__contracts__ = ["resource"]
TREQ = {
"present": {
"require": [
"aws.ec2.subnet.present",
],
},
}
[docs]async def present(
hub,
ctx,
name: str,
subnet_ids: List[str],
cache_subnet_group_description: str,
resource_id: str = None,
tags: Dict[str, Any]
or List[
make_dataclass("Tag", [("Key", str), ("Value", str, field(default=None))])
] = None,
) -> Dict[str, Any]:
"""Creates an AWS Elasticache Subnet Group.
Args:
name(str):
An Idem name of the resource
resource_id(str, Optional):
The name of the AWS Elasticache Subnet Group in Amazon Web Services.
cache_subnet_group_description(str):
A description for the cache subnet group.
subnet_ids(list):
A list of VPC subnet IDs for the cache subnet group.
tags(dict or list, Optional):
Dict in the format of ``{tag-key: tag-value}`` or List of tags in the format of
``[{"Key": tag-key, "Value": tag-value}]`` to associate with the subnet group.
* Key (*str*):
The key of the tag.
* Value (*str*):
The value of the tag.
Request Syntax:
.. code-block:: sls
[idem_test_aws_elasticache_cache_subnet_group]:
aws.elasticache.cache_subnet_group.present:
- name: 'string'
- resource_id: 'string'
- cache_subnet_group_description: 'string'
- subnet_id:
- 'string'
- tags:
- Key: 'string'
Value: 'string'
Returns:
Dict[str, Any]
Examples:
.. code-block:: sls
idem_test_aws_elasticache_cache_subnet_group:
aws.elasticache.cache_subnet_group.present:
- name: 'idem_test_cache_subnet_group'
- cache_subnet_group_description: 'My Elasticache Subnet Group'
- subnet_id:
- 'subnet-12345678'
- tags:
- Key: 'provider'
Value: 'idem'
"""
result = dict(comment=[], name=name, old_state=None, new_state=None, result=True)
before = None
resource_updated = False
are_tags_updated = False
resource_arn = str
if resource_id:
before = await hub.exec.boto3.client.elasticache.describe_cache_subnet_groups(
ctx, CacheSubnetGroupName=resource_id
)
if isinstance(tags, List):
tags = hub.tool.aws.tag_utils.convert_tag_list_to_dict(tags)
try:
if before and before["result"] and before["ret"]["CacheSubnetGroups"]:
convert_ret = await hub.tool.aws.elasticache.conversion_utils.convert_raw_elasticache_subnet_to_present_async(
ctx=ctx,
raw_resource=before["ret"]["CacheSubnetGroups"][0],
idem_resource_name=name,
)
result["result"] = convert_ret["result"]
if not result["result"]:
result["comment"] += convert_ret["comment"]
result["old_state"] = convert_ret["ret"]
plan_state = copy.deepcopy(result["old_state"])
if cache_subnet_group_description != result["old_state"].get(
"cache_subnet_group_description"
) or not hub.tool.aws.state_comparison_utils.are_lists_identical(
subnet_ids, result["old_state"].get("subnet_ids")
):
if not ctx.get("test", False):
update_ret = await hub.exec.boto3.client.elasticache.modify_cache_subnet_group(
ctx=ctx,
CacheSubnetGroupName=name,
CacheSubnetGroupDescription=cache_subnet_group_description,
SubnetIds=subnet_ids,
)
result["comment"] += update_ret["comment"]
result["result"] = update_ret["result"]
resource_updated = resource_updated or bool(update_ret["ret"])
else:
if cache_subnet_group_description is not None:
plan_state[
"cache_subnet_group_description"
] = cache_subnet_group_description
if subnet_ids is not None:
plan_state["subnet_ids"] = subnet_ids
resource_arn = before["ret"]["CacheSubnetGroups"][0]["ARN"]
if tags is not None and tags != result["old_state"].get("tags"):
# Update tags
update_ret = (
await hub.tool.aws.elasticache.elasticache_utils.update_tags(
ctx=ctx,
resource_arn=resource_arn,
old_tags=result["old_state"].get("tags"),
new_tags=tags,
)
)
result["comment"] += update_ret["comment"]
result["result"] = result["result"] and update_ret["result"]
are_tags_updated = bool(update_ret["result"])
resource_updated = resource_updated or are_tags_updated
if ctx.get("test", False) and are_tags_updated:
plan_state["tags"] = update_ret["ret"]
result["comment"] += [
f"Would update tags for aws.elasticache.cache_subnet_group {name}"
]
else:
if ctx.get("test", False):
result["new_state"] = hub.tool.aws.test_state_utils.generate_test_state(
enforced_state={},
desired_state={
"name": name,
"cache_subnet_group_description:": cache_subnet_group_description,
"subnet_ids": subnet_ids,
"tags": tags,
},
)
result["comment"] = hub.tool.aws.comment_utils.would_create_comment(
resource_type="aws.elasticache.cache_subnet_group", name=name
)
return result
ret = await hub.exec.boto3.client.elasticache.create_cache_subnet_group(
ctx,
CacheSubnetGroupName=name,
CacheSubnetGroupDescription=cache_subnet_group_description,
SubnetIds=subnet_ids,
Tags=hub.tool.aws.tag_utils.convert_tag_dict_to_list(tags)
if tags
else None,
)
resource_id = name
result["result"] = ret["result"]
if not result["result"]:
result["comment"] = ret["comment"]
return result
resource_arn = ret["ret"]["CacheSubnetGroup"]["ARN"]
result["comment"] = hub.tool.aws.comment_utils.create_comment(
resource_type="aws.elasticache.cache_subnet_group", name=name
)
except hub.tool.boto3.exception.ClientError as e:
result["result"] = False
result["comment"] += [f"{e.__class__.__name__}: {e}"]
try:
if ctx.get("test", False):
result["new_state"] = plan_state
elif (not before) or resource_updated:
after = (
await hub.exec.boto3.client.elasticache.describe_cache_subnet_groups(
ctx, CacheSubnetGroupName=resource_id
)
)
if after and after.get("ret"):
convert_ret = await hub.tool.aws.elasticache.conversion_utils.convert_raw_elasticache_subnet_to_present_async(
ctx=ctx,
raw_resource=after["ret"]["CacheSubnetGroups"][0],
idem_resource_name=name,
)
result["result"] = convert_ret["result"]
if not result["result"]:
result["comment"] += convert_ret["comment"]
result["new_state"] = convert_ret.get("ret")
else:
result["result"] = result["result"] and after["result"]
if not result["result"]:
result["comment"] += after["comment"]
return result
else:
result["new_state"] = copy.deepcopy(result["old_state"])
except Exception as e:
result["comment"] += [str(e)]
result["result"] = False
return result
[docs]async def absent(hub, ctx, name: str, resource_id: str = None) -> Dict[str, Any]:
"""Deletes the specified AWS Elasticache Subnet Group.
.. warning::
You cannot delete a default cache subnet group or one that is associated with any clusters.
Args:
name(str):
An Idem name of the resource.
resource_id(str, Optional):
The name of the AWS Elasticache Subnet Group in Amazon Web Services.
.. warning::
Idem automatically considers this resource being absent if this field is not specified.
Request Syntax:
.. code-block:: sls
[idem_test_aws_elasticache_cache_subnet_group]:
aws.elasticache.cache_subnet_group.absent:
- name: 'string'
- resource_id: 'string'
Returns:
Dict[str, Any]
Examples:
.. code-block:: sls
idem_test_aws_elasticache_cache_subnet_group:
aws.elasticache.cache_subnet_group.absent:
- name: 'idem_test_cache_subnet_group'
- resource_id: 'my-subnet-group'
"""
result = dict(comment=[], name=name, old_state=None, new_state=None, result=True)
if not resource_id:
result["comment"] = hub.tool.aws.comment_utils.already_absent_comment(
resource_type="aws.elasticache.cache_subnet_group", name=name
)
return result
before = await hub.exec.boto3.client.elasticache.describe_cache_subnet_groups(
ctx, CacheSubnetGroupName=resource_id
)
if not before or not before["result"] or not before["ret"].get("CacheSubnetGroups"):
result["comment"] = hub.tool.aws.comment_utils.already_absent_comment(
resource_type="aws.elasticache.cache_subnet_group", name=name
)
return result
else:
convert_ret = await hub.tool.aws.elasticache.conversion_utils.convert_raw_elasticache_subnet_to_present_async(
ctx=ctx,
raw_resource=before["ret"]["CacheSubnetGroups"][0],
idem_resource_name=name,
)
result["result"] = convert_ret["result"]
if not result["result"]:
result["comment"] += convert_ret["comment"]
result["old_state"] = convert_ret["ret"]
if ctx.get("test", False):
result["comment"] = hub.tool.aws.comment_utils.would_delete_comment(
resource_type="aws.elasticache.cache_subnet_group", name=name
)
return result
try:
ret = await hub.exec.boto3.client.elasticache.delete_cache_subnet_group(
ctx, CacheSubnetGroupName=resource_id
)
result["result"] = ret["result"]
if not result["result"]:
result["comment"] = ret["comment"]
return result
result["comment"] = hub.tool.aws.comment_utils.delete_comment(
resource_type="aws.elasticache.cache_subnet_group", name=name
)
except hub.tool.boto3.exception.ClientError as e:
result["comment"] += [f"{e.__class__.__name__}: {e}"]
return result
[docs]async def describe(hub, ctx) -> Dict[str, Dict[str, Any]]:
"""Describes Elasticache Subnet Groups in a way that can be recreated/managed with the corresponding "present" function.
Returns:
Dict[str, Dict[str, Any]]
Examples:
.. code-block:: bash
$ idem describe aws.elasticache.cache_subnet_group
"""
result = {}
ret = await hub.exec.boto3.client.elasticache.describe_cache_subnet_groups(ctx)
if not ret["result"]:
hub.log.warning(f"Could not describe cache_subnet_groups {ret['comment']}")
return {}
for resource in ret["ret"]["CacheSubnetGroups"]:
resource_id = resource.get("CacheSubnetGroupName")
convert_ret = await hub.tool.aws.elasticache.conversion_utils.convert_raw_elasticache_subnet_to_present_async(
ctx=ctx,
raw_resource=resource,
idem_resource_name=resource_id,
)
if not convert_ret["result"]:
hub.log.warning(
f"Could not describe elasticache subnet group '{resource_id}' with error {convert_ret['comment']}"
)
continue
resource_translated = convert_ret.get("ret")
result[resource_id] = {
"aws.elasticache.cache_subnet_group.present": [
{parameter_key: parameter_value}
for parameter_key, parameter_value in resource_translated.items()
]
}
return result