Updated Branches:
  refs/heads/master 8db0218cf -> bbfec4a99

JCLOUDS-160: Support tags in EC2 images

Based on the work made by Brock Noland


Project: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/commit/bbfec4a9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/tree/bbfec4a9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/diff/bbfec4a9

Branch: refs/heads/master
Commit: bbfec4a9906a9df898fb3a464f1470917999cc1c
Parents: 8db0218
Author: Ignasi Barrera <[email protected]>
Authored: Fri Jul 5 00:43:47 2013 +0200
Committer: Ignasi Barrera <[email protected]>
Committed: Sat Jul 6 10:08:10 2013 +0200

----------------------------------------------------------------------
 .../main/java/org/jclouds/ec2/domain/Image.java | 16 ++++++++--
 .../ec2/xml/DescribeImagesResponseHandler.java  | 28 ++++++++++++++---
 .../xml/DescribeImagesResponseHandlerTest.java  | 25 ++++++++++++---
 .../src/test/resources/describe_images_tags.xml | 33 ++++++++++++++++++++
 .../xml/NovaDescribeImagesResponseHandler.java  |  5 +--
 .../strategy/AWSEC2ReviseParsedImageTest.java   |  5 ++-
 6 files changed, 99 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/bbfec4a9/apis/ec2/src/main/java/org/jclouds/ec2/domain/Image.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/domain/Image.java 
