Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Stephan 2019-04-29 12:11:47 +02:00
commit 5804441d38
104 changed files with 26177 additions and 18562 deletions

View file

@ -710,6 +710,7 @@ def test_create_autoscaling_group_boto3():
'PropagateAtLaunch': False
}],
VPCZoneIdentifier=mocked_networking['subnet1'],
NewInstancesProtectedFromScaleIn=False,
)
response['ResponseMetadata']['HTTPStatusCode'].should.equal(200)
@ -728,13 +729,48 @@ def test_describe_autoscaling_groups_boto3():
MaxSize=20,
DesiredCapacity=5,
VPCZoneIdentifier=mocked_networking['subnet1'],
NewInstancesProtectedFromScaleIn=True,
)
response = client.describe_auto_scaling_groups(
AutoScalingGroupNames=["test_asg"]
)
response['ResponseMetadata']['HTTPStatusCode'].should.equal(200)
response['AutoScalingGroups'][0][
'AutoScalingGroupName'].should.equal('test_asg')
group = response['AutoScalingGroups'][0]
group['AutoScalingGroupName'].should.equal('test_asg')
group['NewInstancesProtectedFromScaleIn'].should.equal(True)
group['Instances'][0]['ProtectedFromScaleIn'].should.equal(True)
@mock_autoscaling
def test_describe_autoscaling_instances_boto3():
mocked_networking = setup_networking()
client = boto3.client('autoscaling', region_name='us-east-1')
_ = client.create_launch_configuration(
LaunchConfigurationName='test_launch_configuration'
)
_ = client.create_auto_scaling_group(
AutoScalingGroupName='test_asg',
LaunchConfigurationName='test_launch_configuration',
MinSize=0,
MaxSize=20,
DesiredCapacity=5,
VPCZoneIdentifier=mocked_networking['subnet1'],
NewInstancesProtectedFromScaleIn=True,
)
response = client.describe_auto_scaling_groups(
AutoScalingGroupNames=["test_asg"]
)
instance_ids = [
instance['InstanceId']
for instance in response['AutoScalingGroups'][0]['Instances']
]
response = client.describe_auto_scaling_instances(InstanceIds=instance_ids)
for instance in response['AutoScalingInstances']:
instance['AutoScalingGroupName'].should.equal('test_asg')
instance['ProtectedFromScaleIn'].should.equal(True)
@mock_autoscaling
@ -751,17 +787,21 @@ def test_update_autoscaling_group_boto3():
MaxSize=20,
DesiredCapacity=5,
VPCZoneIdentifier=mocked_networking['subnet1'],
NewInstancesProtectedFromScaleIn=True,
)
response = client.update_auto_scaling_group(
_ = client.update_auto_scaling_group(
AutoScalingGroupName='test_asg',
MinSize=1,
NewInstancesProtectedFromScaleIn=False,
)
response = client.describe_auto_scaling_groups(
AutoScalingGroupNames=["test_asg"]
)
response['AutoScalingGroups'][0]['MinSize'].should.equal(1)
group = response['AutoScalingGroups'][0]
group['MinSize'].should.equal(1)
group['NewInstancesProtectedFromScaleIn'].should.equal(False)
@mock_autoscaling
@ -992,9 +1032,7 @@ def test_attach_one_instance():
'PropagateAtLaunch': True
}],
VPCZoneIdentifier=mocked_networking['subnet1'],
)
response = client.describe_auto_scaling_groups(
AutoScalingGroupNames=['test_asg']
NewInstancesProtectedFromScaleIn=True,
)
ec2 = boto3.resource('ec2', 'us-east-1')
@ -1009,7 +1047,11 @@ def test_attach_one_instance():
response = client.describe_auto_scaling_groups(
AutoScalingGroupNames=['test_asg']
)
response['AutoScalingGroups'][0]['Instances'].should.have.length_of(3)
instances = response['AutoScalingGroups'][0]['Instances']
instances.should.have.length_of(3)
for instance in instances:
instance['ProtectedFromScaleIn'].should.equal(True)
@mock_autoscaling
@mock_ec2
@ -1100,3 +1142,111 @@ def test_suspend_processes():
launch_suspended = True
assert launch_suspended is True
@mock_autoscaling
def test_set_instance_protection():
mocked_networking = setup_networking()
client = boto3.client('autoscaling', region_name='us-east-1')
_ = client.create_launch_configuration(
LaunchConfigurationName='test_launch_configuration'
)
_ = client.create_auto_scaling_group(
AutoScalingGroupName='test_asg',
LaunchConfigurationName='test_launch_configuration',
MinSize=0,
MaxSize=20,
DesiredCapacity=5,
VPCZoneIdentifier=mocked_networking['subnet1'],
NewInstancesProtectedFromScaleIn=False,
)
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=['test_asg'])
instance_ids = [
instance['InstanceId']
for instance in response['AutoScalingGroups'][0]['Instances']
]
protected = instance_ids[:3]
_ = client.set_instance_protection(
AutoScalingGroupName='test_asg',
InstanceIds=protected,
ProtectedFromScaleIn=True,
)
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=['test_asg'])
for instance in response['AutoScalingGroups'][0]['Instances']:
instance['ProtectedFromScaleIn'].should.equal(
instance['InstanceId'] in protected
)
@mock_autoscaling
def test_set_desired_capacity_up_boto3():
mocked_networking = setup_networking()
client = boto3.client('autoscaling', region_name='us-east-1')
_ = client.create_launch_configuration(
LaunchConfigurationName='test_launch_configuration'
)
_ = client.create_auto_scaling_group(
AutoScalingGroupName='test_asg',
LaunchConfigurationName='test_launch_configuration',
MinSize=0,
MaxSize=20,
DesiredCapacity=5,
VPCZoneIdentifier=mocked_networking['subnet1'],
NewInstancesProtectedFromScaleIn=True,
)
_ = client.set_desired_capacity(
AutoScalingGroupName='test_asg',
DesiredCapacity=10,
)
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=['test_asg'])
instances = response['AutoScalingGroups'][0]['Instances']
instances.should.have.length_of(10)
for instance in instances:
instance['ProtectedFromScaleIn'].should.equal(True)
@mock_autoscaling
def test_set_desired_capacity_down_boto3():
mocked_networking = setup_networking()
client = boto3.client('autoscaling', region_name='us-east-1')
_ = client.create_launch_configuration(
LaunchConfigurationName='test_launch_configuration'
)
_ = client.create_auto_scaling_group(
AutoScalingGroupName='test_asg',
LaunchConfigurationName='test_launch_configuration',
MinSize=0,
MaxSize=20,
DesiredCapacity=5,
VPCZoneIdentifier=mocked_networking['subnet1'],
NewInstancesProtectedFromScaleIn=True,
)
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=['test_asg'])
instance_ids = [
instance['InstanceId']
for instance in response['AutoScalingGroups'][0]['Instances']
]
unprotected, protected = instance_ids[:2], instance_ids[2:]
_ = client.set_instance_protection(
AutoScalingGroupName='test_asg',
InstanceIds=unprotected,
ProtectedFromScaleIn=False,
)
_ = client.set_desired_capacity(
AutoScalingGroupName='test_asg',
DesiredCapacity=1,
)
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=['test_asg'])
group = response['AutoScalingGroups'][0]
group['DesiredCapacity'].should.equal(1)
instance_ids = {instance['InstanceId'] for instance in group['Instances']}
set(protected).should.equal(instance_ids)
set(unprotected).should_not.be.within(instance_ids) # only unprotected killed

View file

@ -12,6 +12,8 @@ import sure # noqa
from freezegun import freeze_time
from moto import mock_lambda, mock_s3, mock_ec2, mock_sns, mock_logs, settings
from nose.tools import assert_raises
from botocore.exceptions import ClientError
_lambda_region = 'us-west-2'
@ -397,6 +399,11 @@ def test_get_function():
result = conn.get_function(FunctionName='testFunction', Qualifier='$LATEST')
result['Configuration']['Version'].should.equal('$LATEST')
# Test get function when can't find function name
with assert_raises(ClientError):
conn.get_function(FunctionName='junk', Qualifier='$LATEST')
@mock_lambda
@mock_s3
@ -464,7 +471,8 @@ def test_publish():
function_list['Functions'].should.have.length_of(1)
latest_arn = function_list['Functions'][0]['FunctionArn']
conn.publish_version(FunctionName='testFunction')
res = conn.publish_version(FunctionName='testFunction')
assert res['ResponseMetadata']['HTTPStatusCode'] == 201
function_list = conn.list_functions()
function_list['Functions'].should.have.length_of(2)
@ -819,3 +827,87 @@ def get_function_policy():
assert isinstance(response['Policy'], str)
res = json.loads(response['Policy'])
assert res['Statement'][0]['Action'] == 'lambda:InvokeFunction'
@mock_lambda
@mock_s3
def test_list_versions_by_function():
s3_conn = boto3.client('s3', 'us-west-2')
s3_conn.create_bucket(Bucket='test-bucket')
zip_content = get_test_zip_file2()
s3_conn.put_object(Bucket='test-bucket', Key='test.zip', Body=zip_content)
conn = boto3.client('lambda', 'us-west-2')
conn.create_function(
FunctionName='testFunction',
Runtime='python2.7',
Role='test-iam-role',
Handler='lambda_function.lambda_handler',
Code={
'S3Bucket': 'test-bucket',
'S3Key': 'test.zip',
},
Description='test lambda function',
Timeout=3,
MemorySize=128,
Publish=True,
)
res = conn.publish_version(FunctionName='testFunction')
assert res['ResponseMetadata']['HTTPStatusCode'] == 201
versions = conn.list_versions_by_function(FunctionName='testFunction')
assert versions['Versions'][0]['FunctionArn'] == 'arn:aws:lambda:us-west-2:123456789012:function:testFunction:$LATEST'
@mock_lambda
@mock_s3
def test_create_function_with_already_exists():
s3_conn = boto3.client('s3', 'us-west-2')
s3_conn.create_bucket(Bucket='test-bucket')
zip_content = get_test_zip_file2()
s3_conn.put_object(Bucket='test-bucket', Key='test.zip', Body=zip_content)
conn = boto3.client('lambda', 'us-west-2')
conn.create_function(
FunctionName='testFunction',
Runtime='python2.7',
Role='test-iam-role',
Handler='lambda_function.lambda_handler',
Code={
'S3Bucket': 'test-bucket',
'S3Key': 'test.zip',
},
Description='test lambda function',
Timeout=3,
MemorySize=128,
Publish=True,
)
response = conn.create_function(
FunctionName='testFunction',
Runtime='python2.7',
Role='test-iam-role',
Handler='lambda_function.lambda_handler',
Code={
'S3Bucket': 'test-bucket',
'S3Key': 'test.zip',
},
Description='test lambda function',
Timeout=3,
MemorySize=128,
Publish=True,
)
assert response['FunctionName'] == 'testFunction'
@mock_lambda
@mock_s3
def test_list_versions_by_function_for_nonexistent_function():
conn = boto3.client('lambda', 'us-west-2')
versions = conn.list_versions_by_function(FunctionName='testFunction')
assert len(versions['Versions']) == 0

View file

@ -323,6 +323,54 @@ def test_create_job_queue():
resp.should.contain('jobQueues')
len(resp['jobQueues']).should.equal(0)
# Create job queue which already exists
try:
resp = batch_client.create_job_queue(
jobQueueName='test_job_queue',
state='ENABLED',
priority=123,
computeEnvironmentOrder=[
{
'order': 123,
'computeEnvironment': arn
},
]
)
except ClientError as err:
err.response['Error']['Code'].should.equal('ClientException')
# Create job queue with incorrect state
try:
resp = batch_client.create_job_queue(
jobQueueName='test_job_queue2',
state='JUNK',
priority=123,
computeEnvironmentOrder=[
{
'order': 123,
'computeEnvironment': arn
},
]
)
except ClientError as err:
err.response['Error']['Code'].should.equal('ClientException')
# Create job queue with no compute env
try:
resp = batch_client.create_job_queue(
jobQueueName='test_job_queue3',
state='JUNK',
priority=123,
computeEnvironmentOrder=[
]
)
except ClientError as err:
err.response['Error']['Code'].should.equal('ClientException')
@mock_ec2
@mock_ecs
@ -397,6 +445,17 @@ def test_update_job_queue():
len(resp['jobQueues']).should.equal(1)
resp['jobQueues'][0]['priority'].should.equal(5)
batch_client.update_job_queue(
jobQueue='test_job_queue',
priority=5
)
resp = batch_client.describe_job_queues()
resp.should.contain('jobQueues')
len(resp['jobQueues']).should.equal(1)
resp['jobQueues'][0]['priority'].should.equal(5)
@mock_ec2
@mock_ecs

View file

@ -1,34 +1,38 @@
from __future__ import unicode_literals
template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "VPC ENI Test CloudFormation",
"Resources": {
"ENI": {
"Type": "AWS::EC2::NetworkInterface",
"Properties": {
"SubnetId": {"Ref": "Subnet"}
}
},
"Subnet": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"AvailabilityZone": "us-east-1a",
"VpcId": {"Ref": "VPC"},
"CidrBlock": "10.0.0.0/24"
}
},
"VPC": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "10.0.0.0/16"
}
}
},
"Outputs": {
"NinjaENI": {
"Description": "Elastic IP mapping to Auto-Scaling Group",
"Value": {"Ref": "ENI"}
}
}
}
from __future__ import unicode_literals
template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "VPC ENI Test CloudFormation",
"Resources": {
"ENI": {
"Type": "AWS::EC2::NetworkInterface",
"Properties": {
"SubnetId": {"Ref": "Subnet"}
}
},
"Subnet": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"AvailabilityZone": "us-east-1a",
"VpcId": {"Ref": "VPC"},
"CidrBlock": "10.0.0.0/24"
}
},
"VPC": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "10.0.0.0/16"
}
}
},
"Outputs": {
"NinjaENI": {
"Description": "Elastic IP mapping to Auto-Scaling Group",
"Value": {"Ref": "ENI"}
},
"ENIIpAddress": {
"Description": "ENI's Private IP address",
"Value": {"Fn::GetAtt": ["ENI", "PrimaryPrivateIpAddress"]}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,471 +1,471 @@
from __future__ import unicode_literals
import json
import yaml
from mock import patch
import sure # noqa
from moto.cloudformation.exceptions import ValidationError
from moto.cloudformation.models import FakeStack
from moto.cloudformation.parsing import resource_class_from_type, parse_condition, Export
from moto.sqs.models import Queue
from moto.s3.models import FakeBucket
from moto.cloudformation.utils import yaml_tag_constructor
from boto.cloudformation.stack import Output
dummy_template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Create a multi-az, load balanced, Auto Scaled sample web site. The Auto Scaling trigger is based on the CPU utilization of the web servers. The AMI is chosen based on the region in which the stack is run. This example creates a web service running across all availability zones in a region. The instances are load balanced with a simple health check. The web site is available on port 80, however, the instances can be configured to listen on any port (8888 by default). **WARNING** This template creates one or more Amazon EC2 instances. You will be billed for the AWS resources used if you create a stack from this template.",
"Resources": {
"Queue": {
"Type": "AWS::SQS::Queue",
"Properties": {
"QueueName": "my-queue",
"VisibilityTimeout": 60,
}
},
"S3Bucket": {
"Type": "AWS::S3::Bucket",
"DeletionPolicy": "Retain"
},
},
}
name_type_template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Create a multi-az, load balanced, Auto Scaled sample web site. The Auto Scaling trigger is based on the CPU utilization of the web servers. The AMI is chosen based on the region in which the stack is run. This example creates a web service running across all availability zones in a region. The instances are load balanced with a simple health check. The web site is available on port 80, however, the instances can be configured to listen on any port (8888 by default). **WARNING** This template creates one or more Amazon EC2 instances. You will be billed for the AWS resources used if you create a stack from this template.",
"Resources": {
"Queue": {
"Type": "AWS::SQS::Queue",
"Properties": {
"VisibilityTimeout": 60,
}
},
},
}
output_dict = {
"Outputs": {
"Output1": {
"Value": {"Ref": "Queue"},
"Description": "This is a description."
}
}
}
bad_output = {
"Outputs": {
"Output1": {
"Value": {"Fn::GetAtt": ["Queue", "InvalidAttribute"]}
}
}
}
get_attribute_output = {
"Outputs": {
"Output1": {
"Value": {"Fn::GetAtt": ["Queue", "QueueName"]}
}
}
}
get_availability_zones_output = {
"Outputs": {
"Output1": {
"Value": {"Fn::GetAZs": ""}
}
}
}
split_select_template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"Queue": {
"Type": "AWS::SQS::Queue",
"Properties": {
"QueueName": {"Fn::Select": [ "1", {"Fn::Split": [ "-", "123-myqueue" ] } ] },
"VisibilityTimeout": 60,
}
}
}
}
sub_template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"Queue1": {
"Type": "AWS::SQS::Queue",
"Properties": {
"QueueName": {"Fn::Sub": '${AWS::StackName}-queue-${!Literal}'},
"VisibilityTimeout": 60,
}
},
"Queue2": {
"Type": "AWS::SQS::Queue",
"Properties": {
"QueueName": {"Fn::Sub": '${Queue1.QueueName}'},
"VisibilityTimeout": 60,
}
},
}
}
export_value_template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"Queue": {
"Type": "AWS::SQS::Queue",
"Properties": {
"QueueName": {"Fn::Sub": '${AWS::StackName}-queue'},
"VisibilityTimeout": 60,
}
}
},
"Outputs": {
"Output1": {
"Value": "value",
"Export": {"Name": 'queue-us-west-1'}
}
}
}
import_value_template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"Queue": {
"Type": "AWS::SQS::Queue",
"Properties": {
"QueueName": {"Fn::ImportValue": 'queue-us-west-1'},
"VisibilityTimeout": 60,
}
}
}
}
outputs_template = dict(list(dummy_template.items()) +
list(output_dict.items()))
bad_outputs_template = dict(
list(dummy_template.items()) + list(bad_output.items()))
get_attribute_outputs_template = dict(
list(dummy_template.items()) + list(get_attribute_output.items()))
get_availability_zones_template = dict(
list(dummy_template.items()) + list(get_availability_zones_output.items()))
dummy_template_json = json.dumps(dummy_template)
name_type_template_json = json.dumps(name_type_template)
output_type_template_json = json.dumps(outputs_template)
bad_output_template_json = json.dumps(bad_outputs_template)
get_attribute_outputs_template_json = json.dumps(
get_attribute_outputs_template)
get_availability_zones_template_json = json.dumps(
get_availability_zones_template)
split_select_template_json = json.dumps(split_select_template)
sub_template_json = json.dumps(sub_template)
export_value_template_json = json.dumps(export_value_template)
import_value_template_json = json.dumps(import_value_template)
def test_parse_stack_resources():
stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=dummy_template_json,
parameters={},
region_name='us-west-1')
stack.resource_map.should.have.length_of(2)
queue = stack.resource_map['Queue']
queue.should.be.a(Queue)
queue.name.should.equal("my-queue")
bucket = stack.resource_map['S3Bucket']
bucket.should.be.a(FakeBucket)
bucket.physical_resource_id.should.equal(bucket.name)
@patch("moto.cloudformation.parsing.logger")
def test_missing_resource_logs(logger):
resource_class_from_type("foobar")
logger.warning.assert_called_with(
'No Moto CloudFormation support for %s', 'foobar')
def test_parse_stack_with_name_type_resource():
stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=name_type_template_json,
parameters={},
region_name='us-west-1')
stack.resource_map.should.have.length_of(1)
list(stack.resource_map.keys())[0].should.equal('Queue')
queue = list(stack.resource_map.values())[0]
queue.should.be.a(Queue)
def test_parse_stack_with_yaml_template():
stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=yaml.dump(name_type_template),
parameters={},
region_name='us-west-1')
stack.resource_map.should.have.length_of(1)
list(stack.resource_map.keys())[0].should.equal('Queue')
queue = list(stack.resource_map.values())[0]
queue.should.be.a(Queue)
def test_parse_stack_with_outputs():
stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=output_type_template_json,
parameters={},
region_name='us-west-1')
stack.output_map.should.have.length_of(1)
list(stack.output_map.keys())[0].should.equal('Output1')
output = list(stack.output_map.values())[0]
output.should.be.a(Output)
output.description.should.equal("This is a description.")
def test_parse_stack_with_get_attribute_outputs():
stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=get_attribute_outputs_template_json,
parameters={},
region_name='us-west-1')
stack.output_map.should.have.length_of(1)
list(stack.output_map.keys())[0].should.equal('Output1')
output = list(stack.output_map.values())[0]
output.should.be.a(Output)
output.value.should.equal("my-queue")
def test_parse_stack_with_get_attribute_kms():
from .fixtures.kms_key import template
template_json = json.dumps(template)
stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=template_json,
parameters={},
region_name='us-west-1')
stack.output_map.should.have.length_of(1)
list(stack.output_map.keys())[0].should.equal('KeyArn')
output = list(stack.output_map.values())[0]
output.should.be.a(Output)
def test_parse_stack_with_get_availability_zones():
stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=get_availability_zones_template_json,
parameters={},
region_name='us-east-1')
stack.output_map.should.have.length_of(1)
list(stack.output_map.keys())[0].should.equal('Output1')
output = list(stack.output_map.values())[0]
output.should.be.a(Output)
output.value.should.equal([ "us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d" ])
def test_parse_stack_with_bad_get_attribute_outputs():
FakeStack.when.called_with(
"test_id", "test_stack", bad_output_template_json, {}, "us-west-1").should.throw(ValidationError)
def test_parse_equals_condition():
parse_condition(
condition={"Fn::Equals": [{"Ref": "EnvType"}, "prod"]},
resources_map={"EnvType": "prod"},
condition_map={},
).should.equal(True)
parse_condition(
condition={"Fn::Equals": [{"Ref": "EnvType"}, "prod"]},
resources_map={"EnvType": "staging"},
condition_map={},
).should.equal(False)
def test_parse_not_condition():
parse_condition(
condition={
"Fn::Not": [{
"Fn::Equals": [{"Ref": "EnvType"}, "prod"]
}]
},
resources_map={"EnvType": "prod"},
condition_map={},
).should.equal(False)
parse_condition(
condition={
"Fn::Not": [{
"Fn::Equals": [{"Ref": "EnvType"}, "prod"]
}]
},
resources_map={"EnvType": "staging"},
condition_map={},
).should.equal(True)
def test_parse_and_condition():
parse_condition(
condition={
"Fn::And": [
{"Fn::Equals": [{"Ref": "EnvType"}, "prod"]},
{"Fn::Equals": [{"Ref": "EnvType"}, "staging"]},
]
},
resources_map={"EnvType": "prod"},
condition_map={},
).should.equal(False)
parse_condition(
condition={
"Fn::And": [
{"Fn::Equals": [{"Ref": "EnvType"}, "prod"]},
{"Fn::Equals": [{"Ref": "EnvType"}, "prod"]},
]
},
resources_map={"EnvType": "prod"},
condition_map={},
).should.equal(True)
def test_parse_or_condition():
parse_condition(
condition={
"Fn::Or": [
{"Fn::Equals": [{"Ref": "EnvType"}, "prod"]},
{"Fn::Equals": [{"Ref": "EnvType"}, "staging"]},
]
},
resources_map={"EnvType": "prod"},
condition_map={},
).should.equal(True)
parse_condition(
condition={
"Fn::Or": [
{"Fn::Equals": [{"Ref": "EnvType"}, "staging"]},
{"Fn::Equals": [{"Ref": "EnvType"}, "staging"]},
]
},
resources_map={"EnvType": "prod"},
condition_map={},
).should.equal(False)
def test_reference_other_conditions():
parse_condition(
condition={"Fn::Not": [{"Condition": "OtherCondition"}]},
resources_map={},
condition_map={"OtherCondition": True},
).should.equal(False)
def test_parse_split_and_select():
stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=split_select_template_json,
parameters={},
region_name='us-west-1')
stack.resource_map.should.have.length_of(1)
queue = stack.resource_map['Queue']
queue.name.should.equal("myqueue")
def test_sub():
stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=sub_template_json,
parameters={},
region_name='us-west-1')
queue1 = stack.resource_map['Queue1']
queue2 = stack.resource_map['Queue2']
queue2.name.should.equal(queue1.name)
def test_import():
export_stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=export_value_template_json,
parameters={},
region_name='us-west-1')
import_stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=import_value_template_json,
parameters={},
region_name='us-west-1',
cross_stack_resources={export_stack.exports[0].value: export_stack.exports[0]})
queue = import_stack.resource_map['Queue']
queue.name.should.equal("value")
def test_short_form_func_in_yaml_teamplate():
template = """---
KeyB64: !Base64 valueToEncode
KeyRef: !Ref foo
KeyAnd: !And
- A
- B
KeyEquals: !Equals [A, B]
KeyIf: !If [A, B, C]
KeyNot: !Not [A]
KeyOr: !Or [A, B]
KeyFindInMap: !FindInMap [A, B, C]
KeyGetAtt: !GetAtt A.B
KeyGetAZs: !GetAZs A
KeyImportValue: !ImportValue A
KeyJoin: !Join [ ":", [A, B, C] ]
KeySelect: !Select [A, B]
KeySplit: !Split [A, B]
KeySub: !Sub A
"""
yaml.add_multi_constructor('', yaml_tag_constructor)
template_dict = yaml.load(template)
key_and_expects = [
['KeyRef', {'Ref': 'foo'}],
['KeyB64', {'Fn::Base64': 'valueToEncode'}],
['KeyAnd', {'Fn::And': ['A', 'B']}],
['KeyEquals', {'Fn::Equals': ['A', 'B']}],
['KeyIf', {'Fn::If': ['A', 'B', 'C']}],
['KeyNot', {'Fn::Not': ['A']}],
['KeyOr', {'Fn::Or': ['A', 'B']}],
['KeyFindInMap', {'Fn::FindInMap': ['A', 'B', 'C']}],
['KeyGetAtt', {'Fn::GetAtt': ['A', 'B']}],
['KeyGetAZs', {'Fn::GetAZs': 'A'}],
['KeyImportValue', {'Fn::ImportValue': 'A'}],
['KeyJoin', {'Fn::Join': [ ":", [ 'A', 'B', 'C' ] ]}],
['KeySelect', {'Fn::Select': ['A', 'B']}],
['KeySplit', {'Fn::Split': ['A', 'B']}],
['KeySub', {'Fn::Sub': 'A'}],
]
for k, v in key_and_expects:
template_dict.should.have.key(k).which.should.be.equal(v)
from __future__ import unicode_literals
import json
import yaml
from mock import patch
import sure # noqa
from moto.cloudformation.exceptions import ValidationError
from moto.cloudformation.models import FakeStack
from moto.cloudformation.parsing import resource_class_from_type, parse_condition, Export
from moto.sqs.models import Queue
from moto.s3.models import FakeBucket
from moto.cloudformation.utils import yaml_tag_constructor
from boto.cloudformation.stack import Output
dummy_template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Create a multi-az, load balanced, Auto Scaled sample web site. The Auto Scaling trigger is based on the CPU utilization of the web servers. The AMI is chosen based on the region in which the stack is run. This example creates a web service running across all availability zones in a region. The instances are load balanced with a simple health check. The web site is available on port 80, however, the instances can be configured to listen on any port (8888 by default). **WARNING** This template creates one or more Amazon EC2 instances. You will be billed for the AWS resources used if you create a stack from this template.",
"Resources": {
"Queue": {
"Type": "AWS::SQS::Queue",
"Properties": {
"QueueName": "my-queue",
"VisibilityTimeout": 60,
}
},
"S3Bucket": {
"Type": "AWS::S3::Bucket",
"DeletionPolicy": "Retain"
},
},
}
name_type_template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Create a multi-az, load balanced, Auto Scaled sample web site. The Auto Scaling trigger is based on the CPU utilization of the web servers. The AMI is chosen based on the region in which the stack is run. This example creates a web service running across all availability zones in a region. The instances are load balanced with a simple health check. The web site is available on port 80, however, the instances can be configured to listen on any port (8888 by default). **WARNING** This template creates one or more Amazon EC2 instances. You will be billed for the AWS resources used if you create a stack from this template.",
"Resources": {
"Queue": {
"Type": "AWS::SQS::Queue",
"Properties": {
"VisibilityTimeout": 60,
}
},
},
}
output_dict = {
"Outputs": {
"Output1": {
"Value": {"Ref": "Queue"},
"Description": "This is a description."
}
}
}
bad_output = {
"Outputs": {
"Output1": {
"Value": {"Fn::GetAtt": ["Queue", "InvalidAttribute"]}
}
}
}
get_attribute_output = {
"Outputs": {
"Output1": {
"Value": {"Fn::GetAtt": ["Queue", "QueueName"]}
}
}
}
get_availability_zones_output = {
"Outputs": {
"Output1": {
"Value": {"Fn::GetAZs": ""}
}
}
}
split_select_template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"Queue": {
"Type": "AWS::SQS::Queue",
"Properties": {
"QueueName": {"Fn::Select": [ "1", {"Fn::Split": [ "-", "123-myqueue" ] } ] },
"VisibilityTimeout": 60,
}
}
}
}
sub_template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"Queue1": {
"Type": "AWS::SQS::Queue",
"Properties": {
"QueueName": {"Fn::Sub": '${AWS::StackName}-queue-${!Literal}'},
"VisibilityTimeout": 60,
}
},
"Queue2": {
"Type": "AWS::SQS::Queue",
"Properties": {
"QueueName": {"Fn::Sub": '${Queue1.QueueName}'},
"VisibilityTimeout": 60,
}
},
}
}
export_value_template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"Queue": {
"Type": "AWS::SQS::Queue",
"Properties": {
"QueueName": {"Fn::Sub": '${AWS::StackName}-queue'},
"VisibilityTimeout": 60,
}
}
},
"Outputs": {
"Output1": {
"Value": "value",
"Export": {"Name": 'queue-us-west-1'}
}
}
}
import_value_template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"Queue": {
"Type": "AWS::SQS::Queue",
"Properties": {
"QueueName": {"Fn::ImportValue": 'queue-us-west-1'},
"VisibilityTimeout": 60,
}
}
}
}
outputs_template = dict(list(dummy_template.items()) +
list(output_dict.items()))
bad_outputs_template = dict(
list(dummy_template.items()) + list(bad_output.items()))
get_attribute_outputs_template = dict(
list(dummy_template.items()) + list(get_attribute_output.items()))
get_availability_zones_template = dict(
list(dummy_template.items()) + list(get_availability_zones_output.items()))
dummy_template_json = json.dumps(dummy_template)
name_type_template_json = json.dumps(name_type_template)
output_type_template_json = json.dumps(outputs_template)
bad_output_template_json = json.dumps(bad_outputs_template)
get_attribute_outputs_template_json = json.dumps(
get_attribute_outputs_template)
get_availability_zones_template_json = json.dumps(
get_availability_zones_template)
split_select_template_json = json.dumps(split_select_template)
sub_template_json = json.dumps(sub_template)
export_value_template_json = json.dumps(export_value_template)
import_value_template_json = json.dumps(import_value_template)
def test_parse_stack_resources():
stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=dummy_template_json,
parameters={},
region_name='us-west-1')
stack.resource_map.should.have.length_of(2)
queue = stack.resource_map['Queue']
queue.should.be.a(Queue)
queue.name.should.equal("my-queue")
bucket = stack.resource_map['S3Bucket']
bucket.should.be.a(FakeBucket)
bucket.physical_resource_id.should.equal(bucket.name)
@patch("moto.cloudformation.parsing.logger")
def test_missing_resource_logs(logger):
resource_class_from_type("foobar")
logger.warning.assert_called_with(
'No Moto CloudFormation support for %s', 'foobar')
def test_parse_stack_with_name_type_resource():
stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=name_type_template_json,
parameters={},
region_name='us-west-1')
stack.resource_map.should.have.length_of(1)
list(stack.resource_map.keys())[0].should.equal('Queue')
queue = list(stack.resource_map.values())[0]
queue.should.be.a(Queue)
def test_parse_stack_with_yaml_template():
stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=yaml.dump(name_type_template),
parameters={},
region_name='us-west-1')
stack.resource_map.should.have.length_of(1)
list(stack.resource_map.keys())[0].should.equal('Queue')
queue = list(stack.resource_map.values())[0]
queue.should.be.a(Queue)
def test_parse_stack_with_outputs():
stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=output_type_template_json,
parameters={},
region_name='us-west-1')
stack.output_map.should.have.length_of(1)
list(stack.output_map.keys())[0].should.equal('Output1')
output = list(stack.output_map.values())[0]
output.should.be.a(Output)
output.description.should.equal("This is a description.")
def test_parse_stack_with_get_attribute_outputs():
stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=get_attribute_outputs_template_json,
parameters={},
region_name='us-west-1')
stack.output_map.should.have.length_of(1)
list(stack.output_map.keys())[0].should.equal('Output1')
output = list(stack.output_map.values())[0]
output.should.be.a(Output)
output.value.should.equal("my-queue")
def test_parse_stack_with_get_attribute_kms():
from .fixtures.kms_key import template
template_json = json.dumps(template)
stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=template_json,
parameters={},
region_name='us-west-1')
stack.output_map.should.have.length_of(1)
list(stack.output_map.keys())[0].should.equal('KeyArn')
output = list(stack.output_map.values())[0]
output.should.be.a(Output)
def test_parse_stack_with_get_availability_zones():
stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=get_availability_zones_template_json,
parameters={},
region_name='us-east-1')
stack.output_map.should.have.length_of(1)
list(stack.output_map.keys())[0].should.equal('Output1')
output = list(stack.output_map.values())[0]
output.should.be.a(Output)
output.value.should.equal([ "us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d" ])
def test_parse_stack_with_bad_get_attribute_outputs():
FakeStack.when.called_with(
"test_id", "test_stack", bad_output_template_json, {}, "us-west-1").should.throw(ValidationError)
def test_parse_equals_condition():
parse_condition(
condition={"Fn::Equals": [{"Ref": "EnvType"}, "prod"]},
resources_map={"EnvType": "prod"},
condition_map={},
).should.equal(True)
parse_condition(
condition={"Fn::Equals": [{"Ref": "EnvType"}, "prod"]},
resources_map={"EnvType": "staging"},
condition_map={},
).should.equal(False)
def test_parse_not_condition():
parse_condition(
condition={
"Fn::Not": [{
"Fn::Equals": [{"Ref": "EnvType"}, "prod"]
}]
},
resources_map={"EnvType": "prod"},
condition_map={},
).should.equal(False)
parse_condition(
condition={
"Fn::Not": [{
"Fn::Equals": [{"Ref": "EnvType"}, "prod"]
}]
},
resources_map={"EnvType": "staging"},
condition_map={},
).should.equal(True)
def test_parse_and_condition():
parse_condition(
condition={
"Fn::And": [
{"Fn::Equals": [{"Ref": "EnvType"}, "prod"]},
{"Fn::Equals": [{"Ref": "EnvType"}, "staging"]},
]
},
resources_map={"EnvType": "prod"},
condition_map={},
).should.equal(False)
parse_condition(
condition={
"Fn::And": [
{"Fn::Equals": [{"Ref": "EnvType"}, "prod"]},
{"Fn::Equals": [{"Ref": "EnvType"}, "prod"]},
]
},
resources_map={"EnvType": "prod"},
condition_map={},
).should.equal(True)
def test_parse_or_condition():
parse_condition(
condition={
"Fn::Or": [
{"Fn::Equals": [{"Ref": "EnvType"}, "prod"]},
{"Fn::Equals": [{"Ref": "EnvType"}, "staging"]},
]
},
resources_map={"EnvType": "prod"},
condition_map={},
).should.equal(True)
parse_condition(
condition={
"Fn::Or": [
{"Fn::Equals": [{"Ref": "EnvType"}, "staging"]},
{"Fn::Equals": [{"Ref": "EnvType"}, "staging"]},
]
},
resources_map={"EnvType": "prod"},
condition_map={},
).should.equal(False)
def test_reference_other_conditions():
parse_condition(
condition={"Fn::Not": [{"Condition": "OtherCondition"}]},
resources_map={},
condition_map={"OtherCondition": True},
).should.equal(False)
def test_parse_split_and_select():
stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=split_select_template_json,
parameters={},
region_name='us-west-1')
stack.resource_map.should.have.length_of(1)
queue = stack.resource_map['Queue']
queue.name.should.equal("myqueue")
def test_sub():
stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=sub_template_json,
parameters={},
region_name='us-west-1')
queue1 = stack.resource_map['Queue1']
queue2 = stack.resource_map['Queue2']
queue2.name.should.equal(queue1.name)
def test_import():
export_stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=export_value_template_json,
parameters={},
region_name='us-west-1')
import_stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=import_value_template_json,
parameters={},
region_name='us-west-1',
cross_stack_resources={export_stack.exports[0].value: export_stack.exports[0]})
queue = import_stack.resource_map['Queue']
queue.name.should.equal("value")
def test_short_form_func_in_yaml_teamplate():
template = """---
KeyB64: !Base64 valueToEncode
KeyRef: !Ref foo
KeyAnd: !And
- A
- B
KeyEquals: !Equals [A, B]
KeyIf: !If [A, B, C]
KeyNot: !Not [A]
KeyOr: !Or [A, B]
KeyFindInMap: !FindInMap [A, B, C]
KeyGetAtt: !GetAtt A.B
KeyGetAZs: !GetAZs A
KeyImportValue: !ImportValue A
KeyJoin: !Join [ ":", [A, B, C] ]
KeySelect: !Select [A, B]
KeySplit: !Split [A, B]
KeySub: !Sub A
"""
yaml.add_multi_constructor('', yaml_tag_constructor, Loader=yaml.Loader)
template_dict = yaml.load(template, Loader=yaml.Loader)
key_and_expects = [
['KeyRef', {'Ref': 'foo'}],
['KeyB64', {'Fn::Base64': 'valueToEncode'}],
['KeyAnd', {'Fn::And': ['A', 'B']}],
['KeyEquals', {'Fn::Equals': ['A', 'B']}],
['KeyIf', {'Fn::If': ['A', 'B', 'C']}],
['KeyNot', {'Fn::Not': ['A']}],
['KeyOr', {'Fn::Or': ['A', 'B']}],
['KeyFindInMap', {'Fn::FindInMap': ['A', 'B', 'C']}],
['KeyGetAtt', {'Fn::GetAtt': ['A', 'B']}],
['KeyGetAZs', {'Fn::GetAZs': 'A'}],
['KeyImportValue', {'Fn::ImportValue': 'A'}],
['KeyJoin', {'Fn::Join': [ ":", [ 'A', 'B', 'C' ] ]}],
['KeySelect', {'Fn::Select': ['A', 'B']}],
['KeySplit', {'Fn::Split': ['A', 'B']}],
['KeySub', {'Fn::Sub': 'A'}],
]
for k, v in key_and_expects:
template_dict.should.have.key(k).which.should.be.equal(v)

