JCLOUDS-482: Add support for arbitrary CPU and RAM This is a combination of 16 commits:
* First approach to ArbitraryCpuRamTemplateBuilderImpl * Several fixes: refactoring some names, format, identation problems, some missing license headers and generateId method * Refactored parse utility * Added GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl to support GCE custom machine URI * extracted hardware creation to automaticHardwareForCpuAndRam method * Fixed ide automatic asterisk imports * correcting WIP base case PR according to comments * added machineTypeUriToHardware to set custom hardware in nodes * fix checkstyle violations and other PR comments * Set the providerId to custom machineType URI and fix adding node log * Arbitrary hardware tests added to BaseTemplateBuilderLiveTest and GoogleComputeEngineTemplateBuilderLiveTest * Added two more tests to BaseTemplateBuilderLiveTest * Move repeated constants to TestUtils to reuse code * Fix full path in the Hardware id and URI * Add custom hardware tests to BaseComputeServiceLiveTest and GCEServiceLiveTest * Change customHardware test to use buildTemplate and fix identation Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/300261b2 Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/300261b2 Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/300261b2 Branch: refs/heads/gsoc2016-ivan Commit: 300261b248e1b60bbb6d192821cb5580899c4716 Parents: 80ec2aa Author: Iván Lomba <[email protected]> Authored: Sat Jun 18 20:27:12 2016 +0200 Committer: Ignasi Barrera <[email protected]> Committed: Wed Aug 10 21:35:03 2016 +0200 ---------------------------------------------------------------------- .../filesystem/FilesystemBlobStoreTest.java | 6 +- .../FilesystemContainerIntegrationTest.java | 10 +- .../FilesystemStorageStrategyImplTest.java | 6 +- .../org/jclouds/filesystem/utils/TestUtils.java | 3 - .../oauth/v2/AuthorizationApiLiveTest.java | 8 +- .../org/jclouds/oauth/v2/OAuthTestUtils.java | 3 - .../ArbitraryCpuRamTemplateBuilderImpl.java | 84 ++++++ .../domain/internal/TemplateBuilderImpl.java | 83 +++--- ...desWithGroupEncodedIntoNameThenAddToSet.java | 4 +- .../compute/util/AutomaticHardwareIdSpec.java | 72 +++++ .../ArbitraryCpuRamTemplateBuilderImplTest.java | 275 ++++++++++++++++++ .../internal/BaseComputeServiceLiveTest.java | 25 ++ .../internal/BaseTemplateBuilderLiveTest.java | 103 +++++++ .../util/AutomaticHardwareIdSpecTest.java | 52 ++++ .../test/java/org/jclouds/utils/TestUtils.java | 3 + ...GoogleComputeEngineServiceContextModule.java | 4 + ...ngineArbitraryCpuRamTemplateBuilderImpl.java | 59 ++++ .../functions/InstanceToNodeMetadata.java | 46 ++- .../GoogleComputeEngineServiceLiveTest.java | 23 +- ...gleComputeEngineTemplateBuilderLiveTest.java | 15 + ...eArbitraryCpuRamTemplateBuilderImplTest.java | 278 +++++++++++++++++++ .../functions/InstanceToNodeMetadataTest.java | 39 ++- 22 files changed, 1123 insertions(+), 78 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/apis/filesystem/src/test/java/org/jclouds/filesystem/FilesystemBlobStoreTest.java ---------------------------------------------------------------------- diff --git a/apis/filesystem/src/test/java/org/jclouds/filesystem/FilesystemBlobStoreTest.java b/apis/filesystem/src/test/java/org/jclouds/filesystem/FilesystemBlobStoreTest.java index 88704e3..d27924f 100644 --- a/apis/filesystem/src/test/java/org/jclouds/filesystem/FilesystemBlobStoreTest.java +++ b/apis/filesystem/src/test/java/org/jclouds/filesystem/FilesystemBlobStoreTest.java @@ -18,6 +18,8 @@ package org.jclouds.filesystem; import static com.google.common.io.BaseEncoding.base16; import static org.jclouds.filesystem.util.Utils.isMacOSX; +import static org.jclouds.utils.TestUtils.NO_INVOCATIONS; +import static org.jclouds.utils.TestUtils.SINGLE_NO_ARG_INVOCATION; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; @@ -912,7 +914,7 @@ public class FilesystemBlobStoreTest { @DataProvider public Object[][] ignoreOnMacOSX() { - return isMacOSX() ? TestUtils.NO_INVOCATIONS - : TestUtils.SINGLE_NO_ARG_INVOCATION; + return isMacOSX() ? NO_INVOCATIONS + : SINGLE_NO_ARG_INVOCATION; } } http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/apis/filesystem/src/test/java/org/jclouds/filesystem/integration/FilesystemContainerIntegrationTest.java ---------------------------------------------------------------------- diff --git a/apis/filesystem/src/test/java/org/jclouds/filesystem/integration/FilesystemContainerIntegrationTest.java b/apis/filesystem/src/test/java/org/jclouds/filesystem/integration/FilesystemContainerIntegrationTest.java index 7a701a0..7dfdd3a 100644 --- a/apis/filesystem/src/test/java/org/jclouds/filesystem/integration/FilesystemContainerIntegrationTest.java +++ b/apis/filesystem/src/test/java/org/jclouds/filesystem/integration/FilesystemContainerIntegrationTest.java @@ -19,6 +19,8 @@ package org.jclouds.filesystem.integration; import static org.jclouds.blobstore.options.ListContainerOptions.Builder.maxResults; import static org.jclouds.filesystem.util.Utils.isMacOSX; import static org.testng.Assert.assertEquals; +import static org.jclouds.utils.TestUtils.NO_INVOCATIONS; +import static org.jclouds.utils.TestUtils.SINGLE_NO_ARG_INVOCATION; import java.io.IOException; import java.util.Properties; @@ -165,14 +167,14 @@ public class FilesystemContainerIntegrationTest extends BaseContainerIntegration @DataProvider public Object[][] ignoreOnMacOSX() { - return isMacOSX() ? TestUtils.NO_INVOCATIONS - : TestUtils.SINGLE_NO_ARG_INVOCATION; + return isMacOSX() ? NO_INVOCATIONS + : SINGLE_NO_ARG_INVOCATION; } @DataProvider public Object[][] ignoreOnWindows() { - return TestUtils.isWindowsOs() ? TestUtils.NO_INVOCATIONS - : TestUtils.SINGLE_NO_ARG_INVOCATION; + return TestUtils.isWindowsOs() ? NO_INVOCATIONS + : SINGLE_NO_ARG_INVOCATION; } @Override http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/apis/filesystem/src/test/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImplTest.java ---------------------------------------------------------------------- diff --git a/apis/filesystem/src/test/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImplTest.java b/apis/filesystem/src/test/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImplTest.java index 3fdd855..9079fa0 100644 --- a/apis/filesystem/src/test/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImplTest.java +++ b/apis/filesystem/src/test/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImplTest.java @@ -17,6 +17,8 @@ package org.jclouds.filesystem.strategy.internal; import static org.jclouds.filesystem.util.Utils.isMacOSX; +import static org.jclouds.utils.TestUtils.NO_INVOCATIONS; +import static org.jclouds.utils.TestUtils.SINGLE_NO_ARG_INVOCATION; import static org.jclouds.utils.TestUtils.randomByteSource; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; @@ -699,7 +701,7 @@ public class FilesystemStorageStrategyImplTest { @DataProvider public Object[][] ignoreOnMacOSX() { - return isMacOSX() ? TestUtils.NO_INVOCATIONS - : TestUtils.SINGLE_NO_ARG_INVOCATION; + return isMacOSX() ? NO_INVOCATIONS + : SINGLE_NO_ARG_INVOCATION; } } http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/apis/filesystem/src/test/java/org/jclouds/filesystem/utils/TestUtils.java ---------------------------------------------------------------------- diff --git a/apis/filesystem/src/test/java/org/jclouds/filesystem/utils/TestUtils.java b/apis/filesystem/src/test/java/org/jclouds/filesystem/utils/TestUtils.java index cd0276c..224c21e 100644 --- a/apis/filesystem/src/test/java/org/jclouds/filesystem/utils/TestUtils.java +++ b/apis/filesystem/src/test/java/org/jclouds/filesystem/utils/TestUtils.java @@ -54,9 +54,6 @@ public class TestUtils { private static final Iterator<File> IMAGE_RESOURCES_ITERATOR = Iterators.cycle(IMAGE_RESOURCES); - public static final Object[][] NO_INVOCATIONS = new Object[0][0]; - public static final Object[][] SINGLE_NO_ARG_INVOCATION = { new Object[0] }; - /** * Generate a random blob key simple name (with no path in the key) * @return http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/apis/oauth/src/test/java/org/jclouds/oauth/v2/AuthorizationApiLiveTest.java ---------------------------------------------------------------------- diff --git a/apis/oauth/src/test/java/org/jclouds/oauth/v2/AuthorizationApiLiveTest.java b/apis/oauth/src/test/java/org/jclouds/oauth/v2/AuthorizationApiLiveTest.java index 5d0d7cf..0aba641 100644 --- a/apis/oauth/src/test/java/org/jclouds/oauth/v2/AuthorizationApiLiveTest.java +++ b/apis/oauth/src/test/java/org/jclouds/oauth/v2/AuthorizationApiLiveTest.java @@ -24,6 +24,8 @@ import static org.jclouds.oauth.v2.config.OAuthProperties.AUDIENCE; import static org.jclouds.oauth.v2.config.OAuthProperties.CERTIFICATE; import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE; import static org.jclouds.providers.AnonymousProviderMetadata.forApiOnEndpoint; +import static org.jclouds.utils.TestUtils.NO_INVOCATIONS; +import static org.jclouds.utils.TestUtils.SINGLE_NO_ARG_INVOCATION; import static org.testng.Assert.assertNotNull; import java.util.Properties; @@ -63,19 +65,19 @@ public class AuthorizationApiLiveTest extends BaseApiLiveTest<AuthorizationApi> @DataProvider public Object[][] onlyRunForP12PrivateKeyCredentials() { return (CredentialType.fromValue(credentialType) == CredentialType.P12_PRIVATE_KEY_CREDENTIALS) ? - OAuthTestUtils.SINGLE_NO_ARG_INVOCATION : OAuthTestUtils.NO_INVOCATIONS; + SINGLE_NO_ARG_INVOCATION : NO_INVOCATIONS; } @DataProvider public Object[][] onlyRunForClientCredentialsSecret() { return (CredentialType.fromValue(credentialType) == CredentialType.CLIENT_CREDENTIALS_SECRET) ? - OAuthTestUtils.SINGLE_NO_ARG_INVOCATION : OAuthTestUtils.NO_INVOCATIONS; + SINGLE_NO_ARG_INVOCATION : NO_INVOCATIONS; } @DataProvider public Object[][] onlyRunForClientCredentialsP12() { return (CredentialType.fromValue(credentialType) == CredentialType.CLIENT_CREDENTIALS_P12_AND_CERTIFICATE) ? - OAuthTestUtils.SINGLE_NO_ARG_INVOCATION : OAuthTestUtils.NO_INVOCATIONS; + SINGLE_NO_ARG_INVOCATION : NO_INVOCATIONS; } @Test(dataProvider = "onlyRunForP12PrivateKeyCredentials") http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/apis/oauth/src/test/java/org/jclouds/oauth/v2/OAuthTestUtils.java ---------------------------------------------------------------------- diff --git a/apis/oauth/src/test/java/org/jclouds/oauth/v2/OAuthTestUtils.java b/apis/oauth/src/test/java/org/jclouds/oauth/v2/OAuthTestUtils.java index d15f8b0..920ff18 100644 --- a/apis/oauth/src/test/java/org/jclouds/oauth/v2/OAuthTestUtils.java +++ b/apis/oauth/src/test/java/org/jclouds/oauth/v2/OAuthTestUtils.java @@ -32,9 +32,6 @@ import com.google.common.io.Files; public class OAuthTestUtils { - public static final Object[][] NO_INVOCATIONS = new Object[0][0]; - public static final Object[][] SINGLE_NO_ARG_INVOCATION = { new Object[0] }; - public static Properties defaultProperties(Properties properties) { try { properties = properties == null ? new Properties() : properties; http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/compute/src/main/java/org/jclouds/compute/domain/internal/ArbitraryCpuRamTemplateBuilderImpl.java ---------------------------------------------------------------------- diff --git a/compute/src/main/java/org/jclouds/compute/domain/internal/ArbitraryCpuRamTemplateBuilderImpl.java b/compute/src/main/java/org/jclouds/compute/domain/internal/ArbitraryCpuRamTemplateBuilderImpl.java new file mode 100644 index 0000000..f99b991 --- /dev/null +++ b/compute/src/main/java/org/jclouds/compute/domain/internal/ArbitraryCpuRamTemplateBuilderImpl.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.compute.domain.internal; + +import com.google.common.base.Supplier; +import org.jclouds.collect.Memoized; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.compute.util.AutomaticHardwareIdSpec; +import org.jclouds.domain.Location; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; +import java.util.NoSuchElementException; +import java.util.Set; + +import static org.jclouds.compute.util.AutomaticHardwareIdSpec.automaticHardwareIdSpecBuilder; +import static org.jclouds.compute.util.AutomaticHardwareIdSpec.isAutomaticId; +import static org.jclouds.compute.util.AutomaticHardwareIdSpec.parseId; + +public class ArbitraryCpuRamTemplateBuilderImpl extends TemplateBuilderImpl { + @Inject + protected ArbitraryCpuRamTemplateBuilderImpl(@Memoized Supplier<Set<? extends Location>> locations, + @Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> hardwares, + Supplier<Location> defaultLocation, @Named("DEFAULT") Provider<TemplateOptions> optionsProvider, + @Named("DEFAULT") Provider<TemplateBuilder> defaultTemplateProvider) { + super(locations, images, hardwares, defaultLocation, optionsProvider, defaultTemplateProvider); + } + + protected Hardware automaticHardwareForCpuAndRam(double cores, int ram) { + return new HardwareBuilder() + .id(automaticHardwareIdSpecBuilder(cores, ram).toString()) + .ram(ram) + .processor(new Processor(cores, 1.0)) + .build(); + } + + protected Hardware findHardwareWithId(Set<? extends Hardware> hardwaresToSearch) { + try { + return super.findHardwareWithId(hardwaresToSearch); + } catch (NoSuchElementException ex) { + if (isAutomaticId(hardwareId)) { + AutomaticHardwareIdSpec spec = parseId(hardwareId); + return automaticHardwareForCpuAndRam(spec.getCores(), spec.getRam()); + } + else { + throw ex; + } + } + } + + protected Hardware resolveHardware(Set<? extends Hardware> hardwarel, final Iterable<? extends Image> images) { + try { + return super.resolveHardware(hardwarel, images); + } + catch (NoSuchElementException ex) { + if (super.minCores != 0 && super.minRam != 0) { + return automaticHardwareForCpuAndRam(minCores, minRam); + } + else throw new IllegalArgumentException("No hardware profile matching the given criteria was found. If " + + "you want to use exact values, please set the minCores and minRam values", ex); + } + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java ---------------------------------------------------------------------- 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 2865409..f860674 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 @@ -16,33 +16,20 @@ */ package org.jclouds.compute.domain.internal; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; -import static com.google.common.base.Predicates.and; -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; -import static org.jclouds.compute.util.ComputeServiceUtils.getCoresAndSpeed; -import static org.jclouds.compute.util.ComputeServiceUtils.getSpace; - -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Set; -import java.util.regex.Pattern; - -import javax.annotation.Resource; -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Provider; - +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.base.Supplier; +import com.google.common.collect.ComparisonChain; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Ordering; +import com.google.common.primitives.Doubles; import org.jclouds.collect.Memoized; import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.Hardware; @@ -59,20 +46,31 @@ import org.jclouds.compute.suppliers.ImageCacheSupplier; import org.jclouds.domain.Location; import org.jclouds.logging.Logger; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Function; -import com.google.common.base.Objects; -import com.google.common.base.Objects.ToStringHelper; -import com.google.common.base.Optional; -import com.google.common.base.Predicate; -import com.google.common.base.Predicates; -import com.google.common.base.Supplier; -import com.google.common.collect.ComparisonChain; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; -import com.google.common.collect.Ordering; -import com.google.common.primitives.Doubles; +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.regex.Pattern; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Predicates.and; +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; +import static org.jclouds.compute.util.ComputeServiceUtils.getCoresAndSpeed; +import static org.jclouds.compute.util.ComputeServiceUtils.getSpace; public class TemplateBuilderImpl implements TemplateBuilder { @Resource @@ -348,7 +346,6 @@ public class TemplateBuilderImpl implements TemplateBuilder { return "imageDescription(" + imageDescription + ")"; } }; - private final Predicate<Hardware> hardwareIdPredicate = new Predicate<Hardware>() { @Override public boolean apply(Hardware input) { @@ -727,7 +724,7 @@ public class TemplateBuilderImpl implements TemplateBuilder { return image.get(); } - private Hardware findHardwareWithId(Set<? extends Hardware> hardwaresToSearch) { + protected Hardware findHardwareWithId(Set<? extends Hardware> hardwaresToSearch) { Hardware hardware; // TODO: switch to GetHardwareStrategy in version 1.5 hardware = tryFind(hardwaresToSearch, hardwareIdPredicate).orNull(); http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/compute/src/main/java/org/jclouds/compute/strategy/impl/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java ---------------------------------------------------------------------- diff --git a/compute/src/main/java/org/jclouds/compute/strategy/impl/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java b/compute/src/main/java/org/jclouds/compute/strategy/impl/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java index e7f3384..6ac36c7 100644 --- a/compute/src/main/java/org/jclouds/compute/strategy/impl/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java +++ b/compute/src/main/java/org/jclouds/compute/strategy/impl/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java @@ -33,6 +33,7 @@ import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; +import com.google.common.base.Objects; import org.jclouds.Constants; import org.jclouds.compute.config.CustomizationResponse; import org.jclouds.compute.domain.ComputeMetadata; @@ -75,7 +76,8 @@ public class CreateNodesWithGroupEncodedIntoNameThenAddToSet implements CreateNo public AtomicReference<NodeMetadata> call() throws Exception { NodeMetadata node = null; logger.debug(">> adding node location(%s) name(%s) image(%s) hardware(%s)", template.getLocation().getId(), - name, template.getImage().getProviderId(), template.getHardware().getProviderId()); + name, Objects.firstNonNull(template.getImage().getProviderId(), template.getImage().getId()), + Objects.firstNonNull(template.getHardware().getProviderId(), template.getHardware().getId())); node = addNodeWithGroupStrategy.createNodeWithGroupEncodedIntoName(group, name, template); logger.debug("<< %s node(%s)", formatStatus(node), node.getId()); return new AtomicReference<NodeMetadata>(node); http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/compute/src/main/java/org/jclouds/compute/util/AutomaticHardwareIdSpec.java ---------------------------------------------------------------------- diff --git a/compute/src/main/java/org/jclouds/compute/util/AutomaticHardwareIdSpec.java b/compute/src/main/java/org/jclouds/compute/util/AutomaticHardwareIdSpec.java new file mode 100644 index 0000000..6aaa44a --- /dev/null +++ b/compute/src/main/java/org/jclouds/compute/util/AutomaticHardwareIdSpec.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.compute.util; + +import com.google.common.base.Splitter; + +import java.util.Map; + +public class AutomaticHardwareIdSpec { + + private double cores; + private int ram; + + public static boolean isAutomaticId(String id) { + return id.startsWith("automatic:"); + } + + public static AutomaticHardwareIdSpec parseId(String hardwareId) { + AutomaticHardwareIdSpec spec = new AutomaticHardwareIdSpec(); + String hardwareSpec = hardwareId.substring(10); + Map<String, String> specValues = Splitter.on(';') + .trimResults() + .omitEmptyStrings() + .withKeyValueSeparator('=') + .split(hardwareSpec); + if (!specValues.containsKey("ram") || !specValues.containsKey("cores")) { + throw new IllegalArgumentException(String.format("Omitted keys on hardwareId: %s. Please set number " + + "of cores and ram amount.", hardwareId)); + } + spec.ram = Integer.parseInt(specValues.get("ram")); + spec.cores = Double.parseDouble(specValues.get("cores")); + return spec; + } + + public static AutomaticHardwareIdSpec automaticHardwareIdSpecBuilder(double cores, int ram) { + AutomaticHardwareIdSpec spec = new AutomaticHardwareIdSpec(); + if (cores == 0 || ram == 0) { + throw new IllegalArgumentException(String.format("Omitted or wrong minCores and minRam. If you" + + " want to use exact values, please set the minCores and minRam values.")); + } + spec.cores = cores; + spec.ram = ram; + return spec; + } + + @Override + public String toString() { + return String.format("automatic:cores=%s;ram=%s", cores, ram); + } + + public double getCores() { + return cores; + } + + public int getRam() { + return ram; + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/compute/src/test/java/org/jclouds/compute/domain/internal/ArbitraryCpuRamTemplateBuilderImplTest.java ---------------------------------------------------------------------- diff --git a/compute/src/test/java/org/jclouds/compute/domain/internal/ArbitraryCpuRamTemplateBuilderImplTest.java b/compute/src/test/java/org/jclouds/compute/domain/internal/ArbitraryCpuRamTemplateBuilderImplTest.java new file mode 100644 index 0000000..568a60b --- /dev/null +++ b/compute/src/test/java/org/jclouds/compute/domain/internal/ArbitraryCpuRamTemplateBuilderImplTest.java @@ -0,0 +1,275 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.compute.domain.internal; + +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.collect.ImmutableSet; +import com.google.common.util.concurrent.Atomics; +import com.google.inject.Provider; +import com.google.inject.util.Providers; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.ImageBuilder; +import org.jclouds.compute.domain.OperatingSystem; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.Template; +import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.compute.strategy.GetImageStrategy; +import org.jclouds.compute.suppliers.ImageCacheSupplier; +import org.jclouds.domain.Location; +import org.jclouds.domain.LocationBuilder; +import org.jclouds.domain.LocationScope; +import org.jclouds.rest.AuthorizationException; +import org.testng.annotations.Test; + +import java.net.URI; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; + +@Test(groups = "unit", singleThreaded = true, testName = "ArbitraryCpuRamTemplateBuilderImplTest") +public class ArbitraryCpuRamTemplateBuilderImplTest { + private Location provider = new LocationBuilder() + .scope(LocationScope.PROVIDER) + .id("generic-provider") + .description("generic-provider") + .build(); + + private Location region = new LocationBuilder() + .scope(LocationScope.REGION) + .id("us-east-1") + .description("us-east-1") + .parent(provider) + .build(); + + private OperatingSystem os = OperatingSystem.builder() + .name("osName") + .version("osVersion") + .description("osDescription") + .arch("X86_32") + .build(); + + private Image image = new ImageBuilder() + .id("imageId") + .providerId("imageId") + .name("imageName") + .description("imageDescription") + .version("imageVersion") + .operatingSystem(os) + .status(Image.Status.AVAILABLE) + .location(null) + .build(); + + private Hardware hardware = new HardwareBuilder() + .ram(2048) + .processor(new Processor(2, 1)) + .id("hardwareId") + .name("hardwareName") + .location(region) + .uri(URI.create("uri")) + .build(); + + private final String errorMessage = "No hardware profile matching the given criteria was found. " + + "If you want to use exact values, please set the minCores and minRam values"; + + @Test + public void testAutoGeneratedHardwareFromId(){ + Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet + .of(region)); + Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet.of(image)); + Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet + .<Hardware> of(hardware)); + Provider<TemplateOptions> optionsProvider = createMock(Provider.class); + Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + + TemplateBuilderImpl templateBuilder = new ArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.<AuthorizationException>newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), + optionsProvider, templateBuilderProvider); + + Hardware hardware = templateBuilder.hardwareId("automatic:cores=2;ram=256").build().getHardware(); + assertThat(hardware.getRam()).isEqualTo(256); + assertThat(hardware.getProcessors()).extracting("cores").containsExactly(2.0); + assertThat(hardware.getId()).isEqualTo("automatic:cores=2.0;ram=256"); + } + + @Test + public void testAutoGeneratedHardwareWithMinCoresAndMinRam(){ + Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet.of(region)); + Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet.of(image)); + Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet + .<Hardware> of(hardware)); + Provider<TemplateOptions> optionsProvider = createMock(Provider.class); + Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new ArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.<AuthorizationException>newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minRam(1024); + templateBuilder.minCores(4); + Template template = templateBuilder.build(); + Hardware hardware = template.getHardware(); + assertThat(hardware.getRam()).isEqualTo(1024); + assertThat(hardware.getProcessors()).extracting("cores").containsExactly(4.0); + assertThat(hardware.getId()).isEqualTo("automatic:cores=4.0;ram=1024"); + } + + @Test + public void testExistingHardwareProfileMatchHardwareProfileWithMinCoresMinRam() { + Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet + .of(region)); + Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet.of(image)); + Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet + .<Hardware> of(hardware)); + Provider<TemplateOptions> optionsProvider = createMock(Provider.class); + Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new ArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.<AuthorizationException>newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minCores(2); + templateBuilder.minRam(1024); + Template template = templateBuilder.build(); + Hardware hardware = template.getHardware(); + assertThat(hardware.getRam()).isEqualTo(2048); + assertThat(hardware.getProcessors()).extracting("cores").containsExactly(2.0); + assertThat(hardware.getId()).isEqualTo("hardwareId"); + } + + @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = errorMessage) + public void testOnlyRamTest() { + Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet.of(region)); + Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet.of(image)); + Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet + .<Hardware> of(hardware)); + Provider<TemplateOptions> optionsProvider = createMock(Provider.class); + Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new ArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.<AuthorizationException>newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minRam(4096); + templateBuilder.build(); + } + + @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = errorMessage) + public void testOnlyCoresTest() { + Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet + .of(region)); + Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet.of(image)); + Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet + .<Hardware> of(hardware)); + Provider<TemplateOptions> optionsProvider = createMock(Provider.class); + Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new ArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.<AuthorizationException>newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minCores(4); + templateBuilder.build(); + } + + @Test + public void testOnlyRamMatchHardwareProfileTest() { + Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet.of(region)); + Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet.of(image)); + Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet + .<Hardware> of(hardware)); + Provider<TemplateOptions> optionsProvider = createMock(Provider.class); + Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new ArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.<AuthorizationException>newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minRam(1024); + templateBuilder.build(); + assertThat(hardware.getRam()).isEqualTo(2048); + assertThat(hardware.getProcessors()).extracting("cores").containsExactly(2.0); + assertThat(hardware.getId()).isEqualTo("hardwareId"); + } + + @Test + public void testOnlyCoresMatchHardwareProfileTest() { + Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet + .of(region)); + Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet.of(image)); + Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet + .<Hardware> of(hardware)); + Provider<TemplateOptions> optionsProvider = createMock(Provider.class); + Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new ArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.<AuthorizationException>newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minCores(1); + templateBuilder.build(); + assertThat(hardware.getRam()).isEqualTo(2048); + assertThat(hardware.getProcessors()).extracting("cores").containsExactly(2.0); + assertThat(hardware.getId()).isEqualTo("hardwareId"); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java ---------------------------------------------------------------------- diff --git a/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java b/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java index 5db3d32..b53412a 100644 --- a/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java +++ b/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java @@ -33,6 +33,7 @@ import static java.lang.String.format; import static java.lang.System.currentTimeMillis; import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.logging.Logger.getAnonymousLogger; +import static org.assertj.core.api.Assertions.assertThat; import static org.jclouds.Constants.PROPERTY_USER_THREADS; import static org.jclouds.compute.options.RunScriptOptions.Builder.nameTask; import static org.jclouds.compute.options.RunScriptOptions.Builder.wrapInInitScript; @@ -44,6 +45,8 @@ import static org.jclouds.compute.predicates.NodePredicates.inGroup; import static org.jclouds.compute.predicates.NodePredicates.runningInGroup; import static org.jclouds.compute.util.ComputeServiceUtils.getCores; import static org.jclouds.util.Predicates2.retry; +import static org.jclouds.utils.TestUtils.NO_INVOCATIONS; +import static org.jclouds.utils.TestUtils.SINGLE_NO_ARG_INVOCATION; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; @@ -81,6 +84,7 @@ import org.jclouds.compute.domain.NodeMetadata.Status; import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.compute.domain.internal.ArbitraryCpuRamTemplateBuilderImpl; import org.jclouds.compute.util.OpenSocketFinder; import org.jclouds.domain.Credentials; import org.jclouds.domain.Location; @@ -96,6 +100,7 @@ import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshException; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeGroups; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import com.google.common.base.Function; @@ -937,6 +942,26 @@ public abstract class BaseComputeServiceLiveTest extends BaseComputeServiceConte } } + @DataProvider + public Object[][] onlyIfAutomaticHardwareSupported() { + return client.templateBuilder() instanceof ArbitraryCpuRamTemplateBuilderImpl ? + SINGLE_NO_ARG_INVOCATION : NO_INVOCATIONS; + } + + @Test(dataProvider = "onlyIfAutomaticHardwareSupported", groups = {"integration", "live"}) + public void testCreateNodeWithCustomHardware() throws Exception { + Template template = buildTemplate(templateBuilder() + .hardwareId("automatic:cores=2;ram=4096")); + try { + NodeMetadata node = getOnlyElement(client.createNodesInGroup("custom", 1, template)); + assertThat(node.getHardware().getRam()).isEqualTo(4096); + assertThat(node.getHardware().getProcessors().get(0).getCores()).isEqualTo(2); + } + finally { + client.destroyNodesMatching(inGroup("custom")); + } + } + @AfterClass(groups = { "integration", "live" }) @Override protected void tearDownContext() { http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/compute/src/test/java/org/jclouds/compute/internal/BaseTemplateBuilderLiveTest.java ---------------------------------------------------------------------- diff --git a/compute/src/test/java/org/jclouds/compute/internal/BaseTemplateBuilderLiveTest.java b/compute/src/test/java/org/jclouds/compute/internal/BaseTemplateBuilderLiveTest.java index 29b543f..5e27d5a 100644 --- a/compute/src/test/java/org/jclouds/compute/internal/BaseTemplateBuilderLiveTest.java +++ b/compute/src/test/java/org/jclouds/compute/internal/BaseTemplateBuilderLiveTest.java @@ -16,7 +16,10 @@ */ package org.jclouds.compute.internal; +import static org.assertj.core.api.Assertions.assertThat; import static org.jclouds.compute.util.ComputeServiceUtils.getCores; +import static org.jclouds.utils.TestUtils.NO_INVOCATIONS; +import static org.jclouds.utils.TestUtils.SINGLE_NO_ARG_INVOCATION; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; @@ -29,10 +32,14 @@ import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.Template; +import org.jclouds.compute.domain.internal.ArbitraryCpuRamTemplateBuilderImpl; +import org.jclouds.compute.util.AutomaticHardwareIdSpec; import org.jclouds.domain.Location; import org.jclouds.domain.LocationScope; import org.jclouds.domain.LoginCredentials; import org.jclouds.rest.config.CredentialStoreModule; +import org.testng.SkipException; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import com.google.common.base.Splitter; @@ -225,4 +232,100 @@ public abstract class BaseTemplateBuilderLiveTest extends BaseComputeServiceCont assertTrue(actual.getLocation().getScope().compareTo(expected.getLocation().getScope()) <= 0); } + @DataProvider + public Object[][] onlyIfAutomaticHardwareSupported() { + return view.getComputeService().templateBuilder() instanceof ArbitraryCpuRamTemplateBuilderImpl ? + SINGLE_NO_ARG_INVOCATION : NO_INVOCATIONS; + } + + @Test(dataProvider = "onlyIfAutomaticHardwareSupported", groups = {"integration", "live"}) + public void testAutoGeneratedHardwareFromId() { + Template template = view.getComputeService().templateBuilder() + .hardwareId("automatic:cores=2;ram=1024").build(); + assertThat(template.getHardware().getId()).isEqualTo("automatic:cores=2;ram=1024"); + assertThat(template.getHardware().getRam()).isEqualTo(1024); + assertThat(template.getHardware().getProcessors().get(0).getCores()).isEqualTo(2); + } + + @Test(dataProvider = "onlyIfAutomaticHardwareSupported", groups = {"integration", "live"}) + public void testAutoGeneratedHardwareMatchHardwareProfile() { + if (!view.getComputeService().listHardwareProfiles().isEmpty()) { + Template template = view.getComputeService().templateBuilder() + .minRam(2048).minCores(2).build(); + assertThat(AutomaticHardwareIdSpec.isAutomaticId(template.getHardware().getId())).isFalse(); + assertThat(template.getHardware().getRam()).isGreaterThanOrEqualTo(2048); + assertThat(template.getHardware().getProcessors().get(0).getCores()).isGreaterThanOrEqualTo(2); + } + else { + throw new SkipException("Hardware profile list is empty, this provider can not match any hardware profile" + + "to the specified minRam and minCores."); + } + } + + @Test(dataProvider = "onlyIfAutomaticHardwareSupported", groups = {"integration", "live"}) + public void testAutoGeneratedHardwareWithMinCoresAndMinRam() { + if (view.getComputeService().listHardwareProfiles().isEmpty()) { + Template template = view.getComputeService().templateBuilder() + .minRam(2048).minCores(2).build(); + assertThat(AutomaticHardwareIdSpec.isAutomaticId(template.getHardware().getId())).isTrue(); + assertThat(template.getHardware().getRam()).isEqualTo(2048); + assertThat(template.getHardware().getProcessors().get(0).getCores()).isEqualTo(2); + } + else { + throw new SkipException("Hardware profile list not empty."); + } + } + + @Test(dataProvider = "onlyIfAutomaticHardwareSupported", groups = {"integration", "live"}) + public void testAutoGeneratedHardwareWithOnlyMinCoresMatchHardwareProfile() { + if (!view.getComputeService().listHardwareProfiles().isEmpty()) { + Template template = view.getComputeService().templateBuilder().minCores(4).build(); + assertThat(AutomaticHardwareIdSpec.isAutomaticId(template.getHardware().getId())).isFalse(); + assertThat(template.getHardware().getProcessors().get(0).getCores()).isGreaterThanOrEqualTo(4); + } + else { + throw new SkipException("Hardware profile list is empty, this provider can not match any hardware profile" + + "to the specified minRam and minCores."); + } + } + + @Test(dataProvider = "onlyIfAutomaticHardwareSupported", groups = {"integration", "live"}) + public void testAutoGeneratedHardwareWithOnlyMinRamMatchHardwareProfile() { + if (!view.getComputeService().listHardwareProfiles().isEmpty()) { + Template template = view.getComputeService().templateBuilder().minRam(4096).build(); + assertThat(AutomaticHardwareIdSpec.isAutomaticId(template.getHardware().getId())).isFalse(); + assertThat(template.getHardware().getRam()).isGreaterThanOrEqualTo(4096); + } + else { + throw new SkipException("Hardware profile list is empty, this provider can not match any hardware profile" + + "to the specified minRam and minCores."); + } + } + + @Test(dataProvider = "onlyIfAutomaticHardwareSupported", groups = {"integration", "live"}, + expectedExceptions = IllegalArgumentException.class, + expectedExceptionsMessageRegExp = "No hardware profile matching the given criteria was found. " + + "If you want to use exact values, please set the minCores and minRam values") + public void testAutoGeneratedHardwareWithOnlyMinRamNotMatchHardwareProfile() { + if (view.getComputeService().listHardwareProfiles().isEmpty()) { + view.getComputeService().templateBuilder().minRam(4096).build(); + } + else { + throw new SkipException("Hardware profile list not empty."); + } + } + + @Test(dataProvider = "onlyIfAutomaticHardwareSupported", groups = {"integration", "live"}, + expectedExceptions = IllegalArgumentException.class, + expectedExceptionsMessageRegExp = "No hardware profile matching the given criteria was found. " + + "If you want to use exact values, please set the minCores and minRam values") + public void testAutoGeneratedHardwareWithOnlyMinCoresNotMatchHardwareProfile() { + if (view.getComputeService().listHardwareProfiles().isEmpty()) { + view.getComputeService().templateBuilder().minCores(4).build(); + } + else { + throw new SkipException("Hardware profile list not empty."); + } + } + } http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/compute/src/test/java/org/jclouds/compute/util/AutomaticHardwareIdSpecTest.java ---------------------------------------------------------------------- diff --git a/compute/src/test/java/org/jclouds/compute/util/AutomaticHardwareIdSpecTest.java b/compute/src/test/java/org/jclouds/compute/util/AutomaticHardwareIdSpecTest.java new file mode 100644 index 0000000..9dc72a2 --- /dev/null +++ b/compute/src/test/java/org/jclouds/compute/util/AutomaticHardwareIdSpecTest.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.compute.util; + +import org.testng.annotations.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +@Test(groups = "unit", testName = "AutomaticHardwareIdSpecTest") +public class AutomaticHardwareIdSpecTest { + @Test + public void isAutomaticIdTest() { + assertThat(AutomaticHardwareIdSpec.isAutomaticId("automatic:cores=2;ram=256")).isTrue(); + } + + @Test + public void isNotAutomaticId() { + assertThat(AutomaticHardwareIdSpec.isAutomaticId("Hi, I'm a non automatic id.")).isFalse(); + } + + @Test + public void parseAutomaticIdTest() { + AutomaticHardwareIdSpec parser = AutomaticHardwareIdSpec.parseId("automatic:cores=2;ram=256"); + assertThat(parser.getRam()).isEqualTo(256); + assertThat(parser.getCores()).isEqualTo(2); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void parseAutomaticIdMissingValuesTest() { + AutomaticHardwareIdSpec.parseId("automatic:cores=2"); + } + + @Test + public void generateAutomaticIdTest() { + AutomaticHardwareIdSpec spec = AutomaticHardwareIdSpec.parseId("automatic:cores=2;ram=1024"); + assertThat(spec.toString()).isEqualTo("automatic:cores=2.0;ram=1024"); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/core/src/test/java/org/jclouds/utils/TestUtils.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/jclouds/utils/TestUtils.java b/core/src/test/java/org/jclouds/utils/TestUtils.java index 7082346..cce923b 100644 --- a/core/src/test/java/org/jclouds/utils/TestUtils.java +++ b/core/src/test/java/org/jclouds/utils/TestUtils.java @@ -27,6 +27,9 @@ import com.google.common.io.ByteSource; */ public class TestUtils { + public static final Object[][] NO_INVOCATIONS = new Object[0][0]; + public static final Object[][] SINGLE_NO_ARG_INVOCATION = { new Object[0] }; + public static boolean isJava6() { return System.getProperty("java.version", "").contains("1.6."); } http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java ---------------------------------------------------------------------- diff --git a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java index 484df91..8c35f32 100644 --- a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java +++ b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java @@ -79,6 +79,8 @@ import com.google.inject.Injector; import com.google.inject.Provides; import com.google.inject.Scopes; import com.google.inject.TypeLiteral; +import org.jclouds.compute.domain.internal.TemplateBuilderImpl; +import org.jclouds.googlecomputeengine.compute.domain.internal.GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl; public final class GoogleComputeEngineServiceContextModule extends ComputeServiceAdapterContextModule<Instance, MachineType, Image, Location> { @@ -92,6 +94,8 @@ public final class GoogleComputeEngineServiceContextModule bind(new TypeLiteral<ComputeServiceAdapter<Instance, MachineType, Image, Location>>() { }).to(GoogleComputeEngineServiceAdapter.class); + bind(TemplateBuilderImpl.class).to(GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl.class); + // Use compute service to supply locations, which are always zones. install(new LocationsFromComputeServiceAdapterModule<Instance, MachineType, Image, Location>() { }); http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/domain/internal/GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl.java ---------------------------------------------------------------------- diff --git a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/domain/internal/GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl.java b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/domain/internal/GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl.java new file mode 100644 index 0000000..774dce9 --- /dev/null +++ b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/domain/internal/GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.googlecomputeengine.compute.domain.internal; + +import com.google.common.base.Supplier; +import org.jclouds.collect.Memoized; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.compute.domain.internal.ArbitraryCpuRamTemplateBuilderImpl; +import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.domain.Location; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; +import java.net.URI; +import java.util.Set; + +public class GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl extends ArbitraryCpuRamTemplateBuilderImpl { + @Inject + protected GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl(@Memoized Supplier<Set<? extends Location>> locations, + @Memoized Supplier<Set<? extends org.jclouds.compute.domain.Image>> images, + @Memoized Supplier<Set<? extends Hardware>> hardwares, Supplier<Location> defaultLocation, + @Named("DEFAULT") Provider<TemplateOptions> optionsProvider, + @Named("DEFAULT") Provider<TemplateBuilder> defaultTemplateProvider) { + super(locations, images, hardwares, defaultLocation, optionsProvider, defaultTemplateProvider); + } + + protected Hardware automaticHardwareForCpuAndRam(double cores, int ram) { + if (location == null) { + location = defaultLocation.get(); + } + String uri = location.getDescription() + "/machineTypes/custom-" + (int)cores + "-" + ram; + return new HardwareBuilder() + .id(uri) + .ram(ram) + .processor(new Processor((int)cores, 1.0)) + .providerId(uri) + .uri(URI.create(uri)) + .build(); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceToNodeMetadata.java ---------------------------------------------------------------------- diff --git a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceToNodeMetadata.java b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceToNodeMetadata.java index 6f72bee..7e7407e 100644 --- a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceToNodeMetadata.java +++ b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceToNodeMetadata.java @@ -16,27 +16,30 @@ */ package org.jclouds.googlecomputeengine.compute.functions; -import static org.jclouds.compute.util.ComputeServiceUtils.groupFromMapOrName; - -import javax.inject.Inject; -import java.net.URI; -import java.util.List; -import java.util.Map; - import com.google.common.base.Function; +import com.google.common.base.Splitter; import com.google.common.base.Supplier; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableList; import org.jclouds.collect.Memoized; import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata.Status; import org.jclouds.compute.domain.NodeMetadataBuilder; +import org.jclouds.compute.domain.Processor; import org.jclouds.compute.functions.GroupNamingConvention; import org.jclouds.domain.Location; import org.jclouds.googlecomputeengine.domain.Image; import org.jclouds.googlecomputeengine.domain.Instance; +import javax.inject.Inject; +import java.net.URI; +import java.util.List; +import java.util.Map; + +import static org.jclouds.compute.util.ComputeServiceUtils.groupFromMapOrName; + public final class InstanceToNodeMetadata implements Function<Instance, NodeMetadata> { private final Map<Instance.Status, NodeMetadata.Status> toPortableNodeStatus; @@ -73,13 +76,21 @@ public final class InstanceToNodeMetadata implements Function<Instance, NodeMeta // a loading cache. That would be more expensive, but could ensure this isn't null. Image image = diskURIToImage.getUnchecked(input.disks().get(0).source()); + Hardware hardware; + if (isCustomMachineTypeURI(input.machineType())) { + hardware = machineTypeURIToCustomHardware(input.machineType()); + } + else { + hardware = hardwares.get().get(input.machineType()); + } + builder.id(input.selfLink().toString()) .name(input.name()) .providerId(input.id()) .hostname(input.name()) .location(zone) .imageId(image != null ? image.selfLink().toString() : null) - .hardware(hardwares.get().get(input.machineType())) + .hardware(hardware) .status(input.status() != null ? toPortableNodeStatus.get(input.status()) : Status.UNRECOGNIZED) .tags(input.tags().items()) .uri(input.selfLink()) @@ -111,4 +122,23 @@ public final class InstanceToNodeMetadata implements Function<Instance, NodeMeta } return publicAddressesBuilder.build(); } + + public static boolean isCustomMachineTypeURI(URI machineType) { + return machineType.toString().contains("machineTypes/custom"); + } + + public static Hardware machineTypeURIToCustomHardware(URI machineType) { + String uri = machineType.toString(); + String values = uri.substring(uri.lastIndexOf('/') + 8); + List<String> hardwareValues = Splitter.on('-') + .trimResults() + .splitToList(values); + return new HardwareBuilder() + .id(uri) + .providerId(uri) + .processor(new Processor(Double.parseDouble(hardwareValues.get(0)), 1.0)) + .ram(Integer.parseInt(hardwareValues.get(1))) + .uri(machineType) + .build(); + } } http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceLiveTest.java ---------------------------------------------------------------------- diff --git a/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceLiveTest.java b/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceLiveTest.java index ca381db..d8bd28e 100644 --- a/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceLiveTest.java +++ b/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceLiveTest.java @@ -17,6 +17,9 @@ package org.jclouds.googlecomputeengine.compute; import static com.google.common.collect.Iterables.contains; +import static com.google.common.collect.Iterables.getOnlyElement; +import static org.assertj.core.api.Assertions.assertThat; +import static org.jclouds.compute.predicates.NodePredicates.inGroup; import static org.jclouds.util.Strings2.toStringAndClose; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; @@ -33,9 +36,9 @@ import com.google.inject.Module; import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.Template; import org.jclouds.compute.internal.BaseComputeServiceLiveTest; import org.jclouds.compute.options.TemplateOptions; -import org.jclouds.compute.predicates.NodePredicates; import org.jclouds.googlecloud.internal.TestProperties; import org.jclouds.googlecomputeengine.GoogleComputeEngineApi; import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions; @@ -95,7 +98,7 @@ public class GoogleComputeEngineServiceLiveTest extends BaseComputeServiceLiveTe assertTrue(instance.scheduling().preemptible()); } finally { - client.destroyNodesMatching(NodePredicates.inGroup(group)); + client.destroyNodesMatching(inGroup(group)); } } /** @@ -152,4 +155,20 @@ public class GoogleComputeEngineServiceLiveTest extends BaseComputeServiceLiveTe // Hardware profiles might not have volumes. } + @Override + @Test(dataProvider = "onlyIfAutomaticHardwareSupported", groups = {"integration", "live"}) + public void testCreateNodeWithCustomHardware() throws Exception { + Template template = buildTemplate(templateBuilder() + .hardwareId("automatic:cores=2;ram=4096")); + try { + NodeMetadata node = getOnlyElement(client.createNodesInGroup("custom", 1, template)); + assertThat(node.getHardware().getRam()).isEqualTo(4096); + assertThat(node.getHardware().getProcessors().get(0).getCores()).isEqualTo(2); + assertThat(node.getHardware().getId()).isEqualTo(node.getLocation().getDescription() + "/machineTypes/custom-2-4096"); + } + finally { + client.destroyNodesMatching(inGroup("custom")); + } + } + } http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineTemplateBuilderLiveTest.java ---------------------------------------------------------------------- diff --git a/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineTemplateBuilderLiveTest.java b/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineTemplateBuilderLiveTest.java index dbbedb3..a954e21 100644 --- a/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineTemplateBuilderLiveTest.java +++ b/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineTemplateBuilderLiveTest.java @@ -17,6 +17,7 @@ package org.jclouds.googlecomputeengine.compute; import static com.google.common.base.Objects.firstNonNull; +import static org.assertj.core.api.Assertions.assertThat; import static org.jclouds.compute.domain.OsFamily.COREOS; import static org.jclouds.compute.domain.OsFamily.DEBIAN; import static org.jclouds.compute.domain.OsFamily.WINDOWS; @@ -25,6 +26,7 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import java.io.IOException; +import java.net.URI; import java.util.Map; import java.util.Properties; import java.util.Set; @@ -76,4 +78,17 @@ public class GoogleComputeEngineTemplateBuilderLiveTest extends BaseTemplateBuil return ImmutableSet.<String> of(); } + @Override + @Test(dataProvider = "onlyIfAutomaticHardwareSupported", groups = {"integration", "live"}) + public void testAutoGeneratedHardwareFromId() { + Template template = view.getComputeService().templateBuilder() + .hardwareId("automatic:cores=2;ram=1024").build(); + assertThat(template.getHardware().getId()).isEqualTo(template.getLocation() + .getDescription() + "/machineTypes/custom-2-1024"); + assertThat(template.getHardware().getRam()).isEqualTo(1024); + assertThat(template.getHardware().getProcessors().get(0).getCores()).isEqualTo(2); + assertThat(template.getHardware().getUri()).isEqualTo(URI.create(template.getLocation() + .getDescription() + "/machineTypes/custom-2-1024")); + } + } http://git-wip-us.apache.org/repos/asf/jclouds/blob/300261b2/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/domain/internal/GoogleComputeEngineArbitraryCpuRamTemplateBuilderImplTest.java ---------------------------------------------------------------------- diff --git a/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/domain/internal/GoogleComputeEngineArbitraryCpuRamTemplateBuilderImplTest.java b/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/domain/internal/GoogleComputeEngineArbitraryCpuRamTemplateBuilderImplTest.java new file mode 100644 index 0000000..98b3144 --- /dev/null +++ b/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/domain/internal/GoogleComputeEngineArbitraryCpuRamTemplateBuilderImplTest.java @@ -0,0 +1,278 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.googlecomputeengine.compute.domain.internal; + +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.collect.ImmutableSet; +import com.google.common.util.concurrent.Atomics; +import com.google.inject.Provider; +import com.google.inject.util.Providers; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.ImageBuilder; +import org.jclouds.compute.domain.OperatingSystem; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.compute.domain.internal.TemplateBuilderImpl; +import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.compute.strategy.GetImageStrategy; +import org.jclouds.compute.suppliers.ImageCacheSupplier; +import org.jclouds.domain.Location; +import org.jclouds.domain.LocationBuilder; +import org.jclouds.domain.LocationScope; +import org.jclouds.rest.AuthorizationException; +import org.testng.annotations.Test; + +import java.net.URI; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; + +@Test(groups = "unit", singleThreaded = true, testName = "GoogleComputeEngineTemplateBuilderImplTest") +public class GoogleComputeEngineArbitraryCpuRamTemplateBuilderImplTest { + private Location provider = new LocationBuilder() + .scope(LocationScope.PROVIDER) + .id("google-compute-engine") + .description("google-compute-engine") + .build(); + + private Location region = new LocationBuilder() + .scope(LocationScope.REGION) + .id("us-east-1") + .description("http://localhost/projects/party/zones/us-east-1") + .parent(provider) + .build(); + + private OperatingSystem os = OperatingSystem.builder() + .name("osName") + .version("osVersion") + .description("osDescription") + .arch("X86_32") + .build(); + + private Image image = new ImageBuilder() + .id("imageId") + .providerId("imageId") + .name("imageName") + .description("imageDescription") + .version("imageVersion") + .operatingSystem(os) + .status(Image.Status.AVAILABLE) + .location(null) + .build(); + + private Hardware hardware = new HardwareBuilder() + .ram(2048) + .processor(new Processor(2, 1)) + .id("http://localhost/projects/party/zones/us-east-1/machineTypes/n2-standard-2") + .name("n2-standard-2") + .location(region) + .uri(URI.create("http://localhost/projects/party/zones/us-east-1/machineTypes/n2-standard-2")) + .build(); + + private final String errorMessage = "No hardware profile matching the given criteria was found. " + + "If you want to use exact values, please set the minCores and minRam values"; + + @Test + public void testAutoGeneratedHardwareFromIdTest(){ + Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet.of(region)); + Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet.of(image)); + Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet + .<Hardware> of(hardware)); + Provider<TemplateOptions> optionsProvider = createMock(Provider.class); + Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + + TemplateBuilderImpl templateBuilder = + new GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl(locations, new ImageCacheSupplier(images, 60, + Atomics.<AuthorizationException>newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), + optionsProvider, templateBuilderProvider); + + Hardware hardware = templateBuilder.hardwareId("automatic:cores=2;ram=1024").build().getHardware(); + assertThat(hardware.getRam()).isEqualTo(1024); + assertThat(hardware.getProcessors()).extracting("cores").containsExactly(2.0); + assertThat(hardware.getUri()).isEqualTo(URI.create("http://localhost/projects/party/zones/us-east-1/machineTypes/custom-2-1024")); + assertThat(hardware.getId()).isEqualTo("http://localhost/projects/party/zones/us-east-1/machineTypes/custom-2-1024"); + } + + @Test + public void testAutoGeneratedHardwareWithMinCoresAndMinRamDontMatchTest() { + Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet + .of(region)); + Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet.of(image)); + Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet + .<Hardware> of(hardware)); + Provider<TemplateOptions> optionsProvider = createMock(Provider.class); + Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.<AuthorizationException>newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minRam(4096); + templateBuilder.minCores(2); + Hardware hardware = templateBuilder.build().getHardware(); + assertThat(hardware.getRam()).isEqualTo(4096); + assertThat(hardware.getProcessors()).extracting("cores").containsExactly(2.0); + assertThat(hardware.getId()).isEqualTo("http://localhost/projects/party/zones/us-east-1/machineTypes/custom-2-4096"); + } + + @Test + public void testAutoGeneratedHardwareMatchHardwareProfile() { + Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet + .of(region)); + Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet.of(image)); + Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet + .<Hardware> of(hardware)); + Provider<TemplateOptions> optionsProvider = createMock(Provider.class); + Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.<AuthorizationException>newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minRam(1024); + templateBuilder.minCores(2); + Hardware hardware = templateBuilder.build().getHardware(); + assertThat(hardware.getRam()).isEqualTo(2048); + assertThat(hardware.getProcessors()).extracting("cores").containsExactly(2.0); + assertThat(hardware.getId()).isEqualTo("http://localhost/projects/party/zones/us-east-1/machineTypes/n2-standard-2"); + } + + @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = errorMessage) + public void testAutoGeneratedHardwareWithOnlyMinCoresTest() { + Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet + .of(region)); + Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet.of(image)); + Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet + .<Hardware> of(hardware)); + Provider<TemplateOptions> optionsProvider = createMock(Provider.class); + Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.<AuthorizationException>newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minCores(4); + templateBuilder.build().getHardware(); + } + + @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = errorMessage) + public void testAutoGeneratedHardwareWithOnlyMinRamTest() { + Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet + .of(region)); + Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet.of(image)); + Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet + .<Hardware> of(hardware)); + Provider<TemplateOptions> optionsProvider = createMock(Provider.class); + Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.<AuthorizationException>newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minRam(4096); + templateBuilder.build().getHardware(); + } + + @Test + public void testAutoGeneratedHardwareWithOnlyMinCoresMatchedHardware() { + Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet + .of(region)); + Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet.of(image)); + Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet + .<Hardware> of(hardware)); + Provider<TemplateOptions> optionsProvider = createMock(Provider.class); + Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.<AuthorizationException>newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minCores(2); + Hardware hardware = templateBuilder.build().getHardware(); + assertThat(hardware.getRam()).isEqualTo(2048); + assertThat(hardware.getProcessors()).extracting("cores").containsExactly(2.0); + assertThat(hardware.getId()) + .isEqualTo("http://localhost/projects/party/zones/us-east-1/machineTypes/n2-standard-2"); + } + + @Test + public void testAutoGeneratedHardwareOnlyRamMatchHardwareProfile() { + Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet + .of(region)); + Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet.of(image)); + Supplier<Set<? extends Hardware>> hardwares = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet + .<Hardware> of(hardware)); + Provider<TemplateOptions> optionsProvider = createMock(Provider.class); + Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class); + TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); + GetImageStrategy getImageStrategy = createMock(GetImageStrategy.class); + + expect(optionsProvider.get()).andReturn(new TemplateOptions()); + expect(getImageStrategy.getImage(anyObject(String.class))).andReturn(null); + replay(defaultTemplate, optionsProvider, templateBuilderProvider, getImageStrategy); + TemplateBuilderImpl templateBuilder = new GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl(locations, + new ImageCacheSupplier(images, 60, + Atomics.<AuthorizationException>newReference(), Providers.of(getImageStrategy)), hardwares, + Suppliers.ofInstance(region), optionsProvider, templateBuilderProvider); + templateBuilder.minRam(1024); + Hardware hardware = templateBuilder.build().getHardware(); + assertThat(hardware.getRam()).isEqualTo(2048); + assertThat(hardware.getProcessors()).extracting("cores").containsExactly(2.0); + assertThat(hardware.getId()) + .isEqualTo("http://localhost/projects/party/zones/us-east-1/machineTypes/n2-standard-2"); + } + +}
