Refactored AMI parsing

This commit is contained in:
Adrian Cole 2010-03-18 18:29:39 -07:00
parent 8a629d0087
commit 92cc6d6a21
8 changed files with 207 additions and 49 deletions

View File

@ -27,7 +27,6 @@ import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Resource;
@ -46,6 +45,7 @@ import org.jclouds.aws.ec2.compute.domain.PortsRegionTag;
import org.jclouds.aws.ec2.compute.domain.RegionTag;
import org.jclouds.aws.ec2.compute.functions.CreateKeyPairIfNeeded;
import org.jclouds.aws.ec2.compute.functions.CreateSecurityGroupIfNeeded;
import org.jclouds.aws.ec2.compute.functions.ImageParser;
import org.jclouds.aws.ec2.compute.functions.RunningInstanceToNodeMetadata;
import org.jclouds.aws.ec2.compute.strategy.EC2DestroyNodeStrategy;
import org.jclouds.aws.ec2.compute.strategy.EC2RunNodesAndAddToSetStrategy;
@ -55,13 +55,10 @@ import org.jclouds.aws.ec2.domain.RunningInstance;
import org.jclouds.aws.ec2.services.InstanceClient;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Size;
import org.jclouds.compute.domain.internal.ImageImpl;
import org.jclouds.compute.internal.ComputeServiceContextImpl;
import org.jclouds.compute.predicates.RunScriptRunning;
import org.jclouds.compute.reference.ComputeServiceConstants;
@ -82,7 +79,6 @@ import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
@ -282,9 +278,6 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
protected Logger logger = Logger.NULL;
}
// alestic-32-eu-west-1/debian-4.0-etch-base-20081130
public static final Pattern ALESTIC_PATTERN = Pattern.compile(".*/([^-]*)-([^-]*)-.*-(.*)");
@Provides
@Singleton
@Named(PROPERTY_EC2_AMI_OWNERS)
@ -297,46 +290,19 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
protected Map<String, ? extends Image> provideImages(final EC2Client sync,
Map<Region, URI> regionMap, LogHolder holder,
Function<ComputeMetadata, String> indexer,
@Named(PROPERTY_EC2_AMI_OWNERS) String[] amiOwners) throws InterruptedException,
ExecutionException, TimeoutException {
@Named(PROPERTY_EC2_AMI_OWNERS) String[] amiOwners, ImageParser parser)
throws InterruptedException, ExecutionException, TimeoutException {
final Set<Image> images = Sets.newHashSet();
holder.logger.debug(">> providing images");
for (final Region region : regionMap.keySet()) {
for (final org.jclouds.aws.ec2.domain.Image from : sync.getAMIServices()
.describeImagesInRegion(region, ownedBy(amiOwners))) {
OsFamily os = null;
String name = null;
String osDescription = from.getImageLocation();
String version = "";
Matcher matcher = ALESTIC_PATTERN.matcher(from.getImageLocation());
if (matcher.find()) {
try {
os = OsFamily.fromValue(matcher.group(1));
name = matcher.group(2);// TODO no field for os version
version = matcher.group(3);
} catch (IllegalArgumentException e) {
holder.logger.debug("<< didn't match os(%s)", matcher.group(1));
}
}
try {
images
.add(new ImageImpl(
from.getId(),
name,
region.toString(),
null,
ImmutableMap.<String, String> of("owner", from.getImageOwnerId()),
from.getDescription(),
version,
os,
osDescription,
from.getArchitecture() == org.jclouds.aws.ec2.domain.Image.Architecture.I386 ? Architecture.X86_32
: Architecture.X86_64));
} catch (NullPointerException e) {
holder.logger.debug("<< image (%s) missing (%s)", from.getId(), e.getMessage());
}
Image image = parser.apply(from);
if (image != null)
images.add(image);
else
holder.logger.debug("<< images(%s) didn't parse", from.getId());
}
}
holder.logger.debug("<< images(%d)", images.size());

View File

@ -0,0 +1,82 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.aws.ec2.compute.functions;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.internal.ImageImpl;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
@Singleton
public class ImageParser implements
Function<org.jclouds.aws.ec2.domain.Image, Image> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
// alestic-32-eu-west-1/debian-4.0-etch-base-20081130
public static final Pattern ALESTIC_PATTERN = Pattern
.compile(".*/([^-]*)-([^-]*)-.*-(.*)(\\.manifest.xml)?");
@Override
public Image apply(org.jclouds.aws.ec2.domain.Image from) {
OsFamily os = null;
String name = "";
String description = from.getDescription() != null ? from.getDescription() : from
.getImageLocation();
String osDescription = from.getImageLocation();
String version = "";
Matcher matcher = ALESTIC_PATTERN.matcher(from.getImageLocation());
if (matcher.find()) {
try {
os = OsFamily.fromValue(matcher.group(1));
name = matcher.group(2);// TODO no field for os version
version = matcher.group(3).replace("\\.manifest.xml", "");
} catch (IllegalArgumentException e) {
logger.debug("<< didn't match os(%s)", matcher.group(1));
}
}
return new ImageImpl(
from.getId(),
name,
from.getRegion().toString(),
null,
ImmutableMap.<String, String> of("owner", from.getImageOwnerId()),
description,
version,
os,
osDescription,
from.getArchitecture() == org.jclouds.aws.ec2.domain.Image.Architecture.I386 ? Architecture.X86_32
: Architecture.X86_64);
}
}