View file

@ -0,0 +1,115 @@
from collections import OrderedDict
import json
import yaml
import os
import boto3
from nose.tools import raises
import botocore
from moto.cloudformation.exceptions import ValidationError
from moto.cloudformation.models import FakeStack
from moto.cloudformation.parsing import resource_class_from_type, parse_condition, Export
from moto.sqs.models import Queue
from moto.s3.models import FakeBucket
from moto.cloudformation.utils import yaml_tag_constructor
from boto.cloudformation.stack import Output
from moto import mock_cloudformation, mock_s3, mock_sqs, mock_ec2
json_template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Stack 1",
"Resources": {
"EC2Instance1": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": "ami-d3adb33f",
"KeyName": "dummy",
"InstanceType": "t2.micro",
"Tags": [
{
"Key": "Description",
"Value": "Test tag"
},
{
"Key": "Name",
"Value": "Name tag for tests"
}
]
}
}
}
}
# One resource is required
json_bad_template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Stack 1"
}
dummy_template_json = json.dumps(json_template)
dummy_bad_template_json = json.dumps(json_bad_template)
@mock_cloudformation
def test_boto3_json_validate_successful():
cf_conn = boto3.client('cloudformation', region_name='us-east-1')
response = cf_conn.validate_template(
TemplateBody=dummy_template_json,
)
assert response['Description'] == "Stack 1"
assert response['Parameters'] == []
assert response['ResponseMetadata']['HTTPStatusCode'] == 200
@mock_cloudformation
def test_boto3_json_invalid_missing_resource():
cf_conn = boto3.client('cloudformation', region_name='us-east-1')
try:
cf_conn.validate_template(
TemplateBody=dummy_bad_template_json,
)
assert False
except botocore.exceptions.ClientError as e:
assert str(e) == 'An error occurred (ValidationError) when calling the ValidateTemplate operation: Stack' \
' with id Missing top level item Resources to file module does not exist'
assert True
yaml_template = """
AWSTemplateFormatVersion: '2010-09-09'
Description: Simple CloudFormation Test Template
Resources:
S3Bucket:
Type: AWS::S3::Bucket
Properties:
AccessControl: PublicRead
BucketName: cf-test-bucket-1
"""
yaml_bad_template = """
AWSTemplateFormatVersion: '2010-09-09'
Description: Simple CloudFormation Test Template
"""
@mock_cloudformation
def test_boto3_yaml_validate_successful():
cf_conn = boto3.client('cloudformation', region_name='us-east-1')
response = cf_conn.validate_template(
TemplateBody=yaml_template,
)
assert response['Description'] == "Simple CloudFormation Test Template"
assert response['Parameters'] == []
assert response['ResponseMetadata']['HTTPStatusCode'] == 200
@mock_cloudformation
def test_boto3_yaml_invalid_missing_resource():
cf_conn = boto3.client('cloudformation', region_name='us-east-1')
try:
cf_conn.validate_template(
TemplateBody=yaml_bad_template,
)
assert False
except botocore.exceptions.ClientError as e:
assert str(e) == 'An error occurred (ValidationError) when calling the ValidateTemplate operation: Stack' \
' with id Missing top level item Resources to file module does not exist'
assert True

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,491 @@
from datetime import datetime, timedelta
import boto3
from botocore.exceptions import ClientError
from nose.tools import assert_raises
from moto.config import mock_config
@mock_config
def test_put_configuration_recorder():
client = boto3.client('config', region_name='us-west-2')
# Try without a name supplied:
with assert_raises(ClientError) as ce:
client.put_configuration_recorder(ConfigurationRecorder={'roleARN': 'somearn'})
assert ce.exception.response['Error']['Code'] == 'InvalidConfigurationRecorderNameException'
assert 'is not valid, blank string.' in ce.exception.response['Error']['Message']
# Try with a really long name:
with assert_raises(ClientError) as ce:
client.put_configuration_recorder(ConfigurationRecorder={'name': 'a' * 257, 'roleARN': 'somearn'})
assert ce.exception.response['Error']['Code'] == 'ValidationException'
assert 'Member must have length less than or equal to 256' in ce.exception.response['Error']['Message']
# With resource types and flags set to True:
bad_groups = [
{'allSupported': True, 'includeGlobalResourceTypes': True, 'resourceTypes': ['item']},
{'allSupported': False, 'includeGlobalResourceTypes': True, 'resourceTypes': ['item']},
{'allSupported': True, 'includeGlobalResourceTypes': False, 'resourceTypes': ['item']},
{'allSupported': False, 'includeGlobalResourceTypes': False, 'resourceTypes': []},
{'includeGlobalResourceTypes': False, 'resourceTypes': []},
{'includeGlobalResourceTypes': True},
{'resourceTypes': []},
{}
]
for bg in bad_groups:
with assert_raises(ClientError) as ce:
client.put_configuration_recorder(ConfigurationRecorder={
'name': 'default',
'roleARN': 'somearn',
'recordingGroup': bg
})
assert ce.exception.response['Error']['Code'] == 'InvalidRecordingGroupException'
assert ce.exception.response['Error']['Message'] == 'The recording group provided is not valid'
# With an invalid Resource Type:
with assert_raises(ClientError) as ce:
client.put_configuration_recorder(ConfigurationRecorder={
'name': 'default',
'roleARN': 'somearn',
'recordingGroup': {
'allSupported': False,
'includeGlobalResourceTypes': False,
# 2 good, and 2 bad:
'resourceTypes': ['AWS::EC2::Volume', 'LOLNO', 'AWS::EC2::VPC', 'LOLSTILLNO']
}
})
assert ce.exception.response['Error']['Code'] == 'ValidationException'
assert "2 validation error detected: Value '['LOLNO', 'LOLSTILLNO']" in str(ce.exception.response['Error']['Message'])
assert 'AWS::EC2::Instance' in ce.exception.response['Error']['Message']
# Create a proper one:
client.put_configuration_recorder(ConfigurationRecorder={
'name': 'testrecorder',
'roleARN': 'somearn',
'recordingGroup': {
'allSupported': False,
'includeGlobalResourceTypes': False,
'resourceTypes': ['AWS::EC2::Volume', 'AWS::EC2::VPC']
}
})
result = client.describe_configuration_recorders()['ConfigurationRecorders']
assert len(result) == 1
assert result[0]['name'] == 'testrecorder'
assert result[0]['roleARN'] == 'somearn'
assert not result[0]['recordingGroup']['allSupported']
assert not result[0]['recordingGroup']['includeGlobalResourceTypes']
assert len(result[0]['recordingGroup']['resourceTypes']) == 2
assert 'AWS::EC2::Volume' in result[0]['recordingGroup']['resourceTypes'] \
and 'AWS::EC2::VPC' in result[0]['recordingGroup']['resourceTypes']
# Now update the configuration recorder:
client.put_configuration_recorder(ConfigurationRecorder={
'name': 'testrecorder',
'roleARN': 'somearn',
'recordingGroup': {
'allSupported': True,
'includeGlobalResourceTypes': True
}
})
result = client.describe_configuration_recorders()['ConfigurationRecorders']
assert len(result) == 1
assert result[0]['name'] == 'testrecorder'
assert result[0]['roleARN'] == 'somearn'
assert result[0]['recordingGroup']['allSupported']
assert result[0]['recordingGroup']['includeGlobalResourceTypes']
assert len(result[0]['recordingGroup']['resourceTypes']) == 0
# With a default recording group (i.e. lacking one)
client.put_configuration_recorder(ConfigurationRecorder={'name': 'testrecorder', 'roleARN': 'somearn'})
result = client.describe_configuration_recorders()['ConfigurationRecorders']
assert len(result) == 1
assert result[0]['name'] == 'testrecorder'
assert result[0]['roleARN'] == 'somearn'
assert result[0]['recordingGroup']['allSupported']
assert not result[0]['recordingGroup']['includeGlobalResourceTypes']
assert not result[0]['recordingGroup'].get('resourceTypes')
# Can currently only have exactly 1 Config Recorder in an account/region:
with assert_raises(ClientError) as ce:
client.put_configuration_recorder(ConfigurationRecorder={
'name': 'someotherrecorder',
'roleARN': 'somearn',
'recordingGroup': {
'allSupported': False,
'includeGlobalResourceTypes': False,
}
})
assert ce.exception.response['Error']['Code'] == 'MaxNumberOfConfigurationRecordersExceededException'
assert "maximum number of configuration recorders: 1 is reached." in ce.exception.response['Error']['Message']
@mock_config
def test_describe_configurations():
client = boto3.client('config', region_name='us-west-2')
# Without any configurations:
result = client.describe_configuration_recorders()
assert not result['ConfigurationRecorders']
client.put_configuration_recorder(ConfigurationRecorder={
'name': 'testrecorder',
'roleARN': 'somearn',
'recordingGroup': {
'allSupported': False,
'includeGlobalResourceTypes': False,
'resourceTypes': ['AWS::EC2::Volume', 'AWS::EC2::VPC']
}
})
result = client.describe_configuration_recorders()['ConfigurationRecorders']
assert len(result) == 1
assert result[0]['name'] == 'testrecorder'
assert result[0]['roleARN'] == 'somearn'
assert not result[0]['recordingGroup']['allSupported']
assert not result[0]['recordingGroup']['includeGlobalResourceTypes']
assert len(result[0]['recordingGroup']['resourceTypes']) == 2
assert 'AWS::EC2::Volume' in result[0]['recordingGroup']['resourceTypes'] \
and 'AWS::EC2::VPC' in result[0]['recordingGroup']['resourceTypes']
# Specify an incorrect name:
with assert_raises(ClientError) as ce:
client.describe_configuration_recorders(ConfigurationRecorderNames=['wrong'])
assert ce.exception.response['Error']['Code'] == 'NoSuchConfigurationRecorderException'
assert 'wrong' in ce.exception.response['Error']['Message']
# And with both a good and wrong name:
with assert_raises(ClientError) as ce:
client.describe_configuration_recorders(ConfigurationRecorderNames=['testrecorder', 'wrong'])
assert ce.exception.response['Error']['Code'] == 'NoSuchConfigurationRecorderException'
assert 'wrong' in ce.exception.response['Error']['Message']
@mock_config
def test_delivery_channels():
client = boto3.client('config', region_name='us-west-2')
# Try without a config recorder:
with assert_raises(ClientError) as ce:
client.put_delivery_channel(DeliveryChannel={})
assert ce.exception.response['Error']['Code'] == 'NoAvailableConfigurationRecorderException'
assert ce.exception.response['Error']['Message'] == 'Configuration recorder is not available to ' \
'put delivery channel.'
# Create a config recorder to continue testing:
client.put_configuration_recorder(ConfigurationRecorder={
'name': 'testrecorder',
'roleARN': 'somearn',
'recordingGroup': {
'allSupported': False,
'includeGlobalResourceTypes': False,
'resourceTypes': ['AWS::EC2::Volume', 'AWS::EC2::VPC']
}
})
# Try without a name supplied:
with assert_raises(ClientError) as ce:
client.put_delivery_channel(DeliveryChannel={})
assert ce.exception.response['Error']['Code'] == 'InvalidDeliveryChannelNameException'
assert 'is not valid, blank string.' in ce.exception.response['Error']['Message']
# Try with a really long name:
with assert_raises(ClientError) as ce:
client.put_delivery_channel(DeliveryChannel={'name': 'a' * 257})
assert ce.exception.response['Error']['Code'] == 'ValidationException'
assert 'Member must have length less than or equal to 256' in ce.exception.response['Error']['Message']
# Without specifying a bucket name:
with assert_raises(ClientError) as ce:
client.put_delivery_channel(DeliveryChannel={'name': 'testchannel'})
assert ce.exception.response['Error']['Code'] == 'NoSuchBucketException'
assert ce.exception.response['Error']['Message'] == 'Cannot find a S3 bucket with an empty bucket name.'
with assert_raises(ClientError) as ce:
client.put_delivery_channel(DeliveryChannel={'name': 'testchannel', 's3BucketName': ''})
assert ce.exception.response['Error']['Code'] == 'NoSuchBucketException'
assert ce.exception.response['Error']['Message'] == 'Cannot find a S3 bucket with an empty bucket name.'
# With an empty string for the S3 key prefix:
with assert_raises(ClientError) as ce:
client.put_delivery_channel(DeliveryChannel={
'name': 'testchannel', 's3BucketName': 'somebucket', 's3KeyPrefix': ''})
assert ce.exception.response['Error']['Code'] == 'InvalidS3KeyPrefixException'
assert 'empty s3 key prefix.' in ce.exception.response['Error']['Message']
# With an empty string for the SNS ARN:
with assert_raises(ClientError) as ce:
client.put_delivery_channel(DeliveryChannel={
'name': 'testchannel', 's3BucketName': 'somebucket', 'snsTopicARN': ''})
assert ce.exception.response['Error']['Code'] == 'InvalidSNSTopicARNException'
assert 'The sns topic arn' in ce.exception.response['Error']['Message']
# With an invalid delivery frequency:
with assert_raises(ClientError) as ce:
client.put_delivery_channel(DeliveryChannel={
'name': 'testchannel',
's3BucketName': 'somebucket',
'configSnapshotDeliveryProperties': {'deliveryFrequency': 'WRONG'}
})
assert ce.exception.response['Error']['Code'] == 'InvalidDeliveryFrequency'
assert 'WRONG' in ce.exception.response['Error']['Message']
assert 'TwentyFour_Hours' in ce.exception.response['Error']['Message']
# Create a proper one:
client.put_delivery_channel(DeliveryChannel={'name': 'testchannel', 's3BucketName': 'somebucket'})
result = client.describe_delivery_channels()['DeliveryChannels']
assert len(result) == 1
assert len(result[0].keys()) == 2
assert result[0]['name'] == 'testchannel'
assert result[0]['s3BucketName'] == 'somebucket'
# Overwrite it with another proper configuration:
client.put_delivery_channel(DeliveryChannel={
'name': 'testchannel',
's3BucketName': 'somebucket',
'snsTopicARN': 'sometopicarn',
'configSnapshotDeliveryProperties': {'deliveryFrequency': 'TwentyFour_Hours'}
})
result = client.describe_delivery_channels()['DeliveryChannels']
assert len(result) == 1
assert len(result[0].keys()) == 4
assert result[0]['name'] == 'testchannel'
assert result[0]['s3BucketName'] == 'somebucket'
assert result[0]['snsTopicARN'] == 'sometopicarn'
assert result[0]['configSnapshotDeliveryProperties']['deliveryFrequency'] == 'TwentyFour_Hours'
# Can only have 1:
with assert_raises(ClientError) as ce:
client.put_delivery_channel(DeliveryChannel={'name': 'testchannel2', 's3BucketName': 'somebucket'})
assert ce.exception.response['Error']['Code'] == 'MaxNumberOfDeliveryChannelsExceededException'
assert 'because the maximum number of delivery channels: 1 is reached.' in ce.exception.response['Error']['Message']
@mock_config
def test_describe_delivery_channels():
client = boto3.client('config', region_name='us-west-2')
client.put_configuration_recorder(ConfigurationRecorder={
'name': 'testrecorder',
'roleARN': 'somearn',
'recordingGroup': {
'allSupported': False,
'includeGlobalResourceTypes': False,
'resourceTypes': ['AWS::EC2::Volume', 'AWS::EC2::VPC']
}
})
# Without any channels:
result = client.describe_delivery_channels()
assert not result['DeliveryChannels']
client.put_delivery_channel(DeliveryChannel={'name': 'testchannel', 's3BucketName': 'somebucket'})
result = client.describe_delivery_channels()['DeliveryChannels']
assert len(result) == 1
assert len(result[0].keys()) == 2
assert result[0]['name'] == 'testchannel'
assert result[0]['s3BucketName'] == 'somebucket'
# Overwrite it with another proper configuration:
client.put_delivery_channel(DeliveryChannel={
'name': 'testchannel',
's3BucketName': 'somebucket',
'snsTopicARN': 'sometopicarn',
'configSnapshotDeliveryProperties': {'deliveryFrequency': 'TwentyFour_Hours'}
})
result = client.describe_delivery_channels()['DeliveryChannels']
assert len(result) == 1
assert len(result[0].keys()) == 4
assert result[0]['name'] == 'testchannel'
assert result[0]['s3BucketName'] == 'somebucket'
assert result[0]['snsTopicARN'] == 'sometopicarn'
assert result[0]['configSnapshotDeliveryProperties']['deliveryFrequency'] == 'TwentyFour_Hours'
# Specify an incorrect name:
with assert_raises(ClientError) as ce:
client.describe_delivery_channels(DeliveryChannelNames=['wrong'])
assert ce.exception.response['Error']['Code'] == 'NoSuchDeliveryChannelException'
assert 'wrong' in ce.exception.response['Error']['Message']
# And with both a good and wrong name:
with assert_raises(ClientError) as ce:
client.describe_delivery_channels(DeliveryChannelNames=['testchannel', 'wrong'])
assert ce.exception.response['Error']['Code'] == 'NoSuchDeliveryChannelException'
assert 'wrong' in ce.exception.response['Error']['Message']
@mock_config
def test_start_configuration_recorder():
client = boto3.client('config', region_name='us-west-2')
# Without a config recorder:
with assert_raises(ClientError) as ce:
client.start_configuration_recorder(ConfigurationRecorderName='testrecorder')
assert ce.exception.response['Error']['Code'] == 'NoSuchConfigurationRecorderException'
# Make the config recorder;
client.put_configuration_recorder(ConfigurationRecorder={
'name': 'testrecorder',
'roleARN': 'somearn',
'recordingGroup': {
'allSupported': False,
'includeGlobalResourceTypes': False,
'resourceTypes': ['AWS::EC2::Volume', 'AWS::EC2::VPC']
}
})
# Without a delivery channel:
with assert_raises(ClientError) as ce:
client.start_configuration_recorder(ConfigurationRecorderName='testrecorder')
assert ce.exception.response['Error']['Code'] == 'NoAvailableDeliveryChannelException'
# Make the delivery channel:
client.put_delivery_channel(DeliveryChannel={'name': 'testchannel', 's3BucketName': 'somebucket'})
# Start it:
client.start_configuration_recorder(ConfigurationRecorderName='testrecorder')
# Verify it's enabled:
result = client.describe_configuration_recorder_status()['ConfigurationRecordersStatus']
lower_bound = (datetime.utcnow() - timedelta(minutes=5))
assert result[0]['recording']
assert result[0]['lastStatus'] == 'PENDING'
assert lower_bound < result[0]['lastStartTime'].replace(tzinfo=None) <= datetime.utcnow()
assert lower_bound < result[0]['lastStatusChangeTime'].replace(tzinfo=None) <= datetime.utcnow()
@mock_config
def test_stop_configuration_recorder():
client = boto3.client('config', region_name='us-west-2')
# Without a config recorder:
with assert_raises(ClientError) as ce:
client.stop_configuration_recorder(ConfigurationRecorderName='testrecorder')
assert ce.exception.response['Error']['Code'] == 'NoSuchConfigurationRecorderException'
# Make the config recorder;
client.put_configuration_recorder(ConfigurationRecorder={
'name': 'testrecorder',
'roleARN': 'somearn',
'recordingGroup': {
'allSupported': False,
'includeGlobalResourceTypes': False,
'resourceTypes': ['AWS::EC2::Volume', 'AWS::EC2::VPC']
}
})
# Make the delivery channel for creation:
client.put_delivery_channel(DeliveryChannel={'name': 'testchannel', 's3BucketName': 'somebucket'})
# Start it:
client.start_configuration_recorder(ConfigurationRecorderName='testrecorder')
client.stop_configuration_recorder(ConfigurationRecorderName='testrecorder')
# Verify it's disabled:
result = client.describe_configuration_recorder_status()['ConfigurationRecordersStatus']
lower_bound = (datetime.utcnow() - timedelta(minutes=5))
assert not result[0]['recording']
assert result[0]['lastStatus'] == 'PENDING'
assert lower_bound < result[0]['lastStartTime'].replace(tzinfo=None) <= datetime.utcnow()
assert lower_bound < result[0]['lastStopTime'].replace(tzinfo=None) <= datetime.utcnow()
assert lower_bound < result[0]['lastStatusChangeTime'].replace(tzinfo=None) <= datetime.utcnow()
@mock_config
def test_describe_configuration_recorder_status():
client = boto3.client('config', region_name='us-west-2')
# Without any:
result = client.describe_configuration_recorder_status()
assert not result['ConfigurationRecordersStatus']
# Make the config recorder;
client.put_configuration_recorder(ConfigurationRecorder={
'name': 'testrecorder',
'roleARN': 'somearn',
'recordingGroup': {
'allSupported': False,
'includeGlobalResourceTypes': False,
'resourceTypes': ['AWS::EC2::Volume', 'AWS::EC2::VPC']
}
})
# Without specifying a config recorder:
result = client.describe_configuration_recorder_status()['ConfigurationRecordersStatus']
assert len(result) == 1
assert result[0]['name'] == 'testrecorder'
assert not result[0]['recording']
# With a proper name:
result = client.describe_configuration_recorder_status(
ConfigurationRecorderNames=['testrecorder'])['ConfigurationRecordersStatus']
assert len(result) == 1
assert result[0]['name'] == 'testrecorder'
assert not result[0]['recording']
# Invalid name:
with assert_raises(ClientError) as ce:
client.describe_configuration_recorder_status(ConfigurationRecorderNames=['testrecorder', 'wrong'])
assert ce.exception.response['Error']['Code'] == 'NoSuchConfigurationRecorderException'
assert 'wrong' in ce.exception.response['Error']['Message']
@mock_config
def test_delete_configuration_recorder():
client = boto3.client('config', region_name='us-west-2')
# Make the config recorder;
client.put_configuration_recorder(ConfigurationRecorder={
'name': 'testrecorder',
'roleARN': 'somearn',
'recordingGroup': {
'allSupported': False,
'includeGlobalResourceTypes': False,
'resourceTypes': ['AWS::EC2::Volume', 'AWS::EC2::VPC']
}
})
# Delete it:
client.delete_configuration_recorder(ConfigurationRecorderName='testrecorder')
# Try again -- it should be deleted:
with assert_raises(ClientError) as ce:
client.delete_configuration_recorder(ConfigurationRecorderName='testrecorder')
assert ce.exception.response['Error']['Code'] == 'NoSuchConfigurationRecorderException'
@mock_config
def test_delete_delivery_channel():
client = boto3.client('config', region_name='us-west-2')
# Need a recorder to test the constraint on recording being enabled:
client.put_configuration_recorder(ConfigurationRecorder={
'name': 'testrecorder',
'roleARN': 'somearn',
'recordingGroup': {
'allSupported': False,
'includeGlobalResourceTypes': False,
'resourceTypes': ['AWS::EC2::Volume', 'AWS::EC2::VPC']
}
})
client.put_delivery_channel(DeliveryChannel={'name': 'testchannel', 's3BucketName': 'somebucket'})
client.start_configuration_recorder(ConfigurationRecorderName='testrecorder')
# With the recorder enabled:
with assert_raises(ClientError) as ce:
client.delete_delivery_channel(DeliveryChannelName='testchannel')
assert ce.exception.response['Error']['Code'] == 'LastDeliveryChannelDeleteFailedException'
assert 'because there is a running configuration recorder.' in ce.exception.response['Error']['Message']
# Stop recording:
client.stop_configuration_recorder(ConfigurationRecorderName='testrecorder')
# Try again:
client.delete_delivery_channel(DeliveryChannelName='testchannel')
# Verify:
with assert_raises(ClientError) as ce:
client.delete_delivery_channel(DeliveryChannelName='testchannel')
assert ce.exception.response['Error']['Code'] == 'NoSuchDeliveryChannelException'

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,234 @@
from __future__ import unicode_literals, print_function
from nose.tools import assert_raises
import boto3
from moto import mock_dynamodb2, mock_dynamodbstreams
class TestCore():
stream_arn = None
mocks = []
def setup(self):
self.mocks = [mock_dynamodb2(), mock_dynamodbstreams()]
for m in self.mocks:
m.start()
# create a table with a stream
conn = boto3.client('dynamodb', region_name='us-east-1')
resp = conn.create_table(
TableName='test-streams',
KeySchema=[{'AttributeName': 'id', 'KeyType': 'HASH'}],
AttributeDefinitions=[{'AttributeName': 'id',
'AttributeType': 'S'}],
ProvisionedThroughput={'ReadCapacityUnits': 1,
'WriteCapacityUnits': 1},
StreamSpecification={
'StreamEnabled': True,
'StreamViewType': 'NEW_AND_OLD_IMAGES'
}
)
self.stream_arn = resp['TableDescription']['LatestStreamArn']
def teardown(self):
conn = boto3.client('dynamodb', region_name='us-east-1')
conn.delete_table(TableName='test-streams')
self.stream_arn = None
for m in self.mocks:
m.stop()
def test_verify_stream(self):
conn = boto3.client('dynamodb', region_name='us-east-1')
resp = conn.describe_table(TableName='test-streams')
assert 'LatestStreamArn' in resp['Table']
def test_describe_stream(self):
conn = boto3.client('dynamodbstreams', region_name='us-east-1')
resp = conn.describe_stream(StreamArn=self.stream_arn)
assert 'StreamDescription' in resp
desc = resp['StreamDescription']
assert desc['StreamArn'] == self.stream_arn
assert desc['TableName'] == 'test-streams'
def test_list_streams(self):
conn = boto3.client('dynamodbstreams', region_name='us-east-1')
resp = conn.list_streams()
assert resp['Streams'][0]['StreamArn'] == self.stream_arn
resp = conn.list_streams(TableName='no-stream')
assert not resp['Streams']
def test_get_shard_iterator(self):
conn = boto3.client('dynamodbstreams', region_name='us-east-1')
resp = conn.describe_stream(StreamArn=self.stream_arn)
shard_id = resp['StreamDescription']['Shards'][0]['ShardId']
resp = conn.get_shard_iterator(
StreamArn=self.stream_arn,
ShardId=shard_id,
ShardIteratorType='TRIM_HORIZON'
)
assert 'ShardIterator' in resp
def test_get_records_empty(self):
conn = boto3.client('dynamodbstreams', region_name='us-east-1')
resp = conn.describe_stream(StreamArn=self.stream_arn)
shard_id = resp['StreamDescription']['Shards'][0]['ShardId']
resp = conn.get_shard_iterator(
StreamArn=self.stream_arn,
ShardId=shard_id,
ShardIteratorType='LATEST'
)
iterator_id = resp['ShardIterator']
resp = conn.get_records(ShardIterator=iterator_id)
assert 'Records' in resp
assert len(resp['Records']) == 0
def test_get_records_seq(self):
conn = boto3.client('dynamodb', region_name='us-east-1')
conn.put_item(
TableName='test-streams',
Item={
'id': {'S': 'entry1'},
'first_col': {'S': 'foo'}
}
)
conn.put_item(
TableName='test-streams',
Item={
'id': {'S': 'entry1'},
'first_col': {'S': 'bar'},
'second_col': {'S': 'baz'}
}
)
conn.delete_item(
TableName='test-streams',
Key={'id': {'S': 'entry1'}}
)
conn = boto3.client('dynamodbstreams', region_name='us-east-1')
resp = conn.describe_stream(StreamArn=self.stream_arn)
shard_id = resp['StreamDescription']['Shards'][0]['ShardId']
resp = conn.get_shard_iterator(
StreamArn=self.stream_arn,
ShardId=shard_id,
ShardIteratorType='TRIM_HORIZON'
)
iterator_id = resp['ShardIterator']
resp = conn.get_records(ShardIterator=iterator_id)
assert len(resp['Records']) == 3
assert resp['Records'][0]['eventName'] == 'INSERT'
assert resp['Records'][1]['eventName'] == 'MODIFY'
assert resp['Records'][2]['eventName'] == 'DELETE'
# now try fetching from the next shard iterator, it should be
# empty
resp = conn.get_records(ShardIterator=resp['NextShardIterator'])
assert len(resp['Records']) == 0
class TestEdges():
mocks = []
def setup(self):
self.mocks = [mock_dynamodb2(), mock_dynamodbstreams()]
for m in self.mocks:
m.start()
def teardown(self):
for m in self.mocks:
m.stop()
def test_enable_stream_on_table(self):
conn = boto3.client('dynamodb', region_name='us-east-1')
resp = conn.create_table(
TableName='test-streams',
KeySchema=[{'AttributeName': 'id', 'KeyType': 'HASH'}],
AttributeDefinitions=[{'AttributeName': 'id',
'AttributeType': 'S'}],
ProvisionedThroughput={'ReadCapacityUnits': 1,
'WriteCapacityUnits': 1}
)
assert 'StreamSpecification' not in resp['TableDescription']
resp = conn.update_table(
TableName='test-streams',
StreamSpecification={
'StreamViewType': 'KEYS_ONLY'
}
)
assert 'StreamSpecification' in resp['TableDescription']
assert resp['TableDescription']['StreamSpecification'] == {
'StreamEnabled': True,
'StreamViewType': 'KEYS_ONLY'
}
assert 'LatestStreamLabel' in resp['TableDescription']
# now try to enable it again
with assert_raises(conn.exceptions.ResourceInUseException):
resp = conn.update_table(
TableName='test-streams',
StreamSpecification={
'StreamViewType': 'OLD_IMAGES'
}
)
def test_stream_with_range_key(self):
dyn = boto3.client('dynamodb', region_name='us-east-1')
resp = dyn.create_table(
TableName='test-streams',
KeySchema=[{'AttributeName': 'id', 'KeyType': 'HASH'},
{'AttributeName': 'color', 'KeyType': 'RANGE'}],
AttributeDefinitions=[{'AttributeName': 'id',
'AttributeType': 'S'},
{'AttributeName': 'color',
'AttributeType': 'S'}],
ProvisionedThroughput={'ReadCapacityUnits': 1,
'WriteCapacityUnits': 1},
StreamSpecification={
'StreamViewType': 'NEW_IMAGES'
}
)
stream_arn = resp['TableDescription']['LatestStreamArn']
streams = boto3.client('dynamodbstreams', region_name='us-east-1')
resp = streams.describe_stream(StreamArn=stream_arn)
shard_id = resp['StreamDescription']['Shards'][0]['ShardId']
resp = streams.get_shard_iterator(
StreamArn=stream_arn,
ShardId=shard_id,
ShardIteratorType='LATEST'
)
iterator_id = resp['ShardIterator']
dyn.put_item(
TableName='test-streams',
Item={'id': {'S': 'row1'}, 'color': {'S': 'blue'}}
)
dyn.put_item(
TableName='test-streams',
Item={'id': {'S': 'row2'}, 'color': {'S': 'green'}}
)
resp = streams.get_records(ShardIterator=iterator_id)
assert len(resp['Records']) == 2
assert resp['Records'][0]['eventName'] == 'INSERT'
assert resp['Records'][1]['eventName'] == 'INSERT'

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,362 +1,367 @@
from __future__ import unicode_literals
# Ensure 'assert_raises' context manager support for Python 2.6
import tests.backport_assert_raises
from nose.tools import assert_raises
import boto3
from botocore.exceptions import ClientError
import boto
import boto.cloudformation
import boto.ec2
from boto.exception import EC2ResponseError
import sure # noqa
from moto import mock_ec2, mock_cloudformation_deprecated, mock_ec2_deprecated
from tests.helpers import requires_boto_gte
from tests.test_cloudformation.fixtures import vpc_eni
import json
@mock_ec2_deprecated
def test_elastic_network_interfaces():
conn = boto.connect_vpc('the_key', 'the_secret')
vpc = conn.create_vpc("10.0.0.0/16")
subnet = conn.create_subnet(vpc.id, "10.0.0.0/18")
with assert_raises(EC2ResponseError) as ex:
eni = conn.create_network_interface(subnet.id, dry_run=True)
ex.exception.error_code.should.equal('DryRunOperation')
ex.exception.status.should.equal(400)
ex.exception.message.should.equal(
'An error occurred (DryRunOperation) when calling the CreateNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
eni = conn.create_network_interface(subnet.id)
all_enis = conn.get_all_network_interfaces()
all_enis.should.have.length_of(1)
eni = all_enis[0]
eni.groups.should.have.length_of(0)
eni.private_ip_addresses.should.have.length_of(0)
with assert_raises(EC2ResponseError) as ex:
conn.delete_network_interface(eni.id, dry_run=True)
ex.exception.error_code.should.equal('DryRunOperation')
ex.exception.status.should.equal(400)
ex.exception.message.should.equal(
'An error occurred (DryRunOperation) when calling the DeleteNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
conn.delete_network_interface(eni.id)
all_enis = conn.get_all_network_interfaces()
all_enis.should.have.length_of(0)
with assert_raises(EC2ResponseError) as cm:
conn.delete_network_interface(eni.id)
cm.exception.error_code.should.equal('InvalidNetworkInterfaceID.NotFound')
cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none
@mock_ec2_deprecated
def test_elastic_network_interfaces_subnet_validation():
conn = boto.connect_vpc('the_key', 'the_secret')
with assert_raises(EC2ResponseError) as cm:
conn.create_network_interface("subnet-abcd1234")
cm.exception.error_code.should.equal('InvalidSubnetID.NotFound')
cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none
@mock_ec2_deprecated
def test_elastic_network_interfaces_with_private_ip():
conn = boto.connect_vpc('the_key', 'the_secret')
vpc = conn.create_vpc("10.0.0.0/16")
subnet = conn.create_subnet(vpc.id, "10.0.0.0/18")
private_ip = "54.0.0.1"
eni = conn.create_network_interface(subnet.id, private_ip)
all_enis = conn.get_all_network_interfaces()
all_enis.should.have.length_of(1)
eni = all_enis[0]
eni.groups.should.have.length_of(0)
eni.private_ip_addresses.should.have.length_of(1)
eni.private_ip_addresses[0].private_ip_address.should.equal(private_ip)
@mock_ec2_deprecated
def test_elastic_network_interfaces_with_groups():
conn = boto.connect_vpc('the_key', 'the_secret')
vpc = conn.create_vpc("10.0.0.0/16")
subnet = conn.create_subnet(vpc.id, "10.0.0.0/18")
security_group1 = conn.create_security_group(
'test security group #1', 'this is a test security group')
security_group2 = conn.create_security_group(
'test security group #2', 'this is a test security group')
conn.create_network_interface(
subnet.id, groups=[security_group1.id, security_group2.id])
all_enis = conn.get_all_network_interfaces()
all_enis.should.have.length_of(1)
eni = all_enis[0]
eni.groups.should.have.length_of(2)
set([group.id for group in eni.groups]).should.equal(
set([security_group1.id, security_group2.id]))
@requires_boto_gte("2.12.0")
@mock_ec2_deprecated
def test_elastic_network_interfaces_modify_attribute():
conn = boto.connect_vpc('the_key', 'the_secret')
vpc = conn.create_vpc("10.0.0.0/16")
subnet = conn.create_subnet(vpc.id, "10.0.0.0/18")
security_group1 = conn.create_security_group(
'test security group #1', 'this is a test security group')
security_group2 = conn.create_security_group(
'test security group #2', 'this is a test security group')
conn.create_network_interface(subnet.id, groups=[security_group1.id])
all_enis = conn.get_all_network_interfaces()
all_enis.should.have.length_of(1)
eni = all_enis[0]
eni.groups.should.have.length_of(1)
eni.groups[0].id.should.equal(security_group1.id)
with assert_raises(EC2ResponseError) as ex:
conn.modify_network_interface_attribute(
eni.id, 'groupset', [security_group2.id], dry_run=True)
ex.exception.error_code.should.equal('DryRunOperation')
ex.exception.status.should.equal(400)
ex.exception.message.should.equal(
'An error occurred (DryRunOperation) when calling the ModifyNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
conn.modify_network_interface_attribute(
eni.id, 'groupset', [security_group2.id])
all_enis = conn.get_all_network_interfaces()
all_enis.should.have.length_of(1)
eni = all_enis[0]
eni.groups.should.have.length_of(1)
eni.groups[0].id.should.equal(security_group2.id)
@mock_ec2_deprecated
def test_elastic_network_interfaces_filtering():
conn = boto.connect_vpc('the_key', 'the_secret')
vpc = conn.create_vpc("10.0.0.0/16")
subnet = conn.create_subnet(vpc.id, "10.0.0.0/18")
security_group1 = conn.create_security_group(
'test security group #1', 'this is a test security group')
security_group2 = conn.create_security_group(
'test security group #2', 'this is a test security group')
eni1 = conn.create_network_interface(
subnet.id, groups=[security_group1.id, security_group2.id])
eni2 = conn.create_network_interface(
subnet.id, groups=[security_group1.id])
eni3 = conn.create_network_interface(subnet.id)
all_enis = conn.get_all_network_interfaces()
all_enis.should.have.length_of(3)
# Filter by NetworkInterfaceId
enis_by_id = conn.get_all_network_interfaces([eni1.id])
enis_by_id.should.have.length_of(1)
set([eni.id for eni in enis_by_id]).should.equal(set([eni1.id]))
# Filter by ENI ID
enis_by_id = conn.get_all_network_interfaces(
filters={'network-interface-id': eni1.id})
enis_by_id.should.have.length_of(1)
set([eni.id for eni in enis_by_id]).should.equal(set([eni1.id]))
# Filter by Security Group
enis_by_group = conn.get_all_network_interfaces(
filters={'group-id': security_group1.id})
enis_by_group.should.have.length_of(2)
set([eni.id for eni in enis_by_group]).should.equal(set([eni1.id, eni2.id]))
# Filter by ENI ID and Security Group
enis_by_group = conn.get_all_network_interfaces(
filters={'network-interface-id': eni1.id, 'group-id': security_group1.id})
enis_by_group.should.have.length_of(1)
set([eni.id for eni in enis_by_group]).should.equal(set([eni1.id]))
# Unsupported filter
conn.get_all_network_interfaces.when.called_with(
filters={'not-implemented-filter': 'foobar'}).should.throw(NotImplementedError)
@mock_ec2
def test_elastic_network_interfaces_get_by_tag_name():
ec2 = boto3.resource('ec2', region_name='us-west-2')
ec2_client = boto3.client('ec2', region_name='us-west-2')
vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16')
subnet = ec2.create_subnet(
VpcId=vpc.id, CidrBlock='10.0.0.0/24', AvailabilityZone='us-west-2a')
eni1 = ec2.create_network_interface(
SubnetId=subnet.id, PrivateIpAddress='10.0.10.5')
with assert_raises(ClientError) as ex:
eni1.create_tags(Tags=[{'Key': 'Name', 'Value': 'eni1'}], DryRun=True)
ex.exception.response['Error']['Code'].should.equal('DryRunOperation')
ex.exception.response['ResponseMetadata'][
'HTTPStatusCode'].should.equal(400)
ex.exception.response['Error']['Message'].should.equal(
'An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
eni1.create_tags(Tags=[{'Key': 'Name', 'Value': 'eni1'}])
# The status of the new interface should be 'available'
waiter = ec2_client.get_waiter('network_interface_available')
waiter.wait(NetworkInterfaceIds=[eni1.id])
filters = [{'Name': 'tag:Name', 'Values': ['eni1']}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(1)
filters = [{'Name': 'tag:Name', 'Values': ['wrong-name']}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(0)
@mock_ec2
def test_elastic_network_interfaces_get_by_availability_zone():
ec2 = boto3.resource('ec2', region_name='us-west-2')
ec2_client = boto3.client('ec2', region_name='us-west-2')
vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16')
subnet1 = ec2.create_subnet(
VpcId=vpc.id, CidrBlock='10.0.0.0/24', AvailabilityZone='us-west-2a')
subnet2 = ec2.create_subnet(
VpcId=vpc.id, CidrBlock='10.0.1.0/24', AvailabilityZone='us-west-2b')
eni1 = ec2.create_network_interface(
SubnetId=subnet1.id, PrivateIpAddress='10.0.0.15')
eni2 = ec2.create_network_interface(
SubnetId=subnet2.id, PrivateIpAddress='10.0.1.15')
# The status of the new interface should be 'available'
waiter = ec2_client.get_waiter('network_interface_available')
waiter.wait(NetworkInterfaceIds=[eni1.id, eni2.id])
filters = [{'Name': 'availability-zone', 'Values': ['us-west-2a']}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(1)
filters = [{'Name': 'availability-zone', 'Values': ['us-west-2c']}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(0)
@mock_ec2
def test_elastic_network_interfaces_get_by_private_ip():
ec2 = boto3.resource('ec2', region_name='us-west-2')
ec2_client = boto3.client('ec2', region_name='us-west-2')
vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16')
subnet = ec2.create_subnet(
VpcId=vpc.id, CidrBlock='10.0.0.0/24', AvailabilityZone='us-west-2a')
eni1 = ec2.create_network_interface(
SubnetId=subnet.id, PrivateIpAddress='10.0.10.5')
# The status of the new interface should be 'available'
waiter = ec2_client.get_waiter('network_interface_available')
waiter.wait(NetworkInterfaceIds=[eni1.id])
filters = [{'Name': 'private-ip-address', 'Values': ['10.0.10.5']}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(1)
filters = [{'Name': 'private-ip-address', 'Values': ['10.0.10.10']}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(0)
filters = [{'Name': 'addresses.private-ip-address', 'Values': ['10.0.10.5']}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(1)
filters = [{'Name': 'addresses.private-ip-address', 'Values': ['10.0.10.10']}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(0)
@mock_ec2
def test_elastic_network_interfaces_get_by_vpc_id():
ec2 = boto3.resource('ec2', region_name='us-west-2')
ec2_client = boto3.client('ec2', region_name='us-west-2')
vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16')
subnet = ec2.create_subnet(
VpcId=vpc.id, CidrBlock='10.0.0.0/24', AvailabilityZone='us-west-2a')
eni1 = ec2.create_network_interface(
SubnetId=subnet.id, PrivateIpAddress='10.0.10.5')
# The status of the new interface should be 'available'
waiter = ec2_client.get_waiter('network_interface_available')
waiter.wait(NetworkInterfaceIds=[eni1.id])
filters = [{'Name': 'vpc-id', 'Values': [subnet.vpc_id]}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(1)
filters = [{'Name': 'vpc-id', 'Values': ['vpc-aaaa1111']}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(0)
@mock_ec2
def test_elastic_network_interfaces_get_by_subnet_id():
ec2 = boto3.resource('ec2', region_name='us-west-2')
ec2_client = boto3.client('ec2', region_name='us-west-2')
vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16')
subnet = ec2.create_subnet(
VpcId=vpc.id, CidrBlock='10.0.0.0/24', AvailabilityZone='us-west-2a')
eni1 = ec2.create_network_interface(
SubnetId=subnet.id, PrivateIpAddress='10.0.10.5')
# The status of the new interface should be 'available'
waiter = ec2_client.get_waiter('network_interface_available')
waiter.wait(NetworkInterfaceIds=[eni1.id])
filters = [{'Name': 'subnet-id', 'Values': [subnet.id]}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(1)
filters = [{'Name': 'subnet-id', 'Values': ['subnet-aaaa1111']}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(0)
@mock_ec2_deprecated
@mock_cloudformation_deprecated
def test_elastic_network_interfaces_cloudformation():
template = vpc_eni.template
template_json = json.dumps(template)
conn = boto.cloudformation.connect_to_region("us-west-1")
conn.create_stack(
"test_stack",
template_body=template_json,
)
ec2_conn = boto.ec2.connect_to_region("us-west-1")
eni = ec2_conn.get_all_network_interfaces()[0]
stack = conn.describe_stacks()[0]
resources = stack.describe_resources()
cfn_eni = [resource for resource in resources if resource.resource_type ==
'AWS::EC2::NetworkInterface'][0]
cfn_eni.physical_resource_id.should.equal(eni.id)
from __future__ import unicode_literals
# Ensure 'assert_raises' context manager support for Python 2.6
import tests.backport_assert_raises
from nose.tools import assert_raises
import boto3
from botocore.exceptions import ClientError
import boto
import boto.cloudformation
import boto.ec2
from boto.exception import EC2ResponseError
import sure # noqa
from moto import mock_ec2, mock_cloudformation_deprecated, mock_ec2_deprecated
from tests.helpers import requires_boto_gte
from tests.test_cloudformation.fixtures import vpc_eni
import json
@mock_ec2_deprecated
def test_elastic_network_interfaces():
conn = boto.connect_vpc('the_key', 'the_secret')
vpc = conn.create_vpc("10.0.0.0/16")
subnet = conn.create_subnet(vpc.id, "10.0.0.0/18")
with assert_raises(EC2ResponseError) as ex:
eni = conn.create_network_interface(subnet.id, dry_run=True)
ex.exception.error_code.should.equal('DryRunOperation')
ex.exception.status.should.equal(400)
ex.exception.message.should.equal(
'An error occurred (DryRunOperation) when calling the CreateNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
eni = conn.create_network_interface(subnet.id)
all_enis = conn.get_all_network_interfaces()
all_enis.should.have.length_of(1)
eni = all_enis[0]
eni.groups.should.have.length_of(0)
eni.private_ip_addresses.should.have.length_of(1)
eni.private_ip_addresses[0].private_ip_address.startswith('10.').should.be.true
with assert_raises(EC2ResponseError) as ex:
conn.delete_network_interface(eni.id, dry_run=True)
ex.exception.error_code.should.equal('DryRunOperation')
ex.exception.status.should.equal(400)
ex.exception.message.should.equal(
'An error occurred (DryRunOperation) when calling the DeleteNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
conn.delete_network_interface(eni.id)
all_enis = conn.get_all_network_interfaces()
all_enis.should.have.length_of(0)
with assert_raises(EC2ResponseError) as cm:
conn.delete_network_interface(eni.id)
cm.exception.error_code.should.equal('InvalidNetworkInterfaceID.NotFound')
cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none
@mock_ec2_deprecated
def test_elastic_network_interfaces_subnet_validation():
conn = boto.connect_vpc('the_key', 'the_secret')
with assert_raises(EC2ResponseError) as cm:
conn.create_network_interface("subnet-abcd1234")
cm.exception.error_code.should.equal('InvalidSubnetID.NotFound')
cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none
@mock_ec2_deprecated
def test_elastic_network_interfaces_with_private_ip():
conn = boto.connect_vpc('the_key', 'the_secret')
vpc = conn.create_vpc("10.0.0.0/16")
subnet = conn.create_subnet(vpc.id, "10.0.0.0/18")
private_ip = "54.0.0.1"
eni = conn.create_network_interface(subnet.id, private_ip)
all_enis = conn.get_all_network_interfaces()
all_enis.should.have.length_of(1)
eni = all_enis[0]
eni.groups.should.have.length_of(0)
eni.private_ip_addresses.should.have.length_of(1)
eni.private_ip_addresses[0].private_ip_address.should.equal(private_ip)
@mock_ec2_deprecated
def test_elastic_network_interfaces_with_groups():
conn = boto.connect_vpc('the_key', 'the_secret')
vpc = conn.create_vpc("10.0.0.0/16")
subnet = conn.create_subnet(vpc.id, "10.0.0.0/18")
security_group1 = conn.create_security_group(
'test security group #1', 'this is a test security group')
security_group2 = conn.create_security_group(
'test security group #2', 'this is a test security group')
conn.create_network_interface(
subnet.id, groups=[security_group1.id, security_group2.id])
all_enis = conn.get_all_network_interfaces()
all_enis.should.have.length_of(1)
eni = all_enis[0]
eni.groups.should.have.length_of(2)
set([group.id for group in eni.groups]).should.equal(
set([security_group1.id, security_group2.id]))
@requires_boto_gte("2.12.0")
@mock_ec2_deprecated
def test_elastic_network_interfaces_modify_attribute():
conn = boto.connect_vpc('the_key', 'the_secret')
vpc = conn.create_vpc("10.0.0.0/16")
subnet = conn.create_subnet(vpc.id, "10.0.0.0/18")
security_group1 = conn.create_security_group(
'test security group #1', 'this is a test security group')
security_group2 = conn.create_security_group(
'test security group #2', 'this is a test security group')
conn.create_network_interface(subnet.id, groups=[security_group1.id])
all_enis = conn.get_all_network_interfaces()
all_enis.should.have.length_of(1)
eni = all_enis[0]
eni.groups.should.have.length_of(1)
eni.groups[0].id.should.equal(security_group1.id)
with assert_raises(EC2ResponseError) as ex:
conn.modify_network_interface_attribute(
eni.id, 'groupset', [security_group2.id], dry_run=True)
ex.exception.error_code.should.equal('DryRunOperation')
ex.exception.status.should.equal(400)
ex.exception.message.should.equal(
'An error occurred (DryRunOperation) when calling the ModifyNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
conn.modify_network_interface_attribute(
eni.id, 'groupset', [security_group2.id])
all_enis = conn.get_all_network_interfaces()
all_enis.should.have.length_of(1)
eni = all_enis[0]
eni.groups.should.have.length_of(1)
eni.groups[0].id.should.equal(security_group2.id)
@mock_ec2_deprecated
def test_elastic_network_interfaces_filtering():
conn = boto.connect_vpc('the_key', 'the_secret')
vpc = conn.create_vpc("10.0.0.0/16")
subnet = conn.create_subnet(vpc.id, "10.0.0.0/18")
security_group1 = conn.create_security_group(
'test security group #1', 'this is a test security group')
security_group2 = conn.create_security_group(
'test security group #2', 'this is a test security group')
eni1 = conn.create_network_interface(
subnet.id, groups=[security_group1.id, security_group2.id])
eni2 = conn.create_network_interface(
subnet.id, groups=[security_group1.id])
eni3 = conn.create_network_interface(subnet.id)
all_enis = conn.get_all_network_interfaces()
all_enis.should.have.length_of(3)
# Filter by NetworkInterfaceId
enis_by_id = conn.get_all_network_interfaces([eni1.id])
enis_by_id.should.have.length_of(1)
set([eni.id for eni in enis_by_id]).should.equal(set([eni1.id]))
# Filter by ENI ID
enis_by_id = conn.get_all_network_interfaces(
filters={'network-interface-id': eni1.id})
enis_by_id.should.have.length_of(1)
set([eni.id for eni in enis_by_id]).should.equal(set([eni1.id]))
# Filter by Security Group
enis_by_group = conn.get_all_network_interfaces(
filters={'group-id': security_group1.id})
enis_by_group.should.have.length_of(2)
set([eni.id for eni in enis_by_group]).should.equal(set([eni1.id, eni2.id]))
# Filter by ENI ID and Security Group
enis_by_group = conn.get_all_network_interfaces(
filters={'network-interface-id': eni1.id, 'group-id': security_group1.id})
enis_by_group.should.have.length_of(1)
set([eni.id for eni in enis_by_group]).should.equal(set([eni1.id]))
# Unsupported filter
conn.get_all_network_interfaces.when.called_with(
filters={'not-implemented-filter': 'foobar'}).should.throw(NotImplementedError)
@mock_ec2
def test_elastic_network_interfaces_get_by_tag_name():
ec2 = boto3.resource('ec2', region_name='us-west-2')
ec2_client = boto3.client('ec2', region_name='us-west-2')
vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16')
subnet = ec2.create_subnet(
VpcId=vpc.id, CidrBlock='10.0.0.0/24', AvailabilityZone='us-west-2a')
eni1 = ec2.create_network_interface(
SubnetId=subnet.id, PrivateIpAddress='10.0.10.5')
with assert_raises(ClientError) as ex:
eni1.create_tags(Tags=[{'Key': 'Name', 'Value': 'eni1'}], DryRun=True)
ex.exception.response['Error']['Code'].should.equal('DryRunOperation')
ex.exception.response['ResponseMetadata'][
'HTTPStatusCode'].should.equal(400)
ex.exception.response['Error']['Message'].should.equal(
'An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
eni1.create_tags(Tags=[{'Key': 'Name', 'Value': 'eni1'}])
# The status of the new interface should be 'available'
waiter = ec2_client.get_waiter('network_interface_available')
waiter.wait(NetworkInterfaceIds=[eni1.id])
filters = [{'Name': 'tag:Name', 'Values': ['eni1']}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(1)
filters = [{'Name': 'tag:Name', 'Values': ['wrong-name']}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(0)
@mock_ec2
def test_elastic_network_interfaces_get_by_availability_zone():
ec2 = boto3.resource('ec2', region_name='us-west-2')
ec2_client = boto3.client('ec2', region_name='us-west-2')
vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16')
subnet1 = ec2.create_subnet(
VpcId=vpc.id, CidrBlock='10.0.0.0/24', AvailabilityZone='us-west-2a')
subnet2 = ec2.create_subnet(
VpcId=vpc.id, CidrBlock='10.0.1.0/24', AvailabilityZone='us-west-2b')
eni1 = ec2.create_network_interface(
SubnetId=subnet1.id, PrivateIpAddress='10.0.0.15')
eni2 = ec2.create_network_interface(
SubnetId=subnet2.id, PrivateIpAddress='10.0.1.15')
# The status of the new interface should be 'available'
waiter = ec2_client.get_waiter('network_interface_available')
waiter.wait(NetworkInterfaceIds=[eni1.id, eni2.id])
filters = [{'Name': 'availability-zone', 'Values': ['us-west-2a']}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(1)
filters = [{'Name': 'availability-zone', 'Values': ['us-west-2c']}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(0)
@mock_ec2
def test_elastic_network_interfaces_get_by_private_ip():
ec2 = boto3.resource('ec2', region_name='us-west-2')
ec2_client = boto3.client('ec2', region_name='us-west-2')
vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16')
subnet = ec2.create_subnet(
VpcId=vpc.id, CidrBlock='10.0.0.0/24', AvailabilityZone='us-west-2a')
eni1 = ec2.create_network_interface(
SubnetId=subnet.id, PrivateIpAddress='10.0.10.5')
# The status of the new interface should be 'available'
waiter = ec2_client.get_waiter('network_interface_available')
waiter.wait(NetworkInterfaceIds=[eni1.id])
filters = [{'Name': 'private-ip-address', 'Values': ['10.0.10.5']}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(1)
filters = [{'Name': 'private-ip-address', 'Values': ['10.0.10.10']}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(0)
filters = [{'Name': 'addresses.private-ip-address', 'Values': ['10.0.10.5']}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(1)
filters = [{'Name': 'addresses.private-ip-address', 'Values': ['10.0.10.10']}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(0)
@mock_ec2
def test_elastic_network_interfaces_get_by_vpc_id():
ec2 = boto3.resource('ec2', region_name='us-west-2')
ec2_client = boto3.client('ec2', region_name='us-west-2')
vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16')
subnet = ec2.create_subnet(
VpcId=vpc.id, CidrBlock='10.0.0.0/24', AvailabilityZone='us-west-2a')
eni1 = ec2.create_network_interface(
SubnetId=subnet.id, PrivateIpAddress='10.0.10.5')
# The status of the new interface should be 'available'
waiter = ec2_client.get_waiter('network_interface_available')
waiter.wait(NetworkInterfaceIds=[eni1.id])
filters = [{'Name': 'vpc-id', 'Values': [subnet.vpc_id]}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(1)
filters = [{'Name': 'vpc-id', 'Values': ['vpc-aaaa1111']}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(0)
@mock_ec2
def test_elastic_network_interfaces_get_by_subnet_id():
ec2 = boto3.resource('ec2', region_name='us-west-2')
ec2_client = boto3.client('ec2', region_name='us-west-2')
vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16')
subnet = ec2.create_subnet(
VpcId=vpc.id, CidrBlock='10.0.0.0/24', AvailabilityZone='us-west-2a')
eni1 = ec2.create_network_interface(
SubnetId=subnet.id, PrivateIpAddress='10.0.10.5')
# The status of the new interface should be 'available'
waiter = ec2_client.get_waiter('network_interface_available')
waiter.wait(NetworkInterfaceIds=[eni1.id])
filters = [{'Name': 'subnet-id', 'Values': [subnet.id]}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(1)
filters = [{'Name': 'subnet-id', 'Values': ['subnet-aaaa1111']}]
enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(0)
@mock_ec2_deprecated
@mock_cloudformation_deprecated
def test_elastic_network_interfaces_cloudformation():
template = vpc_eni.template
template_json = json.dumps(template)
conn = boto.cloudformation.connect_to_region("us-west-1")
conn.create_stack(
"test_stack",
template_body=template_json,
)
ec2_conn = boto.ec2.connect_to_region("us-west-1")
eni = ec2_conn.get_all_network_interfaces()[0]
eni.private_ip_addresses.should.have.length_of(1)
stack = conn.describe_stacks()[0]
resources = stack.describe_resources()
cfn_eni = [resource for resource in resources if resource.resource_type ==
'AWS::EC2::NetworkInterface'][0]
cfn_eni.physical_resource_id.should.equal(eni.id)
outputs = {output.key: output.value for output in stack.outputs}
outputs['ENIIpAddress'].should.equal(eni.private_ip_addresses[0].private_ip_address)

File diff suppressed because it is too large Load diff

View file

@ -1,175 +1,216 @@
from __future__ import unicode_literals
import boto
import sure # noqa
from moto import mock_ec2_deprecated
@mock_ec2_deprecated
def test_default_network_acl_created_with_vpc():
conn = boto.connect_vpc('the_key', 'the secret')
vpc = conn.create_vpc("10.0.0.0/16")
all_network_acls = conn.get_all_network_acls()
all_network_acls.should.have.length_of(2)
@mock_ec2_deprecated
def test_network_acls():
conn = boto.connect_vpc('the_key', 'the secret')
vpc = conn.create_vpc("10.0.0.0/16")
network_acl = conn.create_network_acl(vpc.id)
all_network_acls = conn.get_all_network_acls()
all_network_acls.should.have.length_of(3)
@mock_ec2_deprecated
def test_new_subnet_associates_with_default_network_acl():
conn = boto.connect_vpc('the_key', 'the secret')
vpc = conn.get_all_vpcs()[0]
subnet = conn.create_subnet(vpc.id, "10.0.0.0/18")
all_network_acls = conn.get_all_network_acls()
all_network_acls.should.have.length_of(1)
acl = all_network_acls[0]
acl.associations.should.have.length_of(4)
[a.subnet_id for a in acl.associations].should.contain(subnet.id)
@mock_ec2_deprecated
def test_network_acl_entries():
conn = boto.connect_vpc('the_key', 'the secret')
vpc = conn.create_vpc("10.0.0.0/16")
network_acl = conn.create_network_acl(vpc.id)
network_acl_entry = conn.create_network_acl_entry(
network_acl.id, 110, 6,
'ALLOW', '0.0.0.0/0', False,
port_range_from='443',
port_range_to='443'
)
all_network_acls = conn.get_all_network_acls()
all_network_acls.should.have.length_of(3)
test_network_acl = next(na for na in all_network_acls
if na.id == network_acl.id)
entries = test_network_acl.network_acl_entries
entries.should.have.length_of(1)
entries[0].rule_number.should.equal('110')
entries[0].protocol.should.equal('6')
entries[0].rule_action.should.equal('ALLOW')
@mock_ec2_deprecated
def test_delete_network_acl_entry():
conn = boto.connect_vpc('the_key', 'the secret')
vpc = conn.create_vpc("10.0.0.0/16")
network_acl = conn.create_network_acl(vpc.id)
conn.create_network_acl_entry(
network_acl.id, 110, 6,
'ALLOW', '0.0.0.0/0', False,
port_range_from='443',
port_range_to='443'
)
conn.delete_network_acl_entry(
network_acl.id, 110, False
)
all_network_acls = conn.get_all_network_acls()
test_network_acl = next(na for na in all_network_acls
if na.id == network_acl.id)
entries = test_network_acl.network_acl_entries
entries.should.have.length_of(0)
@mock_ec2_deprecated
def test_replace_network_acl_entry():
conn = boto.connect_vpc('the_key', 'the secret')
vpc = conn.create_vpc("10.0.0.0/16")
network_acl = conn.create_network_acl(vpc.id)
conn.create_network_acl_entry(
network_acl.id, 110, 6,
'ALLOW', '0.0.0.0/0', False,
port_range_from='443',
port_range_to='443'
)
conn.replace_network_acl_entry(
network_acl.id, 110, -1,
'DENY', '0.0.0.0/0', False,
port_range_from='22',
port_range_to='22'
)
all_network_acls = conn.get_all_network_acls()
test_network_acl = next(na for na in all_network_acls
if na.id == network_acl.id)
entries = test_network_acl.network_acl_entries
entries.should.have.length_of(1)
entries[0].rule_number.should.equal('110')
entries[0].protocol.should.equal('-1')
entries[0].rule_action.should.equal('DENY')
@mock_ec2_deprecated
def test_associate_new_network_acl_with_subnet():
conn = boto.connect_vpc('the_key', 'the secret')
vpc = conn.create_vpc("10.0.0.0/16")
subnet = conn.create_subnet(vpc.id, "10.0.0.0/18")
network_acl = conn.create_network_acl(vpc.id)
conn.associate_network_acl(network_acl.id, subnet.id)
all_network_acls = conn.get_all_network_acls()
all_network_acls.should.have.length_of(3)
test_network_acl = next(na for na in all_network_acls
if na.id == network_acl.id)
test_network_acl.associations.should.have.length_of(1)
test_network_acl.associations[0].subnet_id.should.equal(subnet.id)
@mock_ec2_deprecated
def test_delete_network_acl():
conn = boto.connect_vpc('the_key', 'the secret')
vpc = conn.create_vpc("10.0.0.0/16")
subnet = conn.create_subnet(vpc.id, "10.0.0.0/18")
network_acl = conn.create_network_acl(vpc.id)
all_network_acls = conn.get_all_network_acls()
all_network_acls.should.have.length_of(3)
any(acl.id == network_acl.id for acl in all_network_acls).should.be.ok
conn.delete_network_acl(network_acl.id)
updated_network_acls = conn.get_all_network_acls()
updated_network_acls.should.have.length_of(2)
any(acl.id == network_acl.id for acl in updated_network_acls).shouldnt.be.ok
@mock_ec2_deprecated
def test_network_acl_tagging():
conn = boto.connect_vpc('the_key', 'the secret')
vpc = conn.create_vpc("10.0.0.0/16")
network_acl = conn.create_network_acl(vpc.id)
network_acl.add_tag("a key", "some value")
tag = conn.get_all_tags()[0]
tag.name.should.equal("a key")
tag.value.should.equal("some value")
all_network_acls = conn.get_all_network_acls()
test_network_acl = next(na for na in all_network_acls
if na.id == network_acl.id)
test_network_acl.tags.should.have.length_of(1)
test_network_acl.tags["a key"].should.equal("some value")
from __future__ import unicode_literals
import boto
import boto3
import sure # noqa
from moto import mock_ec2_deprecated, mock_ec2
@mock_ec2_deprecated
def test_default_network_acl_created_with_vpc():
conn = boto.connect_vpc('the_key', 'the secret')
vpc = conn.create_vpc("10.0.0.0/16")
all_network_acls = conn.get_all_network_acls()
all_network_acls.should.have.length_of(2)
@mock_ec2_deprecated
def test_network_acls():
conn = boto.connect_vpc('the_key', 'the secret')
vpc = conn.create_vpc("10.0.0.0/16")
network_acl = conn.create_network_acl(vpc.id)
all_network_acls = conn.get_all_network_acls()
all_network_acls.should.have.length_of(3)
@mock_ec2_deprecated
def test_new_subnet_associates_with_default_network_acl():
conn = boto.connect_vpc('the_key', 'the secret')
vpc = conn.get_all_vpcs()[0]
subnet = conn.create_subnet(vpc.id, "10.0.0.0/18")
all_network_acls = conn.get_all_network_acls()
all_network_acls.should.have.length_of(1)
acl = all_network_acls[0]
acl.associations.should.have.length_of(4)
[a.subnet_id for a in acl.associations].should.contain(subnet.id)
@mock_ec2_deprecated
def test_network_acl_entries():
conn = boto.connect_vpc('the_key', 'the secret')
vpc = conn.create_vpc("10.0.0.0/16")
network_acl = conn.create_network_acl(vpc.id)
network_acl_entry = conn.create_network_acl_entry(
network_acl.id, 110, 6,
'ALLOW', '0.0.0.0/0', False,
port_range_from='443',
port_range_to='443'
)
all_network_acls = conn.get_all_network_acls()
all_network_acls.should.have.length_of(3)
test_network_acl = next(na for na in all_network_acls
if na.id == network_acl.id)
entries = test_network_acl.network_acl_entries
entries.should.have.length_of(1)
entries[0].rule_number.should.equal('110')
entries[0].protocol.should.equal('6')
entries[0].rule_action.should.equal('ALLOW')
@mock_ec2_deprecated
def test_delete_network_acl_entry():
conn = boto.connect_vpc('the_key', 'the secret')
vpc = conn.create_vpc("10.0.0.0/16")
network_acl = conn.create_network_acl(vpc.id)
conn.create_network_acl_entry(
network_acl.id, 110, 6,
'ALLOW', '0.0.0.0/0', False,
port_range_from='443',
port_range_to='443'
)
conn.delete_network_acl_entry(
network_acl.id, 110, False
)
all_network_acls = conn.get_all_network_acls()
test_network_acl = next(na for na in all_network_acls
if na.id == network_acl.id)
entries = test_network_acl.network_acl_entries
entries.should.have.length_of(0)
@mock_ec2_deprecated
def test_replace_network_acl_entry():
conn = boto.connect_vpc('the_key', 'the secret')
vpc = conn.create_vpc("10.0.0.0/16")
network_acl = conn.create_network_acl(vpc.id)
conn.create_network_acl_entry(
network_acl.id, 110, 6,
'ALLOW', '0.0.0.0/0', False,
port_range_from='443',
port_range_to='443'
)
conn.replace_network_acl_entry(
network_acl.id, 110, -1,
'DENY', '0.0.0.0/0', False,
port_range_from='22',
port_range_to='22'
)
all_network_acls = conn.get_all_network_acls()
test_network_acl = next(na for na in all_network_acls
if na.id == network_acl.id)
entries = test_network_acl.network_acl_entries
entries.should.have.length_of(1)
entries[0].rule_number.should.equal('110')
entries[0].protocol.should.equal('-1')
entries[0].rule_action.should.equal('DENY')
@mock_ec2_deprecated
def test_associate_new_network_acl_with_subnet():
conn = boto.connect_vpc('the_key', 'the secret')
vpc = conn.create_vpc("10.0.0.0/16")
subnet = conn.create_subnet(vpc.id, "10.0.0.0/18")
network_acl = conn.create_network_acl(vpc.id)
conn.associate_network_acl(network_acl.id, subnet.id)
all_network_acls = conn.get_all_network_acls()
all_network_acls.should.have.length_of(3)
test_network_acl = next(na for na in all_network_acls
if na.id == network_acl.id)
test_network_acl.associations.should.have.length_of(1)
test_network_acl.associations[0].subnet_id.should.equal(subnet.id)
@mock_ec2_deprecated
def test_delete_network_acl():
conn = boto.connect_vpc('the_key', 'the secret')
vpc = conn.create_vpc("10.0.0.0/16")
subnet = conn.create_subnet(vpc.id, "10.0.0.0/18")
network_acl = conn.create_network_acl(vpc.id)
all_network_acls = conn.get_all_network_acls()
all_network_acls.should.have.length_of(3)
any(acl.id == network_acl.id for acl in all_network_acls).should.be.ok
conn.delete_network_acl(network_acl.id)
updated_network_acls = conn.get_all_network_acls()
updated_network_acls.should.have.length_of(2)
any(acl.id == network_acl.id for acl in updated_network_acls).shouldnt.be.ok
@mock_ec2_deprecated
def test_network_acl_tagging():
conn = boto.connect_vpc('the_key', 'the secret')
vpc = conn.create_vpc("10.0.0.0/16")
network_acl = conn.create_network_acl(vpc.id)
network_acl.add_tag("a key", "some value")
tag = conn.get_all_tags()[0]
tag.name.should.equal("a key")
tag.value.should.equal("some value")
all_network_acls = conn.get_all_network_acls()
test_network_acl = next(na for na in all_network_acls
if na.id == network_acl.id)
test_network_acl.tags.should.have.length_of(1)
test_network_acl.tags["a key"].should.equal("some value")
@mock_ec2
def test_new_subnet_in_new_vpc_associates_with_default_network_acl():
ec2 = boto3.resource('ec2', region_name='us-west-1')
new_vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16')
new_vpc.reload()
subnet = ec2.create_subnet(VpcId=new_vpc.id, CidrBlock='10.0.0.0/24')
subnet.reload()
new_vpcs_default_network_acl = next(iter(new_vpc.network_acls.all()), None)
new_vpcs_default_network_acl.reload()
new_vpcs_default_network_acl.vpc_id.should.equal(new_vpc.id)
new_vpcs_default_network_acl.associations.should.have.length_of(1)
new_vpcs_default_network_acl.associations[0]['SubnetId'].should.equal(subnet.id)
@mock_ec2
def test_default_network_acl_default_entries():
ec2 = boto3.resource('ec2', region_name='us-west-1')
default_network_acl = next(iter(ec2.network_acls.all()), None)
default_network_acl.is_default.should.be.ok
default_network_acl.entries.should.have.length_of(4)
unique_entries = []
for entry in default_network_acl.entries:
entry['CidrBlock'].should.equal('0.0.0.0/0')
entry['Protocol'].should.equal('-1')
entry['RuleNumber'].should.be.within([100, 32767])
entry['RuleAction'].should.be.within(['allow', 'deny'])
assert type(entry['Egress']) is bool
if entry['RuleAction'] == 'allow':
entry['RuleNumber'].should.be.equal(100)
else:
entry['RuleNumber'].should.be.equal(32767)
if entry not in unique_entries:
unique_entries.append(entry)
unique_entries.should.have.length_of(4)

View file

@ -1,345 +1,387 @@
from __future__ import unicode_literals
import boto3
import sure # noqa
from moto import mock_ec2
def get_subnet_id(conn):
vpc = conn.create_vpc(CidrBlock="10.0.0.0/8")['Vpc']
subnet = conn.create_subnet(
VpcId=vpc['VpcId'], CidrBlock='10.0.0.0/16', AvailabilityZone='us-east-1a')['Subnet']
subnet_id = subnet['SubnetId']
return subnet_id
def spot_config(subnet_id, allocation_strategy="lowestPrice"):
return {
'ClientToken': 'string',
'SpotPrice': '0.12',
'TargetCapacity': 6,
'IamFleetRole': 'arn:aws:iam::123456789012:role/fleet',
'LaunchSpecifications': [{
'ImageId': 'ami-123',
'KeyName': 'my-key',
'SecurityGroups': [
{
'GroupId': 'sg-123'
},
],
'UserData': 'some user data',
'InstanceType': 't2.small',
'BlockDeviceMappings': [
{
'VirtualName': 'string',
'DeviceName': 'string',
'Ebs': {
'SnapshotId': 'string',
'VolumeSize': 123,
'DeleteOnTermination': True | False,
'VolumeType': 'standard',
'Iops': 123,
'Encrypted': True | False
},
'NoDevice': 'string'
},
],
'Monitoring': {
'Enabled': True
},
'SubnetId': subnet_id,
'IamInstanceProfile': {
'Arn': 'arn:aws:iam::123456789012:role/fleet'
},
'EbsOptimized': False,
'WeightedCapacity': 2.0,
'SpotPrice': '0.13'
}, {
'ImageId': 'ami-123',
'KeyName': 'my-key',
'SecurityGroups': [
{
'GroupId': 'sg-123'
},
],
'UserData': 'some user data',
'InstanceType': 't2.large',
'Monitoring': {
'Enabled': True
},
'SubnetId': subnet_id,
'IamInstanceProfile': {
'Arn': 'arn:aws:iam::123456789012:role/fleet'
},
'EbsOptimized': False,
'WeightedCapacity': 4.0,
'SpotPrice': '10.00',
}],
'AllocationStrategy': allocation_strategy,
'FulfilledCapacity': 6,
}
@mock_ec2
def test_create_spot_fleet_with_lowest_price():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
spot_fleet_res = conn.request_spot_fleet(
SpotFleetRequestConfig=spot_config(subnet_id)
)
spot_fleet_id = spot_fleet_res['SpotFleetRequestId']
spot_fleet_requests = conn.describe_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id])['SpotFleetRequestConfigs']
len(spot_fleet_requests).should.equal(1)
spot_fleet_request = spot_fleet_requests[0]
spot_fleet_request['SpotFleetRequestState'].should.equal("active")
spot_fleet_config = spot_fleet_request['SpotFleetRequestConfig']
spot_fleet_config['SpotPrice'].should.equal('0.12')
spot_fleet_config['TargetCapacity'].should.equal(6)
spot_fleet_config['IamFleetRole'].should.equal(
'arn:aws:iam::123456789012:role/fleet')
spot_fleet_config['AllocationStrategy'].should.equal('lowestPrice')
spot_fleet_config['FulfilledCapacity'].should.equal(6.0)
len(spot_fleet_config['LaunchSpecifications']).should.equal(2)
launch_spec = spot_fleet_config['LaunchSpecifications'][0]
launch_spec['EbsOptimized'].should.equal(False)
launch_spec['SecurityGroups'].should.equal([{"GroupId": "sg-123"}])
launch_spec['IamInstanceProfile'].should.equal(
{"Arn": "arn:aws:iam::123456789012:role/fleet"})
launch_spec['ImageId'].should.equal("ami-123")
launch_spec['InstanceType'].should.equal("t2.small")
launch_spec['KeyName'].should.equal("my-key")
launch_spec['Monitoring'].should.equal({"Enabled": True})
launch_spec['SpotPrice'].should.equal("0.13")
launch_spec['SubnetId'].should.equal(subnet_id)
launch_spec['UserData'].should.equal("some user data")
launch_spec['WeightedCapacity'].should.equal(2.0)
instance_res = conn.describe_spot_fleet_instances(
SpotFleetRequestId=spot_fleet_id)
instances = instance_res['ActiveInstances']
len(instances).should.equal(3)
@mock_ec2
def test_create_diversified_spot_fleet():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
diversified_config = spot_config(
subnet_id, allocation_strategy='diversified')
spot_fleet_res = conn.request_spot_fleet(
SpotFleetRequestConfig=diversified_config
)
spot_fleet_id = spot_fleet_res['SpotFleetRequestId']
instance_res = conn.describe_spot_fleet_instances(
SpotFleetRequestId=spot_fleet_id)
instances = instance_res['ActiveInstances']
len(instances).should.equal(2)
instance_types = set([instance['InstanceType'] for instance in instances])
instance_types.should.equal(set(["t2.small", "t2.large"]))
instances[0]['InstanceId'].should.contain("i-")
@mock_ec2
def test_cancel_spot_fleet_request():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
spot_fleet_res = conn.request_spot_fleet(
SpotFleetRequestConfig=spot_config(subnet_id),
)
spot_fleet_id = spot_fleet_res['SpotFleetRequestId']
conn.cancel_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id], TerminateInstances=True)
spot_fleet_requests = conn.describe_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id])['SpotFleetRequestConfigs']
len(spot_fleet_requests).should.equal(0)
@mock_ec2
def test_modify_spot_fleet_request_up():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
spot_fleet_res = conn.request_spot_fleet(
SpotFleetRequestConfig=spot_config(subnet_id),
)
spot_fleet_id = spot_fleet_res['SpotFleetRequestId']
conn.modify_spot_fleet_request(
SpotFleetRequestId=spot_fleet_id, TargetCapacity=20)
instance_res = conn.describe_spot_fleet_instances(
SpotFleetRequestId=spot_fleet_id)
instances = instance_res['ActiveInstances']
len(instances).should.equal(10)
spot_fleet_config = conn.describe_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id])['SpotFleetRequestConfigs'][0]['SpotFleetRequestConfig']
spot_fleet_config['TargetCapacity'].should.equal(20)
spot_fleet_config['FulfilledCapacity'].should.equal(20.0)
@mock_ec2
def test_modify_spot_fleet_request_up_diversified():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
spot_fleet_res = conn.request_spot_fleet(
SpotFleetRequestConfig=spot_config(
subnet_id, allocation_strategy='diversified'),
)
spot_fleet_id = spot_fleet_res['SpotFleetRequestId']
conn.modify_spot_fleet_request(
SpotFleetRequestId=spot_fleet_id, TargetCapacity=19)
instance_res = conn.describe_spot_fleet_instances(
SpotFleetRequestId=spot_fleet_id)
instances = instance_res['ActiveInstances']
len(instances).should.equal(7)
spot_fleet_config = conn.describe_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id])['SpotFleetRequestConfigs'][0]['SpotFleetRequestConfig']
spot_fleet_config['TargetCapacity'].should.equal(19)
spot_fleet_config['FulfilledCapacity'].should.equal(20.0)
@mock_ec2
def test_modify_spot_fleet_request_down_no_terminate():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
spot_fleet_res = conn.request_spot_fleet(
SpotFleetRequestConfig=spot_config(subnet_id),
)
spot_fleet_id = spot_fleet_res['SpotFleetRequestId']
conn.modify_spot_fleet_request(
SpotFleetRequestId=spot_fleet_id, TargetCapacity=1, ExcessCapacityTerminationPolicy="noTermination")
instance_res = conn.describe_spot_fleet_instances(
SpotFleetRequestId=spot_fleet_id)
instances = instance_res['ActiveInstances']
len(instances).should.equal(3)
spot_fleet_config = conn.describe_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id])['SpotFleetRequestConfigs'][0]['SpotFleetRequestConfig']
spot_fleet_config['TargetCapacity'].should.equal(1)
spot_fleet_config['FulfilledCapacity'].should.equal(6.0)
@mock_ec2
def test_modify_spot_fleet_request_down_odd():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
spot_fleet_res = conn.request_spot_fleet(
SpotFleetRequestConfig=spot_config(subnet_id),
)
spot_fleet_id = spot_fleet_res['SpotFleetRequestId']
conn.modify_spot_fleet_request(
SpotFleetRequestId=spot_fleet_id, TargetCapacity=7)
conn.modify_spot_fleet_request(
SpotFleetRequestId=spot_fleet_id, TargetCapacity=5)
instance_res = conn.describe_spot_fleet_instances(
SpotFleetRequestId=spot_fleet_id)
instances = instance_res['ActiveInstances']
len(instances).should.equal(3)
spot_fleet_config = conn.describe_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id])['SpotFleetRequestConfigs'][0]['SpotFleetRequestConfig']
spot_fleet_config['TargetCapacity'].should.equal(5)
spot_fleet_config['FulfilledCapacity'].should.equal(6.0)
@mock_ec2
def test_modify_spot_fleet_request_down():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
spot_fleet_res = conn.request_spot_fleet(
SpotFleetRequestConfig=spot_config(subnet_id),
)
spot_fleet_id = spot_fleet_res['SpotFleetRequestId']
conn.modify_spot_fleet_request(
SpotFleetRequestId=spot_fleet_id, TargetCapacity=1)
instance_res = conn.describe_spot_fleet_instances(
SpotFleetRequestId=spot_fleet_id)
instances = instance_res['ActiveInstances']
len(instances).should.equal(1)
spot_fleet_config = conn.describe_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id])['SpotFleetRequestConfigs'][0]['SpotFleetRequestConfig']
spot_fleet_config['TargetCapacity'].should.equal(1)
spot_fleet_config['FulfilledCapacity'].should.equal(2.0)
@mock_ec2
def test_modify_spot_fleet_request_down_no_terminate_after_custom_terminate():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
spot_fleet_res = conn.request_spot_fleet(
SpotFleetRequestConfig=spot_config(subnet_id),
)
spot_fleet_id = spot_fleet_res['SpotFleetRequestId']
instance_res = conn.describe_spot_fleet_instances(
SpotFleetRequestId=spot_fleet_id)
instances = instance_res['ActiveInstances']
conn.terminate_instances(InstanceIds=[i['InstanceId'] for i in instances[1:]])
conn.modify_spot_fleet_request(
SpotFleetRequestId=spot_fleet_id, TargetCapacity=1, ExcessCapacityTerminationPolicy="noTermination")
instance_res = conn.describe_spot_fleet_instances(
SpotFleetRequestId=spot_fleet_id)
instances = instance_res['ActiveInstances']
len(instances).should.equal(1)
spot_fleet_config = conn.describe_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id])['SpotFleetRequestConfigs'][0]['SpotFleetRequestConfig']
spot_fleet_config['TargetCapacity'].should.equal(1)
spot_fleet_config['FulfilledCapacity'].should.equal(2.0)
@mock_ec2
def test_create_spot_fleet_without_spot_price():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
# remove prices to force a fallback to ondemand price
spot_config_without_price = spot_config(subnet_id)
del spot_config_without_price['SpotPrice']
for spec in spot_config_without_price['LaunchSpecifications']:
del spec['SpotPrice']
spot_fleet_id = conn.request_spot_fleet(SpotFleetRequestConfig=spot_config_without_price)['SpotFleetRequestId']
spot_fleet_requests = conn.describe_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id])['SpotFleetRequestConfigs']
len(spot_fleet_requests).should.equal(1)
spot_fleet_request = spot_fleet_requests[0]
spot_fleet_config = spot_fleet_request['SpotFleetRequestConfig']
len(spot_fleet_config['LaunchSpecifications']).should.equal(2)
launch_spec1 = spot_fleet_config['LaunchSpecifications'][0]
launch_spec2 = spot_fleet_config['LaunchSpecifications'][1]
# AWS will figure out the price
assert 'SpotPrice' not in launch_spec1
assert 'SpotPrice' not in launch_spec2
from __future__ import unicode_literals
import boto3
import sure # noqa
from moto import mock_ec2
def get_subnet_id(conn):
vpc = conn.create_vpc(CidrBlock="10.0.0.0/8")['Vpc']
subnet = conn.create_subnet(
VpcId=vpc['VpcId'], CidrBlock='10.0.0.0/16', AvailabilityZone='us-east-1a')['Subnet']
subnet_id = subnet['SubnetId']
return subnet_id
def spot_config(subnet_id, allocation_strategy="lowestPrice"):
return {
'ClientToken': 'string',
'SpotPrice': '0.12',
'TargetCapacity': 6,
'IamFleetRole': 'arn:aws:iam::123456789012:role/fleet',
'LaunchSpecifications': [{
'ImageId': 'ami-123',
'KeyName': 'my-key',
'SecurityGroups': [
{
'GroupId': 'sg-123'
},
],
'UserData': 'some user data',
'InstanceType': 't2.small',
'BlockDeviceMappings': [
{
'VirtualName': 'string',
'DeviceName': 'string',
'Ebs': {
'SnapshotId': 'string',
'VolumeSize': 123,
'DeleteOnTermination': True | False,
'VolumeType': 'standard',
'Iops': 123,
'Encrypted': True | False
},
'NoDevice': 'string'
},
],
'Monitoring': {
'Enabled': True
},
'SubnetId': subnet_id,
'IamInstanceProfile': {
'Arn': 'arn:aws:iam::123456789012:role/fleet'
},
'EbsOptimized': False,
'WeightedCapacity': 2.0,
'SpotPrice': '0.13',
}, {
'ImageId': 'ami-123',
'KeyName': 'my-key',
'SecurityGroups': [
{
'GroupId': 'sg-123'
},
],
'UserData': 'some user data',
'InstanceType': 't2.large',
'Monitoring': {
'Enabled': True
},
'SubnetId': subnet_id,
'IamInstanceProfile': {
'Arn': 'arn:aws:iam::123456789012:role/fleet'
},
'EbsOptimized': False,
'WeightedCapacity': 4.0,
'SpotPrice': '10.00',
}],
'AllocationStrategy': allocation_strategy,
'FulfilledCapacity': 6,
}
@mock_ec2
def test_create_spot_fleet_with_lowest_price():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
spot_fleet_res = conn.request_spot_fleet(
SpotFleetRequestConfig=spot_config(subnet_id)
)
spot_fleet_id = spot_fleet_res['SpotFleetRequestId']
spot_fleet_requests = conn.describe_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id])['SpotFleetRequestConfigs']
len(spot_fleet_requests).should.equal(1)
spot_fleet_request = spot_fleet_requests[0]
spot_fleet_request['SpotFleetRequestState'].should.equal("active")
spot_fleet_config = spot_fleet_request['SpotFleetRequestConfig']
spot_fleet_config['SpotPrice'].should.equal('0.12')
spot_fleet_config['TargetCapacity'].should.equal(6)
spot_fleet_config['IamFleetRole'].should.equal(
'arn:aws:iam::123456789012:role/fleet')
spot_fleet_config['AllocationStrategy'].should.equal('lowestPrice')
spot_fleet_config['FulfilledCapacity'].should.equal(6.0)
len(spot_fleet_config['LaunchSpecifications']).should.equal(2)
launch_spec = spot_fleet_config['LaunchSpecifications'][0]
launch_spec['EbsOptimized'].should.equal(False)
launch_spec['SecurityGroups'].should.equal([{"GroupId": "sg-123"}])
launch_spec['IamInstanceProfile'].should.equal(
{"Arn": "arn:aws:iam::123456789012:role/fleet"})
launch_spec['ImageId'].should.equal("ami-123")
launch_spec['InstanceType'].should.equal("t2.small")
launch_spec['KeyName'].should.equal("my-key")
launch_spec['Monitoring'].should.equal({"Enabled": True})
launch_spec['SpotPrice'].should.equal("0.13")
launch_spec['SubnetId'].should.equal(subnet_id)
launch_spec['UserData'].should.equal("some user data")
launch_spec['WeightedCapacity'].should.equal(2.0)
instance_res = conn.describe_spot_fleet_instances(
SpotFleetRequestId=spot_fleet_id)
instances = instance_res['ActiveInstances']
len(instances).should.equal(3)
@mock_ec2
def test_create_diversified_spot_fleet():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
diversified_config = spot_config(
subnet_id, allocation_strategy='diversified')
spot_fleet_res = conn.request_spot_fleet(
SpotFleetRequestConfig=diversified_config
)
spot_fleet_id = spot_fleet_res['SpotFleetRequestId']
instance_res = conn.describe_spot_fleet_instances(
SpotFleetRequestId=spot_fleet_id)
instances = instance_res['ActiveInstances']
len(instances).should.equal(2)
instance_types = set([instance['InstanceType'] for instance in instances])
instance_types.should.equal(set(["t2.small", "t2.large"]))
instances[0]['InstanceId'].should.contain("i-")
@mock_ec2
def test_create_spot_fleet_request_with_tag_spec():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
tag_spec = [
{
'ResourceType': 'instance',
'Tags': [
{
'Key': 'tag-1',
'Value': 'foo',
},
{
'Key': 'tag-2',
'Value': 'bar',
},
]
},
]
config = spot_config(subnet_id)
config['LaunchSpecifications'][0]['TagSpecifications'] = tag_spec
spot_fleet_res = conn.request_spot_fleet(
SpotFleetRequestConfig=config
)
spot_fleet_id = spot_fleet_res['SpotFleetRequestId']
spot_fleet_requests = conn.describe_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id])['SpotFleetRequestConfigs']
spot_fleet_config = spot_fleet_requests[0]['SpotFleetRequestConfig']
spot_fleet_config['LaunchSpecifications'][0]['TagSpecifications'][0][
'ResourceType'].should.equal('instance')
for tag in tag_spec[0]['Tags']:
spot_fleet_config['LaunchSpecifications'][0]['TagSpecifications'][0]['Tags'].should.contain(tag)
instance_res = conn.describe_spot_fleet_instances(
SpotFleetRequestId=spot_fleet_id)
instances = conn.describe_instances(InstanceIds=[i['InstanceId'] for i in instance_res['ActiveInstances']])
for instance in instances['Reservations'][0]['Instances']:
for tag in tag_spec[0]['Tags']:
instance['Tags'].should.contain(tag)
@mock_ec2
def test_cancel_spot_fleet_request():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
spot_fleet_res = conn.request_spot_fleet(
SpotFleetRequestConfig=spot_config(subnet_id),
)
spot_fleet_id = spot_fleet_res['SpotFleetRequestId']
conn.cancel_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id], TerminateInstances=True)
spot_fleet_requests = conn.describe_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id])['SpotFleetRequestConfigs']
len(spot_fleet_requests).should.equal(0)
@mock_ec2
def test_modify_spot_fleet_request_up():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
spot_fleet_res = conn.request_spot_fleet(
SpotFleetRequestConfig=spot_config(subnet_id),
)
spot_fleet_id = spot_fleet_res['SpotFleetRequestId']
conn.modify_spot_fleet_request(
SpotFleetRequestId=spot_fleet_id, TargetCapacity=20)
instance_res = conn.describe_spot_fleet_instances(
SpotFleetRequestId=spot_fleet_id)
instances = instance_res['ActiveInstances']
len(instances).should.equal(10)
spot_fleet_config = conn.describe_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id])['SpotFleetRequestConfigs'][0]['SpotFleetRequestConfig']
spot_fleet_config['TargetCapacity'].should.equal(20)
spot_fleet_config['FulfilledCapacity'].should.equal(20.0)
@mock_ec2
def test_modify_spot_fleet_request_up_diversified():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
spot_fleet_res = conn.request_spot_fleet(
SpotFleetRequestConfig=spot_config(
subnet_id, allocation_strategy='diversified'),
)
spot_fleet_id = spot_fleet_res['SpotFleetRequestId']
conn.modify_spot_fleet_request(
SpotFleetRequestId=spot_fleet_id, TargetCapacity=19)
instance_res = conn.describe_spot_fleet_instances(
SpotFleetRequestId=spot_fleet_id)
instances = instance_res['ActiveInstances']
len(instances).should.equal(7)
spot_fleet_config = conn.describe_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id])['SpotFleetRequestConfigs'][0]['SpotFleetRequestConfig']
spot_fleet_config['TargetCapacity'].should.equal(19)
spot_fleet_config['FulfilledCapacity'].should.equal(20.0)
@mock_ec2
def test_modify_spot_fleet_request_down_no_terminate():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
spot_fleet_res = conn.request_spot_fleet(
SpotFleetRequestConfig=spot_config(subnet_id),
)
spot_fleet_id = spot_fleet_res['SpotFleetRequestId']
conn.modify_spot_fleet_request(
SpotFleetRequestId=spot_fleet_id, TargetCapacity=1, ExcessCapacityTerminationPolicy="noTermination")
instance_res = conn.describe_spot_fleet_instances(
SpotFleetRequestId=spot_fleet_id)
instances = instance_res['ActiveInstances']
len(instances).should.equal(3)
spot_fleet_config = conn.describe_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id])['SpotFleetRequestConfigs'][0]['SpotFleetRequestConfig']
spot_fleet_config['TargetCapacity'].should.equal(1)
spot_fleet_config['FulfilledCapacity'].should.equal(6.0)
@mock_ec2
def test_modify_spot_fleet_request_down_odd():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
spot_fleet_res = conn.request_spot_fleet(
SpotFleetRequestConfig=spot_config(subnet_id),
)
spot_fleet_id = spot_fleet_res['SpotFleetRequestId']
conn.modify_spot_fleet_request(
SpotFleetRequestId=spot_fleet_id, TargetCapacity=7)
conn.modify_spot_fleet_request(
SpotFleetRequestId=spot_fleet_id, TargetCapacity=5)
instance_res = conn.describe_spot_fleet_instances(
SpotFleetRequestId=spot_fleet_id)
instances = instance_res['ActiveInstances']
len(instances).should.equal(3)
spot_fleet_config = conn.describe_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id])['SpotFleetRequestConfigs'][0]['SpotFleetRequestConfig']
spot_fleet_config['TargetCapacity'].should.equal(5)
spot_fleet_config['FulfilledCapacity'].should.equal(6.0)
@mock_ec2
def test_modify_spot_fleet_request_down():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
spot_fleet_res = conn.request_spot_fleet(
SpotFleetRequestConfig=spot_config(subnet_id),
)
spot_fleet_id = spot_fleet_res['SpotFleetRequestId']
conn.modify_spot_fleet_request(
SpotFleetRequestId=spot_fleet_id, TargetCapacity=1)
instance_res = conn.describe_spot_fleet_instances(
SpotFleetRequestId=spot_fleet_id)
instances = instance_res['ActiveInstances']
len(instances).should.equal(1)
spot_fleet_config = conn.describe_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id])['SpotFleetRequestConfigs'][0]['SpotFleetRequestConfig']
spot_fleet_config['TargetCapacity'].should.equal(1)
spot_fleet_config['FulfilledCapacity'].should.equal(2.0)
@mock_ec2
def test_modify_spot_fleet_request_down_no_terminate_after_custom_terminate():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
spot_fleet_res = conn.request_spot_fleet(
SpotFleetRequestConfig=spot_config(subnet_id),
)
spot_fleet_id = spot_fleet_res['SpotFleetRequestId']
instance_res = conn.describe_spot_fleet_instances(
SpotFleetRequestId=spot_fleet_id)
instances = instance_res['ActiveInstances']
conn.terminate_instances(InstanceIds=[i['InstanceId'] for i in instances[1:]])
conn.modify_spot_fleet_request(
SpotFleetRequestId=spot_fleet_id, TargetCapacity=1, ExcessCapacityTerminationPolicy="noTermination")
instance_res = conn.describe_spot_fleet_instances(
SpotFleetRequestId=spot_fleet_id)
instances = instance_res['ActiveInstances']
len(instances).should.equal(1)
spot_fleet_config = conn.describe_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id])['SpotFleetRequestConfigs'][0]['SpotFleetRequestConfig']
spot_fleet_config['TargetCapacity'].should.equal(1)
spot_fleet_config['FulfilledCapacity'].should.equal(2.0)
@mock_ec2
def test_create_spot_fleet_without_spot_price():
conn = boto3.client("ec2", region_name='us-west-2')
subnet_id = get_subnet_id(conn)
# remove prices to force a fallback to ondemand price
spot_config_without_price = spot_config(subnet_id)
del spot_config_without_price['SpotPrice']
for spec in spot_config_without_price['LaunchSpecifications']:
del spec['SpotPrice']
spot_fleet_id = conn.request_spot_fleet(SpotFleetRequestConfig=spot_config_without_price)['SpotFleetRequestId']
spot_fleet_requests = conn.describe_spot_fleet_requests(
SpotFleetRequestIds=[spot_fleet_id])['SpotFleetRequestConfigs']
len(spot_fleet_requests).should.equal(1)
spot_fleet_request = spot_fleet_requests[0]
spot_fleet_config = spot_fleet_request['SpotFleetRequestConfig']
len(spot_fleet_config['LaunchSpecifications']).should.equal(2)
launch_spec1 = spot_fleet_config['LaunchSpecifications'][0]
launch_spec2 = spot_fleet_config['LaunchSpecifications'][1]
# AWS will figure out the price
assert 'SpotPrice' not in launch_spec1
assert 'SpotPrice' not in launch_spec2

