mirror of https://github.com/apache/jclouds.git
JCLOUDS-925: Add support to start and stop instances in the ComputeService
This commit is contained in:
parent
55348c0ddb
commit
2e7ca20f1c
|
@ -16,9 +16,12 @@
|
|||
*/
|
||||
package org.jclouds.googlecomputeengine.compute;
|
||||
|
||||
import static autovalue.shaded.com.google.common.common.collect.Sets.newHashSet;
|
||||
import static com.google.common.collect.Iterables.filter;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
|
||||
import static org.jclouds.compute.predicates.NodePredicates.all;
|
||||
import static org.jclouds.googlecloud.internal.ListPages.concat;
|
||||
|
||||
import java.util.Map;
|
||||
|
@ -62,6 +65,8 @@ import org.jclouds.googlecomputeengine.domain.Operation;
|
|||
import org.jclouds.googlecomputeengine.features.FirewallApi;
|
||||
import org.jclouds.scriptbuilder.functions.InitAdminAccess;
|
||||
|
||||
import autovalue.shaded.com.google.common.common.collect.ImmutableSet;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Predicate;
|
||||
|
@ -119,6 +124,31 @@ public final class GoogleComputeEngineService extends BaseComputeService {
|
|||
this.api = api;
|
||||
this.operationDone = operationDone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyNode(String id) {
|
||||
// GCE does not return TERMINATED nodes, so in practice no node will never reach the TERMINATED
|
||||
// state, and the deleted nodes will never be returned.
|
||||
// In order to be able to clean up the resources associated to the deleted nodes, we have to retrieve
|
||||
// the details of the nodes before deleting them.
|
||||
NodeMetadata node = getNodeMetadata(id);
|
||||
super.destroyNode(id);
|
||||
cleanUpIncidentalResourcesOfDeadNodes(ImmutableSet.of(node));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) {
|
||||
// GCE does not return TERMINATED nodes, so in practice no node will never reach the TERMINATED
|
||||
// state, and the deleted nodes will never be returned.
|
||||
// In order to be able to clean up the resources associated to the deleted nodes, we have to retrieve
|
||||
// the details of the nodes before deleting them.
|
||||
Set<? extends NodeMetadata> nodes = newHashSet(filter(listNodesDetailsMatching(all()), filter));
|
||||
super.destroyNodesMatching(filter); // This returns an empty list (a list of null elements) in GCE, as the api does not return deleted nodes
|
||||
cleanUpIncidentalResourcesOfDeadNodes(nodes);
|
||||
return nodes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected synchronized void cleanUpIncidentalResourcesOfDeadNodes(Set<? extends NodeMetadata> deadNodes) {
|
||||
|
|
|
@ -257,12 +257,12 @@ public final class GoogleComputeEngineServiceAdapter
|
|||
waitOperationDone(resources.resetInstance(URI.create(checkNotNull(selfLink, "id"))));
|
||||
}
|
||||
|
||||
@Override public void resumeNode(String name) {
|
||||
throw new UnsupportedOperationException("resume is not supported by GCE");
|
||||
@Override public void resumeNode(String selfLink) {
|
||||
waitOperationDone(resources.startInstance(URI.create(checkNotNull(selfLink, "id"))));
|
||||
}
|
||||
|
||||
@Override public void suspendNode(String name) {
|
||||
throw new UnsupportedOperationException("suspend is not supported by GCE");
|
||||
@Override public void suspendNode(String selfLink) {
|
||||
waitOperationDone(resources.stopInstance(URI.create(checkNotNull(selfLink, "id"))));
|
||||
}
|
||||
|
||||
private void waitOperationDone(Operation operation) {
|
||||
|
|
|
@ -52,7 +52,7 @@ import org.jclouds.googlecomputeengine.compute.functions.MachineTypeToHardware;
|
|||
import org.jclouds.googlecomputeengine.compute.functions.OrphanedGroupsFromDeadNodes;
|
||||
import org.jclouds.googlecomputeengine.compute.functions.Resources;
|
||||
import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions;
|
||||
import org.jclouds.googlecomputeengine.compute.predicates.AllNodesInGroupTerminated;
|
||||
import org.jclouds.googlecomputeengine.compute.predicates.GroupIsEmpty;
|
||||
import org.jclouds.googlecomputeengine.compute.predicates.AtomicInstanceVisible;
|
||||
import org.jclouds.googlecomputeengine.compute.predicates.AtomicOperationDone;
|
||||
import org.jclouds.googlecomputeengine.compute.strategy.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
|
||||
|
@ -112,7 +112,7 @@ public final class GoogleComputeEngineServiceContextModule
|
|||
}).to(OrphanedGroupsFromDeadNodes.class);
|
||||
|
||||
bind(new TypeLiteral<Predicate<String>>() {
|
||||
}).to(AllNodesInGroupTerminated.class);
|
||||
}).to(GroupIsEmpty.class);
|
||||
|
||||
bind(FirewallTagNamingConvention.Factory.class).in(Scopes.SINGLETON);
|
||||
bindHttpApi(binder(), Resources.class);
|
||||
|
@ -175,7 +175,7 @@ public final class GoogleComputeEngineServiceContextModule
|
|||
.put(Instance.Status.RUNNING, NodeMetadata.Status.RUNNING)
|
||||
.put(Instance.Status.STOPPING, NodeMetadata.Status.PENDING)
|
||||
.put(Instance.Status.STOPPED, NodeMetadata.Status.SUSPENDED)
|
||||
.put(Instance.Status.TERMINATED, NodeMetadata.Status.TERMINATED).build();
|
||||
.put(Instance.Status.TERMINATED, NodeMetadata.Status.SUSPENDED).build();
|
||||
|
||||
@Provides Map<Instance.Status, NodeMetadata.Status> toPortableNodeStatus() {
|
||||
return toPortableNodeStatus;
|
||||
|
|
|
@ -63,9 +63,21 @@ public interface Resources {
|
|||
@DELETE
|
||||
@Fallback(NullOnNotFoundOr404.class) @Nullable Operation delete(@EndpointParam URI selfLink);
|
||||
|
||||
/** Hard-resets the instance by self-link and returns the operation in progres */
|
||||
/** Hard-resets the instance by self-link and returns the operation in progress */
|
||||
@Named("Instances:reset")
|
||||
@POST
|
||||
@Path("/reset")
|
||||
Operation resetInstance(@EndpointParam URI selfLink);
|
||||
|
||||
/** Starts the instance by self-link and returns the operation in progress */
|
||||
@Named("Instances:start")
|
||||
@POST
|
||||
@Path("/start")
|
||||
Operation startInstance(@EndpointParam URI selfLink);
|
||||
|
||||
/** Stops the instance by self-link and returns the operation in progress */
|
||||
@Named("Instances:stop")
|
||||
@POST
|
||||
@Path("/stop")
|
||||
Operation stopInstance(@EndpointParam URI selfLink);
|
||||
}
|
||||
|
|
|
@ -16,9 +16,8 @@
|
|||
*/
|
||||
package org.jclouds.googlecomputeengine.compute.predicates;
|
||||
|
||||
import static com.google.common.collect.Iterables.all;
|
||||
import static autovalue.shaded.com.google.common.common.collect.Iterables.isEmpty;
|
||||
import static com.google.common.collect.Sets.filter;
|
||||
import static org.jclouds.compute.predicates.NodePredicates.TERMINATED;
|
||||
import static org.jclouds.compute.predicates.NodePredicates.all;
|
||||
import static org.jclouds.compute.predicates.NodePredicates.inGroup;
|
||||
|
||||
|
@ -28,16 +27,16 @@ import org.jclouds.compute.ComputeService;
|
|||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
public final class AllNodesInGroupTerminated implements Predicate<String> {
|
||||
public final class GroupIsEmpty implements Predicate<String> {
|
||||
|
||||
private final ComputeService computeService;
|
||||
|
||||
@Inject AllNodesInGroupTerminated(ComputeService computeService) {
|
||||
@Inject GroupIsEmpty(ComputeService computeService) {
|
||||
this.computeService = computeService;
|
||||
}
|
||||
|
||||
|
||||
@Override public boolean apply(String groupName) {
|
||||
return all(filter(computeService.listNodesDetailsMatching(all()), inGroup(groupName)), TERMINATED);
|
||||
return isEmpty(filter(computeService.listNodesDetailsMatching(all()), inGroup(groupName)));
|
||||
}
|
||||
}
|
|
@ -17,18 +17,21 @@
|
|||
package org.jclouds.googlecomputeengine.compute;
|
||||
|
||||
import static com.google.common.collect.Iterables.contains;
|
||||
import static org.jclouds.util.Strings2.toStringAndClose;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.compute.ComputeServiceContext;
|
||||
import org.jclouds.compute.domain.Hardware;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
|
||||
import org.jclouds.googlecloud.internal.TestProperties;
|
||||
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
|
||||
import org.jclouds.googlecomputeengine.domain.MachineType;
|
||||
import org.jclouds.rest.AuthorizationException;
|
||||
import org.jclouds.sshj.config.SshjSshClientModule;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
@ -71,43 +74,28 @@ public class GoogleComputeEngineServiceLiveTest extends BaseComputeServiceLiveTe
|
|||
assertTrue(node.getUserMetadata().keySet().containsAll(userMetadata.keySet()));
|
||||
}
|
||||
|
||||
// do not run until the auth exception problem is figured out.
|
||||
@Test(enabled = false)
|
||||
@Test(expectedExceptions = AuthorizationException.class)
|
||||
@Override
|
||||
public void testCorrectAuthException() throws Exception {
|
||||
}
|
||||
|
||||
// reboot is not supported by GCE
|
||||
@Test(enabled = true, dependsOnMethods = "testGet")
|
||||
public void testReboot() throws Exception {
|
||||
}
|
||||
|
||||
// suspend/Resume is not supported by GCE
|
||||
@Test(enabled = true, dependsOnMethods = "testReboot")
|
||||
public void testSuspendResume() throws Exception {
|
||||
}
|
||||
|
||||
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
|
||||
public void testListNodesByIds() throws Exception {
|
||||
super.testGetNodesWithDetails();
|
||||
}
|
||||
|
||||
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
|
||||
@Override
|
||||
public void testGetNodesWithDetails() throws Exception {
|
||||
super.testGetNodesWithDetails();
|
||||
}
|
||||
|
||||
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
|
||||
@Override
|
||||
public void testListNodes() throws Exception {
|
||||
super.testListNodes();
|
||||
}
|
||||
|
||||
@Test(enabled = true, dependsOnMethods = {"testListNodes", "testGetNodesWithDetails", "testListNodesByIds"})
|
||||
@Override
|
||||
public void testDestroyNodes() {
|
||||
super.testDestroyNodes();
|
||||
ComputeServiceContext context = null;
|
||||
try {
|
||||
String credential = toStringAndClose(getClass().getResourceAsStream("/test"));
|
||||
Properties overrides = setupProperties();
|
||||
overrides.setProperty(provider + ".identity", "000000000000@developer.gserviceaccount.com");
|
||||
overrides.setProperty(provider + ".credential", credential);
|
||||
context = newBuilder()
|
||||
.modules(ImmutableSet.of(getLoggingModule(), credentialStoreModule))
|
||||
.overrides(overrides).build(ComputeServiceContext.class);
|
||||
context.getComputeService().listNodes();
|
||||
} catch (AuthorizationException e) {
|
||||
throw e;
|
||||
} catch (RuntimeException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
} finally {
|
||||
if (context != null)
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,7 +18,6 @@ package org.jclouds.googlecomputeengine.compute;
|
|||
|
||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||
import static org.jclouds.googlecomputeengine.domain.Instance.Status.RUNNING;
|
||||
import static org.jclouds.googlecomputeengine.domain.Instance.Status.TERMINATED;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.assertNull;
|
||||
|
@ -77,11 +76,12 @@ public class GoogleComputeEngineServiceMockTest extends BaseGoogleComputeEngineA
|
|||
server.enqueue(instanceWithNetworkAndStatus("test-delete-1", "default", RUNNING));
|
||||
server.enqueue(singleRegionSingleZoneResponse());
|
||||
server.enqueue(jsonResponse("/aggregated_machinetype_list.json")); // Why are we getting machineTypes to delete an instance?
|
||||
server.enqueue(instanceWithNetworkAndStatus("test-delete-1", "default", RUNNING));
|
||||
server.enqueue(jsonResponse("/operation.json")); // instance delete
|
||||
server.enqueue(jsonResponse("/zone_operation.json"));
|
||||
server.enqueue(instanceWithNetworkAndStatus("test-delete-1", "default", TERMINATED));
|
||||
server.enqueue(aggregatedListWithInstanceNetworkAndStatus("test-delete-1", "default", TERMINATED));
|
||||
server.enqueue(jsonResponse("/GoogleComputeEngineServiceExpectTest/firewall_list.json"));
|
||||
server.enqueue(response404()); // deleted instance no longer exists
|
||||
server.enqueue(aggregatedListInstanceEmpty());
|
||||
server.enqueue(jsonResponse("/firewall_list_compute.json"));
|
||||
server.enqueue(jsonResponse("/operation.json"));
|
||||
server.enqueue(jsonResponse("/zone_operation.json"));
|
||||
|
||||
|
@ -91,6 +91,7 @@ public class GoogleComputeEngineServiceMockTest extends BaseGoogleComputeEngineA
|
|||
assertSent(server, "GET", "/jclouds/zones/us-central1-a/instances/test-delete-1");
|
||||
assertSent(server, "GET", "/projects/party/regions");
|
||||
assertSent(server, "GET", "/projects/party/aggregated/machineTypes"); // Why are we getting machineTypes to delete an instance?
|
||||
assertSent(server, "GET", "/jclouds/zones/us-central1-a/instances/test-delete-1");
|
||||
assertSent(server, "DELETE", "/jclouds/zones/us-central1-a/instances/test-delete-1"); // instance delete
|
||||
assertSent(server, "GET", "/projects/party/zones/us-central1-a/operations/operation-1354084865060");
|
||||
assertSent(server, "GET", "/projects/party/zones/us-central1-a/instances/test-delete-1"); // get instance
|
||||
|
@ -195,5 +196,9 @@ public class GoogleComputeEngineServiceMockTest extends BaseGoogleComputeEngineA
|
|||
stringFromResource("/aggregated_instance_list.json").replace("test-0", instanceName)
|
||||
.replace("default", networkName).replace("RUNNING", status.toString()));
|
||||
}
|
||||
|
||||
private MockResponse aggregatedListInstanceEmpty() {
|
||||
return new MockResponse().setBody(stringFromResource("/aggregated_instance_list_empty.json"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ import org.jclouds.compute.ComputeService;
|
|||
import org.jclouds.compute.domain.ComputeMetadata;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
|
||||
import org.jclouds.googlecomputeengine.compute.predicates.AllNodesInGroupTerminated;
|
||||
import org.jclouds.googlecomputeengine.compute.predicates.GroupIsEmpty;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
@ -51,13 +51,13 @@ public class OrphanedGroupsFromDeadNodesTest {
|
|||
|
||||
|
||||
@Test
|
||||
public void testDetectsAllOrphanedGroupsWhenAllNodesTerminated() {
|
||||
public void testDetectsNoOrphanedGroupsWhenAllNodesArePresentAndTerminated() {
|
||||
|
||||
Set<NodeMetadata> deadNodesGroup1 = (Set) ImmutableSet.builder()
|
||||
Set<NodeMetadata> deadNodesGroup1 = ImmutableSet.<NodeMetadata>builder()
|
||||
.add(new IdAndGroupOnlyNodeMetadata("a", "1", NodeMetadata.Status.TERMINATED)).build();
|
||||
|
||||
Set<NodeMetadata> deadNodesGroup2 = (Set) ImmutableSet.builder()
|
||||
.add(new IdAndGroupOnlyNodeMetadata("b", "2", NodeMetadata.Status.TERMINATED)).build();
|
||||
Set<NodeMetadata> deadNodesGroup2 = ImmutableSet.<NodeMetadata> builder()
|
||||
.add(new IdAndGroupOnlyNodeMetadata("b", "2", NodeMetadata.Status.SUSPENDED)).build();
|
||||
|
||||
Set<NodeMetadata> allDeadNodes = Sets.union(deadNodesGroup1, deadNodesGroup2);
|
||||
|
||||
|
@ -74,18 +74,16 @@ public class OrphanedGroupsFromDeadNodesTest {
|
|||
|
||||
Set<String> orphanedGroups = orphanedGroupsFromDeadNodes.apply(allDeadNodes);
|
||||
|
||||
assertSame(orphanedGroups.size(), 2);
|
||||
assertTrue(orphanedGroups.contains("1"));
|
||||
assertTrue(orphanedGroups.contains("2"));
|
||||
assertTrue(orphanedGroups.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetectsAllOrphanedGroupsWhenSomeNodesTerminatedAndOtherMissing() {
|
||||
public void testDetectsOneOrphanedGroupWhenSomeNodesTerminatedAndOtherMissing() {
|
||||
|
||||
Set<NodeMetadata> deadNodesGroup1 = (Set) ImmutableSet.builder()
|
||||
Set<NodeMetadata> deadNodesGroup1 = ImmutableSet.<NodeMetadata> builder()
|
||||
.add(new IdAndGroupOnlyNodeMetadata("a", "1", NodeMetadata.Status.TERMINATED)).build();
|
||||
|
||||
Set<NodeMetadata> deadNodesGroup2 = (Set) ImmutableSet.builder()
|
||||
Set<NodeMetadata> deadNodesGroup2 = ImmutableSet.<NodeMetadata> builder()
|
||||
.add(new IdAndGroupOnlyNodeMetadata("b", "2", NodeMetadata.Status.TERMINATED)).build();
|
||||
|
||||
Set<NodeMetadata> allDeadNodes = Sets.union(deadNodesGroup1, deadNodesGroup2);
|
||||
|
@ -103,19 +101,18 @@ public class OrphanedGroupsFromDeadNodesTest {
|
|||
|
||||
Set<String> orphanedGroups = orphanedGroupsFromDeadNodes.apply(allDeadNodes);
|
||||
|
||||
assertSame(orphanedGroups.size(), 2);
|
||||
assertTrue(orphanedGroups.contains("1"));
|
||||
assertSame(orphanedGroups.size(), 1);
|
||||
assertTrue(orphanedGroups.contains("2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetectsAllOrphanedGroupsWhenSomeNodesAreAlive() {
|
||||
public void testDetectsOneOrphanedGroupWhenSomeNodesAreAliveAndOtherMissing() {
|
||||
|
||||
Set<NodeMetadata> deadNodesGroup1 = (Set) ImmutableSet.builder()
|
||||
.add(new IdAndGroupOnlyNodeMetadata("a", "1", NodeMetadata.Status.TERMINATED)).build();
|
||||
Set<NodeMetadata> deadNodesGroup1 = ImmutableSet.<NodeMetadata> builder()
|
||||
.add(new IdAndGroupOnlyNodeMetadata("a", "1", NodeMetadata.Status.RUNNING)).build();
|
||||
|
||||
Set<NodeMetadata> deadNodesGroup2 = (Set) ImmutableSet.builder()
|
||||
.add(new IdAndGroupOnlyNodeMetadata("b", "2", NodeMetadata.Status.RUNNING)).build();
|
||||
Set<NodeMetadata> deadNodesGroup2 = ImmutableSet.<NodeMetadata> builder()
|
||||
.add(new IdAndGroupOnlyNodeMetadata("b", "2", NodeMetadata.Status.TERMINATED)).build();
|
||||
|
||||
Set<NodeMetadata> allDeadNodes = Sets.union(deadNodesGroup1, deadNodesGroup2);
|
||||
|
||||
|
@ -123,7 +120,7 @@ public class OrphanedGroupsFromDeadNodesTest {
|
|||
expect(mock.listNodesDetailsMatching(EasyMock.<Predicate<ComputeMetadata>>anyObject()))
|
||||
.andReturn((Set) deadNodesGroup1).once();
|
||||
expect(mock.listNodesDetailsMatching(EasyMock.<Predicate<ComputeMetadata>>anyObject()))
|
||||
.andReturn((Set) deadNodesGroup2).once();
|
||||
.andReturn((Set) ImmutableSet.of()).once();
|
||||
|
||||
replay(mock);
|
||||
|
||||
|
@ -133,7 +130,36 @@ public class OrphanedGroupsFromDeadNodesTest {
|
|||
Set<String> orphanedGroups = orphanedGroupsFromDeadNodes.apply(allDeadNodes);
|
||||
|
||||
assertSame(orphanedGroups.size(), 1);
|
||||
assertTrue(orphanedGroups.contains("2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetectsAllOrphanedGroupsWhenAllNodesArerMissing() {
|
||||
|
||||
Set<NodeMetadata> deadNodesGroup1 = ImmutableSet.<NodeMetadata> builder()
|
||||
.add(new IdAndGroupOnlyNodeMetadata("a", "1", NodeMetadata.Status.RUNNING)).build();
|
||||
|
||||
Set<NodeMetadata> deadNodesGroup2 = ImmutableSet.<NodeMetadata> builder()
|
||||
.add(new IdAndGroupOnlyNodeMetadata("b", "2", NodeMetadata.Status.TERMINATED)).build();
|
||||
|
||||
Set<NodeMetadata> allDeadNodes = Sets.union(deadNodesGroup1, deadNodesGroup2);
|
||||
|
||||
ComputeService mock = createMock(ComputeService.class);
|
||||
expect(mock.listNodesDetailsMatching(EasyMock.<Predicate<ComputeMetadata>>anyObject()))
|
||||
.andReturn((Set) ImmutableSet.of()).once();
|
||||
expect(mock.listNodesDetailsMatching(EasyMock.<Predicate<ComputeMetadata>>anyObject()))
|
||||
.andReturn((Set) ImmutableSet.of()).once();
|
||||
|
||||
replay(mock);
|
||||
|
||||
OrphanedGroupsFromDeadNodes orphanedGroupsFromDeadNodes = new OrphanedGroupsFromDeadNodes(
|
||||
allNodesInGroupTerminated(mock));
|
||||
|
||||
Set<String> orphanedGroups = orphanedGroupsFromDeadNodes.apply(allDeadNodes);
|
||||
|
||||
assertSame(orphanedGroups.size(), 2);
|
||||
assertTrue(orphanedGroups.contains("1"));
|
||||
assertTrue(orphanedGroups.contains("2"));
|
||||
}
|
||||
|
||||
private Predicate<String> allNodesInGroupTerminated(final ComputeService mock) {
|
||||
|
@ -141,6 +167,6 @@ public class OrphanedGroupsFromDeadNodesTest {
|
|||
@Override protected void configure() {
|
||||
bind(ComputeService.class).toInstance(mock);
|
||||
}
|
||||
}).getInstance(AllNodesInGroupTerminated.class); // rather than opening ctor.
|
||||
}).getInstance(GroupIsEmpty.class); // rather than opening ctor.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.googlecomputeengine.compute.functions;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNull;
|
||||
|
||||
import org.jclouds.googlecomputeengine.domain.Instance;
|
||||
import org.jclouds.googlecomputeengine.domain.Network;
|
||||
import org.jclouds.googlecomputeengine.domain.Operation;
|
||||
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiMockTest;
|
||||
import org.jclouds.googlecomputeengine.parse.ParseInstanceTest;
|
||||
import org.jclouds.googlecomputeengine.parse.ParseNetworkTest;
|
||||
import org.jclouds.googlecomputeengine.parse.ParseOperationTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Test(groups = "unit", testName = "ResourcesMockTest", singleThreaded = true)
|
||||
public class ResourcesMockTest extends BaseGoogleComputeEngineApiMockTest {
|
||||
|
||||
public void testInstance() throws Exception {
|
||||
server.enqueue(jsonResponse("/instance_get.json"));
|
||||
|
||||
Instance instance = resourceApi().instance(server.getUrl("/foo/bar").toURI());
|
||||
assertEquals(instance, new ParseInstanceTest().expected(url("/projects")));
|
||||
assertSent(server, "GET", "/foo/bar");
|
||||
}
|
||||
|
||||
public void testInstanceReturns404() throws Exception {
|
||||
server.enqueue(response404());
|
||||
|
||||
Instance instance = resourceApi().instance(server.getUrl("/foo/bar").toURI());
|
||||
assertNull(instance);
|
||||
assertSent(server, "GET", "/foo/bar");
|
||||
}
|
||||
|
||||
public void testNetwork() throws Exception {
|
||||
server.enqueue(jsonResponse("/network_get.json"));
|
||||
|
||||
Network network = resourceApi().network(server.getUrl("/foo/bar").toURI());
|
||||
assertEquals(network, new ParseNetworkTest().expected(url("/projects")));
|
||||
assertSent(server, "GET", "/foo/bar");
|
||||
}
|
||||
|
||||
public void testNetworkReturns404() throws Exception {
|
||||
server.enqueue(response404());
|
||||
|
||||
Network network = resourceApi().network(server.getUrl("/foo/bar").toURI());
|
||||
assertNull(network);
|
||||
assertSent(server, "GET", "/foo/bar");
|
||||
}
|
||||
|
||||
public void testOperation() throws Exception {
|
||||
server.enqueue(jsonResponse("/operation.json"));
|
||||
|
||||
Operation operation = resourceApi().operation(server.getUrl("/foo/bar").toURI());
|
||||
assertEquals(operation, new ParseOperationTest().expected(url("/projects")));
|
||||
assertSent(server, "GET", "/foo/bar");
|
||||
}
|
||||
|
||||
public void testOperationReturns404() throws Exception {
|
||||
server.enqueue(response404());
|
||||
|
||||
Operation operation = resourceApi().operation(server.getUrl("/foo/bar").toURI());
|
||||
assertNull(operation);
|
||||
assertSent(server, "GET", "/foo/bar");
|
||||
}
|
||||
|
||||
public void testDelete() throws Exception {
|
||||
server.enqueue(jsonResponse("/operation.json"));
|
||||
|
||||
Operation operation = resourceApi().delete(server.getUrl("/foo/bar").toURI());
|
||||
assertEquals(operation, new ParseOperationTest().expected(url("/projects")));
|
||||
assertSent(server, "DELETE", "/foo/bar");
|
||||
}
|
||||
|
||||
public void testDeleteReturns404() throws Exception {
|
||||
server.enqueue(response404());
|
||||
|
||||
Operation operation = resourceApi().delete(server.getUrl("/foo/bar").toURI());
|
||||
assertNull(operation);
|
||||
assertSent(server, "DELETE", "/foo/bar");
|
||||
}
|
||||
|
||||
public void testResetInstance() throws Exception {
|
||||
server.enqueue(jsonResponse("/operation.json"));
|
||||
|
||||
Operation operation = resourceApi().resetInstance(server.getUrl("/foo/bar").toURI());
|
||||
assertEquals(operation, new ParseOperationTest().expected(url("/projects")));
|
||||
assertSent(server, "POST", "/foo/bar/reset");
|
||||
}
|
||||
|
||||
public void testStopInstance() throws Exception {
|
||||
server.enqueue(jsonResponse("/operation.json"));
|
||||
|
||||
Operation operation = resourceApi().stopInstance(server.getUrl("/foo/bar").toURI());
|
||||
assertEquals(operation, new ParseOperationTest().expected(url("/projects")));
|
||||
assertSent(server, "POST", "/foo/bar/stop");
|
||||
}
|
||||
|
||||
public void testStartInstance() throws Exception {
|
||||
server.enqueue(jsonResponse("/operation.json"));
|
||||
|
||||
Operation operation = resourceApi().startInstance(server.getUrl("/foo/bar").toURI());
|
||||
assertEquals(operation, new ParseOperationTest().expected(url("/projects")));
|
||||
assertSent(server, "POST", "/foo/bar/start");
|
||||
}
|
||||
|
||||
private Resources resourceApi() {
|
||||
return builder().build().utils().injector().getInstance(Resources.class);
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@ import static com.google.common.base.Charsets.UTF_8;
|
|||
import static com.google.common.base.Throwables.propagate;
|
||||
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
|
||||
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
|
||||
import static org.jclouds.googlecloud.config.GoogleCloudProperties.CREDENTIAL_TYPE;
|
||||
import static org.jclouds.googlecloud.config.GoogleCloudProperties.PROJECT_NAME;
|
||||
import static org.jclouds.googlecomputeengine.config.GoogleComputeEngineProperties.IMAGE_PROJECTS;
|
||||
|
@ -36,9 +37,9 @@ import org.jclouds.ContextBuilder;
|
|||
import org.jclouds.compute.ComputeService;
|
||||
import org.jclouds.compute.ComputeServiceContext;
|
||||
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
||||
import org.jclouds.http.okhttp.config.OkHttpCommandExecutorServiceModule;
|
||||
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
|
||||
import org.jclouds.googlecomputeengine.GoogleComputeEngineProviderMetadata;
|
||||
import org.jclouds.http.okhttp.config.OkHttpCommandExecutorServiceModule;
|
||||
import org.testng.annotations.AfterMethod;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
|
||||
|
@ -72,6 +73,7 @@ public class BaseGoogleComputeEngineApiMockTest {
|
|||
Properties overrides = new Properties();
|
||||
overrides.put(PROJECT_NAME, "party");
|
||||
overrides.put(IMAGE_PROJECTS, "debian-cloud");
|
||||
overrides.put(TIMEOUT_NODE_TERMINATED, "0"); // Avoid retry & polling in mock tests
|
||||
overrides.put(CREDENTIAL_TYPE, BEARER_TOKEN_CREDENTIALS.toString());
|
||||
return ContextBuilder.newBuilder(new GoogleComputeEngineProviderMetadata())
|
||||
.credentials(identity, credential)
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"kind": "compute#network",
|
||||
"id": "13024414170909937976",
|
||||
"creationTimestamp": "2012-10-24T20:13:19.967",
|
||||
"selfLink": "https://www.googleapis.com/compute/v1/projects/party/global/networks/jclouds-test-delete",
|
||||
"name": "jclouds-test-delete",
|
||||
"description": "Default network for the project",
|
||||
"IPv4Range": "10.0.0.0/8",
|
||||
"gatewayIPv4": "10.0.0.1"
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAnJvA40x4OK+9nVYTS0N916VMjC6/qYe/IuDUdy6hdW1wz9IO
|
||||
MTS3CPxlE0KuoNO1/M7O7yFso6IragTxUkNqJ2mUOqV0Bf0CEkUIKzeYRGfpx+QM
|
||||
PorHbLQXjjFinWKwibZuv6lqtvqwcsrjW7bpWsz9x+0qqKM0o0UhjUMhTRqZoYxo
|
||||
E2zUH7WA8JRatE/bQkjv/nWBfI+/WzSDhJn7AjIql0Nd4Q+bxohIJEZu8yDw1H6T
|
||||
pd7mw83m6UYBk4eZH79r3d2euuQMUKIunyLbw7vNJJ8qYTJQuNYIiJuWKnzzjxuJ
|
||||
UfumhdOqfjSobznhAjTLUbA/btZCiQ/TasV4cQIDAQABAoIBAEeOn1b8ZN455qDS
|
||||
aKR2JTT4cX6ICckznnEYW9xNMTcPl4FN0HBJTuzLLn/bcyFHOxtVf5YiJpqqCb46
|
||||
ne1hokp54mHdoaLu1Rh19GKS139CH77XA4U8Mh0IOM8e35lcM5/o/LeUeI89Aoyh
|
||||
CbupWvzDN543TsuZLv7/InKCXt/0dXhAQpq3UiBT63EITQbyom5fSPnMzqM3F8jD
|
||||
E9ZqkX4JsnTPC7FQDIpPCaKjG9YCZqoljz+1ssli3mN66V/JKefcCiVoubalmmT2
|
||||
dpvmRtFaKvhAmkWYakYybYg8aDi3YygAHSU1bzxlY4TNiQgPdnTTDAPyeqqVrE1D
|
||||
Chi+18UCgYEAzlk7c+tFwxZ3ryycOe0loFudUNE5rviHhPgbOHoSTooXh0Hq1Vrb
|
||||
2ic+4FbRpoPHLpcLM9LX+arezUdeFBZ8qunjUG6MbUhAeAm/3cfMk+nZg3Skpg8+
|
||||
C1D3hxGX4qdhURHvc2QUH7VIUWbucvPgtL8pt1z5Su/EE1Cb2XVsvu8CgYEAwkqZ
|
||||
4vTZxI0XqJo6BfUnKGJEDC8xeWr10ELPdXLTCuNDpLSYNedQAxZi9XzvbnbWZ/MF
|
||||
Z7IWkzzyAjsX0gpI56cxxtas/chxUboBlUo6ZW8QcPDcU2sKJi318wzElqqvRMNM
|
||||
InfLf8nuPC9hyhe49/lFBBSZJeIo396DuqnTPp8CgYBO4NVVLm5wcLo3gDoH+psT
|
||||
fXHZXuFJ/T7wmVbuc9tjom30CkKWZDD+Z1olr4pcuKr/KEXj/YkJq0OX/Nv9mcr2
|
||||
GooGSPvtGl1qhW+Oe728HPxEv+XghJsXAFBelV8WCR2uO8jotyzqIgYO9+XWk1sm
|
||||
PJzZtvSkrJqrN3kb20NCiQKBgDDVP0hj8jgMnl2qJdtJesYTrLbDRdQWpiHqKOqE
|
||||
Kbca1+2V1ov1z453GfhJpoRFKi6GTl15zWLEdq9I2vvXyesvgrtPSbufnZvE/JDh
|
||||
TzwfZip832O4C5z9AExOcTrNO7A0xfYD1goQXuiRoCqDO+JXrJkR9EwpQ8zAyKsp
|
||||
9AZRAoGAGq3TYpmlI5oucEURHKsHOrIBirHFD+RaXMynxzgwkRnt6Z5Mg10I7Ddr
|
||||
LiGK8/IrF8bg1F7weLVmj93zjvhQTh5yvb1jwVdFGXM2rbR7/P7F6n2f7xM4+lmv
|
||||
Tq7E9Sv8UVuraAwJihlKCuBtpZM1t2JhcuNjXAZngj7R9j5HIZg=
|
||||
-----END RSA PRIVATE KEY-----
|
Loading…
Reference in New Issue