View File

@ -44,6 +44,11 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
return templateBuilder.osFamily(UBUNTU).smallest().architecture(Architecture.X86_32).build();
}
@Test
public void testTemplateBuilder() {
client.templateBuilder().imageId("ami-d57f93bc").build();
}
@Override
protected JschSshClientModule getSshModule() {
return new JschSshClientModule();

View File

@ -45,10 +45,9 @@ public class PropertiesTest {
}
public void testProperties() {
assertEquals(properties.getProperty("ec2.contextbuilder"),
EC2ContextBuilder.class.getName());
assertEquals(properties.getProperty("ec2.propertiesbuilder"),
EC2PropertiesBuilder.class.getName());
assertEquals(properties.getProperty("ec2.contextbuilder"), EC2ContextBuilder.class.getName());
assertEquals(properties.getProperty("ec2.propertiesbuilder"), EC2PropertiesBuilder.class
.getName());
}
}

View File

@ -0,0 +1,85 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.aws.ec2.functions;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import java.util.Set;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.compute.functions.ImageParser;
import org.jclouds.aws.ec2.domain.Image;
import org.jclouds.aws.ec2.xml.DescribeImagesResponseHandler;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "compute.PropertiesTest")
public class ImageParserTest extends BaseHandlerTest {
public void testParseVostokImage() {
InputStream is = getClass().getResourceAsStream("/ec2/vostok.xml");
Set<Image> result = parseImages(is);
ImageParser parser = new ImageParser();
org.jclouds.compute.domain.Image image = parser.apply(Iterables.get(result, 0));
assertEquals(image.getArchitecture(), org.jclouds.compute.domain.Architecture.X86_32);
assertEquals(image.getDescription(),
"vostok-builds/vostok-0.95-5622/vostok-0.95-5622.manifest.xml");
assertEquals(image.getId(), "ami-870de2ee");
assertEquals(image.getLocationId(), "default");
assertEquals(image.getName(), "");
assertEquals(image.getOsDescription(),
"vostok-builds/vostok-0.95-5622/vostok-0.95-5622.manifest.xml");
assertEquals(image.getOsFamily(), null);
assertEquals(image.getUserMetadata(), ImmutableMap.<String, String> of("owner",
"133804938231"));
assertEquals(image.getVersion(), "");
}
private Set<Image> parseImages(InputStream is) {
DescribeImagesResponseHandler handler = injector
.getInstance(DescribeImagesResponseHandler.class);
addDefaultRegionToHandler(handler);
Set<Image> result = factory.create(handler).parse(is);
return result;
}
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
GeneratedHttpRequest<?> request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(new Object[] { Region.DEFAULT });
replay(request);
handler.setContext(request);
}
}

View File

@ -0,0 +1,19 @@
<?xml version="1.0"?>
<DescribeImagesResponse xmlns="http://ec2.amazonaws.com/doc/2009-11-30/">
<requestId>6104eee1-affd-49d7-92a0-516cab8a8ba6</requestId>
<imagesSet>
<item>
<imageId>ami-870de2ee</imageId>
<imageLocation>vostok-builds/vostok-0.95-5622/vostok-0.95-5622.manifest.xml</imageLocation>
<imageState>available</imageState>
<imageOwnerId>133804938231</imageOwnerId>
<isPublic>false</isPublic>
<architecture>i386</architecture>
<imageType>machine</imageType>
<kernelId>aki-94c527fd</kernelId>
<ramdiskId>ari-96c527ff</ramdiskId>
<rootDeviceType>instance-store</rootDeviceType>
<blockDeviceMapping />
</item>
</imagesSet>
</DescribeImagesResponse>

View File

@ -81,7 +81,7 @@
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="COMPUTEFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-compute.log" />
@ -138,13 +138,13 @@
<category name="jclouds.compute">
<priority value="TRACE" />
<appender-ref ref="ASYNCCOMPUTE" />
</category><!--
</category>
<category name="jclouds.wire">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
--><!-- ======================= -->
<!-- ======================= -->
<!-- Setup the Root category -->
<!-- ======================= -->

View File

@ -104,8 +104,10 @@ public abstract class BaseComputeServiceLiveTest {
}
String secret = Files.toString(new File(secretKeyFile), Charsets.UTF_8);
assert secret.startsWith("-----BEGIN RSA PRIVATE KEY-----") : "invalid key:\n" + secret;
context = new ComputeServiceContextFactory().createContext(service, user, password,
ImmutableSet.of(new Log4JLoggingModule(), getSshModule()));
Injector injector = Guice.createInjector(getSshModule());
sshFactory = injector.getInstance(SshClient.Factory.class);
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);