View file

@ -1,453 +1,482 @@
from __future__ import unicode_literals
from nose.tools import assert_raises
import itertools
import boto
import boto3
from boto.exception import EC2ResponseError
from boto.ec2.instance import Reservation
import sure # noqa
from moto import mock_ec2_deprecated, mock_ec2
from nose.tools import assert_raises
@mock_ec2_deprecated
def test_add_tag():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
with assert_raises(EC2ResponseError) as ex:
instance.add_tag("a key", "some value", dry_run=True)
ex.exception.error_code.should.equal('DryRunOperation')
ex.exception.status.should.equal(400)
ex.exception.message.should.equal(
'An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
instance.add_tag("a key", "some value")
chain = itertools.chain.from_iterable
existing_instances = list(
chain([res.instances for res in conn.get_all_instances()]))
existing_instances.should.have.length_of(1)
existing_instance = existing_instances[0]
existing_instance.tags["a key"].should.equal("some value")
@mock_ec2_deprecated
def test_remove_tag():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
instance.add_tag("a key", "some value")
tags = conn.get_all_tags()
tag = tags[0]
tag.name.should.equal("a key")
tag.value.should.equal("some value")
with assert_raises(EC2ResponseError) as ex:
instance.remove_tag("a key", dry_run=True)
ex.exception.error_code.should.equal('DryRunOperation')
ex.exception.status.should.equal(400)
ex.exception.message.should.equal(
'An error occurred (DryRunOperation) when calling the DeleteTags operation: Request would have succeeded, but DryRun flag is set')
instance.remove_tag("a key")
conn.get_all_tags().should.have.length_of(0)
instance.add_tag("a key", "some value")
conn.get_all_tags().should.have.length_of(1)
instance.remove_tag("a key", "some value")
@mock_ec2_deprecated
def test_get_all_tags():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
instance.add_tag("a key", "some value")
tags = conn.get_all_tags()
tag = tags[0]
tag.name.should.equal("a key")
tag.value.should.equal("some value")
@mock_ec2_deprecated
def test_get_all_tags_with_special_characters():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
instance.add_tag("a key", "some<> value")
tags = conn.get_all_tags()
tag = tags[0]
tag.name.should.equal("a key")
tag.value.should.equal("some<> value")
@mock_ec2_deprecated
def test_create_tags():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
tag_dict = {'a key': 'some value',
'another key': 'some other value',
'blank key': ''}
with assert_raises(EC2ResponseError) as ex:
conn.create_tags(instance.id, tag_dict, dry_run=True)
ex.exception.error_code.should.equal('DryRunOperation')
ex.exception.status.should.equal(400)
ex.exception.message.should.equal(
'An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
conn.create_tags(instance.id, tag_dict)
tags = conn.get_all_tags()
set([key for key in tag_dict]).should.equal(
set([tag.name for tag in tags]))
set([tag_dict[key] for key in tag_dict]).should.equal(
set([tag.value for tag in tags]))
@mock_ec2_deprecated
def test_tag_limit_exceeded():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
tag_dict = {}
for i in range(51):
tag_dict['{0:02d}'.format(i + 1)] = ''
with assert_raises(EC2ResponseError) as cm:
conn.create_tags(instance.id, tag_dict)
cm.exception.code.should.equal('TagLimitExceeded')
cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none
instance.add_tag("a key", "a value")
with assert_raises(EC2ResponseError) as cm:
conn.create_tags(instance.id, tag_dict)
cm.exception.code.should.equal('TagLimitExceeded')
cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none
tags = conn.get_all_tags()
tag = tags[0]
tags.should.have.length_of(1)
tag.name.should.equal("a key")
tag.value.should.equal("a value")
@mock_ec2_deprecated
def test_invalid_parameter_tag_null():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
with assert_raises(EC2ResponseError) as cm:
instance.add_tag("a key", None)
cm.exception.code.should.equal('InvalidParameterValue')
cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none
@mock_ec2_deprecated
def test_invalid_id():
conn = boto.connect_ec2('the_key', 'the_secret')
with assert_raises(EC2ResponseError) as cm:
conn.create_tags('ami-blah', {'key': 'tag'})
cm.exception.code.should.equal('InvalidID')
cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none
with assert_raises(EC2ResponseError) as cm:
conn.create_tags('blah-blah', {'key': 'tag'})
cm.exception.code.should.equal('InvalidID')
cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none
@mock_ec2_deprecated
def test_get_all_tags_resource_id_filter():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
instance.add_tag("an instance key", "some value")
image_id = conn.create_image(instance.id, "test-ami", "this is a test ami")
image = conn.get_image(image_id)
image.add_tag("an image key", "some value")
tags = conn.get_all_tags(filters={'resource-id': instance.id})
tag = tags[0]
tags.should.have.length_of(1)
tag.res_id.should.equal(instance.id)
tag.res_type.should.equal('instance')
tag.name.should.equal("an instance key")
tag.value.should.equal("some value")
tags = conn.get_all_tags(filters={'resource-id': image_id})
tag = tags[0]
tags.should.have.length_of(1)
tag.res_id.should.equal(image_id)
tag.res_type.should.equal('image')
tag.name.should.equal("an image key")
tag.value.should.equal("some value")
@mock_ec2_deprecated
def test_get_all_tags_resource_type_filter():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
instance.add_tag("an instance key", "some value")
image_id = conn.create_image(instance.id, "test-ami", "this is a test ami")
image = conn.get_image(image_id)
image.add_tag("an image key", "some value")
tags = conn.get_all_tags(filters={'resource-type': 'instance'})
tag = tags[0]
tags.should.have.length_of(1)
tag.res_id.should.equal(instance.id)
tag.res_type.should.equal('instance')
tag.name.should.equal("an instance key")
tag.value.should.equal("some value")
tags = conn.get_all_tags(filters={'resource-type': 'image'})
tag = tags[0]
tags.should.have.length_of(1)
tag.res_id.should.equal(image_id)
tag.res_type.should.equal('image')
tag.name.should.equal("an image key")
tag.value.should.equal("some value")
@mock_ec2_deprecated
def test_get_all_tags_key_filter():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
instance.add_tag("an instance key", "some value")
image_id = conn.create_image(instance.id, "test-ami", "this is a test ami")
image = conn.get_image(image_id)
image.add_tag("an image key", "some value")
tags = conn.get_all_tags(filters={'key': 'an instance key'})
tag = tags[0]
tags.should.have.length_of(1)
tag.res_id.should.equal(instance.id)
tag.res_type.should.equal('instance')
tag.name.should.equal("an instance key")
tag.value.should.equal("some value")
@mock_ec2_deprecated
def test_get_all_tags_value_filter():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
instance.add_tag("an instance key", "some value")
reservation_b = conn.run_instances('ami-1234abcd')
instance_b = reservation_b.instances[0]
instance_b.add_tag("an instance key", "some other value")
reservation_c = conn.run_instances('ami-1234abcd')
instance_c = reservation_c.instances[0]
instance_c.add_tag("an instance key", "other value*")
reservation_d = conn.run_instances('ami-1234abcd')
instance_d = reservation_d.instances[0]
instance_d.add_tag("an instance key", "other value**")
reservation_e = conn.run_instances('ami-1234abcd')
instance_e = reservation_e.instances[0]
instance_e.add_tag("an instance key", "other value*?")
image_id = conn.create_image(instance.id, "test-ami", "this is a test ami")
image = conn.get_image(image_id)
image.add_tag("an image key", "some value")
tags = conn.get_all_tags(filters={'value': 'some value'})
tags.should.have.length_of(2)
tags = conn.get_all_tags(filters={'value': 'some*value'})
tags.should.have.length_of(3)
tags = conn.get_all_tags(filters={'value': '*some*value'})
tags.should.have.length_of(3)
tags = conn.get_all_tags(filters={'value': '*some*value*'})
tags.should.have.length_of(3)
tags = conn.get_all_tags(filters={'value': '*value\*'})
tags.should.have.length_of(1)
tags = conn.get_all_tags(filters={'value': '*value\*\*'})
tags.should.have.length_of(1)
tags = conn.get_all_tags(filters={'value': '*value\*\?'})
tags.should.have.length_of(1)
@mock_ec2_deprecated
def test_retrieved_instances_must_contain_their_tags():
tag_key = 'Tag name'
tag_value = 'Tag value'
tags_to_be_set = {tag_key: tag_value}
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
reservation.should.be.a(Reservation)
reservation.instances.should.have.length_of(1)
instance = reservation.instances[0]
reservations = conn.get_all_instances()
reservations.should.have.length_of(1)
reservations[0].id.should.equal(reservation.id)
instances = reservations[0].instances
instances.should.have.length_of(1)
instances[0].id.should.equal(instance.id)
conn.create_tags([instance.id], tags_to_be_set)
reservations = conn.get_all_instances()
instance = reservations[0].instances[0]
retrieved_tags = instance.tags
# Cleanup of instance
conn.terminate_instances([instances[0].id])
# Check whether tag is present with correct value
retrieved_tags[tag_key].should.equal(tag_value)
@mock_ec2_deprecated
def test_retrieved_volumes_must_contain_their_tags():
tag_key = 'Tag name'
tag_value = 'Tag value'
tags_to_be_set = {tag_key: tag_value}
conn = boto.connect_ec2('the_key', 'the_secret')
volume = conn.create_volume(80, "us-east-1a")
all_volumes = conn.get_all_volumes()
volume = all_volumes[0]
conn.create_tags([volume.id], tags_to_be_set)
# Fetch the volume again
all_volumes = conn.get_all_volumes()
volume = all_volumes[0]
retrieved_tags = volume.tags
volume.delete()
# Check whether tag is present with correct value
retrieved_tags[tag_key].should.equal(tag_value)
@mock_ec2_deprecated
def test_retrieved_snapshots_must_contain_their_tags():
tag_key = 'Tag name'
tag_value = 'Tag value'
tags_to_be_set = {tag_key: tag_value}
conn = boto.connect_ec2(aws_access_key_id='the_key',
aws_secret_access_key='the_secret')
volume = conn.create_volume(80, "eu-west-1a")
snapshot = conn.create_snapshot(volume.id)
conn.create_tags([snapshot.id], tags_to_be_set)
# Fetch the snapshot again
all_snapshots = conn.get_all_snapshots()
snapshot = [item for item in all_snapshots if item.id == snapshot.id][0]
retrieved_tags = snapshot.tags
conn.delete_snapshot(snapshot.id)
volume.delete()
# Check whether tag is present with correct value
retrieved_tags[tag_key].should.equal(tag_value)
@mock_ec2_deprecated
def test_filter_instances_by_wildcard_tags():
conn = boto.connect_ec2(aws_access_key_id='the_key',
aws_secret_access_key='the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance_a = reservation.instances[0]
instance_a.add_tag("Key1", "Value1")
reservation_b = conn.run_instances('ami-1234abcd')
instance_b = reservation_b.instances[0]
instance_b.add_tag("Key1", "Value2")
reservations = conn.get_all_instances(filters={'tag:Key1': 'Value*'})
reservations.should.have.length_of(2)
reservations = conn.get_all_instances(filters={'tag-key': 'Key*'})
reservations.should.have.length_of(2)
reservations = conn.get_all_instances(filters={'tag-value': 'Value*'})
reservations.should.have.length_of(2)
@mock_ec2
def test_create_volume_with_tags():
client = boto3.client('ec2', 'us-west-2')
response = client.create_volume(
AvailabilityZone='us-west-2',
Encrypted=False,
Size=40,
TagSpecifications=[
{
'ResourceType': 'volume',
'Tags': [
{
'Key': 'TEST_TAG',
'Value': 'TEST_VALUE'
}
],
}
]
)
assert response['Tags'][0]['Key'] == 'TEST_TAG'
@mock_ec2
def test_create_snapshot_with_tags():
client = boto3.client('ec2', 'us-west-2')
volume_id = client.create_volume(
AvailabilityZone='us-west-2',
Encrypted=False,
Size=40,
TagSpecifications=[
{
'ResourceType': 'volume',
'Tags': [
{
'Key': 'TEST_TAG',
'Value': 'TEST_VALUE'
}
],
}
]
)['VolumeId']
snapshot = client.create_snapshot(
VolumeId=volume_id,
TagSpecifications=[
{
'ResourceType': 'snapshot',
'Tags': [
{
'Key': 'TEST_SNAPSHOT_TAG',
'Value': 'TEST_SNAPSHOT_VALUE'
}
],
}
]
)
expected_tags = [{
'Key': 'TEST_SNAPSHOT_TAG',
'Value': 'TEST_SNAPSHOT_VALUE'
}]
assert snapshot['Tags'] == expected_tags
from __future__ import unicode_literals
from nose.tools import assert_raises
import itertools
import boto
import boto3
from botocore.exceptions import ClientError
from boto.exception import EC2ResponseError
from boto.ec2.instance import Reservation
import sure # noqa
from moto import mock_ec2_deprecated, mock_ec2
from nose.tools import assert_raises
@mock_ec2_deprecated
def test_add_tag():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
with assert_raises(EC2ResponseError) as ex:
instance.add_tag("a key", "some value", dry_run=True)
ex.exception.error_code.should.equal('DryRunOperation')
ex.exception.status.should.equal(400)
ex.exception.message.should.equal(
'An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
instance.add_tag("a key", "some value")
chain = itertools.chain.from_iterable
existing_instances = list(
chain([res.instances for res in conn.get_all_instances()]))
existing_instances.should.have.length_of(1)
existing_instance = existing_instances[0]
existing_instance.tags["a key"].should.equal("some value")
@mock_ec2_deprecated
def test_remove_tag():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
instance.add_tag("a key", "some value")
tags = conn.get_all_tags()
tag = tags[0]
tag.name.should.equal("a key")
tag.value.should.equal("some value")
with assert_raises(EC2ResponseError) as ex:
instance.remove_tag("a key", dry_run=True)
ex.exception.error_code.should.equal('DryRunOperation')
ex.exception.status.should.equal(400)
ex.exception.message.should.equal(
'An error occurred (DryRunOperation) when calling the DeleteTags operation: Request would have succeeded, but DryRun flag is set')
instance.remove_tag("a key")
conn.get_all_tags().should.have.length_of(0)
instance.add_tag("a key", "some value")
conn.get_all_tags().should.have.length_of(1)
instance.remove_tag("a key", "some value")
@mock_ec2_deprecated
def test_get_all_tags():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
instance.add_tag("a key", "some value")
tags = conn.get_all_tags()
tag = tags[0]
tag.name.should.equal("a key")
tag.value.should.equal("some value")
@mock_ec2_deprecated
def test_get_all_tags_with_special_characters():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
instance.add_tag("a key", "some<> value")
tags = conn.get_all_tags()
tag = tags[0]
tag.name.should.equal("a key")
tag.value.should.equal("some<> value")
@mock_ec2_deprecated
def test_create_tags():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
tag_dict = {'a key': 'some value',
'another key': 'some other value',
'blank key': ''}
with assert_raises(EC2ResponseError) as ex:
conn.create_tags(instance.id, tag_dict, dry_run=True)
ex.exception.error_code.should.equal('DryRunOperation')
ex.exception.status.should.equal(400)
ex.exception.message.should.equal(
'An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
conn.create_tags(instance.id, tag_dict)
tags = conn.get_all_tags()
set([key for key in tag_dict]).should.equal(
set([tag.name for tag in tags]))
set([tag_dict[key] for key in tag_dict]).should.equal(
set([tag.value for tag in tags]))
@mock_ec2_deprecated
def test_tag_limit_exceeded():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
tag_dict = {}
for i in range(51):
tag_dict['{0:02d}'.format(i + 1)] = ''
with assert_raises(EC2ResponseError) as cm:
conn.create_tags(instance.id, tag_dict)
cm.exception.code.should.equal('TagLimitExceeded')
cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none
instance.add_tag("a key", "a value")
with assert_raises(EC2ResponseError) as cm:
conn.create_tags(instance.id, tag_dict)
cm.exception.code.should.equal('TagLimitExceeded')
cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none
tags = conn.get_all_tags()
tag = tags[0]
tags.should.have.length_of(1)
tag.name.should.equal("a key")
tag.value.should.equal("a value")
@mock_ec2_deprecated
def test_invalid_parameter_tag_null():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
with assert_raises(EC2ResponseError) as cm:
instance.add_tag("a key", None)
cm.exception.code.should.equal('InvalidParameterValue')
cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none
@mock_ec2_deprecated
def test_invalid_id():
conn = boto.connect_ec2('the_key', 'the_secret')
with assert_raises(EC2ResponseError) as cm:
conn.create_tags('ami-blah', {'key': 'tag'})
cm.exception.code.should.equal('InvalidID')
cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none
with assert_raises(EC2ResponseError) as cm:
conn.create_tags('blah-blah', {'key': 'tag'})
cm.exception.code.should.equal('InvalidID')
cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none
@mock_ec2_deprecated
def test_get_all_tags_resource_id_filter():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
instance.add_tag("an instance key", "some value")
image_id = conn.create_image(instance.id, "test-ami", "this is a test ami")
image = conn.get_image(image_id)
image.add_tag("an image key", "some value")
tags = conn.get_all_tags(filters={'resource-id': instance.id})
tag = tags[0]
tags.should.have.length_of(1)
tag.res_id.should.equal(instance.id)
tag.res_type.should.equal('instance')
tag.name.should.equal("an instance key")
tag.value.should.equal("some value")
tags = conn.get_all_tags(filters={'resource-id': image_id})
tag = tags[0]
tags.should.have.length_of(1)
tag.res_id.should.equal(image_id)
tag.res_type.should.equal('image')
tag.name.should.equal("an image key")
tag.value.should.equal("some value")
@mock_ec2_deprecated
def test_get_all_tags_resource_type_filter():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
instance.add_tag("an instance key", "some value")
image_id = conn.create_image(instance.id, "test-ami", "this is a test ami")
image = conn.get_image(image_id)
image.add_tag("an image key", "some value")
tags = conn.get_all_tags(filters={'resource-type': 'instance'})
tag = tags[0]
tags.should.have.length_of(1)
tag.res_id.should.equal(instance.id)
tag.res_type.should.equal('instance')
tag.name.should.equal("an instance key")
tag.value.should.equal("some value")
tags = conn.get_all_tags(filters={'resource-type': 'image'})
tag = tags[0]
tags.should.have.length_of(1)
tag.res_id.should.equal(image_id)
tag.res_type.should.equal('image')
tag.name.should.equal("an image key")
tag.value.should.equal("some value")
@mock_ec2_deprecated
def test_get_all_tags_key_filter():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
instance.add_tag("an instance key", "some value")
image_id = conn.create_image(instance.id, "test-ami", "this is a test ami")
image = conn.get_image(image_id)
image.add_tag("an image key", "some value")
tags = conn.get_all_tags(filters={'key': 'an instance key'})
tag = tags[0]
tags.should.have.length_of(1)
tag.res_id.should.equal(instance.id)
tag.res_type.should.equal('instance')
tag.name.should.equal("an instance key")
tag.value.should.equal("some value")
@mock_ec2_deprecated
def test_get_all_tags_value_filter():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
instance.add_tag("an instance key", "some value")
reservation_b = conn.run_instances('ami-1234abcd')
instance_b = reservation_b.instances[0]
instance_b.add_tag("an instance key", "some other value")
reservation_c = conn.run_instances('ami-1234abcd')
instance_c = reservation_c.instances[0]
instance_c.add_tag("an instance key", "other value*")
reservation_d = conn.run_instances('ami-1234abcd')
instance_d = reservation_d.instances[0]
instance_d.add_tag("an instance key", "other value**")
reservation_e = conn.run_instances('ami-1234abcd')
instance_e = reservation_e.instances[0]
instance_e.add_tag("an instance key", "other value*?")
image_id = conn.create_image(instance.id, "test-ami", "this is a test ami")
image = conn.get_image(image_id)
image.add_tag("an image key", "some value")
tags = conn.get_all_tags(filters={'value': 'some value'})
tags.should.have.length_of(2)
tags = conn.get_all_tags(filters={'value': 'some*value'})
tags.should.have.length_of(3)
tags = conn.get_all_tags(filters={'value': '*some*value'})
tags.should.have.length_of(3)
tags = conn.get_all_tags(filters={'value': '*some*value*'})
tags.should.have.length_of(3)
tags = conn.get_all_tags(filters={'value': '*value\*'})
tags.should.have.length_of(1)
tags = conn.get_all_tags(filters={'value': '*value\*\*'})
tags.should.have.length_of(1)
tags = conn.get_all_tags(filters={'value': '*value\*\?'})
tags.should.have.length_of(1)
@mock_ec2_deprecated
def test_retrieved_instances_must_contain_their_tags():
tag_key = 'Tag name'
tag_value = 'Tag value'
tags_to_be_set = {tag_key: tag_value}
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
reservation.should.be.a(Reservation)
reservation.instances.should.have.length_of(1)
instance = reservation.instances[0]
reservations = conn.get_all_instances()
reservations.should.have.length_of(1)
reservations[0].id.should.equal(reservation.id)
instances = reservations[0].instances
instances.should.have.length_of(1)
instances[0].id.should.equal(instance.id)
conn.create_tags([instance.id], tags_to_be_set)
reservations = conn.get_all_instances()
instance = reservations[0].instances[0]
retrieved_tags = instance.tags
# Cleanup of instance
conn.terminate_instances([instances[0].id])
# Check whether tag is present with correct value
retrieved_tags[tag_key].should.equal(tag_value)
@mock_ec2_deprecated
def test_retrieved_volumes_must_contain_their_tags():
tag_key = 'Tag name'
tag_value = 'Tag value'
tags_to_be_set = {tag_key: tag_value}
conn = boto.connect_ec2('the_key', 'the_secret')
volume = conn.create_volume(80, "us-east-1a")
all_volumes = conn.get_all_volumes()
volume = all_volumes[0]
conn.create_tags([volume.id], tags_to_be_set)
# Fetch the volume again
all_volumes = conn.get_all_volumes()
volume = all_volumes[0]
retrieved_tags = volume.tags
volume.delete()
# Check whether tag is present with correct value
retrieved_tags[tag_key].should.equal(tag_value)
@mock_ec2_deprecated
def test_retrieved_snapshots_must_contain_their_tags():
tag_key = 'Tag name'
tag_value = 'Tag value'
tags_to_be_set = {tag_key: tag_value}
conn = boto.connect_ec2(aws_access_key_id='the_key',
aws_secret_access_key='the_secret')
volume = conn.create_volume(80, "eu-west-1a")
snapshot = conn.create_snapshot(volume.id)
conn.create_tags([snapshot.id], tags_to_be_set)
# Fetch the snapshot again
all_snapshots = conn.get_all_snapshots()
snapshot = [item for item in all_snapshots if item.id == snapshot.id][0]
retrieved_tags = snapshot.tags
conn.delete_snapshot(snapshot.id)
volume.delete()
# Check whether tag is present with correct value
retrieved_tags[tag_key].should.equal(tag_value)
@mock_ec2_deprecated
def test_filter_instances_by_wildcard_tags():
conn = boto.connect_ec2(aws_access_key_id='the_key',
aws_secret_access_key='the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance_a = reservation.instances[0]
instance_a.add_tag("Key1", "Value1")
reservation_b = conn.run_instances('ami-1234abcd')
instance_b = reservation_b.instances[0]
instance_b.add_tag("Key1", "Value2")
reservations = conn.get_all_instances(filters={'tag:Key1': 'Value*'})
reservations.should.have.length_of(2)
reservations = conn.get_all_instances(filters={'tag-key': 'Key*'})
reservations.should.have.length_of(2)
reservations = conn.get_all_instances(filters={'tag-value': 'Value*'})
reservations.should.have.length_of(2)
@mock_ec2
def test_create_volume_with_tags():
client = boto3.client('ec2', 'us-west-2')
response = client.create_volume(
AvailabilityZone='us-west-2',
Encrypted=False,
Size=40,
TagSpecifications=[
{
'ResourceType': 'volume',
'Tags': [
{
'Key': 'TEST_TAG',
'Value': 'TEST_VALUE'
}
],
}
]
)
assert response['Tags'][0]['Key'] == 'TEST_TAG'
@mock_ec2
def test_create_snapshot_with_tags():
client = boto3.client('ec2', 'us-west-2')
volume_id = client.create_volume(
AvailabilityZone='us-west-2',
Encrypted=False,
Size=40,
TagSpecifications=[
{
'ResourceType': 'volume',
'Tags': [
{
'Key': 'TEST_TAG',
'Value': 'TEST_VALUE'
}
],
}
]
)['VolumeId']
snapshot = client.create_snapshot(
VolumeId=volume_id,
TagSpecifications=[
{
'ResourceType': 'snapshot',
'Tags': [
{
'Key': 'TEST_SNAPSHOT_TAG',
'Value': 'TEST_SNAPSHOT_VALUE'
}
],
}
]
)
expected_tags = [{
'Key': 'TEST_SNAPSHOT_TAG',
'Value': 'TEST_SNAPSHOT_VALUE'
}]
assert snapshot['Tags'] == expected_tags
@mock_ec2
def test_create_tag_empty_resource():
# create ec2 client in us-west-1
client = boto3.client('ec2', region_name='us-west-1')
# create tag with empty resource
with assert_raises(ClientError) as ex:
client.create_tags(
Resources=[],
Tags=[{'Key': 'Value'}]
)
ex.exception.response['Error']['Code'].should.equal('MissingParameter')
ex.exception.response['Error']['Message'].should.equal('The request must contain the parameter resourceIdSet')
@mock_ec2
def test_delete_tag_empty_resource():
# create ec2 client in us-west-1
client = boto3.client('ec2', region_name='us-west-1')
# delete tag with empty resource
with assert_raises(ClientError) as ex:
client.delete_tags(
Resources=[],
Tags=[{'Key': 'Value'}]
)
ex.exception.response['Error']['Code'].should.equal('MissingParameter')
ex.exception.response['Error']['Message'].should.equal('The request must contain the parameter resourceIdSet')

View file

@ -1,132 +1,133 @@
from __future__ import unicode_literals
# Ensure 'assert_raises' context manager support for Python 2.6
import tests.backport_assert_raises
from nose.tools import assert_raises
from moto.ec2.exceptions import EC2ClientError
from botocore.exceptions import ClientError
import boto3
import boto
from boto.exception import EC2ResponseError
import sure # noqa
from moto import mock_ec2, mock_ec2_deprecated
from tests.helpers import requires_boto_gte
@requires_boto_gte("2.32.0")
@mock_ec2_deprecated
def test_vpc_peering_connections():
conn = boto.connect_vpc('the_key', 'the_secret')
vpc = conn.create_vpc("10.0.0.0/16")
peer_vpc = conn.create_vpc("11.0.0.0/16")
vpc_pcx = conn.create_vpc_peering_connection(vpc.id, peer_vpc.id)
vpc_pcx._status.code.should.equal('initiating-request')
return vpc_pcx
@requires_boto_gte("2.32.0")
@mock_ec2_deprecated
def test_vpc_peering_connections_get_all():
conn = boto.connect_vpc('the_key', 'the_secret')
vpc_pcx = test_vpc_peering_connections()
vpc_pcx._status.code.should.equal('initiating-request')
all_vpc_pcxs = conn.get_all_vpc_peering_connections()
all_vpc_pcxs.should.have.length_of(1)
all_vpc_pcxs[0]._status.code.should.equal('pending-acceptance')
@requires_boto_gte("2.32.0")
@mock_ec2_deprecated
def test_vpc_peering_connections_accept():
conn = boto.connect_vpc('the_key', 'the_secret')
vpc_pcx = test_vpc_peering_connections()
vpc_pcx = conn.accept_vpc_peering_connection(vpc_pcx.id)
vpc_pcx._status.code.should.equal('active')
with assert_raises(EC2ResponseError) as cm:
conn.reject_vpc_peering_connection(vpc_pcx.id)
cm.exception.code.should.equal('InvalidStateTransition')
cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none
all_vpc_pcxs = conn.get_all_vpc_peering_connections()
all_vpc_pcxs.should.have.length_of(1)
all_vpc_pcxs[0]._status.code.should.equal('active')
@requires_boto_gte("2.32.0")
@mock_ec2_deprecated
def test_vpc_peering_connections_reject():
conn = boto.connect_vpc('the_key', 'the_secret')
vpc_pcx = test_vpc_peering_connections()
verdict = conn.reject_vpc_peering_connection(vpc_pcx.id)
verdict.should.equal(True)
with assert_raises(EC2ResponseError) as cm:
conn.accept_vpc_peering_connection(vpc_pcx.id)
cm.exception.code.should.equal('InvalidStateTransition')
cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none
all_vpc_pcxs = conn.get_all_vpc_peering_connections()
all_vpc_pcxs.should.have.length_of(1)
all_vpc_pcxs[0]._status.code.should.equal('rejected')
@requires_boto_gte("2.32.1")
@mock_ec2_deprecated
def test_vpc_peering_connections_delete():
conn = boto.connect_vpc('the_key', 'the_secret')
vpc_pcx = test_vpc_peering_connections()
verdict = vpc_pcx.delete()
verdict.should.equal(True)
all_vpc_pcxs = conn.get_all_vpc_peering_connections()
all_vpc_pcxs.should.have.length_of(0)
with assert_raises(EC2ResponseError) as cm:
conn.delete_vpc_peering_connection("pcx-1234abcd")
cm.exception.code.should.equal('InvalidVpcPeeringConnectionId.NotFound')
cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none
@mock_ec2
def test_vpc_peering_connections_cross_region():
# create vpc in us-west-1 and ap-northeast-1
ec2_usw1 = boto3.resource('ec2', region_name='us-west-1')
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock='10.90.0.0/16')
ec2_apn1 = boto3.resource('ec2', region_name='ap-northeast-1')
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock='10.20.0.0/16')
# create peering
vpc_pcx = ec2_usw1.create_vpc_peering_connection(
VpcId=vpc_usw1.id,
PeerVpcId=vpc_apn1.id,
PeerRegion='ap-northeast-1',
)
vpc_pcx.status['Code'].should.equal('initiating-request')
vpc_pcx.requester_vpc.id.should.equal(vpc_usw1.id)
vpc_pcx.accepter_vpc.id.should.equal(vpc_apn1.id)
@mock_ec2
def test_vpc_peering_connections_cross_region_fail():
# create vpc in us-west-1 and ap-northeast-1
ec2_usw1 = boto3.resource('ec2', region_name='us-west-1')
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock='10.90.0.0/16')
ec2_apn1 = boto3.resource('ec2', region_name='ap-northeast-1')
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock='10.20.0.0/16')
# create peering wrong region with no vpc
with assert_raises(ClientError) as cm:
ec2_usw1.create_vpc_peering_connection(
VpcId=vpc_usw1.id,
PeerVpcId=vpc_apn1.id,
PeerRegion='ap-northeast-2')
cm.exception.response['Error']['Code'].should.equal('InvalidVpcID.NotFound')
from __future__ import unicode_literals
# Ensure 'assert_raises' context manager support for Python 2.6
import tests.backport_assert_raises
from nose.tools import assert_raises
from moto.ec2.exceptions import EC2ClientError
from botocore.exceptions import ClientError
import boto3
import boto
from boto.exception import EC2ResponseError
import sure # noqa
from moto import mock_ec2, mock_ec2_deprecated
from tests.helpers import requires_boto_gte
@requires_boto_gte("2.32.0")
@mock_ec2_deprecated
def test_vpc_peering_connections():
conn = boto.connect_vpc('the_key', 'the_secret')
vpc = conn.create_vpc("10.0.0.0/16")
peer_vpc = conn.create_vpc("11.0.0.0/16")
vpc_pcx = conn.create_vpc_peering_connection(vpc.id, peer_vpc.id)
vpc_pcx._status.code.should.equal('initiating-request')
return vpc_pcx
@requires_boto_gte("2.32.0")
@mock_ec2_deprecated
def test_vpc_peering_connections_get_all():
conn = boto.connect_vpc('the_key', 'the_secret')
vpc_pcx = test_vpc_peering_connections()
vpc_pcx._status.code.should.equal('initiating-request')
all_vpc_pcxs = conn.get_all_vpc_peering_connections()
all_vpc_pcxs.should.have.length_of(1)
all_vpc_pcxs[0]._status.code.should.equal('pending-acceptance')
@requires_boto_gte("2.32.0")
@mock_ec2_deprecated
def test_vpc_peering_connections_accept():
conn = boto.connect_vpc('the_key', 'the_secret')
vpc_pcx = test_vpc_peering_connections()
vpc_pcx = conn.accept_vpc_peering_connection(vpc_pcx.id)
vpc_pcx._status.code.should.equal('active')
with assert_raises(EC2ResponseError) as cm:
conn.reject_vpc_peering_connection(vpc_pcx.id)
cm.exception.code.should.equal('InvalidStateTransition')
cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none
all_vpc_pcxs = conn.get_all_vpc_peering_connections()
all_vpc_pcxs.should.have.length_of(1)
all_vpc_pcxs[0]._status.code.should.equal('active')
@requires_boto_gte("2.32.0")
@mock_ec2_deprecated
def test_vpc_peering_connections_reject():
conn = boto.connect_vpc('the_key', 'the_secret')
vpc_pcx = test_vpc_peering_connections()
verdict = conn.reject_vpc_peering_connection(vpc_pcx.id)
verdict.should.equal(True)
with assert_raises(EC2ResponseError) as cm:
conn.accept_vpc_peering_connection(vpc_pcx.id)
cm.exception.code.should.equal('InvalidStateTransition')
cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none
all_vpc_pcxs = conn.get_all_vpc_peering_connections()
all_vpc_pcxs.should.have.length_of(1)
all_vpc_pcxs[0]._status.code.should.equal('rejected')
@requires_boto_gte("2.32.1")
@mock_ec2_deprecated
def test_vpc_peering_connections_delete():
conn = boto.connect_vpc('the_key', 'the_secret')
vpc_pcx = test_vpc_peering_connections()
verdict = vpc_pcx.delete()
verdict.should.equal(True)
all_vpc_pcxs = conn.get_all_vpc_peering_connections()
all_vpc_pcxs.should.have.length_of(1)
all_vpc_pcxs[0]._status.code.should.equal('deleted')
with assert_raises(EC2ResponseError) as cm:
conn.delete_vpc_peering_connection("pcx-1234abcd")
cm.exception.code.should.equal('InvalidVpcPeeringConnectionId.NotFound')
cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none
@mock_ec2
def test_vpc_peering_connections_cross_region():
# create vpc in us-west-1 and ap-northeast-1
ec2_usw1 = boto3.resource('ec2', region_name='us-west-1')
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock='10.90.0.0/16')
ec2_apn1 = boto3.resource('ec2', region_name='ap-northeast-1')
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock='10.20.0.0/16')
# create peering
vpc_pcx = ec2_usw1.create_vpc_peering_connection(
VpcId=vpc_usw1.id,
PeerVpcId=vpc_apn1.id,
PeerRegion='ap-northeast-1',
)
vpc_pcx.status['Code'].should.equal('initiating-request')
vpc_pcx.requester_vpc.id.should.equal(vpc_usw1.id)
vpc_pcx.accepter_vpc.id.should.equal(vpc_apn1.id)
@mock_ec2
def test_vpc_peering_connections_cross_region_fail():
# create vpc in us-west-1 and ap-northeast-1
ec2_usw1 = boto3.resource('ec2', region_name='us-west-1')
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock='10.90.0.0/16')
ec2_apn1 = boto3.resource('ec2', region_name='ap-northeast-1')
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock='10.20.0.0/16')
# create peering wrong region with no vpc
with assert_raises(ClientError) as cm:
ec2_usw1.create_vpc_peering_connection(
VpcId=vpc_usw1.id,
PeerVpcId=vpc_apn1.id,
PeerRegion='ap-northeast-2')
cm.exception.response['Error']['Code'].should.equal('InvalidVpcID.NotFound')

