adjusted defaults to allow smallest softlayer size; parameterized configuration; fixed state where guest without billing item was permitted

This commit is contained in:
Adrian Cole 2011-10-03 22:36:39 -07:00
parent 007ebc693e
commit d5e130ab3c
16 changed files with 861 additions and 511 deletions

View File

@ -21,11 +21,20 @@ package org.jclouds.softlayer;
import static org.jclouds.Constants.PROPERTY_API_VERSION; import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_ENDPOINT; import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.Constants.PROPERTY_ISO3166_CODES; import static org.jclouds.Constants.PROPERTY_ISO3166_CODES;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_CPU_REGEX;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_DISK0_TYPE;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PORT_SPEED;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PRICES;
import java.util.Properties; import java.util.Properties;
import org.jclouds.PropertiesBuilder; import org.jclouds.PropertiesBuilder;
import org.jclouds.softlayer.reference.SoftLayerConstants;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
/** /**
* Builds properties used in SoftLayer Clients * Builds properties used in SoftLayer Clients
@ -38,9 +47,28 @@ public class SoftLayerPropertiesBuilder extends PropertiesBuilder {
Properties properties = super.defaultProperties(); Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_ENDPOINT, "https://api.softlayer.com/rest"); properties.setProperty(PROPERTY_ENDPOINT, "https://api.softlayer.com/rest");
properties.setProperty(PROPERTY_API_VERSION, "3"); properties.setProperty(PROPERTY_API_VERSION, "3");
properties.setProperty(SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME, "Cloud Server"); properties.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY, "" + 60 * 60 * 1000);
properties.setProperty(SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY, ""+60*60*1000); properties.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME, "Cloud Server");
// ex: for private (ex. don't share hardware) use "Private [0-9]+ x ([.0-9]+) GHz Core[s]?"
// ex: for private and public use ".*[0-9]+ x ([.0-9]+) GHz Core[s]?"
properties.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_CPU_REGEX, "[0-9]+ x ([0-9.]+) GHz Core[s]?");
// SAN or LOCAL
properties.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_DISK0_TYPE, "LOCAL");
// 10, 100, 1000
properties.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_PORT_SPEED, "10");
properties.setProperty(PROPERTY_ISO3166_CODES, "SG,US-CA,US-TX,US-VA,US-WA,US-TX"); properties.setProperty(PROPERTY_ISO3166_CODES, "SG,US-CA,US-TX,US-VA,US-WA,US-TX");
Builder<String> prices = ImmutableSet.<String> builder();
prices.add("21"); // 1 IP Address
prices.add("55"); // Host Ping: categoryCode: monitoring, notification
prices.add("57"); // Email and Ticket: categoryCode: notification
prices.add("58"); // Automated Notification: categoryCode: response
prices.add("1800"); // 0 GB Bandwidth: categoryCode: bandwidth
prices.add("905"); // Reboot / Remote Console: categoryCode: remote_management
prices.add("418"); // Nessus Vulnerability Assessment & Reporting: categoryCode:
// vulnerability_scanner
prices.add("420"); // Unlimited SSL VPN Users & 1 PPTP VPN User per account: categoryCode:
// vpn_management
properties.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_PRICES, Joiner.on(',').join(prices.build()));
return properties; return properties;
} }

View File

@ -18,8 +18,17 @@
*/ */
package org.jclouds.softlayer.compute.config; package org.jclouds.softlayer.compute.config;
import java.util.Set; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.find;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PRICES;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeServiceAdapter; import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule; import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
@ -28,6 +37,7 @@ import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.location.suppliers.OnlyLocationOrFirstZone; import org.jclouds.location.suppliers.OnlyLocationOrFirstZone;
import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
import org.jclouds.softlayer.SoftLayerAsyncClient; import org.jclouds.softlayer.SoftLayerAsyncClient;
import org.jclouds.softlayer.SoftLayerClient; import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.compute.functions.DatacenterToLocation; import org.jclouds.softlayer.compute.functions.DatacenterToLocation;
@ -38,19 +48,27 @@ import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions;
import org.jclouds.softlayer.compute.strategy.SoftLayerComputeServiceAdapter; import org.jclouds.softlayer.compute.strategy.SoftLayerComputeServiceAdapter;
import org.jclouds.softlayer.domain.Datacenter; import org.jclouds.softlayer.domain.Datacenter;
import org.jclouds.softlayer.domain.ProductItem; import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.ProductItemPrice;
import org.jclouds.softlayer.domain.ProductPackage;
import org.jclouds.softlayer.domain.VirtualGuest; import org.jclouds.softlayer.domain.VirtualGuest;
import org.jclouds.softlayer.features.AccountClient;
import org.jclouds.softlayer.features.ProductPackageClient;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class SoftLayerComputeServiceContextModule extends public class SoftLayerComputeServiceContextModule
ComputeServiceAdapterContextModule<SoftLayerClient, SoftLayerAsyncClient, VirtualGuest, Set<ProductItem>, ProductItem, Datacenter> { extends
ComputeServiceAdapterContextModule<SoftLayerClient, SoftLayerAsyncClient, VirtualGuest, Iterable<ProductItem>, ProductItem, Datacenter> {
public SoftLayerComputeServiceContextModule() { public SoftLayerComputeServiceContextModule() {
super(SoftLayerClient.class, SoftLayerAsyncClient.class); super(SoftLayerClient.class, SoftLayerAsyncClient.class);
@ -59,26 +77,59 @@ public class SoftLayerComputeServiceContextModule extends
@Override @Override
protected void configure() { protected void configure() {
super.configure(); super.configure();
bind(new TypeLiteral<ComputeServiceAdapter<VirtualGuest, Set<ProductItem>, ProductItem, Datacenter>>() {}) bind(new TypeLiteral<ComputeServiceAdapter<VirtualGuest, Iterable<ProductItem>, ProductItem, Datacenter>>() {
.to(SoftLayerComputeServiceAdapter.class); }).to(SoftLayerComputeServiceAdapter.class);
bind(new TypeLiteral<Function<VirtualGuest, NodeMetadata>>() {}) bind(new TypeLiteral<Function<VirtualGuest, NodeMetadata>>() {
.to(VirtualGuestToNodeMetadata.class); }).to(VirtualGuestToNodeMetadata.class);
bind(new TypeLiteral<Function<ProductItem, org.jclouds.compute.domain.Image>>() {}) bind(new TypeLiteral<Function<ProductItem, org.jclouds.compute.domain.Image>>() {
.to(ProductItemToImage.class); }).to(ProductItemToImage.class);
bind(new TypeLiteral<Function<Set<ProductItem>, org.jclouds.compute.domain.Hardware>>() {}) bind(new TypeLiteral<Function<Iterable<ProductItem>, org.jclouds.compute.domain.Hardware>>() {
.to(ProductItemsToHardware.class); }).to(ProductItemsToHardware.class);
bind(new TypeLiteral<Function<Datacenter, Location>>() {}) bind(new TypeLiteral<Function<Datacenter, Location>>() {
.to(DatacenterToLocation.class); }).to(DatacenterToLocation.class);
bind(new TypeLiteral<Supplier<Location>>() {}) bind(new TypeLiteral<Supplier<Location>>() {
.to(OnlyLocationOrFirstZone.class); }).to(OnlyLocationOrFirstZone.class);
bind(TemplateOptions.class).to(SoftLayerTemplateOptions.class); bind(TemplateOptions.class).to(SoftLayerTemplateOptions.class);
} }
protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) { protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) {
return template.osFamily(OsFamily.UBUNTU) return template.osFamily(OsFamily.UBUNTU).osVersionMatches("1[10].[10][04]").os64Bit(true).osDescriptionMatches(
.osVersionMatches("1[10].[10][04]") ".*Minimal Install.*");
.os64Bit(true)
.osDescriptionMatches(".*Minimal Install.*")
.minCores(2);
} }
}
/**
* Many requests need the same productPackage, which is in this case the package for virtual
* guests. We may at some point need to make an annotation qualifying it as such. ex. @VirtualGuest
*/
@Provides
@Singleton
@Memoized
public Supplier<ProductPackage> getProductPackage(@Named(PROPERTY_SESSION_INTERVAL) long seconds,
final SoftLayerClient client,
@Named(PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME) final String virtualGuestPackageName) {
return new MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<ProductPackage>(authException, seconds,
new Supplier<ProductPackage>() {
@Override
public ProductPackage get() {
AccountClient accountClient = client.getAccountClient();
ProductPackageClient productPackageClient = client.getProductPackageClient();
ProductPackage p = find(accountClient.getActivePackages(), named(virtualGuestPackageName));
return productPackageClient.getProductPackage(p.getId());
}
});
}
// TODO: check the prices really do exist
@Provides
@Singleton
public Iterable<ProductItemPrice> prices(@Named(PROPERTY_SOFTLAYER_VIRTUALGUEST_PRICES) String prices) {
return Iterables.transform(Splitter.on(',').split(checkNotNull(prices, "prices")),
new Function<String, ProductItemPrice>() {
@Override
public ProductItemPrice apply(String arg0) {
return ProductItemPrice.builder().id(Integer.parseInt(arg0)).build();
}
});
}
}

View File

