Skip to content

Commit 143d93c

Browse files
author
Rohan McGovern
authored
Merge pull request release-engineering#38 from JAVGan/multitags
AWS: Allow setting tags to snapshots or AMIs only
2 parents 1df18a2 + c49b004 commit 143d93c

2 files changed

Lines changed: 127 additions & 4 deletions

File tree

cloudimg/aws.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ class AWSPublishingMetadata(PublishingMetadata):
8383
billing_products (list, optional): Billing product identifiers
8484
8585
boot_mode (str, optional): The boot mode for booting up the AMI on EC2.
86+
87+
snapshot_tags (dict, optional): Tags to be applied to the snapshot
88+
import only.
89+
90+
ami_tags (dict, optional): Tags to be applied to the registered AMI
91+
only.
8692
"""
8793

8894
def __init__(self, *args, **kwargs):
@@ -91,6 +97,8 @@ def __init__(self, *args, **kwargs):
9197
self.billing_products = kwargs.pop('billing_products', None)
9298
bmode_str = kwargs.pop('boot_mode', None) or "not_set"
9399
self.boot_mode = AWSBootMode[bmode_str]
100+
self.snapshot_tags = kwargs.pop('snapshot_tags', None)
101+
self.ami_tags = kwargs.pop('ami_tags', None)
94102

95103
super(AWSPublishingMetadata, self).__init__(*args, **kwargs)
96104

@@ -564,6 +572,13 @@ def publish(self, metadata):
564572
Returns:
565573
An EC2 Image
566574
"""
575+
def add_tags(tag_parameter_name, extra_kwargs):
576+
new_tags = getattr(metadata, tag_parameter_name, None)
577+
if new_tags:
578+
tags = extra_kwargs.get("tags") or {}
579+
new_tags.update(tags)
580+
extra_kwargs.update({"tags": new_tags})
581+
567582
log.info('Searching for image: %s', metadata.image_name)
568583
image = (
569584
self.get_image_by_name(metadata.image_name) or
@@ -584,8 +599,7 @@ def publish(self, metadata):
584599

585600
# Set tags when they're provided
586601
extra_kwargs = {}
587-
if metadata.tags:
588-
extra_kwargs.update({"tags": metadata.tags})
602+
add_tags("tags", extra_kwargs)
589603

590604
if not obj:
591605
log.info('Object does not exist: %s', metadata.object_name)
@@ -596,6 +610,7 @@ def publish(self, metadata):
596610
else:
597611
log.info('Object already exists')
598612

613+
add_tags("snapshot_tags", extra_kwargs)
599614
snapshot = self.import_snapshot(obj,
600615
metadata.snapshot_name,
601616
**extra_kwargs)
@@ -771,8 +786,10 @@ def register_image(self, snapshot, metadata):
771786
BillingProducts=metadata.billing_products,
772787
**optional_kwargs,
773788
)
774-
if metadata.tags:
775-
self.tag_image(image, metadata.tags)
789+
if metadata.tags or metadata.ami_tags:
790+
tags = metadata.tags or {}
791+
tags.update(metadata.ami_tags or {})
792+
self.tag_image(image, tags)
776793
return image
777794

778795
def share_image(self, image, accounts=[], groups=[]):

tests/test_aws.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,85 @@ def test_publish_tags(self,
700700
self.md.object_name,
701701
tags=tags)
702702