View file

@ -47,6 +47,15 @@ def test_list_clusters():
'arn:aws:ecs:us-east-1:012345678910:cluster/test_cluster1')
@mock_ecs
def test_describe_clusters():
client = boto3.client('ecs', region_name='us-east-1')
response = client.describe_clusters(clusters=["some-cluster"])
response['failures'].should.contain({
'arn': 'arn:aws:ecs:us-east-1:012345678910:cluster/some-cluster',
'reason': 'MISSING'
})
@mock_ecs
def test_delete_cluster():
client = boto3.client('ecs', region_name='us-east-1')
@ -925,6 +934,65 @@ def test_update_container_instances_state():
status='test_status').should.throw(Exception)
@mock_ec2
@mock_ecs
def test_update_container_instances_state_by_arn():
ecs_client = boto3.client('ecs', region_name='us-east-1')
ec2 = boto3.resource('ec2', region_name='us-east-1')
test_cluster_name = 'test_ecs_cluster'
_ = ecs_client.create_cluster(
clusterName=test_cluster_name
)
instance_to_create = 3
test_instance_arns = []
for i in range(0, instance_to_create):
test_instance = ec2.create_instances(
ImageId="ami-1234abcd",
MinCount=1,
MaxCount=1,
)[0]
instance_id_document = json.dumps(
ec2_utils.generate_instance_identity_document(test_instance)
)
response = ecs_client.register_container_instance(
cluster=test_cluster_name,
instanceIdentityDocument=instance_id_document)
test_instance_arns.append(response['containerInstance']['containerInstanceArn'])
response = ecs_client.update_container_instances_state(cluster=test_cluster_name,
containerInstances=test_instance_arns,
status='DRAINING')
len(response['failures']).should.equal(0)
len(response['containerInstances']).should.equal(instance_to_create)
response_statuses = [ci['status'] for ci in response['containerInstances']]
for status in response_statuses:
status.should.equal('DRAINING')
response = ecs_client.update_container_instances_state(cluster=test_cluster_name,
containerInstances=test_instance_arns,
status='DRAINING')
len(response['failures']).should.equal(0)
len(response['containerInstances']).should.equal(instance_to_create)
response_statuses = [ci['status'] for ci in response['containerInstances']]
for status in response_statuses:
status.should.equal('DRAINING')
response = ecs_client.update_container_instances_state(cluster=test_cluster_name,
containerInstances=test_instance_arns,
status='ACTIVE')
len(response['failures']).should.equal(0)
len(response['containerInstances']).should.equal(instance_to_create)
response_statuses = [ci['status'] for ci in response['containerInstances']]
for status in response_statuses:
status.should.equal('ACTIVE')
ecs_client.update_container_instances_state.when.called_with(cluster=test_cluster_name,
containerInstances=test_instance_arns,
status='test_status').should.throw(Exception)
@mock_ec2
@mock_ecs
def test_run_task():

