JCLOUDS-1421: Add default credentials to images created by the ImageExtension

By default, when listing images the ComputeServiceAdapter adds the
default credentials for each image. This is not done when images are
created by the image extension, and NPEs can appear in code that assumes
the default credentials are there, as the field is not nullable.

This change tries to populate the known node credentials for images
created form nodes, and falls back to the default strategy to add the
default credentials to an image if there are not known credentials.
This commit is contained in:
Ignasi Barrera 2018-05-16 09:27:24 +02:00
parent 29655f3149
commit b76a594e81
11 changed files with 423 additions and 160 deletions

View File

@ -17,11 +17,11 @@
package org.jclouds.cloudstack.compute;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.cloudstack.predicates.SshKeyPairPredicates.nameMatches;
import static org.jclouds.cloudstack.predicates.ZonePredicates.supportsSecurityGroups;
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.cloudstack.predicates.SshKeyPairPredicates.nameMatches;
import static org.jclouds.cloudstack.predicates.ZonePredicates.supportsSecurityGroups;
import java.util.Map;
import java.util.Set;
@ -33,6 +33,13 @@ import javax.inject.Provider;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.cloudstack.CloudStackApi;
import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions;
import org.jclouds.cloudstack.domain.SecurityGroup;
import org.jclouds.cloudstack.domain.SshKeyPair;
import org.jclouds.cloudstack.domain.Zone;
import org.jclouds.cloudstack.domain.ZoneAndName;
import org.jclouds.cloudstack.predicates.SecurityGroupPredicates;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.callables.RunScriptOnNode;
@ -42,11 +49,11 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.extensions.internal.DelegatingImageExtension;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.internal.PersistNodeCredentials;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetImageStrategy;
@ -58,13 +65,6 @@ import org.jclouds.compute.strategy.ResumeNodeStrategy;
import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.cloudstack.CloudStackApi;
import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions;
import org.jclouds.cloudstack.domain.SecurityGroup;
import org.jclouds.cloudstack.domain.SshKeyPair;
import org.jclouds.cloudstack.domain.Zone;
import org.jclouds.cloudstack.domain.ZoneAndName;
import org.jclouds.cloudstack.predicates.SecurityGroupPredicates;
import org.jclouds.scriptbuilder.functions.InitAdminAccess;
import com.google.common.base.Function;
@ -88,32 +88,30 @@ public class CloudStackComputeService extends BaseComputeService {
@Inject
protected CloudStackComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetImageStrategy getImageStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy,
DestroyNodeStrategy destroyNodeStrategy, ResumeNodeStrategy startNodeStrategy,
SuspendNodeStrategy stopNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider,
@Named("DEFAULT") Provider<TemplateOptions> templateOptionsProvider,
@Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning,
@Named(TIMEOUT_NODE_TERMINATED) Predicate<AtomicReference<NodeMetadata>> nodeTerminated,
@Named(TIMEOUT_NODE_SUSPENDED) Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, CloudStackApi client,
LoadingCache<ZoneAndName, SecurityGroup> securityGroupMap,
LoadingCache<String, SshKeyPair> keyPairCache,
Function<Set<? extends NodeMetadata>, Multimap<String, String>> orphanedGroupsByZoneId,
GroupNamingConvention.Factory namingConvention,
Supplier<LoadingCache<String, Zone>> zoneIdToZone,
Optional<ImageExtension> imageExtension,
Optional<SecurityGroupExtension> securityGroupExtension) {
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetImageStrategy getImageStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy,
DestroyNodeStrategy destroyNodeStrategy, ResumeNodeStrategy startNodeStrategy,
SuspendNodeStrategy stopNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider,
@Named("DEFAULT") Provider<TemplateOptions> templateOptionsProvider,
@Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning,
@Named(TIMEOUT_NODE_TERMINATED) Predicate<AtomicReference<NodeMetadata>> nodeTerminated,
@Named(TIMEOUT_NODE_SUSPENDED) Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, CloudStackApi client,
LoadingCache<ZoneAndName, SecurityGroup> securityGroupMap, LoadingCache<String, SshKeyPair> keyPairCache,
Function<Set<? extends NodeMetadata>, Multimap<String, String>> orphanedGroupsByZoneId,
GroupNamingConvention.Factory namingConvention, Supplier<LoadingCache<String, Zone>> zoneIdToZone,
Optional<ImageExtension> imageExtension, Optional<SecurityGroupExtension> securityGroupExtension,
DelegatingImageExtension.Factory delegatingImageExtension) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy,
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, timeouts, userExecutor, imageExtension, securityGroupExtension);
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, userExecutor, imageExtension, securityGroupExtension, delegatingImageExtension);
this.zoneIdToZone = checkNotNull(zoneIdToZone, "zoneIdToZone");
this.client = checkNotNull(client, "client");
this.securityGroupMap = checkNotNull(securityGroupMap, "securityGroupMap");