@ -29,63 +29,63 @@ import java.util.Set;
public class ProductItems { public class ProductItems {
/** /**
* Creates a function to get the capacity from a product item. * Creates a function to get the capacity from a product item.
*/ */
public static Function<ProductItem,Float> capacity() { public static Function<ProductItem, Float> capacity() {
return new Function<ProductItem,Float>() { return new Function<ProductItem, Float>() {
@Override @Override
public Float apply(ProductItem productItem) { public Float apply(ProductItem productItem) {
return productItem.getCapacity(); return productItem.getCapacity();
} }
}; };
} }
/**
* Creates a function to get the description from a product item.
*/
public static Function<ProductItem,String> description() {
return new Function<ProductItem,String>() {
@Override
public String apply(ProductItem productItem) {
return productItem.getDescription();
}
};
}
/**
* Creates a function to get the ProductItemPrice for the ProductItem.
* Currently returns the first price.
* This will need to be changed if more than one price is returned.
*/
public static Function<ProductItem,ProductItemPrice> price() {
return new Function<ProductItem,ProductItemPrice>() {
@Override
public ProductItemPrice apply(ProductItem productItem) {
if(productItem.getPrices().size()<1) throw new NoSuchElementException("ProductItem has no prices:"+productItem);
return Iterables.get(productItem.getPrices(), 0);
}
};
}
/** /**
* Creates a function to get the ProductItem for the ProductItemPrice. * Creates a function to get the description from a product item.
* Copies the category information from the price to the item if necessary */
* The ProductItemPrices must have ProductItems. public static Function<ProductItem, String> description() {
*/ return new Function<ProductItem, String>() {
public static Function<ProductItemPrice,ProductItem> item() { @Override
return new Function<ProductItemPrice,ProductItem>() { public String apply(ProductItem productItem) {
@Override return productItem.getDescription();
public ProductItem apply(ProductItemPrice productItemPrice) { }
Set<ProductItemCategory> categories = productItemPrice.getCategories(); };
ProductItem item = productItemPrice.getItem(); }
ProductItem.Builder builder = ProductItem.Builder.fromProductItem(productItemPrice.getItem());
if( item.getCategories().size()==0 && categories.size() != 0) {
builder.categories(categories);
}
return builder.build(); /**
* Creates a function to get the ProductItemPrice for the ProductItem. Currently returns the
* first price. This will need to be changed if more than one price is returned.
*/
public static Function<ProductItem, ProductItemPrice> price() {
return new Function<ProductItem, ProductItemPrice>() {
@Override
public ProductItemPrice apply(ProductItem productItem) {
if (productItem.getPrices().size() < 1)
throw new NoSuchElementException("ProductItem has no prices:" + productItem);
return Iterables.get(productItem.getPrices(), 0);
}
};
}
/**
* Creates a function to get the ProductItem for the ProductItemPrice. Copies the category
* information from the price to the item if necessary The ProductItemPrices must have
* ProductItems.
*/
public static Function<ProductItemPrice, ProductItem> item() {
return new Function<ProductItemPrice, ProductItem>() {
@Override
public ProductItem apply(ProductItemPrice productItemPrice) {
Set<ProductItemCategory> categories = productItemPrice.getCategories();
ProductItem item = productItemPrice.getItem();
ProductItem.Builder builder = ProductItem.Builder.fromProductItem(productItemPrice.getItem());
if (item.getCategories().size() == 0 && categories.size() != 0) {
builder.categories(categories);
} }
};
} return builder.build();
}
};
}
} }

View File

