Issue 158: ProductItemToImage implementation and tests

This commit is contained in:
Jason King 2011-09-26 15:39:34 +01:00
parent 7894d830bf
commit 7bcdde91a3
4 changed files with 294 additions and 79 deletions

View File

@ -18,8 +18,9 @@
*/
package org.jclouds.softlayer.compute.config;
import java.util.Set;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.inject.TypeLiteral;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
import org.jclouds.compute.domain.NodeMetadata;
@ -28,17 +29,16 @@ import org.jclouds.location.suppliers.OnlyLocationOrFirstZone;
import org.jclouds.softlayer.SoftLayerAsyncClient;
import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.compute.functions.DatacenterToLocation;
import org.jclouds.softlayer.compute.functions.ProductItemPriceToImage;
import org.jclouds.softlayer.compute.functions.ProductItemPricesToHardware;
import org.jclouds.softlayer.compute.functions.ProductItemToImage;
import org.jclouds.softlayer.compute.functions.VirtualGuestToNodeMetadata;
import org.jclouds.softlayer.compute.strategy.SoftLayerComputeServiceAdapter;
import org.jclouds.softlayer.domain.Datacenter;
import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.ProductItemPrice;
import org.jclouds.softlayer.domain.VirtualGuest;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.inject.TypeLiteral;
import java.util.Set;
/**
*
@ -54,17 +54,17 @@ public class SoftLayerComputeServiceContextModule extends
@Override
protected void configure() {
super.configure();
bind(new TypeLiteral<ComputeServiceAdapter<VirtualGuest, Set<ProductItemPrice>, ProductItemPrice, Datacenter>>() {
}).to(SoftLayerComputeServiceAdapter.class);
bind(new TypeLiteral<Function<VirtualGuest, NodeMetadata>>() {
}).to(VirtualGuestToNodeMetadata.class);
bind(new TypeLiteral<Function<ProductItemPrice, org.jclouds.compute.domain.Image>>() {
}).to(ProductItemPriceToImage.class);
bind(new TypeLiteral<Function<Set<ProductItemPrice>, org.jclouds.compute.domain.Hardware>>() {
}).to(ProductItemPricesToHardware.class);
bind(new TypeLiteral<Function<Datacenter, Location>>() {
}).to(DatacenterToLocation.class);
bind(new TypeLiteral<Supplier<Location>>() {
}).to(OnlyLocationOrFirstZone.class);
bind(new TypeLiteral<ComputeServiceAdapter<VirtualGuest, Set<ProductItemPrice>, ProductItemPrice, Datacenter>>() {})
.to(SoftLayerComputeServiceAdapter.class);
bind(new TypeLiteral<Function<VirtualGuest, NodeMetadata>>() {})
.to(VirtualGuestToNodeMetadata.class);
bind(new TypeLiteral<Function<ProductItem, org.jclouds.compute.domain.Image>>() {})
.to(ProductItemToImage.class);
bind(new TypeLiteral<Function<Set<ProductItemPrice>, org.jclouds.compute.domain.Hardware>>() {})
.to(ProductItemPricesToHardware.class);
bind(new TypeLiteral<Function<Datacenter, Location>>() {})
.to(DatacenterToLocation.class);
bind(new TypeLiteral<Supplier<Location>>() {})
.to(OnlyLocationOrFirstZone.class);
}
}

View File

@ -1,61 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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.softlayer.compute.functions;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.softlayer.domain.ProductItemPrice;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Singleton
public class ProductItemPriceToImage implements Function<ProductItemPrice, Image> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
@Override
public Image apply(ProductItemPrice from) {
ImageBuilder builder = new ImageBuilder();
//TODO
// builder.ids(from.id + "");
// builder.name(from.name);
// builder.description(from.name);
//
// OsFamily family = null;
// try {
// family = OsFamily.fromValue(from.name);
// builder.operatingSystem(new OperatingSystem.Builder().name(from.name).family(family).build());
// } catch (IllegalArgumentException e) {
// logger.debug("<< didn't match os(%s)", from);
// }
return builder.build();
}
}

View File

@ -0,0 +1,147 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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.softlayer.compute.functions;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.softlayer.domain.ProductItem;
import com.google.common.base.Function;
import java.util.NoSuchElementException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Jason King
*/
@Singleton
public class ProductItemToImage implements Function<ProductItem, Image> {
/** Pattern to capture the number of bits e.g. "a (32 bit) os" */
private static final Pattern OS_BITS_PATTERN = Pattern.compile(".*\\((\\d+) ?bit\\).*");
private static final String CENTOS = "CentOS";
private static final String DEBIAN = "Debian GNU/Linux";
private static final String FEDORA = "Fedora Release";
private static final String RHEL = "Red Hat Enterprise Linux";
private static final String UBUNTU = "Ubuntu Linux";
private static final String WINDOWS = "Windows Server";
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
@Override
public Image apply(ProductItem from) {
//Somehow this method gets called with the correct product item.
OsFamily family = osFamily().apply(from);
Integer bits = osBits().apply(from);
OperatingSystem os = OperatingSystem.builder()
.description(from.getDescription())
.family(family)
.version(osVersion().apply(from))
.is64Bit(bits.equals(64))
.build();
return new ImageBuilder()
.id("" + from.getId())
.description(from.getDescription())
.operatingSystem(os)
.build();
}
/**
* Parses the item description to determine the OSFamily
* @return the @see OsFamily or OsFamily.UNRECOGNIZED
*/
public static Function<ProductItem,OsFamily> osFamily() {
return new Function<ProductItem,OsFamily>() {
@Override
public OsFamily apply(ProductItem productItem) {
final String description = productItem.getDescription();
if ( description.startsWith(CENTOS)) return OsFamily.CENTOS;
else if( description.startsWith(DEBIAN) ) return OsFamily.DEBIAN;
else if( description.startsWith(FEDORA) ) return OsFamily.FEDORA;
else if( description.startsWith(RHEL) ) return OsFamily.RHEL;
else if( description.startsWith(UBUNTU) ) return OsFamily.UBUNTU;
else if( description.startsWith(WINDOWS) ) return OsFamily.WINDOWS;
return OsFamily.UNRECOGNIZED;
}
};
}
/**
* Parses the item description to determine the os version
* @return the version
* @throws java.util.NoSuchElementException if the version cannot be determined
*/
public static Function<ProductItem,String> osVersion() {
return new Function<ProductItem,String>() {
@Override
public String apply(ProductItem productItem) {
final String description = productItem.getDescription();
OsFamily family = osFamily().apply(productItem);
if (family.equals(OsFamily.CENTOS)) return parseVersion(description, CENTOS);
else if(family.equals(OsFamily.DEBIAN)) return parseVersion(description, DEBIAN);
else if(family.equals(OsFamily.FEDORA)) return parseVersion(description, FEDORA);
else if(family.equals(OsFamily.RHEL)) return parseVersion(description, RHEL);
else if(family.equals(OsFamily.UBUNTU)) return parseVersion(description, UBUNTU);
else if(family.equals(OsFamily.WINDOWS)) return parseVersion(description, WINDOWS);
else throw new NoSuchElementException("No os parseVersion for item:"+productItem);
}
};
}
private static String parseVersion(String description, String os) {
String noOsName = description.replaceFirst(os,"").trim();
return noOsName.split(" ")[0];
}
/**
* Parses the item description to determine the number of OS bits
* Expects the number to be in parenthesis and to contain the word "bit".
* The following return 64: "A (64 bit) OS", "A (64bit) OS"
* @return the number of bits
* @throws java.util.NoSuchElementException if the number of bits cannot be determined
*/
public static Function<ProductItem,Integer> osBits() {
return new Function<ProductItem,Integer>() {
@Override
public Integer apply(ProductItem productItem) {
Matcher m = OS_BITS_PATTERN.matcher(productItem.getDescription());
if (m.matches()) {
return Integer.parseInt(m.group(1));
} else {
throw new NoSuchElementException("Cannot determine os-bits for item:"+productItem);
}
}
};
}
}