View File

@ -57,6 +57,7 @@ import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.extensions.internal.DelegatingImageExtension;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.functions.GroupNamingConvention.Factory;
import org.jclouds.compute.internal.BaseComputeService;
@ -113,30 +114,31 @@ public class EC2ComputeService extends BaseComputeService {
@Inject
protected EC2ComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetImageStrategy getImageStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy,
DestroyNodeStrategy destroyNodeStrategy, ResumeNodeStrategy startNodeStrategy,
SuspendNodeStrategy stopNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider,
@Named("DEFAULT") Provider<TemplateOptions> templateOptionsProvider,
@Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning,
@Named(TIMEOUT_NODE_TERMINATED) Predicate<AtomicReference<NodeMetadata>> nodeTerminated,
@Named(TIMEOUT_NODE_SUSPENDED) Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, EC2Api client,
ConcurrentMap<RegionAndName, KeyPair> credentialsMap,
@Named("SECURITY") LoadingCache<RegionAndName, String> securityGroupMap,
Optional<ImageExtension> imageExtension, GroupNamingConvention.Factory namingConvention,
@Named(PROPERTY_EC2_GENERATE_INSTANCE_NAMES) boolean generateInstanceNames,
Optional<SecurityGroupExtension> securityGroupExtension) {
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetImageStrategy getImageStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy,
DestroyNodeStrategy destroyNodeStrategy, ResumeNodeStrategy startNodeStrategy,
SuspendNodeStrategy stopNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider,
@Named("DEFAULT") Provider<TemplateOptions> templateOptionsProvider,
@Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning,
@Named(TIMEOUT_NODE_TERMINATED) Predicate<AtomicReference<NodeMetadata>> nodeTerminated,
@Named(TIMEOUT_NODE_SUSPENDED) Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, EC2Api client,
ConcurrentMap<RegionAndName, KeyPair> credentialsMap,
@Named("SECURITY") LoadingCache<RegionAndName, String> securityGroupMap,
Optional<ImageExtension> imageExtension, GroupNamingConvention.Factory namingConvention,
@Named(PROPERTY_EC2_GENERATE_INSTANCE_NAMES) boolean generateInstanceNames,
Optional<SecurityGroupExtension> securityGroupExtension,
DelegatingImageExtension.Factory delegatingImageExtension) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy,
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, timeouts, userExecutor, imageExtension, securityGroupExtension);
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, userExecutor, imageExtension, securityGroupExtension, delegatingImageExtension);
this.client = client;
this.credentialsMap = credentialsMap;
this.securityGroupMap = securityGroupMap;

View File

