Skip to content
This repository was archived by the owner on Dec 19, 2025. It is now read-only.
3 changes: 2 additions & 1 deletion grails-app/conf/BuildConfig.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions grails-app/conf/Config.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ log4j = {
}

root {
info 'asgardrolling'
debug 'asgardrolling'
}

// Set level for all application artifacts
Expand Down Expand Up @@ -68,7 +68,7 @@ log4j = {
development {
console name: 'stdout', layout: pattern(conversionPattern: '[%d{ISO8601}] %c{4} %m%n')
root {
info 'stdout'
debug 'stdout'
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,7 @@ class AwsAutoScalingService implements CacheInitializer, InitializingBean {

void afterPropertiesSet() {
awsClient = new MultiRegionAwsClient<AmazonAutoScaling>({ Region region ->
AmazonAutoScaling client = awsClientService.create(AmazonAutoScaling)
client.setEndpoint("autoscaling.${region}.amazonaws.com")
client
awsClientService.create(AmazonAutoScaling,region)
})
}

Expand Down Expand Up @@ -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)
Expand Down
50 changes: 30 additions & 20 deletions grails-app/services/com/netflix/asgard/AwsClientService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -45,46 +46,55 @@ class AwsClientService implements InitializingBean {

def grailsApplication
def secretService
def endpointService
def serverService
def configService

/**
* Interface names mapped to ClientTypes wrapper objects. For each interface name, a real and fake concrete class
* type should be provided.
*/
private Map<String, Class> interfaceSimpleNamesToAwsClientClasses
private Map<String, Map<String, Class>> 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<String> 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> T create(Class<T> interfaceType) {
Class implementationType = interfaceSimpleNamesToAwsClientClasses[interfaceType.simpleName]
createImpl(implementationType)
public <T> T create(Class<T> interfaceType, Region region = Region.US_EAST_1) {
Class implementationType = interfaceSimpleNamesToAwsClientClasses[region.provider][interfaceType.simpleName]
createImpl(implementationType, interfaceType, region)
}

public <T> T createImpl(Class<T> implementationType) {
implementationType.newInstance(secretService.awsCredentials, clientConfiguration) as T
public <T> T createImpl(Class<T> implementationType, Class<T> 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<String> mocks = grailsApplication.config.grails?."${region.provider}"?.mockServices ?: []
!mocks.contains(interfaceType.simpleName) && grailsApplication.config.server.online ? real : fake
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,7 @@ class AwsCloudWatchService implements CacheInitializer, InitializingBean {

void afterPropertiesSet() {
awsClient = new MultiRegionAwsClient<AmazonCloudWatch>( { Region region ->
AmazonCloudWatch client = awsClientService.create(AmazonCloudWatch)
client.setEndpoint("monitoring.${region}.amazonaws.com")
client
awsClientService.create(AmazonCloudWatch,region)
})
}

Expand Down
8 changes: 3 additions & 5 deletions grails-app/services/com/netflix/asgard/AwsEc2Service.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,8 @@ class AwsEc2Service implements CacheInitializer, InitializingBean {
private static final int TAG_IMAGE_CHUNK_SIZE = 250

void afterPropertiesSet() {
awsClient = awsClient ?: new MultiRegionAwsClient<AmazonEC2>({ Region region ->
AmazonEC2 client = awsClientService.create(AmazonEC2)
client.setEndpoint("ec2.${region}.amazonaws.com")
client
awsClient = new MultiRegionAwsClient<AmazonEC2>({ Region region ->
awsClientService.create(AmazonEC2,region)
})
accounts = configService.awsAccounts
}
Expand Down Expand Up @@ -161,7 +159,7 @@ class AwsEc2Service implements CacheInitializer, InitializingBean {
// Images

private List<Image> retrieveImages(Region region) {
List<String> owners = configService.publicResourceAccounts + configService.awsAccounts
List<String> owners = configService.publicResourceAccounts + configService.getAwsAccounts(region)
DescribeImagesRequest request = new DescribeImagesRequest().withOwners(owners)
AmazonEC2 awsClientForRegion = awsClient.by(region)
List<Image> images = awsClientForRegion.describeImages(request).getImages()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,7 @@ class AwsLoadBalancerService implements CacheInitializer, InitializingBean {

void afterPropertiesSet() {
awsClient = awsClient ?: new MultiRegionAwsClient<AmazonElasticLoadBalancing>( { Region region ->
AmazonElasticLoadBalancing client = awsClientService.create(AmazonElasticLoadBalancing)
client.setEndpoint("elasticloadbalancing.${region}.amazonaws.com")
client
awsClientService.create(AmazonElasticLoadBalancing,region)
})
}

Expand Down
4 changes: 1 addition & 3 deletions grails-app/services/com/netflix/asgard/AwsRdsService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,7 @@ class AwsRdsService implements CacheInitializer, InitializingBean {

void afterPropertiesSet() {
awsClient = new MultiRegionAwsClient<AmazonRDS>( { Region region ->
AmazonRDS client = awsClientService.create(AmazonRDS)
client.setEndpoint("rds.${region}.amazonaws.com")
client
awsClientService.create(AmazonRDS,region)
})
accounts = configService.awsAccounts
}
Expand Down
5 changes: 1 addition & 4 deletions grails-app/services/com/netflix/asgard/AwsS3Service.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,7 @@ class AwsS3Service implements InitializingBean {

void afterPropertiesSet() {
awsClient = new MultiRegionAwsClient<AmazonS3>( { 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)
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,7 @@ class AwsSimpleDbService implements InitializingBean {

void afterPropertiesSet() {
awsClient = new MultiRegionAwsClient<AmazonSimpleDB>( { 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)
})
}

Expand Down
9 changes: 2 additions & 7 deletions grails-app/services/com/netflix/asgard/AwsSnsService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ class AwsSnsService implements CacheInitializer, InitializingBean {

static transactional = false

private String accountNumber
MultiRegionAwsClient<AmazonSNS> awsClient
def grailsApplication
def awsClientService
Expand Down Expand Up @@ -67,12 +66,8 @@ class AwsSnsService implements CacheInitializer, InitializingBean {
}

void afterPropertiesSet() {
accountNumber = configService.awsAccountNumber

awsClient = awsClient ?: new MultiRegionAwsClient<AmazonSNS>( { Region region ->
AmazonSNS client = awsClientService.create(AmazonSNS)
client.setEndpoint("sns.${region}.amazonaws.com")
client
awsClientService.create(AmazonSNS,region)
})
}

Expand All @@ -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)
Expand Down
10 changes: 4 additions & 6 deletions grails-app/services/com/netflix/asgard/AwsSqsService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,7 @@ class AwsSqsService implements CacheInitializer, InitializingBean {
accountNumber = grailsApplication.config.grails.awsAccounts[0]

awsClient = new MultiRegionAwsClient<AmazonSQS>( { Region region ->
AmazonSQS client = awsClientService.create(AmazonSQS)
client.setEndpoint("sqs.${region}.amazonaws.com")
client
awsClientService.create(AmazonSQS,region)
})
}

Expand All @@ -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 []
}
}
Expand Down
10 changes: 5 additions & 5 deletions grails-app/services/com/netflix/asgard/Caches.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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()
Expand Down
28 changes: 14 additions & 14 deletions grails-app/services/com/netflix/asgard/ConfigService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,17 @@ 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]
}

/**
* Gets the mapping of all relevant account numbers to account names.
*
* @return Map <String, String> account numbers to account names
*/
Map<String, String> getAwsAccountNames() {
grailsApplication.config.grails?.awsAccountNames ?: [:]
Map<String, String> getAwsAccountNames(Region region=Region.US_EAST_1) {
grailsApplication.config.grails?."${region.provider()}"?.awsAccountNames ?: [:]
}

/**
Expand Down Expand Up @@ -193,8 +193,8 @@ class ConfigService {
*
* @return list of relevant AWS account numbers, starting with the current account of the current environment
*/
List<String> getAwsAccounts() {
grailsApplication.config.grails?.awsAccounts ?: []
List<String> getAwsAccounts(Region region=Region.US_EAST_1) {
grailsApplication.config.grails?."${region.provider}"?.awsAccounts ?: []
}

/**
Expand Down Expand Up @@ -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() {
Expand Down
Loading