mirror of https://github.com/apache/jclouds.git
JCLOUDS-160: Support tags in EC2 images
Based on the work made by Brock Noland
This commit is contained in:
parent
8db0218cf7
commit
bbfec4a990
|
@ -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 + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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>
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue