Autoscaling instance azs (#2030)
* Add instance AZ support in autoscaling * Resolve py36-py27 format string error in test_autoscaling
This commit is contained in:
parent
fb2a76fd66
commit
868d0107bf
@ -1,4 +1,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
from boto.ec2.blockdevicemapping import BlockDeviceType, BlockDeviceMapping
|
from boto.ec2.blockdevicemapping import BlockDeviceType, BlockDeviceMapping
|
||||||
from moto.compat import OrderedDict
|
from moto.compat import OrderedDict
|
||||||
from moto.core import BaseBackend, BaseModel
|
from moto.core import BaseBackend, BaseModel
|
||||||
@ -159,13 +162,7 @@ class FakeAutoScalingGroup(BaseModel):
|
|||||||
self.autoscaling_backend = autoscaling_backend
|
self.autoscaling_backend = autoscaling_backend
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
if not availability_zones and not vpc_zone_identifier:
|
self._set_azs_and_vpcs(availability_zones, vpc_zone_identifier)
|
||||||
raise AutoscalingClientError(
|
|
||||||
"ValidationError",
|
|
||||||
"At least one Availability Zone or VPC Subnet is required."
|
|
||||||
)
|
|
||||||
self.availability_zones = availability_zones
|
|
||||||
self.vpc_zone_identifier = vpc_zone_identifier
|
|
||||||
|
|
||||||
self.max_size = max_size
|
self.max_size = max_size
|
||||||
self.min_size = min_size
|
self.min_size = min_size
|
||||||
@ -188,6 +185,35 @@ class FakeAutoScalingGroup(BaseModel):
|
|||||||
self.tags = tags if tags else []
|
self.tags = tags if tags else []
|
||||||
self.set_desired_capacity(desired_capacity)
|
self.set_desired_capacity(desired_capacity)
|
||||||
|
|
||||||
|
def _set_azs_and_vpcs(self, availability_zones, vpc_zone_identifier, update=False):
|
||||||
|
# for updates, if only AZs are provided, they must not clash with
|
||||||
|
# the AZs of existing VPCs
|
||||||
|
if update and availability_zones and not vpc_zone_identifier:
|
||||||
|
vpc_zone_identifier = self.vpc_zone_identifier
|
||||||
|
|
||||||
|
if vpc_zone_identifier:
|
||||||
|
# extract azs for vpcs
|
||||||
|
subnet_ids = vpc_zone_identifier.split(',')
|
||||||
|
subnets = self.autoscaling_backend.ec2_backend.get_all_subnets(subnet_ids=subnet_ids)
|
||||||
|
vpc_zones = [subnet.availability_zone for subnet in subnets]
|
||||||
|
|
||||||
|
if availability_zones and set(availability_zones) != set(vpc_zones):
|
||||||
|
raise AutoscalingClientError(
|
||||||
|
"ValidationError",
|
||||||
|
"The availability zones of the specified subnets and the Auto Scaling group do not match",
|
||||||
|
)
|
||||||
|
availability_zones = vpc_zones
|
||||||
|
elif not availability_zones:
|
||||||
|
if not update:
|
||||||
|
raise AutoscalingClientError(
|
||||||
|
"ValidationError",
|
||||||
|
"At least one Availability Zone or VPC Subnet is required."
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
self.availability_zones = availability_zones
|
||||||
|
self.vpc_zone_identifier = vpc_zone_identifier
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
|
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
|
||||||
properties = cloudformation_json['Properties']
|
properties = cloudformation_json['Properties']
|
||||||
@ -246,8 +272,8 @@ class FakeAutoScalingGroup(BaseModel):
|
|||||||
health_check_period, health_check_type,
|
health_check_period, health_check_type,
|
||||||
placement_group, termination_policies,
|
placement_group, termination_policies,
|
||||||
new_instances_protected_from_scale_in=None):
|
new_instances_protected_from_scale_in=None):
|
||||||
if availability_zones:
|
self._set_azs_and_vpcs(availability_zones, vpc_zone_identifier, update=True)
|
||||||
self.availability_zones = availability_zones
|
|
||||||
if max_size is not None:
|
if max_size is not None:
|
||||||
self.max_size = max_size
|
self.max_size = max_size
|
||||||
if min_size is not None:
|
if min_size is not None:
|
||||||
@ -257,8 +283,6 @@ class FakeAutoScalingGroup(BaseModel):
|
|||||||
self.launch_config = self.autoscaling_backend.launch_configurations[
|
self.launch_config = self.autoscaling_backend.launch_configurations[
|
||||||
launch_config_name]
|
launch_config_name]
|
||||||
self.launch_config_name = launch_config_name
|
self.launch_config_name = launch_config_name
|
||||||
if vpc_zone_identifier is not None:
|
|
||||||
self.vpc_zone_identifier = vpc_zone_identifier
|
|
||||||
if health_check_period is not None:
|
if health_check_period is not None:
|
||||||
self.health_check_period = health_check_period
|
self.health_check_period = health_check_period
|
||||||
if health_check_type is not None:
|
if health_check_type is not None:
|
||||||
@ -319,7 +343,8 @@ class FakeAutoScalingGroup(BaseModel):
|
|||||||
self.launch_config.user_data,
|
self.launch_config.user_data,
|
||||||
self.launch_config.security_groups,
|
self.launch_config.security_groups,
|
||||||
instance_type=self.launch_config.instance_type,
|
instance_type=self.launch_config.instance_type,
|
||||||
tags={'instance': propagated_tags}
|
tags={'instance': propagated_tags},
|
||||||
|
placement=random.choice(self.availability_zones),
|
||||||
)
|
)
|
||||||
for instance in reservation.instances:
|
for instance in reservation.instances:
|
||||||
instance.autoscaling_group = self
|
instance.autoscaling_group = self
|
||||||
|
@ -499,7 +499,7 @@ DESCRIBE_AUTOSCALING_GROUPS_TEMPLATE = """<DescribeAutoScalingGroupsResponse xml
|
|||||||
{% for instance_state in group.instance_states %}
|
{% for instance_state in group.instance_states %}
|
||||||
<member>
|
<member>
|
||||||
<HealthStatus>{{ instance_state.health_status }}</HealthStatus>
|
<HealthStatus>{{ instance_state.health_status }}</HealthStatus>
|
||||||
<AvailabilityZone>us-east-1e</AvailabilityZone>
|
<AvailabilityZone>{{ instance_state.instance.placement }}</AvailabilityZone>
|
||||||
<InstanceId>{{ instance_state.instance.id }}</InstanceId>
|
<InstanceId>{{ instance_state.instance.id }}</InstanceId>
|
||||||
<LaunchConfigurationName>{{ group.launch_config_name }}</LaunchConfigurationName>
|
<LaunchConfigurationName>{{ group.launch_config_name }}</LaunchConfigurationName>
|
||||||
<LifecycleState>{{ instance_state.lifecycle_state }}</LifecycleState>
|
<LifecycleState>{{ instance_state.lifecycle_state }}</LifecycleState>
|
||||||
@ -585,7 +585,7 @@ DESCRIBE_AUTOSCALING_INSTANCES_TEMPLATE = """<DescribeAutoScalingInstancesRespon
|
|||||||
<member>
|
<member>
|
||||||
<HealthStatus>{{ instance_state.health_status }}</HealthStatus>
|
<HealthStatus>{{ instance_state.health_status }}</HealthStatus>
|
||||||
<AutoScalingGroupName>{{ instance_state.instance.autoscaling_group.name }}</AutoScalingGroupName>
|
<AutoScalingGroupName>{{ instance_state.instance.autoscaling_group.name }}</AutoScalingGroupName>
|
||||||
<AvailabilityZone>us-east-1e</AvailabilityZone>
|
<AvailabilityZone>{{ instance_state.instance.placement }}</AvailabilityZone>
|
||||||
<InstanceId>{{ instance_state.instance.id }}</InstanceId>
|
<InstanceId>{{ instance_state.instance.id }}</InstanceId>
|
||||||
<LaunchConfigurationName>{{ instance_state.instance.autoscaling_group.launch_config_name }}</LaunchConfigurationName>
|
<LaunchConfigurationName>{{ instance_state.instance.autoscaling_group.launch_config_name }}</LaunchConfigurationName>
|
||||||
<LifecycleState>{{ instance_state.lifecycle_state }}</LifecycleState>
|
<LifecycleState>{{ instance_state.lifecycle_state }}</LifecycleState>
|
||||||
|
@ -32,7 +32,7 @@ def test_create_autoscaling_group():
|
|||||||
|
|
||||||
group = AutoScalingGroup(
|
group = AutoScalingGroup(
|
||||||
name='tester_group',
|
name='tester_group',
|
||||||
availability_zones=['us-east-1c', 'us-east-1b'],
|
availability_zones=['us-east-1a', 'us-east-1b'],
|
||||||
default_cooldown=60,
|
default_cooldown=60,
|
||||||
desired_capacity=2,
|
desired_capacity=2,
|
||||||
health_check_period=100,
|
health_check_period=100,
|
||||||
@ -42,7 +42,10 @@ def test_create_autoscaling_group():
|
|||||||
launch_config=config,
|
launch_config=config,
|
||||||
load_balancers=["test_lb"],
|
load_balancers=["test_lb"],
|
||||||
placement_group="test_placement",
|
placement_group="test_placement",
|
||||||
vpc_zone_identifier=mocked_networking['subnet1'],
|
vpc_zone_identifier="{subnet1},{subnet2}".format(
|
||||||
|
subnet1=mocked_networking['subnet1'],
|
||||||
|
subnet2=mocked_networking['subnet2'],
|
||||||
|
),
|
||||||
termination_policies=["OldestInstance", "NewestInstance"],
|
termination_policies=["OldestInstance", "NewestInstance"],
|
||||||
tags=[Tag(
|
tags=[Tag(
|
||||||
resource_id='tester_group',
|
resource_id='tester_group',
|
||||||
@ -57,12 +60,15 @@ def test_create_autoscaling_group():
|
|||||||
group = conn.get_all_groups()[0]
|
group = conn.get_all_groups()[0]
|
||||||
group.name.should.equal('tester_group')
|
group.name.should.equal('tester_group')
|
||||||
set(group.availability_zones).should.equal(
|
set(group.availability_zones).should.equal(
|
||||||
set(['us-east-1c', 'us-east-1b']))
|
set(['us-east-1a', 'us-east-1b']))
|
||||||
group.desired_capacity.should.equal(2)
|
group.desired_capacity.should.equal(2)
|
||||||
group.max_size.should.equal(2)
|
group.max_size.should.equal(2)
|
||||||
group.min_size.should.equal(2)
|
group.min_size.should.equal(2)
|
||||||
group.instances.should.have.length_of(2)
|
group.instances.should.have.length_of(2)
|
||||||
group.vpc_zone_identifier.should.equal(mocked_networking['subnet1'])
|
group.vpc_zone_identifier.should.equal("{subnet1},{subnet2}".format(
|
||||||
|
subnet1=mocked_networking['subnet1'],
|
||||||
|
subnet2=mocked_networking['subnet2'],
|
||||||
|
))
|
||||||
group.launch_config_name.should.equal('tester')
|
group.launch_config_name.should.equal('tester')
|
||||||
group.default_cooldown.should.equal(60)
|
group.default_cooldown.should.equal(60)
|
||||||
group.health_check_period.should.equal(100)
|
group.health_check_period.should.equal(100)
|
||||||
@ -109,7 +115,7 @@ def test_create_autoscaling_groups_defaults():
|
|||||||
group.launch_config_name.should.equal('tester')
|
group.launch_config_name.should.equal('tester')
|
||||||
|
|
||||||
# Defaults
|
# Defaults
|
||||||
list(group.availability_zones).should.equal([])
|
list(group.availability_zones).should.equal(['us-east-1a']) # subnet1
|
||||||
group.desired_capacity.should.equal(2)
|
group.desired_capacity.should.equal(2)
|
||||||
group.vpc_zone_identifier.should.equal(mocked_networking['subnet1'])
|
group.vpc_zone_identifier.should.equal(mocked_networking['subnet1'])
|
||||||
group.default_cooldown.should.equal(300)
|
group.default_cooldown.should.equal(300)
|
||||||
@ -217,7 +223,6 @@ def test_autoscaling_update():
|
|||||||
|
|
||||||
group = AutoScalingGroup(
|
group = AutoScalingGroup(
|
||||||
name='tester_group',
|
name='tester_group',
|
||||||
availability_zones=['us-east-1c', 'us-east-1b'],
|
|
||||||
desired_capacity=2,
|
desired_capacity=2,
|
||||||
max_size=2,
|
max_size=2,
|
||||||
min_size=2,
|
min_size=2,
|
||||||
@ -227,13 +232,16 @@ def test_autoscaling_update():
|
|||||||
conn.create_auto_scaling_group(group)
|
conn.create_auto_scaling_group(group)
|
||||||
|
|
||||||
group = conn.get_all_groups()[0]
|
group = conn.get_all_groups()[0]
|
||||||
|
group.availability_zones.should.equal(['us-east-1a'])
|
||||||
group.vpc_zone_identifier.should.equal(mocked_networking['subnet1'])
|
group.vpc_zone_identifier.should.equal(mocked_networking['subnet1'])
|
||||||
|
|
||||||
group.vpc_zone_identifier = 'subnet-5678efgh'
|
group.availability_zones = ['us-east-1b']
|
||||||
|
group.vpc_zone_identifier = mocked_networking['subnet2']
|
||||||
group.update()
|
group.update()
|
||||||
|
|
||||||
group = conn.get_all_groups()[0]
|
group = conn.get_all_groups()[0]
|
||||||
group.vpc_zone_identifier.should.equal('subnet-5678efgh')
|
group.availability_zones.should.equal(['us-east-1b'])
|
||||||
|
group.vpc_zone_identifier.should.equal(mocked_networking['subnet2'])
|
||||||
|
|
||||||
|
|
||||||
@mock_autoscaling_deprecated
|
@mock_autoscaling_deprecated
|
||||||
@ -249,7 +257,7 @@ def test_autoscaling_tags_update():
|
|||||||
|
|
||||||
group = AutoScalingGroup(
|
group = AutoScalingGroup(
|
||||||
name='tester_group',
|
name='tester_group',
|
||||||
availability_zones=['us-east-1c', 'us-east-1b'],
|
availability_zones=['us-east-1a'],
|
||||||
desired_capacity=2,
|
desired_capacity=2,
|
||||||
max_size=2,
|
max_size=2,
|
||||||
min_size=2,
|
min_size=2,
|
||||||
@ -309,7 +317,7 @@ def test_autoscaling_group_delete():
|
|||||||
@mock_autoscaling_deprecated
|
@mock_autoscaling_deprecated
|
||||||
def test_autoscaling_group_describe_instances():
|
def test_autoscaling_group_describe_instances():
|
||||||
mocked_networking = setup_networking_deprecated()
|
mocked_networking = setup_networking_deprecated()
|
||||||
conn = boto.connect_autoscale()
|
conn = boto.ec2.autoscale.connect_to_region('us-east-1')
|
||||||
config = LaunchConfiguration(
|
config = LaunchConfiguration(
|
||||||
name='tester',
|
name='tester',
|
||||||
image_id='ami-abcd1234',
|
image_id='ami-abcd1234',
|
||||||
@ -332,7 +340,7 @@ def test_autoscaling_group_describe_instances():
|
|||||||
instances[0].health_status.should.equal('Healthy')
|
instances[0].health_status.should.equal('Healthy')
|
||||||
autoscale_instance_ids = [instance.instance_id for instance in instances]
|
autoscale_instance_ids = [instance.instance_id for instance in instances]
|
||||||
|
|
||||||
ec2_conn = boto.connect_ec2()
|
ec2_conn = boto.ec2.connect_to_region('us-east-1')
|
||||||
reservations = ec2_conn.get_all_instances()
|
reservations = ec2_conn.get_all_instances()
|
||||||
instances = reservations[0].instances
|
instances = reservations[0].instances
|
||||||
instances.should.have.length_of(2)
|
instances.should.have.length_of(2)
|
||||||
@ -355,7 +363,7 @@ def test_set_desired_capacity_up():
|
|||||||
|
|
||||||
group = AutoScalingGroup(
|
group = AutoScalingGroup(
|
||||||
name='tester_group',
|
name='tester_group',
|
||||||
availability_zones=['us-east-1c', 'us-east-1b'],
|
availability_zones=['us-east-1a'],
|
||||||
desired_capacity=2,
|
desired_capacity=2,
|
||||||
max_size=2,
|
max_size=2,
|
||||||
min_size=2,
|
min_size=2,
|
||||||
@ -391,7 +399,7 @@ def test_set_desired_capacity_down():
|
|||||||
|
|
||||||
group = AutoScalingGroup(
|
group = AutoScalingGroup(
|
||||||
name='tester_group',
|
name='tester_group',
|
||||||
availability_zones=['us-east-1c', 'us-east-1b'],
|
availability_zones=['us-east-1a'],
|
||||||
desired_capacity=2,
|
desired_capacity=2,
|
||||||
max_size=2,
|
max_size=2,
|
||||||
min_size=2,
|
min_size=2,
|
||||||
@ -427,7 +435,7 @@ def test_set_desired_capacity_the_same():
|
|||||||
|
|
||||||
group = AutoScalingGroup(
|
group = AutoScalingGroup(
|
||||||
name='tester_group',
|
name='tester_group',
|
||||||
availability_zones=['us-east-1c', 'us-east-1b'],
|
availability_zones=['us-east-1a'],
|
||||||
desired_capacity=2,
|
desired_capacity=2,
|
||||||
max_size=2,
|
max_size=2,
|
||||||
min_size=2,
|
min_size=2,
|
||||||
@ -739,8 +747,12 @@ def test_describe_autoscaling_groups_boto3():
|
|||||||
response['ResponseMetadata']['HTTPStatusCode'].should.equal(200)
|
response['ResponseMetadata']['HTTPStatusCode'].should.equal(200)
|
||||||
group = response['AutoScalingGroups'][0]
|
group = response['AutoScalingGroups'][0]
|
||||||
group['AutoScalingGroupName'].should.equal('test_asg')
|
group['AutoScalingGroupName'].should.equal('test_asg')
|
||||||
|
group['AvailabilityZones'].should.equal(['us-east-1a'])
|
||||||
|
group['VPCZoneIdentifier'].should.equal(mocked_networking['subnet1'])
|
||||||
group['NewInstancesProtectedFromScaleIn'].should.equal(True)
|
group['NewInstancesProtectedFromScaleIn'].should.equal(True)
|
||||||
group['Instances'][0]['ProtectedFromScaleIn'].should.equal(True)
|
for instance in group['Instances']:
|
||||||
|
instance['AvailabilityZone'].should.equal('us-east-1a')
|
||||||
|
instance['ProtectedFromScaleIn'].should.equal(True)
|
||||||
|
|
||||||
|
|
||||||
@mock_autoscaling
|
@mock_autoscaling
|
||||||
@ -771,6 +783,7 @@ def test_describe_autoscaling_instances_boto3():
|
|||||||
response = client.describe_auto_scaling_instances(InstanceIds=instance_ids)
|
response = client.describe_auto_scaling_instances(InstanceIds=instance_ids)
|
||||||
for instance in response['AutoScalingInstances']:
|
for instance in response['AutoScalingInstances']:
|
||||||
instance['AutoScalingGroupName'].should.equal('test_asg')
|
instance['AutoScalingGroupName'].should.equal('test_asg')
|
||||||
|
instance['AvailabilityZone'].should.equal('us-east-1a')
|
||||||
instance['ProtectedFromScaleIn'].should.equal(True)
|
instance['ProtectedFromScaleIn'].should.equal(True)
|
||||||
|
|
||||||
|
|
||||||
@ -794,6 +807,10 @@ def test_update_autoscaling_group_boto3():
|
|||||||
_ = client.update_auto_scaling_group(
|
_ = client.update_auto_scaling_group(
|
||||||
AutoScalingGroupName='test_asg',
|
AutoScalingGroupName='test_asg',
|
||||||
MinSize=1,
|
MinSize=1,
|
||||||
|
VPCZoneIdentifier="{subnet1},{subnet2}".format(
|
||||||
|
subnet1=mocked_networking['subnet1'],
|
||||||
|
subnet2=mocked_networking['subnet2'],
|
||||||
|
),
|
||||||
NewInstancesProtectedFromScaleIn=False,
|
NewInstancesProtectedFromScaleIn=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -802,6 +819,7 @@ def test_update_autoscaling_group_boto3():
|
|||||||
)
|
)
|
||||||
group = response['AutoScalingGroups'][0]
|
group = response['AutoScalingGroups'][0]
|
||||||
group['MinSize'].should.equal(1)
|
group['MinSize'].should.equal(1)
|
||||||
|
set(group['AvailabilityZones']).should.equal({'us-east-1a', 'us-east-1b'})
|
||||||
group['NewInstancesProtectedFromScaleIn'].should.equal(False)
|
group['NewInstancesProtectedFromScaleIn'].should.equal(False)
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ def test_detach_all_target_groups():
|
|||||||
MaxSize=INSTANCE_COUNT,
|
MaxSize=INSTANCE_COUNT,
|
||||||
DesiredCapacity=INSTANCE_COUNT,
|
DesiredCapacity=INSTANCE_COUNT,
|
||||||
TargetGroupARNs=[target_group_arn],
|
TargetGroupARNs=[target_group_arn],
|
||||||
VPCZoneIdentifier=mocked_networking['vpc'])
|
VPCZoneIdentifier=mocked_networking['subnet1'])
|
||||||
|
|
||||||
response = client.describe_load_balancer_target_groups(
|
response = client.describe_load_balancer_target_groups(
|
||||||
AutoScalingGroupName='test_asg')
|
AutoScalingGroupName='test_asg')
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import boto
|
import boto
|
||||||
import boto3
|
import boto3
|
||||||
|
from boto import vpc as boto_vpc
|
||||||
from moto import mock_ec2, mock_ec2_deprecated
|
from moto import mock_ec2, mock_ec2_deprecated
|
||||||
|
|
||||||
|
|
||||||
@ -19,9 +20,14 @@ def setup_networking():
|
|||||||
|
|
||||||
@mock_ec2_deprecated
|
@mock_ec2_deprecated
|
||||||
def setup_networking_deprecated():
|
def setup_networking_deprecated():
|
||||||
conn = boto.connect_vpc()
|
conn = boto_vpc.connect_to_region('us-east-1')
|
||||||
vpc = conn.create_vpc("10.11.0.0/16")
|
vpc = conn.create_vpc("10.11.0.0/16")
|
||||||
subnet1 = conn.create_subnet(vpc.id, "10.11.1.0/24")
|
subnet1 = conn.create_subnet(
|
||||||
subnet2 = conn.create_subnet(vpc.id, "10.11.2.0/24")
|
vpc.id,
|
||||||
|
"10.11.1.0/24",
|
||||||
|
availability_zone='us-east-1a')
|
||||||
|
subnet2 = conn.create_subnet(
|
||||||
|
vpc.id,
|
||||||
|
"10.11.2.0/24",
|
||||||
|
availability_zone='us-east-1b')
|
||||||
return {'vpc': vpc.id, 'subnet1': subnet1.id, 'subnet2': subnet2.id}
|
return {'vpc': vpc.id, 'subnet1': subnet1.id, 'subnet2': subnet2.id}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ from moto import mock_ec2_deprecated, mock_ec2
|
|||||||
|
|
||||||
@mock_ec2_deprecated
|
@mock_ec2_deprecated
|
||||||
def test_create_and_delete_volume():
|
def test_create_and_delete_volume():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.ec2.connect_to_region("us-east-1")
|
||||||
volume = conn.create_volume(80, "us-east-1a")
|
volume = conn.create_volume(80, "us-east-1a")
|
||||||
|
|
||||||
all_volumes = conn.get_all_volumes()
|
all_volumes = conn.get_all_volumes()
|
||||||
@ -52,7 +52,7 @@ def test_create_and_delete_volume():
|
|||||||
|
|
||||||
@mock_ec2_deprecated
|
@mock_ec2_deprecated
|
||||||
def test_create_encrypted_volume_dryrun():
|
def test_create_encrypted_volume_dryrun():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.ec2.connect_to_region("us-east-1")
|
||||||
with assert_raises(EC2ResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.create_volume(80, "us-east-1a", encrypted=True, dry_run=True)
|
conn.create_volume(80, "us-east-1a", encrypted=True, dry_run=True)
|
||||||
ex.exception.error_code.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
@ -63,7 +63,7 @@ def test_create_encrypted_volume_dryrun():
|
|||||||
|
|
||||||
@mock_ec2_deprecated
|
@mock_ec2_deprecated
|
||||||
def test_create_encrypted_volume():
|
def test_create_encrypted_volume():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.ec2.connect_to_region("us-east-1")
|
||||||
volume = conn.create_volume(80, "us-east-1a", encrypted=True)
|
volume = conn.create_volume(80, "us-east-1a", encrypted=True)
|
||||||
|
|
||||||
with assert_raises(EC2ResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
@ -79,7 +79,7 @@ def test_create_encrypted_volume():
|
|||||||
|
|
||||||
@mock_ec2_deprecated
|
@mock_ec2_deprecated
|
||||||
def test_filter_volume_by_id():
|
def test_filter_volume_by_id():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.ec2.connect_to_region("us-east-1")
|
||||||
volume1 = conn.create_volume(80, "us-east-1a")
|
volume1 = conn.create_volume(80, "us-east-1a")
|
||||||
volume2 = conn.create_volume(36, "us-east-1b")
|
volume2 = conn.create_volume(36, "us-east-1b")
|
||||||
volume3 = conn.create_volume(20, "us-east-1c")
|
volume3 = conn.create_volume(20, "us-east-1c")
|
||||||
@ -99,7 +99,7 @@ def test_filter_volume_by_id():
|
|||||||
|
|
||||||
@mock_ec2_deprecated
|
@mock_ec2_deprecated
|
||||||
def test_volume_filters():
|
def test_volume_filters():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.ec2.connect_to_region("us-east-1")
|
||||||
|
|
||||||
reservation = conn.run_instances('ami-1234abcd')
|
reservation = conn.run_instances('ami-1234abcd')
|
||||||
instance = reservation.instances[0]
|
instance = reservation.instances[0]
|
||||||
@ -196,7 +196,7 @@ def test_volume_filters():
|
|||||||
|
|
||||||
@mock_ec2_deprecated
|
@mock_ec2_deprecated
|
||||||
def test_volume_attach_and_detach():
|
def test_volume_attach_and_detach():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.ec2.connect_to_region("us-east-1")
|
||||||
reservation = conn.run_instances('ami-1234abcd')
|
reservation = conn.run_instances('ami-1234abcd')
|
||||||
instance = reservation.instances[0]
|
instance = reservation.instances[0]
|
||||||
volume = conn.create_volume(80, "us-east-1a")
|
volume = conn.create_volume(80, "us-east-1a")
|
||||||
@ -252,7 +252,7 @@ def test_volume_attach_and_detach():
|
|||||||
|
|
||||||
@mock_ec2_deprecated
|
@mock_ec2_deprecated
|
||||||
def test_create_snapshot():
|
def test_create_snapshot():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.ec2.connect_to_region("us-east-1")
|
||||||
volume = conn.create_volume(80, "us-east-1a")
|
volume = conn.create_volume(80, "us-east-1a")
|
||||||
|
|
||||||
with assert_raises(EC2ResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
@ -291,7 +291,7 @@ def test_create_snapshot():
|
|||||||
|
|
||||||
@mock_ec2_deprecated
|
@mock_ec2_deprecated
|
||||||
def test_create_encrypted_snapshot():
|
def test_create_encrypted_snapshot():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.ec2.connect_to_region("us-east-1")
|
||||||
volume = conn.create_volume(80, "us-east-1a", encrypted=True)
|
volume = conn.create_volume(80, "us-east-1a", encrypted=True)
|
||||||
snapshot = volume.create_snapshot('a test snapshot')
|
snapshot = volume.create_snapshot('a test snapshot')
|
||||||
snapshot.update()
|
snapshot.update()
|
||||||
@ -306,7 +306,7 @@ def test_create_encrypted_snapshot():
|
|||||||
|
|
||||||
@mock_ec2_deprecated
|
@mock_ec2_deprecated
|
||||||
def test_filter_snapshot_by_id():
|
def test_filter_snapshot_by_id():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.ec2.connect_to_region("us-east-1")
|
||||||
volume1 = conn.create_volume(36, "us-east-1a")
|
volume1 = conn.create_volume(36, "us-east-1a")
|
||||||
snap1 = volume1.create_snapshot('a test snapshot 1')
|
snap1 = volume1.create_snapshot('a test snapshot 1')
|
||||||
volume2 = conn.create_volume(42, 'us-east-1a')
|
volume2 = conn.create_volume(42, 'us-east-1a')
|
||||||
@ -333,7 +333,7 @@ def test_filter_snapshot_by_id():
|
|||||||
|
|
||||||
@mock_ec2_deprecated
|
@mock_ec2_deprecated
|
||||||
def test_snapshot_filters():
|
def test_snapshot_filters():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.ec2.connect_to_region("us-east-1")
|
||||||
volume1 = conn.create_volume(20, "us-east-1a", encrypted=False)
|
volume1 = conn.create_volume(20, "us-east-1a", encrypted=False)
|
||||||
volume2 = conn.create_volume(25, "us-east-1a", encrypted=True)
|
volume2 = conn.create_volume(25, "us-east-1a", encrypted=True)
|
||||||
|
|
||||||
@ -404,7 +404,7 @@ def test_snapshot_filters():
|
|||||||
def test_snapshot_attribute():
|
def test_snapshot_attribute():
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.ec2.connect_to_region("us-east-1")
|
||||||
volume = conn.create_volume(80, "us-east-1a")
|
volume = conn.create_volume(80, "us-east-1a")
|
||||||
snapshot = volume.create_snapshot()
|
snapshot = volume.create_snapshot()
|
||||||
|
|
||||||
@ -507,7 +507,7 @@ def test_snapshot_attribute():
|
|||||||
|
|
||||||
@mock_ec2_deprecated
|
@mock_ec2_deprecated
|
||||||
def test_create_volume_from_snapshot():
|
def test_create_volume_from_snapshot():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.ec2.connect_to_region("us-east-1")
|
||||||
volume = conn.create_volume(80, "us-east-1a")
|
volume = conn.create_volume(80, "us-east-1a")
|
||||||
snapshot = volume.create_snapshot('a test snapshot')
|
snapshot = volume.create_snapshot('a test snapshot')
|
||||||
|
|
||||||
@ -529,7 +529,7 @@ def test_create_volume_from_snapshot():
|
|||||||
|
|
||||||
@mock_ec2_deprecated
|
@mock_ec2_deprecated
|
||||||
def test_create_volume_from_encrypted_snapshot():
|
def test_create_volume_from_encrypted_snapshot():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.ec2.connect_to_region("us-east-1")
|
||||||
volume = conn.create_volume(80, "us-east-1a", encrypted=True)
|
volume = conn.create_volume(80, "us-east-1a", encrypted=True)
|
||||||
|
|
||||||
snapshot = volume.create_snapshot('a test snapshot')
|
snapshot = volume.create_snapshot('a test snapshot')
|
||||||
@ -574,7 +574,7 @@ def test_modify_attribute_blockDeviceMapping():
|
|||||||
|
|
||||||
@mock_ec2_deprecated
|
@mock_ec2_deprecated
|
||||||
def test_volume_tag_escaping():
|
def test_volume_tag_escaping():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.ec2.connect_to_region("us-east-1")
|
||||||
vol = conn.create_volume(10, 'us-east-1a')
|
vol = conn.create_volume(10, 'us-east-1a')
|
||||||
snapshot = conn.create_snapshot(vol.id, 'Desc')
|
snapshot = conn.create_snapshot(vol.id, 'Desc')
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ def test_add_servers():
|
|||||||
@freeze_time("2014-01-01 05:00:00")
|
@freeze_time("2014-01-01 05:00:00")
|
||||||
@mock_ec2_deprecated
|
@mock_ec2_deprecated
|
||||||
def test_instance_launch_and_terminate():
|
def test_instance_launch_and_terminate():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.ec2.connect_to_region("us-east-1")
|
||||||
|
|
||||||
with assert_raises(EC2ResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
reservation = conn.run_instances('ami-1234abcd', dry_run=True)
|
reservation = conn.run_instances('ami-1234abcd', dry_run=True)
|
||||||
@ -820,7 +820,7 @@ def test_run_instance_with_instance_type():
|
|||||||
|
|
||||||
@mock_ec2_deprecated
|
@mock_ec2_deprecated
|
||||||
def test_run_instance_with_default_placement():
|
def test_run_instance_with_default_placement():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.ec2.connect_to_region("us-east-1")
|
||||||
reservation = conn.run_instances('ami-1234abcd')
|
reservation = conn.run_instances('ami-1234abcd')
|
||||||
instance = reservation.instances[0]
|
instance = reservation.instances[0]
|
||||||
|
|
||||||
|
@ -68,8 +68,10 @@ def test_create_autoscaling_group():
|
|||||||
image_id='ami-abcd1234',
|
image_id='ami-abcd1234',
|
||||||
instance_type='m1.small',
|
instance_type='m1.small',
|
||||||
)
|
)
|
||||||
us_conn.create_launch_configuration(config)
|
x = us_conn.create_launch_configuration(config)
|
||||||
|
|
||||||
|
us_subnet_id = list(ec2_backends['us-east-1'].subnets['us-east-1c'].keys())[0]
|
||||||
|
ap_subnet_id = list(ec2_backends['ap-northeast-1'].subnets['ap-northeast-1a'].keys())[0]
|
||||||
group = boto.ec2.autoscale.AutoScalingGroup(
|
group = boto.ec2.autoscale.AutoScalingGroup(
|
||||||
name='us_tester_group',
|
name='us_tester_group',
|
||||||
availability_zones=['us-east-1c'],
|
availability_zones=['us-east-1c'],
|
||||||
@ -82,7 +84,7 @@ def test_create_autoscaling_group():
|
|||||||
launch_config=config,
|
launch_config=config,
|
||||||
load_balancers=["us_test_lb"],
|
load_balancers=["us_test_lb"],
|
||||||
placement_group="us_test_placement",
|
placement_group="us_test_placement",
|
||||||
vpc_zone_identifier='subnet-1234abcd',
|
vpc_zone_identifier=us_subnet_id,
|
||||||
termination_policies=["OldestInstance", "NewestInstance"],
|
termination_policies=["OldestInstance", "NewestInstance"],
|
||||||
)
|
)
|
||||||
us_conn.create_auto_scaling_group(group)
|
us_conn.create_auto_scaling_group(group)
|
||||||
@ -107,7 +109,7 @@ def test_create_autoscaling_group():
|
|||||||
launch_config=config,
|
launch_config=config,
|
||||||
load_balancers=["ap_test_lb"],
|
load_balancers=["ap_test_lb"],
|
||||||
placement_group="ap_test_placement",
|
placement_group="ap_test_placement",
|
||||||
vpc_zone_identifier='subnet-5678efgh',
|
vpc_zone_identifier=ap_subnet_id,
|
||||||
termination_policies=["OldestInstance", "NewestInstance"],
|
termination_policies=["OldestInstance", "NewestInstance"],
|
||||||
)
|
)
|
||||||
ap_conn.create_auto_scaling_group(group)
|
ap_conn.create_auto_scaling_group(group)
|
||||||
@ -121,7 +123,7 @@ def test_create_autoscaling_group():
|
|||||||
us_group.desired_capacity.should.equal(2)
|
us_group.desired_capacity.should.equal(2)
|
||||||
us_group.max_size.should.equal(2)
|
us_group.max_size.should.equal(2)
|
||||||
us_group.min_size.should.equal(2)
|
us_group.min_size.should.equal(2)
|
||||||
us_group.vpc_zone_identifier.should.equal('subnet-1234abcd')
|
us_group.vpc_zone_identifier.should.equal(us_subnet_id)
|
||||||
us_group.launch_config_name.should.equal('us_tester')
|
us_group.launch_config_name.should.equal('us_tester')
|
||||||
us_group.default_cooldown.should.equal(60)
|
us_group.default_cooldown.should.equal(60)
|
||||||
us_group.health_check_period.should.equal(100)
|
us_group.health_check_period.should.equal(100)
|
||||||
@ -137,7 +139,7 @@ def test_create_autoscaling_group():
|
|||||||
ap_group.desired_capacity.should.equal(2)
|
ap_group.desired_capacity.should.equal(2)
|
||||||
ap_group.max_size.should.equal(2)
|
ap_group.max_size.should.equal(2)
|
||||||
ap_group.min_size.should.equal(2)
|
ap_group.min_size.should.equal(2)
|
||||||
ap_group.vpc_zone_identifier.should.equal('subnet-5678efgh')
|
ap_group.vpc_zone_identifier.should.equal(ap_subnet_id)
|
||||||
ap_group.launch_config_name.should.equal('ap_tester')
|
ap_group.launch_config_name.should.equal('ap_tester')
|
||||||
ap_group.default_cooldown.should.equal(60)
|
ap_group.default_cooldown.should.equal(60)
|
||||||
ap_group.health_check_period.should.equal(100)
|
ap_group.health_check_period.should.equal(100)
|
||||||
|
@ -21,7 +21,7 @@ from moto import mock_elb, mock_ec2, mock_elb_deprecated, mock_ec2_deprecated
|
|||||||
@mock_ec2_deprecated
|
@mock_ec2_deprecated
|
||||||
def test_create_load_balancer():
|
def test_create_load_balancer():
|
||||||
conn = boto.connect_elb()
|
conn = boto.connect_elb()
|
||||||
ec2 = boto.connect_ec2('the_key', 'the_secret')
|
ec2 = boto.ec2.connect_to_region("us-east-1")
|
||||||
|
|
||||||
security_group = ec2.create_security_group('sg-abc987', 'description')
|
security_group = ec2.create_security_group('sg-abc987', 'description')
|
||||||
|
|
||||||
|
@ -177,30 +177,29 @@ def test_default_cluster_attributes():
|
|||||||
cluster['NumberOfNodes'].should.equal(1)
|
cluster['NumberOfNodes'].should.equal(1)
|
||||||
|
|
||||||
|
|
||||||
@mock_redshift_deprecated
|
@mock_redshift
|
||||||
@mock_ec2_deprecated
|
@mock_ec2
|
||||||
def test_create_cluster_in_subnet_group():
|
def test_create_cluster_in_subnet_group():
|
||||||
vpc_conn = boto.connect_vpc()
|
ec2 = boto3.resource('ec2', region_name='us-east-1')
|
||||||
vpc = vpc_conn.create_vpc("10.0.0.0/16")
|
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
|
||||||
subnet = vpc_conn.create_subnet(vpc.id, "10.0.0.0/24")
|
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/24")
|
||||||
redshift_conn = boto.connect_redshift()
|
client = boto3.client('redshift', region_name='us-east-1')
|
||||||
redshift_conn.create_cluster_subnet_group(
|
client.create_cluster_subnet_group(
|
||||||
"my_subnet_group",
|
ClusterSubnetGroupName="my_subnet_group",
|
||||||
"This is my subnet group",
|
Description="This is my subnet group",
|
||||||
subnet_ids=[subnet.id],
|
SubnetIds=[subnet.id],
|
||||||
)
|
)
|
||||||
|
|
||||||
redshift_conn.create_cluster(
|
client.create_cluster(
|
||||||
"my_cluster",
|
ClusterIdentifier="my_cluster",
|
||||||
node_type="dw.hs1.xlarge",
|
NodeType="dw.hs1.xlarge",
|
||||||
master_username="username",
|
MasterUsername="username",
|
||||||
master_user_password="password",
|
MasterUserPassword="password",
|
||||||
cluster_subnet_group_name='my_subnet_group',
|
ClusterSubnetGroupName='my_subnet_group',
|
||||||
)
|
)
|
||||||
|
|
||||||
cluster_response = redshift_conn.describe_clusters("my_cluster")
|
cluster_response = client.describe_clusters(ClusterIdentifier="my_cluster")
|
||||||
cluster = cluster_response['DescribeClustersResponse'][
|
cluster = cluster_response['Clusters'][0]
|
||||||
'DescribeClustersResult']['Clusters'][0]
|
|
||||||
cluster['ClusterSubnetGroupName'].should.equal('my_subnet_group')
|
cluster['ClusterSubnetGroupName'].should.equal('my_subnet_group')
|
||||||
|
|
||||||
|
|
||||||
@ -476,28 +475,26 @@ def test_modify_cluster():
|
|||||||
cluster['NumberOfNodes'].should.equal(1)
|
cluster['NumberOfNodes'].should.equal(1)
|
||||||
|
|
||||||
|
|
||||||
@mock_redshift_deprecated
|
@mock_redshift
|
||||||
@mock_ec2_deprecated
|
@mock_ec2
|
||||||
def test_create_cluster_subnet_group():
|
def test_create_cluster_subnet_group():
|
||||||
vpc_conn = boto.connect_vpc()
|
ec2 = boto3.resource('ec2', region_name='us-east-1')
|
||||||
vpc = vpc_conn.create_vpc("10.0.0.0/16")
|
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
|
||||||
subnet1 = vpc_conn.create_subnet(vpc.id, "10.0.0.0/24")
|
subnet1 = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/24")
|
||||||
subnet2 = vpc_conn.create_subnet(vpc.id, "10.0.1.0/24")
|
subnet2 = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.1.0/24")
|
||||||
|
client = boto3.client('redshift', region_name='us-east-1')
|
||||||
|
|
||||||
redshift_conn = boto.connect_redshift()
|
client.create_cluster_subnet_group(
|
||||||
|
ClusterSubnetGroupName='my_subnet_group',
|
||||||
redshift_conn.create_cluster_subnet_group(
|
Description='This is my subnet group',
|
||||||
"my_subnet",
|
SubnetIds=[subnet1.id, subnet2.id],
|
||||||
"This is my subnet group",
|
|
||||||
subnet_ids=[subnet1.id, subnet2.id],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
subnets_response = redshift_conn.describe_cluster_subnet_groups(
|
subnets_response = client.describe_cluster_subnet_groups(
|
||||||
"my_subnet")
|
ClusterSubnetGroupName="my_subnet_group")
|
||||||
my_subnet = subnets_response['DescribeClusterSubnetGroupsResponse'][
|
my_subnet = subnets_response['ClusterSubnetGroups'][0]
|
||||||
'DescribeClusterSubnetGroupsResult']['ClusterSubnetGroups'][0]
|
|
||||||
|
|
||||||
my_subnet['ClusterSubnetGroupName'].should.equal("my_subnet")
|
my_subnet['ClusterSubnetGroupName'].should.equal("my_subnet_group")
|
||||||
my_subnet['Description'].should.equal("This is my subnet group")
|
my_subnet['Description'].should.equal("This is my subnet group")
|
||||||
subnet_ids = [subnet['SubnetIdentifier']
|
subnet_ids = [subnet['SubnetIdentifier']
|
||||||
for subnet in my_subnet['Subnets']]
|
for subnet in my_subnet['Subnets']]
|
||||||
@ -522,35 +519,33 @@ def test_describe_non_existent_subnet_group():
|
|||||||
"not-a-subnet-group").should.throw(ClusterSubnetGroupNotFound)
|
"not-a-subnet-group").should.throw(ClusterSubnetGroupNotFound)
|
||||||
|
|
||||||
|
|
||||||
@mock_redshift_deprecated
|
@mock_redshift
|
||||||
@mock_ec2_deprecated
|
@mock_ec2
|
||||||
def test_delete_cluster_subnet_group():
|
def test_delete_cluster_subnet_group():
|
||||||
vpc_conn = boto.connect_vpc()
|
ec2 = boto3.resource('ec2', region_name='us-east-1')
|
||||||
vpc = vpc_conn.create_vpc("10.0.0.0/16")
|
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
|
||||||
subnet = vpc_conn.create_subnet(vpc.id, "10.0.0.0/24")
|
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/24")
|
||||||
redshift_conn = boto.connect_redshift()
|
client = boto3.client('redshift', region_name='us-east-1')
|
||||||
|
|
||||||
redshift_conn.create_cluster_subnet_group(
|
client.create_cluster_subnet_group(
|
||||||
"my_subnet",
|
ClusterSubnetGroupName='my_subnet_group',
|
||||||
"This is my subnet group",
|
Description='This is my subnet group',
|
||||||
subnet_ids=[subnet.id],
|
SubnetIds=[subnet.id],
|
||||||
)
|
)
|
||||||
|
|
||||||
subnets_response = redshift_conn.describe_cluster_subnet_groups()
|
subnets_response = client.describe_cluster_subnet_groups()
|
||||||
subnets = subnets_response['DescribeClusterSubnetGroupsResponse'][
|
subnets = subnets_response['ClusterSubnetGroups']
|
||||||
'DescribeClusterSubnetGroupsResult']['ClusterSubnetGroups']
|
|
||||||
subnets.should.have.length_of(1)
|
subnets.should.have.length_of(1)
|
||||||
|
|
||||||
redshift_conn.delete_cluster_subnet_group("my_subnet")
|
client.delete_cluster_subnet_group(ClusterSubnetGroupName="my_subnet_group")
|
||||||
|
|
||||||
subnets_response = redshift_conn.describe_cluster_subnet_groups()
|
subnets_response = client.describe_cluster_subnet_groups()
|
||||||
subnets = subnets_response['DescribeClusterSubnetGroupsResponse'][
|
subnets = subnets_response['ClusterSubnetGroups']
|
||||||
'DescribeClusterSubnetGroupsResult']['ClusterSubnetGroups']
|
|
||||||
subnets.should.have.length_of(0)
|
subnets.should.have.length_of(0)
|
||||||
|
|
||||||
# Delete invalid id
|
# Delete invalid id
|
||||||
redshift_conn.delete_cluster_subnet_group.when.called_with(
|
client.delete_cluster_subnet_group.when.called_with(
|
||||||
"not-a-subnet-group").should.throw(ClusterSubnetGroupNotFound)
|
ClusterSubnetGroupName="not-a-subnet-group").should.throw(ClientError)
|
||||||
|
|
||||||
|
|
||||||
@mock_redshift_deprecated
|
@mock_redshift_deprecated
|
||||||
|
Loading…
x
Reference in New Issue
Block a user