1# Licensed to the Apache Software Foundation (ASF) under one or more
2# contributor license agreements.  See the NOTICE file distributed with
3# this work for additional information regarding copyright ownership.
4# The ASF licenses this file to You under the Apache License, Version 2.0
5# (the "License"); you may not use this file except in compliance with
6# the License.  You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import sys
17
18from libcloud.test import unittest
19
20from libcloud.container.base import ContainerCluster, ContainerImage, Container
21from libcloud.container.drivers.ecs import ElasticContainerDriver
22from libcloud.container.utils.docker import RegistryClient
23
24from libcloud.utils.py3 import httplib
25from libcloud.test.secrets import CONTAINER_PARAMS_ECS
26from libcloud.test.file_fixtures import ContainerFileFixtures
27from libcloud.test import MockHttp
28
29
30class ElasticContainerDriverTestCase(unittest.TestCase):
31
32    def setUp(self):
33        ElasticContainerDriver.connectionCls.conn_class = ECSMockHttp
34        ECSMockHttp.type = None
35        ECSMockHttp.use_param = 'a'
36        ElasticContainerDriver.ecrConnectionClass.conn_class = ECSMockHttp
37
38        self.driver = ElasticContainerDriver(*CONTAINER_PARAMS_ECS)
39
40    def test_list_clusters(self):
41        clusters = self.driver.list_clusters()
42        self.assertEqual(len(clusters), 1)
43        self.assertEqual(clusters[0].id, 'arn:aws:ecs:us-east-1:012345678910:cluster/default')
44        self.assertEqual(clusters[0].name, 'default')
45
46    def test_create_cluster(self):
47        cluster = self.driver.create_cluster('my-cluster')
48        self.assertEqual(cluster.name, 'my-cluster')
49
50    def test_destroy_cluster(self):
51        self.assertTrue(
52            self.driver.destroy_cluster(
53                ContainerCluster(
54                    id='arn:aws:ecs:us-east-1:012345678910:cluster/jim',
55                    name='jim',
56                    driver=self.driver)))
57
58    def test_list_containers(self):
59        containers = self.driver.list_containers()
60        self.assertEqual(len(containers), 1)
61
62    def test_list_containers_for_cluster(self):
63        cluster = self.driver.list_clusters()[0]
64        containers = self.driver.list_containers(cluster=cluster)
65        self.assertEqual(len(containers), 1)
66
67    def test_deploy_container(self):
68        container = self.driver.deploy_container(
69            name='jim',
70            image=ContainerImage(
71                id=None,
72                name='mysql',
73                path='mysql',
74                version=None,
75                driver=self.driver
76            )
77        )
78        self.assertEqual(container.id, 'arn:aws:ecs:ap-southeast-2:647433528374:container/e443d10f-dea3-481e-8a1e-966b9ad4e498')
79
80    def test_get_container(self):
81        container = self.driver.get_container(
82            'arn:aws:ecs:us-east-1:012345678910:container/76c980a8-2454-4a9c-acc4-9eb103117273'
83        )
84        self.assertEqual(container.id, 'arn:aws:ecs:ap-southeast-2:647433528374:container/d56d4e2c-9804-42a7-9f2a-6029cb50d4a2')
85        self.assertEqual(container.name, 'simple-app')
86        self.assertEqual(container.image.name, 'simple-app')
87
88    def test_start_container(self):
89        container = self.driver.start_container(
90            Container(
91                id=None,
92                name=None,
93                image=None,
94                state=None,
95                ip_addresses=None,
96                driver=self.driver,
97                extra={
98                    'taskDefinitionArn': ''
99                }
100            )
101        )
102        self.assertFalse(container is None)
103
104    def test_stop_container(self):
105        container = self.driver.stop_container(
106            Container(
107                id=None,
108                name=None,
109                image=None,
110                state=None,
111                ip_addresses=None,
112                driver=self.driver,
113                extra={
114                    'taskArn': '12345',
115                    'taskDefinitionArn': '123556'
116                }
117            )
118        )
119        self.assertFalse(container is None)
120
121    def test_restart_container(self):
122        container = self.driver.restart_container(
123            Container(
124                id=None,
125                name=None,
126                image=None,
127                state=None,
128                ip_addresses=None,
129                driver=self.driver,
130                extra={
131                    'taskArn': '12345',
132                    'taskDefinitionArn': '123556'
133                }
134            )
135        )
136        self.assertFalse(container is None)
137
138    def test_list_images(self):
139        images = self.driver.list_images('my-images')
140        self.assertEqual(len(images), 1)
141        self.assertEqual(images[0].name, '647433528374.dkr.ecr.region.amazonaws.com/my-images:latest')
142
143    def test_ex_create_service(self):
144        cluster = self.driver.list_clusters()[0]
145        task_definition = self.driver.list_containers()[0].extra['taskDefinitionArn']
146        service = self.driver.ex_create_service(cluster=cluster,
147                                                name='jim',
148                                                task_definition=task_definition)
149        self.assertEqual(service['serviceName'], 'test')
150
151    def test_ex_list_service_arns(self):
152        arns = self.driver.ex_list_service_arns()
153        self.assertEqual(len(arns), 2)
154
155    def test_ex_describe_service(self):
156        arn = self.driver.ex_list_service_arns()[0]
157        service = self.driver.ex_describe_service(arn)
158        self.assertEqual(service['serviceName'], 'test')
159
160    def test_ex_destroy_service(self):
161        arn = self.driver.ex_list_service_arns()[0]
162        service = self.driver.ex_destroy_service(arn)
163        self.assertEqual(service['status'], 'DRAINING')
164
165    def test_ex_get_registry_client(self):
166        client = self.driver.ex_get_registry_client('my-images')
167        self.assertIsInstance(client, RegistryClient)
168
169
170class ECSMockHttp(MockHttp):
171    fixtures = ContainerFileFixtures('ecs')
172    fixture_map = {
173        'DescribeClusters': 'describeclusters.json',
174        'CreateCluster': 'createcluster.json',
175        'DeleteCluster': 'deletecluster.json',
176        'DescribeTasks': 'describetasks.json',
177        'ListTasks': 'listtasks.json',
178        'ListClusters': 'listclusters.json',
179        'RegisterTaskDefinition': 'registertaskdefinition.json',
180        'RunTask': 'runtask.json',
181        'StopTask': 'stoptask.json',
182        'ListImages': 'listimages.json',
183        'DescribeRepositories': 'describerepositories.json',
184        'CreateService': 'createservice.json',
185        'ListServices': 'listservices.json',
186        'DescribeServices': 'describeservices.json',
187        'DeleteService': 'deleteservice.json',
188        'GetAuthorizationToken': 'getauthorizationtoken.json'
189    }
190
191    def root(self, method, url, body, headers):
192        target = headers['x-amz-target']
193
194        # Workaround for host not being correctly set for the tests
195        if '%s' in self.host:
196            self.host = self.host % ('region')
197
198        if target is not None:
199            type = target.split('.')[-1]
200            if type is None or self.fixture_map.get(type) is None:
201                raise AssertionError('Unsupported request type %s' % (target))
202            body = self.fixtures.load(self.fixture_map.get(type))
203        else:
204            raise AssertionError('Unsupported method')
205        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
206
207if __name__ == '__main__':
208    sys.exit(unittest.main())
209