mirror of
https://github.com/apache/jclouds.git
synced 2025-02-09 03:25:39 +00:00
Cleanup node authentication
This commit is contained in:
parent
4772587722
commit
d6d1e7dde5
@ -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:
|
||||
|
||||
|
@ -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<Instance> 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<AttachDisk> 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>(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<Operation> 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);
|
||||
|
@ -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<Function<Network, SecurityGroup>>() {
|
||||
}).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);
|
||||
}
|
||||
|
||||
|
@ -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<URI> 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<URI> 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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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<NetworkAndAddressRange, Network> networkMap;
|
||||
private final Predicate<AtomicReference<Operation>> 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<AtomicReference<Operation>> operationDone,
|
||||
LoadingCache<NetworkAndAddressRange, Network> 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<AtomicReference<Operation>> operationDone,
|
||||
LoadingCache<NetworkAndAddressRange, Network> 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<?, ListenableFuture<Void>> execute(String group, int count,
|
||||
Template template,
|
||||
Set<NodeMetadata> goodNodes,
|
||||
Map<NodeMetadata, Exception> badNodes,
|
||||
Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
|
||||
@Override
|
||||
public Map<?, ListenableFuture<Void>> execute(String group, int count, Template template,
|
||||
Set<NodeMetadata> goodNodes, Map<NodeMetadata, Exception> badNodes,
|
||||
Multimap<NodeMetadata, CustomizationResponse> 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<String, String> 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.
|
||||
* <p>
|
||||
* 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<AtomicReference<Operation>> operations = Lists.newArrayList();
|
||||
@ -138,17 +163,11 @@ public final class CreateNodesWithGroupEncodedIntoNameThenAddToSet extends
|
||||
if (firewall == null) {
|
||||
List<String> ports = ImmutableList.of(String.valueOf(port));
|
||||
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(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> operation = Atomics.newReference(firewallApi.createInNetwork(
|
||||
firewallOptions.name(),
|
||||
network.selfLink(),
|
||||
firewallOptions));
|
||||
firewallOptions.name(), network.selfLink(), firewallOptions));
|
||||
operations.add(operation);
|
||||
}
|
||||
}
|
||||
|
@ -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<String, String> 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();
|
||||
}
|
||||
|
||||
}
|
@ -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<Template, LoginCredentials> 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();
|
||||
}
|
||||
}
|
@ -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));
|
||||
|
Loading…
x
Reference in New Issue
Block a user