View file

@ -1,211 +1,216 @@
import random
import boto3
import json
from moto.events import mock_events
from botocore.exceptions import ClientError
from nose.tools import assert_raises
RULES = [
{'Name': 'test1', 'ScheduleExpression': 'rate(5 minutes)'},
{'Name': 'test2', 'ScheduleExpression': 'rate(1 minute)'},
{'Name': 'test3', 'EventPattern': '{"source": ["test-source"]}'}
]
TARGETS = {
'test-target-1': {
'Id': 'test-target-1',
'Arn': 'arn:aws:lambda:us-west-2:111111111111:function:test-function-1',
'Rules': ['test1', 'test2']
},
'test-target-2': {
'Id': 'test-target-2',
'Arn': 'arn:aws:lambda:us-west-2:111111111111:function:test-function-2',
'Rules': ['test1', 'test3']
},
'test-target-3': {
'Id': 'test-target-3',
'Arn': 'arn:aws:lambda:us-west-2:111111111111:function:test-function-3',
'Rules': ['test1', 'test2']
},
'test-target-4': {
'Id': 'test-target-4',
'Arn': 'arn:aws:lambda:us-west-2:111111111111:function:test-function-4',
'Rules': ['test1', 'test3']
},
'test-target-5': {
'Id': 'test-target-5',
'Arn': 'arn:aws:lambda:us-west-2:111111111111:function:test-function-5',
'Rules': ['test1', 'test2']
},
'test-target-6': {
'Id': 'test-target-6',
'Arn': 'arn:aws:lambda:us-west-2:111111111111:function:test-function-6',
'Rules': ['test1', 'test3']
}
}
def get_random_rule():
return RULES[random.randint(0, len(RULES) - 1)]
def generate_environment():
client = boto3.client('events', 'us-west-2')
for rule in RULES:
client.put_rule(
Name=rule['Name'],
ScheduleExpression=rule.get('ScheduleExpression', ''),
EventPattern=rule.get('EventPattern', '')
)
targets = []
for target in TARGETS:
if rule['Name'] in TARGETS[target].get('Rules'):
targets.append({'Id': target, 'Arn': TARGETS[target]['Arn']})
client.put_targets(Rule=rule['Name'], Targets=targets)
return client
@mock_events
def test_list_rules():
client = generate_environment()
response = client.list_rules()
assert(response is not None)
assert(len(response['Rules']) > 0)
@mock_events
def test_describe_rule():
rule_name = get_random_rule()['Name']
client = generate_environment()
response = client.describe_rule(Name=rule_name)
assert(response is not None)
assert(response.get('Name') == rule_name)
assert(response.get('Arn') is not None)
@mock_events
def test_enable_disable_rule():
rule_name = get_random_rule()['Name']
client = generate_environment()
# Rules should start out enabled in these tests.
rule = client.describe_rule(Name=rule_name)
assert(rule['State'] == 'ENABLED')
client.disable_rule(Name=rule_name)
rule = client.describe_rule(Name=rule_name)
assert(rule['State'] == 'DISABLED')
client.enable_rule(Name=rule_name)
rule = client.describe_rule(Name=rule_name)
assert(rule['State'] == 'ENABLED')
@mock_events
def test_list_rule_names_by_target():
test_1_target = TARGETS['test-target-1']
test_2_target = TARGETS['test-target-2']
client = generate_environment()
rules = client.list_rule_names_by_target(TargetArn=test_1_target['Arn'])
assert(len(rules['RuleNames']) == len(test_1_target['Rules']))
for rule in rules['RuleNames']:
assert(rule in test_1_target['Rules'])
rules = client.list_rule_names_by_target(TargetArn=test_2_target['Arn'])
assert(len(rules['RuleNames']) == len(test_2_target['Rules']))
for rule in rules['RuleNames']:
assert(rule in test_2_target['Rules'])
@mock_events
def test_list_rules():
client = generate_environment()
rules = client.list_rules()
assert(len(rules['Rules']) == len(RULES))
@mock_events
def test_delete_rule():
client = generate_environment()
client.delete_rule(Name=RULES[0]['Name'])
rules = client.list_rules()
assert(len(rules['Rules']) == len(RULES) - 1)
@mock_events
def test_list_targets_by_rule():
rule_name = get_random_rule()['Name']
client = generate_environment()
targets = client.list_targets_by_rule(Rule=rule_name)
expected_targets = []
for target in TARGETS:
if rule_name in TARGETS[target].get('Rules'):
expected_targets.append(target)
assert(len(targets['Targets']) == len(expected_targets))
@mock_events
def test_remove_targets():
rule_name = get_random_rule()['Name']
client = generate_environment()
targets = client.list_targets_by_rule(Rule=rule_name)['Targets']
targets_before = len(targets)
assert(targets_before > 0)
client.remove_targets(Rule=rule_name, Ids=[targets[0]['Id']])
targets = client.list_targets_by_rule(Rule=rule_name)['Targets']
targets_after = len(targets)
assert(targets_before - 1 == targets_after)
@mock_events
def test_permissions():
client = boto3.client('events', 'eu-central-1')
client.put_permission(Action='events:PutEvents', Principal='111111111111', StatementId='Account1')
client.put_permission(Action='events:PutEvents', Principal='222222222222', StatementId='Account2')
resp = client.describe_event_bus()
resp_policy = json.loads(resp['Policy'])
assert len(resp_policy['Statement']) == 2
client.remove_permission(StatementId='Account2')
resp = client.describe_event_bus()
resp_policy = json.loads(resp['Policy'])
assert len(resp_policy['Statement']) == 1
assert resp_policy['Statement'][0]['Sid'] == 'Account1'
@mock_events
def test_put_events():
client = boto3.client('events', 'eu-central-1')
event = {
"Source": "com.mycompany.myapp",
"Detail": '{"key1": "value3", "key2": "value4"}',
"Resources": ["resource1", "resource2"],
"DetailType": "myDetailType"
}
client.put_events(Entries=[event])
# Boto3 would error if it didn't return 200 OK
with assert_raises(ClientError):
client.put_events(Entries=[event]*20)
import random
import boto3
import json
from moto.events import mock_events
from botocore.exceptions import ClientError
from nose.tools import assert_raises
RULES = [
{'Name': 'test1', 'ScheduleExpression': 'rate(5 minutes)'},
{'Name': 'test2', 'ScheduleExpression': 'rate(1 minute)'},
{'Name': 'test3', 'EventPattern': '{"source": ["test-source"]}'}
]
TARGETS = {
'test-target-1': {
'Id': 'test-target-1',
'Arn': 'arn:aws:lambda:us-west-2:111111111111:function:test-function-1',
'Rules': ['test1', 'test2']
},
'test-target-2': {
'Id': 'test-target-2',
'Arn': 'arn:aws:lambda:us-west-2:111111111111:function:test-function-2',
'Rules': ['test1', 'test3']
},
'test-target-3': {
'Id': 'test-target-3',
'Arn': 'arn:aws:lambda:us-west-2:111111111111:function:test-function-3',
'Rules': ['test1', 'test2']
},
'test-target-4': {
'Id': 'test-target-4',
'Arn': 'arn:aws:lambda:us-west-2:111111111111:function:test-function-4',
'Rules': ['test1', 'test3']
},
'test-target-5': {
'Id': 'test-target-5',
'Arn': 'arn:aws:lambda:us-west-2:111111111111:function:test-function-5',
'Rules': ['test1', 'test2']
},
'test-target-6': {
'Id': 'test-target-6',
'Arn': 'arn:aws:lambda:us-west-2:111111111111:function:test-function-6',
'Rules': ['test1', 'test3']
}
}
def get_random_rule():
return RULES[random.randint(0, len(RULES) - 1)]
def generate_environment():
client = boto3.client('events', 'us-west-2')
for rule in RULES:
client.put_rule(
Name=rule['Name'],
ScheduleExpression=rule.get('ScheduleExpression', ''),
EventPattern=rule.get('EventPattern', '')
)
targets = []
for target in TARGETS:
if rule['Name'] in TARGETS[target].get('Rules'):
targets.append({'Id': target, 'Arn': TARGETS[target]['Arn']})
client.put_targets(Rule=rule['Name'], Targets=targets)
return client
@mock_events
def test_list_rules():
client = generate_environment()
response = client.list_rules()
assert(response is not None)
assert(len(response['Rules']) > 0)
@mock_events
def test_describe_rule():
rule_name = get_random_rule()['Name']
client = generate_environment()
response = client.describe_rule(Name=rule_name)
assert(response is not None)
assert(response.get('Name') == rule_name)
assert(response.get('Arn') is not None)
@mock_events
def test_enable_disable_rule():
rule_name = get_random_rule()['Name']
client = generate_environment()
# Rules should start out enabled in these tests.
rule = client.describe_rule(Name=rule_name)
assert(rule['State'] == 'ENABLED')
client.disable_rule(Name=rule_name)
rule = client.describe_rule(Name=rule_name)
assert(rule['State'] == 'DISABLED')
client.enable_rule(Name=rule_name)
rule = client.describe_rule(Name=rule_name)
assert(rule['State'] == 'ENABLED')
# Test invalid name
try:
client.enable_rule(Name='junk')
except ClientError as ce:
assert ce.response['Error']['Code'] == 'ResourceNotFoundException'
@mock_events
def test_list_rule_names_by_target():
test_1_target = TARGETS['test-target-1']
test_2_target = TARGETS['test-target-2']
client = generate_environment()
rules = client.list_rule_names_by_target(TargetArn=test_1_target['Arn'])
assert(len(rules['RuleNames']) == len(test_1_target['Rules']))
for rule in rules['RuleNames']:
assert(rule in test_1_target['Rules'])
rules = client.list_rule_names_by_target(TargetArn=test_2_target['Arn'])
assert(len(rules['RuleNames']) == len(test_2_target['Rules']))
for rule in rules['RuleNames']:
assert(rule in test_2_target['Rules'])
@mock_events
def test_list_rules():
client = generate_environment()
rules = client.list_rules()
assert(len(rules['Rules']) == len(RULES))
@mock_events
def test_delete_rule():
client = generate_environment()
client.delete_rule(Name=RULES[0]['Name'])
rules = client.list_rules()
assert(len(rules['Rules']) == len(RULES) - 1)
@mock_events
def test_list_targets_by_rule():
rule_name = get_random_rule()['Name']
client = generate_environment()
targets = client.list_targets_by_rule(Rule=rule_name)
expected_targets = []
for target in TARGETS:
if rule_name in TARGETS[target].get('Rules'):
expected_targets.append(target)
assert(len(targets['Targets']) == len(expected_targets))
@mock_events
def test_remove_targets():
rule_name = get_random_rule()['Name']
client = generate_environment()
targets = client.list_targets_by_rule(Rule=rule_name)['Targets']
targets_before = len(targets)
assert(targets_before > 0)
client.remove_targets(Rule=rule_name, Ids=[targets[0]['Id']])
targets = client.list_targets_by_rule(Rule=rule_name)['Targets']
targets_after = len(targets)
assert(targets_before - 1 == targets_after)
@mock_events
def test_permissions():
client = boto3.client('events', 'eu-central-1')
client.put_permission(Action='events:PutEvents', Principal='111111111111', StatementId='Account1')
client.put_permission(Action='events:PutEvents', Principal='222222222222', StatementId='Account2')
resp = client.describe_event_bus()
resp_policy = json.loads(resp['Policy'])
assert len(resp_policy['Statement']) == 2
client.remove_permission(StatementId='Account2')
resp = client.describe_event_bus()
resp_policy = json.loads(resp['Policy'])
assert len(resp_policy['Statement']) == 1
assert resp_policy['Statement'][0]['Sid'] == 'Account1'
@mock_events
def test_put_events():
client = boto3.client('events', 'eu-central-1')
event = {
"Source": "com.mycompany.myapp",
"Detail": '{"key1": "value3", "key2": "value4"}',
"Resources": ["resource1", "resource2"],
"DetailType": "myDetailType"
}
client.put_events(Entries=[event])
# Boto3 would error if it didn't return 200 OK
with assert_raises(ClientError):
client.put_events(Entries=[event]*20)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,8 @@
from __future__ import unicode_literals
import logging
# Disable extra logging for tests
logging.getLogger('boto').setLevel(logging.CRITICAL)
logging.getLogger('boto3').setLevel(logging.CRITICAL)
logging.getLogger('botocore').setLevel(logging.CRITICAL)
logging.getLogger('nose').setLevel(logging.CRITICAL)

