diff --git a/grails-app/conf/BuildConfig.groovy b/grails-app/conf/BuildConfig.groovy index 56551c28..9ce1efe3 100644 --- a/grails-app/conf/BuildConfig.groovy +++ b/grails-app/conf/BuildConfig.groovy @@ -80,7 +80,8 @@ grails.project.dependency.resolution = { compile( // Amazon Web Services programmatic interface - 'com.amazonaws:aws-java-sdk:1.3.32', + 'com.amazonaws:aws-java-sdk:1.4.0', + //'com.amazonaws:aws-java-sdk:1.3.32', ) { // AWS defines their dependencies as open-ended, which causes problems when resolving. // See http://stackoverflow.com/a/7990573/869 diff --git a/grails-app/conf/Config.groovy b/grails-app/conf/Config.groovy index 4645115c..bcf766dd 100644 --- a/grails-app/conf/Config.groovy +++ b/grails-app/conf/Config.groovy @@ -32,7 +32,7 @@ log4j = { } root { - info 'asgardrolling' + debug 'asgardrolling' } // Set level for all application artifacts @@ -68,7 +68,7 @@ log4j = { development { console name: 'stdout', layout: pattern(conversionPattern: '[%d{ISO8601}] %c{4} %m%n') root { - info 'stdout' + debug 'stdout' } } } diff --git a/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy b/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy index 7b64f294..d72b4372 100644 --- a/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsAutoScalingService.groovy @@ -121,9 +121,7 @@ class AwsAutoScalingService implements CacheInitializer, InitializingBean { void afterPropertiesSet() { awsClient = new MultiRegionAwsClient({ Region region -> - AmazonAutoScaling client = awsClientService.create(AmazonAutoScaling) - client.setEndpoint("autoscaling.${region}.amazonaws.com") - client + awsClientService.create(AmazonAutoScaling,region) }) } @@ -938,7 +936,7 @@ class AwsAutoScalingService implements CacheInitializer, InitializingBean { private void ensureUserDataIsDecodedAndTruncated(LaunchConfiguration launchConfiguration) { ensureUserDataIsDecoded(launchConfiguration) - String userData = launchConfiguration.userData + String userData = userData!=null?launchConfiguration.userData:"" int maxLength = configService.cachedUserDataMaxLength if (userData.length() > maxLength) { launchConfiguration.userData = userData.substring(0, maxLength) diff --git a/grails-app/services/com/netflix/asgard/AwsClientService.groovy b/grails-app/services/com/netflix/asgard/AwsClientService.groovy index 46835251..95b524f1 100644 --- a/grails-app/services/com/netflix/asgard/AwsClientService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsClientService.groovy @@ -16,6 +16,7 @@ package com.netflix.asgard import com.amazonaws.ClientConfiguration +import com.amazonaws.regions.Regions import com.amazonaws.services.autoscaling.AmazonAutoScalingClient import com.amazonaws.services.cloudwatch.AmazonCloudWatchClient import com.amazonaws.services.ec2.AmazonEC2Client @@ -45,6 +46,7 @@ class AwsClientService implements InitializingBean { def grailsApplication def secretService + def endpointService def serverService def configService @@ -52,39 +54,47 @@ class AwsClientService implements InitializingBean { * Interface names mapped to ClientTypes wrapper objects. For each interface name, a real and fake concrete class * type should be provided. */ - private Map interfaceSimpleNamesToAwsClientClasses + private Map> interfaceSimpleNamesToAwsClientClasses = [:] private ClientConfiguration clientConfiguration void afterPropertiesSet() { - interfaceSimpleNamesToAwsClientClasses = [ - AmazonAutoScaling: concrete(AmazonAutoScalingClient, MockAmazonAutoScalingClient), - AmazonCloudWatch: concrete(AmazonCloudWatchClient, MockAmazonCloudWatchClient), - AmazonEC2: concrete(AmazonEC2Client, MockAmazonEC2Client), - AmazonElasticLoadBalancing: concrete(AmazonElasticLoadBalancingClient, - MockAmazonElasticLoadBalancingClient), - AmazonRDS: concrete(AmazonRDSClient, MockAmazonRDSClient), - AmazonS3: concrete(AmazonS3Client, MockAmazonS3Client), - AmazonSimpleDB: concrete(AmazonSimpleDBClient, MockAmazonSimpleDBClient), - AmazonSNS: concrete(AmazonSNSClient, MockAmazonSnsClient), - AmazonSQS: concrete(AmazonSQSClient, MockAmazonSqsClient) - ] + Set providers = Region.values().collect { it.provider } as Set + Region.values().findAll { providers.remove(it.provider) }.each { Region region -> + interfaceSimpleNamesToAwsClientClasses[region.provider] = [ + AmazonAutoScaling: concrete(region, AmazonAutoScalingClient, MockAmazonAutoScalingClient), + AmazonCloudWatch: concrete(region, AmazonCloudWatchClient, MockAmazonCloudWatchClient), + AmazonEC2: concrete(region, AmazonEC2Client, MockAmazonEC2Client), + AmazonElasticLoadBalancing: concrete(region, AmazonElasticLoadBalancingClient, MockAmazonElasticLoadBalancingClient), + AmazonRDS: concrete(region, AmazonRDSClient, MockAmazonRDSClient), + AmazonS3: concrete(region, AmazonS3Client, MockAmazonS3Client), + AmazonSimpleDB: concrete(region, AmazonSimpleDBClient, MockAmazonSimpleDBClient), + AmazonSNS: concrete(region, AmazonSNSClient, MockAmazonSnsClient), + AmazonSQS: concrete(region, AmazonSQSClient, MockAmazonSqsClient) + ] + } clientConfiguration = new ClientConfiguration() clientConfiguration.proxyHost = configService.proxyHost clientConfiguration.proxyPort = configService.proxyPort clientConfiguration.userAgent = 'asgard-' + serverService.version } - public T create(Class interfaceType) { - Class implementationType = interfaceSimpleNamesToAwsClientClasses[interfaceType.simpleName] - createImpl(implementationType) + public T create(Class interfaceType, Region region = Region.US_EAST_1) { + Class implementationType = interfaceSimpleNamesToAwsClientClasses[region.provider][interfaceType.simpleName] + createImpl(implementationType, interfaceType, region) } - public T createImpl(Class implementationType) { - implementationType.newInstance(secretService.awsCredentials, clientConfiguration) as T + public T createImpl(Class implementationType, Class interfaceType = null, Region region = Region.US_EAST_1) { + //GRZE:NOTE: just default to Region.US_EAST_1 if there is no endpoint, need to make sure and use right credentials then. + region = endpointService.getEndpoint(region, interfaceType) != null ? region : Region.US_EAST_1 + T client = implementationType.newInstance(secretService.awsCredentials[region], clientConfiguration) as T + client.setEndpoint(endpointService.getEndpoint(region, interfaceType)) + client } - Class concrete(Class real, Class fake) { - grailsApplication.config.server.online ? real : fake + Class concrete(Region region, Class real, Class fake) { + Class interfaceType = real.class.interfaces[0] + Set mocks = grailsApplication.config.grails?."${region.provider}"?.mockServices ?: [] + !mocks.contains(interfaceType.simpleName) && grailsApplication.config.server.online ? real : fake } } diff --git a/grails-app/services/com/netflix/asgard/AwsCloudWatchService.groovy b/grails-app/services/com/netflix/asgard/AwsCloudWatchService.groovy index 4ee2b7ec..06c3831a 100644 --- a/grails-app/services/com/netflix/asgard/AwsCloudWatchService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsCloudWatchService.groovy @@ -53,9 +53,7 @@ class AwsCloudWatchService implements CacheInitializer, InitializingBean { void afterPropertiesSet() { awsClient = new MultiRegionAwsClient( { Region region -> - AmazonCloudWatch client = awsClientService.create(AmazonCloudWatch) - client.setEndpoint("monitoring.${region}.amazonaws.com") - client + awsClientService.create(AmazonCloudWatch,region) }) } diff --git a/grails-app/services/com/netflix/asgard/AwsEc2Service.groovy b/grails-app/services/com/netflix/asgard/AwsEc2Service.groovy index 6199271d..14763acd 100644 --- a/grails-app/services/com/netflix/asgard/AwsEc2Service.groovy +++ b/grails-app/services/com/netflix/asgard/AwsEc2Service.groovy @@ -119,10 +119,8 @@ class AwsEc2Service implements CacheInitializer, InitializingBean { private static final int TAG_IMAGE_CHUNK_SIZE = 250 void afterPropertiesSet() { - awsClient = awsClient ?: new MultiRegionAwsClient({ Region region -> - AmazonEC2 client = awsClientService.create(AmazonEC2) - client.setEndpoint("ec2.${region}.amazonaws.com") - client + awsClient = new MultiRegionAwsClient({ Region region -> + awsClientService.create(AmazonEC2,region) }) accounts = configService.awsAccounts } @@ -161,7 +159,7 @@ class AwsEc2Service implements CacheInitializer, InitializingBean { // Images private List retrieveImages(Region region) { - List owners = configService.publicResourceAccounts + configService.awsAccounts + List owners = configService.publicResourceAccounts + configService.getAwsAccounts(region) DescribeImagesRequest request = new DescribeImagesRequest().withOwners(owners) AmazonEC2 awsClientForRegion = awsClient.by(region) List images = awsClientForRegion.describeImages(request).getImages() diff --git a/grails-app/services/com/netflix/asgard/AwsLoadBalancerService.groovy b/grails-app/services/com/netflix/asgard/AwsLoadBalancerService.groovy index b9a88245..24cd9ae5 100644 --- a/grails-app/services/com/netflix/asgard/AwsLoadBalancerService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsLoadBalancerService.groovy @@ -58,9 +58,7 @@ class AwsLoadBalancerService implements CacheInitializer, InitializingBean { void afterPropertiesSet() { awsClient = awsClient ?: new MultiRegionAwsClient( { Region region -> - AmazonElasticLoadBalancing client = awsClientService.create(AmazonElasticLoadBalancing) - client.setEndpoint("elasticloadbalancing.${region}.amazonaws.com") - client + awsClientService.create(AmazonElasticLoadBalancing,region) }) } diff --git a/grails-app/services/com/netflix/asgard/AwsRdsService.groovy b/grails-app/services/com/netflix/asgard/AwsRdsService.groovy index e8f0eee7..be72dc01 100644 --- a/grails-app/services/com/netflix/asgard/AwsRdsService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsRdsService.groovy @@ -70,9 +70,7 @@ class AwsRdsService implements CacheInitializer, InitializingBean { void afterPropertiesSet() { awsClient = new MultiRegionAwsClient( { Region region -> - AmazonRDS client = awsClientService.create(AmazonRDS) - client.setEndpoint("rds.${region}.amazonaws.com") - client + awsClientService.create(AmazonRDS,region) }) accounts = configService.awsAccounts } diff --git a/grails-app/services/com/netflix/asgard/AwsS3Service.groovy b/grails-app/services/com/netflix/asgard/AwsS3Service.groovy index 6f165644..db6758c8 100644 --- a/grails-app/services/com/netflix/asgard/AwsS3Service.groovy +++ b/grails-app/services/com/netflix/asgard/AwsS3Service.groovy @@ -34,10 +34,7 @@ class AwsS3Service implements InitializingBean { void afterPropertiesSet() { awsClient = new MultiRegionAwsClient( { Region region -> - AmazonS3 client = awsClientService.create(AmazonS3) - // Unconventional S3 endpoints. http://docs.amazonwebservices.com/general/latest/gr/index.html?rande.html - if (region != Region.US_EAST_1) { client.setEndpoint("s3-${region}.amazonaws.com") } - client + awsClientService.create(AmazonS3,region) }) } diff --git a/grails-app/services/com/netflix/asgard/AwsSimpleDbService.groovy b/grails-app/services/com/netflix/asgard/AwsSimpleDbService.groovy index 859592a6..d7a6a23a 100644 --- a/grails-app/services/com/netflix/asgard/AwsSimpleDbService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsSimpleDbService.groovy @@ -43,10 +43,7 @@ class AwsSimpleDbService implements InitializingBean { void afterPropertiesSet() { awsClient = new MultiRegionAwsClient( { Region region -> - AmazonSimpleDB client = awsClientService.create(AmazonSimpleDB) - // Unconventional SDB endpoints. http://docs.amazonwebservices.com/general/latest/gr/index.html?rande.html - if (region != Region.US_EAST_1) { client.setEndpoint("sdb.${region}.amazonaws.com") } - client + awsClientService.create(AmazonSimpleDB,region) }) } diff --git a/grails-app/services/com/netflix/asgard/AwsSnsService.groovy b/grails-app/services/com/netflix/asgard/AwsSnsService.groovy index c0e693ea..72762dd6 100644 --- a/grails-app/services/com/netflix/asgard/AwsSnsService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsSnsService.groovy @@ -39,7 +39,6 @@ class AwsSnsService implements CacheInitializer, InitializingBean { static transactional = false - private String accountNumber MultiRegionAwsClient awsClient def grailsApplication def awsClientService @@ -67,12 +66,8 @@ class AwsSnsService implements CacheInitializer, InitializingBean { } void afterPropertiesSet() { - accountNumber = configService.awsAccountNumber - awsClient = awsClient ?: new MultiRegionAwsClient( { Region region -> - AmazonSNS client = awsClientService.create(AmazonSNS) - client.setEndpoint("sns.${region}.amazonaws.com") - client + awsClientService.create(AmazonSNS,region) }) } @@ -98,7 +93,7 @@ class AwsSnsService implements CacheInitializer, InitializingBean { return caches.allTopics.by(region).get(topicName) } TopicData existingTopic = caches.allTopics.by(region).get(topicName) - TopicData topic = existingTopic ?: new TopicData(region, accountNumber, topicName) + TopicData topic = existingTopic ?: new TopicData(region, configService.awsAccountNumber, topicName) String arn = topic.arn try { GetTopicAttributesRequest attributesRequest = new GetTopicAttributesRequest(arn) diff --git a/grails-app/services/com/netflix/asgard/AwsSqsService.groovy b/grails-app/services/com/netflix/asgard/AwsSqsService.groovy index 582ffe93..8dd15ad4 100644 --- a/grails-app/services/com/netflix/asgard/AwsSqsService.groovy +++ b/grails-app/services/com/netflix/asgard/AwsSqsService.groovy @@ -42,9 +42,7 @@ class AwsSqsService implements CacheInitializer, InitializingBean { accountNumber = grailsApplication.config.grails.awsAccounts[0] awsClient = new MultiRegionAwsClient( { Region region -> - AmazonSQS client = awsClientService.create(AmazonSQS) - client.setEndpoint("sqs.${region}.amazonaws.com") - client + awsClientService.create(AmazonSQS,region) }) } @@ -58,9 +56,9 @@ class AwsSqsService implements CacheInitializer, InitializingBean { try { return awsClient.by(region).listQueues(new ListQueuesRequest()).queueUrls.collect { new SimpleQueue(it) } } catch (AmazonServiceException ase) { - if (ase.errorCode != 'OptInRequired') { // Ignore if SQS is disabled for this account - throw ase - } +// if (ase.errorCode != 'OptInRequired') { // Ignore if SQS is disabled for this account +// throw ase +// } return [] } } diff --git a/grails-app/services/com/netflix/asgard/Caches.groovy b/grails-app/services/com/netflix/asgard/Caches.groovy index f8a060da..ad14aaf4 100644 --- a/grails-app/services/com/netflix/asgard/Caches.groovy +++ b/grails-app/services/com/netflix/asgard/Caches.groovy @@ -94,16 +94,16 @@ class Caches { Caches(CachedMapBuilder cachedMapBuilder, ConfigService configService = null) { allClusters = cachedMapBuilder.of(EntityType.cluster).buildMultiRegionCachedMap() - allAutoScalingGroups = cachedMapBuilder.of(EntityType.autoScaling, 120).buildMultiRegionCachedMap() + allAutoScalingGroups = cachedMapBuilder.of(EntityType.autoScaling, 15).buildMultiRegionCachedMap() allLaunchConfigurations = cachedMapBuilder.of(EntityType.launchConfiguration, 180).buildMultiRegionCachedMap() - allLoadBalancers = cachedMapBuilder.of(EntityType.loadBalancer, 120).buildMultiRegionCachedMap() + allLoadBalancers = cachedMapBuilder.of(EntityType.loadBalancer, 15).buildMultiRegionCachedMap() allSourceSecurityGroups = cachedMapBuilder.of(EntityType.sourceSecurityGroup).buildMultiRegionCachedMap() allAvailabilityZones = cachedMapBuilder.of(EntityType.availabilityZone, 3600).buildMultiRegionCachedMap() allSubnets = cachedMapBuilder.of(EntityType.subnet, 3600).buildMultiRegionCachedMap() allVpcs = cachedMapBuilder.of(EntityType.vpc, 3600).buildMultiRegionCachedMap() - allKeyPairs = cachedMapBuilder.of(EntityType.keyPair).buildMultiRegionCachedMap() + allKeyPairs = cachedMapBuilder.of(EntityType.keyPair, 120).buildMultiRegionCachedMap() allImages = cachedMapBuilder.of(EntityType.image, 120).buildMultiRegionCachedMap() - allInstances = cachedMapBuilder.of(EntityType.instance, 120).buildMultiRegionCachedMap() + allInstances = cachedMapBuilder.of(EntityType.instance, 15).buildMultiRegionCachedMap() allSpotInstanceRequests = cachedMapBuilder.of(EntityType.spotInstanceRequest, 120).buildMultiRegionCachedMap() allApplicationInstances = cachedMapBuilder.of(EntityType.applicationInstance, 60).buildMultiRegionCachedMap() allReservedInstancesGroups = cachedMapBuilder.of(EntityType.reservation, 3600).buildMultiRegionCachedMap() @@ -121,7 +121,7 @@ class Caches { platformServiceRegions) allScalingPolicies = cachedMapBuilder.of(EntityType.scalingPolicy, 120).buildMultiRegionCachedMap() allScheduledActions = cachedMapBuilder.of(EntityType.scheduledAction, 120).buildMultiRegionCachedMap() - allSignificantStackInstanceHealthChecks = cachedMapBuilder.of(EntityType.instanceHealth, 300). + allSignificantStackInstanceHealthChecks = cachedMapBuilder.of(EntityType.instanceHealth, 60). buildMultiRegionCachedMap() allApplications = cachedMapBuilder.of(EntityType.application, 120).buildCachedMap() allCustomMetrics = cachedMapBuilder.of(EntityType.metric, 120).buildCachedMap() diff --git a/grails-app/services/com/netflix/asgard/ConfigService.groovy b/grails-app/services/com/netflix/asgard/ConfigService.groovy index 3a929098..e672975c 100644 --- a/grails-app/services/com/netflix/asgard/ConfigService.groovy +++ b/grails-app/services/com/netflix/asgard/ConfigService.groovy @@ -51,8 +51,8 @@ class ConfigService { * * @return the AWS account number for the current environment */ - String getAwsAccountNumber() { - grailsApplication.config.grails?.awsAccounts[0] + String getAwsAccountNumber(Region region=Region.US_EAST_1) { + grailsApplication.config.grails?."${region.provider()}"?.awsAccounts[0] } /** @@ -60,8 +60,8 @@ class ConfigService { * * @return Map account numbers to account names */ - Map getAwsAccountNames() { - grailsApplication.config.grails?.awsAccountNames ?: [:] + Map getAwsAccountNames(Region region=Region.US_EAST_1) { + grailsApplication.config.grails?."${region.provider()}"?.awsAccountNames ?: [:] } /** @@ -193,8 +193,8 @@ class ConfigService { * * @return list of relevant AWS account numbers, starting with the current account of the current environment */ - List getAwsAccounts() { - grailsApplication.config.grails?.awsAccounts ?: [] + List getAwsAccounts(Region region=Region.US_EAST_1) { + grailsApplication.config.grails?."${region.provider}"?.awsAccounts ?: [] } /** @@ -239,20 +239,20 @@ class ConfigService { grailsApplication.config.server.online } - String getAccessId() { - grailsApplication.config.secret?.accessId ?: null + String getAccessId(Region region=Region.US_EAST_1) { + grailsApplication.config.secret?."${region.provider}"?.accessId ?: null } - String getSecretKey() { - grailsApplication.config.secret?.secretKey ?: null + String getSecretKey(Region region=Region.US_EAST_1) { + grailsApplication.config.secret?."${region.provider}"?.secretKey ?: null } - String getAccessIdFileName() { - grailsApplication.config.secret?.accessIdFileName ?: null + String getAccessIdFileName(Region region=Region.US_EAST_1) { + grailsApplication.config.secret?."${region.provider}"?.accessIdFileName ?: null } - String getSecretKeyFileName() { - grailsApplication.config.secret?.secretKeyFileName ?: null + String getSecretKeyFileName(Region region=Region.US_EAST_1) { + grailsApplication.config.secret?."${region.provider}"?.secretKeyFileName ?: null } String getLoadBalancerUsernameFile() { diff --git a/grails-app/services/com/netflix/asgard/EndpointService.groovy b/grails-app/services/com/netflix/asgard/EndpointService.groovy new file mode 100644 index 00000000..9a4d3471 --- /dev/null +++ b/grails-app/services/com/netflix/asgard/EndpointService.groovy @@ -0,0 +1,53 @@ +package com.netflix.asgard + +import org.springframework.beans.factory.InitializingBean + +class EndpointService implements InitializingBean { + static transactional = false + + def grailsApplication + + private def providers + void afterPropertiesSet() { + providers = [ + 'aws': [ + AmazonAutoScaling: { Region region -> "autoscaling.${region}.amazonaws.com" }, + AmazonCloudWatch: { Region region -> "monitoring.${region}.amazonaws.com" }, + AmazonEC2: { Region region -> "ec2.${region}.amazonaws.com" }, + AmazonElasticLoadBalancing: { Region region -> "elasticloadbalancing.${region}.amazonaws.com" }, + AmazonRDS: { Region region -> "rds.${region}.amazonaws.com" }, + // Unconventional S3 endpoints. http://docs.amazonwebservices.com/general/latest/gr/index.html?rande.html + AmazonS3: { Region region -> region != Region.US_EAST_1 ? "s3-${region}.amazonaws.com" : "s3.amazonaws.com" }, + // Unconventional SDB endpoints. http://docs.amazonwebservices.com/general/latest/gr/index.html?rande.html + AmazonSimpleDB: { Region region -> region != Region.US_EAST_1 ? "sdb.${region}.amazonaws.com" : "sdb.amazonaws.com" }, + AmazonSNS: { Region region -> "sns.${region}.amazonaws.com" }, + AmazonSQS: { Region region -> "sqs.${region}.amazonaws.com" } + ] as Map, + 'eucauser': createEucalyptusEndpoints(),//GRZE:HACK: temporary! + 'eucalyptus': createEucalyptusEndpoints() + ] + } + + String getEndpoint(Region region, Class serviceInterfaceClass) { + Set useAws = grailsApplication.config.grails?."${region.provider}"?.useAwsServices ?: [] + if(useAws.contains(serviceInterfaceClass.simpleName)){ + return null; + } else { + def endpointSupplier = providers[region.provider]?.get(serviceInterfaceClass.simpleName) ?: null + endpointSupplier?.call(region) + } + } + + private Map createEucalyptusEndpoints() { + //GRZE:NOTE: this is a temporary hack related to the region enum fwiw. + def configHostName = grailsApplication.config.grails?.eucalyptus?.hostName + [ + AmazonAutoScaling: { Region region, String hostName -> "http://${hostName}:8773/services/AutoScaling" }.rcurry(configHostName), + AmazonCloudWatch: { Region region, String hostName -> "http://${hostName}:8773/services/CloudWatch" }.rcurry(configHostName), + AmazonEC2: { Region region, String hostName -> "http://${hostName}:8773/services/Eucalyptus/" }.rcurry(configHostName), + AmazonElasticLoadBalancing: { Region region, String hostName -> "http://${hostName}:8773/services/LoadBalancing" }.rcurry(configHostName), + AmazonS3: { Region region, String hostName -> "http://${hostName}:8773/services/Walrus" }.rcurry(configHostName), + ] as Map + } + +} diff --git a/grails-app/services/com/netflix/asgard/InitService.groovy b/grails-app/services/com/netflix/asgard/InitService.groovy index 97bc26c2..f13462f6 100644 --- a/grails-app/services/com/netflix/asgard/InitService.groovy +++ b/grails-app/services/com/netflix/asgard/InitService.groovy @@ -7,7 +7,7 @@ * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software + * Unless required by applicable law or agrleed 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 @@ -78,6 +78,6 @@ class InitService implements ApplicationContextAware { */ boolean cachesFilled() { Collection fillableCaches = caches.properties*.value.findAll { it instanceof Fillable } - !fillableCaches.find { !it.filled } + !fillableCaches.find { !it.filled; } } } diff --git a/grails-app/services/com/netflix/asgard/InstanceTypeService.groovy b/grails-app/services/com/netflix/asgard/InstanceTypeService.groovy index 87a1dc02..058c5b4a 100644 --- a/grails-app/services/com/netflix/asgard/InstanceTypeService.groovy +++ b/grails-app/services/com/netflix/asgard/InstanceTypeService.groovy @@ -241,7 +241,7 @@ class InstanceTypeService implements CacheInitializer { } } } else { - throw new Exception("Unexpected format of HTML on ${instanceTypesUrl}") +// throw new Exception("Unexpected format of HTML on ${instanceTypesUrl}") } hardwareProfiles } diff --git a/grails-app/services/com/netflix/asgard/SecretService.groovy b/grails-app/services/com/netflix/asgard/SecretService.groovy index 7d14a753..0b8242c4 100644 --- a/grails-app/services/com/netflix/asgard/SecretService.groovy +++ b/grails-app/services/com/netflix/asgard/SecretService.groovy @@ -24,7 +24,7 @@ class SecretService implements InitializingBean { def configService def sshService - BasicAWSCredentials awsCredentials + Map awsCredentials = [:] String loadBalancerUserName String loadBalancerPassword @@ -37,9 +37,11 @@ class SecretService implements InitializingBean { void afterPropertiesSet() { if (configService.online) { - String awsAccessId = configService.accessId ?: fetch(configService.accessIdFileName) - String awsSecretKey = configService.secretKey ?: fetch(configService.secretKeyFileName) - awsCredentials = new BasicAWSCredentials(awsAccessId, awsSecretKey) + Region.values().each { Region region -> + String awsAccessId = configService.getAccessId(region) ?: fetch(configService.getAccessIdFileName(region)) + String awsSecretKey = configService.getSecretKey(region) ?: fetch(configService.getSecretKeyFileName(region)) + awsCredentials[region] = new BasicAWSCredentials(awsAccessId, awsSecretKey) + } if (configService.loadBalancerUsernameFile && configService.loadBalancerPasswordFile) { loadBalancerUserName = fetchRemote(configService.loadBalancerUsernameFile) loadBalancerPassword = fetchRemote(configService.loadBalancerPasswordFile) diff --git a/src/groovy/com/netflix/asgard/Region.groovy b/src/groovy/com/netflix/asgard/Region.groovy index a3d1b327..b2872ae1 100644 --- a/src/groovy/com/netflix/asgard/Region.groovy +++ b/src/groovy/com/netflix/asgard/Region.groovy @@ -20,6 +20,20 @@ package com.netflix.asgard */ enum Region { + EUCALYPTUS('euca-admin', + 'eucalyptus', + 'eucalyptus.png', + 'Santa Barbara', + 'Eucalyptus' + ), + + EUCALYPTUS_USER('euca-user', + 'eucauser', + 'eucalyptus.png', + 'Santa Barbara', + 'Eucauser' + ), + US_EAST_1('us-east-1', 'us-east', 'us-east-1.png', @@ -72,12 +86,19 @@ enum Region { String pricingJsonCode String mapImageFileName String location + String provider + + Region(String code, String pricingJsonCode, String mapImageFileName, String location, String provider) { + this(code, pricingJsonCode, mapImageFileName, location) + this.provider = provider + } Region(String code, String pricingJsonCode, mapImageFileName, location) { this.code = code this.pricingJsonCode = pricingJsonCode this.mapImageFileName = mapImageFileName this.location = location + this.provider = 'AWS' } /** @@ -116,9 +137,12 @@ enum Region { } [] } + static Region defaultRegion() { Region.US_EAST_1 } String getDescription() { "$code ($location)" } String toString() { code } + + String getProvider() { provider.toLowerCase() } } diff --git a/test/unit/com/netflix/asgard/EndpointServiceSpec.groovy b/test/unit/com/netflix/asgard/EndpointServiceSpec.groovy new file mode 100644 index 00000000..bee7e485 --- /dev/null +++ b/test/unit/com/netflix/asgard/EndpointServiceSpec.groovy @@ -0,0 +1,20 @@ +package com.netflix.asgard + +import grails.test.mixin.TestFor +import spock.lang.Specification + +/** + * See the API for {@link grails.test.mixin.services.ServiceUnitTestMixin} for usage instructions + */ +@TestFor(EndpointService) +class EndpointServiceSpec extends Specification { + + def setup() { + } + + def cleanup() { + } + + void "test something"() { + } +} diff --git a/web-app/images/worldmap/eucalyptus.png b/web-app/images/worldmap/eucalyptus.png new file mode 100644 index 00000000..6d97fb0f Binary files /dev/null and b/web-app/images/worldmap/eucalyptus.png differ