@ -18,73 +18,101 @@
*/ */
package org.jclouds.softlayer.compute.functions; package org.jclouds.softlayer.compute.functions;
import com.google.common.base.Function; import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.ImmutableList; import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.get;
import static com.google.common.collect.Iterables.getOnlyElement;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.categoryCode;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.categoryCodeMatches;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.matches;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_CPU_REGEX;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.HardwareBuilder; import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Processor; import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume; import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.internal.VolumeImpl; import org.jclouds.compute.domain.internal.VolumeImpl;
import org.jclouds.softlayer.compute.strategy.SoftLayerComputeServiceAdapter;
import org.jclouds.softlayer.domain.ProductItem; import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.ProductItemPrice; import org.jclouds.softlayer.domain.ProductItemPrice;
import javax.inject.Singleton; import com.google.common.base.Function;
import java.util.List; import com.google.common.collect.ImmutableList;
import java.util.Set; import com.google.common.collect.Iterables;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.getOnlyElement;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.*;
/** /**
* Converts a set of ProductItems to Hardware. * Converts a set of ProductItems to Hardware. All cores have a speed of 2.0Ghz The Hardware Id will
* All cores have a speed of 2.0Ghz * be a comma separated list containing the price ids: cpus,ram,volume
* The Hardware Id will be a comma separated list containing the price ids: *
* cpus,ram,volume
*
* @author Jason King * @author Jason King
*/ */
@Singleton @Singleton
public class ProductItemsToHardware implements Function<Set<ProductItem>, Hardware> { public class ProductItemsToHardware implements Function<Iterable<ProductItem>, Hardware> {
static final double CORE_SPEED = 2.0; private final Pattern cpuRegex;
private final Pattern categoryCodeMatches;
@Inject
public ProductItemsToHardware(@Named(PROPERTY_SOFTLAYER_VIRTUALGUEST_CPU_REGEX) String cpuRegex) {
this(Pattern.compile(checkNotNull(cpuRegex, "cpuRegex")), Pattern.compile("guest_disk[0-9]"));
}
public ProductItemsToHardware(Pattern cpuRegex, Pattern categoryCodeMatches) {
this.cpuRegex = checkNotNull(cpuRegex, "cpuRegex");
this.categoryCodeMatches = checkNotNull(categoryCodeMatches, "categoryCodeMatches");
}
@Override @Override
public Hardware apply(Set<ProductItem> items) { public Hardware apply(Iterable<ProductItem> items) {
ProductItem coresItem = getOnlyElement(filter(items, units("PRIVATE_CORE"))); ProductItem coresItem = getOnlyElement(filter(items, matches(cpuRegex)));
ProductItem ramItem = getOnlyElement(filter(items, categoryCode("ram"))); ProductItem ramItem = getOnlyElement(filter(items, categoryCode("ram")));
ProductItem volumeItem = getOnlyElement(filter(items, matches(SoftLayerComputeServiceAdapter.SAN_DESCRIPTION_REGEX))); ProductItem volumeItem = get(filter(items, categoryCode("guest_disk0")), 0);
final String hardwareId = hardwareId().apply(ImmutableList.of(coresItem, ramItem, volumeItem)); String hardwareId = hardwareId().apply(ImmutableList.of(coresItem, ramItem, volumeItem));
final double cores = ProductItems.capacity().apply(coresItem).doubleValue(); double cores = ProductItems.capacity().apply(coresItem).doubleValue();
final int ram = ProductItems.capacity().apply(ramItem).intValue(); Matcher cpuMatcher = cpuRegex.matcher(coresItem.getDescription());
final float volumeSize = ProductItems.capacity().apply(volumeItem); double coreSpeed = (cpuMatcher.matches()) ? Double.parseDouble(cpuMatcher.group(cpuMatcher.groupCount())) : 2.0;
int ram = ProductItems.capacity().apply(ramItem).intValue();
return new HardwareBuilder() return new HardwareBuilder().ids(hardwareId).processors(ImmutableList.of(new Processor(cores, coreSpeed))).ram(
.ids(hardwareId) ram).volumes(
.processors(ImmutableList.of(new Processor(cores, CORE_SPEED))) Iterables.transform(filter(items, categoryCodeMatches(categoryCodeMatches)),
.ram(ram) new Function<ProductItem, Volume>() {
.volumes(ImmutableList.<Volume> of(new VolumeImpl(volumeSize, true, false)))
.build(); @Override
public Volume apply(ProductItem arg0) {
float volumeSize = ProductItems.capacity().apply(arg0);
return new VolumeImpl(
arg0.getId() + "",
arg0.getDescription().indexOf("SAN") != -1 ? Volume.Type.SAN : Volume.Type.LOCAL,
volumeSize, null, categoryCode("guest_disk0").apply(arg0), false);
}
})).build();
} }
/** /**
* Generates a hardwareId based on the priceId's of the items in the list * Generates a hardwareId based on the priceId's of the items in the list
*
* @return comma separated list of priceid's * @return comma separated list of priceid's
*/ */
public static Function<List<ProductItem>,String> hardwareId() { public static Function<List<ProductItem>, String> hardwareId() {
return new Function<List<ProductItem>,String>() { return new Function<List<ProductItem>, String>() {
@Override @Override
public String apply(List<ProductItem> productItems) { public String apply(List<ProductItem> productItems) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
for(ProductItem item:productItems) { for (ProductItem item : productItems) {
ProductItemPrice price = ProductItems.price().apply(item); ProductItemPrice price = ProductItems.price().apply(item);
builder.append(price.getId()) builder.append(price.getId()).append(",");
.append(",");
} }
return builder.toString().substring(0,builder.lastIndexOf(",")); return builder.toString().substring(0, builder.lastIndexOf(","));
} }
}; };
} }

View File

@ -36,7 +36,6 @@ import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState; import org.jclouds.compute.domain.NodeState;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.http.HttpResponseException;
import org.jclouds.softlayer.SoftLayerClient; import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.domain.Datacenter; import org.jclouds.softlayer.domain.Datacenter;
import org.jclouds.softlayer.domain.ProductItem; import org.jclouds.softlayer.domain.ProductItem;
@ -49,7 +48,6 @@ import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
/** /**
* @author Adrian Cole * @author Adrian Cole
@ -129,25 +127,24 @@ public class VirtualGuestToNodeMetadata implements Function<VirtualGuest, NodeMe
@Singleton @Singleton
public static class GetHardwareForVirtualGuest { public static class GetHardwareForVirtualGuest {
private SoftLayerClient client; private final SoftLayerClient client;
private final Function<Iterable<ProductItem>, Hardware> productItemsToHardware;
@Inject @Inject
public GetHardwareForVirtualGuest(SoftLayerClient client) { public GetHardwareForVirtualGuest(SoftLayerClient client,
this.client = client; Function<Iterable<ProductItem>, Hardware> productItemsToHardware) {
this.client = checkNotNull(client, "client");
this.productItemsToHardware = checkNotNull(productItemsToHardware, "productItemsToHardware");
} }
public Hardware getHardware(VirtualGuest guest) { public Hardware getHardware(VirtualGuest guest) {
// 'bad' orders have no start cpu's and cause the order lookup to fail. // 'bad' orders have no start cpu's and cause the order lookup to fail.
if (guest.getStartCpus() < 1) if (guest.getStartCpus() < 1)
return null; return null;
try { ProductOrder order = client.getVirtualGuestClient().getOrderTemplate(guest.getId());
ProductOrder order = client.getVirtualGuestClient().getOrderTemplate(guest.getId()); Iterable<ProductItem> items = Iterables.transform(order.getPrices(), ProductItems.item());
Iterable<ProductItem> items = Iterables.transform(order.getPrices(), ProductItems.item()); return productItemsToHardware.apply(items);
return new ProductItemsToHardware().apply(Sets.newLinkedHashSet(items));
} catch (HttpResponseException e) {
// Shouldn't happen any more - was blowing up in Singapore
return null;
}
} }
} }
@ -165,15 +162,10 @@ public class VirtualGuestToNodeMetadata implements Function<VirtualGuest, NodeMe
// 'bad' orders have no start cpu's and cause the order lookup to fail. // 'bad' orders have no start cpu's and cause the order lookup to fail.
if (guest.getStartCpus() < 1) if (guest.getStartCpus() < 1)
return null; return null;
try { ProductOrder order = client.getVirtualGuestClient().getOrderTemplate(guest.getId());
ProductOrder order = client.getVirtualGuestClient().getOrderTemplate(guest.getId()); Iterable<ProductItem> items = Iterables.transform(order.getPrices(), ProductItems.item());
Iterable<ProductItem> items = Iterables.transform(order.getPrices(), ProductItems.item()); ProductItem os = Iterables.find(items, ProductItemPredicates.categoryCode("os"));
ProductItem os = Iterables.find(items, ProductItemPredicates.categoryCode("os")); return new ProductItemToImage().apply(os);
return new ProductItemToImage().apply(os);
} catch (HttpResponseException e) {
// Shouldn't happen any more - was blowing up in Singapore
return null;
}
} }
} }

View File

@ -18,37 +18,54 @@
*/ */
package org.jclouds.softlayer.compute.strategy; package org.jclouds.softlayer.compute.strategy;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Credentials;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.compute.functions.ProductItems;
import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions;
import org.jclouds.softlayer.domain.*;
import org.jclouds.softlayer.features.AccountClient;
import org.jclouds.softlayer.features.ProductPackageClient;
import org.jclouds.softlayer.reference.SoftLayerConstants;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.Map;
import java.util.Set;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.*; import static com.google.common.base.Predicates.and;
import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named; import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.get;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.capacity;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.categoryCode;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.matches;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_CPU_REGEX;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_DISK0_TYPE;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PORT_SPEED;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Credentials;
import org.jclouds.logging.Logger;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions;
import org.jclouds.softlayer.domain.Datacenter;
import org.jclouds.softlayer.domain.Password;
import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.ProductItemPrice;
import org.jclouds.softlayer.domain.ProductOrder;
import org.jclouds.softlayer.domain.ProductOrderReceipt;
import org.jclouds.softlayer.domain.ProductPackage;
import org.jclouds.softlayer.domain.VirtualGuest;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
/** /**
* defines the connection between the {@link SoftLayerClient} implementation and the jclouds * defines the connection between the {@link SoftLayerClient} implementation and the jclouds
@ -57,28 +74,40 @@ import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named;
*/ */
@Singleton @Singleton
public class SoftLayerComputeServiceAdapter implements public class SoftLayerComputeServiceAdapter implements
ComputeServiceAdapter<VirtualGuest, Set<ProductItem>, ProductItem, Datacenter> { ComputeServiceAdapter<VirtualGuest, Iterable<ProductItem>, ProductItem, Datacenter> {
public static final String SAN_DESCRIPTION_REGEX = ".*GB \\(SAN\\).*"; @Resource
private static final Float BOOT_VOLUME_CAPACITY = 100F; @Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final SoftLayerClient client; private final SoftLayerClient client;
private final String virtualGuestPackageName; private final Supplier<ProductPackage> productPackageSupplier;
private final RetryablePredicate<VirtualGuest> loginDetailsTester; private final RetryablePredicate<VirtualGuest> loginDetailsTester;
private final long guestLoginDelay; private final long guestLoginDelay;
private final Pattern cpuPattern;
private final Pattern disk0Type;
private final float portSpeed;
private final Iterable<ProductItemPrice> prices;
@Inject @Inject
public SoftLayerComputeServiceAdapter(SoftLayerClient client, public SoftLayerComputeServiceAdapter(SoftLayerClient client,
@Named(SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME) String virtualGuestPackageName,
VirtualGuestHasLoginDetailsPresent virtualGuestHasLoginDetailsPresent, VirtualGuestHasLoginDetailsPresent virtualGuestHasLoginDetailsPresent,
@Named(SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY) long guestLoginDelay) { @Memoized Supplier<ProductPackage> productPackageSupplier, Iterable<ProductItemPrice> prices,
@Named(PROPERTY_SOFTLAYER_VIRTUALGUEST_CPU_REGEX) String cpuRegex,
@Named(PROPERTY_SOFTLAYER_VIRTUALGUEST_DISK0_TYPE) String disk0Type,
@Named(PROPERTY_SOFTLAYER_VIRTUALGUEST_PORT_SPEED) float portSpeed,
@Named(PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY) long guestLoginDelay) {
this.client = checkNotNull(client, "client"); this.client = checkNotNull(client, "client");
this.virtualGuestPackageName = checkNotNull(virtualGuestPackageName, "virtualGuestPackageName"); this.guestLoginDelay = guestLoginDelay;
this.productPackageSupplier = checkNotNull(productPackageSupplier, "productPackageSupplier");
checkArgument(guestLoginDelay > 500, "guestOrderDelay must be in milliseconds and greater than 500"); checkArgument(guestLoginDelay > 500, "guestOrderDelay must be in milliseconds and greater than 500");
this.guestLoginDelay =guestLoginDelay;
this.loginDetailsTester = new RetryablePredicate<VirtualGuest>(virtualGuestHasLoginDetailsPresent, this.loginDetailsTester = new RetryablePredicate<VirtualGuest>(virtualGuestHasLoginDetailsPresent,
guestLoginDelay); guestLoginDelay);
this.cpuPattern = Pattern.compile(checkNotNull(cpuRegex, "cpuRegex"));
this.prices = checkNotNull(prices, "prices");
this.portSpeed = portSpeed;
checkArgument(portSpeed > 0, "portSpeed must be greater than zero, often 10, 100, 1000, 10000");
this.disk0Type = Pattern.compile(".*" + checkNotNull(disk0Type, "disk0Type") + ".*");
} }
@Override @Override
@ -87,34 +116,38 @@ public class SoftLayerComputeServiceAdapter implements
checkNotNull(template, "template was null"); checkNotNull(template, "template was null");
checkNotNull(template.getOptions(), "template options was null"); checkNotNull(template.getOptions(), "template options was null");
checkArgument(template.getOptions().getClass().isAssignableFrom(SoftLayerTemplateOptions.class), checkArgument(template.getOptions().getClass().isAssignableFrom(SoftLayerTemplateOptions.class),
"options class %s should have been assignable from SoftLayerTemplateOptions", template.getOptions() "options class %s should have been assignable from SoftLayerTemplateOptions", template.getOptions()
.getClass()); .getClass());
String domainName = template.getOptions().as(SoftLayerTemplateOptions.class).getDomainName(); String domainName = template.getOptions().as(SoftLayerTemplateOptions.class).getDomainName();
VirtualGuest newGuest = VirtualGuest.builder().domain(domainName).hostname(name).build(); VirtualGuest newGuest = VirtualGuest.builder().domain(domainName).hostname(name).build();
ProductOrder order = ProductOrder.builder().packageId(getProductPackage().getId()).location( ProductOrder order = ProductOrder.builder().packageId(productPackageSupplier.get().getId()).location(
template.getLocation().getId()).quantity(1).useHourlyPricing(true).prices(getPrices(template)) template.getLocation().getId()).quantity(1).useHourlyPricing(true).prices(getPrices(template))
.virtualGuest(newGuest).build(); .virtualGuest(newGuest).build();
logger.debug(">> ordering new virtualGuest domain(%s) hostname(%s)", domainName, name);
ProductOrderReceipt productOrderReceipt = client.getVirtualGuestClient().orderVirtualGuest(order); ProductOrderReceipt productOrderReceipt = client.getVirtualGuestClient().orderVirtualGuest(order);
VirtualGuest result = Iterables.get(productOrderReceipt.getOrderDetails().getVirtualGuests(), 0); VirtualGuest result = get(productOrderReceipt.getOrderDetails().getVirtualGuests(), 0);
logger.trace("<< virtualGuest(%s)", result.getId());
logger.debug(">> awaiting login details for virtualGuest(%s)", result.getId());
boolean orderInSystem = loginDetailsTester.apply(result); boolean orderInSystem = loginDetailsTester.apply(result);
logger.trace("<< virtualGuest(%s) complete(%s)", result.getId(), orderInSystem);
checkState(orderInSystem, "order for guest %s doesn't have login details within %sms", result, Long.toString(guestLoginDelay)); checkState(orderInSystem, "order for guest %s doesn't have login details within %sms", result, Long
.toString(guestLoginDelay));
result = client.getVirtualGuestClient().getVirtualGuest(result.getId()); result = client.getVirtualGuestClient().getVirtualGuest(result.getId());
Password pw = Iterables.get(result.getOperatingSystem().getPasswords(),0); Password pw = get(result.getOperatingSystem().getPasswords(), 0);
Credentials credentials = new Credentials(pw.getUsername(), pw.getPassword()); Credentials credentials = new Credentials(pw.getUsername(), pw.getPassword());
credentialStore.put("node#" + result.getId(), credentials); credentialStore.put("node#" + result.getId(), credentials);
return result; return result;
} }
private Iterable<ProductItemPrice> getPrices(Template template) { private Iterable<ProductItemPrice> getPrices(Template template) {
Set<ProductItemPrice> result = Sets.newLinkedHashSet(); Builder<ProductItemPrice> result = ImmutableSet.<ProductItemPrice> builder();
int imageId = Integer.parseInt(template.getImage().getId()); int imageId = Integer.parseInt(template.getImage().getId());
result.add(ProductItemPrice.builder().id(imageId).build()); result.add(ProductItemPrice.builder().id(imageId).build());
@ -124,46 +157,31 @@ public class SoftLayerComputeServiceAdapter implements
int id = Integer.parseInt(hardwareId); int id = Integer.parseInt(hardwareId);
result.add(ProductItemPrice.builder().id(id).build()); result.add(ProductItemPrice.builder().id(id).build());
} }
ProductItem uplinkItem = find(productPackageSupplier.get().getItems(), and(capacity(portSpeed),
result.addAll(SoftLayerConstants.DEFAULT_VIRTUAL_GUEST_PRICES); categoryCode("port_speed")));
result.add(get(uplinkItem.getPrices(), 0));
return result; result.addAll(prices);
return result.build();
} }
@Override @Override
public Iterable<Set<ProductItem>> listHardwareProfiles() { public Iterable<Iterable<ProductItem>> listHardwareProfiles() {
ProductPackage productPackage = getProductPackage(); ProductPackage productPackage = productPackageSupplier.get();
Set<ProductItem> items = productPackage.getItems(); Set<ProductItem> items = productPackage.getItems();
Builder<Iterable<ProductItem>> result = ImmutableSet.<Iterable<ProductItem>> builder();
Iterable<ProductItem> cpuItems = Iterables.filter(items, units("PRIVATE_CORE")); for (ProductItem cpuItem : filter(items, matches(cpuPattern))) {
Iterable<ProductItem> ramItems = Iterables.filter(items, categoryCode("ram")); for (ProductItem ramItem : filter(items, categoryCode("ram"))) {
Iterable<ProductItem> sanItems = Iterables.filter(items, Predicates.and(matches(SAN_DESCRIPTION_REGEX), for (ProductItem sanItem : filter(items, and(matches(disk0Type), categoryCode("guest_disk0")))) {
categoryCode("one_time_charge"))); result.add(ImmutableSet.of(cpuItem, ramItem, sanItem));
}
Map<Float, ProductItem> cpuMap = Maps.uniqueIndex(cpuItems, ProductItems.capacity()); }
Map<Float, ProductItem> ramMap = Maps.uniqueIndex(ramItems, ProductItems.capacity());
Map<Float, ProductItem> sanMap = Maps.uniqueIndex(sanItems, ProductItems.capacity());
final ProductItem bootVolume = sanMap.get(BOOT_VOLUME_CAPACITY);
assert bootVolume != null : "Boot volume capacity not found:" + BOOT_VOLUME_CAPACITY + ", available:" + sanItems;
Set<Set<ProductItem>> result = Sets.newLinkedHashSet();
for (Map.Entry<Float, ProductItem> coresEntry : cpuMap.entrySet()) {
Float cores = coresEntry.getKey();
ProductItem ramItem = ramMap.get(cores);
// Amount of RAM and number of cores must match.
if (ramItem == null)
continue;
result.add(ImmutableSet.of(coresEntry.getValue(), ramItem, bootVolume));
} }
return result.build();
return result;
} }
@Override @Override
public Iterable<ProductItem> listImages() { public Iterable<ProductItem> listImages() {
return Iterables.filter(getProductPackage().getItems(), categoryCode("os")); return filter(productPackageSupplier.get().getItems(), categoryCode("os"));
} }
@Override @Override
@ -173,15 +191,7 @@ public class SoftLayerComputeServiceAdapter implements
@Override @Override
public Iterable<Datacenter> listLocations() { public Iterable<Datacenter> listLocations() {
return getProductPackage().getDatacenters(); return productPackageSupplier.get().getDatacenters();
}
private ProductPackage getProductPackage() {
AccountClient accountClient = client.getAccountClient();
ProductPackageClient productPackageClient = client.getProductPackageClient();
ProductPackage p = Iterables.find(accountClient.getActivePackages(), named(virtualGuestPackageName));
return productPackageClient.getProductPackage(p.getId());
} }
@Override @Override
@ -197,8 +207,10 @@ public class SoftLayerComputeServiceAdapter implements
return; return;
if (guest.getBillingItemId() == -1) if (guest.getBillingItemId() == -1)
return; throw new IllegalStateException(String.format("no billing item for guest(%s) so we cannot cancel the order",
id));
logger.debug(">> canceling service for guest(%s) billingItem(%s)", id, guest.getBillingItemId());
client.getVirtualGuestClient().cancelService(guest.getBillingItemId()); client.getVirtualGuestClient().cancelService(guest.getBillingItemId());
} }
@ -232,7 +244,8 @@ public class SoftLayerComputeServiceAdapter implements
VirtualGuest newGuest = client.getVirtualGuestClient().getVirtualGuest(guest.getId()); VirtualGuest newGuest = client.getVirtualGuestClient().getVirtualGuest(guest.getId());
boolean hasBackendIp = newGuest.getPrimaryBackendIpAddress() != null; boolean hasBackendIp = newGuest.getPrimaryBackendIpAddress() != null;
boolean hasPrimaryIp = newGuest.getPrimaryIpAddress() != null; boolean hasPrimaryIp = newGuest.getPrimaryIpAddress() != null;
boolean hasPasswords = newGuest.getOperatingSystem()!=null && newGuest.getOperatingSystem().getPasswords().size() > 0; boolean hasPasswords = newGuest.getOperatingSystem() != null
&& newGuest.getOperatingSystem().getPasswords().size() > 0;
return hasBackendIp && hasPrimaryIp && hasPasswords; return hasBackendIp && hasPrimaryIp && hasPasswords;
} }

