1import boto.ec2
2import boto.ec2.autoscale
3import boto.ec2.elb
4import boto3
5import pytest
6import sure  # noqa # pylint: disable=unused-import
7from boto3 import Session
8
9from botocore.exceptions import ClientError
10from moto import mock_ec2_deprecated, mock_autoscaling_deprecated, mock_elb_deprecated
11from moto import mock_autoscaling, mock_ec2, mock_elb
12
13from moto.ec2 import ec2_backends
14from tests import EXAMPLE_AMI_ID, EXAMPLE_AMI_ID2
15from uuid import uuid4
16from .test_instances import retrieve_all_instances
17
18
19def test_use_boto_regions():
20    boto_regions = set()
21    for region in Session().get_available_regions("ec2"):
22        boto_regions.add(region)
23    for region in Session().get_available_regions("ec2", partition_name="aws-us-gov"):
24        boto_regions.add(region)
25    for region in Session().get_available_regions("ec2", partition_name="aws-cn"):
26        boto_regions.add(region)
27    moto_regions = set(ec2_backends)
28
29    moto_regions.should.equal(boto_regions)
30
31
32def add_servers_to_region(ami_id, count, region):
33    conn = boto.ec2.connect_to_region(region)
34    for _ in range(count):
35        conn.run_instances(ami_id)
36
37
38def add_servers_to_region_boto3(ami_id, count, region):
39    ec2 = boto3.resource("ec2", region_name=region)
40    return ec2.create_instances(ImageId=ami_id, MinCount=count, MaxCount=count)
41
42
43# Has boto3 equivalent
44@mock_ec2_deprecated
45def test_add_servers_to_a_single_region():
46    region = "ap-northeast-1"
47    add_servers_to_region(EXAMPLE_AMI_ID, 1, region)
48    add_servers_to_region(EXAMPLE_AMI_ID2, 1, region)
49
50    conn = boto.ec2.connect_to_region(region)
51    reservations = conn.get_all_reservations()
52    len(reservations).should.equal(2)
53
54    image_ids = [r.instances[0].image_id for r in reservations]
55    image_ids.should.equal([EXAMPLE_AMI_ID, EXAMPLE_AMI_ID2])
56
57
58@mock_ec2
59def test_add_servers_to_a_single_region_boto3():
60    region = "ap-northeast-1"
61    id_1 = add_servers_to_region_boto3(EXAMPLE_AMI_ID, 1, region)[0].id
62    id_2 = add_servers_to_region_boto3(EXAMPLE_AMI_ID2, 1, region)[0].id
63
64    client = boto3.client("ec2", region_name=region)
65    instances = retrieve_all_instances(client)
66
67    instance1 = [i for i in instances if i["InstanceId"] == id_1][0]
68    instance1["ImageId"].should.equal(EXAMPLE_AMI_ID)
69    instance2 = [i for i in instances if i["InstanceId"] == id_2][0]
70    instance2["ImageId"].should.equal(EXAMPLE_AMI_ID2)
71
72
73# Has boto3 equivalent
74@mock_ec2_deprecated
75def test_add_servers_to_multiple_regions():
76    region1 = "us-east-1"
77    region2 = "ap-northeast-1"
78    add_servers_to_region(EXAMPLE_AMI_ID, 1, region1)
79    add_servers_to_region(EXAMPLE_AMI_ID2, 1, region2)
80
81    us_conn = boto.ec2.connect_to_region(region1)
82    ap_conn = boto.ec2.connect_to_region(region2)
83    us_reservations = us_conn.get_all_reservations()
84    ap_reservations = ap_conn.get_all_reservations()
85
86    len(us_reservations).should.equal(1)
87    len(ap_reservations).should.equal(1)
88
89    us_reservations[0].instances[0].image_id.should.equal(EXAMPLE_AMI_ID)
90    ap_reservations[0].instances[0].image_id.should.equal(EXAMPLE_AMI_ID2)
91
92
93@mock_ec2
94def test_add_servers_to_multiple_regions_boto3():
95    region1 = "us-east-1"
96    region2 = "ap-northeast-1"
97    us_id = add_servers_to_region_boto3(EXAMPLE_AMI_ID, 1, region1)[0].id
98    ap_id = add_servers_to_region_boto3(EXAMPLE_AMI_ID2, 1, region2)[0].id
99
100    us_client = boto3.client("ec2", region_name=region1)
101    ap_client = boto3.client("ec2", region_name=region2)
102    us_instances = retrieve_all_instances(us_client)
103    ap_instances = retrieve_all_instances(ap_client)
104
105    [r["InstanceId"] for r in us_instances].should.contain(us_id)
106    [r["InstanceId"] for r in us_instances].shouldnt.contain(ap_id)
107    [r["InstanceId"] for r in ap_instances].should.contain(ap_id)
108    [r["InstanceId"] for r in ap_instances].shouldnt.contain(us_id)
109
110    us_instance = us_client.describe_instances(InstanceIds=[us_id])["Reservations"][0][
111        "Instances"
112    ][0]
113    us_instance["ImageId"].should.equal(EXAMPLE_AMI_ID)
114    ap_instance = ap_client.describe_instances(InstanceIds=[ap_id])["Reservations"][0][
115        "Instances"
116    ][0]
117    ap_instance["ImageId"].should.equal(EXAMPLE_AMI_ID2)
118
119
120# Has boto3 equivalent
121@mock_autoscaling_deprecated
122@mock_elb_deprecated
123def test_create_autoscaling_group():
124    elb_conn = boto.ec2.elb.connect_to_region("us-east-1")
125    elb_conn.create_load_balancer(
126        "us_test_lb", zones=[], listeners=[(80, 8080, "http")]
127    )
128    elb_conn = boto.ec2.elb.connect_to_region("ap-northeast-1")
129    elb_conn.create_load_balancer(
130        "ap_test_lb", zones=[], listeners=[(80, 8080, "http")]
131    )
132
133    us_conn = boto.ec2.autoscale.connect_to_region("us-east-1")
134    config = boto.ec2.autoscale.LaunchConfiguration(
135        name="us_tester", image_id=EXAMPLE_AMI_ID, instance_type="m1.small"
136    )
137    us_conn.create_launch_configuration(config)
138
139    us_subnet_id = list(ec2_backends["us-east-1"].subnets["us-east-1c"].keys())[0]
140    ap_subnet_id = list(
141        ec2_backends["ap-northeast-1"].subnets["ap-northeast-1a"].keys()
142    )[0]
143    group = boto.ec2.autoscale.AutoScalingGroup(
144        name="us_tester_group",
145        availability_zones=["us-east-1c"],
146        default_cooldown=60,
147        desired_capacity=2,
148        health_check_period=100,
149        health_check_type="EC2",
150        max_size=2,
151        min_size=2,
152        launch_config=config,
153        load_balancers=["us_test_lb"],
154        placement_group="us_test_placement",
155        vpc_zone_identifier=us_subnet_id,
156        termination_policies=["OldestInstance", "NewestInstance"],
157    )
158    us_conn.create_auto_scaling_group(group)
159
160    ap_conn = boto.ec2.autoscale.connect_to_region("ap-northeast-1")
161    config = boto.ec2.autoscale.LaunchConfiguration(
162        name="ap_tester", image_id=EXAMPLE_AMI_ID, instance_type="m1.small"
163    )
164    ap_conn.create_launch_configuration(config)
165
166    group = boto.ec2.autoscale.AutoScalingGroup(
167        name="ap_tester_group",
168        availability_zones=["ap-northeast-1a"],
169        default_cooldown=60,
170        desired_capacity=2,
171        health_check_period=100,
172        health_check_type="EC2",
173        max_size=2,
174        min_size=2,
175        launch_config=config,
176        load_balancers=["ap_test_lb"],
177        placement_group="ap_test_placement",
178        vpc_zone_identifier=ap_subnet_id,
179        termination_policies=["OldestInstance", "NewestInstance"],
180    )
181    ap_conn.create_auto_scaling_group(group)
182
183    len(us_conn.get_all_groups()).should.equal(1)
184    len(ap_conn.get_all_groups()).should.equal(1)
185
186    us_group = us_conn.get_all_groups()[0]
187    us_group.name.should.equal("us_tester_group")
188    list(us_group.availability_zones).should.equal(["us-east-1c"])
189    us_group.desired_capacity.should.equal(2)
190    us_group.max_size.should.equal(2)
191    us_group.min_size.should.equal(2)
192    us_group.vpc_zone_identifier.should.equal(us_subnet_id)
193    us_group.launch_config_name.should.equal("us_tester")
194    us_group.default_cooldown.should.equal(60)
195    us_group.health_check_period.should.equal(100)
196    us_group.health_check_type.should.equal("EC2")
197    list(us_group.load_balancers).should.equal(["us_test_lb"])
198    us_group.placement_group.should.equal("us_test_placement")
199    list(us_group.termination_policies).should.equal(
200        ["OldestInstance", "NewestInstance"]
201    )
202
203    ap_group = ap_conn.get_all_groups()[0]
204    ap_group.name.should.equal("ap_tester_group")
205    list(ap_group.availability_zones).should.equal(["ap-northeast-1a"])
206    ap_group.desired_capacity.should.equal(2)
207    ap_group.max_size.should.equal(2)
208    ap_group.min_size.should.equal(2)
209    ap_group.vpc_zone_identifier.should.equal(ap_subnet_id)
210    ap_group.launch_config_name.should.equal("ap_tester")
211    ap_group.default_cooldown.should.equal(60)
212    ap_group.health_check_period.should.equal(100)
213    ap_group.health_check_type.should.equal("EC2")
214    list(ap_group.load_balancers).should.equal(["ap_test_lb"])
215    ap_group.placement_group.should.equal("ap_test_placement")
216    list(ap_group.termination_policies).should.equal(
217        ["OldestInstance", "NewestInstance"]
218    )
219
220
221@mock_autoscaling
222@mock_elb
223@mock_ec2
224def test_create_autoscaling_group_boto3():
225    regions = [("us-east-1", "c"), ("ap-northeast-1", "a")]
226    for region, zone in regions:
227        a_zone = "{}{}".format(region, zone)
228        asg_name = "{}_tester_group_{}".format(region, str(uuid4())[0:6])
229        lb_name = "{}_lb_{}".format(region, str(uuid4())[0:6])
230        config_name = "{}_tester_{}".format(region, str(uuid4())[0:6])
231
232        elb_client = boto3.client("elb", region_name=region)
233        elb_client.create_load_balancer(
234            LoadBalancerName=lb_name,
235            Listeners=[
236                {"Protocol": "http", "LoadBalancerPort": 80, "InstancePort": 8080}
237            ],
238            AvailabilityZones=[],
239        )
240
241        as_client = boto3.client("autoscaling", region_name=region)
242        as_client.create_launch_configuration(
243            LaunchConfigurationName=config_name,
244            ImageId=EXAMPLE_AMI_ID,
245            InstanceType="m1.small",
246        )
247
248        ec2_client = boto3.client("ec2", region_name=region)
249        subnet_id = ec2_client.describe_subnets(
250            Filters=[{"Name": "availability-zone", "Values": [a_zone]}]
251        )["Subnets"][0]["SubnetId"]
252
253        as_client.create_auto_scaling_group(
254            AutoScalingGroupName=asg_name,
255            AvailabilityZones=[a_zone],
256            DefaultCooldown=60,
257            DesiredCapacity=2,
258            HealthCheckGracePeriod=100,
259            HealthCheckType="EC2",
260            LaunchConfigurationName=config_name,
261            LoadBalancerNames=[lb_name],
262            MinSize=2,
263            MaxSize=2,
264            PlacementGroup="us_test_placement",
265            VPCZoneIdentifier=subnet_id,
266            TerminationPolicies=["OldestInstance", "NewestInstance"],
267        )
268
269        groups = as_client.describe_auto_scaling_groups(
270            AutoScalingGroupNames=[asg_name]
271        )["AutoScalingGroups"]
272        groups.should.have.length_of(1)
273        group = groups[0]
274
275        group["AutoScalingGroupName"].should.equal(asg_name)
276        group["DesiredCapacity"].should.equal(2)
277        group["MaxSize"].should.equal(2)
278        group["MinSize"].should.equal(2)
279        group["VPCZoneIdentifier"].should.equal(subnet_id)
280        group["LaunchConfigurationName"].should.equal(config_name)
281        group["DefaultCooldown"].should.equal(60)
282        group["HealthCheckGracePeriod"].should.equal(100)
283        group["HealthCheckType"].should.equal("EC2")
284        group["LoadBalancerNames"].should.equal([lb_name])
285        group["PlacementGroup"].should.equal("us_test_placement")
286        group["TerminationPolicies"].should.equal(["OldestInstance", "NewestInstance"])
287
288
289@mock_ec2
290def test_describe_regions_dryrun():
291    client = boto3.client("ec2", region_name="us-east-1")
292
293    with pytest.raises(ClientError) as ex:
294        client.describe_regions(DryRun=True)
295    ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
296    ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
297    ex.value.response["Error"]["Message"].should.equal(
298        "An error occurred (DryRunOperation) when calling the DescribeRegions operation: Request would have succeeded, but DryRun flag is set"
299    )
300