View File

@ -0,0 +1,129 @@
package org.jclouds.softlayer.compute.functions;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.softlayer.domain.ProductItem;
import org.testng.annotations.Test;
import java.util.Arrays;
import java.util.List;
import java.util.NoSuchElementException;
import static org.jclouds.softlayer.compute.functions.ProductItemToImage.*;
import static org.testng.AssertJUnit.*;
/**
* Tests {@code ProductItemToImage}
*
* @author Jason King
*/
@Test(groups = "unit")
public class ProductItemToImageTest {
// Operating Systems available SEPT 2011
private static final List<String> operatingSystems = Arrays.asList(
"CentOS 5 - LAMP Install (32 bit)",
"CentOS 5 - LAMP Install (64 bit)",
"CentOS 5 - Minimal Install (32 bit)",
"CentOS 5 - Minimal Install (64 bit)",
"CentOS 6.0 - LAMP Install (32 bit)",
"CentOS 6.0 - LAMP Install (64 bit)",
"CentOS 6.0 - Minimal Install (32 bit)",
"CentOS 6.0 - Minimal Install (64 bit)",
"Debian GNU/Linux 5.0 Lenny/Stable - LAMP Install (32 bit)",
"Debian GNU/Linux 5.0 Lenny/Stable - LAMP Install (64 bit)",
"Debian GNU/Linux 5.0 Lenny/Stable - Minimal Install (32 bit)",
"Debian GNU/Linux 5.0 Lenny/Stable - Minimal Install (64 bit)",
"Fedora Release 13 (32bit) - LAMP Install",
"Fedora Release 13 (32bit) - Minimal Install",
"Fedora Release 13 (64bit) - LAMP Install",
"Fedora Release 13 (64bit) - Minimal Install",
"Fedora Release 15 (32bit) - LAMP Install",
"Fedora Release 15 (32bit) - Minimal Install",
"Fedora Release 15 (64bit) - LAMP Install",
"Fedora Release 15 (64bit) - Minimal Install",
"Red Hat Enterprise Linux 5 - LAMP Install (32 bit)",
"Red Hat Enterprise Linux 5 - LAMP Install (64 bit)",
"Red Hat Enterprise Linux 5 - Minimal Install (64 bit)",
"Red Hat Enterprise Linux 6 - LAMP Install (32 bit)",
"Red Hat Enterprise Linux 6 - LAMP Install (64 bit)",
"Red Hat Enterprise Linux 6 - Minimal Install (32 bit)",
"Red Hat Enterprise Linux 6 - Minimal Install (64 bit)",
"Ubuntu Linux 10.04 LTS Lucid Lynx - LAMP Install (32 bit)",
"Ubuntu Linux 10.04 LTS Lucid Lynx - LAMP Install (64 bit)",
"Ubuntu Linux 10.04 LTS Lucid Lynx - Minimal Install (32 bit)",
"Ubuntu Linux 10.04 LTS Lucid Lynx - Minimal Install (64 bit)",
"Ubuntu Linux 8 LTS Hardy Heron - LAMP Install (32 bit)",
"Ubuntu Linux 8 LTS Hardy Heron - LAMP Install (64 bit)",
"Ubuntu Linux 8 LTS Hardy Heron - Minimal Install (32 bit)",
"Ubuntu Linux 8 LTS Hardy Heron - Minimal Install (64 bit)",
"Windows Server 2003 Datacenter SP2 with R2 (32 bit)",
"Windows Server 2003 Datacenter SP2 with R2 (64 bit)",
"Windows Server 2003 Enterprise SP2 with R2 (64 bit)",
"Windows Server 2003 Standard SP2 with R2 (64 bit)",
"Windows Server 2008 Datacenter Edition SP2 (32bit)",
"Windows Server 2008 Datacenter Edition SP2 (64bit)",
"Windows Server 2008 Enterprise Edition SP2 (32bit)",
"Windows Server 2008 Enterprise Edition SP2 (64bit)",
"Windows Server 2008 R2 Datacenter Edition (64bit)",
"Windows Server 2008 R2 Enterprise Edition (64bit)",
"Windows Server 2008 R2 Standard Edition (64bit)",
"Windows Server 2008 Standard Edition SP2 (32bit)",
"Windows Server 2008 Standard Edition SP2 (64bit)");
@Test
public void testConversion() {
for( String description : operatingSystems )
{
ProductItem item = ProductItem.builder().description(description).build();
Image i = new ProductItemToImage().apply(item);
OperatingSystem os = i.getOperatingSystem();
assertNotNull(os);
assertNotNull(os.getFamily());
assertFalse(os.getFamily().equals(OsFamily.UNRECOGNIZED));
assertNotNull(os.getVersion());
}
}
@Test
public void testOsFamily() {
ProductItem item = ProductItem.builder().description("Ubuntu Linux os").build();
assertEquals(OsFamily.UBUNTU,osFamily().apply(item));
}
@Test
public void testOsFamilyUnrecognized() {
ProductItem item = ProductItem.builder().description("not a known operating system").build();
assertEquals(OsFamily.UNRECOGNIZED,osFamily().apply(item));
}
@Test
public void testBitsWithSpace() {
ProductItem item = ProductItem.builder().description("a (32 bit) os").build();
assertEquals(osBits().apply(item),new Integer(32));
}
@Test
public void testBitsNoSpace() {
ProductItem item = ProductItem.builder().description("a (64bit) os").build();
assertEquals(osBits().apply(item),new Integer(64));
}
@Test(expectedExceptions = NoSuchElementException.class)
public void testBitsMissing() {
ProductItem item = ProductItem.builder().description("an os").build();
osBits().apply(item);
}
@Test
public void testOsVersion() {
ProductItem item = ProductItem.builder().description("Windows Server 2099 (256 bit)").build();
assertEquals("2099",osVersion().apply(item));
}
@Test(expectedExceptions = NoSuchElementException.class)
public void testOsVersionMissing() {
ProductItem item = ProductItem.builder().description("asd Server ").build();
osVersion().apply(item);
}
}