@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
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 java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
@ -39,10 +40,10 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.extensions.internal.DelegatingImageExtension;
import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.internal.PersistNodeCredentials;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetImageStrategy;
@ -69,28 +70,28 @@ public class NovaComputeService extends BaseComputeService {
@Inject
protected NovaComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetImageStrategy getImageStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy,
DestroyNodeStrategy destroyNodeStrategy, ResumeNodeStrategy startNodeStrategy,
SuspendNodeStrategy stopNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider,
@Named("DEFAULT") Provider<TemplateOptions> templateOptionsProvider,
@Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning,
@Named(TIMEOUT_NODE_TERMINATED) Predicate<AtomicReference<NodeMetadata>> nodeTerminated,
@Named(TIMEOUT_NODE_SUSPENDED) Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
CleanupResources cleanupResources,
Optional<ImageExtension> imageExtension,
Optional<SecurityGroupExtension> securityGroupExtension) {
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetImageStrategy getImageStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy,
DestroyNodeStrategy destroyNodeStrategy, ResumeNodeStrategy startNodeStrategy,
SuspendNodeStrategy stopNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider,
@Named("DEFAULT") Provider<TemplateOptions> templateOptionsProvider,
@Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning,
@Named(TIMEOUT_NODE_TERMINATED) Predicate<AtomicReference<NodeMetadata>> nodeTerminated,
@Named(TIMEOUT_NODE_SUSPENDED) Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
CleanupResources cleanupResources, Optional<ImageExtension> imageExtension,
Optional<SecurityGroupExtension> securityGroupExtension,
DelegatingImageExtension.Factory delegatingImageExtension) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy,
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, timeouts, userExecutor, imageExtension, securityGroupExtension);
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, userExecutor, imageExtension, securityGroupExtension, delegatingImageExtension);
this.cleanupResources = checkNotNull(cleanupResources, "cleanupResources");
}

View File