View file

@ -0,0 +1,37 @@
# #!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import mock
from moto.packages.httpretty.core import HTTPrettyRequest, fake_gethostname, fake_gethostbyname
def test_parse_querystring():
core = HTTPrettyRequest(headers='test test HTTP/1.1')
qs = 'test test'
response = core.parse_querystring(qs)
assert response == {}
def test_parse_request_body():
core = HTTPrettyRequest(headers='test test HTTP/1.1')
qs = 'test'
response = core.parse_request_body(qs)
assert response == 'test'
def test_fake_gethostname():
response = fake_gethostname()
assert response == 'localhost'
def test_fake_gethostbyname():
host = 'test'
response = fake_gethostbyname(host=host)
assert response == '127.0.0.1'

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,105 +1,106 @@
# coding=utf-8
from __future__ import unicode_literals
import sure # noqa
from flask.testing import FlaskClient
import moto.server as server
'''
Test the different server responses
'''
class AuthenticatedClient(FlaskClient):
def open(self, *args, **kwargs):
kwargs['headers'] = kwargs.get('headers', {})
kwargs['headers']['Authorization'] = "Any authorization header"
return super(AuthenticatedClient, self).open(*args, **kwargs)
def authenticated_client():
backend = server.create_backend_app("s3")
backend.test_client_class = AuthenticatedClient
return backend.test_client()
def test_s3_server_get():
test_client = authenticated_client()
res = test_client.get('/')
res.data.should.contain(b'ListAllMyBucketsResult')
def test_s3_server_bucket_create():
test_client = authenticated_client()
res = test_client.put('/', 'http://foobaz.localhost:5000/')
res.status_code.should.equal(200)
res = test_client.get('/')
res.data.should.contain(b'<Name>foobaz</Name>')
res = test_client.get('/', 'http://foobaz.localhost:5000/')
res.status_code.should.equal(200)
res.data.should.contain(b"ListBucketResult")
res = test_client.put(
'/bar', 'http://foobaz.localhost:5000/', data='test value')
res.status_code.should.equal(200)
assert 'ETag' in dict(res.headers)
res = test_client.get('/bar', 'http://foobaz.localhost:5000/')
res.status_code.should.equal(200)
res.data.should.equal(b"test value")
def test_s3_server_bucket_versioning():
test_client = authenticated_client()
# Just enough XML to enable versioning
body = '<Status>Enabled</Status>'
res = test_client.put(
'/?versioning', 'http://foobaz.localhost:5000', data=body)
res.status_code.should.equal(200)
def test_s3_server_post_to_bucket():
test_client = authenticated_client()
res = test_client.put('/', 'http://tester.localhost:5000/')
res.status_code.should.equal(200)
test_client.post('/', "https://tester.localhost:5000/", data={
'key': 'the-key',
'file': 'nothing'
})
res = test_client.get('/the-key', 'http://tester.localhost:5000/')
res.status_code.should.equal(200)
res.data.should.equal(b"nothing")
def test_s3_server_post_without_content_length():
test_client = authenticated_client()
res = test_client.put('/', 'http://tester.localhost:5000/', environ_overrides={'CONTENT_LENGTH': ''})
res.status_code.should.equal(411)
res = test_client.post('/', "https://tester.localhost:5000/", environ_overrides={'CONTENT_LENGTH': ''})
res.status_code.should.equal(411)
def test_s3_server_post_unicode_bucket_key():
# Make sure that we can deal with non-ascii characters in request URLs (e.g., S3 object names)
dispatcher = server.DomainDispatcherApplication(server.create_backend_app)
backend_app = dispatcher.get_application({
'HTTP_HOST': 's3.amazonaws.com',
'PATH_INFO': '/test-bucket/test-object-てすと'
})
assert backend_app
backend_app = dispatcher.get_application({
'HTTP_HOST': 's3.amazonaws.com',
'PATH_INFO': '/test-bucket/test-object-てすと'.encode('utf-8')
})
assert backend_app
# coding=utf-8
from __future__ import unicode_literals
import sure # noqa
from flask.testing import FlaskClient
import moto.server as server
'''
Test the different server responses
'''
class AuthenticatedClient(FlaskClient):
def open(self, *args, **kwargs):
kwargs['headers'] = kwargs.get('headers', {})
kwargs['headers']['Authorization'] = "Any authorization header"
kwargs['content_length'] = 0 # Fixes content-length complaints.
return super(AuthenticatedClient, self).open(*args, **kwargs)
def authenticated_client():
backend = server.create_backend_app("s3")
backend.test_client_class = AuthenticatedClient
return backend.test_client()
def test_s3_server_get():
test_client = authenticated_client()
res = test_client.get('/')
res.data.should.contain(b'ListAllMyBucketsResult')
def test_s3_server_bucket_create():
test_client = authenticated_client()
res = test_client.put('/', 'http://foobaz.localhost:5000/')
res.status_code.should.equal(200)
res = test_client.get('/')
res.data.should.contain(b'<Name>foobaz</Name>')
res = test_client.get('/', 'http://foobaz.localhost:5000/')
res.status_code.should.equal(200)
res.data.should.contain(b"ListBucketResult")
res = test_client.put(
'/bar', 'http://foobaz.localhost:5000/', data='test value')
res.status_code.should.equal(200)
assert 'ETag' in dict(res.headers)
res = test_client.get('/bar', 'http://foobaz.localhost:5000/')
res.status_code.should.equal(200)
res.data.should.equal(b"test value")
def test_s3_server_bucket_versioning():
test_client = authenticated_client()
# Just enough XML to enable versioning
body = '<Status>Enabled</Status>'
res = test_client.put(
'/?versioning', 'http://foobaz.localhost:5000', data=body)
res.status_code.should.equal(200)
def test_s3_server_post_to_bucket():
test_client = authenticated_client()
res = test_client.put('/', 'http://tester.localhost:5000/')
res.status_code.should.equal(200)
test_client.post('/', "https://tester.localhost:5000/", data={
'key': 'the-key',
'file': 'nothing'
})
res = test_client.get('/the-key', 'http://tester.localhost:5000/')
res.status_code.should.equal(200)
res.data.should.equal(b"nothing")
def test_s3_server_post_without_content_length():
test_client = authenticated_client()
res = test_client.put('/', 'http://tester.localhost:5000/', environ_overrides={'CONTENT_LENGTH': ''})
res.status_code.should.equal(411)
res = test_client.post('/', "https://tester.localhost:5000/", environ_overrides={'CONTENT_LENGTH': ''})
res.status_code.should.equal(411)
def test_s3_server_post_unicode_bucket_key():
# Make sure that we can deal with non-ascii characters in request URLs (e.g., S3 object names)
dispatcher = server.DomainDispatcherApplication(server.create_backend_app)
backend_app = dispatcher.get_application({
'HTTP_HOST': 's3.amazonaws.com',
'PATH_INFO': '/test-bucket/test-object-てすと'
})
assert backend_app
backend_app = dispatcher.get_application({
'HTTP_HOST': 's3.amazonaws.com',
'PATH_INFO': '/test-bucket/test-object-てすと'.encode('utf-8')
})
assert backend_app