View File

@ -30,93 +30,126 @@ public class ProductItemPredicates {
/** /**
* Tests if the ProductItem contains the required category. * Tests if the ProductItem contains the required category.
*
* @param category * @param category
* @return true if it does, otherwise false. * @return true if it does, otherwise false.
*/ */
public static Predicate<ProductItem> categoryCode(final String category) { public static Predicate<ProductItem> categoryCode(final String category) {
checkNotNull(category, "category cannot be null"); checkNotNull(category, "category cannot be null");
return new Predicate<ProductItem>() { return new Predicate<ProductItem>() {
@Override @Override
public boolean apply(ProductItem productItem) { public boolean apply(ProductItem productItem) {
checkNotNull(productItem, "productItem cannot ne null"); checkNotNull(productItem, "productItem cannot ne null");
for(ProductItemCategory productItemCategory: productItem.getCategories()) { for (ProductItemCategory productItemCategory : productItem.getCategories()) {
if(category.equals(productItemCategory.getCategoryCode())) return true; if (category.equals(productItemCategory.getCategoryCode()))
} return true;
return false;
} }
return false;
}
@Override @Override
public String toString() { public String toString() {
return "categoryCode("+category+")"; return "categoryCode(" + category + ")";
}
};
}
/**
* Tests if the ProductItem contains a category that matches the supplied Pattern
*
* @param category
* @return true if it does, otherwise false.
*/
public static Predicate<ProductItem> categoryCodeMatches(final Pattern category) {
checkNotNull(category, "category cannot be null");
return new Predicate<ProductItem>() {
@Override
public boolean apply(ProductItem productItem) {
checkNotNull(productItem, "productItem cannot ne null");
for (ProductItemCategory productItemCategory : productItem.getCategories()) {
if (category.matcher(productItemCategory.getCategoryCode()).matches())
return true;
} }
}; return false;
} }
/** @Override
public String toString() {
return "categoryCodeMatches(" + category + ")";
}
};
}
/**
* Tests if the ProductItem has the required capacity. * Tests if the ProductItem has the required capacity.
*
* @param capacity * @param capacity
* @return true if it does, otherwise false. * @return true if it does, otherwise false.
*/ */
public static Predicate<ProductItem> capacity(final Float capacity) { public static Predicate<ProductItem> capacity(final Float capacity) {
checkNotNull(capacity, "capacity cannot be null"); checkNotNull(capacity, "capacity cannot be null");
return new Predicate<ProductItem>() { return new Predicate<ProductItem>() {
@Override @Override
public boolean apply(ProductItem productItem) { public boolean apply(ProductItem productItem) {
checkNotNull(productItem, "productItem cannot ne null"); checkNotNull(productItem, "productItem cannot ne null");
Float productItemCapacity = productItem.getCapacity(); Float productItemCapacity = productItem.getCapacity();
if (productItemCapacity == null) return false; if (productItemCapacity == null)
return capacity.equals(productItemCapacity); return false;
} return capacity.equals(productItemCapacity);
}
@Override @Override
public String toString() { public String toString() {
return "capacity("+capacity+")"; return "capacity(" + capacity + ")";
} }
}; };
} }
/** /**
* Tests if the ProductItem has the required units. * Tests if the ProductItem has the required units.
*
* @param units * @param units
* @return true if it does, otherwise false. * @return true if it does, otherwise false.
*/ */
public static Predicate<ProductItem> units(final String units) { public static Predicate<ProductItem> units(final String units) {
checkNotNull(units, "units cannot be null"); checkNotNull(units, "units cannot be null");
return new Predicate<ProductItem>() { return new Predicate<ProductItem>() {
@Override @Override
public boolean apply(ProductItem productItem) { public boolean apply(ProductItem productItem) {
checkNotNull(productItem, "productItem cannot ne null"); checkNotNull(productItem, "productItem cannot ne null");
return units.equals(productItem.getUnits()); return units.equals(productItem.getUnits());
} }
@Override @Override
public String toString() { public String toString() {
return "units("+units+")"; return "units(" + units + ")";
} }
}; };
} }
/** /**
* Tests if the ProductItem's description matches the supplied regular expression. * Tests if the ProductItem's description matches the supplied regular expression.
* @param regex a regular expression to match against. *
* @param regex
* a regular expression to match against.
* @return true if it does, otherwise false. * @return true if it does, otherwise false.
* @throws java.util.regex.PatternSyntaxException if the regex is invalid * @throws java.util.regex.PatternSyntaxException
* if the regex is invalid
*/ */
public static Predicate<ProductItem> matches(final String regex) { public static Predicate<ProductItem> matches(final Pattern regex) {
checkNotNull(regex, "regex cannot be null"); checkNotNull(regex, "regex cannot be null");
final Pattern PATTERN = Pattern.compile(regex);
return new Predicate<ProductItem>() { return new Predicate<ProductItem>() {
@Override @Override
public boolean apply(ProductItem productItem) { public boolean apply(ProductItem productItem) {
checkNotNull(productItem, "productItem cannot ne null"); checkNotNull(productItem, "productItem cannot ne null");
return PATTERN.matcher(productItem.getDescription()).matches(); return regex.matcher(productItem.getDescription()).matches();
} }
@Override @Override
public String toString() { public String toString() {
return "regex("+regex+")"; return "regex(" + regex + ")";
} }
}; };
} }
} }

View File

@ -18,38 +18,41 @@
*/ */
package org.jclouds.softlayer.reference; package org.jclouds.softlayer.reference;
import com.google.common.collect.ImmutableSet;
import org.jclouds.softlayer.domain.ProductItemPrice;
import java.util.Set;
/** /**
* Configuration properties and constants used in SoftLayer connections. * Configuration properties and constants used in SoftLayer connections.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public interface SoftLayerConstants { public interface SoftLayerConstants {
/** /**
* Name of the product package corresponding to cloud servers * Name of the product package corresponding to cloud servers
*/ */
public static final String PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME = "jclouds.softlayer.virtualguest.package-name"; public static final String PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME = "jclouds.softlayer.virtualguest.package-name";
/**
* pattern where last group matches core speed
*/
public static final String PROPERTY_SOFTLAYER_VIRTUALGUEST_CPU_REGEX = "jclouds.softlayer.virtualguest.cpu-regex";
/**
* Uplink port speed for new guests (10, 100, 1000)
*/
public static final String PROPERTY_SOFTLAYER_VIRTUALGUEST_PORT_SPEED = "jclouds.softlayer.virtualguest.port-speed";
/**
* Default Boot Disk type (SAN, LOCAL)
*/
public static final String PROPERTY_SOFTLAYER_VIRTUALGUEST_DISK0_TYPE = "jclouds.softlayer.virtualguest.disk0-type";
/** /**
* number of milliseconds to wait for an order to arrive on the api. * number of milliseconds to wait for an order to arrive on the api.
*/ */
public static final String PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY = "jclouds.softlayer.virtualguest.order-delay"; public static final String PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY = "jclouds.softlayer.virtualguest.order-delay";
public static final Set<ProductItemPrice> DEFAULT_VIRTUAL_GUEST_PRICES = ImmutableSet.<ProductItemPrice>builder() /**
.add(ProductItemPrice.builder().id(1639).build()) // 100 GB (SAN) * standard prices for all new guests.
.add(ProductItemPrice.builder().id(21).build()) // 1 IP Address */
.add(ProductItemPrice.builder().id(55).build()) // Host Ping public static final String PROPERTY_SOFTLAYER_VIRTUALGUEST_PRICES = "jclouds.softlayer.virtualguest.prices";
.add(ProductItemPrice.builder().id(58).build()) // Automated Notification
.add(ProductItemPrice.builder().id(1800).build()) // 0 GB Bandwidth
.add(ProductItemPrice.builder().id(57).build()) // Email and Ticket
.add(ProductItemPrice.builder().id(274).build()) // 1000 Mbps Public & Private Networks
.add(ProductItemPrice.builder().id(905).build()) // Reboot / Remote Console
.add(ProductItemPrice.builder().id(418).build()) // Nessus Vulnerability Assessment & Reporting
.add(ProductItemPrice.builder().id(420).build()) // Unlimited SSL VPN Users & 1 PPTP VPN User per account
.build();
} }

