Merge branch 'master' of git://github.com/jclouds/jclouds

This commit is contained in:
Jason King 2011-09-23 08:57:27 +01:00
commit 20d03bbb13
28 changed files with 753 additions and 160 deletions

View File

@ -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<Module> modules) {
modules.add(new BYONComputeServiceContextModule());
addNodeStoreModuleIfNotPresent(modules);
}
protected void addNodeStoreModuleIfNotPresent(List<Module> modules) {
if (!Iterables.any(modules, new Predicate<Module>() {
public boolean apply(Module input) {
return input.getClass().isAnnotationPresent(ConfiguresNodeStore.class);
}
})) {
addNodeStoreModule(modules);
}
}
protected void addNodeStoreModule(List<Module> modules) {
modules.add(new YamlNodeStoreModule());
}
}

View File

@ -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<Supplier, Supplier> {
JCloudsNativeComputeServiceAdapterContextModule<Supplier, Supplier> {
public BYONComputeServiceContextModule() {
super(Supplier.class, Supplier.class, BYONComputeServiceAdapter.class);
@ -55,7 +53,7 @@ public class BYONComputeServiceContextModule extends
@Provides
@Singleton
Supplier provideApi(Supplier<Map<String, Node>> in) {
Supplier provideApi(Supplier<Cache<String, Node>> in) {
return in;
}
@ -64,15 +62,12 @@ public class BYONComputeServiceContextModule extends
super.configure();
bind(new TypeLiteral<Supplier<Location>>() {
}).to(OnlyLocationOrFirstZone.class);
bind(new TypeLiteral<Supplier<Map<String, Node>>>() {
}).to(NodesParsedFromSupplier.class);
bind(new TypeLiteral<Function<URI, InputStream>>() {
}).to(SupplyFromProviderURIOrNodesProperty.class);
bind(new TypeLiteral<Supplier<InputStream>>() {
}).annotatedWith(Provider.class).to(SupplyFromProviderURIOrNodesProperty.class);
bind(new TypeLiteral<Function<URI, InputStream>>() {
}).to(SupplyFromProviderURIOrNodesProperty.class);
// TODO make this somehow overridable via user request
bind(new TypeLiteral<Function<InputStream, Map<String, Node>>>() {
}).to(NodesFromYamlStream.class);
}
}

View File

@ -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<String, Node> backing;
public CacheNodeStoreModule(Cache<String, Node> backing) {
this.backing = checkNotNull(backing, "backing");
}
public CacheNodeStoreModule(Map<String, Node> backing) {
this(CacheBuilder.newBuilder().<String, Node>build(CacheLoader.from(Functions.forMap(backing))));
for (String node : backing.keySet())
this.backing.getUnchecked(node);
}
@Override
protected void configure() {
bind(new TypeLiteral<Cache<String, Node>>() {
}).toInstance(backing);
bind(new TypeLiteral<Supplier<Cache<String, Node>>>() {
}).toInstance(Suppliers.<Cache<String, Node>> ofInstance(backing));
}
}

View File

@ -27,7 +27,7 @@ import java.lang.annotation.Target;
import com.google.common.annotations.Beta;
/**
* designates the module configures a {@code Map<String, Node>}
* designates the module configures a {@code Cache<String, Node>}
*
* @author Adrian Cole
*

View File

@ -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<Supplier<Cache<String, Node>>>() {
}).to(NodesParsedFromSupplier.class);
bind(new TypeLiteral<Function<InputStream, Cache<String, Node>>>() {
}).to(NodesFromYamlStream.class);
bind(new TypeLiteral<Function<YamlNode, InputStream>>() {
}).toInstance(org.jclouds.byon.domain.YamlNode.yamlNodeToInputStream);
bind(new TypeLiteral<Function<InputStream, YamlNode>>() {
@ -66,27 +81,37 @@ public class YamlNodeStoreModule extends AbstractModule {
}).toInstance(org.jclouds.byon.domain.YamlNode.toNode);
if (backing != null) {
bind(new TypeLiteral<Map<String, InputStream>>() {
}).toInstance(backing);
}).annotatedWith(Names.named("yaml")).toInstance(backing);
} else {
bind(new TypeLiteral<Map<String, InputSupplier<InputStream>>>() {
}).toInstance(BACKING);
}).annotatedWith(Names.named("yaml")).toInstance(BACKING);
bind(new TypeLiteral<Map<String, InputStream>>() {
}).to(new TypeLiteral<CopyInputStreamInputSupplierMap>() {
}).annotatedWith(Names.named("yaml")).to(new TypeLiteral<YAMLCopyInputStreamInputSupplierMap>() {
});
}
}
@Singleton
public static class YAMLCopyInputStreamInputSupplierMap extends CopyInputStreamInputSupplierMap {
@Inject
public YAMLCopyInputStreamInputSupplierMap(@Named("yaml") Map<String, InputSupplier<InputStream>> toMap,
CopyInputStreamIntoSupplier putFunction) {
super(toMap, putFunction);
}
}
@Provides
@Singleton
protected Map<String, Node> provideNodeStore(Map<String, YamlNode> backing,
Function<Node, YamlNode> yamlSerializer, Function<YamlNode, Node> yamlDeserializer) {
return new TransformingMap<String, YamlNode, Node>(backing, yamlDeserializer, yamlSerializer);
protected Cache<String, Node> provideNodeStore(Map<String, YamlNode> backing, Function<Node, YamlNode> yamlSerializer,
Function<YamlNode, Node> yamlDeserializer) {
return CacheBuilder.newBuilder().build(CacheLoader.from(Functions.forMap(new TransformingMap<String, YamlNode, Node>(backing, yamlDeserializer, yamlSerializer))));
}
@Provides
@Singleton
protected Map<String, YamlNode> provideYamlStore(Map<String, InputStream> backing,
Function<YamlNode, InputStream> yamlSerializer, Function<InputStream, YamlNode> yamlDeserializer) {
protected Map<String, YamlNode> provideYamlStore(@Named("yaml") Map<String, InputStream> backing,
Function<YamlNode, InputStream> yamlSerializer, Function<InputStream, YamlNode> yamlDeserializer) {
return new TransformingMap<String, InputStream, YamlNode>(backing, yamlDeserializer, yamlSerializer);
}
}

View File

@ -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<InputStream, Map<String, Node>> {
public class NodesFromYamlStream implements Function<InputStream, Cache<String, Node>> {
/**
* Type-safe config class for YAML
@ -76,7 +80,7 @@ public class NodesFromYamlStream implements Function<InputStream, Map<String, No
}
@Override
public Map<String, Node> apply(InputStream source) {
public Cache<String, Node> apply(InputStream source) {
Constructor constructor = new Constructor(Config.class);
@ -87,17 +91,23 @@ public class NodesFromYamlStream implements Function<InputStream, Map<String, No
TypeDescription configDesc = new TypeDescription(Config.class);
configDesc.putListPropertyType("nodes", YamlNode.class);
constructor.addTypeDescription(configDesc);
// note that snakeyaml also throws nosuchmethod error when you use the non-deprecated
// note that snakeyaml also throws nosuchmethod error when you use the
// non-deprecated
// constructor
Yaml yaml = new Yaml(new Loader(constructor));
Config config = (Config) yaml.load(source);
checkState(config != null, "missing config: class");
checkState(config.nodes != null, "missing nodes: collection");
return Maps.uniqueIndex(Iterables.transform(config.nodes, YamlNode.toNode), new Function<Node, String>() {
public String apply(Node node) {
return node.getId();
}
});
Map<String, Node> backingMap = Maps.uniqueIndex(Iterables.transform(config.nodes, YamlNode.toNode),
new Function<Node, String>() {
public String apply(Node node) {
return node.getId();
}
});
Cache<String, Node> cache = CacheBuilder.newBuilder().build(CacheLoader.from(Functions.forMap(backingMap)));
for (String node : backingMap.keySet())
cache.getUnchecked(node);
return cache;
}
}

View File

@ -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<Map<String, Node>> nodes;
private final Supplier<Cache<String, Node>> nodes;
private final NodeToNodeMetadata converter;
private final JustProvider locationSupplier;
@Inject
public BYONComputeServiceAdapter(Supplier<Map<String, Node>> nodes, NodeToNodeMetadata converter,
public BYONComputeServiceAdapter(Supplier<Cache<String, Node>> 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<NodeMetadata> listNodes() {
return Iterables.transform(nodes.get().values(), converter);
return Iterables.transform(nodes.get().asMap().values(), converter);
}
@Override
public Iterable<Location> listLocations() {
Builder<Location> locations = ImmutableSet.builder();
Location provider = Iterables.getOnlyElement(locationSupplier.get());
Set<String> zones = ImmutableSet.copyOf(Iterables.filter(Iterables.transform(nodes.get().values(),
Set<String> zones = ImmutableSet.copyOf(Iterables.filter(Iterables.transform(nodes.get().asMap().values(),
new Function<Node, String>() {
@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;
}

View File

@ -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<Map<String, Node>> {
public class NodesParsedFromSupplier implements Supplier<Cache<String, Node>> {
@Resource
protected Logger logger = Logger.NULL;
private final Supplier<InputStream> supplier;
private final Function<InputStream, Map<String, Node>> parser;
private final Function<InputStream, Cache<String, Node>> parser;
@Inject
NodesParsedFromSupplier(@Provider Supplier<InputStream> supplier, Function<InputStream, Map<String, Node>> parser) {
NodesParsedFromSupplier(@Provider Supplier<InputStream> supplier, Function<InputStream, Cache<String, Node>> parser) {
this.supplier = checkNotNull(supplier, "supplier");
this.parser = checkNotNull(parser, "parser");
}
@Override
public Map<String, Node> get() {
Map<String, Node> nodes = parser.apply(supplier.get());
public Cache<String, Node> get() {
Cache<String, Node> nodes = parser.apply(supplier.get());
checkState(nodes != null && nodes.size() > 0, "no nodes parsed from supplier: %s", supplier);
return nodes;
}

View File

@ -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.<Module> of(new CacheNodeStoreModule(ImmutableMap.<String, Node> 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.<Module> of());
}
@Test
public void testNodesParseWithClasspathUrl() throws Exception {
assertNodesParse("classpath:///test1.yaml");
assertNodesParse("classpath:///test1.yaml", ImmutableSet.<Module> of());
}
private void assertNodesParse(String endpoint) {
private void assertNodesParse(String endpoint, Iterable<Module> 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
.<Module> of(new SshjSshClientModule()), props);
context = new ComputeServiceContextFactory().createContext("byon", "foo", "bar", modules, props);
assertEquals(context.getProviderSpecificContext().getEndpoint(), URI.create(endpoint));
@SuppressWarnings("unchecked")
Supplier<Map<String, Node>> supplier = (Supplier<Map<String, Node>>) context.getProviderSpecificContext()
.getApi();
Supplier<Cache<String, Node>> supplier = (Supplier<Cache<String, Node>>) context.getProviderSpecificContext()
.getApi();
assertEquals(supplier.get().size(), context.getComputeService().listNodes().size());
assertEquals(supplier.get(), ImmutableMap.<String, Node> of(NodesFromYamlTest.TEST1.getId(),
NodesFromYamlTest.TEST1));
assertEquals(supplier.get().asMap(),
ImmutableMap.<String, Node> 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
.<Module> of(new SshjSshClientModule()), props);
context = new ComputeServiceContextFactory().createContext("byon", "foo", "bar",
ImmutableSet.<Module> of(), props);
assertEquals(context.getProviderSpecificContext().getEndpoint(), URI.create(endpoint));
@SuppressWarnings("unchecked")
Supplier<Map<String, Node>> supplier = (Supplier<Map<String, Node>>) context.getProviderSpecificContext()
.getApi();
Supplier<Cache<String, Node>> supplier = (Supplier<Cache<String, Node>>) context.getProviderSpecificContext()
.getApi();
assertEquals(supplier.get().size(), context.getComputeService().listNodes().size());
assertEquals(supplier.get(), ImmutableMap.<String, Node> of(NodesFromYamlTest.TEST2.getId(),
NodesFromYamlTest.TEST2, NodesFromYamlTest.TEST3.getId(), NodesFromYamlTest.TEST3));
assertEquals(supplier.get().asMap(), ImmutableMap.<String, Node> 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)

View File

@ -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<String, Node> 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<String, Node> map = Maps.newConcurrentMap();
Injector injector = createInjectorWithProvidedMap(map);
assertEquals(injector.getInstance(Key.get(new TypeLiteral<Cache<String, Node>>() {
})).asMap(), map);
Cache<String, Node> 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<String, Node> 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<String, Node> map = Maps.newConcurrentMap();
Cache<String, Node> 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<String, Node> getStore(Injector injector) {
return injector.getInstance(Key.get(new TypeLiteral<Cache<String, Node>>() {
}));
}
private Injector createInjectorWithProvidedMap(Map<String, Node> map) {
return Guice.createInjector(new CacheNodeStoreModule(map), new AbstractModule() {
@Override
public void configure() {
bind(new TypeLiteral<Supplier<InputStream>>() {
}).annotatedWith(Provider.class).toInstance(Suppliers.<InputStream> ofInstance(null));
}
});
}
private Injector createInjectorWithProvidedCache(Cache<String, Node> cache) {
return Guice.createInjector(new CacheNodeStoreModule(cache), new AbstractModule() {
@Override
public void configure() {
bind(new TypeLiteral<Supplier<InputStream>>() {
}).annotatedWith(Provider.class).toInstance(Suppliers.<InputStream> ofInstance(null));
}
});
}
private void check(Map<String, Node> map, Cache<String, Node> 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<String, Node> map, Cache<String, Node> 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<String, Node> map, Cache<String, Node> 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<String, Node> map, Cache<String, Node> 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);
}
}

View File

@ -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<String, InputStream> map = new CopyInputStreamInputSupplierMap(
new ConcurrentHashMap<String, InputSupplier<InputStream>>());
new ConcurrentHashMap<String, InputSupplier<InputStream>>());
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<String, InputStream> map = new CopyInputStreamInputSupplierMap(
new ConcurrentHashMap<String, InputSupplier<InputStream>>());
new ConcurrentHashMap<String, InputSupplier<InputStream>>());
Injector injector = createInjectorWithProvidedMap(map);
assertEquals(injector.getInstance(Key.get(new TypeLiteral<Map<String, InputStream>>() {
})), map);
Map<String, Node> store = getStore(injector);
}, Names.named("yaml"))), map);
Cache<String, Node> 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<String, InputStream> map = new CopyInputStreamInputSupplierMap(
new ConcurrentHashMap<String, InputSupplier<InputStream>>());
new ConcurrentHashMap<String, InputSupplier<InputStream>>());
put(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename");
checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename");
@ -100,52 +107,77 @@ public class YamlNodeStoreModuleTest {
Map<String, InputStream> 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<String, Node> getStore(Injector injector) {
return injector.getInstance(Key.get(new TypeLiteral<Map<String, Node>>() {
protected Cache<String, Node> getStore(Injector injector) {
return injector.getInstance(Key.get(new TypeLiteral<Cache<String, Node>>() {
}));
}
protected Map<String, InputStream> getMap(Injector injector) {
return injector.getInstance(Key.get(new TypeLiteral<Map<String, InputStream>>() {
}));
}, Names.named("yaml")));
}
protected Injector createInjectorWithProvidedMap(Map<String, InputStream> map) {
return Guice.createInjector(new YamlNodeStoreModule(map));
return Guice.createInjector(new YamlNodeStoreModule(map), new AbstractModule() {
@Override
protected void configure() {
bind(new TypeLiteral<Supplier<InputStream>>() {
}).annotatedWith(Provider.class).toInstance(Suppliers.<InputStream> ofInstance(null));
}
});
}
protected Injector createInjector() {
return Guice.createInjector(new YamlNodeStoreModule());
return Guice.createInjector(new YamlNodeStoreModule(), new AbstractModule() {
@Override
protected void configure() {
bind(new TypeLiteral<Supplier<InputStream>>() {
}).annotatedWith(Provider.class).toInstance(Suppliers.<InputStream> ofInstance(null));
}
});
}
protected void check(Map<String, InputStream> map, Map<String, Node> store, String key, String id, String name)
throws IOException {
protected void check(Map<String, InputStream> map, Cache<String, Node> 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<String, InputStream> map, Map<String, Node> store, String key) {
store.remove(key);
protected void remove(Map<String, InputStream> map, Cache<String, Node> 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<String, InputStream> map, Map<String, Node> store, String key, String id,
String name) throws IOException {
assertEquals(store.size(), 1);
protected void checkConsistent(Map<String, InputStream> map, Cache<String, Node> 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<String, InputStream> map, Map<String, Node> store, String key, String id, String name) {
protected void put(Map<String, InputStream> map, Cache<String, Node> 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);
}
}

View File

@ -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<String, Credentials> credentialStore = Maps.newLinkedHashMap();
NodeToNodeMetadata parser = new NodeToNodeMetadata(Suppliers.ofInstance(provider), Suppliers
.<Set<? extends Location>> ofInstance(ImmutableSet.of(provider, zoneCalled("virginia", provider))),
new SupplyFromProviderURIOrNodesProperty(URI.create("test")), credentialStore);
NodeToNodeMetadata parser = new NodeToNodeMetadata(Suppliers.ofInstance(provider),
Suppliers.<Set<? extends Location>> 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));

View File

@ -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)

View File

@ -22,6 +22,7 @@ import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_TIMEOUT_SECURITYGROUP_PRESENT;
import java.util.Properties;
@ -40,6 +41,7 @@ public class EC2PropertiesBuilder extends PropertiesBuilder {
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
properties.setProperty(PROPERTY_API_VERSION, EC2AsyncClient.VERSION);
properties.setProperty(PROPERTY_EC2_AMI_OWNERS, "*");
properties.setProperty(PROPERTY_EC2_TIMEOUT_SECURITYGROUP_PRESENT, "500");
return properties;
}

View File

@ -18,8 +18,11 @@
*/
package org.jclouds.ec2.compute.config;
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_TIMEOUT_SECURITYGROUP_PRESENT;
import java.security.SecureRandom;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import javax.inject.Singleton;
@ -44,13 +47,16 @@ import org.jclouds.ec2.compute.functions.RegionAndIdToImage;
import org.jclouds.ec2.compute.functions.RunningInstanceToNodeMetadata;
import org.jclouds.ec2.compute.internal.EC2TemplateBuilderImpl;
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.compute.predicates.SecurityGroupPresent;
import org.jclouds.ec2.domain.InstanceState;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.ec2.domain.RunningInstance;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.RestContextImpl;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
@ -144,6 +150,14 @@ public class EC2ComputeServiceDependenciesModule extends AbstractModule {
return CacheBuilder.newBuilder().build(in);
}
@Provides
@Singleton
@Named("SECURITY")
protected Predicate<RegionAndName> securityGroupEventualConsistencyDelay(SecurityGroupPresent in,
@Named(PROPERTY_EC2_TIMEOUT_SECURITYGROUP_PRESENT) long msDelay) {
return new RetryablePredicate<RegionAndName>(in, msDelay, 100l, TimeUnit.MILLISECONDS);
}
@Provides
@Singleton
// keys that we know about.

View File

@ -31,8 +31,10 @@ import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.UserIdGroupPair;
import org.jclouds.ec2.services.SecurityGroupClient;
import org.jclouds.logging.Logger;
import com.google.common.base.Predicate;
import com.google.common.cache.CacheLoader;
import com.google.common.collect.Iterables;
@ -45,16 +47,25 @@ public class CreateSecurityGroupIfNeeded extends CacheLoader<RegionAndName, Stri
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
protected final EC2Client ec2Client;
protected final SecurityGroupClient securityClient;
protected final Predicate<RegionAndName> securityGroupEventualConsistencyDelay;
@Inject
public CreateSecurityGroupIfNeeded(EC2Client ec2Client) {
this.ec2Client = checkNotNull(ec2Client, "ec2Client");
public CreateSecurityGroupIfNeeded(EC2Client ec2Client,
@Named("SECURITY") Predicate<RegionAndName> securityGroupEventualConsistencyDelay) {
this(checkNotNull(ec2Client, "ec2Client").getSecurityGroupServices(), securityGroupEventualConsistencyDelay);
}
public CreateSecurityGroupIfNeeded(SecurityGroupClient securityClient,
@Named("SECURITY") Predicate<RegionAndName> securityGroupEventualConsistencyDelay) {
this.securityClient = checkNotNull(securityClient, "securityClient");
this.securityGroupEventualConsistencyDelay = checkNotNull(securityGroupEventualConsistencyDelay,
"securityGroupEventualConsistencyDelay");
}
@Override
public String load(RegionAndName from) {
RegionNameAndIngressRules realFrom = RegionNameAndIngressRules.class.cast(from);
RegionNameAndIngressRules realFrom = RegionNameAndIngressRules.class.cast(from);
createSecurityGroupInRegion(from.getRegion(), from.getName(), realFrom.getPorts());
return from.getName();
}
@ -64,7 +75,11 @@ public class CreateSecurityGroupIfNeeded extends CacheLoader<RegionAndName, Stri
checkNotNull(name, "name");
logger.debug(">> creating securityGroup region(%s) name(%s)", region, name);
try {
ec2Client.getSecurityGroupServices().createSecurityGroupInRegion(region, name, name);
securityClient.createSecurityGroupInRegion(region, name, name);
boolean created = securityGroupEventualConsistencyDelay.apply(new RegionAndName(region, name));
if (!created)
throw new RuntimeException(String.format("security group %s/%s is not available after creating", region,
name));
logger.debug("<< created securityGroup(%s)", name);
for (int port : ports) {
createIngressRuleForTCPPort(region, name, port);
@ -79,17 +94,14 @@ public class CreateSecurityGroupIfNeeded extends CacheLoader<RegionAndName, Stri
private void createIngressRuleForTCPPort(String region, String name, int port) {
logger.debug(">> authorizing securityGroup region(%s) name(%s) port(%s)", region, name, port);
ec2Client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(region, name, IpProtocol.TCP, port,
port, "0.0.0.0/0");
securityClient.authorizeSecurityGroupIngressInRegion(region, name, IpProtocol.TCP, port, port, "0.0.0.0/0");
logger.debug("<< authorized securityGroup(%s)", name);
}
private void authorizeGroupToItself(String region, String name) {
logger.debug(">> authorizing securityGroup region(%s) name(%s) permission to itself", region, name);
String myOwnerId = Iterables.get(
ec2Client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, name), 0).getOwnerId();
ec2Client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(region, name,
new UserIdGroupPair(myOwnerId, name));
String myOwnerId = Iterables.get(securityClient.describeSecurityGroupsInRegion(region, name), 0).getOwnerId();
securityClient.authorizeSecurityGroupIngressInRegion(region, name, new UserIdGroupPair(myOwnerId, name));
logger.debug("<< authorized securityGroup(%s)", name);
}

View File

@ -0,0 +1,70 @@
/**
* 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.ec2.compute.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.NoSuchElementException;
import javax.annotation.Resource;
import javax.inject.Singleton;
import org.jclouds.ec2.EC2Client;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.domain.SecurityGroup;
import org.jclouds.logging.Logger;
import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
/**
*
* @author Adrian Cole
*/
@Singleton
public class SecurityGroupPresent implements Predicate<RegionAndName> {
private final EC2Client client;
@Resource
protected Logger logger = Logger.NULL;
@Inject
public SecurityGroupPresent(EC2Client client) {
this.client = checkNotNull(client, "client");
}
public boolean apply(RegionAndName securityGroup) {
logger.trace("looking for security group %s/%s", securityGroup.getRegion(), securityGroup.getName());
try {
return refresh(securityGroup) != null;
} catch (ResourceNotFoundException e) {
return false;
} catch (NoSuchElementException e) {
return false;
}
}
protected SecurityGroup refresh(RegionAndName securityGroup) {
return Iterables.getOnlyElement(client.getSecurityGroupServices().describeSecurityGroupsInRegion(
securityGroup.getRegion(), securityGroup.getName()));
}
}

View File

@ -37,6 +37,12 @@ public class UserIdGroupPair implements Comparable<UserIdGroupPair> {
}
@Override
public String toString() {
return "[userId=" + userId + ", groupName=" + groupName + "]";
}
/**
* {@inheritDoc}
*/

View File

@ -31,5 +31,10 @@ public interface EC2Constants {
* the ami owners you wish to use in {@link ComputeService}
*/
public static final String PROPERTY_EC2_AMI_OWNERS = "jclouds.ec2.ami-owners";
/**
* Eventual consistency delay for retrieving a security group after it is created (in ms)
*/
public static final String PROPERTY_EC2_TIMEOUT_SECURITYGROUP_PRESENT = "jclouds.ec2.timeout.securitygroup-present";
}

View File

@ -0,0 +1,110 @@
/**
* 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.ec2.compute.functions;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.SecurityGroup;
import org.jclouds.ec2.domain.UserIdGroupPair;
import org.jclouds.ec2.services.SecurityGroupClient;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", singleThreaded = true, testName = "CreateSecurityGroupIfNeeded")
public class CreateSecurityGroupIfNeededTest {
@SuppressWarnings("unchecked")
@Test
public void testWhenPort22AndToItselfAuthorizesIngressTwice() throws ExecutionException {
SecurityGroupClient client = createMock(SecurityGroupClient.class);
Predicate<RegionAndName> tester = Predicates.alwaysTrue();
SecurityGroup group = createNiceMock(SecurityGroup.class);
Set<SecurityGroup> groups = ImmutableSet.<SecurityGroup> of(group);
client.createSecurityGroupInRegion("region", "group", "group");
client.authorizeSecurityGroupIngressInRegion("region", "group", IpProtocol.TCP, 22, 22, "0.0.0.0/0");
expect(client.describeSecurityGroupsInRegion("region", "group")).andReturn(Set.class.cast(groups));
expect(group.getOwnerId()).andReturn("ownerId");
client.authorizeSecurityGroupIngressInRegion("region", "group", new UserIdGroupPair("ownerId", "group"));
replay(client);
replay(group);
CreateSecurityGroupIfNeeded function = new CreateSecurityGroupIfNeeded(client, tester);
assertEquals("group", function.load(new RegionNameAndIngressRules("region", "group", new int[] { 22 }, true)));
verify(client);
verify(group);
}
@Test
public void testIllegalStateExceptionCreatingGroupJustReturns() throws ExecutionException {
SecurityGroupClient client = createMock(SecurityGroupClient.class);
Predicate<RegionAndName> tester = Predicates.alwaysTrue();
client.createSecurityGroupInRegion("region", "group", "group");
expectLastCall().andThrow(new IllegalStateException());
replay(client);
CreateSecurityGroupIfNeeded function = new CreateSecurityGroupIfNeeded(client, tester);
assertEquals("group", function.load(new RegionNameAndIngressRules("region", "group", new int[] { 22 }, true)));
verify(client);
}
@Test(expectedExceptions = RuntimeException.class)
public void testWhenEventualConsistencyExpiresIllegalStateException() throws ExecutionException {
SecurityGroupClient client = createMock(SecurityGroupClient.class);
Predicate<RegionAndName> tester = Predicates.alwaysFalse();
client.createSecurityGroupInRegion("region", "group", "group");
replay(client);
CreateSecurityGroupIfNeeded function = new CreateSecurityGroupIfNeeded(client, tester);
function.load(new RegionNameAndIngressRules("region", "group", new int[] { 22 }, true));
}
}

View File

@ -59,6 +59,20 @@ public class CacheLearningTest {
} catch (NullPointerException e) {
assertEquals(e.getMessage(), "testLoader returned null for key foo.");
}
try {
assertEquals(cache.activeEntries(Integer.MAX_VALUE).size(), 1);
assert false : "I suppose this works now! Go hunt asMap().keySet()!";
} catch (UnsupportedOperationException e) {
}
try {
cache.asMap().put("foo", "bar");
assertEquals(cache.get("foo"), "bar");
assert false : "I suppose this works now! Go hunt for invalidate calls!";
} catch (UnsupportedOperationException e) {
}
try {
cache.get("exception");
} catch (ExecutionException e) {

View File

@ -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");

View File

@ -78,7 +78,7 @@ public class CloudSigmaComputeServiceContextModule
protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) {
// until there is a way to query by drive info that can suggest which
// drives are ssh boot
return template.imageId("a3011b07-3f04-467e-9390-f9a85d859de1").minRam(1024);
return template.imageId("f3c7c665-cd54-4a78-8fd2-7ec2f028cf29").minRam(1024);
// return
// template.osFamily(UBUNTU).osVersionMatches("1[10].[10][04]").os64Bit(true).minRam(1024);
}

View File

@ -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()));

View File

@ -19,6 +19,8 @@
package org.jclouds.cloudsigma.compute;
import org.jclouds.compute.BaseComputeServiceLiveTest;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test;
@ -37,5 +39,14 @@ public class CloudSigmaComputeServiceLiveTest extends BaseComputeServiceLiveTest
protected Module getSshModule() {
return new SshjSshClientModule();
}
protected void checkResponseEqualsHostname(ExecResponse execResponse, NodeMetadata node1) {
// hostname is not predictable based on node metadata
assert execResponse.getOutput().trim().equals("ubuntu");
}
@Override
public void testOptionToNotBlock() {
// start call has to block until we have a pool of reserved pre-cloned drives.
}
}

View File

@ -52,9 +52,8 @@ public class CloudSigmaTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTe
public boolean apply(OsFamilyVersion64Bit input) {
switch (input.family) {
case UBUNTU:
return input.version.equals("11.04") || (input.version.equals("11.04") && !input.is64Bit)
|| !input.version.equals("11.10")
&& (input.version.equals("") || !(input.version.matches("^[89].*")) && input.is64Bit);
return input.version.equals("11.04") || (input.version.equals("10.04") && !input.is64Bit)
|| (input.version.equals("10.10") && input.is64Bit) || input.version.equals("");
case SOLARIS:
return !input.is64Bit;
case DEBIAN:
@ -77,8 +76,8 @@ public class CloudSigmaTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTe
@Override
public void testDefaultTemplateBuilder() throws IOException {
Template defaultTemplate = context.getComputeService().templateBuilder().build();
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "11.04");
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "10.04");
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), false);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
}

View File

@ -18,10 +18,11 @@
*/
package org.jclouds.virtualbox.experiment;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
import org.jclouds.byon.Node;
import org.jclouds.byon.config.CacheNodeStoreModule;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.OsFamily;
@ -29,41 +30,48 @@ import org.jclouds.encryption.bouncycastle.config.BouncyCastleCryptoModule;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
import org.jclouds.sshj.config.SshjSshClientModule;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
public class TestUtils {
public static ComputeServiceContext computeServiceForLocalhost() throws FileNotFoundException, IOException {
Properties contextProperties = new Properties();
public static ComputeServiceContext computeServiceForLocalhost() throws IOException {
StringBuilder nodes = new StringBuilder();
nodes.append("nodes:\n");
nodes.append(" - id: host\n");
nodes.append(" name: host installing virtualbox\n");
nodes.append(" hostname: localhost\n");
nodes.append(" os_family: ").append(OsFamily.LINUX).append("\n");
nodes.append(" os_description: ").append(System.getProperty("os.name")).append("\n");
nodes.append(" os_version: ").append(System.getProperty("os.version")).append("\n");
nodes.append(" group: ").append("ssh").append("\n");
nodes.append(" username: ").append(System.getProperty("user.name")).append("\n");
nodes.append(" credential_url: file://").append(System.getProperty("user.home")).append("/.ssh/id_rsa")
.append("\n");
nodes.append("\n");
nodes.append(" - id: guest\n");
nodes.append(" name: new guest\n");
nodes.append(" hostname: localhost\n");
nodes.append(" login_port: 2222\n");
nodes.append(" os_family: ubuntu").append("\n");
nodes.append(" os_description: ubuntu/11.04").append("\n");
nodes.append(" os_version: 11.04").append("\n");
nodes.append(" group: guest").append("\n");
nodes.append(" username: toor").append("\n");
nodes.append(" sudo_password: password").append("\n");
nodes.append(" credential: password").append("\n");
Node host = Node.builder().id("host")
.name("host installing virtualbox")
.hostname("localhost")
.osFamily(OsFamily.LINUX.toString())
.osDescription(System.getProperty("os.name"))
.osVersion(System.getProperty("os.version"))
.group("ssh")
.username(System.getProperty("user.name"))
.credentialUrl(privateKeyFile())
.build();
Node guest = Node.builder().id("guest")
.name("new guest")
.hostname("localhost")
.loginPort(2222)
.osFamily(OsFamily.UBUNTU.toString())
.osDescription("ubuntu/11.04")
.osVersion(System.getProperty("11.04"))
.group("guest")
.username("toor")
.sudoPassword("password")
.credential("password")
.build();
contextProperties.setProperty("byon.nodes", nodes.toString());
final Map<String, Node> nodeMap = ImmutableMap.<String, Node>builder().put("host", host).put("guest", guest).build();
return new ComputeServiceContextFactory().createContext("byon", "foo", "bar", ImmutableSet.<Module>of(
new SshjSshClientModule(), new SLF4JLoggingModule(), new BouncyCastleCryptoModule(), new CacheNodeStoreModule(nodeMap)));
}
return new ComputeServiceContextFactory().createContext("byon", "foo", "bar", ImmutableSet.<Module> of(
new SshjSshClientModule(), new SLF4JLoggingModule(), new BouncyCastleCryptoModule()), contextProperties);
private static URI privateKeyFile() {
try {
return new URI("file://" + System.getProperty("user.home") + "/.ssh/id_rsa");
} catch (URISyntaxException e) {
e.printStackTrace();
}
return null;
}
}

View File

@ -25,6 +25,7 @@ import static org.testng.Assert.assertEquals;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
@ -34,17 +35,23 @@ import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.domain.Credentials;
import org.jclouds.encryption.bouncycastle.config.BouncyCastleCryptoModule;
import org.jclouds.logging.Logger;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
import org.jclouds.net.IPSocket;
import org.jclouds.predicates.InetSocketAddressConnect;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.ssh.SshClient;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.BeforeMethod;
@ -63,8 +70,10 @@ import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.inject.Injector;
import com.google.inject.Module;
@Test(groups = "live", testName = "virtualbox.VirtualboxLiveTest")
public class VirtualboxLiveTest {
@ -227,7 +236,7 @@ public class VirtualboxLiveTest {
mutable.getNetworkAdapter(new Long(0)).setAttachmentType(NetworkAttachmentType.Bridged);
mutable.getNetworkAdapter(new Long(0)).setAdapterType(NetworkAdapterType.Am79C973);
mutable.getNetworkAdapter(new Long(0)).setMACAddress("0800279DA478");
mutable.getNetworkAdapter(new Long(0)).setBridgedInterface("virbr0");
mutable.getNetworkAdapter(new Long(0)).setBridgedInterface(hostInterface.trim());
mutable.getNetworkAdapter(new Long(0)).setEnabled(true);
mutable.saveSettings();
session.unlockMachine();
@ -247,15 +256,15 @@ public class VirtualboxLiveTest {
String simplifiedMacAddressOfClonedVM = macAddressOfClonedVM;
/*
if(isOSX(hostId)) {
if(simplifiedMacAddressOfClonedVM.contains("00"))
simplifiedMacAddressOfClonedVM = new StringBuffer(simplifiedMacAddressOfClonedVM).delete(simplifiedMacAddressOfClonedVM.indexOf("00"), simplifiedMacAddressOfClonedVM.indexOf("00") + 1).toString();
if(simplifiedMacAddressOfClonedVM.contains("0"))
if(simplifiedMacAddressOfClonedVM.indexOf("0") + 1 != ':' && simplifiedMacAddressOfClonedVM.indexOf("0") - 1 != ':')
simplifiedMacAddressOfClonedVM = new StringBuffer(simplifiedMacAddressOfClonedVM).delete(simplifiedMacAddressOfClonedVM.indexOf("0"), simplifiedMacAddressOfClonedVM.indexOf("0") + 1).toString();
*/
runScriptOnNode(hostId, "for i in $(seq 1 254) ; do ping -c 1 -t 1 192.168.122.$i & done", runAsRoot(false).wrapInInitScript(false));
}
runScriptOnNode(hostId, "for i in $(seq 1 254) ; do ping -c 1 -t 1 192.168.1.$i & done", runAsRoot(false).wrapInInitScript(false));
String arpLine = runScriptOnNode(hostId, "arp -an | grep " + simplifiedMacAddressOfClonedVM, runAsRoot(false).wrapInInitScript(false)).getOutput();
String ipAddress = arpLine.substring(arpLine.indexOf("(") + 1, arpLine.indexOf(")"));
@ -271,10 +280,9 @@ public class VirtualboxLiveTest {
}
}
*/
//TODO
IPSocket socket = new IPSocket(ipAddress, 22);
checkSSH(socket);
runScriptOnNode(guestId, "echo ciao");
}
private void launchVMProcess(IMachine machine, ISession session) {