File size: 6,316 Bytes
105b369
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
from typing import Optional, Any, Dict, List

from phi.aws.api_client import AwsApiClient
from phi.aws.resource.base import AwsResource
from phi.cli.console import print_info
from phi.utils.log import logger


class EcsCluster(AwsResource):
    """
    Reference:
    - https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ecs.html
    """

    resource_type: Optional[str] = "EcsCluster"
    service_name: str = "ecs"

    # Name of the cluster.
    name: str
    # Name for the cluster.
    # Use name if not provided.
    ecs_cluster_name: Optional[str] = None

    tags: Optional[List[Dict[str, str]]] = None
    # The setting to use when creating a cluster.
    settings: Optional[List[Dict[str, Any]]] = None
    # The execute command configuration for the cluster.
    configuration: Optional[Dict[str, Any]] = None
    # The short name of one or more capacity providers to associate with the cluster.
    # A capacity provider must be associated with a cluster before it can be included as part of the default capacity
    # provider strategy of the cluster or used in a capacity provider strategy when calling the CreateService/RunTask.
    capacity_providers: Optional[List[str]] = None
    # The capacity provider strategy to set as the default for the cluster. After a default capacity provider strategy
    # is set for a cluster, when you call the RunTask or CreateService APIs with no capacity provider strategy or
    # launch type specified, the default capacity provider strategy for the cluster is used.
    default_capacity_provider_strategy: Optional[List[Dict[str, Any]]] = None
    # Use this parameter to set a default Service Connect namespace.
    # After you set a default Service Connect namespace, any new services with Service Connect turned on that are
    # created in the cluster are added as client services in the namespace.
    service_connect_namespace: Optional[str] = None

    def get_ecs_cluster_name(self):
        return self.ecs_cluster_name or self.name

    def _create(self, aws_client: AwsApiClient) -> bool:
        """Creates the EcsCluster

        Args:
            aws_client: The AwsApiClient for the current cluster
        """
        print_info(f"Creating {self.get_resource_type()}: {self.get_resource_name()}")

        # create a dict of args which are not null, otherwise aws type validation fails
        not_null_args: Dict[str, Any] = {}
        if self.tags is not None:
            not_null_args["tags"] = self.tags
        if self.settings is not None:
            not_null_args["settings"] = self.settings
        if self.configuration is not None:
            not_null_args["configuration"] = self.configuration
        if self.capacity_providers is not None:
            not_null_args["capacityProviders"] = self.capacity_providers
        if self.default_capacity_provider_strategy is not None:
            not_null_args["defaultCapacityProviderStrategy"] = self.default_capacity_provider_strategy
        if self.service_connect_namespace is not None:
            not_null_args["serviceConnectDefaults"] = {
                "namespace": self.service_connect_namespace,
            }

        # Create EcsCluster
        service_client = self.get_service_client(aws_client)
        try:
            create_response = service_client.create_cluster(
                clusterName=self.get_ecs_cluster_name(),
                **not_null_args,
            )
            logger.debug(f"EcsCluster: {create_response}")
            resource_dict = create_response.get("cluster", {})

            # Validate resource creation
            if resource_dict is not None:
                self.active_resource = create_response
                return True
        except Exception as e:
            logger.error(f"{self.get_resource_type()} could not be created.")
            logger.error(e)
        return False

    def _read(self, aws_client: AwsApiClient) -> Optional[Any]:
        """Returns the EcsCluster

        Args:
            aws_client: The AwsApiClient for the current cluster
        """
        logger.debug(f"Reading {self.get_resource_type()}: {self.get_resource_name()}")

        from botocore.exceptions import ClientError

        service_client = self.get_service_client(aws_client)
        try:
            cluster_name = self.get_ecs_cluster_name()
            describe_response = service_client.describe_clusters(clusters=[cluster_name])
            logger.debug(f"EcsCluster: {describe_response}")
            resource_list = describe_response.get("clusters", None)

            if resource_list is not None and isinstance(resource_list, list):
                for resource in resource_list:
                    _cluster_identifier = resource.get("clusterName", None)
                    if _cluster_identifier == cluster_name:
                        _cluster_status = resource.get("status", None)
                        if _cluster_status == "ACTIVE":
                            self.active_resource = resource
                            break
        except ClientError as ce:
            logger.debug(f"ClientError: {ce}")
        except Exception as e:
            logger.error(f"Error reading {self.get_resource_type()}.")
            logger.error(e)
        return self.active_resource

    def _delete(self, aws_client: AwsApiClient) -> bool:
        """Deletes the EcsCluster

        Args:
            aws_client: The AwsApiClient for the current cluster
        """
        print_info(f"Deleting {self.get_resource_type()}: {self.get_resource_name()}")

        service_client = self.get_service_client(aws_client)
        self.active_resource = None

        try:
            delete_response = service_client.delete_cluster(cluster=self.get_ecs_cluster_name())
            logger.debug(f"EcsCluster: {delete_response}")
            return True
        except Exception as e:
            logger.error(f"{self.get_resource_type()} could not be deleted.")
            logger.error("Please try again or delete resources manually.")
            logger.error(e)
        return False

    def get_arn(self, aws_client: AwsApiClient) -> Optional[str]:
        tg = self._read(aws_client)
        if tg is None:
            return None
        tg_arn = tg.get("ListenerArn", None)
        return tg_arn