diff options
-rw-r--r-- | boto/ec2/ec2object.py | 49 | ||||
-rw-r--r-- | tests/unit/ec2/test_ec2object.py | 66 |
2 files changed, 94 insertions, 21 deletions
diff --git a/boto/ec2/ec2object.py b/boto/ec2/ec2object.py index 9edf12ee..fa50a9fc 100644 --- a/boto/ec2/ec2object.py +++ b/boto/ec2/ec2object.py @@ -65,7 +65,7 @@ class TaggedEC2Object(EC2Object): def add_tag(self, key, value='', dry_run=False): """ - Add a tag to this object. Tag's are stored by AWS and can be used + Add a tag to this object. Tags are stored by AWS and can be used to organize and filter resources. Adding a tag involves a round-trip to the EC2 service. @@ -77,14 +77,7 @@ class TaggedEC2Object(EC2Object): If you want only the tag name and no value, the value should be the empty string. """ - status = self.connection.create_tags( - [self.id], - {key: value}, - dry_run=dry_run - ) - if self.tags is None: - self.tags = TagSet() - self.tags[key] = value + self.add_tags({key: value}, dry_run) def add_tags(self, tags, dry_run=False): """ @@ -117,21 +110,35 @@ class TaggedEC2Object(EC2Object): :type value: str :param value: An optional value that can be stored with the tag. - If a value is provided, it must match the value - currently stored in EC2. If not, the tag will not - be removed. If a value of None is provided, all - tags with the specified name will be deleted. - NOTE: There is an important distinction between - a value of '' and a value of None. + If a value is provided, it must match the value currently + stored in EC2. If not, the tag will not be removed. If + a value of None is provided, the tag will be + unconditionally deleted. + NOTE: There is an important distinction between a value + of '' and a value of None. + """ + self.remove_tags({key: value}, dry_run) + + def remove_tags(self, tags, dry_run=False): + """ + Removes tags from this object. Removing tags involves a round-trip + to the EC2 service. + + :type tags: dict + :param tags: A dictionary of key-value pairs for the tags being removed. + For each key, the provided value must match the value + currently stored in EC2. If not, that particular tag will + not be removed. However, if a value of None is provided, + the tag will be unconditionally deleted. + NOTE: There is an important distinction between a value of + '' and a value of None. """ - if value is not None: - tags = {key: value} - else: - tags = [key] status = self.connection.delete_tags( [self.id], tags, dry_run=dry_run ) - if key in self.tags: - del self.tags[key] + for key, value in tags.items(): + if key in self.tags: + if value is None or value == self.tags[key]: + del self.tags[key] diff --git a/tests/unit/ec2/test_ec2object.py b/tests/unit/ec2/test_ec2object.py index 4ece8d92..14841e91 100644 --- a/tests/unit/ec2/test_ec2object.py +++ b/tests/unit/ec2/test_ec2object.py @@ -138,8 +138,74 @@ class TestRemoveTags(AWSMockServiceTestCase): 'SignatureVersion', 'Timestamp', 'Version']) + self.assertEqual(taggedEC2Object.tags, + {"key1": "value1", "key2": "value2"}) + + def test_remove_tags(self): + self.set_http_response(status_code=200) + taggedEC2Object = TaggedEC2Object(self.service_connection) + taggedEC2Object.id = "i-abcd1234" + taggedEC2Object.tags["key1"] = "value1" + taggedEC2Object.tags["key2"] = "value2" + + taggedEC2Object.remove_tags({"key1": "value1", "key2": "value2"}) + + self.assert_request_parameters({ + 'ResourceId.1': 'i-abcd1234', + 'Action': 'DeleteTags', + 'Tag.1.Key': 'key1', + 'Tag.1.Value': 'value1', + 'Tag.2.Key': 'key2', + 'Tag.2.Value': 'value2'}, + ignore_params_values=['AWSAccessKeyId', 'SignatureMethod', + 'SignatureVersion', 'Timestamp', + 'Version']) + + self.assertEqual(taggedEC2Object.tags, {}) + + def test_remove_tags_wrong_values(self): + self.set_http_response(status_code=200) + taggedEC2Object = TaggedEC2Object(self.service_connection) + taggedEC2Object.id = "i-abcd1234" + taggedEC2Object.tags["key1"] = "value1" + taggedEC2Object.tags["key2"] = "value2" + + taggedEC2Object.remove_tags({"key1": "value1", "key2": "value3"}) + + self.assert_request_parameters({ + 'ResourceId.1': 'i-abcd1234', + 'Action': 'DeleteTags', + 'Tag.1.Key': 'key1', + 'Tag.1.Value': 'value1', + 'Tag.2.Key': 'key2', + 'Tag.2.Value': 'value3'}, + ignore_params_values=['AWSAccessKeyId', 'SignatureMethod', + 'SignatureVersion', 'Timestamp', + 'Version']) + self.assertEqual(taggedEC2Object.tags, {"key2": "value2"}) + def test_remove_tags_none_values(self): + self.set_http_response(status_code=200) + taggedEC2Object = TaggedEC2Object(self.service_connection) + taggedEC2Object.id = "i-abcd1234" + taggedEC2Object.tags["key1"] = "value1" + taggedEC2Object.tags["key2"] = "value2" + + taggedEC2Object.remove_tags({"key1": "value1", "key2": None}) + + self.assert_request_parameters({ + 'ResourceId.1': 'i-abcd1234', + 'Action': 'DeleteTags', + 'Tag.1.Key': 'key1', + 'Tag.1.Value': 'value1', + 'Tag.2.Key': 'key2'}, + ignore_params_values=['AWSAccessKeyId', 'SignatureMethod', + 'SignatureVersion', 'Timestamp', + 'Version']) + + self.assertEqual(taggedEC2Object.tags, {}) + if __name__ == '__main__': unittest.main() |