@ -45,6 +45,7 @@ import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.extensions.internal.DelegatingImageExtension;
import org.jclouds.compute.functions.CreateSshClientOncePortIsListeningOnNode;
import org.jclouds.compute.functions.DefaultCredentialsFromImageOrOverridingCredentials;
import org.jclouds.compute.options.RunScriptOptions;
@ -112,6 +113,8 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
}, InitializeRunScriptOnNodeOrPlaceInBadMap.class).build(InitializeRunScriptOnNodeOrPlaceInBadMap.Factory.class));
install(new FactoryModuleBuilder().build(BlockUntilInitScriptStatusIsZeroThenReturnOutput.Factory.class));
install(new FactoryModuleBuilder().build(DelegatingImageExtension.Factory.class));
}
protected void bindCredentialsOverriderFunction() {

View File

@ -16,17 +16,30 @@
*/
package org.jclouds.compute.extensions.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule.AddDefaultCredentialsToImage;
import org.jclouds.compute.domain.CloneImageTemplate;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.ImageTemplate;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.suppliers.ImageCacheSupplier;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.logging.Logger;
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.assistedinject.Assisted;
/**
* Delegates to the provider specific {@link ImageExtension} and takes care of
@ -35,20 +48,65 @@ import com.google.common.util.concurrent.ListenableFuture;
@Beta
public class DelegatingImageExtension implements ImageExtension {
public interface Factory {
DelegatingImageExtension create(ImageCacheSupplier imageCache, ImageExtension delegate);
}
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final ImageCacheSupplier imageCache;
private final ImageExtension delegate;
private final AddDefaultCredentialsToImage addDefaultCredentialsToImage;
private final Map<String, Credentials> credentialStore;
public DelegatingImageExtension(ImageCacheSupplier imageCache, ImageExtension delegate) {
this.imageCache = checkNotNull(imageCache, "imageCache");
this.delegate = checkNotNull(delegate, "delegate");
@Inject
DelegatingImageExtension(@Assisted ImageCacheSupplier imageCache, @Assisted ImageExtension delegate,
AddDefaultCredentialsToImage addDefaultCredentialsToImage, Map<String, Credentials> credentialStore) {
this.imageCache = imageCache;
this.delegate = delegate;
this.addDefaultCredentialsToImage = addDefaultCredentialsToImage;
this.credentialStore = credentialStore;
}
public ImageTemplate buildImageTemplateFromNode(String name, String id) {
return delegate.buildImageTemplateFromNode(name, id);
}
public ListenableFuture<Image> createImage(ImageTemplate template) {
public ListenableFuture<Image> createImage(final ImageTemplate template) {
ListenableFuture<Image> future = delegate.createImage(template);
// Populate the default image credentials, if missing
future = Futures.transform(future, new Function<Image, Image>() {
@Override
public Image apply(Image input) {
if (input.getDefaultCredentials() != null) {
return input;
}
// If the image has been created by cloning a node, then try to
// populate the known node credentials as the default image
// credentials
if (template instanceof CloneImageTemplate) {
final CloneImageTemplate cloneImageTemplate = (CloneImageTemplate) template;
Credentials nodeCredentials = credentialStore.get("node#" + cloneImageTemplate.getSourceNodeId());
if (nodeCredentials != null) {
logger.info(">> Adding node(%s) credentials to image(%s)...", cloneImageTemplate.getSourceNodeId(),
cloneImageTemplate.getName());
return ImageBuilder.fromImage(input)
.defaultCredentials(LoginCredentials.fromCredentials(nodeCredentials)).build();
}
}
// If no credentials are known for the node, populate the default
// credentials using the defined strategy
logger.info(">> Adding default image credentials to image(%s)...", template.getName());
return addDefaultCredentialsToImage.apply(input);
}
});
Futures.addCallback(future, new FutureCallback<Image>() {
@Override
public void onSuccess(Image result) {

View File

@ -68,7 +68,6 @@ import org.jclouds.compute.extensions.internal.DelegatingImageExtension;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetImageStrategy;
@ -131,7 +130,6 @@ public class BaseComputeService implements ComputeService {
private final Predicate<AtomicReference<NodeMetadata>> nodeTerminated;
private final Predicate<AtomicReference<NodeMetadata>> nodeSuspended;
private final InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory;
private final Timeouts timeouts;
private final InitAdminAccess initAdminAccess;
private final PersistNodeCredentials persistNodeCredentials;
private final RunScriptOnNode.Factory runScriptOnNodeFactory;
@ -154,8 +152,9 @@ public class BaseComputeService implements ComputeService {
@Named(TIMEOUT_NODE_SUSPENDED) Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, InitAdminAccess initAdminAccess,
RunScriptOnNode.Factory runScriptOnNodeFactory, PersistNodeCredentials persistNodeCredentials,
Timeouts timeouts, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
Optional<ImageExtension> imageExtension, Optional<SecurityGroupExtension> securityGroupExtension) {
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
Optional<ImageExtension> imageExtension, Optional<SecurityGroupExtension> securityGroupExtension,
DelegatingImageExtension.Factory delegatingImageExtension) {
this.context = checkNotNull(context, "context");
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
this.images = checkNotNull(images, "images");
@ -175,15 +174,14 @@ public class BaseComputeService implements ComputeService {
this.nodeTerminated = checkNotNull(nodeTerminated, "nodeTerminated");
this.nodeSuspended = checkNotNull(nodeSuspended, "nodeSuspended");
this.initScriptRunnerFactory = checkNotNull(initScriptRunnerFactory, "initScriptRunnerFactory");
this.timeouts = checkNotNull(timeouts, "timeouts");
this.initAdminAccess = checkNotNull(initAdminAccess, "initAdminAccess");
this.runScriptOnNodeFactory = checkNotNull(runScriptOnNodeFactory, "runScriptOnNodeFactory");
this.persistNodeCredentials = checkNotNull(persistNodeCredentials, "persistNodeCredentials");
this.userExecutor = checkNotNull(userExecutor, "userExecutor");
this.securityGroupExtension = checkNotNull(securityGroupExtension, "securityGroupExtension");
if (imageExtension.isPresent() && images instanceof ImageCacheSupplier) {
this.imageExtension = Optional.<ImageExtension> of(new DelegatingImageExtension(ImageCacheSupplier.class
.cast(images), imageExtension.get()));
this.imageExtension = Optional.<ImageExtension> of(delegatingImageExtension.create(
ImageCacheSupplier.class.cast(images), imageExtension.get()));
} else {
this.imageExtension = checkNotNull(imageExtension, "imageExtension");
}

View File

@ -0,0 +1,214 @@
/*
* 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.compute.extensions.internal;
import static com.google.common.util.concurrent.Futures.immediateFuture;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule.AddDefaultCredentialsToImage;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.Image.Status;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.ImageTemplate;
import org.jclouds.compute.domain.ImageTemplateBuilder.CloneImageTemplateBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.internal.ImageTemplateImpl;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.suppliers.ImageCacheSupplier;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.LoginCredentials;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.Futures;
@Test(groups = "unit", testName = "DelegatingImageExtensionTest")
public class DelegatingImageExtensionTest {
@Test
public void createImageRegistersInCacheAndAddsCredentials() {
ImageCacheSupplier imageCache = createMock(ImageCacheSupplier.class);
ImageExtension delegate = createMock(ImageExtension.class);
AddDefaultCredentialsToImage credsToImage = createMock(AddDefaultCredentialsToImage.class);
ImageTemplate template = new ImageTemplateImpl("test") {
};
Image result = new ImageBuilder().id("test")
.operatingSystem(OperatingSystem.builder().description("test").build()).status(Status.AVAILABLE).build();
LoginCredentials credentials = LoginCredentials.builder().user("jclouds").password("pass").build();
Image withCredentials = ImageBuilder.fromImage(result).defaultCredentials(credentials).build();
expect(delegate.createImage(template)).andReturn(immediateFuture(result));
expect(credsToImage.apply(result)).andReturn(withCredentials);
imageCache.registerImage(withCredentials);
expectLastCall();
replay(delegate, imageCache, credsToImage);
new DelegatingImageExtension(imageCache, delegate, credsToImage, null).createImage(template);
verify(delegate, imageCache, credsToImage);
}
@Test
public void createImageDoesNotRegisterInCacheWhenFailed() {
ImageCacheSupplier imageCache = createMock(ImageCacheSupplier.class);
ImageExtension delegate = createMock(ImageExtension.class);
AddDefaultCredentialsToImage credsToImage = createMock(AddDefaultCredentialsToImage.class);
ImageTemplate template = new ImageTemplateImpl("test") {
};
expect(delegate.createImage(template)).andReturn(Futures.<Image> immediateFailedFuture(new RuntimeException()));
replay(delegate, imageCache, credsToImage);
new DelegatingImageExtension(imageCache, delegate, credsToImage, null).createImage(template);
verify(delegate, imageCache, credsToImage);
}
@Test
public void createImageDoesNotRegisterInCacheWhenCancelled() {
ImageCacheSupplier imageCache = createMock(ImageCacheSupplier.class);
ImageExtension delegate = createMock(ImageExtension.class);
AddDefaultCredentialsToImage credsToImage = createMock(AddDefaultCredentialsToImage.class);
ImageTemplate template = new ImageTemplateImpl("test") {
};
expect(delegate.createImage(template)).andReturn(Futures.<Image> immediateCancelledFuture());
replay(delegate, imageCache, credsToImage);
new DelegatingImageExtension(imageCache, delegate, credsToImage, null).createImage(template);
verify(delegate, imageCache, credsToImage);
}
@Test
public void deleteUnregistersImageFromCache() {
ImageCacheSupplier imageCache = createMock(ImageCacheSupplier.class);
ImageExtension delegate = createMock(ImageExtension.class);
expect(delegate.deleteImage("test")).andReturn(true);
imageCache.removeImage("test");
expectLastCall();
replay(delegate, imageCache);
new DelegatingImageExtension(imageCache, delegate, null, null).deleteImage("test");
verify(delegate, imageCache);
}
@Test
public void deleteDoesNotUnregisterImageFromCacheWhenFailed() {
ImageCacheSupplier imageCache = createMock(ImageCacheSupplier.class);
ImageExtension delegate = createMock(ImageExtension.class);
expect(delegate.deleteImage("test")).andReturn(false);
replay(delegate, imageCache);
new DelegatingImageExtension(imageCache, delegate, null, null).deleteImage("test");
verify(delegate, imageCache);
}
@Test
public void createByCloningDoesNothingIfImageHasCredentials() throws InterruptedException, ExecutionException {
LoginCredentials credentials = LoginCredentials.builder().user("jclouds").password("pass").build();
ImageCacheSupplier imageCache = createMock(ImageCacheSupplier.class);
ImageExtension delegate = createMock(ImageExtension.class);
AddDefaultCredentialsToImage credsToImage = createMock(AddDefaultCredentialsToImage.class);
ImageTemplate template = new CloneImageTemplateBuilder().name("test").nodeId("node1").build();
Image result = new ImageBuilder().id("test")
.operatingSystem(OperatingSystem.builder().description("test").build()).status(Status.AVAILABLE)
.defaultCredentials(credentials).build();
expect(delegate.createImage(template)).andReturn(immediateFuture(result));
replay(delegate, credsToImage);
Future<Image> image = new DelegatingImageExtension(imageCache, delegate, credsToImage, null)
.createImage(template);
// Verify that the exact same instance is returned unmodified
assertTrue(image.get() == result);
verify(delegate, credsToImage);
}
@Test
public void createByCloningAddsNodeCredentials() throws InterruptedException, ExecutionException {
Credentials credentials = LoginCredentials.builder().user("jclouds").password("pass").build();
ImageCacheSupplier imageCache = createMock(ImageCacheSupplier.class);
ImageExtension delegate = createMock(ImageExtension.class);
AddDefaultCredentialsToImage credsToImage = createMock(AddDefaultCredentialsToImage.class);
Map<String, Credentials> credentialStore = ImmutableMap.of("node#node1", credentials);
ImageTemplate template = new CloneImageTemplateBuilder().name("test").nodeId("node1").build();
Image result = new ImageBuilder().id("test")
.operatingSystem(OperatingSystem.builder().description("test").build()).status(Status.AVAILABLE).build();
expect(delegate.createImage(template)).andReturn(immediateFuture(result));
replay(delegate, credsToImage);
Future<Image> image = new DelegatingImageExtension(imageCache, delegate, credsToImage, credentialStore)
.createImage(template);
assertEquals(image.get().getDefaultCredentials(), credentials);
verify(delegate, credsToImage);
}
@Test
public void createByCloningAddsDefaultImageCredentials() throws InterruptedException, ExecutionException {
LoginCredentials credentials = LoginCredentials.builder().user("jclouds").password("pass").build();
ImageCacheSupplier imageCache = createMock(ImageCacheSupplier.class);
ImageExtension delegate = createMock(ImageExtension.class);
AddDefaultCredentialsToImage credsToImage = createMock(AddDefaultCredentialsToImage.class);
Map<String, Credentials> credentialStore = Collections.emptyMap();
ImageTemplate template = new CloneImageTemplateBuilder().name("test").nodeId("node1").build();
Image result = new ImageBuilder().id("test")
.operatingSystem(OperatingSystem.builder().description("test").build()).status(Status.AVAILABLE).build();
expect(delegate.createImage(template)).andReturn(immediateFuture(result));
expect(credsToImage.apply(result)).andReturn(
ImageBuilder.fromImage(result).defaultCredentials(credentials).build());
replay(delegate, credsToImage);
Future<Image> image = new DelegatingImageExtension(imageCache, delegate, credsToImage, credentialStore)
.createImage(template);
assertEquals(image.get().getDefaultCredentials(), credentials);
verify(delegate, credsToImage);
}
}

View File

@ -47,6 +47,7 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.extensions.internal.DelegatingImageExtension;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.internal.PersistNodeCredentials;
import org.jclouds.compute.options.TemplateOptions;
@ -103,13 +104,14 @@ public class AWSEC2ComputeService extends EC2ComputeService {
@Named("DELETED") Predicate<PlacementGroup> placementGroupDeleted, Optional<ImageExtension> imageExtension,
GroupNamingConvention.Factory namingConvention,
@Named(PROPERTY_EC2_GENERATE_INSTANCE_NAMES) boolean generateInstanceNames,
Optional<SecurityGroupExtension> securityGroupExtension) {
Optional<SecurityGroupExtension> securityGroupExtension,
DelegatingImageExtension.Factory delegatingImageExtension) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy,
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, runScriptOnNodeFactory, initAdminAccess,
persistNodeCredentials, timeouts, userExecutor, client, credentialsMap, securityGroupMap, imageExtension,
namingConvention, generateInstanceNames, securityGroupExtension);
namingConvention, generateInstanceNames, securityGroupExtension, delegatingImageExtension);
this.client = client;
this.placementGroupMap = placementGroupMap;
this.placementGroupDeleted = placementGroupDeleted;

View File

@ -16,6 +16,10 @@
*/
package org.jclouds.azurecompute.arm.compute;
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 java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
@ -38,10 +42,10 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.extensions.internal.DelegatingImageExtension;
import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.internal.PersistNodeCredentials;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetImageStrategy;
@ -62,10 +66,6 @@ import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.ListeningExecutorService;
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;
@Singleton
public class AzureComputeService extends BaseComputeService {
private final CleanupResources cleanupResources;
@ -84,15 +84,16 @@ public class AzureComputeService extends BaseComputeService {
@Named(TIMEOUT_NODE_SUSPENDED) Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
PersistNodeCredentials persistNodeCredentials,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
CleanupResources cleanupResources, Optional<ImageExtension> imageExtension,
Optional<SecurityGroupExtension> securityGroupExtension) {
Optional<SecurityGroupExtension> securityGroupExtension,
DelegatingImageExtension.Factory delegatingImageExtension) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy,
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, timeouts, userExecutor, imageExtension, securityGroupExtension);
persistNodeCredentials, userExecutor, imageExtension, securityGroupExtension, delegatingImageExtension);
this.cleanupResources = cleanupResources;
}