b/apis/ec2/src/main/java/org/jclouds/ec2/domain/Image.java
index c4e7946..6304c43 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/domain/Image.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/domain/Image.java
@@ -59,6 +59,7 @@ public class Image implements Comparable<Image> {
    @Nullable
    private final String rootDeviceName;
    private final Map<String, EbsBlockDevice> ebsBlockDevices = 
Maps.newHashMap();
+   private final Map<String, String> tags = Maps.newLinkedHashMap();
    private final VirtualizationType virtualizationType;
 
    public VirtualizationType getVirtualizationType() {
@@ -76,7 +77,7 @@ public class Image implements Comparable<Image> {
             ImageType imageType, boolean isPublic, Iterable<String> 
productCodes, @Nullable String kernelId,
             @Nullable String platform, @Nullable String ramdiskId, 
RootDeviceType rootDeviceType,
             @Nullable String rootDeviceName, Map<String, EbsBlockDevice> 
ebsBlockDevices,
-            VirtualizationType virtualizationType, Hypervisor hypervisor) {
+            Map<String, String> tags, VirtualizationType virtualizationType, 
Hypervisor hypervisor) {
       this.region = checkNotNull(region, "region");
       this.architecture = architecture;
       this.imageId = checkNotNull(imageId, "imageId");
@@ -95,6 +96,7 @@ public class Image implements Comparable<Image> {
       this.ramdiskId = ramdiskId;
       this.rootDeviceType = checkNotNull(rootDeviceType, "rootDeviceType");
       this.ebsBlockDevices.putAll(checkNotNull(ebsBlockDevices, 
"ebsBlockDevices"));
+      this.tags.putAll(checkNotNull(tags, "tags"));
       this.virtualizationType = checkNotNull(virtualizationType, 
"virtualizationType");
       this.hypervisor = checkNotNull(hypervisor, "hypervisor");
    }
@@ -346,6 +348,10 @@ public class Image implements Comparable<Image> {
       return ebsBlockDevices;
    }
 
+   public Map<String, String> getTags() {
+      return tags;
+   }
+
    @Override
    public int hashCode() {
       final int prime = 31;
@@ -353,6 +359,7 @@ public class Image implements Comparable<Image> {
       result = prime * result + ((architecture == null) ? 0 : 
architecture.hashCode());
       result = prime * result + ((description == null) ? 0 : 
description.hashCode());
       result = prime * result + ((ebsBlockDevices == null) ? 0 : 
ebsBlockDevices.hashCode());
+      result = prime * result + ((tags == null) ? 0 : tags.hashCode());
       result = prime * result + ((imageId == null) ? 0 : imageId.hashCode());
       result = prime * result + ((imageLocation == null) ? 0 : 
imageLocation.hashCode());
       result = prime * result + ((imageOwnerId == null) ? 0 : 
imageOwnerId.hashCode());
@@ -395,6 +402,11 @@ public class Image implements Comparable<Image> {
             return false;
       } else if (!ebsBlockDevices.equals(other.ebsBlockDevices))
          return false;
+      if (tags == null) {
+         if (other.tags != null)
+            return false;
+      } else if (!tags.equals(other.tags))
+         return false;
       if (imageId == null) {
          if (other.imageId != null)
             return false;
@@ -478,7 +490,7 @@ public class Image implements Comparable<Image> {
                + ", kernelId=" + kernelId + ", name=" + name + ", platform=" + 
platform + ", productCodes="
                + productCodes + ", ramdiskId=" + ramdiskId + ", region=" + 
region + ", rootDeviceName="
                + rootDeviceName + ", rootDeviceType=" + rootDeviceType + ", 
virtualizationType=" + virtualizationType
-               + ", hypervisor=" + hypervisor + "]";
+               + ", hypervisor=" + hypervisor + ", tags=" + tags + "]";
    }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/bbfec4a9/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeImagesResponseHandler.java
----------------------------------------------------------------------
diff --git 
a/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeImagesResponseHandler.java 
b/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeImagesResponseHandler.java
index edcf499..8e9a656 100644
--- 
a/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeImagesResponseHandler.java
+++ 
b/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeImagesResponseHandler.java
@@ -17,6 +17,7 @@
 package org.jclouds.ec2.xml;
 
 import static org.jclouds.util.SaxUtils.currentOrNull;
+import static org.jclouds.util.SaxUtils.equalsOrSuffix;
 
 import java.util.Map;
 import java.util.Set;
@@ -54,8 +55,9 @@ import com.google.common.collect.Sets;
 public class DescribeImagesResponseHandler extends 
ParseSax.HandlerForGeneratedRequestWithResult<Set<Image>> {
 
    @Inject
-   public DescribeImagesResponseHandler(@Region Supplier<String> 
defaultRegion) {
+   public DescribeImagesResponseHandler(@Region Supplier<String> 
defaultRegion, TagSetHandler tagSetHandler) {
       this.defaultRegion = defaultRegion;
+      this.tagSetHandler = tagSetHandler;
    }
 
    @Resource
@@ -64,6 +66,7 @@ public class DescribeImagesResponseHandler extends 
ParseSax.HandlerForGeneratedR
    protected Set<Image> contents = Sets.newLinkedHashSet();
    private StringBuilder currentText = new StringBuilder();
    private final Supplier<String> defaultRegion;
+   private final TagSetHandler tagSetHandler;
 
    private Architecture architecture;
    private String name;
@@ -81,8 +84,10 @@ public class DescribeImagesResponseHandler extends 
ParseSax.HandlerForGeneratedR
    private String ramdiskId;
    private boolean inProductCodes;
    private boolean inBlockDeviceMapping;
+   private boolean inTagSet;
    private RootDeviceType rootDeviceType = RootDeviceType.INSTANCE_STORE;
    private Map<String, EbsBlockDevice> ebsBlockDevices = Maps.newHashMap();
+   private Map<String, String> tags = Maps.newLinkedHashMap();
    private String deviceName;
    private String snapshotId;
    private VirtualizationType virtualizationType = 
VirtualizationType.PARAVIRTUAL;
@@ -102,10 +107,21 @@ public class DescribeImagesResponseHandler extends 
ParseSax.HandlerForGeneratedR
          inProductCodes = true;
       } else if (qName.equals("blockDeviceMapping")) {
          inBlockDeviceMapping = true;
+      } else if (equalsOrSuffix(qName, "tagSet")) {
+         inTagSet = true;
+      }
+      if (inTagSet) {
+         tagSetHandler.startElement(uri, name, qName, attrs);
       }
    }
 
    public void endElement(String uri, String name, String qName) {
+      if (equalsOrSuffix(qName, "tagSet")) {
+         inTagSet = false;
+         tags = tagSetHandler.getResult();
+      } else if (inTagSet) {
+         tagSetHandler.endElement(uri, name, qName);
+      }
       if (qName.equals("architecture")) {
          architecture = Architecture.fromValue(currentText.toString().trim());
       // Nova Diablo uses the wrong name for this field
@@ -161,14 +177,14 @@ public class DescribeImagesResponseHandler extends 
ParseSax.HandlerForGeneratedR
             this.snapshotId = null;
             this.volumeSize = 0;
             this.deleteOnTermination = true;
-         } else if (!inProductCodes) {
+         } else if (!inTagSet && !inProductCodes) {
             try {
                String region = getRequest() != null ? 
AWSUtils.findRegionInArgsOrNull(getRequest()) : null;
                if (region == null)
                   region = defaultRegion.get();
                contents.add(new Image(region, architecture, this.name, 
description, imageId, imageLocation,
                         imageOwnerId, imageState, rawState, imageType, 
isPublic, productCodes, kernelId, platform,
-                        ramdiskId, rootDeviceType, rootDeviceName, 
ebsBlockDevices, virtualizationType, hypervisor));
+                        ramdiskId, rootDeviceType, rootDeviceName, 
ebsBlockDevices, tags, virtualizationType, hypervisor));
             } catch (NullPointerException e) {
                logger.warn(e, "malformed image: %s", imageId);
             }
@@ -198,6 +214,10 @@ public class DescribeImagesResponseHandler extends 
ParseSax.HandlerForGeneratedR
    }
 
    public void characters(char ch[], int start, int length) {
-      currentText.append(ch, start, length);
+      if (inTagSet) {
+         tagSetHandler.characters(ch, start, length);
+      } else {
+         currentText.append(ch, start, length);
+      }
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/bbfec4a9/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeImagesResponseHandlerTest.java
----------------------------------------------------------------------
diff --git 
a/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeImagesResponseHandlerTest.java
 
b/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeImagesResponseHandlerTest.java
index 2ddf4ab..f2b0894 100644
--- 
a/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeImagesResponseHandlerTest.java
+++ 
b/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeImagesResponseHandlerTest.java
@@ -59,7 +59,7 @@ public class DescribeImagesResponseHandlerTest {
                "ec2-public-images/fedora-8-i386-base-v1.04.manifest.xml", 
"206029621532", ImageState.AVAILABLE, "available",
                ImageType.MACHINE, false, Sets.<String> newHashSet("9961934F"), 
"aki-4438dd2d", null, "ari-4538dd2c",
                RootDeviceType.INSTANCE_STORE, null, ImmutableMap.<String, 
EbsBlockDevice> of(),
-               VirtualizationType.PARAVIRTUAL, Hypervisor.XEN));
+               ImmutableMap.<String, String> of(), 
VirtualizationType.PARAVIRTUAL, Hypervisor.XEN));
 
       Set<Image> result = parseImages("/describe_images.xml");
 
@@ -73,7 +73,7 @@ public class DescribeImagesResponseHandlerTest {
                
"aws-solutions-amis/SqlSvrStd2003r2-x86_64-Win_SFWBasic5.1-v1.0.manifest.xml", 
"771350841976",
                ImageState.AVAILABLE, "available", ImageType.MACHINE, true, 
Sets.<String> newHashSet("5771E9A6"), null, "windows",
                null, RootDeviceType.INSTANCE_STORE, null, 
ImmutableMap.<String, EbsBlockDevice> of(),
-               VirtualizationType.PARAVIRTUAL, Hypervisor.XEN));
+               ImmutableMap.<String, String> of(), 
VirtualizationType.PARAVIRTUAL, Hypervisor.XEN));
 
 
       Set<Image> result = parseImages("/describe_images_windows.xml");
