Source code for ecs_composex.cloudmap.cloudmap_x_resources

#  SPDX-License-Identifier: MPL-2.0
#  Copyright 2020-2022 John Mille <john@compose-x.io>

"""
Manage the registration of x-resources into AWS CloudMap namespace
"""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from ecs_composex.common.settings import ComposeXSettings
    from ecs_composex.compose.x_resources.network_x_resources import (
        NetworkXResource,
        DatabaseXResource,
    )
    from ecs_composex.cloudmap.cloudmap_stack import PrivateNamespace

from compose_x_common.compose_x_common import keyisset
from troposphere import NoValue, Ref
from troposphere.servicediscovery import DnsConfig, DnsRecord, Instance, Service

from ecs_composex.common.logging import LOG
from ecs_composex.common.troposphere_tools import (
    add_parameters,
    add_resource,
    add_update_mapping,
)

from .cloudmap_params import PRIVATE_NAMESPACE_ID


[docs]def process_dns_config( namespace: PrivateNamespace, resource: NetworkXResource | DatabaseXResource, dns_settings: dict, settings: ComposeXSettings, service: Service, instance: Instance, ) -> None: """ Process the DnsSettings of the x-cloudmap configuration """ hostname = ( dns_settings["Hostname"] if keyisset("Hostname", dns_settings) else resource.logical_name ) if namespace.zone_name not in hostname: hostname = f"{hostname}.{namespace.zone_name}" record = DnsRecord(Type="CNAME", TTL="15") config = DnsConfig(DnsRecords=[record], NamespaceId=NoValue) setattr(service, "DnsConfig", config) setattr(service, "Name", hostname) if not hasattr(resource, "db_cluster_endpoint_param"): return attribute_pointer = resource.attributes_outputs[resource.db_cluster_endpoint_param] if resource.cfn_resource: add_parameters( namespace.stack.stack_template, [attribute_pointer["ImportParameter"]] ) namespace.stack.Parameters.update( { attribute_pointer["ImportParameter"].title: attribute_pointer[ "ImportValue" ] } ) instance.InstanceAttributes.update( {"AWS_INSTANCE_CNAME": Ref(attribute_pointer["ImportParameter"])} ) else: add_update_mapping( namespace.stack.stack_template, resource.module.mapping_key, settings.mappings[resource.module.mapping_key], ) instance.InstanceAttributes.update( {"AWS_INSTANCE_CNAME": attribute_pointer["ImportValue"]} )
[docs]def process_return_values( namespace: PrivateNamespace, resource, return_values: dict, instance_props: dict, settings, ): """ Processes the ReturnValues attributes to assign to an instance. :param namespace: :param ecs_composex.compose.x_resources.XResource resource: :param dict return_values: :param dict instance_props: :param ecs_composex.common.settings.ComposeXSettings settings: """ for key, value in return_values.items(): for attribute_param in resource.attributes_outputs.keys(): if attribute_param.title == key or ( attribute_param.return_value and attribute_param.return_value == key ): break else: raise KeyError( f"{resource.module.res_key}.{resource.name}" " - ReturnValue {key} not found. Available", [p.title for p in resource.attributes_outputs.keys()], ) attribute_pointer = resource.attributes_outputs[attribute_param] if resource.cfn_resource: add_parameters( namespace.stack.stack_template, [attribute_pointer["ImportParameter"]] ) namespace.stack.Parameters.update( { attribute_pointer["ImportParameter"].title: attribute_pointer[ "ImportValue" ] } ) instance_props["InstanceAttributes"][key] = Ref( attribute_pointer["ImportParameter"] ) else: add_update_mapping( namespace.stack.stack_template, resource.module.mapping_key, settings.mappings[resource.module.mapping_key], ) instance_props["InstanceAttributes"][value] = attribute_pointer[ "ImportValue" ]
[docs]def process_additional_attributes(additional_attributes: dict, instance_props: dict): """ Processes the ReturnValues attributes to assign to an instance. :param dict additional_attributes: :param dict instance_props: """ for key, value in additional_attributes.items(): if key.startswith("AWS_"): continue instance_props["InstanceAttributes"][key] = value
[docs]def handle_resource_cloudmap_settings( namespace: PrivateNamespace, resource, cloudmap_settings: dict, settings ) -> None: """ Function to handle x-cloudmap.{} settings :type namespace: class`ecs_composex.cloudmap.cloudmap_stack.PrivateNamespace` :type resource: class`Union[DatabaseXResource, NetworkXResource]` :type settings: class`ecs_composex.common.settings.ComposeXSettings` """ if cloudmap_settings["Namespace"] != namespace.name: LOG.debug("NAMESPACE DOES NOT MATCH", cloudmap_settings, namespace.name) return if not resource.cfn_resource and not keyisset("ForceRegister", cloudmap_settings): LOG.debug("LOOKUP AND NO FORCE", cloudmap_settings) return resource_service_title = ( f"{resource.module.mapping_key}{resource.logical_name}Service" ) if resource_service_title in namespace.stack.stack_template.resources: LOG.debug("ALREADY BEEN PROCESSED", resource.name) return LOG.debug( "PROCESSING IN HANDLER", resource.module.res_key, resource.name, cloudmap_settings, ) namespace_id_pointer = ( namespace.attributes_outputs[PRIVATE_NAMESPACE_ID]["ImportValue"] if not namespace.cfn_resource else Ref(namespace.cfn_resource) ) service_props = { "Description": f"{resource.name}", "NamespaceId": namespace_id_pointer, "Type": "HTTP", } instance_props = {"InstanceAttributes": {}} if keyisset("ReturnValues", cloudmap_settings): process_return_values( namespace, resource, cloudmap_settings["ReturnValues"], instance_props, settings, ) if keyisset("AdditionalAttributes", cloudmap_settings): process_additional_attributes( cloudmap_settings["AdditionalAttributes"], instance_props ) resource_service = Service(resource_service_title, **service_props) instance_props["ServiceId"] = Ref(resource_service) resource_instance = Instance(f"{resource_service_title}Instance", **instance_props) if keyisset("DnsSettings", cloudmap_settings) and resource.cloudmap_dns_supported: del service_props["Type"] process_dns_config( namespace, resource, cloudmap_settings["DnsSettings"], settings, resource_service, resource_instance, ) elif not resource.cloudmap_dns_supported and keyisset( "DnsSettings", cloudmap_settings ): LOG.warning( f"{resource.module.res_key}.{resource.name}" " does not support DnsSettings for x-cloudmap." ) add_resource(namespace.stack.stack_template, resource_service) add_resource(namespace.stack.stack_template, resource_instance)