View File

@ -18,25 +18,22 @@
*/ */
package org.jclouds.softlayer.compute; package org.jclouds.softlayer.compute;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.categoryCode;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.units;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertFalse;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.Set;
import org.jclouds.compute.domain.ExecResponse; import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.net.IPSocket; import org.jclouds.net.IPSocket;
import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions; import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions;
import org.jclouds.softlayer.compute.strategy.SoftLayerComputeServiceAdapter; import org.jclouds.softlayer.compute.strategy.SoftLayerComputeServiceAdapter;
import org.jclouds.softlayer.domain.ProductItem; import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.VirtualGuest; import org.jclouds.softlayer.domain.VirtualGuest;
import org.jclouds.softlayer.features.BaseSoftLayerClientLiveTest; import org.jclouds.softlayer.features.BaseSoftLayerClientLiveTest;
import org.jclouds.softlayer.features.ProductPackageClientLiveTest;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import org.testng.annotations.AfterGroups; import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeGroups;
@ -45,6 +42,7 @@ import org.testng.annotations.Test;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.net.InetAddresses; import com.google.common.net.InetAddresses;
import com.google.inject.Guice;
@Test(groups = "live", singleThreaded = true, testName = "SoftLayerComputeServiceAdapterLiveTest") @Test(groups = "live", singleThreaded = true, testName = "SoftLayerComputeServiceAdapterLiveTest")
public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientLiveTest { public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientLiveTest {
@ -55,9 +53,8 @@ public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientL
@BeforeGroups(groups = { "live" }) @BeforeGroups(groups = { "live" })
public void setupClient() { public void setupClient() {
super.setupClient(); super.setupClient();
adapter = new SoftLayerComputeServiceAdapter(context.getApi(), adapter = Guice.createInjector(module, new Log4JLoggingModule())
ProductPackageClientLiveTest.CLOUD_SERVER_PACKAGE_NAME, .getInstance(SoftLayerComputeServiceAdapter.class);
new SoftLayerComputeServiceAdapter.VirtualGuestHasLoginDetailsPresent(context.getApi()),60*60*1000);
} }
@Test @Test
@ -68,12 +65,12 @@ public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientL
@Test @Test
public void testCreateNodeWithGroupEncodedIntoNameThenStoreCredentials() { public void testCreateNodeWithGroupEncodedIntoNameThenStoreCredentials() {
String group = "foo"; String group = "foo";
String name = "node"+new Random().nextInt(); String name = "node" + new Random().nextInt();
Template template = computeContext.getComputeService().templateBuilder().build(); Template template = computeContext.getComputeService().templateBuilder().build();
// test passing custom options // test passing custom options
template.getOptions().as(SoftLayerTemplateOptions.class).domainName("me.org"); template.getOptions().as(SoftLayerTemplateOptions.class).domainName("me.org");
Map<String, Credentials> credentialStore = Maps.newLinkedHashMap(); Map<String, Credentials> credentialStore = Maps.newLinkedHashMap();
guest = adapter.createNodeWithGroupEncodedIntoNameThenStoreCredentials(group, name, template, credentialStore); guest = adapter.createNodeWithGroupEncodedIntoNameThenStoreCredentials(group, name, template, credentialStore);
assertEquals(guest.getHostname(), name); assertEquals(guest.getHostname(), name);
@ -86,8 +83,7 @@ public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientL
} }
protected void doConnectViaSsh(VirtualGuest guest, Credentials creds) { protected void doConnectViaSsh(VirtualGuest guest, Credentials creds) {
SshClient ssh = computeContext.utils().sshFactory() SshClient ssh = computeContext.utils().sshFactory().create(new IPSocket(guest.getPrimaryIpAddress(), 22), creds);
.create(new IPSocket(guest.getPrimaryIpAddress(), 22), creds);
try { try {
ssh.connect(); ssh.connect();
ExecResponse hello = ssh.exec("echo hello"); ExecResponse hello = ssh.exec("echo hello");
@ -103,15 +99,12 @@ public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientL
@Test @Test
public void testListHardwareProfiles() { public void testListHardwareProfiles() {
Iterable<Set<ProductItem>> profiles = adapter.listHardwareProfiles(); Iterable<Iterable<ProductItem>> profiles = adapter.listHardwareProfiles();
assertFalse(Iterables.isEmpty(profiles)); assertFalse(Iterables.isEmpty(profiles));
for (Set<ProductItem> profile : profiles) { for (Iterable<ProductItem> profile : profiles) {
// CPU, RAM and Volume // CPU, RAM and Volume
assertEquals(profile.size(), 3); assertEquals(Iterables.size(profile), 3);
ProductItem cpuItem = Iterables.getOnlyElement(Iterables.filter(profile, units("PRIVATE_CORE")));
ProductItem ramItem = Iterables.getOnlyElement(Iterables.filter(profile, categoryCode("ram")));
assertEquals(cpuItem.getCapacity(), ramItem.getCapacity());
} }
} }

View File

@ -19,21 +19,31 @@
package org.jclouds.softlayer.compute; package org.jclouds.softlayer.compute;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores; import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.jclouds.compute.util.ComputeServiceUtils.getSpace;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_CPU_REGEX;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_DISK0_TYPE;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PORT_SPEED;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.io.IOException; import java.io.IOException;
import java.util.Properties;
import java.util.Set; import java.util.Set;
import org.jclouds.compute.BaseTemplateBuilderLiveTest; import org.jclouds.compute.BaseTemplateBuilderLiveTest;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.OsFamilyVersion64Bit; import org.jclouds.compute.domain.OsFamilyVersion64Bit;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.Volume;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions; import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
/** /**
* *
@ -46,7 +56,7 @@ public class SoftLayerTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTes
provider = "softlayer"; provider = "softlayer";
} }
/// allows us to break when a new os is added // / allows us to break when a new os is added
@Override @Override
protected Predicate<OsFamilyVersion64Bit> defineUnsupportedOperatingSystems() { protected Predicate<OsFamilyVersion64Bit> defineUnsupportedOperatingSystems() {
return Predicates.not(new Predicate<OsFamilyVersion64Bit>() { return Predicates.not(new Predicate<OsFamilyVersion64Bit>() {
@ -55,20 +65,20 @@ public class SoftLayerTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTes
public boolean apply(OsFamilyVersion64Bit input) { public boolean apply(OsFamilyVersion64Bit input) {
// For each os-type both 32- and 64-bit are supported. // For each os-type both 32- and 64-bit are supported.
switch (input.family) { switch (input.family) {
case UBUNTU: case UBUNTU:
return input.version.equals("") || input.version.equals("10.04") || input.version.equals("8"); return input.version.equals("") || input.version.equals("10.04") || input.version.equals("8");
case DEBIAN: case DEBIAN:
return input.version.equals("") || input.version.equals("5.0"); return input.version.equals("") || input.version.equals("5.0");
case FEDORA: case FEDORA:
return input.version.equals("") || input.version.equals("13") || input.version.equals("15"); return input.version.equals("") || input.version.equals("13") || input.version.equals("15");
case RHEL: case RHEL:
return input.version.equals("") || input.version.equals("5") || input.version.equals("6"); return input.version.equals("") || input.version.equals("5") || input.version.equals("6");
case CENTOS: case CENTOS:
return input.version.equals("") || input.version.equals("5") || input.version.equals("6.0"); return input.version.equals("") || input.version.equals("5") || input.version.equals("6.0");
case WINDOWS: case WINDOWS:
return input.version.equals("") || input.version.equals("2003") || input.version.equals("2008"); return input.version.equals("") || input.version.equals("2003") || input.version.equals("2008");
default: default:
return false; return false;
} }
} }
@ -81,13 +91,134 @@ public class SoftLayerTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTes
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "10.04"); assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "10.04");
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true); assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU); assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(getCores(defaultTemplate.getHardware()), 2.0d); assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
assertEquals(defaultTemplate.getHardware().getRam(), 1);
assertEquals(getSpace(defaultTemplate.getHardware()), 25.0d);
assertEquals(defaultTemplate.getHardware().getVolumes().get(0).getType(), Volume.Type.LOCAL);
// test that we bound the correct templateoptions in guice // test that we bound the correct templateoptions in guice
assertEquals(defaultTemplate.getOptions().getClass(), SoftLayerTemplateOptions.class); assertEquals(defaultTemplate.getOptions().getClass(), SoftLayerTemplateOptions.class);
} }
@Test
public void testTemplateBuilderFindsGigabitUplink() throws IOException {
ComputeServiceContext context = null;
try {
Properties overrides = setupProperties();
overrides.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_PORT_SPEED, "1000");
context = new ComputeServiceContextFactory().createContext(provider, ImmutableSet
.<Module> of(new Log4JLoggingModule()), overrides);
// TODO add something to the template about port speed?
context.getComputeService().templateBuilder().build();
} finally {
if (context != null)
context.close();
}
}
@Test
public void testTemplateBuilderFindsMegabitUplink() throws IOException {
ComputeServiceContext context = null;
try {
Properties overrides = setupProperties();
overrides.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_PORT_SPEED, "100");
context = new ComputeServiceContextFactory().createContext(provider, ImmutableSet
.<Module> of(new Log4JLoggingModule()), overrides);
// TODO add something to the template about port speed?
context.getComputeService().templateBuilder().build();
} finally {
if (context != null)
context.close();
}
}
@Test
public void testBiggestTemplateBuilderWhenBootIsSAN() throws IOException {
ComputeServiceContext context = null;
try {
Properties overrides = setupProperties();
overrides.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_DISK0_TYPE, "SAN");
context = new ComputeServiceContextFactory().createContext(provider, ImmutableSet
.<Module> of(new Log4JLoggingModule()), overrides);
Template template = context.getComputeService().templateBuilder().biggest().build();
assertEquals(getCores(template.getHardware()), 16.0d);
assertEquals(template.getHardware().getRam(), 16);
assertEquals(getSpace(template.getHardware()), 100.0d);
assertEquals(template.getHardware().getVolumes().get(0).getType(), Volume.Type.SAN);
} finally {
if (context != null)
context.close();
}
}
@Test
public void testDefaultTemplateBuilderWhenPrivateNetwork() throws IOException {
ComputeServiceContext context = null;
try {
Properties overrides = setupProperties();
overrides.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_CPU_REGEX, "Private [0-9]+ x ([.0-9]+) GHz Core[s]?");
context = new ComputeServiceContextFactory().createContext(provider, ImmutableSet
.<Module> of(new Log4JLoggingModule()), overrides);
Template template = context.getComputeService().templateBuilder().build();
assertEquals(getCores(template.getHardware()), 1.0d);
assertEquals(template.getHardware().getRam(), 1);
assertEquals(getSpace(template.getHardware()), 25.0d);
assertEquals(template.getHardware().getVolumes().get(0).getType(), Volume.Type.LOCAL);
} finally {
if (context != null)
context.close();
}
}
@Test
public void testBiggestTemplateBuilderWhenPrivateNetwork() throws IOException {
ComputeServiceContext context = null;
try {
Properties overrides = setupProperties();
overrides.setProperty(PROPERTY_SOFTLAYER_VIRTUALGUEST_CPU_REGEX, "Private [0-9]+ x ([.0-9]+) GHz Core[s]?");
context = new ComputeServiceContextFactory().createContext(provider, ImmutableSet
.<Module> of(new Log4JLoggingModule()), overrides);
Template template = context.getComputeService().templateBuilder().biggest().build();
assertEquals(getCores(template.getHardware()), 8.0d);
assertEquals(template.getHardware().getRam(), 16);
assertEquals(getSpace(template.getHardware()), 100.0d);
assertEquals(template.getHardware().getVolumes().get(0).getType(), Volume.Type.LOCAL);
} finally {
if (context != null)
context.close();
}
}
@Test
public void testFastestTemplateBuilder() throws IOException {
Template template = context.getComputeService().templateBuilder().fastest().build();
assertEquals(getCores(template.getHardware()), 16.0d);
assertEquals(template.getHardware().getRam(), 1);
assertEquals(getSpace(template.getHardware()), 25.0d);
assertEquals(template.getHardware().getVolumes().get(0).getType(), Volume.Type.LOCAL);
}
@Test
public void testBiggestTemplateBuilder() throws IOException {
Template template = context.getComputeService().templateBuilder().biggest().build();
assertEquals(getCores(template.getHardware()), 16.0d);
assertEquals(template.getHardware().getRam(), 16);
assertEquals(getSpace(template.getHardware()), 100.0d);
assertEquals(template.getHardware().getVolumes().get(0).getType(), Volume.Type.LOCAL);
}
@Override @Override
protected Set<String> getIso3166Codes() { protected Set<String> getIso3166Codes() {
return ImmutableSet.<String> of("SG","US-CA","US-TX","US-VA","US-WA","US-TX"); return ImmutableSet.<String> of("SG", "US-CA", "US-TX", "US-VA", "US-WA", "US-TX");
} }
} }

View File

@ -18,24 +18,30 @@
*/ */
package org.jclouds.softlayer.compute.functions; package org.jclouds.softlayer.compute.functions;
import com.google.common.collect.ImmutableList; import static com.google.inject.name.Names.bindProperties;
import com.google.common.collect.ImmutableSet; import static org.jclouds.softlayer.compute.functions.ProductItemsToHardware.hardwareId;
import static org.testng.AssertJUnit.assertEquals;
import java.util.List;
import java.util.Properties;
import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Processor; import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume; import org.jclouds.compute.domain.Volume;
import org.jclouds.softlayer.SoftLayerPropertiesBuilder;
import org.jclouds.softlayer.domain.ProductItem; import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.ProductItemCategory; import org.jclouds.softlayer.domain.ProductItemCategory;
import org.jclouds.softlayer.domain.ProductItemPrice; import org.jclouds.softlayer.domain.ProductItemPrice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.util.List; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import static org.jclouds.softlayer.compute.functions.ProductItemsToHardware.hardwareId; import com.google.inject.AbstractModule;
import static org.testng.AssertJUnit.assertEquals; import com.google.inject.Guice;
/** /**
* Tests {@code ProductItemsToHardware} * Tests {@code ProductItemsToHardware}
* *
* @author Jason King * @author Jason King
*/ */
@Test(groups = "unit") @Test(groups = "unit")
@ -48,46 +54,41 @@ public class ProductItemsToHardwareTest {
ProductItem item3 = ProductItem.builder().price(ProductItemPrice.builder().id(789).build()).build(); ProductItem item3 = ProductItem.builder().price(ProductItemPrice.builder().id(789).build()).build();
String id = hardwareId().apply(ImmutableList.of(item1, item2, item3)); String id = hardwareId().apply(ImmutableList.of(item1, item2, item3));
assertEquals("123,456,789",id); assertEquals("123,456,789", id);
} }
@Test @Test
public void testHardware() { public void testHardware() {
ProductItem cpuItem = ProductItem.builder() ProductItem cpuItem = ProductItem.builder().id(1).description("2 x 2.0 GHz Cores").units("PRIVATE_CORE")
.id(1) .capacity(2F).price(ProductItemPrice.builder().id(123).build()).build();
.description("2 cores")
.units("PRIVATE_CORE")
.capacity(2F)
.price(ProductItemPrice.builder().id(123).build())
.build();
ProductItem ramItem = ProductItem.builder()
.id(2)
.description("2GB ram")
.capacity(2F)
.category(ProductItemCategory.builder().categoryCode("ram").build())
.price(ProductItemPrice.builder().id(456).build())
.build();
ProductItem volumeItem = ProductItem.builder() ProductItem ramItem = ProductItem.builder().id(2).description("2GB ram").capacity(2F).category(
.id(3) ProductItemCategory.builder().categoryCode("ram").build()).price(
.description("100 GB (SAN)") ProductItemPrice.builder().id(456).build()).build();
.capacity(100F)
.price(ProductItemPrice.builder().id(789).build())
.build();
Hardware hardware = new ProductItemsToHardware().apply(ImmutableSet.of(cpuItem,ramItem,volumeItem)); ProductItem volumeItem = ProductItem.builder().id(3).description("100 GB (SAN)").capacity(100F).price(
ProductItemPrice.builder().id(789).build()).category(
ProductItemCategory.builder().categoryCode("guest_disk0").build()).build();
assertEquals("123,456,789",hardware.getId()); Hardware hardware = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bindProperties(binder(), new SoftLayerPropertiesBuilder(new Properties()).build());
}
}).getInstance(ProductItemsToHardware.class).apply(ImmutableSet.of(cpuItem, ramItem, volumeItem));
assertEquals("123,456,789", hardware.getId());
List<? extends Processor> processors = hardware.getProcessors(); List<? extends Processor> processors = hardware.getProcessors();
assertEquals(1,processors.size()); assertEquals(1, processors.size());
assertEquals(2.0,processors.get(0).getCores()); assertEquals(2.0, processors.get(0).getCores());
assertEquals(2, hardware.getRam()); assertEquals(2, hardware.getRam());
List<? extends Volume> volumes = hardware.getVolumes(); List<? extends Volume> volumes = hardware.getVolumes();
assertEquals(1,volumes.size()); assertEquals(1, volumes.size());
assertEquals(100F,volumes.get(0).getSize()); assertEquals(100F, volumes.get(0).getSize());
} }
} }

