Merge pull request #2061 from rubelw/master
Update kms, iam and lambda to work with terraform
This commit is contained in:
commit
7f0b1d6795
@ -500,6 +500,11 @@ class LambdaStorage(object):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
return self._functions[name]['latest']
|
return self._functions[name]['latest']
|
||||||
|
|
||||||
|
def list_versions_by_function(self, name):
|
||||||
|
if name not in self._functions:
|
||||||
|
return None
|
||||||
|
return [self._functions[name]['latest']]
|
||||||
|
|
||||||
def get_arn(self, arn):
|
def get_arn(self, arn):
|
||||||
return self._arns.get(arn, None)
|
return self._arns.get(arn, None)
|
||||||
|
|
||||||
@ -607,6 +612,9 @@ class LambdaBackend(BaseBackend):
|
|||||||
def get_function(self, function_name, qualifier=None):
|
def get_function(self, function_name, qualifier=None):
|
||||||
return self._lambdas.get_function(function_name, qualifier)
|
return self._lambdas.get_function(function_name, qualifier)
|
||||||
|
|
||||||
|
def list_versions_by_function(self, function_name):
|
||||||
|
return self._lambdas.list_versions_by_function(function_name)
|
||||||
|
|
||||||
def get_function_by_arn(self, function_arn):
|
def get_function_by_arn(self, function_arn):
|
||||||
return self._lambdas.get_arn(function_arn)
|
return self._lambdas.get_arn(function_arn)
|
||||||
|
|
||||||
|
@ -52,7 +52,11 @@ class LambdaResponse(BaseResponse):
|
|||||||
self.setup_class(request, full_url, headers)
|
self.setup_class(request, full_url, headers)
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
# This is ListVersionByFunction
|
# This is ListVersionByFunction
|
||||||
raise ValueError("Cannot handle request")
|
|
||||||
|
path = request.path if hasattr(request, 'path') else path_url(request.url)
|
||||||
|
function_name = path.split('/')[-2]
|
||||||
|
return self._list_versions_by_function(function_name)
|
||||||
|
|
||||||
elif request.method == 'POST':
|
elif request.method == 'POST':
|
||||||
return self._publish_function(request, full_url, headers)
|
return self._publish_function(request, full_url, headers)
|
||||||
else:
|
else:
|
||||||
@ -151,6 +155,19 @@ class LambdaResponse(BaseResponse):
|
|||||||
|
|
||||||
return 200, {}, json.dumps(result)
|
return 200, {}, json.dumps(result)
|
||||||
|
|
||||||
|
def _list_versions_by_function(self, function_name):
|
||||||
|
result = {
|
||||||
|
'Versions': []
|
||||||
|
}
|
||||||
|
|
||||||
|
functions = self.lambda_backend.list_versions_by_function(function_name)
|
||||||
|
if functions:
|
||||||
|
for fn in functions:
|
||||||
|
json_data = fn.get_configuration()
|
||||||
|
result['Versions'].append(json_data)
|
||||||
|
|
||||||
|
return 200, {}, json.dumps(result)
|
||||||
|
|
||||||
def _create_function(self, request, full_url, headers):
|
def _create_function(self, request, full_url, headers):
|
||||||
try:
|
try:
|
||||||
fn = self.lambda_backend.create_function(self.json_body)
|
fn = self.lambda_backend.create_function(self.json_body)
|
||||||
|
@ -134,6 +134,7 @@ class Role(BaseModel):
|
|||||||
self.managed_policies = {}
|
self.managed_policies = {}
|
||||||
self.create_date = datetime.now(pytz.utc)
|
self.create_date = datetime.now(pytz.utc)
|
||||||
self.tags = {}
|
self.tags = {}
|
||||||
|
self.description = ""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
|
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
|
||||||
@ -473,6 +474,16 @@ class IAMBackend(BaseBackend):
|
|||||||
policy = arns[policy_arn]
|
policy = arns[policy_arn]
|
||||||
policy.attach_to(self.get_role(role_name))
|
policy.attach_to(self.get_role(role_name))
|
||||||
|
|
||||||
|
def update_role_description(self, role_name, role_description):
|
||||||
|
role = self.get_role(role_name)
|
||||||
|
role.description = role_description
|
||||||
|
return role
|
||||||
|
|
||||||
|
def update_role(self, role_name, role_description):
|
||||||
|
role = self.get_role(role_name)
|
||||||
|
role.description = role_description
|
||||||
|
return role
|
||||||
|
|
||||||
def detach_role_policy(self, policy_arn, role_name):
|
def detach_role_policy(self, policy_arn, role_name):
|
||||||
arns = dict((p.arn, p) for p in self.managed_policies.values())
|
arns = dict((p.arn, p) for p in self.managed_policies.values())
|
||||||
try:
|
try:
|
||||||
@ -881,6 +892,16 @@ class IAMBackend(BaseBackend):
|
|||||||
|
|
||||||
return users
|
return users
|
||||||
|
|
||||||
|
def list_roles(self, path_prefix, marker, max_items):
|
||||||
|
roles = None
|
||||||
|
try:
|
||||||
|
roles = self.roles.values()
|
||||||
|
except KeyError:
|
||||||
|
raise IAMNotFoundException(
|
||||||
|
"Users {0}, {1}, {2} not found".format(path_prefix, marker, max_items))
|
||||||
|
|
||||||
|
return roles
|
||||||
|
|
||||||
def upload_signing_certificate(self, user_name, body):
|
def upload_signing_certificate(self, user_name, body):
|
||||||
user = self.get_user(user_name)
|
user = self.get_user(user_name)
|
||||||
cert_id = random_resource_id(size=32)
|
cert_id = random_resource_id(size=32)
|
||||||
|
@ -107,6 +107,69 @@ class IamResponse(BaseResponse):
|
|||||||
template = self.response_template(LIST_POLICIES_TEMPLATE)
|
template = self.response_template(LIST_POLICIES_TEMPLATE)
|
||||||
return template.render(policies=policies, marker=marker)
|
return template.render(policies=policies, marker=marker)
|
||||||
|
|
||||||
|
def list_entities_for_policy(self):
|
||||||
|
policy_arn = self._get_param('PolicyArn')
|
||||||
|
|
||||||
|
# Options 'User'|'Role'|'Group'|'LocalManagedPolicy'|'AWSManagedPolicy
|
||||||
|
entity = self._get_param('EntityFilter')
|
||||||
|
path_prefix = self._get_param('PathPrefix')
|
||||||
|
# policy_usage_filter = self._get_param('PolicyUsageFilter')
|
||||||
|
marker = self._get_param('Marker')
|
||||||
|
max_items = self._get_param('MaxItems')
|
||||||
|
|
||||||
|
entity_roles = []
|
||||||
|
entity_groups = []
|
||||||
|
entity_users = []
|
||||||
|
|
||||||
|
if entity == 'User':
|
||||||
|
users = iam_backend.list_users(path_prefix, marker, max_items)
|
||||||
|
if users:
|
||||||
|
for user in users:
|
||||||
|
for p in user.managed_policies:
|
||||||
|
if p == policy_arn:
|
||||||
|
entity_users.append(user.name)
|
||||||
|
|
||||||
|
elif entity == 'Role':
|
||||||
|
roles = iam_backend.list_roles(path_prefix, marker, max_items)
|
||||||
|
if roles:
|
||||||
|
for role in roles:
|
||||||
|
for p in role.managed_policies:
|
||||||
|
if p == policy_arn:
|
||||||
|
entity_roles.append(role.name)
|
||||||
|
|
||||||
|
elif entity == 'Group':
|
||||||
|
groups = iam_backend.list_groups()
|
||||||
|
if groups:
|
||||||
|
for group in groups:
|
||||||
|
for p in group.managed_policies:
|
||||||
|
if p == policy_arn:
|
||||||
|
entity_groups.append(group.name)
|
||||||
|
|
||||||
|
elif entity == 'LocalManagedPolicy' or entity == 'AWSManagedPolicy':
|
||||||
|
users = iam_backend.list_users(path_prefix, marker, max_items)
|
||||||
|
if users:
|
||||||
|
for user in users:
|
||||||
|
for p in user.managed_policies:
|
||||||
|
if p == policy_arn:
|
||||||
|
entity_users.append(user.name)
|
||||||
|
|
||||||
|
roles = iam_backend.list_roles(path_prefix, marker, max_items)
|
||||||
|
if roles:
|
||||||
|
for role in roles:
|
||||||
|
for p in role.managed_policies:
|
||||||
|
if p == policy_arn:
|
||||||
|
entity_roles.append(role.name)
|
||||||
|
|
||||||
|
groups = iam_backend.list_groups()
|
||||||
|
if groups:
|
||||||
|
for group in groups:
|
||||||
|
for p in group.managed_policies:
|
||||||
|
if p == policy_arn:
|
||||||
|
entity_groups.append(group.name)
|
||||||
|
|
||||||
|
template = self.response_template(LIST_ENTITIES_FOR_POLICY_TEMPLATE)
|
||||||
|
return template.render(roles=entity_roles, users=entity_users, groups=entity_groups)
|
||||||
|
|
||||||
def create_role(self):
|
def create_role(self):
|
||||||
role_name = self._get_param('RoleName')
|
role_name = self._get_param('RoleName')
|
||||||
path = self._get_param('Path')
|
path = self._get_param('Path')
|
||||||
@ -169,6 +232,20 @@ class IamResponse(BaseResponse):
|
|||||||
template = self.response_template(GENERIC_EMPTY_TEMPLATE)
|
template = self.response_template(GENERIC_EMPTY_TEMPLATE)
|
||||||
return template.render(name="UpdateAssumeRolePolicyResponse")
|
return template.render(name="UpdateAssumeRolePolicyResponse")
|
||||||
|
|
||||||
|
def update_role_description(self):
|
||||||
|
role_name = self._get_param('RoleName')
|
||||||
|
description = self._get_param('Description')
|
||||||
|
role = iam_backend.update_role_description(role_name, description)
|
||||||
|
template = self.response_template(UPDATE_ROLE_DESCRIPTION_TEMPLATE)
|
||||||
|
return template.render(role=role)
|
||||||
|
|
||||||
|
def update_role(self):
|
||||||
|
role_name = self._get_param('RoleName')
|
||||||
|
description = self._get_param('Description')
|
||||||
|
role = iam_backend.update_role(role_name, description)
|
||||||
|
template = self.response_template(UPDATE_ROLE_TEMPLATE)
|
||||||
|
return template.render(role=role)
|
||||||
|
|
||||||
def create_policy_version(self):
|
def create_policy_version(self):
|
||||||
policy_arn = self._get_param('PolicyArn')
|
policy_arn = self._get_param('PolicyArn')
|
||||||
policy_document = self._get_param('PolicyDocument')
|
policy_document = self._get_param('PolicyDocument')
|
||||||
@ -655,6 +732,37 @@ class IamResponse(BaseResponse):
|
|||||||
return template.render()
|
return template.render()
|
||||||
|
|
||||||
|
|
||||||
|
LIST_ENTITIES_FOR_POLICY_TEMPLATE = """<ListEntitiesForPolicyResponse>
|
||||||
|
<ListEntitiesForPolicyResult>
|
||||||
|
<PolicyRoles>
|
||||||
|
{% for role in roles %}
|
||||||
|
<member>
|
||||||
|
<RoleName>{{ role }}</RoleName>
|
||||||
|
</member>
|
||||||
|
{% endfor %}
|
||||||
|
</PolicyRoles>
|
||||||
|
<PolicyGroups>
|
||||||
|
{% for group in groups %}
|
||||||
|
<member>
|
||||||
|
<GroupName>{{ group }}</GroupName>
|
||||||
|
</member>
|
||||||
|
{% endfor %}
|
||||||
|
</PolicyGroups>
|
||||||
|
<IsTruncated>false</IsTruncated>
|
||||||
|
<PolicyUsers>
|
||||||
|
{% for user in users %}
|
||||||
|
<member>
|
||||||
|
<UserName>{{ user }}</UserName>
|
||||||
|
</member>
|
||||||
|
{% endfor %}
|
||||||
|
</PolicyUsers>
|
||||||
|
</ListEntitiesForPolicyResult>
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>eb358e22-9d1f-11e4-93eb-190ecEXAMPLE</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</ListEntitiesForPolicyResponse>"""
|
||||||
|
|
||||||
|
|
||||||
ATTACH_ROLE_POLICY_TEMPLATE = """<AttachRolePolicyResponse>
|
ATTACH_ROLE_POLICY_TEMPLATE = """<AttachRolePolicyResponse>
|
||||||
<ResponseMetadata>
|
<ResponseMetadata>
|
||||||
<RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
|
<RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
|
||||||
@ -898,6 +1006,40 @@ GET_ROLE_POLICY_TEMPLATE = """<GetRolePolicyResponse xmlns="https://iam.amazonaw
|
|||||||
</ResponseMetadata>
|
</ResponseMetadata>
|
||||||
</GetRolePolicyResponse>"""
|
</GetRolePolicyResponse>"""
|
||||||
|
|
||||||
|
UPDATE_ROLE_TEMPLATE = """<UpdateRoleResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
|
||||||
|
<UpdateRoleResult>
|
||||||
|
</UpdateRoleResult>
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>df37e965-9967-11e1-a4c3-270EXAMPLE04</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</UpdateRoleResponse>"""
|
||||||
|
|
||||||
|
UPDATE_ROLE_DESCRIPTION_TEMPLATE = """<UpdateRoleDescriptionResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
|
||||||
|
<UpdateRoleDescriptionResult>
|
||||||
|
<Role>
|
||||||
|
<Path>{{ role.path }}</Path>
|
||||||
|
<Arn>{{ role.arn }}</Arn>
|
||||||
|
<RoleName>{{ role.name }}</RoleName>
|
||||||
|
<AssumeRolePolicyDocument>{{ role.assume_role_policy_document }}</AssumeRolePolicyDocument>
|
||||||
|
<CreateDate>{{ role.create_date.isoformat() }}</CreateDate>
|
||||||
|
<RoleId>{{ role.id }}</RoleId>
|
||||||
|
{% if role.tags %}
|
||||||
|
<Tags>
|
||||||
|
{% for tag in role.get_tags() %}
|
||||||
|
<member>
|
||||||
|
<Key>{{ tag['Key'] }}</Key>
|
||||||
|
<Value>{{ tag['Value'] }}</Value>
|
||||||
|
</member>
|
||||||
|
{% endfor %}
|
||||||
|
</Tags>
|
||||||
|
{% endif %}
|
||||||
|
</Role>
|
||||||
|
</UpdateRoleDescriptionResult>
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>df37e965-9967-11e1-a4c3-270EXAMPLE04</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</UpdateRoleDescriptionResponse>"""
|
||||||
|
|
||||||
GET_ROLE_TEMPLATE = """<GetRoleResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
|
GET_ROLE_TEMPLATE = """<GetRoleResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
|
||||||
<GetRoleResult>
|
<GetRoleResult>
|
||||||
<Role>
|
<Role>
|
||||||
|
@ -21,6 +21,7 @@ class Key(BaseModel):
|
|||||||
self.account_id = "0123456789012"
|
self.account_id = "0123456789012"
|
||||||
self.key_rotation_status = False
|
self.key_rotation_status = False
|
||||||
self.deletion_date = None
|
self.deletion_date = None
|
||||||
|
self.tags = {}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def physical_resource_id(self):
|
def physical_resource_id(self):
|
||||||
@ -35,7 +36,7 @@ class Key(BaseModel):
|
|||||||
"KeyMetadata": {
|
"KeyMetadata": {
|
||||||
"AWSAccountId": self.account_id,
|
"AWSAccountId": self.account_id,
|
||||||
"Arn": self.arn,
|
"Arn": self.arn,
|
||||||
"CreationDate": "2015-01-01 00:00:00",
|
"CreationDate": datetime.strftime(datetime.utcnow(), "%Y-%m-%dT%H:%M:%SZ"),
|
||||||
"Description": self.description,
|
"Description": self.description,
|
||||||
"Enabled": self.enabled,
|
"Enabled": self.enabled,
|
||||||
"KeyId": self.id,
|
"KeyId": self.id,
|
||||||
@ -63,7 +64,6 @@ class Key(BaseModel):
|
|||||||
)
|
)
|
||||||
key.key_rotation_status = properties['EnableKeyRotation']
|
key.key_rotation_status = properties['EnableKeyRotation']
|
||||||
key.enabled = properties['Enabled']
|
key.enabled = properties['Enabled']
|
||||||
|
|
||||||
return key
|
return key
|
||||||
|
|
||||||
def get_cfn_attribute(self, attribute_name):
|
def get_cfn_attribute(self, attribute_name):
|
||||||
@ -84,6 +84,18 @@ class KmsBackend(BaseBackend):
|
|||||||
self.keys[key.id] = key
|
self.keys[key.id] = key
|
||||||
return key
|
return key
|
||||||
|
|
||||||
|
def update_key_description(self, key_id, description):
|
||||||
|
key = self.keys[self.get_key_id(key_id)]
|
||||||
|
key.description = description
|
||||||
|
|
||||||
|
def tag_resource(self, key_id, tags):
|
||||||
|
key = self.keys[self.get_key_id(key_id)]
|
||||||
|
key.tags = tags
|
||||||
|
|
||||||
|
def list_resource_tags(self, key_id):
|
||||||
|
key = self.keys[self.get_key_id(key_id)]
|
||||||
|
return key.tags
|
||||||
|
|
||||||
def delete_key(self, key_id):
|
def delete_key(self, key_id):
|
||||||
if key_id in self.keys:
|
if key_id in self.keys:
|
||||||
if key_id in self.key_to_aliases:
|
if key_id in self.key_to_aliases:
|
||||||
|
@ -38,6 +38,28 @@ class KmsResponse(BaseResponse):
|
|||||||
policy, key_usage, description, self.region)
|
policy, key_usage, description, self.region)
|
||||||
return json.dumps(key.to_dict())
|
return json.dumps(key.to_dict())
|
||||||
|
|
||||||
|
def update_key_description(self):
|
||||||
|
key_id = self.parameters.get('KeyId')
|
||||||
|
description = self.parameters.get('Description')
|
||||||
|
|
||||||
|
self.kms_backend.update_key_description(key_id, description)
|
||||||
|
return json.dumps(None)
|
||||||
|
|
||||||
|
def tag_resource(self):
|
||||||
|
key_id = self.parameters.get('KeyId')
|
||||||
|
tags = self.parameters.get('Tags')
|
||||||
|
self.kms_backend.tag_resource(key_id, tags)
|
||||||
|
return json.dumps({})
|
||||||
|
|
||||||
|
def list_resource_tags(self):
|
||||||
|
key_id = self.parameters.get('KeyId')
|
||||||
|
tags = self.kms_backend.list_resource_tags(key_id)
|
||||||
|
return json.dumps({
|
||||||
|
"Tags": tags,
|
||||||
|
"NextMarker": None,
|
||||||
|
"Truncated": False,
|
||||||
|
})
|
||||||
|
|
||||||
def describe_key(self):
|
def describe_key(self):
|
||||||
key_id = self.parameters.get('KeyId')
|
key_id = self.parameters.get('KeyId')
|
||||||
try:
|
try:
|
||||||
|
@ -29,7 +29,6 @@ import re
|
|||||||
from .compat import BaseClass
|
from .compat import BaseClass
|
||||||
from .utils import decode_utf8
|
from .utils import decode_utf8
|
||||||
|
|
||||||
|
|
||||||
STATUSES = {
|
STATUSES = {
|
||||||
100: "Continue",
|
100: "Continue",
|
||||||
101: "Switching Protocols",
|
101: "Switching Protocols",
|
||||||
|
@ -12,6 +12,8 @@ import sure # noqa
|
|||||||
|
|
||||||
from freezegun import freeze_time
|
from freezegun import freeze_time
|
||||||
from moto import mock_lambda, mock_s3, mock_ec2, mock_sns, mock_logs, settings
|
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'
|
_lambda_region = 'us-west-2'
|
||||||
|
|
||||||
@ -397,6 +399,11 @@ def test_get_function():
|
|||||||
result = conn.get_function(FunctionName='testFunction', Qualifier='$LATEST')
|
result = conn.get_function(FunctionName='testFunction', Qualifier='$LATEST')
|
||||||
result['Configuration']['Version'].should.equal('$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_lambda
|
||||||
@mock_s3
|
@mock_s3
|
||||||
@ -819,3 +826,87 @@ def get_function_policy():
|
|||||||
assert isinstance(response['Policy'], str)
|
assert isinstance(response['Policy'], str)
|
||||||
res = json.loads(response['Policy'])
|
res = json.loads(response['Policy'])
|
||||||
assert res['Statement'][0]['Action'] == 'lambda:InvokeFunction'
|
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,
|
||||||
|
)
|
||||||
|
|
||||||
|
conn.publish_version(FunctionName='testFunction')
|
||||||
|
|
||||||
|
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
|
||||||
|
@ -323,6 +323,54 @@ def test_create_job_queue():
|
|||||||
resp.should.contain('jobQueues')
|
resp.should.contain('jobQueues')
|
||||||
len(resp['jobQueues']).should.equal(0)
|
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_ec2
|
||||||
@mock_ecs
|
@mock_ecs
|
||||||
@ -397,6 +445,17 @@ def test_update_job_queue():
|
|||||||
len(resp['jobQueues']).should.equal(1)
|
len(resp['jobQueues']).should.equal(1)
|
||||||
resp['jobQueues'][0]['priority'].should.equal(5)
|
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_ec2
|
||||||
@mock_ecs
|
@mock_ecs
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import random
|
import random
|
||||||
|
|
||||||
import boto3
|
import boto3
|
||||||
import json
|
import json
|
||||||
|
|
||||||
@ -7,7 +6,6 @@ from moto.events import mock_events
|
|||||||
from botocore.exceptions import ClientError
|
from botocore.exceptions import ClientError
|
||||||
from nose.tools import assert_raises
|
from nose.tools import assert_raises
|
||||||
|
|
||||||
|
|
||||||
RULES = [
|
RULES = [
|
||||||
{'Name': 'test1', 'ScheduleExpression': 'rate(5 minutes)'},
|
{'Name': 'test1', 'ScheduleExpression': 'rate(5 minutes)'},
|
||||||
{'Name': 'test2', 'ScheduleExpression': 'rate(1 minute)'},
|
{'Name': 'test2', 'ScheduleExpression': 'rate(1 minute)'},
|
||||||
@ -109,6 +107,13 @@ def test_enable_disable_rule():
|
|||||||
rule = client.describe_rule(Name=rule_name)
|
rule = client.describe_rule(Name=rule_name)
|
||||||
assert(rule['State'] == 'ENABLED')
|
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
|
@mock_events
|
||||||
def test_list_rule_names_by_target():
|
def test_list_rule_names_by_target():
|
||||||
|
@ -1151,3 +1151,118 @@ def test_untag_role():
|
|||||||
# With a role that doesn't exist:
|
# With a role that doesn't exist:
|
||||||
with assert_raises(ClientError):
|
with assert_raises(ClientError):
|
||||||
conn.untag_role(RoleName='notarole', TagKeys=['somevalue'])
|
conn.untag_role(RoleName='notarole', TagKeys=['somevalue'])
|
||||||
|
|
||||||
|
|
||||||
|
@mock_iam()
|
||||||
|
def test_update_role_description():
|
||||||
|
conn = boto3.client('iam', region_name='us-east-1')
|
||||||
|
|
||||||
|
with assert_raises(ClientError):
|
||||||
|
conn.delete_role(RoleName="my-role")
|
||||||
|
|
||||||
|
conn.create_role(RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/")
|
||||||
|
response = conn.update_role_description(RoleName="my-role", Description="test")
|
||||||
|
|
||||||
|
assert response['Role']['RoleName'] == 'my-role'
|
||||||
|
|
||||||
|
@mock_iam()
|
||||||
|
def test_update_role():
|
||||||
|
conn = boto3.client('iam', region_name='us-east-1')
|
||||||
|
|
||||||
|
with assert_raises(ClientError):
|
||||||
|
conn.delete_role(RoleName="my-role")
|
||||||
|
|
||||||
|
conn.create_role(RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/")
|
||||||
|
response = conn.update_role_description(RoleName="my-role", Description="test")
|
||||||
|
assert response['Role']['RoleName'] == 'my-role'
|
||||||
|
|
||||||
|
@mock_iam()
|
||||||
|
def test_update_role():
|
||||||
|
conn = boto3.client('iam', region_name='us-east-1')
|
||||||
|
|
||||||
|
with assert_raises(ClientError):
|
||||||
|
conn.delete_role(RoleName="my-role")
|
||||||
|
|
||||||
|
conn.create_role(RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/")
|
||||||
|
response = conn.update_role(RoleName="my-role", Description="test")
|
||||||
|
assert len(response.keys()) == 1
|
||||||
|
|
||||||
|
|
||||||
|
@mock_iam()
|
||||||
|
def test_list_entities_for_policy():
|
||||||
|
import json
|
||||||
|
test_policy = json.dumps({
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Action": "s3:ListBucket",
|
||||||
|
"Resource": "*",
|
||||||
|
"Effect": "Allow",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
conn = boto3.client('iam', region_name='us-east-1')
|
||||||
|
conn.create_role(RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/")
|
||||||
|
conn.create_user(Path='/', UserName='testUser')
|
||||||
|
conn.create_group(Path='/', GroupName='testGroup')
|
||||||
|
conn.create_policy(
|
||||||
|
PolicyName='testPolicy',
|
||||||
|
Path='/',
|
||||||
|
PolicyDocument=test_policy,
|
||||||
|
Description='Test Policy'
|
||||||
|
)
|
||||||
|
|
||||||
|
# Attach things to the user and group:
|
||||||
|
conn.put_user_policy(UserName='testUser', PolicyName='testPolicy', PolicyDocument=test_policy)
|
||||||
|
conn.put_group_policy(GroupName='testGroup', PolicyName='testPolicy', PolicyDocument=test_policy)
|
||||||
|
|
||||||
|
conn.attach_user_policy(UserName='testUser', PolicyArn='arn:aws:iam::123456789012:policy/testPolicy')
|
||||||
|
conn.attach_group_policy(GroupName='testGroup', PolicyArn='arn:aws:iam::123456789012:policy/testPolicy')
|
||||||
|
|
||||||
|
conn.add_user_to_group(UserName='testUser', GroupName='testGroup')
|
||||||
|
|
||||||
|
# Add things to the role:
|
||||||
|
conn.create_instance_profile(InstanceProfileName='ipn')
|
||||||
|
conn.add_role_to_instance_profile(InstanceProfileName='ipn', RoleName='my-role')
|
||||||
|
conn.tag_role(RoleName='my-role', Tags=[
|
||||||
|
{
|
||||||
|
'Key': 'somekey',
|
||||||
|
'Value': 'somevalue'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'Key': 'someotherkey',
|
||||||
|
'Value': 'someothervalue'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
conn.put_role_policy(RoleName='my-role', PolicyName='test-policy', PolicyDocument=test_policy)
|
||||||
|
conn.attach_role_policy(RoleName='my-role', PolicyArn='arn:aws:iam::123456789012:policy/testPolicy')
|
||||||
|
|
||||||
|
response = conn.list_entities_for_policy(
|
||||||
|
PolicyArn='arn:aws:iam::123456789012:policy/testPolicy',
|
||||||
|
EntityFilter='Role'
|
||||||
|
)
|
||||||
|
assert response['PolicyRoles'] == [{'RoleName': 'my-role'}]
|
||||||
|
|
||||||
|
response = conn.list_entities_for_policy(
|
||||||
|
PolicyArn='arn:aws:iam::123456789012:policy/testPolicy',
|
||||||
|
EntityFilter='User',
|
||||||
|
)
|
||||||
|
assert response['PolicyUsers'] == [{'UserName': 'testUser'}]
|
||||||
|
|
||||||
|
response = conn.list_entities_for_policy(
|
||||||
|
PolicyArn='arn:aws:iam::123456789012:policy/testPolicy',
|
||||||
|
EntityFilter='Group',
|
||||||
|
)
|
||||||
|
assert response['PolicyGroups'] == [{'GroupName': 'testGroup'}]
|
||||||
|
|
||||||
|
response = conn.list_entities_for_policy(
|
||||||
|
PolicyArn='arn:aws:iam::123456789012:policy/testPolicy',
|
||||||
|
EntityFilter='LocalManagedPolicy',
|
||||||
|
)
|
||||||
|
assert response['PolicyGroups'] == [{'GroupName': 'testGroup'}]
|
||||||
|
assert response['PolicyUsers'] == [{'UserName': 'testUser'}]
|
||||||
|
assert response['PolicyRoles'] == [{'RoleName': 'my-role'}]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import os, re
|
import os, re
|
||||||
|
|
||||||
import boto3
|
import boto3
|
||||||
import boto.kms
|
import boto.kms
|
||||||
from boto.exception import JSONResponseError
|
from boto.exception import JSONResponseError
|
||||||
@ -717,3 +716,60 @@ def test_cancel_key_deletion():
|
|||||||
assert result["KeyMetadata"]["Enabled"] == False
|
assert result["KeyMetadata"]["Enabled"] == False
|
||||||
assert result["KeyMetadata"]["KeyState"] == 'Disabled'
|
assert result["KeyMetadata"]["KeyState"] == 'Disabled'
|
||||||
assert 'DeletionDate' not in result["KeyMetadata"]
|
assert 'DeletionDate' not in result["KeyMetadata"]
|
||||||
|
|
||||||
|
|
||||||
|
@mock_kms
|
||||||
|
def test_update_key_description():
|
||||||
|
client = boto3.client('kms', region_name='us-east-1')
|
||||||
|
key = client.create_key(Description='old_description')
|
||||||
|
key_id = key['KeyMetadata']['KeyId']
|
||||||
|
|
||||||
|
result = client.update_key_description(KeyId=key_id, Description='new_description')
|
||||||
|
assert 'ResponseMetadata' in result
|
||||||
|
|
||||||
|
|
||||||
|
@mock_kms
|
||||||
|
def test_tag_resource():
|
||||||
|
client = boto3.client('kms', region_name='us-east-1')
|
||||||
|
key = client.create_key(Description='cancel-key-deletion')
|
||||||
|
response = client.schedule_key_deletion(
|
||||||
|
KeyId=key['KeyMetadata']['KeyId']
|
||||||
|
)
|
||||||
|
|
||||||
|
keyid = response['KeyId']
|
||||||
|
response = client.tag_resource(
|
||||||
|
KeyId=keyid,
|
||||||
|
Tags=[
|
||||||
|
{
|
||||||
|
'TagKey': 'string',
|
||||||
|
'TagValue': 'string'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Shouldn't have any data, just header
|
||||||
|
assert len(response.keys()) == 1
|
||||||
|
|
||||||
|
|
||||||
|
@mock_kms
|
||||||
|
def test_list_resource_tags():
|
||||||
|
client = boto3.client('kms', region_name='us-east-1')
|
||||||
|
key = client.create_key(Description='cancel-key-deletion')
|
||||||
|
response = client.schedule_key_deletion(
|
||||||
|
KeyId=key['KeyMetadata']['KeyId']
|
||||||
|
)
|
||||||
|
|
||||||
|
keyid = response['KeyId']
|
||||||
|
response = client.tag_resource(
|
||||||
|
KeyId=keyid,
|
||||||
|
Tags=[
|
||||||
|
{
|
||||||
|
'TagKey': 'string',
|
||||||
|
'TagValue': 'string'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
response = client.list_resource_tags(KeyId=keyid)
|
||||||
|
assert response['Tags'][0]['TagKey'] == 'string'
|
||||||
|
assert response['Tags'][0]['TagValue'] == 'string'
|
||||||
|
8
tests/test_packages/__init__.py
Normal file
8
tests/test_packages/__init__.py
Normal 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)
|
37
tests/test_packages/test_httpretty.py
Normal file
37
tests/test_packages/test_httpretty.py
Normal 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'
|
Loading…
Reference in New Issue
Block a user