703+
@patch('cloudimg.aws.AWSService.upload_to_container')
704+
@patch('cloudimg.aws.AWSService.import_snapshot')
705+
@patch('cloudimg.aws.AWSService.register_image')
706+
@patch('cloudimg.aws.AWSService.share_image')
707+
@patch('cloudimg.aws.AWSService.get_image_by_tags')
708+
@patch('cloudimg.aws.AWSService.get_image_by_name')
709+
@patch('cloudimg.aws.AWSService.get_snapshot_by_name')
710+
@patch('cloudimg.aws.AWSService.get_object_by_name')
711+
def test_publish_snapshot_tags(self,
712+
get_object_by_name,
713+
get_snapshot_by_name,
714+
get_image_by_name,
715+
get_image_by_tags,
716+
share_image,
717+
register_image,
718+
import_snapshot,
719+
upload_to_container):
720+
get_image_by_name.return_value = None
721+
get_image_by_tags.return_value = None
722+
get_snapshot_by_name.return_value = None
723+
get_object_by_name.return_value = None
724+
self.md.tags = None
725+
self.md.snapshot_tags = {"snapshot": "tag"}
726+
published = self.svc.publish(self.md)
727+
728+
share_image.assert_called_once_with(published,
729+
accounts=[],
730+
groups=[])
731+
self.assertEqual(register_image.call_count, 1)
732+
import_snapshot.assert_called_once_with(
733+
ANY,
734+
self.md.snapshot_name,
735+
tags={"snapshot": "tag"},
736+
)
737+
upload_to_container.assert_called_once_with(self.md.image_path,
738+
self.md.container,
739+
self.md.object_name)
740+
741+
@patch('cloudimg.aws.AWSService.upload_to_container')
742+
@patch('cloudimg.aws.AWSService.import_snapshot')
743+
@patch('cloudimg.aws.AWSService.register_image')
744+
@patch('cloudimg.aws.AWSService.share_image')
745+
@patch('cloudimg.aws.AWSService.get_image_by_tags')
746+
@patch('cloudimg.aws.AWSService.get_image_by_name')
747+
@patch('cloudimg.aws.AWSService.get_snapshot_by_name')
748+
@patch('cloudimg.aws.AWSService.get_object_by_name')
749+
def test_publish_merged_snapshot_tags(
750+
self,
751+
get_object_by_name,
752+
get_snapshot_by_name,
753+
get_image_by_name,
754+
get_image_by_tags,
755+
share_image,
756+
register_image,
757+
import_snapshot,
758+
upload_to_container,
759+
):
760+
get_image_by_name.return_value = None
761+
get_image_by_tags.return_value = None
762+
get_snapshot_by_name.return_value = None
763+
get_object_by_name.return_value = None
764+
self.md.tags = {"foo": "bar"}
765+
self.md.snapshot_tags = {"snapshot": "tag"}
766+
published = self.svc.publish(self.md)
767+
768+
share_image.assert_called_once_with(published,
769+
accounts=[],
770+
groups=[])
771+
self.assertEqual(register_image.call_count, 1)
772+
import_snapshot.assert_called_once_with(
773+
ANY,
774+
self.md.snapshot_name,
775+
tags={"foo": "bar", "snapshot": "tag"},
776+
)
777+
upload_to_container.assert_called_once_with(self.md.image_path,
778+
self.md.container,
779+
self.md.object_name,
780+
tags={"foo": "bar"})
781+
703782
@patch('cloudimg.aws.AWSService.tag_image')
704783
def test_register_image_no_tags(self, tag_image):
705784
self.mock_register_image.return_value = "fakeimg"
@@ -741,6 +820,33 @@ def test_register_image_tags(self, tag_image):
741820
tag_image.assert_called_once_with("fakeimg", self.md.tags)
742821
self.assertEqual(res, "fakeimg")
743822

823+
@patch('cloudimg.aws.AWSService.tag_image')
824+
def test_register_image_ami_tags(self, tag_image):
825+
self.md.tags = None
826+
self.md.ami_tags = {"ami": "tag"}
827+
self.mock_register_image.return_value = "fakeimg"
828+
829+
res = self.svc.register_image(MagicMock(), self.md)
830+
831+
self.mock_register_image.assert_called_once()
832+
tag_image.assert_called_once_with("fakeimg", {"ami": "tag"})
833+
self.assertEqual(res, "fakeimg")
834+
835+
@patch('cloudimg.aws.AWSService.tag_image')
836+
def test_register_image_merged_ami_tags(self, tag_image):
837+
self.md.tags = {"tag": "tag"}
838+
self.md.ami_tags = {"ami": "tag"}
839+
self.mock_register_image.return_value = "fakeimg"
840+
841+
res = self.svc.register_image(MagicMock(), self.md)
842+
843+
self.mock_register_image.assert_called_once()
844+
tag_image.assert_called_once_with(
845+
"fakeimg",
846+
{"tag": "tag", "ami": "tag"},
847+
)
848+
self.assertEqual(res, "fakeimg")
849+
744850
@patch('cloudimg.aws.AWSService.tag_image')
745851
def test_register_image_boot_mode(self, tag_image):
746852
self.mock_register_image.return_value = "fakeimg"

0 commit comments

Comments
 (0)