View File

@ -18,26 +18,40 @@
*/ */
package org.jclouds.softlayer.compute.functions; package org.jclouds.softlayer.compute.functions;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import com.google.common.collect.Iterables; import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.*; import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.compute.functions.VirtualGuestToNodeMetadata.FindLocationForVirtualGuest; import org.jclouds.softlayer.compute.functions.VirtualGuestToNodeMetadata.FindLocationForVirtualGuest;
import org.jclouds.softlayer.domain.Password; import org.jclouds.softlayer.domain.Password;
import org.jclouds.softlayer.domain.VirtualGuest; import org.jclouds.softlayer.domain.VirtualGuest;
import org.jclouds.softlayer.parse.*; import org.jclouds.softlayer.parse.ParseBadVirtualGuest;
import org.jclouds.softlayer.parse.ParseVirtualGuestHaltedTest;
import org.jclouds.softlayer.parse.ParseVirtualGuestPausedTest;
import org.jclouds.softlayer.parse.ParseVirtualGuestRunningTest;
import org.jclouds.softlayer.parse.ParseVirtualGuestWithNoPasswordTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.base.Suppliers; import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/** /**
* @author Adrian Cole * @author Adrian Cole
@ -209,8 +223,9 @@ public class VirtualGuestToNodeMetadataTest {
} }
private static class GetHardwareForVirtualGuestMock extends VirtualGuestToNodeMetadata.GetHardwareForVirtualGuest { private static class GetHardwareForVirtualGuestMock extends VirtualGuestToNodeMetadata.GetHardwareForVirtualGuest {
@SuppressWarnings("unchecked")
public GetHardwareForVirtualGuestMock() { public GetHardwareForVirtualGuestMock() {
super(null); super(createNiceMock(SoftLayerClient.class), createNiceMock(Function.class));
} }
@Override @Override

View File

@ -19,20 +19,36 @@
package org.jclouds.softlayer.features; package org.jclouds.softlayer.features;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.inject.name.Names.bindProperties;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PRICES;
import java.util.Properties;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory; import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.softlayer.SoftLayerAsyncClient; import org.jclouds.softlayer.SoftLayerAsyncClient;
import org.jclouds.softlayer.SoftLayerClient; import org.jclouds.softlayer.SoftLayerClient;
import org.jclouds.softlayer.SoftLayerPropertiesBuilder;
import org.jclouds.softlayer.compute.config.SoftLayerComputeServiceContextModule;
import org.jclouds.softlayer.domain.ProductItemPrice;
import org.jclouds.softlayer.domain.ProductPackage;
import org.jclouds.sshj.config.SshjSshClientModule; import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.AfterGroups; import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.inject.AbstractModule;
import com.google.inject.Module; import com.google.inject.Module;
import com.google.inject.Provides;
/** /**
* Tests behavior of {@code SoftLayerClient} * Tests behavior of {@code SoftLayerClient}
@ -44,16 +60,41 @@ public class BaseSoftLayerClientLiveTest {
protected RestContext<SoftLayerClient, SoftLayerAsyncClient> context; protected RestContext<SoftLayerClient, SoftLayerAsyncClient> context;
protected ComputeServiceContext computeContext; protected ComputeServiceContext computeContext;
protected Module module;
@BeforeGroups(groups = { "live" }) @BeforeGroups(groups = { "live" })
public void setupClient() { public void setupClient() {
String identity = checkNotNull(System.getProperty("test.softlayer.identity"), "test.softlayer.identity"); String identity = checkNotNull(System.getProperty("test.softlayer.identity"), "test.softlayer.identity");
String credential = checkNotNull(System.getProperty("test.softlayer.credential"), "test.softlayer.credential"); String credential = checkNotNull(System.getProperty("test.softlayer.credential"), "test.softlayer.credential");
computeContext = new ComputeServiceContextFactory().createContext("softlayer", identity, credential, computeContext = new ComputeServiceContextFactory().createContext("softlayer", identity, credential, ImmutableSet
ImmutableSet.<Module> of(new Log4JLoggingModule(), new SshjSshClientModule())); .<Module> of(new Log4JLoggingModule(), new SshjSshClientModule()));
context = computeContext.getProviderSpecificContext(); context = computeContext.getProviderSpecificContext();
module = new AbstractModule() {
@Override
protected void configure() {
bindProperties(binder(), new SoftLayerPropertiesBuilder(new Properties()).build());
bind(SoftLayerClient.class).toInstance(context.getApi());
}
@SuppressWarnings("unused")
@Provides
@Singleton
@Memoized
public Supplier<ProductPackage> getProductPackage(SoftLayerClient client,
@Named(PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME) String virtualGuestPackageName) {
return new SoftLayerComputeServiceContextModule().getProductPackage(30, client, virtualGuestPackageName);
}
@SuppressWarnings("unused")
@Provides
@Singleton
public Iterable<ProductItemPrice> prices(@Named(PROPERTY_SOFTLAYER_VIRTUALGUEST_PRICES) String prices) {
return new SoftLayerComputeServiceContextModule().prices(prices);
}
};
} }
@AfterGroups(groups = "live") @AfterGroups(groups = "live")

View File

@ -43,9 +43,11 @@ import static org.testng.Assert.*;
public class ProductPackageClientLiveTest extends BaseSoftLayerClientLiveTest { public class ProductPackageClientLiveTest extends BaseSoftLayerClientLiveTest {
/** /**
* Name of the package used for ordering virtual guests. * Name of the package used for ordering virtual guests. For real this is passed in using the
* For real this is passed in using the property * property
* @{code org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME} *
* @{code org.jclouds.softlayer.reference.SoftLayerConstants.
* PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME}
*/ */
public static final String CLOUD_SERVER_PACKAGE_NAME = "Cloud Server"; public static final String CLOUD_SERVER_PACKAGE_NAME = "Cloud Server";
@ -56,7 +58,8 @@ public class ProductPackageClientLiveTest extends BaseSoftLayerClientLiveTest {
accountClient = context.getApi().getAccountClient(); accountClient = context.getApi().getAccountClient();
// This is used several times, so cache to speed up the test. // This is used several times, so cache to speed up the test.
cloudServerPackageId = Iterables.find(accountClient.getActivePackages(),named(CLOUD_SERVER_PACKAGE_NAME)).getId(); cloudServerPackageId = Iterables.find(accountClient.getActivePackages(), named(CLOUD_SERVER_PACKAGE_NAME))
.getId();
cloudServerProductPackage = client.getProductPackage(cloudServerPackageId); cloudServerProductPackage = client.getProductPackage(cloudServerPackageId);
} }
@ -107,7 +110,7 @@ public class ProductPackageClientLiveTest extends BaseSoftLayerClientLiveTest {
assertEquals(datacenters.size(), expected.size()); assertEquals(datacenters.size(), expected.size());
assertTrue(datacenters.containsAll(expected)); assertTrue(datacenters.containsAll(expected));
for(Datacenter dataCenter: datacenters) { for (Datacenter dataCenter : datacenters) {
Address address = dataCenter.getLocationAddress(); Address address = dataCenter.getLocationAddress();
assertNotNull(address); assertNotNull(address);
checkAddress(address); checkAddress(address);
@ -116,37 +119,42 @@ public class ProductPackageClientLiveTest extends BaseSoftLayerClientLiveTest {
@Test @Test
public void testGetOneGBRamPrice() { public void testGetOneGBRamPrice() {
//Predicate p = Predicates.and(ProductItemPredicates.categoryCode("ram"),ProductItemPredicates.capacity(1.0f)); // Predicate p =
Iterable<ProductItem> ramItems = Iterables.filter(cloudServerProductPackage.getItems(), // Predicates.and(ProductItemPredicates.categoryCode("ram"),ProductItemPredicates.capacity(1.0f));
Predicates.and(categoryCode("ram"), capacity(1.0f))); Iterable<ProductItem> ramItems = Iterables.filter(cloudServerProductPackage.getItems(), Predicates.and(
categoryCode("ram"), capacity(1.0f)));
// capacity is key in GB (1Gb = 1.0f) // capacity is key in GB (1Gb = 1.0f)
Map<Float, ProductItem> ramToProductItem = Maps.uniqueIndex(ramItems, ProductItems.capacity()); Map<Float, ProductItem> ramToProductItem = Maps.uniqueIndex(ramItems, ProductItems.capacity());
ProductItemPrice price = ProductItems.price().apply(ramToProductItem.get(1.0f)); ProductItemPrice price = ProductItems.price().apply(ramToProductItem.get(1.0f));
assert new Integer(1644).equals(price.getId()); assert new Integer(1644).equals(price.getId());
} }
@Test @Test
public void testGetTwoCPUCoresPrice() { public void testGetTwoCPUCoresPrice() {
// If use ProductItemPredicates.categoryCode("guest_core") get duplicate capacities (units = PRIVATE_CORE and N/A) // If use ProductItemPredicates.categoryCode("guest_core") get duplicate capacities (units =
Iterable<ProductItem> cpuItems = Iterables.filter(cloudServerProductPackage.getItems(), Predicates.and(units("PRIVATE_CORE"), capacity(2.0f))); // PRIVATE_CORE and N/A)
Iterable<ProductItem> cpuItems = Iterables.filter(cloudServerProductPackage.getItems(), Predicates.and(
units("PRIVATE_CORE"), capacity(2.0f)));
// number of cores is the key // number of cores is the key
Map<Float, ProductItem> coresToProductItem = Maps.uniqueIndex(cpuItems, ProductItems.capacity()); Map<Float, ProductItem> coresToProductItem = Maps.uniqueIndex(cpuItems, ProductItems.capacity());
ProductItemPrice price = ProductItems.price().apply(coresToProductItem.get(2.0f)); ProductItemPrice price = ProductItems.price().apply(coresToProductItem.get(2.0f));
assert new Integer(1963).equals(price.getId()); assert new Integer(1963).equals(price.getId());
} }
@Test @Test
public void testGetUbuntuPrice() { public void testGetUbuntuPrice() {
Iterable<ProductItem> operatingSystems = Iterables.filter(cloudServerProductPackage.getItems(), categoryCode("os")); Iterable<ProductItem> operatingSystems = Iterables.filter(cloudServerProductPackage.getItems(),
categoryCode("os"));
Map<String, ProductItem> osToProductItem = Maps.uniqueIndex(operatingSystems, ProductItems.description()); Map<String, ProductItem> osToProductItem = Maps.uniqueIndex(operatingSystems, ProductItems.description());
ProductItemPrice price = ProductItems.price().apply(osToProductItem.get("Ubuntu Linux 8 LTS Hardy Heron - Minimal Install (64 bit)")); ProductItemPrice price = ProductItems.price().apply(
assert new Integer(1693).equals(price.getId()); osToProductItem.get("Ubuntu Linux 8 LTS Hardy Heron - Minimal Install (64 bit)"));
assert new Integer(1693).equals(price.getId());
} }
private void checkProductItem(ProductItem item) { private void checkProductItem(ProductItem item) {
@ -178,17 +186,17 @@ public class ProductPackageClientLiveTest extends BaseSoftLayerClientLiveTest {
} }
private void checkAddress(Address address) { private void checkAddress(Address address) {
assert address.getId() >0 : address; assert address.getId() > 0 : address;
assert address.getCountry() != null : address; assert address.getCountry() != null : address;
if (!address.getCountry().equals("SG")) if (!address.getCountry().equals("SG"))
assert address.getState() != null : address; assert address.getState() != null : address;
} }
private void checkCategories(Set<ProductItemCategory> categories) { private void checkCategories(Set<ProductItemCategory> categories) {
for( ProductItemCategory category: categories ) { for (ProductItemCategory category : categories) {
assert category.getId() >0 : category; assert category.getId() > 0 : category;
assert category.getName() != null : category; assert category.getName() != null : category;
assert category.getCategoryCode() != null : category; assert category.getCategoryCode() != null : category;
} }
} }
} }

View File

@ -18,23 +18,36 @@
*/ */
package org.jclouds.softlayer.features; package org.jclouds.softlayer.features;
import com.google.common.base.Predicates; import static org.jclouds.softlayer.predicates.ProductItemPredicates.capacity;
import com.google.common.collect.Iterables; import static org.jclouds.softlayer.predicates.ProductItemPredicates.categoryCode;
import com.google.common.collect.Maps; import static org.jclouds.softlayer.predicates.ProductItemPredicates.units;
import com.google.common.collect.Sets; import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named;
import org.jclouds.softlayer.compute.functions.ProductItems; import static org.testng.Assert.assertEquals;
import org.jclouds.softlayer.domain.*; import static org.testng.Assert.assertNotNull;
import org.jclouds.softlayer.reference.SoftLayerConstants; import static org.testng.Assert.assertTrue;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import static org.jclouds.softlayer.predicates.ProductItemPredicates.*; import org.jclouds.softlayer.compute.functions.ProductItems;
import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named; import org.jclouds.softlayer.domain.ProductItem;
import static org.testng.Assert.*; import org.jclouds.softlayer.domain.ProductItemPrice;
import org.jclouds.softlayer.domain.ProductOrder;
import org.jclouds.softlayer.domain.ProductOrderReceipt;
import org.jclouds.softlayer.domain.ProductPackage;
import org.jclouds.softlayer.domain.VirtualGuest;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.ImmutableSet.Builder;
import com.google.inject.Guice;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
/** /**
* Tests behavior of {@code VirtualGuestClient} * Tests behavior of {@code VirtualGuestClient}
@ -66,70 +79,69 @@ public class VirtualGuestClientLiveTest extends BaseSoftLayerClientLiveTest {
} }
} }
@Test(enabled = false) @Test(enabled = false, groups = "live")
public void testCancelAndPlaceOrder() { public void testCancelAndPlaceOrder() {
// This method was not working needs testing out. // This method was not working needs testing out.
// TODO: Should also check if there are active transactions before trying to cancel. // TODO: Should also check if there are active transactions before trying to cancel.
// objectMask: virtualGuests.activeTransaction // objectMask: virtualGuests.activeTransaction
for( VirtualGuest guest: client.listVirtualGuests()) { for (VirtualGuest guest : client.listVirtualGuests()) {
if (guest.getHostname().startsWith(TEST_HOSTNAME_PREFIX)) { if (guest.getHostname().startsWith(TEST_HOSTNAME_PREFIX)) {
if(guest.getBillingItemId()!=-1) { if (guest.getBillingItemId() != -1) {
client.cancelService(guest.getBillingItemId()); client.cancelService(guest.getBillingItemId());
} }
} }
} }
int pkgId = Iterables.find(context.getApi().getAccountClient().getActivePackages(),named(ProductPackageClientLiveTest.CLOUD_SERVER_PACKAGE_NAME)).getId(); int pkgId = Iterables.find(context.getApi().getAccountClient().getActivePackages(),
named(ProductPackageClientLiveTest.CLOUD_SERVER_PACKAGE_NAME)).getId();
ProductPackage productPackage = context.getApi().getProductPackageClient().getProductPackage(pkgId); ProductPackage productPackage = context.getApi().getProductPackageClient().getProductPackage(pkgId);
Iterable<ProductItem> ramItems = Iterables.filter(productPackage.getItems(), Iterable<ProductItem> ramItems = Iterables.filter(productPackage.getItems(), Predicates.and(categoryCode("ram"),
Predicates.and(categoryCode("ram"), capacity(2.0f))); capacity(2.0f)));
Map<Float, ProductItem> ramToProductItem = Maps.uniqueIndex(ramItems, ProductItems.capacity()); Map<Float, ProductItem> ramToProductItem = Maps.uniqueIndex(ramItems, ProductItems.capacity());
ProductItemPrice ramPrice = ProductItems.price().apply(ramToProductItem.get(2.0f)); ProductItemPrice ramPrice = ProductItems.price().apply(ramToProductItem.get(2.0f));
Iterable<ProductItem> cpuItems = Iterables.filter(productPackage.getItems(), Predicates.and(units("PRIVATE_CORE"), capacity(2.0f))); Iterable<ProductItem> cpuItems = Iterables.filter(productPackage.getItems(), Predicates.and(
Map<Float, ProductItem> coresToProductItem = Maps.uniqueIndex(cpuItems, ProductItems.capacity()); units("PRIVATE_CORE"), capacity(2.0f)));
Map<Float, ProductItem> coresToProductItem = Maps.uniqueIndex(cpuItems, ProductItems.capacity());
ProductItemPrice cpuPrice = ProductItems.price().apply(coresToProductItem.get(2.0f)); ProductItemPrice cpuPrice = ProductItems.price().apply(coresToProductItem.get(2.0f));
Iterable<ProductItem> operatingSystems = Iterables.filter(productPackage.getItems(), categoryCode("os")); Iterable<ProductItem> operatingSystems = Iterables.filter(productPackage.getItems(), categoryCode("os"));
Map<String, ProductItem> osToProductItem = Maps.uniqueIndex(operatingSystems, ProductItems.description()); Map<String, ProductItem> osToProductItem = Maps.uniqueIndex(operatingSystems, ProductItems.description());
ProductItemPrice osPrice = ProductItems.price().apply(osToProductItem.get("Ubuntu Linux 8 LTS Hardy Heron - Minimal Install (64 bit)")); ProductItemPrice osPrice = ProductItems.price().apply(
osToProductItem.get("Ubuntu Linux 8 LTS Hardy Heron - Minimal Install (64 bit)"));
Set<ProductItemPrice> prices = Sets.<ProductItemPrice>newLinkedHashSet(); Builder<ProductItemPrice> prices = ImmutableSet.<ProductItemPrice> builder();
prices.addAll(SoftLayerConstants.DEFAULT_VIRTUAL_GUEST_PRICES); prices.addAll(Guice.createInjector(module).getInstance(Key.get(new TypeLiteral<Iterable<ProductItemPrice>>() {
prices.add(ramPrice); })));
prices.add(cpuPrice); prices.add(ramPrice);
prices.add(osPrice); prices.add(cpuPrice);
prices.add(osPrice);
VirtualGuest guest = VirtualGuest.builder().domain("jclouds.org") VirtualGuest guest = VirtualGuest.builder().domain("jclouds.org").hostname(
.hostname(TEST_HOSTNAME_PREFIX+new Random().nextInt()) TEST_HOSTNAME_PREFIX + new Random().nextInt()).build();
.build();
ProductOrder order = ProductOrder.builder() ProductOrder order = ProductOrder.builder().packageId(pkgId).quantity(1).useHourlyPricing(true).prices(
.packageId(pkgId) prices.build()).virtualGuest(guest).build();
.quantity(1)
.useHourlyPricing(true)
.prices(prices)
.virtualGuest(guest)
.build();
ProductOrderReceipt receipt = context.getApi().getVirtualGuestClient().orderVirtualGuest(order); ProductOrderReceipt receipt = context.getApi().getVirtualGuestClient().orderVirtualGuest(order);
ProductOrder order2 = receipt.getOrderDetails(); ProductOrder order2 = receipt.getOrderDetails();
VirtualGuest result = Iterables.get(order2.getVirtualGuests(), 0); VirtualGuest result = Iterables.get(order2.getVirtualGuests(), 0);
ProductOrder order3 = context.getApi().getVirtualGuestClient().getOrderTemplate(result.getId()); ProductOrder order3 = context.getApi().getVirtualGuestClient().getOrderTemplate(result.getId());
assertEquals(order.getPrices(),order3.getPrices()); assertEquals(order.getPrices(), order3.getPrices());
assertNotNull(receipt); assertNotNull(receipt);
} }
private void checkVirtualGuest(VirtualGuest vg) { private void checkVirtualGuest(VirtualGuest vg) {
if (vg.getBillingItemId()==-1) return;//Quotes and shutting down guests if (vg.getBillingItemId() == -1)
return;// Quotes and shutting down guests
assert vg.getAccountId() > 0 : vg; assert vg.getAccountId() > 0 : vg;
assert vg.getCreateDate() != null : vg; assert vg.getCreateDate() != null : vg;

View File

@ -18,15 +18,18 @@
*/ */
package org.jclouds.softlayer.predicates; package org.jclouds.softlayer.predicates;
import com.google.common.collect.ImmutableSet; import static org.testng.Assert.assertFalse;
import java.util.regex.Pattern;
import org.jclouds.softlayer.domain.ProductItem; import org.jclouds.softlayer.domain.ProductItem;
import org.jclouds.softlayer.domain.ProductItemCategory; import org.jclouds.softlayer.domain.ProductItemCategory;
import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import static org.testng.Assert.assertFalse; import com.google.common.collect.ImmutableSet;
@Test(sequential = true,groups = "unit") @Test(singleThreaded = true, groups = "unit")
public class ProductItemPredicatesTest { public class ProductItemPredicatesTest {
private ProductItemCategory ramCategory; private ProductItemCategory ramCategory;
@ -37,66 +40,64 @@ public class ProductItemPredicatesTest {
public void setupClient() { public void setupClient() {
ramCategory = ProductItemCategory.builder().id(1).categoryCode("ram").build(); ramCategory = ProductItemCategory.builder().id(1).categoryCode("ram").build();
item = ProductItem.builder().id(1) item = ProductItem.builder().id(1).description("a test item").categories(ImmutableSet.of(ramCategory)).capacity(
.description("a test item") 2.0f).units("GB").build();
.categories(ImmutableSet.of(ramCategory))
.capacity(2.0f)
.units("GB")
.build();
emptyItem = ProductItem.builder().id(1).build(); emptyItem = ProductItem.builder().id(1).build();
} }
@Test @Test
public void testCategoryCodePresent() { public void testCategoryCodePresent() {
assert ProductItemPredicates.categoryCode("ram").apply(item); assert ProductItemPredicates.categoryCode("ram").apply(item);
} }
@Test @Test
public void testCategoryCodePresentTwoCategories() { public void testCategoryCodePresentTwoCategories() {
ProductItemCategory osCategory = ProductItemCategory.builder() ProductItemCategory osCategory = ProductItemCategory.builder().id(2).categoryCode("os").build();
.id(2).categoryCode("os")
.build();
ProductItem item = ProductItem.builder() ProductItem item = ProductItem.builder().categories(ImmutableSet.of(ramCategory, osCategory)).build();
.categories(ImmutableSet.of(ramCategory, osCategory))
.build();
assert ProductItemPredicates.categoryCode("ram").apply(item); assert ProductItemPredicates.categoryCode("ram").apply(item);
} }
@Test @Test
public void testCategoryCodeMissing() { public void testCategoryCodeMissing() {
assertFalse(ProductItemPredicates.categoryCode("missing").apply(emptyItem)); assertFalse(ProductItemPredicates.categoryCode("missing").apply(emptyItem));
} }
@Test
public void testCategoryCodeMatches() {
ProductItemPredicates.categoryCodeMatches(Pattern.compile("ra.*")).apply(item);
}
@Test
public void testCapacityPresent() {
assert ProductItemPredicates.capacity(2.0f).apply(item);
}
@Test @Test
public void testCapacityMissing() { public void testCapacityPresent() {
assertFalse(ProductItemPredicates.capacity(1.0f).apply(item)); assert ProductItemPredicates.capacity(2.0f).apply(item);
} }
@Test @Test
public void testUnitsPresent() { public void testCapacityMissing() {
assert ProductItemPredicates.units("GB").apply(item); assertFalse(ProductItemPredicates.capacity(1.0f).apply(item));
} }
@Test @Test
public void testUnitsMissing() { public void testUnitsPresent() {
assertFalse(ProductItemPredicates.units("Kg").apply(item)); assert ProductItemPredicates.units("GB").apply(item);
} }
@Test @Test
public void testMatchesRegex() { public void testUnitsMissing() {
assert ProductItemPredicates.matches(".*test.*").apply(item); assertFalse(ProductItemPredicates.units("Kg").apply(item));
} }
@Test @Test
public void testNoMatchRegex() { public void testMatchesRegex() {
assertFalse(ProductItemPredicates.matches("no match").apply(item)); assert ProductItemPredicates.matches(Pattern.compile(".*test.*")).apply(item);
} }
@Test
public void testNoMatchRegex() {
assertFalse(ProductItemPredicates.matches(Pattern.compile("no match")).apply(item));
}
} }