View File

@ -38,10 +38,10 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.extensions.internal.DelegatingImageExtension;
import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.internal.PersistNodeCredentials;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetImageStrategy;
@ -65,26 +65,26 @@ import com.google.common.util.concurrent.ListeningExecutorService;
public class GoGridComputeService extends BaseComputeService {
@Inject
protected GoGridComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@Memoized Supplier<Set<? extends Image>> images,
@Memoized Supplier<Set<? extends Hardware>> hardwareProfiles,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetImageStrategy getImageStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy,
DestroyNodeStrategy destroyNodeStrategy, ResumeNodeStrategy resumeNodeStrategy,
SuspendNodeStrategy suspendNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider,
@Named("DEFAULT") Provider<TemplateOptions> templateOptionsProvider,
@Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning,
@Named(TIMEOUT_NODE_TERMINATED) Predicate<AtomicReference<NodeMetadata>> nodeTerminated,
@Named(TIMEOUT_NODE_SUSPENDED) Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, InitAdminAccess initAdminAccess,
RunScriptOnNode.Factory runScriptOnNodeFactory, PersistNodeCredentials persistNodeCredentials,
Timeouts timeouts, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
Optional<ImageExtension> imageExtension, Optional<SecurityGroupExtension> securityGroupExtension) {
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> hardwareProfiles,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetImageStrategy getImageStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy,
DestroyNodeStrategy destroyNodeStrategy, ResumeNodeStrategy resumeNodeStrategy,
SuspendNodeStrategy suspendNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider,
@Named("DEFAULT") Provider<TemplateOptions> templateOptionsProvider,
@Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning,
@Named(TIMEOUT_NODE_TERMINATED) Predicate<AtomicReference<NodeMetadata>> nodeTerminated,
@Named(TIMEOUT_NODE_SUSPENDED) Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, InitAdminAccess initAdminAccess,
RunScriptOnNode.Factory runScriptOnNodeFactory, PersistNodeCredentials persistNodeCredentials,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
Optional<ImageExtension> imageExtension, Optional<SecurityGroupExtension> securityGroupExtension,
DelegatingImageExtension.Factory delegatingImageExtension) {
super(context, credentialStore, images, hardwareProfiles, locations, listNodesStrategy, getImageStrategy,
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
resumeNodeStrategy, suspendNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, timeouts, userExecutor, imageExtension, securityGroupExtension);
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
resumeNodeStrategy, suspendNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, userExecutor, imageExtension, securityGroupExtension, delegatingImageExtension);
}
/**

View File

@ -39,11 +39,11 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.extensions.SecurityGroupExtension;
import org.jclouds.compute.extensions.internal.DelegatingImageExtension;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.internal.PersistNodeCredentials;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetImageStrategy;
@ -76,44 +76,30 @@ public final class GoogleComputeEngineService extends BaseComputeService {
private final GoogleComputeEngineApi api;
private final Predicate<AtomicReference<Operation>> operationDone;
@Inject GoogleComputeEngineService(ComputeServiceContext context,
Map<String, Credentials> credentialStore,
@Memoized Supplier<Set<? extends Image>> images,
@Memoized Supplier<Set<? extends Hardware>> hardwareProfiles,
@Memoized Supplier<Set<? extends Location>> locations,
ListNodesStrategy listNodesStrategy,
GetImageStrategy getImageStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy,
CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy,
DestroyNodeStrategy destroyNodeStrategy,
ResumeNodeStrategy resumeNodeStrategy,
SuspendNodeStrategy suspendNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider,
@Named("DEFAULT") Provider<TemplateOptions> templateOptionsProvider,
@Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>>
nodeRunning,
@Named(TIMEOUT_NODE_TERMINATED) Predicate<AtomicReference<NodeMetadata>>
nodeTerminated,
@Named(TIMEOUT_NODE_SUSPENDED)
Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
InitAdminAccess initAdminAccess,
RunScriptOnNode.Factory runScriptOnNodeFactory,
PersistNodeCredentials persistNodeCredentials,
ComputeServiceConstants.Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
Optional<ImageExtension> imageExtension,
Optional<SecurityGroupExtension> securityGroupExtension,
Function<Set<? extends NodeMetadata>, Set<String>> findOrphanedGroups,
GroupNamingConvention.Factory namingConvention,
GoogleComputeEngineApi api,
Predicate<AtomicReference<Operation>> operationDone) {
@Inject
GoogleComputeEngineService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> hardwareProfiles,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetImageStrategy getImageStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy,
DestroyNodeStrategy destroyNodeStrategy, ResumeNodeStrategy resumeNodeStrategy,
SuspendNodeStrategy suspendNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider,
@Named("DEFAULT") Provider<TemplateOptions> templateOptionsProvider,
@Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning,
@Named(TIMEOUT_NODE_TERMINATED) Predicate<AtomicReference<NodeMetadata>> nodeTerminated,
@Named(TIMEOUT_NODE_SUSPENDED) Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, InitAdminAccess initAdminAccess,
RunScriptOnNode.Factory runScriptOnNodeFactory, PersistNodeCredentials persistNodeCredentials,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
Optional<ImageExtension> imageExtension, Optional<SecurityGroupExtension> securityGroupExtension,
Function<Set<? extends NodeMetadata>, Set<String>> findOrphanedGroups,
GroupNamingConvention.Factory namingConvention, GoogleComputeEngineApi api,
Predicate<AtomicReference<Operation>> operationDone, DelegatingImageExtension.Factory delegatingImageExtension) {
super(context, credentialStore, images, hardwareProfiles, locations, listNodesStrategy, getImageStrategy,
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
resumeNodeStrategy, suspendNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, timeouts, userExecutor, imageExtension, securityGroupExtension);
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
resumeNodeStrategy, suspendNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, userExecutor, imageExtension, securityGroupExtension, delegatingImageExtension);
this.findOrphanedGroups = findOrphanedGroups;
this.namingConvention = namingConvention;
this.api = api;