From 6ad732cda78b8013200cc20bfdeef45ebde26a93 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Thu, 22 Sep 2011 13:09:45 -0700 Subject: [PATCH] Issue 693:add ability to supply node object directly to byon --- .../BYONComputeServiceContextBuilder.java | 19 ++ .../BYONComputeServiceContextModule.java | 15 +- .../byon/config/CacheNodeStoreModule.java | 64 +++++++ .../byon/config/ConfiguresNodeStore.java | 2 +- .../byon/config/YamlNodeStoreModule.java | 41 ++++- .../byon/functions/NodesFromYamlStream.java | 26 ++- .../internal/BYONComputeServiceAdapter.java | 20 +- .../suppliers/NodesParsedFromSupplier.java | 12 +- .../jclouds/byon/BYONComputeServiceTest.java | 54 +++--- .../byon/config/CacheNodeStoreModuleTest.java | 171 ++++++++++++++++++ .../byon/config/YamlNodeStoreModuleTest.java | 81 ++++++--- .../functions/NodeToNodeMetadataTest.java | 15 +- .../byon/functions/NodesFromYamlTest.java | 6 +- .../PlacementGroupClientLiveTest.java | 2 +- .../cloudsigma/CloudSigmaClientLiveTest.java | 6 +- 15 files changed, 434 insertions(+), 100 deletions(-) create mode 100644 apis/byon/src/main/java/org/jclouds/byon/config/CacheNodeStoreModule.java create mode 100644 apis/byon/src/test/java/org/jclouds/byon/config/CacheNodeStoreModuleTest.java diff --git a/apis/byon/src/main/java/org/jclouds/byon/BYONComputeServiceContextBuilder.java b/apis/byon/src/main/java/org/jclouds/byon/BYONComputeServiceContextBuilder.java index 0aa8ea7890..15bdb626a9 100644 --- a/apis/byon/src/main/java/org/jclouds/byon/BYONComputeServiceContextBuilder.java +++ b/apis/byon/src/main/java/org/jclouds/byon/BYONComputeServiceContextBuilder.java @@ -22,9 +22,13 @@ import java.util.List; import java.util.Properties; import org.jclouds.byon.config.BYONComputeServiceContextModule; +import org.jclouds.byon.config.ConfiguresNodeStore; +import org.jclouds.byon.config.YamlNodeStoreModule; import org.jclouds.compute.StandaloneComputeServiceContextBuilder; +import com.google.common.base.Predicate; import com.google.common.base.Supplier; +import com.google.common.collect.Iterables; import com.google.inject.Module; /** @@ -41,6 +45,21 @@ public class BYONComputeServiceContextBuilder extends StandaloneComputeServiceCo @Override protected void addContextModule(List modules) { modules.add(new BYONComputeServiceContextModule()); + addNodeStoreModuleIfNotPresent(modules); } + protected void addNodeStoreModuleIfNotPresent(List modules) { + if (!Iterables.any(modules, new Predicate() { + public boolean apply(Module input) { + return input.getClass().isAnnotationPresent(ConfiguresNodeStore.class); + } + + })) { + addNodeStoreModule(modules); + } + } + + protected void addNodeStoreModule(List modules) { + modules.add(new YamlNodeStoreModule()); + } } diff --git a/apis/byon/src/main/java/org/jclouds/byon/config/BYONComputeServiceContextModule.java b/apis/byon/src/main/java/org/jclouds/byon/config/BYONComputeServiceContextModule.java index 0aa24df25d..7bff8b097d 100644 --- a/apis/byon/src/main/java/org/jclouds/byon/config/BYONComputeServiceContextModule.java +++ b/apis/byon/src/main/java/org/jclouds/byon/config/BYONComputeServiceContextModule.java @@ -20,14 +20,11 @@ package org.jclouds.byon.config; import java.io.InputStream; import java.net.URI; -import java.util.Map; import javax.inject.Singleton; import org.jclouds.byon.Node; -import org.jclouds.byon.functions.NodesFromYamlStream; import org.jclouds.byon.internal.BYONComputeServiceAdapter; -import org.jclouds.byon.suppliers.NodesParsedFromSupplier; import org.jclouds.byon.suppliers.SupplyFromProviderURIOrNodesProperty; import org.jclouds.compute.config.JCloudsNativeComputeServiceAdapterContextModule; import org.jclouds.concurrent.SingleThreaded; @@ -37,6 +34,7 @@ import org.jclouds.location.suppliers.OnlyLocationOrFirstZone; import com.google.common.base.Function; import com.google.common.base.Supplier; +import com.google.common.cache.Cache; import com.google.inject.Provides; import com.google.inject.TypeLiteral; @@ -47,7 +45,7 @@ import com.google.inject.TypeLiteral; @SuppressWarnings("unchecked") @SingleThreaded public class BYONComputeServiceContextModule extends - JCloudsNativeComputeServiceAdapterContextModule { + JCloudsNativeComputeServiceAdapterContextModule { public BYONComputeServiceContextModule() { super(Supplier.class, Supplier.class, BYONComputeServiceAdapter.class); @@ -55,7 +53,7 @@ public class BYONComputeServiceContextModule extends @Provides @Singleton - Supplier provideApi(Supplier> in) { + Supplier provideApi(Supplier> in) { return in; } @@ -64,15 +62,12 @@ public class BYONComputeServiceContextModule extends super.configure(); bind(new TypeLiteral>() { }).to(OnlyLocationOrFirstZone.class); - bind(new TypeLiteral>>() { - }).to(NodesParsedFromSupplier.class); + bind(new TypeLiteral>() { + }).to(SupplyFromProviderURIOrNodesProperty.class); bind(new TypeLiteral>() { }).annotatedWith(Provider.class).to(SupplyFromProviderURIOrNodesProperty.class); bind(new TypeLiteral>() { }).to(SupplyFromProviderURIOrNodesProperty.class); - // TODO make this somehow overridable via user request - bind(new TypeLiteral>>() { - }).to(NodesFromYamlStream.class); } } diff --git a/apis/byon/src/main/java/org/jclouds/byon/config/CacheNodeStoreModule.java b/apis/byon/src/main/java/org/jclouds/byon/config/CacheNodeStoreModule.java new file mode 100644 index 0000000000..7e33379cec --- /dev/null +++ b/apis/byon/src/main/java/org/jclouds/byon/config/CacheNodeStoreModule.java @@ -0,0 +1,64 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.byon.config; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; + +import org.jclouds.byon.Node; + +import com.google.common.annotations.Beta; +import com.google.common.base.Functions; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.inject.AbstractModule; +import com.google.inject.TypeLiteral; + +/** + * + * @author Adrian Cole + */ +@ConfiguresNodeStore +@Beta +public class CacheNodeStoreModule extends AbstractModule { + private final Cache backing; + + public CacheNodeStoreModule(Cache backing) { + this.backing = checkNotNull(backing, "backing"); + } + + public CacheNodeStoreModule(Map backing) { + this(CacheBuilder.newBuilder().build(CacheLoader.from(Functions.forMap(backing)))); + for (String node : backing.keySet()) + this.backing.getUnchecked(node); + } + + @Override + protected void configure() { + bind(new TypeLiteral>() { + }).toInstance(backing); + bind(new TypeLiteral>>() { + }).toInstance(Suppliers.> ofInstance(backing)); + } + +} \ No newline at end of file diff --git a/apis/byon/src/main/java/org/jclouds/byon/config/ConfiguresNodeStore.java b/apis/byon/src/main/java/org/jclouds/byon/config/ConfiguresNodeStore.java index 2afcb75175..319cf76fcd 100644 --- a/apis/byon/src/main/java/org/jclouds/byon/config/ConfiguresNodeStore.java +++ b/apis/byon/src/main/java/org/jclouds/byon/config/ConfiguresNodeStore.java @@ -27,7 +27,7 @@ import java.lang.annotation.Target; import com.google.common.annotations.Beta; /** - * designates the module configures a {@code Map} + * designates the module configures a {@code Cache} * * @author Adrian Cole * diff --git a/apis/byon/src/main/java/org/jclouds/byon/config/YamlNodeStoreModule.java b/apis/byon/src/main/java/org/jclouds/byon/config/YamlNodeStoreModule.java index 5d4f062caf..cd902170fc 100644 --- a/apis/byon/src/main/java/org/jclouds/byon/config/YamlNodeStoreModule.java +++ b/apis/byon/src/main/java/org/jclouds/byon/config/YamlNodeStoreModule.java @@ -22,19 +22,30 @@ import java.io.InputStream; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import javax.inject.Inject; +import javax.inject.Named; import javax.inject.Singleton; import org.jclouds.byon.Node; import org.jclouds.byon.domain.YamlNode; +import org.jclouds.byon.functions.NodesFromYamlStream; +import org.jclouds.byon.suppliers.NodesParsedFromSupplier; import org.jclouds.collect.TransformingMap; import org.jclouds.io.CopyInputStreamInputSupplierMap; +import org.jclouds.io.CopyInputStreamIntoSupplier; import com.google.common.annotations.Beta; import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.base.Supplier; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; import com.google.common.io.InputSupplier; import com.google.inject.AbstractModule; import com.google.inject.Provides; import com.google.inject.TypeLiteral; +import com.google.inject.name.Names; /** * @@ -56,6 +67,10 @@ public class YamlNodeStoreModule extends AbstractModule { @Override protected void configure() { + bind(new TypeLiteral>>() { + }).to(NodesParsedFromSupplier.class); + bind(new TypeLiteral>>() { + }).to(NodesFromYamlStream.class); bind(new TypeLiteral>() { }).toInstance(org.jclouds.byon.domain.YamlNode.yamlNodeToInputStream); bind(new TypeLiteral>() { @@ -66,27 +81,37 @@ public class YamlNodeStoreModule extends AbstractModule { }).toInstance(org.jclouds.byon.domain.YamlNode.toNode); if (backing != null) { bind(new TypeLiteral>() { - }).toInstance(backing); + }).annotatedWith(Names.named("yaml")).toInstance(backing); } else { bind(new TypeLiteral>>() { - }).toInstance(BACKING); + }).annotatedWith(Names.named("yaml")).toInstance(BACKING); bind(new TypeLiteral>() { - }).to(new TypeLiteral() { + }).annotatedWith(Names.named("yaml")).to(new TypeLiteral() { }); } + + } + + @Singleton + public static class YAMLCopyInputStreamInputSupplierMap extends CopyInputStreamInputSupplierMap { + @Inject + public YAMLCopyInputStreamInputSupplierMap(@Named("yaml") Map> toMap, + CopyInputStreamIntoSupplier putFunction) { + super(toMap, putFunction); + } } @Provides @Singleton - protected Map provideNodeStore(Map backing, - Function yamlSerializer, Function yamlDeserializer) { - return new TransformingMap(backing, yamlDeserializer, yamlSerializer); + protected Cache provideNodeStore(Map backing, Function yamlSerializer, + Function yamlDeserializer) { + return CacheBuilder.newBuilder().build(CacheLoader.from(Functions.forMap(new TransformingMap(backing, yamlDeserializer, yamlSerializer)))); } @Provides @Singleton - protected Map provideYamlStore(Map backing, - Function yamlSerializer, Function yamlDeserializer) { + protected Map provideYamlStore(@Named("yaml") Map backing, + Function yamlSerializer, Function yamlDeserializer) { return new TransformingMap(backing, yamlDeserializer, yamlSerializer); } } \ No newline at end of file diff --git a/apis/byon/src/main/java/org/jclouds/byon/functions/NodesFromYamlStream.java b/apis/byon/src/main/java/org/jclouds/byon/functions/NodesFromYamlStream.java index 8f22a5140c..880457d349 100644 --- a/apis/byon/src/main/java/org/jclouds/byon/functions/NodesFromYamlStream.java +++ b/apis/byon/src/main/java/org/jclouds/byon/functions/NodesFromYamlStream.java @@ -34,6 +34,10 @@ import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.Constructor; import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; @@ -65,7 +69,7 @@ import com.google.common.collect.Maps; * @author Adrian Cole */ @Singleton -public class NodesFromYamlStream implements Function> { +public class NodesFromYamlStream implements Function> { /** * Type-safe config class for YAML @@ -76,7 +80,7 @@ public class NodesFromYamlStream implements Function apply(InputStream source) { + public Cache apply(InputStream source) { Constructor constructor = new Constructor(Config.class); @@ -87,17 +91,23 @@ public class NodesFromYamlStream implements Function() { - public String apply(Node node) { - return node.getId(); - } - }); + Map backingMap = Maps.uniqueIndex(Iterables.transform(config.nodes, YamlNode.toNode), + new Function() { + public String apply(Node node) { + return node.getId(); + } + }); + Cache cache = CacheBuilder.newBuilder().build(CacheLoader.from(Functions.forMap(backingMap))); + for (String node : backingMap.keySet()) + cache.getUnchecked(node); + return cache; } } diff --git a/apis/byon/src/main/java/org/jclouds/byon/internal/BYONComputeServiceAdapter.java b/apis/byon/src/main/java/org/jclouds/byon/internal/BYONComputeServiceAdapter.java index 890336e459..4f9190bab6 100644 --- a/apis/byon/src/main/java/org/jclouds/byon/internal/BYONComputeServiceAdapter.java +++ b/apis/byon/src/main/java/org/jclouds/byon/internal/BYONComputeServiceAdapter.java @@ -42,9 +42,11 @@ import org.jclouds.location.suppliers.JustProvider; import com.google.common.base.Function; import com.google.common.base.Predicates; import com.google.common.base.Supplier; +import com.google.common.cache.Cache; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; import com.google.common.collect.ImmutableSet.Builder; +import com.google.common.collect.Iterables; +import com.google.common.util.concurrent.UncheckedExecutionException; /** * @@ -52,12 +54,12 @@ import com.google.common.collect.ImmutableSet.Builder; */ @Singleton public class BYONComputeServiceAdapter implements JCloudsNativeComputeServiceAdapter { - private final Supplier> nodes; + private final Supplier> nodes; private final NodeToNodeMetadata converter; private final JustProvider locationSupplier; @Inject - public BYONComputeServiceAdapter(Supplier> nodes, NodeToNodeMetadata converter, + public BYONComputeServiceAdapter(Supplier> nodes, NodeToNodeMetadata converter, JustProvider locationSupplier) { this.nodes = checkNotNull(nodes, "nodes"); this.converter = checkNotNull(converter, "converter"); @@ -82,14 +84,14 @@ public class BYONComputeServiceAdapter implements JCloudsNativeComputeServiceAda @Override public Iterable listNodes() { - return Iterables.transform(nodes.get().values(), converter); + return Iterables.transform(nodes.get().asMap().values(), converter); } @Override public Iterable listLocations() { Builder locations = ImmutableSet.builder(); Location provider = Iterables.getOnlyElement(locationSupplier.get()); - Set zones = ImmutableSet.copyOf(Iterables.filter(Iterables.transform(nodes.get().values(), + Set zones = ImmutableSet.copyOf(Iterables.filter(Iterables.transform(nodes.get().asMap().values(), new Function() { @Override @@ -109,7 +111,13 @@ public class BYONComputeServiceAdapter implements JCloudsNativeComputeServiceAda @Override public NodeMetadata getNode(String id) { - Node node = nodes.get().get(id); + + Node node = null; + try { + node = nodes.get().getUnchecked(id); + } catch (UncheckedExecutionException e) { + + } return node != null ? converter.apply(node) : null; } diff --git a/apis/byon/src/main/java/org/jclouds/byon/suppliers/NodesParsedFromSupplier.java b/apis/byon/src/main/java/org/jclouds/byon/suppliers/NodesParsedFromSupplier.java index 94cfc8d495..0cbf0e532a 100644 --- a/apis/byon/src/main/java/org/jclouds/byon/suppliers/NodesParsedFromSupplier.java +++ b/apis/byon/src/main/java/org/jclouds/byon/suppliers/NodesParsedFromSupplier.java @@ -22,7 +22,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import java.io.InputStream; -import java.util.Map; import javax.annotation.Resource; import javax.inject.Inject; @@ -34,28 +33,29 @@ import org.jclouds.logging.Logger; import com.google.common.base.Function; import com.google.common.base.Supplier; +import com.google.common.cache.Cache; /** * * @author Adrian Cole */ @Singleton -public class NodesParsedFromSupplier implements Supplier> { +public class NodesParsedFromSupplier implements Supplier> { @Resource protected Logger logger = Logger.NULL; private final Supplier supplier; - private final Function> parser; + private final Function> parser; @Inject - NodesParsedFromSupplier(@Provider Supplier supplier, Function> parser) { + NodesParsedFromSupplier(@Provider Supplier supplier, Function> parser) { this.supplier = checkNotNull(supplier, "supplier"); this.parser = checkNotNull(parser, "parser"); } @Override - public Map get() { - Map nodes = parser.apply(supplier.get()); + public Cache get() { + Cache nodes = parser.apply(supplier.get()); checkState(nodes != null && nodes.size() > 0, "no nodes parsed from supplier: %s", supplier); return nodes; } diff --git a/apis/byon/src/test/java/org/jclouds/byon/BYONComputeServiceTest.java b/apis/byon/src/test/java/org/jclouds/byon/BYONComputeServiceTest.java index 45ab6d8a8f..de1a4958bc 100644 --- a/apis/byon/src/test/java/org/jclouds/byon/BYONComputeServiceTest.java +++ b/apis/byon/src/test/java/org/jclouds/byon/BYONComputeServiceTest.java @@ -24,17 +24,17 @@ import static org.jclouds.byon.functions.NodeToNodeMetadataTest.zoneCalled; import static org.testng.Assert.assertEquals; import java.net.URI; -import java.util.Map; import java.util.Properties; +import org.jclouds.byon.config.CacheNodeStoreModule; import org.jclouds.byon.functions.NodesFromYamlTest; import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContextFactory; import org.jclouds.domain.Location; -import org.jclouds.sshj.config.SshjSshClientModule; import org.testng.annotations.Test; import com.google.common.base.Supplier; +import com.google.common.cache.Cache; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.inject.Module; @@ -43,41 +43,48 @@ import com.google.inject.Module; * * @author Adrian Cole */ -@Test(groups = "live") +@Test(singleThreaded = true, testName = "BYONComputeServiceTest") public class BYONComputeServiceTest { + @Test + public void testNodesParseNodeMap() throws Exception { + assertNodesParse( + "foo", + ImmutableSet. of(new CacheNodeStoreModule(ImmutableMap. of( + NodesFromYamlTest.TEST1.getId(), NodesFromYamlTest.TEST1)))); + } + @Test public void testNodesParseWithFileUrl() throws Exception { - assertNodesParse("file://" + getClass().getResource("/test1.yaml").getPath()); + assertNodesParse("file://" + getClass().getResource("/test1.yaml").getPath(), ImmutableSet. of()); } @Test public void testNodesParseWithClasspathUrl() throws Exception { - assertNodesParse("classpath:///test1.yaml"); + assertNodesParse("classpath:///test1.yaml", ImmutableSet. of()); } - private void assertNodesParse(String endpoint) { + private void assertNodesParse(String endpoint, Iterable modules) { ComputeServiceContext context = null; try { Location providerLocation = expectedProviderLocationFromResource(endpoint); Properties props = new Properties(); props.setProperty("byon.endpoint", endpoint); - context = new ComputeServiceContextFactory().createContext("byon", "foo", "bar", ImmutableSet - . of(new SshjSshClientModule()), props); + context = new ComputeServiceContextFactory().createContext("byon", "foo", "bar", modules, props); assertEquals(context.getProviderSpecificContext().getEndpoint(), URI.create(endpoint)); @SuppressWarnings("unchecked") - Supplier> supplier = (Supplier>) context.getProviderSpecificContext() - .getApi(); + Supplier> supplier = (Supplier>) context.getProviderSpecificContext() + .getApi(); assertEquals(supplier.get().size(), context.getComputeService().listNodes().size()); - assertEquals(supplier.get(), ImmutableMap. of(NodesFromYamlTest.TEST1.getId(), - NodesFromYamlTest.TEST1)); + assertEquals(supplier.get().asMap(), + ImmutableMap. of(NodesFromYamlTest.TEST1.getId(), NodesFromYamlTest.TEST1)); - assertEquals(context.getComputeService().listNodes(), ImmutableSet - .of(expectedNodeMetadataFromResource(endpoint))); + assertEquals(context.getComputeService().listNodes(), + ImmutableSet.of(expectedNodeMetadataFromResource(endpoint))); assertEquals(context.getComputeService().listAssignableLocations(), ImmutableSet.of(providerLocation)); } finally { if (context != null) @@ -91,26 +98,27 @@ public class BYONComputeServiceTest { String endpoint = "file://" + getClass().getResource("/test_location.yaml").getPath(); Properties props = new Properties(); props.setProperty("byon.endpoint", endpoint); - context = new ComputeServiceContextFactory().createContext("byon", "foo", "bar", ImmutableSet - . of(new SshjSshClientModule()), props); + context = new ComputeServiceContextFactory().createContext("byon", "foo", "bar", + ImmutableSet. of(), props); assertEquals(context.getProviderSpecificContext().getEndpoint(), URI.create(endpoint)); @SuppressWarnings("unchecked") - Supplier> supplier = (Supplier>) context.getProviderSpecificContext() - .getApi(); + Supplier> supplier = (Supplier>) context.getProviderSpecificContext() + .getApi(); assertEquals(supplier.get().size(), context.getComputeService().listNodes().size()); - assertEquals(supplier.get(), ImmutableMap. of(NodesFromYamlTest.TEST2.getId(), - NodesFromYamlTest.TEST2, NodesFromYamlTest.TEST3.getId(), NodesFromYamlTest.TEST3)); + assertEquals(supplier.get().asMap(), ImmutableMap. of(NodesFromYamlTest.TEST2.getId(), + NodesFromYamlTest.TEST2, NodesFromYamlTest.TEST3.getId(), NodesFromYamlTest.TEST3)); Location providerLocation = expectedProviderLocationFromResource(endpoint); Location virginia = zoneCalled("virginia", providerLocation); Location maryland = zoneCalled("maryland", providerLocation); - assertEquals(context.getComputeService().listNodes(), ImmutableSet.of(expectedNodeMetadataFromResource(1, - endpoint, virginia), expectedNodeMetadataFromResource(2, endpoint, maryland, 2022))); - + assertEquals(context.getComputeService().listNodes(), ImmutableSet.of( + expectedNodeMetadataFromResource(1, endpoint, virginia), + expectedNodeMetadataFromResource(2, endpoint, maryland, 2022))); + assertEquals(context.getComputeService().listAssignableLocations(), ImmutableSet.of(virginia, maryland)); } finally { if (context != null) diff --git a/apis/byon/src/test/java/org/jclouds/byon/config/CacheNodeStoreModuleTest.java b/apis/byon/src/test/java/org/jclouds/byon/config/CacheNodeStoreModuleTest.java new file mode 100644 index 0000000000..af64f18645 --- /dev/null +++ b/apis/byon/src/test/java/org/jclouds/byon/config/CacheNodeStoreModuleTest.java @@ -0,0 +1,171 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.byon.config; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +import org.jclouds.byon.Node; +import org.jclouds.location.Provider; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import com.google.common.base.Functions; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.collect.Maps; +import com.google.common.util.concurrent.UncheckedExecutionException; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", singleThreaded = true, testName = "CacheNodeStoreModuleTest") +public class CacheNodeStoreModuleTest { + + @DataProvider(name = "names") + public Object[][] createData() { + return new Object[][] { { "instance1", "bear" }, { "instance2", "apple" }, { "instance2", "francis" }, + { "instance4", "robot" } }; + } + + public void testProvidedMapWithValue() throws IOException { + Map map = Maps.newConcurrentMap(); + + map.put("test", Node.builder().id("instance1").name("instancename").build()); + checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename"); + checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename"); + remove(map, getStore(createInjectorWithProvidedMap(map)), "test"); + + } + + public void testProvidedConsistentAcrossRepeatedWrites() throws IOException { + Map map = Maps.newConcurrentMap(); + + Injector injector = createInjectorWithProvidedMap(map); + assertEquals(injector.getInstance(Key.get(new TypeLiteral>() { + })).asMap(), map); + Cache store = getStore(injector); + + for (int i = 0; i < 10; i++) + check(map, store, "test" + i, "instance1" + i, "instancename" + i); + + } + + public void testProvidedConsistentAcrossMultipleInjectors() throws IOException { + Map map = Maps.newConcurrentMap(); + + put(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename"); + checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename"); + checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename"); + remove(map, getStore(createInjectorWithProvidedMap(map)), "test"); + + } + + public void testProvidedCacheConsistentAcrossMultipleInjectors() throws IOException { + Map map = Maps.newConcurrentMap(); + + Cache cache = CacheBuilder.newBuilder().build(CacheLoader.from(Functions.forMap(map))); + + put(map, getStore(createInjectorWithProvidedCache(cache)), "test", "instance1", "instancename"); + checkConsistent(map, getStore(createInjectorWithProvidedCache(cache)), "test", "instance1", "instancename"); + checkConsistent(map, getStore(createInjectorWithProvidedCache(cache)), "test", "instance1", "instancename"); + remove(map, getStore(createInjectorWithProvidedCache(cache)), "test"); + + } + + private Cache getStore(Injector injector) { + return injector.getInstance(Key.get(new TypeLiteral>() { + })); + } + + private Injector createInjectorWithProvidedMap(Map map) { + return Guice.createInjector(new CacheNodeStoreModule(map), new AbstractModule() { + + @Override + public void configure() { + bind(new TypeLiteral>() { + }).annotatedWith(Provider.class).toInstance(Suppliers. ofInstance(null)); + } + + }); + } + + private Injector createInjectorWithProvidedCache(Cache cache) { + return Guice.createInjector(new CacheNodeStoreModule(cache), new AbstractModule() { + + @Override + public void configure() { + bind(new TypeLiteral>() { + }).annotatedWith(Provider.class).toInstance(Suppliers. ofInstance(null)); + } + + }); + } + + private void check(Map map, Cache store, String key, String id, String name) + throws IOException { + put(map, store, key, id, name); + checkConsistent(map, store, key, id, name); + remove(map, store, key); + } + + private void remove(Map map, Cache store, String key) { + store.invalidate(key); + assertEquals(store.size(), 0); + map.remove(key); + assertEquals(map.size(), 0); + try { + assertEquals(store.getUnchecked(key), null); + assert false : "should not work as null is invalid"; + } catch (UncheckedExecutionException e) { + + } + assertEquals(map.get(key), null); + } + + private void checkConsistent(Map map, Cache store, String key, String id, String name) + throws IOException { + assertEquals(map.size(), 1); + if (store.size() == 0) + store.getUnchecked(key); + assertEquals(store.size(), 1); + // checkRepeatedRead + assertEquals(store.getUnchecked(key), Node.builder().id(id).name(name).build()); + assertEquals(store.getUnchecked(key), Node.builder().id(id).name(name).build()); + } + + private void put(Map map, Cache store, String key, String id, String name) { + assertEquals(store.size(), 0); + assertEquals(map.size(), 0); + map.put(key, Node.builder().id(id).name(name).build()); + store.getUnchecked(key); + } +} \ No newline at end of file diff --git a/apis/byon/src/test/java/org/jclouds/byon/config/YamlNodeStoreModuleTest.java b/apis/byon/src/test/java/org/jclouds/byon/config/YamlNodeStoreModuleTest.java index 25ac42e2a1..97e285f8dc 100644 --- a/apis/byon/src/test/java/org/jclouds/byon/config/YamlNodeStoreModuleTest.java +++ b/apis/byon/src/test/java/org/jclouds/byon/config/YamlNodeStoreModuleTest.java @@ -28,16 +28,23 @@ import java.util.concurrent.ConcurrentHashMap; import org.jclouds.byon.Node; import org.jclouds.io.CopyInputStreamInputSupplierMap; +import org.jclouds.location.Provider; import org.jclouds.util.Strings2; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.yaml.snakeyaml.Yaml; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.cache.Cache; import com.google.common.io.InputSupplier; +import com.google.common.util.concurrent.UncheckedExecutionException; +import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.TypeLiteral; +import com.google.inject.name.Names; /** * @@ -45,12 +52,12 @@ import com.google.inject.TypeLiteral; */ @Test(groups = "unit", singleThreaded = true) public class YamlNodeStoreModuleTest { - Yaml json = createInjector().getInstance(Yaml.class); + Yaml yaml = createInjector().getInstance(Yaml.class); @DataProvider(name = "names") public Object[][] createData() { return new Object[][] { { "instance1", "bear" }, { "instance2", "apple" }, { "instance2", "francis" }, - { "instance4", "robot" } }; + { "instance4", "robot" } }; } @Test(dataProvider = "names") @@ -62,7 +69,7 @@ public class YamlNodeStoreModuleTest { public void testProvidedMapWithValue() throws IOException { Map map = new CopyInputStreamInputSupplierMap( - new ConcurrentHashMap>()); + new ConcurrentHashMap>()); map.put("test", new ByteArrayInputStream("id: instance1\nname: instancename\n".getBytes())); checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename"); @@ -73,12 +80,12 @@ public class YamlNodeStoreModuleTest { public void testProvidedConsistentAcrossRepeatedWrites() throws IOException { Map map = new CopyInputStreamInputSupplierMap( - new ConcurrentHashMap>()); + new ConcurrentHashMap>()); Injector injector = createInjectorWithProvidedMap(map); assertEquals(injector.getInstance(Key.get(new TypeLiteral>() { - })), map); - Map store = getStore(injector); + }, Names.named("yaml"))), map); + Cache store = getStore(injector); for (int i = 0; i < 10; i++) check(map, store, "test" + i, "instance1" + i, "instancename" + i); @@ -87,7 +94,7 @@ public class YamlNodeStoreModuleTest { public void testProvidedConsistentAcrossMultipleInjectors() throws IOException { Map map = new CopyInputStreamInputSupplierMap( - new ConcurrentHashMap>()); + new ConcurrentHashMap>()); put(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename"); checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename"); @@ -100,52 +107,77 @@ public class YamlNodeStoreModuleTest { Map map = getMap(createInjector()); put(map, getStore(createInjector()), "test", "instance1", "instancename"); + checkConsistent(map, getStore(createInjector()), "test", "instance1", "instancename"); checkConsistent(map, getStore(createInjector()), "test", "instance1", "instancename"); remove(map, getStore(createInjector()), "test"); } - protected Map getStore(Injector injector) { - return injector.getInstance(Key.get(new TypeLiteral>() { + protected Cache getStore(Injector injector) { + return injector.getInstance(Key.get(new TypeLiteral>() { })); } protected Map getMap(Injector injector) { return injector.getInstance(Key.get(new TypeLiteral>() { - })); + }, Names.named("yaml"))); } protected Injector createInjectorWithProvidedMap(Map map) { - return Guice.createInjector(new YamlNodeStoreModule(map)); + return Guice.createInjector(new YamlNodeStoreModule(map), new AbstractModule() { + + @Override + protected void configure() { + bind(new TypeLiteral>() { + }).annotatedWith(Provider.class).toInstance(Suppliers. ofInstance(null)); + } + + }); } protected Injector createInjector() { - return Guice.createInjector(new YamlNodeStoreModule()); + return Guice.createInjector(new YamlNodeStoreModule(), new AbstractModule() { + + @Override + protected void configure() { + bind(new TypeLiteral>() { + }).annotatedWith(Provider.class).toInstance(Suppliers. ofInstance(null)); + } + + }); } - protected void check(Map map, Map store, String key, String id, String name) - throws IOException { + protected void check(Map map, Cache store, String key, String id, String name) + throws IOException { put(map, store, key, id, name); checkConsistent(map, store, key, id, name); remove(map, store, key); } - protected void remove(Map map, Map store, String key) { - store.remove(key); + protected void remove(Map map, Cache store, String key) { + store.invalidate(key); assertEquals(store.size(), 0); + map.remove(key); assertEquals(map.size(), 0); - assertEquals(store.get(key), null); + try { + assertEquals(store.getUnchecked(key), null); + assert false : "should not work as null is invalid"; + } catch (UncheckedExecutionException e) { + + } assertEquals(map.get(key), null); } - protected void checkConsistent(Map map, Map store, String key, String id, - String name) throws IOException { - assertEquals(store.size(), 1); + protected void checkConsistent(Map map, Cache store, String key, String id, + String name) throws IOException { assertEquals(map.size(), 1); + if (store.size() == 0) + store.getUnchecked(key); + assertEquals(store.size(), 1); // checkRepeatedRead - assertEquals(store.get(key), Node.builder().id(id).name(name).build()); - assertEquals(store.get(key), Node.builder().id(id).name(name).build()); + assertEquals(store.getUnchecked(key), Node.builder().id(id).name(name).build()); + assertEquals(store.getUnchecked(key), Node.builder().id(id).name(name).build()); // checkRepeatedRead checkToYaml(map, key, id, name); checkToYaml(map, key, id, name); @@ -155,9 +187,10 @@ public class YamlNodeStoreModuleTest { assertEquals(Strings2.toStringAndClose(map.get(key)), String.format("id: %s\nname: %s\n", id, name)); } - protected void put(Map map, Map store, String key, String id, String name) { + protected void put(Map map, Cache store, String key, String id, String name) { assertEquals(store.size(), 0); assertEquals(map.size(), 0); - store.put(key, Node.builder().id(id).name(name).build()); + map.put(key, new ByteArrayInputStream(String.format("id: %s\nname: %s\n", id, name).getBytes())); + store.getUnchecked(key); } } \ No newline at end of file diff --git a/apis/byon/src/test/java/org/jclouds/byon/functions/NodeToNodeMetadataTest.java b/apis/byon/src/test/java/org/jclouds/byon/functions/NodeToNodeMetadataTest.java index 4358e38530..1fc15839e3 100644 --- a/apis/byon/src/test/java/org/jclouds/byon/functions/NodeToNodeMetadataTest.java +++ b/apis/byon/src/test/java/org/jclouds/byon/functions/NodeToNodeMetadataTest.java @@ -45,6 +45,7 @@ import com.google.common.collect.Maps; * * @author Adrian Cole */ +@Test(singleThreaded = true, testName = "NodeToNodeMetadataTest") public class NodeToNodeMetadataTest { public static Location expectedProviderLocationFromResource(String resource) { return new LocationBuilder().scope(LocationScope.PROVIDER).id("byon").description(resource).build(); @@ -60,9 +61,9 @@ public class NodeToNodeMetadataTest { Map credentialStore = Maps.newLinkedHashMap(); - NodeToNodeMetadata parser = new NodeToNodeMetadata(Suppliers.ofInstance(provider), Suppliers - .> ofInstance(ImmutableSet.of(provider, zoneCalled("virginia", provider))), - new SupplyFromProviderURIOrNodesProperty(URI.create("test")), credentialStore); + NodeToNodeMetadata parser = new NodeToNodeMetadata(Suppliers.ofInstance(provider), + Suppliers.> ofInstance(ImmutableSet.of(provider, zoneCalled("virginia", provider))), + new SupplyFromProviderURIOrNodesProperty(URI.create("test")), credentialStore); public static NodeMetadata expectedNodeMetadataFromResource(String resource) { return expectedNodeMetadataFromResource(resource, expectedProviderLocationFromResource(resource)); @@ -75,7 +76,7 @@ public class NodeToNodeMetadataTest { public static NodeMetadata expectedNodeMetadataFromResource(int id, String resource, Location location) { return expectedNodeMetadataFromResource(id, resource, location, 22); } - + public static NodeMetadata expectedNodeMetadataFromResource(int id, String resource, Location location, int loginPort) { return new NodeMetadataBuilder() .ids("cluster-" + id) @@ -99,11 +100,11 @@ public class NodeToNodeMetadataTest { @Test public void testNodesParseLocation() throws Exception { - assertEquals(parser.apply(NodesFromYamlTest.TEST2), expectedNodeMetadataFromResource(resource, zoneCalled( - "virginia", provider))); + assertEquals(parser.apply(NodesFromYamlTest.TEST2), + expectedNodeMetadataFromResource(resource, zoneCalled("virginia", provider))); assertEquals(credentialStore, ImmutableMap.of("node#cluster-1", new Credentials("myUser", NodesFromYamlTest.key))); } - + @Test public void testNodesParseLoginPort() throws Exception { assertEquals(parser.apply(NodesFromYamlTest.TEST3), expectedNodeMetadataFromResource(2, resource, provider, 2022)); diff --git a/apis/byon/src/test/java/org/jclouds/byon/functions/NodesFromYamlTest.java b/apis/byon/src/test/java/org/jclouds/byon/functions/NodesFromYamlTest.java index fc1417aee2..27603cf1bb 100644 --- a/apis/byon/src/test/java/org/jclouds/byon/functions/NodesFromYamlTest.java +++ b/apis/byon/src/test/java/org/jclouds/byon/functions/NodesFromYamlTest.java @@ -58,7 +58,7 @@ public class NodesFromYamlTest { InputStream is = getClass().getResourceAsStream("/test1.yaml"); NodesFromYamlStream parser = new NodesFromYamlStream(); - assertEquals(parser.apply(is), ImmutableMap.of(TEST1.getId(), TEST1)); + assertEquals(parser.apply(is).asMap(), ImmutableMap.of(TEST1.getId(), TEST1)); } @Test @@ -67,7 +67,7 @@ public class NodesFromYamlTest { InputStream is = getClass().getResourceAsStream("/test_location.yaml"); NodesFromYamlStream parser = new NodesFromYamlStream(); - assertEquals(parser.apply(is), ImmutableMap.of(TEST2.getId(), TEST2, TEST3.getId(), TEST3)); + assertEquals(parser.apply(is).asMap(), ImmutableMap.of(TEST2.getId(), TEST2, TEST3.getId(), TEST3)); } @Test @@ -76,7 +76,7 @@ public class NodesFromYamlTest { InputStream is = getClass().getResourceAsStream("/test_with_url.yaml"); NodesFromYamlStream parser = new NodesFromYamlStream(); - assertEquals(parser.apply(is), ImmutableMap.of(TEST1.getId(), TEST1)); + assertEquals(parser.apply(is).asMap(), ImmutableMap.of(TEST1.getId(), TEST1)); } @Test(expectedExceptions = IllegalStateException.class) diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/PlacementGroupClientLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/PlacementGroupClientLiveTest.java index 2652969beb..c1e061de9b 100644 --- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/PlacementGroupClientLiveTest.java +++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/PlacementGroupClientLiveTest.java @@ -168,7 +168,7 @@ public class PlacementGroupClientLiveTest { public void testStartCCInstance() throws Exception { - Template template = context.getComputeService().templateBuilder().fastest().osVersionMatches("11.04").build(); + Template template = context.getComputeService().templateBuilder().fastest().osDescriptionMatches(".*/ubuntu-images/.*").osVersionMatches("11.04").build(); assert template != null : "The returned template was null, but it should have a value."; assertEquals(template.getHardware().getProviderId(), InstanceType.CC1_4XLARGE); assertEquals(template.getImage().getUserMetadata().get("rootDeviceType"), "ebs"); diff --git a/providers/cloudsigma-zrh/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java b/providers/cloudsigma-zrh/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java index c50b8fdb3a..8b53fca3d6 100644 --- a/providers/cloudsigma-zrh/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java +++ b/providers/cloudsigma-zrh/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java @@ -73,7 +73,7 @@ import com.google.inject.Module; * * @author Adrian Cole */ -@Test(groups = "live", sequential = true) +@Test(groups = "live", singleThreaded = true) public class CloudSigmaClientLiveTest { protected long driveSize = 8 * 1024 * 1024 * 1024l; protected int maxDriveImageTime = 300; @@ -455,12 +455,12 @@ public class CloudSigmaClientLiveTest { } protected Credentials getSshCredentials(Server server) { - return new Credentials("cloudsigma", "cloudsigma"); + return new Credentials("root", vncPassword); } protected void prepareDrive() { client.destroyDrive(drive.getUuid()); - drive = client.cloneDrive("6a9cd9c2-4814-4953-8e86-f8ee6a3e57d5", drive.getName(), + drive = client.cloneDrive("f3c7c665-cd54-4a78-8fd2-7ec2f028cf29", drive.getName(), new CloneDriveOptions().size(driveSize)); assert driveNotClaimed.apply(drive) : client.getDriveInfo(drive.getUuid()); System.err.println("after prepare" + client.getDriveInfo(drive.getUuid()));