diff --git a/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java b/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java index 272d4a8445..ac19f22b00 100644 --- a/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java +++ b/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java @@ -24,6 +24,7 @@ import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Iterables.find; import static com.google.common.collect.Iterables.size; import static com.google.common.collect.Iterables.transform; +import static com.google.common.collect.Iterables.tryFind; import static com.google.common.collect.Lists.newArrayList; import static java.lang.String.format; import static org.jclouds.compute.util.ComputeServiceUtils.getCores; @@ -401,27 +402,23 @@ public class TemplateBuilderImpl implements TemplateBuilder { private Predicate buildHardwarePredicate() { List> predicates = newArrayList(); - if (hardwareId != null) { - predicates.add(hardwareIdPredicate); - } else { - if (location != null) - predicates.add(new Predicate() { + if (location != null) + predicates.add(new Predicate() { - @Override - public boolean apply(Hardware input) { - return locationPredicate.apply(input); - } + @Override + public boolean apply(Hardware input) { + return locationPredicate.apply(input); + } - @Override - public String toString() { - return locationPredicate.toString(); - } - }); - if (hypervisor != null) - predicates.add(hypervisorPredicate); - predicates.add(hardwareCoresPredicate); - predicates.add(hardwareRamPredicate); - } + @Override + public String toString() { + return locationPredicate.toString(); + } + }); + if (hypervisor != null) + predicates.add(hypervisorPredicate); + predicates.add(hardwareCoresPredicate); + predicates.add(hardwareRamPredicate); // looks verbose, but explicit type needed for this to compile // properly @@ -610,35 +607,87 @@ public class TemplateBuilderImpl implements TemplateBuilder { options = optionsProvider.get(); logger.debug(">> searching params(%s)", this); Set images = getImages(); + Set hardwaresToSearch = hardwares.get(); + + Image image = null; + if (imageId != null) { + image = findImageWithId(images); + if (currentLocationWiderThan(image.getLocation())) + this.location = image.getLocation(); + } + + Hardware hardware = null; + if (hardwareId != null) { + hardware = findHardwareWithId(hardwaresToSearch); + if (currentLocationWiderThan(hardware.getLocation())) + this.location = hardware.getLocation(); + } + + // if the user hasn't specified a location id, or an image or hardware + // with location, let's search scoped to the implicit one if (location == null) location = defaultLocation.get(); - Predicate imagePredicate = buildImagePredicate(); - Iterable supportedImages = filter(images, imagePredicate); - if (size(supportedImages) == 0) { - if (imagePredicate == idPredicate) { - throwNoSuchElementExceptionAfterLoggingImageIds(format("%s not found", idPredicate), images); - } else { - throwNoSuchElementExceptionAfterLoggingImageIds(format("no image matched predicate: %s", imagePredicate), - images); - } + if (image == null) { + Iterable supportedImages = findSupportedImages(images); + if (hardware == null) + hardware = resolveHardware(hardwaresToSearch, supportedImages); + image = resolveImage(hardware, supportedImages); + } else { + if (hardware == null) + hardware = resolveHardware(hardwaresToSearch, ImmutableSet.of(image)); } - Hardware hardware = resolveHardware(hardwareSorter(), supportedImages); - Image image = resolveImage(hardware, supportedImages); - logger.debug("<< matched image(%s)", image.getId()); + logger.debug("<< matched image(%s) hardware(%s) location(%s)", image.getId(), hardware.getId(), + location.getId()); return new TemplateImpl(image, hardware, location, options); } - protected void throwNoSuchElementExceptionAfterLoggingImageIds(String message, Iterable images) { + private Iterable findSupportedImages(Set images) { + Predicate imagePredicate = buildImagePredicate(); + Iterable supportedImages = filter(images, imagePredicate); + if (size(supportedImages) == 0) { + throw throwNoSuchElementExceptionAfterLoggingImageIds( + format("no image matched predicate: %s", imagePredicate), images); + } + return supportedImages; + } + + private Image findImageWithId(Set images) { + Image image; + // TODO: switch to GetImageStrategy in version 1.5 + image = tryFind(images, idPredicate).orNull(); + if (image == null) + throwNoSuchElementExceptionAfterLoggingImageIds(format("%s not found", idPredicate), images); + return image; + } + + private Hardware findHardwareWithId(Set hardwaresToSearch) { + Hardware hardware; + // TODO: switch to GetHardwareStrategy in version 1.5 + hardware = tryFind(hardwaresToSearch, hardwareIdPredicate).orNull(); + if (hardware == null) + throw throwNoSuchElementExceptionAfterLoggingHardwareIds(format("%s not found", hardwareIdPredicate), + hardwaresToSearch); + return hardware; + } + + protected NoSuchElementException throwNoSuchElementExceptionAfterLoggingImageIds(String message, Iterable images) { NoSuchElementException exception = new NoSuchElementException(message); if (logger.isTraceEnabled()) logger.warn(exception, "image ids that didn't match: %s", transform(images, imageToId)); throw exception; } - protected Hardware resolveHardware(Ordering hardwareOrdering, final Iterable images) { - Set hardwarel = hardwares.get(); + protected NoSuchElementException throwNoSuchElementExceptionAfterLoggingHardwareIds(String message, Iterable hardwares) { + NoSuchElementException exception = new NoSuchElementException(message); + if (logger.isTraceEnabled()) + logger.warn(exception, "hardware ids that didn't match: %s", transform(hardwares, hardwareToId)); + throw exception; + } + + protected Hardware resolveHardware(Set hardwarel, final Iterable images) { + Ordering hardwareOrdering = hardwareSorter(); Iterable hardwaresThatAreCompatibleWithOurImages = ImmutableSet.of(); try { hardwaresThatAreCompatibleWithOurImages = filter(hardwarel, new Predicate() { @@ -665,11 +714,7 @@ public class TemplateBuilderImpl implements TemplateBuilder { } if (size(hardwaresThatAreCompatibleWithOurImages) == 0) { String message = format("no hardware profiles support images matching params: %s", toString()); - NoSuchElementException exception = new NoSuchElementException(message); - if (logger.isTraceEnabled()) - logger.warn(exception, "hardware profiles %s\nimage ids %s", transform(hardwarel, hardwareToId), transform( - images, imageToId)); - throw exception; + throw throwNoSuchElementExceptionAfterLoggingHardwareIds(message, hardwaresThatAreCompatibleWithOurImages); } Predicate hardwarePredicate = buildHardwarePredicate(); Hardware hardware; @@ -677,11 +722,7 @@ public class TemplateBuilderImpl implements TemplateBuilder { hardware = hardwareOrdering.max(filter(hardwaresThatAreCompatibleWithOurImages, hardwarePredicate)); } catch (NoSuchElementException exception) { String message = format("no hardware profiles match params: %s", hardwarePredicate); - exception = new NoSuchElementException(message); - if (logger.isTraceEnabled()) - logger.warn(exception, "hardware profiles %s", transform(hardwaresThatAreCompatibleWithOurImages, - hardwareToId)); - throw exception; + throw throwNoSuchElementExceptionAfterLoggingHardwareIds(message, hardwaresThatAreCompatibleWithOurImages); } logger.debug("<< matched hardware(%s)", hardware.getId()); return hardware; @@ -739,59 +780,55 @@ public class TemplateBuilderImpl implements TemplateBuilder { private Predicate buildImagePredicate() { List> predicates = newArrayList(); - if (imageId != null) { - predicates.add(idPredicate); - } else { - if (location != null) - predicates.add(new Predicate() { + if (location != null) + predicates.add(new Predicate() { - @Override - public boolean apply(Image input) { - return locationPredicate.apply(input); - } + @Override + public boolean apply(Image input) { + return locationPredicate.apply(input); + } - @Override - public String toString() { - return locationPredicate.toString(); - } - }); + @Override + public String toString() { + return locationPredicate.toString(); + } + }); - final List> osPredicates = newArrayList(); - if (osFamily != null) - osPredicates.add(osFamilyPredicate); - if (osName != null) - osPredicates.add(osNamePredicate); - if (osDescription != null) - osPredicates.add(osDescriptionPredicate); - if (osVersion != null) - osPredicates.add(osVersionPredicate); - if (os64Bit != null) - osPredicates.add(os64BitPredicate); - if (osArch != null) - osPredicates.add(osArchPredicate); - if (osPredicates.size() > 0) - predicates.add(new Predicate() { + final List> osPredicates = newArrayList(); + if (osFamily != null) + osPredicates.add(osFamilyPredicate); + if (osName != null) + osPredicates.add(osNamePredicate); + if (osDescription != null) + osPredicates.add(osDescriptionPredicate); + if (osVersion != null) + osPredicates.add(osVersionPredicate); + if (os64Bit != null) + osPredicates.add(os64BitPredicate); + if (osArch != null) + osPredicates.add(osArchPredicate); + if (osPredicates.size() > 0) + predicates.add(new Predicate() { - @Override - public boolean apply(Image input) { - return and(osPredicates).apply(input.getOperatingSystem()); - } + @Override + public boolean apply(Image input) { + return and(osPredicates).apply(input.getOperatingSystem()); + } - @Override - public String toString() { - return and(osPredicates).toString(); - } + @Override + public String toString() { + return and(osPredicates).toString(); + } - }); - if (imageVersion != null) - predicates.add(imageVersionPredicate); - if (imageName != null) - predicates.add(imageNamePredicate); - if (imageDescription != null) - predicates.add(imageDescriptionPredicate); - if (imagePredicate != null) - predicates.add(imagePredicate); - } + }); + if (imageVersion != null) + predicates.add(imageVersionPredicate); + if (imageName != null) + predicates.add(imageNamePredicate); + if (imageDescription != null) + predicates.add(imageDescriptionPredicate); + if (imagePredicate != null) + predicates.add(imagePredicate); // looks verbose, but explicit type needed for this to compile // properly diff --git a/compute/src/test/java/org/jclouds/compute/domain/internal/TemplateBuilderImplTest.java b/compute/src/test/java/org/jclouds/compute/domain/internal/TemplateBuilderImplTest.java index 992e49f9e5..48680d2682 100644 --- a/compute/src/test/java/org/jclouds/compute/domain/internal/TemplateBuilderImplTest.java +++ b/compute/src/test/java/org/jclouds/compute/domain/internal/TemplateBuilderImplTest.java @@ -62,6 +62,9 @@ public class TemplateBuilderImplTest { protected Location region = new LocationBuilder().scope(LocationScope.REGION).id("us-east-1").description("us-east-1") .parent(provider).build(); + protected Location region2 = new LocationBuilder().scope(LocationScope.REGION).id("us-east-2").description("us-east-2") + .parent(provider).build(); + @SuppressWarnings("unchecked") public void testLocationPredicateWhenComputeMetadataIsNotLocationBound() { Image image = createMock(Image.class); @@ -851,4 +854,53 @@ public class TemplateBuilderImplTest { assertEquals(template.getImage().getId(), "Ubuntu 11.04 64-bit"); } + + + @Test + public void testImageLocationNonDefault() { + + final Supplier> locations = Suppliers.> ofInstance(ImmutableSet + . of(region)); + final Supplier> images = Suppliers.> ofInstance(ImmutableSet + . of( + new ImageBuilder() + .id("us-east-2/ami-ffff") + .providerId("ami-ffff") + .name("Ubuntu 11.04 x64") + .description("Ubuntu 11.04 x64") + .location(region2) + .operatingSystem( + OperatingSystem.builder().name("Ubuntu 11.04 x64").description("Ubuntu 11.04 x64") + .is64Bit(true).version("11.04").family(OsFamily.UBUNTU).build()).build())); + + final Supplier> hardwares = Suppliers.> ofInstance(ImmutableSet + . of( + new HardwareBuilder() + .ids("m1.small").ram(512) + .processors(ImmutableList.of(new Processor(1, 1.0))) + .volumes(ImmutableList. of(new VolumeImpl((float) 5, true, true))).build())); + + final Provider optionsProvider = new Provider() { + + @Override + public TemplateOptions get() { + return new TemplateOptions(); + } + + }; + Provider templateBuilderProvider = new Provider() { + + @Override + public TemplateBuilder get() { + return createTemplateBuilder(null, locations, images, hardwares, region, optionsProvider, this); + } + + }; + + TemplateBuilder templateBuilder = templateBuilderProvider.get().hardwareId("m1.small").imageId("us-east-2/ami-ffff"); + + Template template = templateBuilder.build(); + assertEquals(template.getLocation().getId(), "us-east-2"); + + } }