From d6d1e7dde518d0b485e72685225bf66e25562c8d Mon Sep 17 00:00:00 2001 From: Ignasi Barrera Date: Tue, 23 Dec 2014 00:17:14 +0100 Subject: [PATCH] Cleanup node authentication --- providers/google-compute-engine/README.md | 2 +- .../GoogleComputeEngineServiceAdapter.java | 75 +++++-------- ...ogleComputeEngineServiceContextModule.java | 9 -- .../GoogleComputeEngineTemplateOptions.java | 23 ++-- ...sWithGroupEncodedIntoNameThenAddToSet.java | 101 +++++++++++------- ...faultLoginCredentialsForImageStrategy.java | 69 ------------ ...odeCredentialsButOverrideFromTemplate.java | 57 ---------- .../GoogleComputeEngineServiceMockTest.java | 3 +- 8 files changed, 105 insertions(+), 234 deletions(-) delete mode 100644 providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java delete mode 100644 providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/UseNodeCredentialsButOverrideFromTemplate.java diff --git a/providers/google-compute-engine/README.md b/providers/google-compute-engine/README.md index 47ff426b33..e4706983ea 100644 --- a/providers/google-compute-engine/README.md +++ b/providers/google-compute-engine/README.md @@ -6,7 +6,7 @@ Authenticating into the instances: -------- User: -If no user is provided in GoogleComputeEngineTemplateOptions when launching an instance by default "jclouds" is used. +If no user is provided in GoogleComputeEngineTemplateOptions when launching an instance by default "root" is used. Credential: diff --git a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceAdapter.java b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceAdapter.java index 29f239d646..91a8dfeea7 100644 --- a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceAdapter.java +++ b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceAdapter.java @@ -36,6 +36,7 @@ import org.jclouds.compute.ComputeServiceAdapter; import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.Template; +import org.jclouds.compute.options.TemplateOptions; import org.jclouds.domain.Location; import org.jclouds.domain.LocationBuilder; import org.jclouds.domain.LocationScope; @@ -59,6 +60,7 @@ import org.jclouds.location.suppliers.all.JustProvider; import com.google.common.base.Predicate; import com.google.common.base.Splitter; +import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; @@ -108,25 +110,17 @@ public final class GoogleComputeEngineServiceAdapter @Override public NodeAndInitialCredentials createNodeWithGroupEncodedIntoName(String group, String name, Template template) { - - checkNotNull(template, "template"); - GoogleComputeEngineTemplateOptions options = GoogleComputeEngineTemplateOptions.class.cast(template.getOptions()); checkNotNull(options.network(), "template options must specify a network"); - Hardware hardware = checkNotNull(template.getHardware(), "hardware must be set"); - - checkNotNull(hardware.getUri(), "hardware must have a URI"); + checkNotNull(template.getHardware().getUri(), "hardware must have a URI"); checkNotNull(template.getImage().getUri(), "image URI is null"); List disks = Lists.newArrayList(); disks.add(AttachDisk.newBootDisk(template.getImage().getUri())); - for (URI existingDisk : options.additionalDisks()) { - disks.add(AttachDisk.existingDisk(existingDisk)); - } NewInstance newInstance = NewInstance.create( name, // name - hardware.getUri(), // machineType + template.getHardware().getUri(), // machineType options.network(), // network disks, // disks group // description @@ -141,9 +135,11 @@ public final class GoogleComputeEngineServiceAdapter // Add metadata from template and for ssh key and image id newInstance.metadata().putAll(options.getUserMetadata()); - if (options.getPublicKey() != null) { // TODO: why are we doing this? - newInstance.metadata().put("sshKeys", format("%s:%s %s@localhost", checkNotNull(options.getLoginUser(), - "loginUser cannot be null"), options.getPublicKey(), options.getLoginUser())); + + LoginCredentials credentials = resolveNodeCredentials(template); + if (options.getPublicKey() != null) { + newInstance.metadata().put("sshKeys", + format("%s:%s %s@localhost", credentials.getUser(), options.getPublicKey(), credentials.getUser())); } String zone = template.getLocation().getId(); @@ -174,7 +170,6 @@ public final class GoogleComputeEngineServiceAdapter // Add lookup for InstanceToNodeMetadata diskToSourceImage.put(instance.get().disks().get(0).source(), template.getImage().getUri()); - LoginCredentials credentials = getFromImageAndOverrideIfRequired(template.getImage(), options); return new NodeAndInitialCredentials(instance.get(), instance.get().selfLink().toString(), credentials); } @@ -256,40 +251,6 @@ public final class GoogleComputeEngineServiceAdapter throw new UnsupportedOperationException("suspend is not supported by GCE"); } - // TODO: this entire method is questionable. needs a test case, or to be removed. - private static LoginCredentials getFromImageAndOverrideIfRequired(org.jclouds.compute.domain.Image image, - GoogleComputeEngineTemplateOptions options) { - LoginCredentials defaultCredentials = image.getDefaultCredentials(); - String[] keys = defaultCredentials.getPrivateKey().split(":"); - String publicKey = keys[0]; - String privateKey = keys[1]; - - LoginCredentials.Builder credentialsBuilder = defaultCredentials.toBuilder(); - credentialsBuilder.privateKey(privateKey); - - // LoginCredentials from image stores the public key along with the private key in the privateKey field - // @see GoogleComputePopulateDefaultLoginCredentialsForImageStrategy - // so if options doesn't have a public key set we set it from the default - if (options.getPublicKey() == null) { - options.authorizePublicKey(publicKey); - } - if (options.hasLoginPrivateKeyOption()) { - credentialsBuilder.privateKey(options.getPrivateKey()); - } - if (options.getLoginUser() != null) { - credentialsBuilder.identity(options.getLoginUser()); - } - if (options.hasLoginPasswordOption()) { - credentialsBuilder.password(options.getLoginPassword()); - } - if (options.shouldAuthenticateSudo() != null) { - credentialsBuilder.authenticateSudo(options.shouldAuthenticateSudo()); - } - LoginCredentials credentials = credentialsBuilder.build(); - options.overrideLoginCredentials(credentials); - return credentials; - } - private void waitOperationDone(Operation operation) { AtomicReference operationRef = Atomics.newReference(operation); @@ -306,6 +267,24 @@ public final class GoogleComputeEngineServiceAdapter } } + private LoginCredentials resolveNodeCredentials(Template template) { + TemplateOptions options = template.getOptions(); + LoginCredentials.Builder credentials = LoginCredentials.builder(template.getImage().getDefaultCredentials()); + if (!Strings.isNullOrEmpty(options.getLoginUser())) { + credentials.user(options.getLoginUser()); + } + if (!Strings.isNullOrEmpty(options.getLoginPrivateKey())) { + credentials.privateKey(options.getLoginPrivateKey()); + } + if (!Strings.isNullOrEmpty(options.getLoginPassword())) { + credentials.password(options.getLoginPassword()); + } + if (options.shouldAuthenticateSudo() != null) { + credentials.authenticateSudo(options.shouldAuthenticateSudo()); + } + return credentials.build(); + } + private static String toName(URI link) { String path = link.getPath(); return path.substring(path.lastIndexOf('/') + 1); diff --git a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java index 47d10a9c4c..b99ef02f9b 100644 --- a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java +++ b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java @@ -43,7 +43,6 @@ import org.jclouds.compute.domain.SecurityGroup; import org.jclouds.compute.extensions.ImageExtension; import org.jclouds.compute.extensions.SecurityGroupExtension; import org.jclouds.compute.options.TemplateOptions; -import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate; import org.jclouds.domain.Location; import org.jclouds.googlecomputeengine.compute.GoogleComputeEngineService; import org.jclouds.googlecomputeengine.compute.GoogleComputeEngineServiceAdapter; @@ -64,8 +63,6 @@ import org.jclouds.googlecomputeengine.compute.predicates.AllNodesInGroupTermina import org.jclouds.googlecomputeengine.compute.predicates.AtomicInstanceVisible; import org.jclouds.googlecomputeengine.compute.predicates.AtomicOperationDone; import org.jclouds.googlecomputeengine.compute.strategy.CreateNodesWithGroupEncodedIntoNameThenAddToSet; -import org.jclouds.googlecomputeengine.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy; -import org.jclouds.googlecomputeengine.compute.strategy.UseNodeCredentialsButOverrideFromTemplate; import org.jclouds.googlecomputeengine.domain.Firewall; import org.jclouds.googlecomputeengine.domain.Image; import org.jclouds.googlecomputeengine.domain.Instance; @@ -125,9 +122,6 @@ public final class GoogleComputeEngineServiceContextModule bind(new TypeLiteral>() { }).to(NetworkToSecurityGroup.class); - bind(org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy.class) - .to(PopulateDefaultLoginCredentialsForImageStrategy.class); - bind(org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet.class) .to(CreateNodesWithGroupEncodedIntoNameThenAddToSet.class); @@ -146,10 +140,7 @@ public final class GoogleComputeEngineServiceContextModule }).to(FindNetworkOrCreate.class); bind(SecurityGroupExtension.class).to(GoogleComputeEngineSecurityGroupExtension.class); - - bind(PrioritizeCredentialsFromTemplate.class).to(UseNodeCredentialsButOverrideFromTemplate.class); bind(FirewallTagNamingConvention.Factory.class).in(Scopes.SINGLETON); - bindHttpApi(binder(), Resources.class); } diff --git a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/options/GoogleComputeEngineTemplateOptions.java b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/options/GoogleComputeEngineTemplateOptions.java index 3aabae3f92..1b1dac8659 100644 --- a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/options/GoogleComputeEngineTemplateOptions.java +++ b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/options/GoogleComputeEngineTemplateOptions.java @@ -17,7 +17,6 @@ package org.jclouds.googlecomputeengine.compute.options; import java.net.URI; -import java.util.List; import java.util.Map; import org.jclouds.compute.options.TemplateOptions; @@ -25,13 +24,11 @@ import org.jclouds.domain.LoginCredentials; import org.jclouds.javax.annotation.Nullable; import org.jclouds.scriptbuilder.domain.Statement; -import com.google.common.collect.Lists; - /** Instance options specific to Google Compute Engine. */ public final class GoogleComputeEngineTemplateOptions extends TemplateOptions { private URI network = null; - private final List additionalDisks = Lists.newArrayList(); + private boolean autoCreateKeyPair = true; @Override public GoogleComputeEngineTemplateOptions clone() { @@ -46,6 +43,7 @@ public final class GoogleComputeEngineTemplateOptions extends TemplateOptions { if (to instanceof GoogleComputeEngineTemplateOptions) { GoogleComputeEngineTemplateOptions eTo = GoogleComputeEngineTemplateOptions.class.cast(to); eTo.network(network()); + eTo.autoCreateKeyPair(autoCreateKeyPair()); } } @@ -60,10 +58,19 @@ public final class GoogleComputeEngineTemplateOptions extends TemplateOptions { return network; } - /** Additional disks to attach to this instance. */ - // TODO: test me or remove me! - public List additionalDisks() { - return additionalDisks; + /** + * Sets whether an SSH key pair should be created automatically. + */ + public GoogleComputeEngineTemplateOptions autoCreateKeyPair(boolean autoCreateKeyPair) { + this.autoCreateKeyPair = autoCreateKeyPair; + return this; + } + + /** + * Sets whether an SSH key pair should be created automatically. + */ + public boolean autoCreateKeyPair() { + return autoCreateKeyPair; } /** diff --git a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java index 8c889d240e..7fb71df685 100644 --- a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java +++ b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java @@ -25,6 +25,7 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; +import javax.annotation.Resource; import javax.inject.Inject; import javax.inject.Named; @@ -47,8 +48,11 @@ import org.jclouds.googlecomputeengine.domain.Network; import org.jclouds.googlecomputeengine.domain.Operation; import org.jclouds.googlecomputeengine.features.FirewallApi; import org.jclouds.googlecomputeengine.options.FirewallOptions; +import org.jclouds.logging.Logger; +import org.jclouds.ssh.SshKeyPairGenerator; import com.google.common.base.Predicate; +import com.google.common.base.Strings; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; @@ -58,7 +62,7 @@ import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; public final class CreateNodesWithGroupEncodedIntoNameThenAddToSet extends - org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet { + org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet { public static final String EXTERIOR_RANGE = "0.0.0.0/0"; public static final String DEFAULT_INTERNAL_NETWORK_RANGE = "10.0.0.0/8"; @@ -67,67 +71,88 @@ public final class CreateNodesWithGroupEncodedIntoNameThenAddToSet extends private final LoadingCache networkMap; private final Predicate> operationDone; private final FirewallTagNamingConvention.Factory firewallTagNamingConvention; + private final SshKeyPairGenerator keyGenerator; - @Inject CreateNodesWithGroupEncodedIntoNameThenAddToSet( - CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy, - ListNodesStrategy listNodesStrategy, - GroupNamingConvention.Factory namingConvention, - @Named(Constants.PROPERTY_USER_THREADS) - ListeningExecutorService userExecutor, - CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory - customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory, - GoogleComputeEngineApi api, - Predicate> operationDone, - LoadingCache networkMap, - FirewallTagNamingConvention.Factory firewallTagNamingConvention) { + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + @Inject + CreateNodesWithGroupEncodedIntoNameThenAddToSet( + CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy, + ListNodesStrategy listNodesStrategy, + GroupNamingConvention.Factory namingConvention, + @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, + CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory, + GoogleComputeEngineApi api, Predicate> operationDone, + LoadingCache networkMap, + FirewallTagNamingConvention.Factory firewallTagNamingConvention, SshKeyPairGenerator keyGenerator) { super(addNodeWithGroupStrategy, listNodesStrategy, namingConvention, userExecutor, - customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory); + customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory); this.api = api; this.operationDone = operationDone; this.networkMap = networkMap; this.firewallTagNamingConvention = firewallTagNamingConvention; + this.keyGenerator = keyGenerator; } - @Override // TODO: why synchronized? - public synchronized Map> execute(String group, int count, - Template template, - Set goodNodes, - Map badNodes, - Multimap customizationResponses) { + @Override + public Map> execute(String group, int count, Template template, + Set goodNodes, Map badNodes, + Multimap customizationResponses) { String sharedResourceName = namingConvention.create().sharedNameForGroup(group); Template mutableTemplate = template.clone(); - GoogleComputeEngineTemplateOptions templateOptions = GoogleComputeEngineTemplateOptions.class.cast(mutableTemplate - .getOptions()); + GoogleComputeEngineTemplateOptions templateOptions = GoogleComputeEngineTemplateOptions.class + .cast(mutableTemplate.getOptions()); assert template.getOptions().equals(templateOptions) : "options didn't clone properly"; - // get or insert the network and insert a firewall with the users configuration + // get or insert the network and insert a firewall with the users + // configuration Network network = getOrCreateNetwork(templateOptions, sharedResourceName); getOrCreateFirewalls(templateOptions, network, firewallTagNamingConvention.get(group)); templateOptions.network(network.selfLink()); templateOptions.userMetadata(ComputeServiceConstants.NODE_GROUP_KEY, group); + // Configure the default credentials, if needed + if (templateOptions.autoCreateKeyPair() && Strings.isNullOrEmpty(templateOptions.getPublicKey())) { + logger.debug(">> creating default keypair..."); + Map defaultKeys = keyGenerator.get(); + templateOptions.authorizePublicKey(defaultKeys.get("public")); + templateOptions.overrideLoginPrivateKey(defaultKeys.get("private")); + } + + if (templateOptions.getRunScript() != null && templateOptions.getLoginPrivateKey() == null) { + logger.warn(">> A runScript has been configured but no SSH key has been provided." + + " Authentication will delegate to the ssh-agent"); + } + return super.execute(group, count, mutableTemplate, goodNodes, badNodes, customizationResponses); } /** - * Try and find a network either previously created by jclouds or user defined. + * Try and find a network either previously created by jclouds or user + * defined. */ private Network getOrCreateNetwork(GoogleComputeEngineTemplateOptions templateOptions, String sharedResourceName) { String networkName = templateOptions.network() != null ? toName(templateOptions.network()) : sharedResourceName; - return networkMap.apply(NetworkAndAddressRange.create(networkName, DEFAULT_INTERNAL_NETWORK_RANGE, null)); + return networkMap.getUnchecked(NetworkAndAddressRange.create(networkName, DEFAULT_INTERNAL_NETWORK_RANGE, null)); } /** - * Ensures that a firewall exists for every inbound port that the instance requests. + * Ensures that a firewall exists for every inbound port that the instance + * requests. *

- * For each port, there must be a firewall with a name following the {@link FirewallTagNamingConvention}, - * with a target tag also following the {@link FirewallTagNamingConvention}, which opens the requested port - * for all sources on both TCP and UDP protocols. - * @see org.jclouds.googlecomputeengine.features.FirewallApi#patch(String, org.jclouds.googlecomputeengine.options.FirewallOptions) + * For each port, there must be a firewall with a name following the + * {@link FirewallTagNamingConvention}, with a target tag also following the + * {@link FirewallTagNamingConvention}, which opens the requested port for + * all sources on both TCP and UDP protocols. + * + * @see org.jclouds.googlecomputeengine.features.FirewallApi#patch(String, + * org.jclouds.googlecomputeengine.options.FirewallOptions) */ private void getOrCreateFirewalls(GoogleComputeEngineTemplateOptions templateOptions, Network network, - FirewallTagNamingConvention naming) { + FirewallTagNamingConvention naming) { FirewallApi firewallApi = api.firewalls(); List> operations = Lists.newArrayList(); @@ -138,17 +163,11 @@ public final class CreateNodesWithGroupEncodedIntoNameThenAddToSet extends if (firewall == null) { List ports = ImmutableList.of(String.valueOf(port)); List 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(DEFAULT_INTERNAL_NETWORK_RANGE, EXTERIOR_RANGE)) - .targetTags(ImmutableList.of(name)); + FirewallOptions firewallOptions = new FirewallOptions().name(name).network(network.selfLink()) + .allowedRules(rules).sourceTags(templateOptions.getTags()) + .sourceRanges(of(DEFAULT_INTERNAL_NETWORK_RANGE, EXTERIOR_RANGE)).targetTags(ImmutableList.of(name)); AtomicReference operation = Atomics.newReference(firewallApi.createInNetwork( - firewallOptions.name(), - network.selfLink(), - firewallOptions)); + firewallOptions.name(), network.selfLink(), firewallOptions)); operations.add(operation); } } diff --git a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java deleted file mode 100644 index 082d9ed879..0000000000 --- a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.strategy; - -import static com.google.common.base.Preconditions.checkNotNull; -import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE; - -import java.security.NoSuchAlgorithmException; -import java.util.Map; - -import javax.annotation.PostConstruct; -import javax.inject.Named; -import javax.inject.Singleton; - -import org.jclouds.compute.domain.TemplateBuilderSpec; -import org.jclouds.domain.LoginCredentials; -import org.jclouds.ssh.internal.RsaSshKeyPairGenerator; - -import com.google.inject.Inject; - -@Singleton -public class PopulateDefaultLoginCredentialsForImageStrategy implements - org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy { - - private final TemplateBuilderSpec templateBuilder; - private final RsaSshKeyPairGenerator keyPairGenerator; - private String compoundKey; - - @Inject - PopulateDefaultLoginCredentialsForImageStrategy(@Named(TEMPLATE) String templateSpec, - RsaSshKeyPairGenerator keyPairGenerator) - throws NoSuchAlgorithmException { - this.templateBuilder = TemplateBuilderSpec.parse(checkNotNull(templateSpec, "template builder spec")); - checkNotNull(templateBuilder.getLoginUser(), "template builder spec must provide a loginUser"); - this.keyPairGenerator = checkNotNull(keyPairGenerator, "keypair generator"); - } - - @PostConstruct - private void generateKeys() { - Map keys = keyPairGenerator.get(); - // as we need to store both the pubk and the pk, store them separated by : (base64 does not contain that char) - compoundKey = String.format("%s:%s", checkNotNull(keys.get("public"), "public key cannot be null"), - checkNotNull(keys.get("private"), "private key cannot be null")); - } - - @Override - public LoginCredentials apply(Object image) { - return LoginCredentials.builder() - .authenticateSudo(templateBuilder.getAuthenticateSudo() != null ? - templateBuilder.getAuthenticateSudo() : false) - .privateKey(compoundKey) - .user(templateBuilder.getLoginUser()).build(); - } - -} diff --git a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/UseNodeCredentialsButOverrideFromTemplate.java b/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/UseNodeCredentialsButOverrideFromTemplate.java deleted file mode 100644 index a908910ced..0000000000 --- a/providers/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/UseNodeCredentialsButOverrideFromTemplate.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.strategy; - -import static com.google.common.base.Preconditions.checkNotNull; - -import org.jclouds.compute.domain.Template; -import org.jclouds.compute.options.RunScriptOptions; -import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate; -import org.jclouds.domain.LoginCredentials; - -import com.google.common.base.Function; -import com.google.inject.Inject; -import com.google.inject.Singleton; - -/** - * GCE needs the credentials to insert the node so the node credentials already take the Image credentials into account, - * as such only overriding the TemplateOptions credentials is required. - */ -@Singleton -public class UseNodeCredentialsButOverrideFromTemplate extends PrioritizeCredentialsFromTemplate { - - - @Inject - public UseNodeCredentialsButOverrideFromTemplate( - Function credentialsFromImageOrTemplateOptions) { - super(credentialsFromImageOrTemplateOptions); - } - - public LoginCredentials apply(Template template, LoginCredentials fromNode) { - RunScriptOptions options = checkNotNull(template.getOptions(), "template options are required"); - LoginCredentials.Builder builder = LoginCredentials.builder(fromNode); - if (options.getLoginUser() != null) - builder.user(template.getOptions().getLoginUser()); - if (options.getLoginPassword() != null) - builder.password(options.getLoginPassword()); - if (options.getLoginPrivateKey() != null) - builder.privateKey(options.getLoginPrivateKey()); - if (options.shouldAuthenticateSudo() != null && options.shouldAuthenticateSudo()) - builder.authenticateSudo(true); - return builder.build(); - } -} diff --git a/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceMockTest.java b/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceMockTest.java index 70458211f3..839a344846 100644 --- a/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceMockTest.java +++ b/providers/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceMockTest.java @@ -166,7 +166,8 @@ public class GoogleComputeEngineServiceMockTest extends BaseGoogleComputeEngineA ComputeService computeService = computeService(); GoogleComputeEngineTemplateOptions options = computeService.templateOptions() - .as(GoogleComputeEngineTemplateOptions.class).tags(ImmutableSet.of("aTag")).blockUntilRunning(false); + .as(GoogleComputeEngineTemplateOptions.class).autoCreateKeyPair(false) + .tags(ImmutableSet.of("aTag")).blockUntilRunning(false); Template template = computeService.templateBuilder().options(options).build(); NodeMetadata node = getOnlyElement(computeService.createNodesInGroup("test", 1, template));