@@ -89,7 +89,7 @@ public class DescribeImagesResponseHandlerTest {
                ImageState.AVAILABLE, "available", ImageType.MACHINE, true, 
Sets.<String> newHashSet(), null, "windows", null,
                RootDeviceType.EBS, "/dev/sda1", ImmutableMap.<String, 
EbsBlockDevice> of("/dev/sda1",
                         new EbsBlockDevice("snap-d01272b9", 30, true), "xvdf", 
new EbsBlockDevice("snap-d31272ba", 250,
-                                 false)), VirtualizationType.HVM, 
Hypervisor.XEN));
+                                 false)), ImmutableMap.<String, String> of(), 
VirtualizationType.HVM, Hypervisor.XEN));
 
       Set<Image> result = parseImages("/describe_images_ebs.xml");
 
@@ -98,12 +98,29 @@ public class DescribeImagesResponseHandlerTest {
       assertEquals(get(result, 0).getRawState(), "available");
    }
    
+   public void testTags() {
+      Set<Image> contents = ImmutableSet.of(new Image("us-east-1", 
Architecture.I386, null, null, "ami-be3adfd7",
+            "ec2-public-images/fedora-8-i386-base-v1.04.manifest.xml", 
"206029621532", ImageState.AVAILABLE, "available",
+            ImageType.MACHINE, false, Sets.<String> newHashSet("9961934F"), 
"aki-4438dd2d", null, "ari-4538dd2c",
+            RootDeviceType.INSTANCE_STORE, null, ImmutableMap.<String, 
EbsBlockDevice> of(),
+            ImmutableMap.<String, String> of("Name", "Some machine name", 
"Second", "Second value"),
+            VirtualizationType.PARAVIRTUAL, Hypervisor.XEN));
+
+      Set<Image> result = parseImages("/describe_images_tags.xml");
+
+      assertEquals(result.toString(), contents.toString());
+      assertEquals(get(result, 0).getImageState(), ImageState.AVAILABLE);
+      assertEquals(get(result, 0).getRawState(), "available");
+      assertEquals(get(result, 0).getTags().get("Name"), "Some machine name");
+      assertEquals(get(result, 0).getTags().get("Second"), "Second value");
+   }
+
    public void testDiabloWithIncorrectDisplayNameField() {
       Set<Image> contents = ImmutableSet.of(new Image("us-east-1", 
Architecture.X86_64, "CentOS 6.2 Server 64-bit 20120125", "", "ami-0000054e",
                "local (CentOS 6.2 Server 64-bit 20120125)", "", 
ImageState.AVAILABLE, "available",
                ImageType.MACHINE, true, Sets.<String> newHashSet(), 
"aki-0000054c", null, "ari-0000054d",
                RootDeviceType.INSTANCE_STORE, "/dev/sda1", 
ImmutableMap.<String, EbsBlockDevice> of(),
-               VirtualizationType.PARAVIRTUAL, Hypervisor.XEN));
+               ImmutableMap.<String, String> of(), 
VirtualizationType.PARAVIRTUAL, Hypervisor.XEN));
       
       Set<Image> result = parseImages("/describe_images_nova.xml");
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/bbfec4a9/apis/ec2/src/test/resources/describe_images_tags.xml
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/resources/describe_images_tags.xml 
b/apis/ec2/src/test/resources/describe_images_tags.xml
new file mode 100644
index 0000000..ab22d1d
--- /dev/null
+++ b/apis/ec2/src/test/resources/describe_images_tags.xml
@@ -0,0 +1,33 @@
+<DescribeImagesResponse xmlns="http://ec2.amazonaws.com/doc/2009-11-30/";>
+    <imagesSet>
+        <item>
+            <imageId>ami-be3adfd7</imageId>
+            
<imageLocation>ec2-public-images/fedora-8-i386-base-v1.04.manifest.xml</imageLocation>
+            <imageState>available</imageState>
+            <imageOwnerId>206029621532</imageOwnerId>
+            <isPublic>false</isPublic>
+            <productCodes>
+                <item>
+                    <productCode>9961934F</productCode>
+                </item>
+            </productCodes>
+            <architecture>i386</architecture>
+            <imageType>machine</imageType>
+            <kernelId>aki-4438dd2d</kernelId>
+            <ramdiskId>ari-4538dd2c</ramdiskId>
+            <rootDeviceType>instance-store</rootDeviceType>
+            <blockDeviceMapping />
+            <virtualizationType>paravirtual</virtualizationType>
+            <tagSet>
+                <item>
+                    <key>Name</key>
+                    <value>Some machine name</value>
+                </item>
+                <item>
+                    <key>Second</key>
+                    <value>Second value</value>
+                </item>
+            </tagSet>
+        </item>
+    </imagesSet>
+</DescribeImagesResponse>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/bbfec4a9/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/xml/NovaDescribeImagesResponseHandler.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/xml/NovaDescribeImagesResponseHandler.java
 