View file

@ -1,113 +1,114 @@
from __future__ import unicode_literals
import sure # noqa
from flask.testing import FlaskClient
import moto.server as server
'''
Test the different server responses
'''
class AuthenticatedClient(FlaskClient):
def open(self, *args, **kwargs):
kwargs['headers'] = kwargs.get('headers', {})
kwargs['headers']['Authorization'] = "Any authorization header"
return super(AuthenticatedClient, self).open(*args, **kwargs)
def authenticated_client():
backend = server.create_backend_app("s3bucket_path")
backend.test_client_class = AuthenticatedClient
return backend.test_client()
def test_s3_server_get():
test_client = authenticated_client()
res = test_client.get('/')
res.data.should.contain(b'ListAllMyBucketsResult')
def test_s3_server_bucket_create():
test_client = authenticated_client()
res = test_client.put('/foobar', 'http://localhost:5000')
res.status_code.should.equal(200)
res = test_client.get('/')
res.data.should.contain(b'<Name>foobar</Name>')
res = test_client.get('/foobar', 'http://localhost:5000')
res.status_code.should.equal(200)
res.data.should.contain(b"ListBucketResult")
res = test_client.put('/foobar2/', 'http://localhost:5000')
res.status_code.should.equal(200)
res = test_client.get('/')
res.data.should.contain(b'<Name>foobar2</Name>')
res = test_client.get('/foobar2/', 'http://localhost:5000')
res.status_code.should.equal(200)
res.data.should.contain(b"ListBucketResult")
res = test_client.get('/missing-bucket', 'http://localhost:5000')
res.status_code.should.equal(404)
res = test_client.put(
'/foobar/bar', 'http://localhost:5000', data='test value')
res.status_code.should.equal(200)
res = test_client.get('/foobar/bar', 'http://localhost:5000')
res.status_code.should.equal(200)
res.data.should.equal(b"test value")
def test_s3_server_post_to_bucket():
test_client = authenticated_client()
res = test_client.put('/foobar2', 'http://localhost:5000/')
res.status_code.should.equal(200)
test_client.post('/foobar2', "https://localhost:5000/", data={
'key': 'the-key',
'file': 'nothing'
})
res = test_client.get('/foobar2/the-key', 'http://localhost:5000/')
res.status_code.should.equal(200)
res.data.should.equal(b"nothing")
def test_s3_server_put_ipv6():
test_client = authenticated_client()
res = test_client.put('/foobar2', 'http://[::]:5000/')
res.status_code.should.equal(200)
test_client.post('/foobar2', "https://[::]:5000/", data={
'key': 'the-key',
'file': 'nothing'
})
res = test_client.get('/foobar2/the-key', 'http://[::]:5000/')
res.status_code.should.equal(200)
res.data.should.equal(b"nothing")
def test_s3_server_put_ipv4():
test_client = authenticated_client()
res = test_client.put('/foobar2', 'http://127.0.0.1:5000/')
res.status_code.should.equal(200)
test_client.post('/foobar2', "https://127.0.0.1:5000/", data={
'key': 'the-key',
'file': 'nothing'
})
res = test_client.get('/foobar2/the-key', 'http://127.0.0.1:5000/')
res.status_code.should.equal(200)
res.data.should.equal(b"nothing")
from __future__ import unicode_literals
import sure # noqa
from flask.testing import FlaskClient
import moto.server as server
'''
Test the different server responses
'''
class AuthenticatedClient(FlaskClient):
def open(self, *args, **kwargs):
kwargs['headers'] = kwargs.get('headers', {})
kwargs['headers']['Authorization'] = "Any authorization header"
kwargs['content_length'] = 0 # Fixes content-length complaints.
return super(AuthenticatedClient, self).open(*args, **kwargs)
def authenticated_client():
backend = server.create_backend_app("s3bucket_path")
backend.test_client_class = AuthenticatedClient
return backend.test_client()
def test_s3_server_get():
test_client = authenticated_client()
res = test_client.get('/')
res.data.should.contain(b'ListAllMyBucketsResult')
def test_s3_server_bucket_create():
test_client = authenticated_client()
res = test_client.put('/foobar', 'http://localhost:5000')
res.status_code.should.equal(200)
res = test_client.get('/')
res.data.should.contain(b'<Name>foobar</Name>')
res = test_client.get('/foobar', 'http://localhost:5000')
res.status_code.should.equal(200)
res.data.should.contain(b"ListBucketResult")
res = test_client.put('/foobar2/', 'http://localhost:5000')
res.status_code.should.equal(200)
res = test_client.get('/')
res.data.should.contain(b'<Name>foobar2</Name>')
res = test_client.get('/foobar2/', 'http://localhost:5000')
res.status_code.should.equal(200)
res.data.should.contain(b"ListBucketResult")
res = test_client.get('/missing-bucket', 'http://localhost:5000')
res.status_code.should.equal(404)
res = test_client.put(
'/foobar/bar', 'http://localhost:5000', data='test value')
res.status_code.should.equal(200)
res = test_client.get('/foobar/bar', 'http://localhost:5000')
res.status_code.should.equal(200)
res.data.should.equal(b"test value")
def test_s3_server_post_to_bucket():
test_client = authenticated_client()
res = test_client.put('/foobar2', 'http://localhost:5000/')
res.status_code.should.equal(200)
test_client.post('/foobar2', "https://localhost:5000/", data={
'key': 'the-key',
'file': 'nothing'
})
res = test_client.get('/foobar2/the-key', 'http://localhost:5000/')
res.status_code.should.equal(200)
res.data.should.equal(b"nothing")
def test_s3_server_put_ipv6():
test_client = authenticated_client()
res = test_client.put('/foobar2', 'http://[::]:5000/')
res.status_code.should.equal(200)
test_client.post('/foobar2', "https://[::]:5000/", data={
'key': 'the-key',
'file': 'nothing'
})
res = test_client.get('/foobar2/the-key', 'http://[::]:5000/')
res.status_code.should.equal(200)
res.data.should.equal(b"nothing")
def test_s3_server_put_ipv4():
test_client = authenticated_client()
res = test_client.put('/foobar2', 'http://127.0.0.1:5000/')
res.status_code.should.equal(200)
test_client.post('/foobar2', "https://127.0.0.1:5000/", data={
'key': 'the-key',
'file': 'nothing'
})
res = test_client.get('/foobar2/the-key', 'http://127.0.0.1:5000/')
res.status_code.should.equal(200)
res.data.should.equal(b"nothing")

View file

@ -1,286 +1,505 @@
from __future__ import unicode_literals
import boto3
from moto import mock_secretsmanager
from botocore.exceptions import ClientError
import sure # noqa
import string
import unittest
from nose.tools import assert_raises
@mock_secretsmanager
def test_get_secret_value():
conn = boto3.client('secretsmanager', region_name='us-west-2')
create_secret = conn.create_secret(Name='java-util-test-password',
SecretString="foosecret")
result = conn.get_secret_value(SecretId='java-util-test-password')
assert result['SecretString'] == 'foosecret'
@mock_secretsmanager
def test_get_secret_that_does_not_exist():
conn = boto3.client('secretsmanager', region_name='us-west-2')
with assert_raises(ClientError):
result = conn.get_secret_value(SecretId='i-dont-exist')
@mock_secretsmanager
def test_get_secret_that_does_not_match():
conn = boto3.client('secretsmanager', region_name='us-west-2')
create_secret = conn.create_secret(Name='java-util-test-password',
SecretString="foosecret")
with assert_raises(ClientError):
result = conn.get_secret_value(SecretId='i-dont-match')
@mock_secretsmanager
def test_create_secret():
conn = boto3.client('secretsmanager', region_name='us-east-1')
result = conn.create_secret(Name='test-secret', SecretString="foosecret")
assert result['ARN'] == (
'arn:aws:secretsmanager:us-east-1:1234567890:secret:test-secret-rIjad')
assert result['Name'] == 'test-secret'
secret = conn.get_secret_value(SecretId='test-secret')
assert secret['SecretString'] == 'foosecret'
@mock_secretsmanager
def test_get_random_password_default_length():
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password()
assert len(random_password['RandomPassword']) == 32
@mock_secretsmanager
def test_get_random_password_default_requirements():
# When require_each_included_type, default true
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password()
# Should contain lowercase, upppercase, digit, special character
assert any(c.islower() for c in random_password['RandomPassword'])
assert any(c.isupper() for c in random_password['RandomPassword'])
assert any(c.isdigit() for c in random_password['RandomPassword'])
assert any(c in string.punctuation
for c in random_password['RandomPassword'])
@mock_secretsmanager
def test_get_random_password_custom_length():
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password(PasswordLength=50)
assert len(random_password['RandomPassword']) == 50
@mock_secretsmanager
def test_get_random_exclude_lowercase():
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password(PasswordLength=55,
ExcludeLowercase=True)
assert any(c.islower() for c in random_password['RandomPassword']) == False
@mock_secretsmanager
def test_get_random_exclude_uppercase():
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password(PasswordLength=55,
ExcludeUppercase=True)
assert any(c.isupper() for c in random_password['RandomPassword']) == False
@mock_secretsmanager
def test_get_random_exclude_characters_and_symbols():
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password(PasswordLength=20,
ExcludeCharacters='xyzDje@?!.')
assert any(c in 'xyzDje@?!.' for c in random_password['RandomPassword']) == False
@mock_secretsmanager
def test_get_random_exclude_numbers():
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password(PasswordLength=100,
ExcludeNumbers=True)
assert any(c.isdigit() for c in random_password['RandomPassword']) == False
@mock_secretsmanager
def test_get_random_exclude_punctuation():
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password(PasswordLength=100,
ExcludePunctuation=True)
assert any(c in string.punctuation
for c in random_password['RandomPassword']) == False
@mock_secretsmanager
def test_get_random_include_space_false():
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password(PasswordLength=300)
assert any(c.isspace() for c in random_password['RandomPassword']) == False
@mock_secretsmanager
def test_get_random_include_space_true():
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password(PasswordLength=4,
IncludeSpace=True)
assert any(c.isspace() for c in random_password['RandomPassword']) == True
@mock_secretsmanager
def test_get_random_require_each_included_type():
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password(PasswordLength=4,
RequireEachIncludedType=True)
assert any(c in string.punctuation for c in random_password['RandomPassword']) == True
assert any(c in string.ascii_lowercase for c in random_password['RandomPassword']) == True
assert any(c in string.ascii_uppercase for c in random_password['RandomPassword']) == True
assert any(c in string.digits for c in random_password['RandomPassword']) == True
@mock_secretsmanager
def test_get_random_too_short_password():
conn = boto3.client('secretsmanager', region_name='us-west-2')
with assert_raises(ClientError):
random_password = conn.get_random_password(PasswordLength=3)
@mock_secretsmanager
def test_get_random_too_long_password():
conn = boto3.client('secretsmanager', region_name='us-west-2')
with assert_raises(Exception):
random_password = conn.get_random_password(PasswordLength=5555)
@mock_secretsmanager
def test_describe_secret():
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name='test-secret',
SecretString='foosecret')
secret_description = conn.describe_secret(SecretId='test-secret')
assert secret_description # Returned dict is not empty
assert secret_description['ARN'] == (
'arn:aws:secretsmanager:us-west-2:1234567890:secret:test-secret-rIjad')
@mock_secretsmanager
def test_describe_secret_that_does_not_exist():
conn = boto3.client('secretsmanager', region_name='us-west-2')
with assert_raises(ClientError):
result = conn.get_secret_value(SecretId='i-dont-exist')
@mock_secretsmanager
def test_describe_secret_that_does_not_match():
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name='test-secret',
SecretString='foosecret')
with assert_raises(ClientError):
result = conn.get_secret_value(SecretId='i-dont-match')
@mock_secretsmanager
def test_rotate_secret():
secret_name = 'test-secret'
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name=secret_name,
SecretString='foosecret')
rotated_secret = conn.rotate_secret(SecretId=secret_name)
assert rotated_secret
assert rotated_secret['ARN'] == (
'arn:aws:secretsmanager:us-west-2:1234567890:secret:test-secret-rIjad'
)
assert rotated_secret['Name'] == secret_name
assert rotated_secret['VersionId'] != ''
@mock_secretsmanager
def test_rotate_secret_enable_rotation():
secret_name = 'test-secret'
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name=secret_name,
SecretString='foosecret')
initial_description = conn.describe_secret(SecretId=secret_name)
assert initial_description
assert initial_description['RotationEnabled'] is False
assert initial_description['RotationRules']['AutomaticallyAfterDays'] == 0
conn.rotate_secret(SecretId=secret_name,
RotationRules={'AutomaticallyAfterDays': 42})
rotated_description = conn.describe_secret(SecretId=secret_name)
assert rotated_description
assert rotated_description['RotationEnabled'] is True
assert rotated_description['RotationRules']['AutomaticallyAfterDays'] == 42
@mock_secretsmanager
def test_rotate_secret_that_does_not_exist():
conn = boto3.client('secretsmanager', 'us-west-2')
with assert_raises(ClientError):
result = conn.rotate_secret(SecretId='i-dont-exist')
@mock_secretsmanager
def test_rotate_secret_that_does_not_match():
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name='test-secret',
SecretString='foosecret')
with assert_raises(ClientError):
result = conn.rotate_secret(SecretId='i-dont-match')
@mock_secretsmanager
def test_rotate_secret_client_request_token_too_short():
# Test is intentionally empty. Boto3 catches too short ClientRequestToken
# and raises ParamValidationError before Moto can see it.
# test_server actually handles this error.
assert True
@mock_secretsmanager
def test_rotate_secret_client_request_token_too_long():
secret_name = 'test-secret'
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name=secret_name,
SecretString='foosecret')
client_request_token = (
'ED9F8B6C-85B7-446A-B7E4-38F2A3BEB13C-'
'ED9F8B6C-85B7-446A-B7E4-38F2A3BEB13C'
)
with assert_raises(ClientError):
result = conn.rotate_secret(SecretId=secret_name,
ClientRequestToken=client_request_token)
@mock_secretsmanager
def test_rotate_secret_rotation_lambda_arn_too_long():
secret_name = 'test-secret'
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name=secret_name,
SecretString='foosecret')
rotation_lambda_arn = '85B7-446A-B7E4' * 147 # == 2058 characters
with assert_raises(ClientError):
result = conn.rotate_secret(SecretId=secret_name,
RotationLambdaARN=rotation_lambda_arn)
@mock_secretsmanager
def test_rotate_secret_rotation_period_zero():
# Test is intentionally empty. Boto3 catches zero day rotation period
# and raises ParamValidationError before Moto can see it.
# test_server actually handles this error.
assert True
@mock_secretsmanager
def test_rotate_secret_rotation_period_too_long():
secret_name = 'test-secret'
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name=secret_name,
SecretString='foosecret')
rotation_rules = {'AutomaticallyAfterDays': 1001}
with assert_raises(ClientError):
result = conn.rotate_secret(SecretId=secret_name,
RotationRules=rotation_rules)
from __future__ import unicode_literals
import boto3
from moto import mock_secretsmanager
from botocore.exceptions import ClientError
import sure # noqa
import string
import pytz
from datetime import datetime
import unittest
from nose.tools import assert_raises
@mock_secretsmanager
def test_get_secret_value():
conn = boto3.client('secretsmanager', region_name='us-west-2')
create_secret = conn.create_secret(Name='java-util-test-password',
SecretString="foosecret")
result = conn.get_secret_value(SecretId='java-util-test-password')
assert result['SecretString'] == 'foosecret'
@mock_secretsmanager
def test_get_secret_that_does_not_exist():
conn = boto3.client('secretsmanager', region_name='us-west-2')
with assert_raises(ClientError):
result = conn.get_secret_value(SecretId='i-dont-exist')
@mock_secretsmanager
def test_get_secret_that_does_not_match():
conn = boto3.client('secretsmanager', region_name='us-west-2')
create_secret = conn.create_secret(Name='java-util-test-password',
SecretString="foosecret")
with assert_raises(ClientError):
result = conn.get_secret_value(SecretId='i-dont-match')
@mock_secretsmanager
def test_get_secret_value_that_is_marked_deleted():
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name='test-secret',
SecretString='foosecret')
conn.delete_secret(SecretId='test-secret')
with assert_raises(ClientError):
result = conn.get_secret_value(SecretId='test-secret')
@mock_secretsmanager
def test_create_secret():
conn = boto3.client('secretsmanager', region_name='us-east-1')
result = conn.create_secret(Name='test-secret', SecretString="foosecret")
assert result['ARN']
assert result['Name'] == 'test-secret'
secret = conn.get_secret_value(SecretId='test-secret')
assert secret['SecretString'] == 'foosecret'
@mock_secretsmanager
def test_create_secret_with_tags():
conn = boto3.client('secretsmanager', region_name='us-east-1')
secret_name = 'test-secret-with-tags'
result = conn.create_secret(
Name=secret_name,
SecretString="foosecret",
Tags=[{"Key": "Foo", "Value": "Bar"}, {"Key": "Mykey", "Value": "Myvalue"}]
)
assert result['ARN']
assert result['Name'] == secret_name
secret_value = conn.get_secret_value(SecretId=secret_name)
assert secret_value['SecretString'] == 'foosecret'
secret_details = conn.describe_secret(SecretId=secret_name)
assert secret_details['Tags'] == [{"Key": "Foo", "Value": "Bar"}, {"Key": "Mykey", "Value": "Myvalue"}]
@mock_secretsmanager
def test_delete_secret():
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name='test-secret',
SecretString='foosecret')
deleted_secret = conn.delete_secret(SecretId='test-secret')
assert deleted_secret['ARN']
assert deleted_secret['Name'] == 'test-secret'
assert deleted_secret['DeletionDate'] > datetime.fromtimestamp(1, pytz.utc)
secret_details = conn.describe_secret(SecretId='test-secret')
assert secret_details['ARN']
assert secret_details['Name'] == 'test-secret'
assert secret_details['DeletedDate'] > datetime.fromtimestamp(1, pytz.utc)
@mock_secretsmanager
def test_delete_secret_force():
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name='test-secret',
SecretString='foosecret')
result = conn.delete_secret(SecretId='test-secret', ForceDeleteWithoutRecovery=True)
assert result['ARN']
assert result['DeletionDate'] > datetime.fromtimestamp(1, pytz.utc)
assert result['Name'] == 'test-secret'
with assert_raises(ClientError):
result = conn.get_secret_value(SecretId='test-secret')
@mock_secretsmanager
def test_delete_secret_that_does_not_exist():
conn = boto3.client('secretsmanager', region_name='us-west-2')
with assert_raises(ClientError):
result = conn.delete_secret(SecretId='i-dont-exist', ForceDeleteWithoutRecovery=True)
@mock_secretsmanager
def test_delete_secret_fails_with_both_force_delete_flag_and_recovery_window_flag():
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name='test-secret',
SecretString='foosecret')
with assert_raises(ClientError):
result = conn.delete_secret(SecretId='test-secret', RecoveryWindowInDays=1, ForceDeleteWithoutRecovery=True)
@mock_secretsmanager
def test_delete_secret_recovery_window_too_short():
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name='test-secret',
SecretString='foosecret')
with assert_raises(ClientError):
result = conn.delete_secret(SecretId='test-secret', RecoveryWindowInDays=6)
@mock_secretsmanager
def test_delete_secret_recovery_window_too_long():
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name='test-secret',
SecretString='foosecret')
with assert_raises(ClientError):
result = conn.delete_secret(SecretId='test-secret', RecoveryWindowInDays=31)
@mock_secretsmanager
def test_delete_secret_that_is_marked_deleted():
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name='test-secret',
SecretString='foosecret')
deleted_secret = conn.delete_secret(SecretId='test-secret')
with assert_raises(ClientError):
result = conn.delete_secret(SecretId='test-secret')
@mock_secretsmanager
def test_get_random_password_default_length():
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password()
assert len(random_password['RandomPassword']) == 32
@mock_secretsmanager
def test_get_random_password_default_requirements():
# When require_each_included_type, default true
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password()
# Should contain lowercase, upppercase, digit, special character
assert any(c.islower() for c in random_password['RandomPassword'])
assert any(c.isupper() for c in random_password['RandomPassword'])
assert any(c.isdigit() for c in random_password['RandomPassword'])
assert any(c in string.punctuation
for c in random_password['RandomPassword'])
@mock_secretsmanager
def test_get_random_password_custom_length():
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password(PasswordLength=50)
assert len(random_password['RandomPassword']) == 50
@mock_secretsmanager
def test_get_random_exclude_lowercase():
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password(PasswordLength=55,
ExcludeLowercase=True)
assert any(c.islower() for c in random_password['RandomPassword']) == False
@mock_secretsmanager
def test_get_random_exclude_uppercase():
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password(PasswordLength=55,
ExcludeUppercase=True)
assert any(c.isupper() for c in random_password['RandomPassword']) == False
@mock_secretsmanager
def test_get_random_exclude_characters_and_symbols():
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password(PasswordLength=20,
ExcludeCharacters='xyzDje@?!.')
assert any(c in 'xyzDje@?!.' for c in random_password['RandomPassword']) == False
@mock_secretsmanager
def test_get_random_exclude_numbers():
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password(PasswordLength=100,
ExcludeNumbers=True)
assert any(c.isdigit() for c in random_password['RandomPassword']) == False
@mock_secretsmanager
def test_get_random_exclude_punctuation():
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password(PasswordLength=100,
ExcludePunctuation=True)
assert any(c in string.punctuation
for c in random_password['RandomPassword']) == False
@mock_secretsmanager
def test_get_random_include_space_false():
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password(PasswordLength=300)
assert any(c.isspace() for c in random_password['RandomPassword']) == False
@mock_secretsmanager
def test_get_random_include_space_true():
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password(PasswordLength=4,
IncludeSpace=True)
assert any(c.isspace() for c in random_password['RandomPassword']) == True
@mock_secretsmanager
def test_get_random_require_each_included_type():
conn = boto3.client('secretsmanager', region_name='us-west-2')
random_password = conn.get_random_password(PasswordLength=4,
RequireEachIncludedType=True)
assert any(c in string.punctuation for c in random_password['RandomPassword']) == True
assert any(c in string.ascii_lowercase for c in random_password['RandomPassword']) == True
assert any(c in string.ascii_uppercase for c in random_password['RandomPassword']) == True
assert any(c in string.digits for c in random_password['RandomPassword']) == True
@mock_secretsmanager
def test_get_random_too_short_password():
conn = boto3.client('secretsmanager', region_name='us-west-2')
with assert_raises(ClientError):
random_password = conn.get_random_password(PasswordLength=3)
@mock_secretsmanager
def test_get_random_too_long_password():
conn = boto3.client('secretsmanager', region_name='us-west-2')
with assert_raises(Exception):
random_password = conn.get_random_password(PasswordLength=5555)
@mock_secretsmanager
def test_describe_secret():
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name='test-secret',
SecretString='foosecret')
conn.create_secret(Name='test-secret-2',
SecretString='barsecret')
secret_description = conn.describe_secret(SecretId='test-secret')
secret_description_2 = conn.describe_secret(SecretId='test-secret-2')
assert secret_description # Returned dict is not empty
assert secret_description['Name'] == ('test-secret')
assert secret_description['ARN'] != '' # Test arn not empty
assert secret_description_2['Name'] == ('test-secret-2')
assert secret_description_2['ARN'] != '' # Test arn not empty
@mock_secretsmanager
def test_describe_secret_that_does_not_exist():
conn = boto3.client('secretsmanager', region_name='us-west-2')
with assert_raises(ClientError):
result = conn.get_secret_value(SecretId='i-dont-exist')
@mock_secretsmanager
def test_describe_secret_that_does_not_match():
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name='test-secret',
SecretString='foosecret')
with assert_raises(ClientError):
result = conn.get_secret_value(SecretId='i-dont-match')
@mock_secretsmanager
def test_list_secrets_empty():
conn = boto3.client('secretsmanager', region_name='us-west-2')
secrets = conn.list_secrets()
assert secrets['SecretList'] == []
@mock_secretsmanager
def test_list_secrets():
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name='test-secret',
SecretString='foosecret')
conn.create_secret(Name='test-secret-2',
SecretString='barsecret',
Tags=[{
'Key': 'a',
'Value': '1'
}])
secrets = conn.list_secrets()
assert secrets['SecretList'][0]['ARN'] is not None
assert secrets['SecretList'][0]['Name'] == 'test-secret'
assert secrets['SecretList'][1]['ARN'] is not None
assert secrets['SecretList'][1]['Name'] == 'test-secret-2'
assert secrets['SecretList'][1]['Tags'] == [{
'Key': 'a',
'Value': '1'
}]
@mock_secretsmanager
def test_restore_secret():
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name='test-secret',
SecretString='foosecret')
conn.delete_secret(SecretId='test-secret')
described_secret_before = conn.describe_secret(SecretId='test-secret')
assert described_secret_before['DeletedDate'] > datetime.fromtimestamp(1, pytz.utc)
restored_secret = conn.restore_secret(SecretId='test-secret')
assert restored_secret['ARN']
assert restored_secret['Name'] == 'test-secret'
described_secret_after = conn.describe_secret(SecretId='test-secret')
assert 'DeletedDate' not in described_secret_after
@mock_secretsmanager
def test_restore_secret_that_is_not_deleted():
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name='test-secret',
SecretString='foosecret')
restored_secret = conn.restore_secret(SecretId='test-secret')
assert restored_secret['ARN']
assert restored_secret['Name'] == 'test-secret'
@mock_secretsmanager
def test_restore_secret_that_does_not_exist():
conn = boto3.client('secretsmanager', region_name='us-west-2')
with assert_raises(ClientError):
result = conn.restore_secret(SecretId='i-dont-exist')
@mock_secretsmanager
def test_rotate_secret():
secret_name = 'test-secret'
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name=secret_name,
SecretString='foosecret')
rotated_secret = conn.rotate_secret(SecretId=secret_name)
assert rotated_secret
assert rotated_secret['ARN'] != '' # Test arn not empty
assert rotated_secret['Name'] == secret_name
assert rotated_secret['VersionId'] != ''
@mock_secretsmanager
def test_rotate_secret_enable_rotation():
secret_name = 'test-secret'
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name=secret_name,
SecretString='foosecret')
initial_description = conn.describe_secret(SecretId=secret_name)
assert initial_description
assert initial_description['RotationEnabled'] is False
assert initial_description['RotationRules']['AutomaticallyAfterDays'] == 0
conn.rotate_secret(SecretId=secret_name,
RotationRules={'AutomaticallyAfterDays': 42})
rotated_description = conn.describe_secret(SecretId=secret_name)
assert rotated_description
assert rotated_description['RotationEnabled'] is True
assert rotated_description['RotationRules']['AutomaticallyAfterDays'] == 42
@mock_secretsmanager
def test_rotate_secret_that_is_marked_deleted():
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name='test-secret',
SecretString='foosecret')
conn.delete_secret(SecretId='test-secret')
with assert_raises(ClientError):
result = conn.rotate_secret(SecretId='test-secret')
@mock_secretsmanager
def test_rotate_secret_that_does_not_exist():
conn = boto3.client('secretsmanager', 'us-west-2')
with assert_raises(ClientError):
result = conn.rotate_secret(SecretId='i-dont-exist')
@mock_secretsmanager
def test_rotate_secret_that_does_not_match():
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name='test-secret',
SecretString='foosecret')
with assert_raises(ClientError):
result = conn.rotate_secret(SecretId='i-dont-match')
@mock_secretsmanager
def test_rotate_secret_client_request_token_too_short():
# Test is intentionally empty. Boto3 catches too short ClientRequestToken
# and raises ParamValidationError before Moto can see it.
# test_server actually handles this error.
assert True
@mock_secretsmanager
def test_rotate_secret_client_request_token_too_long():
secret_name = 'test-secret'
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name=secret_name,
SecretString='foosecret')
client_request_token = (
'ED9F8B6C-85B7-446A-B7E4-38F2A3BEB13C-'
'ED9F8B6C-85B7-446A-B7E4-38F2A3BEB13C'
)
with assert_raises(ClientError):
result = conn.rotate_secret(SecretId=secret_name,
ClientRequestToken=client_request_token)
@mock_secretsmanager
def test_rotate_secret_rotation_lambda_arn_too_long():
secret_name = 'test-secret'
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name=secret_name,
SecretString='foosecret')
rotation_lambda_arn = '85B7-446A-B7E4' * 147 # == 2058 characters
with assert_raises(ClientError):
result = conn.rotate_secret(SecretId=secret_name,
RotationLambdaARN=rotation_lambda_arn)
@mock_secretsmanager
def test_rotate_secret_rotation_period_zero():
# Test is intentionally empty. Boto3 catches zero day rotation period
# and raises ParamValidationError before Moto can see it.
# test_server actually handles this error.
assert True
@mock_secretsmanager
def test_rotate_secret_rotation_period_too_long():
secret_name = 'test-secret'
conn = boto3.client('secretsmanager', region_name='us-west-2')
conn.create_secret(Name=secret_name,
SecretString='foosecret')
rotation_rules = {'AutomaticallyAfterDays': 1001}
with assert_raises(ClientError):
result = conn.rotate_secret(SecretId=secret_name,
RotationRules=rotation_rules)

