Merge pull request #637 from aplowe/master

Issue 872: softlayer ProductItemToImage handling for unrecognised operating systems
This commit is contained in:
Adrian Cole 2012-05-15 10:40:15 -07:00
commit 0b2e14735f
2 changed files with 181 additions and 97 deletions

View File

@ -20,7 +20,6 @@ package org.jclouds.softlayer.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.NoSuchElementException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -38,6 +37,7 @@ import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.ProductItemPrice;
import com.google.common.base.Function;
import com.google.common.base.Objects;
/**
* @author Jason King
@ -45,14 +45,16 @@ import com.google.common.base.Function;
@Singleton
public class ProductItemToImage implements Function<ProductItem, Image> {
/** Pattern to capture the number of bits e.g. "a (32 bit) os" */
/**
* 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 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";
private static final String CLOUD_LINUX = "CloudLinux";
@ -62,111 +64,123 @@ public class ProductItemToImage implements Function<ProductItem, Image> {
@Override
public Image apply(ProductItem productItem) {
checkNotNull(productItem,"productItem");
checkNotNull(productItem, "productItem");
String description = checkNotNull(productItem.getDescription(), "productItem.description");
OsFamily family = osFamily().apply(productItem);
Integer bits = osBits().apply(productItem);
OsFamily osFamily = osFamily().apply(description);
if (osFamily == OsFamily.UNRECOGNIZED) {
logger.debug("Cannot determine os family for item: %s", productItem);
}
Integer bits = osBits().apply(description);
if (bits == null) {
logger.debug("Cannot determine os bits for item: %s", productItem);
}
String osVersion = osVersion().apply(description);
if (osVersion == null) {
logger.debug("Cannot determine os version for item: %s", productItem);
}
OperatingSystem os = OperatingSystem.builder()
.description(productItem.getDescription())
.family(family)
.version(osVersion().apply(productItem))
.is64Bit(bits.equals(64))
.build();
.description(description)
.family(osFamily)
.version(osVersion)
.is64Bit(Objects.equal(bits, 64))
.build();
return new ImageBuilder()
.ids(imageId().apply(productItem))
.description(productItem.getDescription())
.description(description)
.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) {
checkNotNull(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;
else if(description.startsWith(CLOUD_LINUX)) return OsFamily.CLOUD_LINUX;
return OsFamily.UNRECOGNIZED;
public static Function<String, OsFamily> osFamily() {
return new Function<String, OsFamily>() {
@Override
public OsFamily apply(final String description) {
if (description != null) {
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;
else if (description.startsWith(CLOUD_LINUX)) return OsFamily.CLOUD_LINUX;
}
};
}
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
*
* @return the version or null if the version cannot be determined
*/
public static Function<ProductItem,String> osVersion() {
return new Function<ProductItem,String>() {
@Override
public String apply(ProductItem productItem) {
checkNotNull(productItem,"productItem");
public static Function<String, String> osVersion() {
return new Function<String, String>() {
@Override
public String apply(final String description) {
OsFamily family = osFamily().apply(description);
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 if(family.equals(OsFamily.CLOUD_LINUX)) return parseVersion(description, CLOUD_LINUX);
else throw new NoSuchElementException("No os version for item:"+productItem);
}
};
}
if (Objects.equal(family, OsFamily.CENTOS)) return parseVersion(description, CENTOS);
else if (Objects.equal(family, OsFamily.DEBIAN)) return parseVersion(description, DEBIAN);
else if (Objects.equal(family, OsFamily.FEDORA)) return parseVersion(description, FEDORA);
else if (Objects.equal(family, OsFamily.RHEL)) return parseVersion(description, RHEL);
else if (Objects.equal(family, OsFamily.UBUNTU)) return parseVersion(description, UBUNTU);
else if (Objects.equal(family, OsFamily.WINDOWS)) return parseVersion(description, WINDOWS);
else if (Objects.equal(family, OsFamily.CLOUD_LINUX)) return parseVersion(description, CLOUD_LINUX);
private static String parseVersion(String description, String os) {
String noOsName = description.replaceFirst(os,"").trim();
return noOsName.split(" ")[0];
}
return null;
}
};
}
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
*
* @return the number of bits or null 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) {
checkNotNull(productItem,"productItem");
Matcher m = OS_BITS_PATTERN.matcher(productItem.getDescription());
public static Function<String, Integer> osBits() {
return new Function<String, Integer>() {
@Override
public Integer apply(String description) {
if (description != null) {
Matcher m = OS_BITS_PATTERN.matcher(description);
if (m.matches()) {
return Integer.parseInt(m.group(1));
} else {
throw new NoSuchElementException("Cannot determine os-bits for item:"+productItem);
}
}
};
}
/**
* Generates an id for an Image.
* @return the generated id
*/
public static Function<ProductItem,String> imageId() {
return new Function<ProductItem,String>() {
return null;
}
};
}
/**
* Generates an id for an Image.
*
* @return the generated id
*/
public static Function<ProductItem, String> imageId() {
return new Function<ProductItem, String>() {
@Override
public String apply(ProductItem productItem) {
checkNotNull(productItem,"productItem");
checkNotNull(productItem, "productItem");
ProductItemPrice price = ProductItems.price().apply(productItem);
return ""+price.getId();
return "" + price.getId();
}
};
}

View File

@ -25,6 +25,7 @@ import static org.jclouds.softlayer.compute.functions.ProductItemToImage.osVersi
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertNotNull;
import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertTrue;
import java.util.Arrays;
@ -131,6 +132,62 @@ public class ProductItemToImageTest {
assertTrue(os.is64Bit());
}
@Test
public void testUbuntuNoBitCount() {
ProductItem item = ProductItem.builder()
.description("Ubuntu Linux 10.04 LTS Lucid Lynx - Minimal Install")
.price(ProductItemPrice.builder().id(1234).build())
.build();
Image i = new ProductItemToImage().apply(item);
OperatingSystem os = i.getOperatingSystem();
assertNotNull(os);
assertEquals(OsFamily.UBUNTU, os.getFamily());
assertEquals("10.04",os.getVersion());
assertFalse(os.is64Bit());
}
@Test
public void testCompletelyUnknown() {
ProductItem item = ProductItem.builder()
.description("This fails to match anything!!!")
.price(ProductItemPrice.builder().id(1234).build())
.build();
Image i = new ProductItemToImage().apply(item);
OperatingSystem os = i.getOperatingSystem();
assertNotNull(os);
assertEquals(OsFamily.UNRECOGNIZED, os.getFamily());
assertNull(os.getVersion());
assertFalse(os.is64Bit());
}
@Test
public void test64BitUnknown() {
ProductItem item = ProductItem.builder()
.description("This only has the bit-count (64 bit)")
.price(ProductItemPrice.builder().id(1234).build())
.build();
Image i = new ProductItemToImage().apply(item);
OperatingSystem os = i.getOperatingSystem();
assertNotNull(os);
assertEquals(OsFamily.UNRECOGNIZED, os.getFamily());
assertNull(os.getVersion());
assertTrue(os.is64Bit());
}
@Test(expectedExceptions = NullPointerException.class)
public void testNull() {
new ProductItemToImage().apply(null);
}
@Test(expectedExceptions = NullPointerException.class)
public void testNoDescription() {
ProductItem item = ProductItem.builder()
.price(ProductItemPrice.builder().id(1234).build())
.build();
new ProductItemToImage().apply(item);
}
@Test
public void testId() {
ProductItemPrice price = ProductItemPrice.builder().id(1234).build();
@ -151,46 +208,59 @@ public class ProductItemToImageTest {
ProductItem item = ProductItem.builder().build();
imageId().apply(item);
}
@Test(expectedExceptions = NullPointerException.class)
public void testIdNull() {
imageId().apply(null);
}
@Test
public void testOsFamily() {
ProductItem item = ProductItem.builder().description("Ubuntu Linux os").build();
assertEquals(OsFamily.UBUNTU,osFamily().apply(item));
assertEquals(OsFamily.UBUNTU,osFamily().apply("Ubuntu Linux os"));
}
@Test
public void testOsFamilyUnrecognized() {
ProductItem item = ProductItem.builder().description("not a known operating system").build();
assertEquals(OsFamily.UNRECOGNIZED,osFamily().apply(item));
assertEquals(OsFamily.UNRECOGNIZED,osFamily().apply("not a known operating system"));
}
@Test
public void testOsFamilyNull() {
assertEquals(OsFamily.UNRECOGNIZED,osFamily().apply(null));
}
@Test
public void testBitsWithSpace() {
ProductItem item = ProductItem.builder().description("a (32 bit) os").build();
assertEquals(osBits().apply(item),new Integer(32));
public void testOsBitsWithSpace() {
assertEquals(osBits().apply("a (32 bit) os"),new Integer(32));
}
@Test
public void testBitsNoSpace() {
ProductItem item = ProductItem.builder().description("a (64bit) os").build();
assertEquals(osBits().apply(item),new Integer(64));
public void testOsBitsNoSpace() {
assertEquals(osBits().apply("a (64bit) os"),new Integer(64));
}
@Test(expectedExceptions = NoSuchElementException.class)
public void testBitsMissing() {
ProductItem item = ProductItem.builder().description("an os").build();
osBits().apply(item);
@Test
public void testOsBitsMissing() {
assertNull(osBits().apply("an os"));
}
@Test
public void testOsBitsNull() {
assertNull(osBits().apply(null));
}
@Test
public void testOsVersion() {
ProductItem item = ProductItem.builder().description("Windows Server 2099 (256 bit)").build();
assertEquals("2099",osVersion().apply(item));
assertEquals("2099",osVersion().apply("Windows Server 2099 (256 bit)"));
}
@Test(expectedExceptions = NoSuchElementException.class)
@Test
public void testOsVersionMissing() {
ProductItem item = ProductItem.builder().description("asd Server").build();
osVersion().apply(item);
assertNull(osVersion().apply("asd Server"));
}
@Test
public void testOsVersionNull() {
assertNull(osVersion().apply(null));
}
}