b/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/xml/NovaDescribeImagesResponseHandler.java
index 12fdfe7..bf654d1 100644
--- 
a/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/xml/NovaDescribeImagesResponseHandler.java
+++ 
b/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/xml/NovaDescribeImagesResponseHandler.java
@@ -23,6 +23,7 @@ import javax.inject.Inject;
 import org.jclouds.ec2.domain.Image;
 import org.jclouds.ec2.domain.Image.ImageType;
 import org.jclouds.ec2.xml.DescribeImagesResponseHandler;
+import org.jclouds.ec2.xml.TagSetHandler;
 import org.jclouds.location.Region;
 
 import com.google.common.base.Predicate;
@@ -37,8 +38,8 @@ import com.google.common.collect.Iterables;
  */
 public class NovaDescribeImagesResponseHandler extends 
DescribeImagesResponseHandler {
    @Inject
-   public NovaDescribeImagesResponseHandler(@Region Supplier<String> 
defaultRegion) {
-      super(defaultRegion);
+   public NovaDescribeImagesResponseHandler(@Region Supplier<String> 
defaultRegion, TagSetHandler tagSetHandler) {
+      super(defaultRegion, tagSetHandler);
    }
 
    public Set<Image> getResult() {

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/bbfec4a9/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2ReviseParsedImageTest.java
----------------------------------------------------------------------
diff --git 
a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2ReviseParsedImageTest.java
 
b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2ReviseParsedImageTest.java
index 7789af2..e63a9b4 100644
--- 
a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2ReviseParsedImageTest.java
+++ 
b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2ReviseParsedImageTest.java
@@ -100,9 +100,12 @@ public class AWSEC2ReviseParsedImageTest {
         RootDeviceType rootDeviceType = RootDeviceType.EBS;
         String rootDeviceName = "";
         Map<String, Image.EbsBlockDevice> ebsBlockDevices = ImmutableMap.of();
+        Map<String, String> tags = ImmutableMap.of();
         VirtualizationType virtualizationType = VirtualizationType.HVM;
         Hypervisor hypervisor = Hypervisor.XEN;
-        Image from = new Image(region, architecture, imageName, description, 
imageId, imageOwnerId + "/" + imageName, imageOwnerId, imageState, "available", 
imageType, isPublic, productCodes, kernelId, platform, ramdiskId, 
rootDeviceType, rootDeviceName, ebsBlockDevices, virtualizationType, 
hypervisor);
+      Image from = new Image(region, architecture, imageName, description, 
imageId, imageOwnerId + "/" + imageName,
+            imageOwnerId, imageState, "available", imageType, isPublic, 
productCodes, kernelId, platform, ramdiskId,
+            rootDeviceType, rootDeviceName, ebsBlockDevices, tags, 
virtualizationType, hypervisor);
         return from;
     }
 }

Reply via email to