View file

@ -1,421 +1,446 @@
from __future__ import unicode_literals
import json
import sure # noqa
import moto.server as server
from moto import mock_secretsmanager
'''
Test the different server responses for secretsmanager
'''
@mock_secretsmanager
def test_get_secret_value():
backend = server.create_backend_app("secretsmanager")
test_client = backend.test_client()
create_secret = test_client.post('/',
data={"Name": "test-secret",
"SecretString": "foo-secret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"},
)
get_secret = test_client.post('/',
data={"SecretId": "test-secret",
"VersionStage": "AWSCURRENT"},
headers={
"X-Amz-Target": "secretsmanager.GetSecretValue"},
)
json_data = json.loads(get_secret.data.decode("utf-8"))
assert json_data['SecretString'] == 'foo-secret'
@mock_secretsmanager
def test_get_secret_that_does_not_exist():
backend = server.create_backend_app("secretsmanager")
test_client = backend.test_client()
get_secret = test_client.post('/',
data={"SecretId": "i-dont-exist",
"VersionStage": "AWSCURRENT"},
headers={
"X-Amz-Target": "secretsmanager.GetSecretValue"},
)
json_data = json.loads(get_secret.data.decode("utf-8"))
assert json_data['message'] == "Secrets Manager can't find the specified secret"
assert json_data['__type'] == 'ResourceNotFoundException'
@mock_secretsmanager
def test_get_secret_that_does_not_match():
backend = server.create_backend_app("secretsmanager")
test_client = backend.test_client()
create_secret = test_client.post('/',
data={"Name": "test-secret",
"SecretString": "foo-secret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"},
)
get_secret = test_client.post('/',
data={"SecretId": "i-dont-match",
"VersionStage": "AWSCURRENT"},
headers={
"X-Amz-Target": "secretsmanager.GetSecretValue"},
)
json_data = json.loads(get_secret.data.decode("utf-8"))
assert json_data['message'] == "Secrets Manager can't find the specified secret"
assert json_data['__type'] == 'ResourceNotFoundException'
@mock_secretsmanager
def test_create_secret():
backend = server.create_backend_app("secretsmanager")
test_client = backend.test_client()
res = test_client.post('/',
data={"Name": "test-secret",
"SecretString": "foo-secret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"},
)
json_data = json.loads(res.data.decode("utf-8"))
assert json_data['ARN'] == (
'arn:aws:secretsmanager:us-east-1:1234567890:secret:test-secret-rIjad')
assert json_data['Name'] == 'test-secret'
@mock_secretsmanager
def test_describe_secret():
backend = server.create_backend_app('secretsmanager')
test_client = backend.test_client()
create_secret = test_client.post('/',
data={"Name": "test-secret",
"SecretString": "foosecret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"
},
)
describe_secret = test_client.post('/',
data={"SecretId": "test-secret"},
headers={
"X-Amz-Target": "secretsmanager.DescribeSecret"
},
)
json_data = json.loads(describe_secret.data.decode("utf-8"))
assert json_data # Returned dict is not empty
assert json_data['ARN'] == (
'arn:aws:secretsmanager:us-east-1:1234567890:secret:test-secret-rIjad'
)
@mock_secretsmanager
def test_describe_secret_that_does_not_exist():
backend = server.create_backend_app('secretsmanager')
test_client = backend.test_client()
describe_secret = test_client.post('/',
data={"SecretId": "i-dont-exist"},
headers={
"X-Amz-Target": "secretsmanager.DescribeSecret"
},
)
json_data = json.loads(describe_secret.data.decode("utf-8"))
assert json_data['message'] == "Secrets Manager can't find the specified secret"
assert json_data['__type'] == 'ResourceNotFoundException'
@mock_secretsmanager
def test_describe_secret_that_does_not_match():
backend = server.create_backend_app('secretsmanager')
test_client = backend.test_client()
create_secret = test_client.post('/',
data={"Name": "test-secret",
"SecretString": "foosecret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"
},
)
describe_secret = test_client.post('/',
data={"SecretId": "i-dont-match"},
headers={
"X-Amz-Target": "secretsmanager.DescribeSecret"
},
)
json_data = json.loads(describe_secret.data.decode("utf-8"))
assert json_data['message'] == "Secrets Manager can't find the specified secret"
assert json_data['__type'] == 'ResourceNotFoundException'
@mock_secretsmanager
def test_rotate_secret():
backend = server.create_backend_app('secretsmanager')
test_client = backend.test_client()
create_secret = test_client.post('/',
data={"Name": "test-secret",
"SecretString": "foosecret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"
},
)
client_request_token = "EXAMPLE2-90ab-cdef-fedc-ba987SECRET2"
rotate_secret = test_client.post('/',
data={"SecretId": "test-secret",
"ClientRequestToken": client_request_token},
headers={
"X-Amz-Target": "secretsmanager.RotateSecret"
},
)
json_data = json.loads(rotate_secret.data.decode("utf-8"))
assert json_data # Returned dict is not empty
assert json_data['ARN'] == (
'arn:aws:secretsmanager:us-east-1:1234567890:secret:test-secret-rIjad'
)
assert json_data['Name'] == 'test-secret'
assert json_data['VersionId'] == client_request_token
# @mock_secretsmanager
# def test_rotate_secret_enable_rotation():
# backend = server.create_backend_app('secretsmanager')
# test_client = backend.test_client()
# create_secret = test_client.post(
# '/',
# data={
# "Name": "test-secret",
# "SecretString": "foosecret"
# },
# headers={
# "X-Amz-Target": "secretsmanager.CreateSecret"
# },
# )
# initial_description = test_client.post(
# '/',
# data={
# "SecretId": "test-secret"
# },
# headers={
# "X-Amz-Target": "secretsmanager.DescribeSecret"
# },
# )
# json_data = json.loads(initial_description.data.decode("utf-8"))
# assert json_data # Returned dict is not empty
# assert json_data['RotationEnabled'] is False
# assert json_data['RotationRules']['AutomaticallyAfterDays'] == 0
# rotate_secret = test_client.post(
# '/',
# data={
# "SecretId": "test-secret",
# "RotationRules": {"AutomaticallyAfterDays": 42}
# },
# headers={
# "X-Amz-Target": "secretsmanager.RotateSecret"
# },
# )
# rotated_description = test_client.post(
# '/',
# data={
# "SecretId": "test-secret"
# },
# headers={
# "X-Amz-Target": "secretsmanager.DescribeSecret"
# },
# )
# json_data = json.loads(rotated_description.data.decode("utf-8"))
# assert json_data # Returned dict is not empty
# assert json_data['RotationEnabled'] is True
# assert json_data['RotationRules']['AutomaticallyAfterDays'] == 42
@mock_secretsmanager
def test_rotate_secret_that_does_not_exist():
backend = server.create_backend_app('secretsmanager')
test_client = backend.test_client()
rotate_secret = test_client.post('/',
data={"SecretId": "i-dont-exist"},
headers={
"X-Amz-Target": "secretsmanager.RotateSecret"
},
)
json_data = json.loads(rotate_secret.data.decode("utf-8"))
assert json_data['message'] == "Secrets Manager can't find the specified secret"
assert json_data['__type'] == 'ResourceNotFoundException'
@mock_secretsmanager
def test_rotate_secret_that_does_not_match():
backend = server.create_backend_app('secretsmanager')
test_client = backend.test_client()
create_secret = test_client.post('/',
data={"Name": "test-secret",
"SecretString": "foosecret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"
},
)
rotate_secret = test_client.post('/',
data={"SecretId": "i-dont-match"},
headers={
"X-Amz-Target": "secretsmanager.RotateSecret"
},
)
json_data = json.loads(rotate_secret.data.decode("utf-8"))
assert json_data['message'] == "Secrets Manager can't find the specified secret"
assert json_data['__type'] == 'ResourceNotFoundException'
@mock_secretsmanager
def test_rotate_secret_client_request_token_too_short():
backend = server.create_backend_app('secretsmanager')
test_client = backend.test_client()
create_secret = test_client.post('/',
data={"Name": "test-secret",
"SecretString": "foosecret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"
},
)
client_request_token = "ED9F8B6C-85B7-B7E4-38F2A3BEB13C"
rotate_secret = test_client.post('/',
data={"SecretId": "test-secret",
"ClientRequestToken": client_request_token},
headers={
"X-Amz-Target": "secretsmanager.RotateSecret"
},
)
json_data = json.loads(rotate_secret.data.decode("utf-8"))
assert json_data['message'] == "ClientRequestToken must be 32-64 characters long."
assert json_data['__type'] == 'InvalidParameterException'
@mock_secretsmanager
def test_rotate_secret_client_request_token_too_long():
backend = server.create_backend_app('secretsmanager')
test_client = backend.test_client()
create_secret = test_client.post('/',
data={"Name": "test-secret",
"SecretString": "foosecret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"
},
)
client_request_token = (
'ED9F8B6C-85B7-446A-B7E4-38F2A3BEB13C-'
'ED9F8B6C-85B7-446A-B7E4-38F2A3BEB13C'
)
rotate_secret = test_client.post('/',
data={"SecretId": "test-secret",
"ClientRequestToken": client_request_token},
headers={
"X-Amz-Target": "secretsmanager.RotateSecret"
},
)
json_data = json.loads(rotate_secret.data.decode("utf-8"))
assert json_data['message'] == "ClientRequestToken must be 32-64 characters long."
assert json_data['__type'] == 'InvalidParameterException'
@mock_secretsmanager
def test_rotate_secret_rotation_lambda_arn_too_long():
backend = server.create_backend_app('secretsmanager')
test_client = backend.test_client()
create_secret = test_client.post('/',
data={"Name": "test-secret",
"SecretString": "foosecret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"
},
)
rotation_lambda_arn = '85B7-446A-B7E4' * 147 # == 2058 characters
rotate_secret = test_client.post('/',
data={"SecretId": "test-secret",
"RotationLambdaARN": rotation_lambda_arn},
headers={
"X-Amz-Target": "secretsmanager.RotateSecret"
},
)
json_data = json.loads(rotate_secret.data.decode("utf-8"))
assert json_data['message'] == "RotationLambdaARN must <= 2048 characters long."
assert json_data['__type'] == 'InvalidParameterException'
#
# The following tests should work, but fail on the embedded dict in
# RotationRules. The error message suggests a problem deeper in the code, which
# needs further investigation.
#
# @mock_secretsmanager
# def test_rotate_secret_rotation_period_zero():
# backend = server.create_backend_app('secretsmanager')
# test_client = backend.test_client()
# create_secret = test_client.post('/',
# data={"Name": "test-secret",
# "SecretString": "foosecret"},
# headers={
# "X-Amz-Target": "secretsmanager.CreateSecret"
# },
# )
# rotate_secret = test_client.post('/',
# data={"SecretId": "test-secret",
# "RotationRules": {"AutomaticallyAfterDays": 0}},
# headers={
# "X-Amz-Target": "secretsmanager.RotateSecret"
# },
# )
# json_data = json.loads(rotate_secret.data.decode("utf-8"))
# assert json_data['message'] == "RotationRules.AutomaticallyAfterDays must be within 1-1000."
# assert json_data['__type'] == 'InvalidParameterException'
# @mock_secretsmanager
# def test_rotate_secret_rotation_period_too_long():
# backend = server.create_backend_app('secretsmanager')
# test_client = backend.test_client()
# create_secret = test_client.post('/',
# data={"Name": "test-secret",
# "SecretString": "foosecret"},
# headers={
# "X-Amz-Target": "secretsmanager.CreateSecret"
# },
# )
# rotate_secret = test_client.post('/',
# data={"SecretId": "test-secret",
# "RotationRules": {"AutomaticallyAfterDays": 1001}},
# headers={
# "X-Amz-Target": "secretsmanager.RotateSecret"
# },
# )
# json_data = json.loads(rotate_secret.data.decode("utf-8"))
# assert json_data['message'] == "RotationRules.AutomaticallyAfterDays must be within 1-1000."
# assert json_data['__type'] == 'InvalidParameterException'
from __future__ import unicode_literals
import json
import sure # noqa
import moto.server as server
from moto import mock_secretsmanager
'''
Test the different server responses for secretsmanager
'''
@mock_secretsmanager
def test_get_secret_value():
backend = server.create_backend_app("secretsmanager")
test_client = backend.test_client()
create_secret = test_client.post('/',
data={"Name": "test-secret",
"SecretString": "foo-secret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"},
)
get_secret = test_client.post('/',
data={"SecretId": "test-secret",
"VersionStage": "AWSCURRENT"},
headers={
"X-Amz-Target": "secretsmanager.GetSecretValue"},
)
json_data = json.loads(get_secret.data.decode("utf-8"))
assert json_data['SecretString'] == 'foo-secret'
@mock_secretsmanager
def test_get_secret_that_does_not_exist():
backend = server.create_backend_app("secretsmanager")
test_client = backend.test_client()
get_secret = test_client.post('/',
data={"SecretId": "i-dont-exist",
"VersionStage": "AWSCURRENT"},
headers={
"X-Amz-Target": "secretsmanager.GetSecretValue"},
)
json_data = json.loads(get_secret.data.decode("utf-8"))
assert json_data['message'] == "Secrets Manager can't find the specified secret"
assert json_data['__type'] == 'ResourceNotFoundException'
@mock_secretsmanager
def test_get_secret_that_does_not_match():
backend = server.create_backend_app("secretsmanager")
test_client = backend.test_client()
create_secret = test_client.post('/',
data={"Name": "test-secret",
"SecretString": "foo-secret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"},
)
get_secret = test_client.post('/',
data={"SecretId": "i-dont-match",
"VersionStage": "AWSCURRENT"},
headers={
"X-Amz-Target": "secretsmanager.GetSecretValue"},
)
json_data = json.loads(get_secret.data.decode("utf-8"))
assert json_data['message'] == "Secrets Manager can't find the specified secret"
assert json_data['__type'] == 'ResourceNotFoundException'
@mock_secretsmanager
def test_create_secret():
backend = server.create_backend_app("secretsmanager")
test_client = backend.test_client()
res = test_client.post('/',
data={"Name": "test-secret",
"SecretString": "foo-secret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"},
)
res_2 = test_client.post('/',
data={"Name": "test-secret-2",
"SecretString": "bar-secret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"},
)
json_data = json.loads(res.data.decode("utf-8"))
assert json_data['ARN'] != ''
assert json_data['Name'] == 'test-secret'
json_data_2 = json.loads(res_2.data.decode("utf-8"))
assert json_data_2['ARN'] != ''
assert json_data_2['Name'] == 'test-secret-2'
@mock_secretsmanager
def test_describe_secret():
backend = server.create_backend_app('secretsmanager')
test_client = backend.test_client()
create_secret = test_client.post('/',
data={"Name": "test-secret",
"SecretString": "foosecret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"
},
)
describe_secret = test_client.post('/',
data={"SecretId": "test-secret"},
headers={
"X-Amz-Target": "secretsmanager.DescribeSecret"
},
)
create_secret_2 = test_client.post('/',
data={"Name": "test-secret-2",
"SecretString": "barsecret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"
},
)
describe_secret_2 = test_client.post('/',
data={"SecretId": "test-secret-2"},
headers={
"X-Amz-Target": "secretsmanager.DescribeSecret"
},
)
json_data = json.loads(describe_secret.data.decode("utf-8"))
assert json_data # Returned dict is not empty
assert json_data['ARN'] != ''
assert json_data['Name'] == 'test-secret'
json_data_2 = json.loads(describe_secret_2.data.decode("utf-8"))
assert json_data_2 # Returned dict is not empty
assert json_data_2['ARN'] != ''
assert json_data_2['Name'] == 'test-secret-2'
@mock_secretsmanager
def test_describe_secret_that_does_not_exist():
backend = server.create_backend_app('secretsmanager')
test_client = backend.test_client()
describe_secret = test_client.post('/',
data={"SecretId": "i-dont-exist"},
headers={
"X-Amz-Target": "secretsmanager.DescribeSecret"
},
)
json_data = json.loads(describe_secret.data.decode("utf-8"))
assert json_data['message'] == "Secrets Manager can't find the specified secret"
assert json_data['__type'] == 'ResourceNotFoundException'
@mock_secretsmanager
def test_describe_secret_that_does_not_match():
backend = server.create_backend_app('secretsmanager')
test_client = backend.test_client()
create_secret = test_client.post('/',
data={"Name": "test-secret",
"SecretString": "foosecret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"
},
)
describe_secret = test_client.post('/',
data={"SecretId": "i-dont-match"},
headers={
"X-Amz-Target": "secretsmanager.DescribeSecret"
},
)
json_data = json.loads(describe_secret.data.decode("utf-8"))
assert json_data['message'] == "Secrets Manager can't find the specified secret"
assert json_data['__type'] == 'ResourceNotFoundException'
@mock_secretsmanager
def test_rotate_secret():
backend = server.create_backend_app('secretsmanager')
test_client = backend.test_client()
create_secret = test_client.post('/',
data={"Name": "test-secret",
"SecretString": "foosecret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"
},
)
client_request_token = "EXAMPLE2-90ab-cdef-fedc-ba987SECRET2"
rotate_secret = test_client.post('/',
data={"SecretId": "test-secret",
"ClientRequestToken": client_request_token},
headers={
"X-Amz-Target": "secretsmanager.RotateSecret"
},
)
json_data = json.loads(rotate_secret.data.decode("utf-8"))
assert json_data # Returned dict is not empty
assert json_data['ARN'] != ''
assert json_data['Name'] == 'test-secret'
assert json_data['VersionId'] == client_request_token
# @mock_secretsmanager
# def test_rotate_secret_enable_rotation():
# backend = server.create_backend_app('secretsmanager')
# test_client = backend.test_client()
# create_secret = test_client.post(
# '/',
# data={
# "Name": "test-secret",
# "SecretString": "foosecret"
# },
# headers={
# "X-Amz-Target": "secretsmanager.CreateSecret"
# },
# )
# initial_description = test_client.post(
# '/',
# data={
# "SecretId": "test-secret"
# },
# headers={
# "X-Amz-Target": "secretsmanager.DescribeSecret"
# },
# )
# json_data = json.loads(initial_description.data.decode("utf-8"))
# assert json_data # Returned dict is not empty
# assert json_data['RotationEnabled'] is False
# assert json_data['RotationRules']['AutomaticallyAfterDays'] == 0
# rotate_secret = test_client.post(
# '/',
# data={
# "SecretId": "test-secret",
# "RotationRules": {"AutomaticallyAfterDays": 42}
# },
# headers={
# "X-Amz-Target": "secretsmanager.RotateSecret"
# },
# )
# rotated_description = test_client.post(
# '/',
# data={
# "SecretId": "test-secret"
# },
# headers={
# "X-Amz-Target": "secretsmanager.DescribeSecret"
# },
# )
# json_data = json.loads(rotated_description.data.decode("utf-8"))
# assert json_data # Returned dict is not empty
# assert json_data['RotationEnabled'] is True
# assert json_data['RotationRules']['AutomaticallyAfterDays'] == 42
@mock_secretsmanager
def test_rotate_secret_that_does_not_exist():
backend = server.create_backend_app('secretsmanager')
test_client = backend.test_client()
rotate_secret = test_client.post('/',
data={"SecretId": "i-dont-exist"},
headers={
"X-Amz-Target": "secretsmanager.RotateSecret"
},
)
json_data = json.loads(rotate_secret.data.decode("utf-8"))
assert json_data['message'] == "Secrets Manager can't find the specified secret"
assert json_data['__type'] == 'ResourceNotFoundException'
@mock_secretsmanager
def test_rotate_secret_that_does_not_match():
backend = server.create_backend_app('secretsmanager')
test_client = backend.test_client()
create_secret = test_client.post('/',
data={"Name": "test-secret",
"SecretString": "foosecret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"
},
)
rotate_secret = test_client.post('/',
data={"SecretId": "i-dont-match"},
headers={
"X-Amz-Target": "secretsmanager.RotateSecret"
},
)
json_data = json.loads(rotate_secret.data.decode("utf-8"))
assert json_data['message'] == "Secrets Manager can't find the specified secret"
assert json_data['__type'] == 'ResourceNotFoundException'
@mock_secretsmanager
def test_rotate_secret_client_request_token_too_short():
backend = server.create_backend_app('secretsmanager')
test_client = backend.test_client()
create_secret = test_client.post('/',
data={"Name": "test-secret",
"SecretString": "foosecret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"
},
)
client_request_token = "ED9F8B6C-85B7-B7E4-38F2A3BEB13C"
rotate_secret = test_client.post('/',
data={"SecretId": "test-secret",
"ClientRequestToken": client_request_token},
headers={
"X-Amz-Target": "secretsmanager.RotateSecret"
},
)
json_data = json.loads(rotate_secret.data.decode("utf-8"))
assert json_data['message'] == "ClientRequestToken must be 32-64 characters long."
assert json_data['__type'] == 'InvalidParameterException'
@mock_secretsmanager
def test_rotate_secret_client_request_token_too_long():
backend = server.create_backend_app('secretsmanager')
test_client = backend.test_client()
create_secret = test_client.post('/',
data={"Name": "test-secret",
"SecretString": "foosecret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"
},
)
client_request_token = (
'ED9F8B6C-85B7-446A-B7E4-38F2A3BEB13C-'
'ED9F8B6C-85B7-446A-B7E4-38F2A3BEB13C'
)
rotate_secret = test_client.post('/',
data={"SecretId": "test-secret",
"ClientRequestToken": client_request_token},
headers={
"X-Amz-Target": "secretsmanager.RotateSecret"
},
)
json_data = json.loads(rotate_secret.data.decode("utf-8"))
assert json_data['message'] == "ClientRequestToken must be 32-64 characters long."
assert json_data['__type'] == 'InvalidParameterException'
@mock_secretsmanager
def test_rotate_secret_rotation_lambda_arn_too_long():
backend = server.create_backend_app('secretsmanager')
test_client = backend.test_client()
create_secret = test_client.post('/',
data={"Name": "test-secret",
"SecretString": "foosecret"},
headers={
"X-Amz-Target": "secretsmanager.CreateSecret"
},
)
rotation_lambda_arn = '85B7-446A-B7E4' * 147 # == 2058 characters
rotate_secret = test_client.post('/',
data={"SecretId": "test-secret",
"RotationLambdaARN": rotation_lambda_arn},
headers={
"X-Amz-Target": "secretsmanager.RotateSecret"
},
)
json_data = json.loads(rotate_secret.data.decode("utf-8"))
assert json_data['message'] == "RotationLambdaARN must <= 2048 characters long."
assert json_data['__type'] == 'InvalidParameterException'
#
# The following tests should work, but fail on the embedded dict in
# RotationRules. The error message suggests a problem deeper in the code, which
# needs further investigation.
#
# @mock_secretsmanager
# def test_rotate_secret_rotation_period_zero():
# backend = server.create_backend_app('secretsmanager')
# test_client = backend.test_client()
# create_secret = test_client.post('/',
# data={"Name": "test-secret",
# "SecretString": "foosecret"},
# headers={
# "X-Amz-Target": "secretsmanager.CreateSecret"
# },
# )
# rotate_secret = test_client.post('/',
# data={"SecretId": "test-secret",
# "RotationRules": {"AutomaticallyAfterDays": 0}},
# headers={
# "X-Amz-Target": "secretsmanager.RotateSecret"
# },
# )
# json_data = json.loads(rotate_secret.data.decode("utf-8"))
# assert json_data['message'] == "RotationRules.AutomaticallyAfterDays must be within 1-1000."
# assert json_data['__type'] == 'InvalidParameterException'
# @mock_secretsmanager
# def test_rotate_secret_rotation_period_too_long():
# backend = server.create_backend_app('secretsmanager')
# test_client = backend.test_client()
# create_secret = test_client.post('/',
# data={"Name": "test-secret",
# "SecretString": "foosecret"},
# headers={
# "X-Amz-Target": "secretsmanager.CreateSecret"
# },
# )
# rotate_secret = test_client.post('/',
# data={"SecretId": "test-secret",
# "RotationRules": {"AutomaticallyAfterDays": 1001}},
# headers={
# "X-Amz-Target": "secretsmanager.RotateSecret"
# },
# )
# json_data = json.loads(rotate_secret.data.decode("utf-8"))
# assert json_data['message'] == "RotationRules.AutomaticallyAfterDays must be within 1-1000."
# assert json_data['__type'] == 'InvalidParameterException'

File diff suppressed because it is too large Load diff