mirror of https://github.com/apache/jclouds.git
Fix GCE live tests
This commit is contained in:
parent
a0f659faed
commit
715994b125
|
@ -16,32 +16,11 @@
|
|||
*/
|
||||
package org.jclouds.googlecomputeengine.compute.functions;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import com.google.common.util.concurrent.Atomics;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.crypto.Crypto;
|
||||
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
|
||||
import org.jclouds.googlecomputeengine.domain.Instance;
|
||||
import org.jclouds.googlecomputeengine.domain.Instance.SerialPortOutput;
|
||||
import org.jclouds.googlecomputeengine.domain.Metadata;
|
||||
import org.jclouds.googlecomputeengine.domain.Operation;
|
||||
import org.jclouds.googlecomputeengine.features.InstanceApi;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.util.Predicates2;
|
||||
import static com.google.common.base.Predicates.notNull;
|
||||
import static com.google.common.collect.Iterables.filter;
|
||||
import static com.google.common.collect.Iterables.transform;
|
||||
import static com.google.common.collect.Iterables.tryFind;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.InvalidKeyException;
|
||||
|
@ -53,13 +32,42 @@ import java.security.spec.RSAPublicKeySpec;
|
|||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import javax.annotation.Resource;
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.crypto.Crypto;
|
||||
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
|
||||
import org.jclouds.googlecomputeengine.domain.Instance;
|
||||
import org.jclouds.googlecomputeengine.domain.Instance.SerialPortOutput;
|
||||
import org.jclouds.googlecomputeengine.domain.Metadata;
|
||||
import org.jclouds.googlecomputeengine.domain.Operation;
|
||||
import org.jclouds.googlecomputeengine.features.InstanceApi;
|
||||
import org.jclouds.json.Json;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.util.Predicates2;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import com.google.common.util.concurrent.Atomics;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
/**
|
||||
* References:
|
||||
|
@ -92,12 +100,15 @@ public class ResetWindowsPassword implements Function<Map<String, ?>, String> {
|
|||
private final GoogleComputeEngineApi api;
|
||||
private final Crypto crypto;
|
||||
private final Predicate<AtomicReference<Operation>> operationDone;
|
||||
private final Json json;
|
||||
|
||||
@Inject
|
||||
protected ResetWindowsPassword(GoogleComputeEngineApi api, Crypto crypto, Predicate<AtomicReference<Operation>> operationDone) {
|
||||
protected ResetWindowsPassword(GoogleComputeEngineApi api, Crypto crypto,
|
||||
Predicate<AtomicReference<Operation>> operationDone, Json json) {
|
||||
this.api = api;
|
||||
this.crypto = crypto;
|
||||
this.operationDone = operationDone;
|
||||
this.json = json;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -135,31 +146,64 @@ public class ResetWindowsPassword implements Function<Map<String, ?>, String> {
|
|||
operation.get().httpErrorMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
final Map<String, String> passwordDict = new HashMap<String, String>();
|
||||
boolean passwordRetrieved = Predicates2.retry(new Predicate<Instance>() {
|
||||
public boolean apply(Instance instance) {
|
||||
String serialPortContents = instanceApi.getSerialPortOutput(instance.name(), 4).contents();
|
||||
if (!serialPortContents.startsWith("{\"ready\":true")) {
|
||||
return false;
|
||||
}
|
||||
String[] contentEntries = serialPortContents.split("\n");
|
||||
passwordDict.clear();
|
||||
passwordDict.putAll(new Gson().fromJson(contentEntries[contentEntries.length - 1], Map.class));
|
||||
passwordDict.put("passwordDictContentEntries", contentEntries[contentEntries.length - 1]);
|
||||
return passwordDict.get("encryptedPassword") != null;
|
||||
}
|
||||
}, 10 * 60, 30, TimeUnit.SECONDS).apply(instance.get()); // Notice that timeoutDuration should be less than EXPIRE_DURATION
|
||||
if (passwordRetrieved) {
|
||||
return decryptPassword(checkNotNull(passwordDict.get("encryptedPassword"), "encryptedPassword shouldn't be null"), keys);
|
||||
} else {
|
||||
throw new IllegalStateException("encryptedPassword shouldn't be null: " + passwordDict.get("passwordDictContentEntries"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw Throwables.propagate(e);
|
||||
}
|
||||
try {
|
||||
final AtomicReference<String> encryptedPassword = Atomics.newReference();
|
||||
boolean passwordRetrieved = Predicates2.retry(new Predicate<Instance>() {
|
||||
public boolean apply(Instance instance) {
|
||||
String serialPortContents = instanceApi.getSerialPortOutput(instance.name(), 4).contents();
|
||||
List<String> contentEntries = Splitter.on('\n').splitToList(serialPortContents);
|
||||
|
||||
Optional<String> retrievedPassword = tryFind(
|
||||
filter(transform(contentEntries, deserializeSerialOutput(json)), notNull()), HasEncryptedPassword)
|
||||
.transform(ExtractEncryptedPassword);
|
||||
|
||||
if (retrievedPassword.isPresent()) {
|
||||
encryptedPassword.set(retrievedPassword.get());
|
||||
}
|
||||
|
||||
return retrievedPassword.isPresent();
|
||||
}
|
||||
// Notice that timeoutDuration should be less than EXPIRE_DURATION
|
||||
}, 10 * 60, 30, TimeUnit.SECONDS).apply(instance.get());
|
||||
|
||||
if (passwordRetrieved) {
|
||||
return decryptPassword(encryptedPassword.get(), keys);
|
||||
} else {
|
||||
throw new IllegalStateException("Did not find the encrypted password in the serial port output");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw Throwables.propagate(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Function<String, Map<String, Object>> deserializeSerialOutput(final Json json) {
|
||||
return new Function<String, Map<String, Object>>() {
|
||||
@Override
|
||||
public Map<String, Object> apply(String input) {
|
||||
try {
|
||||
return json.fromJson(input, new TypeLiteral<Map<String, Object>>() {
|
||||
}.getType());
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static final Predicate<Map<String, Object>> HasEncryptedPassword = new Predicate<Map<String, Object>>() {
|
||||
@Override
|
||||
public boolean apply(Map<String, Object> input) {
|
||||
return input.containsKey("encryptedPassword");
|
||||
}
|
||||
};
|
||||
|
||||
private static final Function<Map<String, Object>, String> ExtractEncryptedPassword = new Function<Map<String, Object>, String>() {
|
||||
@Override
|
||||
public String apply(Map<String, Object> input) {
|
||||
return (String) input.get("encryptedPassword");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Decrypts the given password - the encrypted text is base64-encoded.
|
||||
* As per the GCE docs, assumes it was encrypted with algorithm "RSA/NONE/OAEPPadding", and UTF-8.
|
||||
|
|
|
@ -208,34 +208,32 @@ public final class CreateNodesWithGroupEncodedIntoNameThenAddToSet extends
|
|||
}
|
||||
|
||||
int[] inboundPorts = templateOptions.getInboundPorts();
|
||||
if ((inboundPorts == null) || inboundPorts.length == 0){
|
||||
return;
|
||||
}
|
||||
|
||||
if (inboundPorts != null && inboundPorts.length > 0) {
|
||||
List<String> ports = simplifyPorts(inboundPorts);
|
||||
String name = naming.name(ports);
|
||||
Firewall firewall = firewallApi.get(name);
|
||||
AtomicReference<Operation> operation = null;
|
||||
|
||||
List<String> ports = simplifyPorts(inboundPorts);
|
||||
String name = naming.name(ports);
|
||||
Firewall firewall = firewallApi.get(name);
|
||||
AtomicReference<Operation> operation = null;
|
||||
|
||||
String interiorRange = subnet.isPresent() ? subnet.get().ipCidrRange() : DEFAULT_INTERNAL_NETWORK_RANGE;
|
||||
|
||||
if (firewall == null) {
|
||||
List<Rule> rules = ImmutableList.of(Rule.create("tcp", ports), Rule.create("udp", ports));
|
||||
FirewallOptions firewallOptions = new FirewallOptions().name(name).network(network.selfLink())
|
||||
String interiorRange = subnet.isPresent() ? subnet.get().ipCidrRange() : DEFAULT_INTERNAL_NETWORK_RANGE;
|
||||
|
||||
if (firewall == null) {
|
||||
List<Rule> rules = ImmutableList.of(Rule.create("tcp", ports), Rule.create("udp", ports));
|
||||
FirewallOptions firewallOptions = new FirewallOptions().name(name).network(network.selfLink())
|
||||
.allowedRules(rules).sourceTags(templateOptions.getTags())
|
||||
.sourceRanges(of(interiorRange, EXTERIOR_RANGE))
|
||||
.targetTags(ImmutableList.of(name));
|
||||
.sourceRanges(of(interiorRange, EXTERIOR_RANGE)).targetTags(ImmutableList.of(name));
|
||||
|
||||
operation = Atomics.newReference(firewallApi
|
||||
.createInNetwork(firewallOptions.name(), network.selfLink(), firewallOptions));
|
||||
operation = Atomics.newReference(firewallApi.createInNetwork(firewallOptions.name(), network.selfLink(),
|
||||
firewallOptions));
|
||||
|
||||
operationDone.apply(operation);
|
||||
checkState(operation.get().httpErrorStatusCode() == null, "Could not insert firewall, operation failed %s",
|
||||
operation);
|
||||
operationDone.apply(operation);
|
||||
checkState(operation.get().httpErrorStatusCode() == null, "Could not insert firewall, operation failed %s",
|
||||
operation);
|
||||
}
|
||||
|
||||
// Add tags for firewalls
|
||||
tags.add(name);
|
||||
tags.add(name); // Add tags for the inbound ports firewall
|
||||
}
|
||||
|
||||
templateOptions.tags(tags);
|
||||
}
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ public abstract class Image {
|
|||
|
||||
public abstract Status status();
|
||||
|
||||
public abstract Long archiveSizeBytes();
|
||||
@Nullable public abstract Long archiveSizeBytes();
|
||||
|
||||
public abstract Long diskSizeGb();
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@ import com.google.common.base.Predicate;
|
|||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import org.jclouds.crypto.Crypto;
|
||||
import org.jclouds.encryption.bouncycastle.BouncyCastleCrypto;
|
||||
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
|
||||
|
@ -29,6 +31,7 @@ import org.jclouds.googlecomputeengine.domain.Metadata;
|
|||
import org.jclouds.googlecomputeengine.domain.Operation;
|
||||
import org.jclouds.googlecomputeengine.features.InstanceApi;
|
||||
import org.jclouds.googlecomputeengine.parse.ParseInstanceTest;
|
||||
import org.jclouds.json.internal.GsonWrapper;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
@ -93,7 +96,7 @@ public class ResetWindowsPasswordTest {
|
|||
|
||||
replay(api, instanceApi, operation, serialPortOutput, crypto, keyPairGenerator);
|
||||
|
||||
ResetWindowsPassword generator = new ResetWindowsPassword(api, crypto, operationDone);
|
||||
ResetWindowsPassword generator = new ResetWindowsPassword(api, crypto, operationDone, new GsonWrapper(new Gson()));
|
||||
String result = generator.apply(ImmutableMap.of("instance", new AtomicReference<Instance>(instance), "zone", zone, "email", "test@google.com", "userName", "test"));
|
||||
|
||||
verify(api, instanceApi, operation, serialPortOutput);
|
||||
|
|
|
@ -53,7 +53,7 @@ public class AddressApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
|
|||
assertEquals(addresses.next().size(), 1);
|
||||
}
|
||||
|
||||
@Test(groups = "live", dependsOnMethods = "testListAddress")
|
||||
@Test(groups = "live", dependsOnMethods = "testListAddress", alwaysRun = true)
|
||||
public void testDeleteAddress() {
|
||||
assertOperationDoneSuccessfully(api().delete(ADDRESS_NAME));
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ public class BackendServiceApiLiveTest extends BaseGoogleComputeEngineApiLiveTes
|
|||
}
|
||||
*/
|
||||
|
||||
@Test(groups = "live", dependsOnMethods = "testListBackendService")
|
||||
@Test(groups = "live", dependsOnMethods = "testListBackendService", alwaysRun = true)
|
||||
public void testDeleteBackendService() {
|
||||
assertOperationDoneSuccessfully(api().delete(BACKEND_SERVICE_NAME));
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ public class DiskApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
|
|||
assertDiskEquals(disksAsList.get(0));
|
||||
}
|
||||
|
||||
@Test(groups = "live", dependsOnMethods = "testListDisk")
|
||||
@Test(groups = "live", dependsOnMethods = "testListDisk", alwaysRun = true)
|
||||
public void testDeleteDisk() {
|
||||
assertOperationDoneSuccessfully(api().delete(DISK_NAME));
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ public class FirewallApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
|
|||
assertEquals(firewalls.next().size(), 1);
|
||||
}
|
||||
|
||||
@Test(groups = "live", dependsOnMethods = "testListFirewall")
|
||||
@Test(groups = "live", dependsOnMethods = "testListFirewall", alwaysRun = true)
|
||||
public void testDeleteFirewall() {
|
||||
assertOperationDoneSuccessfully(api().delete(FIREWALL_NAME));
|
||||
assertOperationDoneSuccessfully(api.networks().delete(FIREWALL_NETWORK_NAME));
|
||||
|
|
|
@ -73,7 +73,7 @@ public class ForwardingRuleApiLiveTest extends BaseGoogleComputeEngineApiLiveTes
|
|||
address = addressApi().get(ADDRESS_NAME);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@AfterClass(alwaysRun = true)
|
||||
public void tearDown() {
|
||||
assertOperationDoneSuccessfully(targetPoolApi().delete(TARGETPOOL_NAME));
|
||||
assertOperationDoneSuccessfully(targetPoolApi().delete(TARGETPOOL_NAME_NEW));
|
||||
|
|
|
@ -104,7 +104,7 @@ public class GlobalForwardingRuleApiLiveTest extends BaseGoogleComputeEngineApiL
|
|||
assertEquals(forwardingRules.size(), 1);
|
||||
}
|
||||
|
||||
@Test(groups = "live", dependsOnMethods = "testListGlobalForwardingRule")
|
||||
@Test(groups = "live", dependsOnMethods = "testListGlobalForwardingRule", alwaysRun = true)
|
||||
public void testDeleteGlobalForwardingRule() {
|
||||
assertOperationDoneSuccessfully(api().delete(GLOBAL_FORWARDING_RULE_NAME));
|
||||
|
||||
|
|
|
@ -354,7 +354,7 @@ public class InstanceApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
|
|||
assertEquals(resultTags, expectedTags);
|
||||
}
|
||||
|
||||
@AfterClass(groups = { "integration", "live" })
|
||||
@AfterClass(groups = { "integration", "live" }, alwaysRun = true)
|
||||
protected void tearDownContext() {
|
||||
try {
|
||||
waitOperationDone(api().delete(INSTANCE_NAME));
|
||||
|
|
|
@ -119,7 +119,7 @@ public class InstanceApiWindowsLiveTest extends BaseGoogleComputeEngineApiLiveTe
|
|||
assertFalse(Strings.isNullOrEmpty(result), "Password shouldn't be empty");
|
||||
}
|
||||
|
||||
@AfterClass(groups = { "integration", "live" })
|
||||
@AfterClass(groups = { "integration", "live" }, alwaysRun = true)
|
||||
protected void tearDownContext() {
|
||||
try {
|
||||
waitOperationDone(api().delete(INSTANCE_NAME));
|
||||
|
|
|
@ -61,7 +61,7 @@ public class NetworkApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
|
|||
assertNetworkEquals(networksAsList.get(0));
|
||||
}
|
||||
|
||||
@Test(groups = "live", dependsOnMethods = "testListNetwork")
|
||||
@Test(groups = "live", dependsOnMethods = "testListNetwork", alwaysRun = true)
|
||||
public void testDeleteNetwork() {
|
||||
assertOperationDoneSuccessfully(api().delete(NETWORK_NAME));
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ public class ProjectApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
|
|||
assertNotNull(project.commonInstanceMetadata().fingerprint());
|
||||
}
|
||||
|
||||
@Test(groups = "live", dependsOnMethods = "addItemToMetadata")
|
||||
@Test(groups = "live", dependsOnMethods = "addItemToMetadata", alwaysRun = true)
|
||||
public void testDeleteItemFromMetadata() {
|
||||
Metadata metadata = project.commonInstanceMetadata().remove(METADATA_ITEM_KEY);
|
||||
assertOperationDoneSuccessfully(api.project().setCommonInstanceMetadata(metadata));
|
||||
|
|
|
@ -75,7 +75,7 @@ public class RouteApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
|
|||
assertRouteEquals(routesAsList.get(0));
|
||||
}
|
||||
|
||||
@Test(groups = "live", dependsOnMethods = "testListRoute")
|
||||
@Test(groups = "live", dependsOnMethods = "testListRoute", alwaysRun = true)
|
||||
public void testDeleteRoute() {
|
||||
assertOperationDoneSuccessfully(api().delete(ROUTE_NAME));
|
||||
assertOperationDoneSuccessfully(api.networks().delete(ROUTE_NETWORK_NAME));
|
||||
|
|
|
@ -71,7 +71,7 @@ public class SnapshotApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
|
|||
assertSnapshotEquals(snapshotsAsList.get(0));
|
||||
}
|
||||
|
||||
@Test(groups = "live", dependsOnMethods = "testListSnapshot")
|
||||
@Test(groups = "live", dependsOnMethods = "testListSnapshot", alwaysRun = true)
|
||||
public void testDeleteDisk() {
|
||||
assertOperationDoneSuccessfully(diskApi().delete(DISK_NAME));
|
||||
assertOperationDoneSuccessfully(api().delete(SNAPSHOT_NAME));
|
||||
|
|
|
@ -258,7 +258,7 @@ public class TargetPoolApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
|
|||
assertOperationDoneSuccessfully(api().delete(BACKUP_TARGETPOOL_NAME));
|
||||
}
|
||||
|
||||
@AfterClass(groups = { "integration", "live" })
|
||||
@AfterClass(groups = { "integration", "live" }, alwaysRun = true)
|
||||
public void testCleanup(){
|
||||
InstanceApi instanceApi = api.instancesInZone(DEFAULT_ZONE_NAME);
|
||||
HttpHealthCheckApi httpHealthCheckApi = api.httpHeathChecks();
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</encoder>
|
||||
</appender>
|
||||
<appender name="COMPUTEFILE" class="ch.qos.logback.core.FileAppender">
|
||||
<file>target/jclouds-compute.log</file>
|
||||
<file>target/test-data/jclouds-compute.log</file>
|
||||
<encoder>
|
||||
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
|
||||
</encoder>
|
||||
|
|
Loading…
Reference in New Issue