Issue 872: softlayer ProductItemToImage now categorizes unknown operating systems accordingly, instead of throwing exceptions

This commit is contained in:
Adam Lowe 2012-05-14 17:22:56 +01:00
parent 1b2eb74604
commit c259bce623
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 static com.google.common.base.Preconditions.checkNotNull;
import java.util.NoSuchElementException;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -38,6 +37,7 @@ import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.ProductItemPrice; import org.jclouds.softlayer.domain.ProductItemPrice;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Objects;
/** /**
* @author Jason King * @author Jason King
@ -45,14 +45,16 @@ import com.google.common.base.Function;
@Singleton @Singleton
public class ProductItemToImage implements Function<ProductItem, Image> { 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 Pattern OS_BITS_PATTERN = Pattern.compile(".*\\((\\d+) ?bit\\).*");
private static final String CENTOS = "CentOS"; private static final String CENTOS = "CentOS";
private static final String DEBIAN = "Debian GNU/Linux"; private static final String DEBIAN = "Debian GNU/Linux";
private static final String FEDORA = "Fedora Release"; private static final String FEDORA = "Fedora Release";
private static final String RHEL = "Red Hat Enterprise Linux"; private static final String RHEL = "Red Hat Enterprise Linux";
private static final String UBUNTU = "Ubuntu Linux"; private static final String UBUNTU = "Ubuntu Linux";
private static final String WINDOWS = "Windows Server"; private static final String WINDOWS = "Windows Server";
private static final String CLOUD_LINUX = "CloudLinux"; private static final String CLOUD_LINUX = "CloudLinux";
@ -62,111 +64,123 @@ public class ProductItemToImage implements Function<ProductItem, Image> {
@Override @Override
public Image apply(ProductItem productItem) { public Image apply(ProductItem productItem) {
checkNotNull(productItem,"productItem"); checkNotNull(productItem, "productItem");
String description = checkNotNull(productItem.getDescription(), "productItem.description");
OsFamily family = osFamily().apply(productItem); OsFamily osFamily = osFamily().apply(description);
Integer bits = osBits().apply(productItem); 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() OperatingSystem os = OperatingSystem.builder()
.description(productItem.getDescription()) .description(description)
.family(family) .family(osFamily)
.version(osVersion().apply(productItem)) .version(osVersion)
.is64Bit(bits.equals(64)) .is64Bit(Objects.equal(bits, 64))
.build(); .build();
return new ImageBuilder() return new ImageBuilder()
.ids(imageId().apply(productItem)) .ids(imageId().apply(productItem))
.description(productItem.getDescription()) .description(description)
.operatingSystem(os) .operatingSystem(os)
.build(); .build();
} }
/** /**
* Parses the item description to determine the OSFamily * Parses the item description to determine the OSFamily
*
* @return the @see OsFamily or OsFamily.UNRECOGNIZED * @return the @see OsFamily or OsFamily.UNRECOGNIZED
*/ */
public static Function<ProductItem,OsFamily> osFamily() { public static Function<String, OsFamily> osFamily() {
return new Function<ProductItem,OsFamily>() { return new Function<String, OsFamily>() {
@Override @Override
public OsFamily apply(ProductItem productItem) { public OsFamily apply(final String description) {
checkNotNull(productItem,"productItem"); if (description != null) {
if (description.startsWith(CENTOS)) return OsFamily.CENTOS;
final String description = productItem.getDescription(); else if (description.startsWith(DEBIAN)) return OsFamily.DEBIAN;
if(description.startsWith(CENTOS)) return OsFamily.CENTOS; else if (description.startsWith(FEDORA)) return OsFamily.FEDORA;
else if(description.startsWith(DEBIAN)) return OsFamily.DEBIAN; else if (description.startsWith(RHEL)) return OsFamily.RHEL;
else if(description.startsWith(FEDORA)) return OsFamily.FEDORA; else if (description.startsWith(UBUNTU)) return OsFamily.UBUNTU;
else if(description.startsWith(RHEL)) return OsFamily.RHEL; else if (description.startsWith(WINDOWS)) return OsFamily.WINDOWS;
else if(description.startsWith(UBUNTU)) return OsFamily.UBUNTU; else if (description.startsWith(CLOUD_LINUX)) return OsFamily.CLOUD_LINUX;
else if(description.startsWith(WINDOWS)) return OsFamily.WINDOWS;
else if(description.startsWith(CLOUD_LINUX)) return OsFamily.CLOUD_LINUX;
return OsFamily.UNRECOGNIZED;
} }
};
} return OsFamily.UNRECOGNIZED;
}
};
}
/** /**
* Parses the item description to determine the os version * 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() { public static Function<String, String> osVersion() {
return new Function<ProductItem,String>() { return new Function<String, String>() {
@Override @Override
public String apply(ProductItem productItem) { public String apply(final String description) {
checkNotNull(productItem,"productItem"); OsFamily family = osFamily().apply(description);
final String description = productItem.getDescription(); if (Objects.equal(family, OsFamily.CENTOS)) return parseVersion(description, CENTOS);
OsFamily family = osFamily().apply(productItem); else if (Objects.equal(family, OsFamily.DEBIAN)) return parseVersion(description, DEBIAN);
if (family.equals(OsFamily.CENTOS)) return parseVersion(description, CENTOS); else if (Objects.equal(family, OsFamily.FEDORA)) return parseVersion(description, FEDORA);
else if(family.equals(OsFamily.DEBIAN)) return parseVersion(description, DEBIAN); else if (Objects.equal(family, OsFamily.RHEL)) return parseVersion(description, RHEL);
else if(family.equals(OsFamily.FEDORA)) return parseVersion(description, FEDORA); else if (Objects.equal(family, OsFamily.UBUNTU)) return parseVersion(description, UBUNTU);
else if(family.equals(OsFamily.RHEL)) return parseVersion(description, RHEL); else if (Objects.equal(family, OsFamily.WINDOWS)) return parseVersion(description, WINDOWS);
else if(family.equals(OsFamily.UBUNTU)) return parseVersion(description, UBUNTU); else if (Objects.equal(family, OsFamily.CLOUD_LINUX)) return parseVersion(description, CLOUD_LINUX);
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);
}
};
}
private static String parseVersion(String description, String os) { return null;
String noOsName = description.replaceFirst(os,"").trim(); }
return noOsName.split(" ")[0]; };
} }
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 * Parses the item description to determine the number of OS bits
* Expects the number to be in parenthesis and to contain the word "bit". * Expects the number to be in parenthesis and to contain the word "bit".
* The following return 64: "A (64 bit) OS", "A (64bit) OS" * 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() { public static Function<String, Integer> osBits() {
return new Function<ProductItem,Integer>() { return new Function<String, Integer>() {
@Override @Override
public Integer apply(ProductItem productItem) { public Integer apply(String description) {
checkNotNull(productItem,"productItem"); if (description != null) {
Matcher m = OS_BITS_PATTERN.matcher(description);
Matcher m = OS_BITS_PATTERN.matcher(productItem.getDescription());
if (m.matches()) { if (m.matches()) {
return Integer.parseInt(m.group(1)); return Integer.parseInt(m.group(1));
} else {
throw new NoSuchElementException("Cannot determine os-bits for item:"+productItem);
} }
} }
};
}
/** return null;
* Generates an id for an Image. }
* @return the generated id };
*/ }
public static Function<ProductItem,String> imageId() {
return new Function<ProductItem,String>() { /**
* Generates an id for an Image.
*
* @return the generated id
*/
public static Function<ProductItem, String> imageId() {
return new Function<ProductItem, String>() {
@Override @Override
public String apply(ProductItem productItem) { public String apply(ProductItem productItem) {
checkNotNull(productItem,"productItem"); checkNotNull(productItem, "productItem");
ProductItemPrice price = ProductItems.price().apply(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.assertEquals;
import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertNotNull; import static org.testng.AssertJUnit.assertNotNull;
import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertTrue; import static org.testng.AssertJUnit.assertTrue;
import java.util.Arrays; import java.util.Arrays;
@ -131,6 +132,62 @@ public class ProductItemToImageTest {
assertTrue(os.is64Bit()); 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 @Test
public void testId() { public void testId() {
ProductItemPrice price = ProductItemPrice.builder().id(1234).build(); ProductItemPrice price = ProductItemPrice.builder().id(1234).build();
@ -151,46 +208,59 @@ public class ProductItemToImageTest {
ProductItem item = ProductItem.builder().build(); ProductItem item = ProductItem.builder().build();
imageId().apply(item); imageId().apply(item);
} }
@Test(expectedExceptions = NullPointerException.class)
public void testIdNull() {
imageId().apply(null);
}
@Test @Test
public void testOsFamily() { public void testOsFamily() {
ProductItem item = ProductItem.builder().description("Ubuntu Linux os").build(); assertEquals(OsFamily.UBUNTU,osFamily().apply("Ubuntu Linux os"));
assertEquals(OsFamily.UBUNTU,osFamily().apply(item));
} }
@Test @Test
public void testOsFamilyUnrecognized() { public void testOsFamilyUnrecognized() {
ProductItem item = ProductItem.builder().description("not a known operating system").build(); assertEquals(OsFamily.UNRECOGNIZED,osFamily().apply("not a known operating system"));
assertEquals(OsFamily.UNRECOGNIZED,osFamily().apply(item)); }
@Test
public void testOsFamilyNull() {
assertEquals(OsFamily.UNRECOGNIZED,osFamily().apply(null));
} }
@Test @Test
public void testBitsWithSpace() { public void testOsBitsWithSpace() {
ProductItem item = ProductItem.builder().description("a (32 bit) os").build(); assertEquals(osBits().apply("a (32 bit) os"),new Integer(32));
assertEquals(osBits().apply(item),new Integer(32));
} }
@Test @Test
public void testBitsNoSpace() { public void testOsBitsNoSpace() {
ProductItem item = ProductItem.builder().description("a (64bit) os").build(); assertEquals(osBits().apply("a (64bit) os"),new Integer(64));
assertEquals(osBits().apply(item),new Integer(64));
} }
@Test(expectedExceptions = NoSuchElementException.class) @Test
public void testBitsMissing() { public void testOsBitsMissing() {
ProductItem item = ProductItem.builder().description("an os").build(); assertNull(osBits().apply("an os"));
osBits().apply(item); }
@Test
public void testOsBitsNull() {
assertNull(osBits().apply(null));
} }
@Test @Test
public void testOsVersion() { public void testOsVersion() {
ProductItem item = ProductItem.builder().description("Windows Server 2099 (256 bit)").build(); assertEquals("2099",osVersion().apply("Windows Server 2099 (256 bit)"));
assertEquals("2099",osVersion().apply(item));
} }
@Test(expectedExceptions = NoSuchElementException.class) @Test
public void testOsVersionMissing() { public void testOsVersionMissing() {
ProductItem item = ProductItem.builder().description("asd Server").build(); assertNull(osVersion().apply("asd Server"));
osVersion().apply(item); }
@Test
public void testOsVersionNull() {
assertNull(osVersion().apply(null));
} }
} }