From 9606ac4611ca9fe897a2b5a0f86664a46b4adba1 Mon Sep 17 00:00:00 2001 From: David Date: Wed, 30 Jul 2014 10:12:17 -0400 Subject: [PATCH 1/3] Adding the T2 class of burstable instances --- grails-app/conf/BuildConfig.groovy | 2 +- .../netflix/asgard/InstanceTypeService.groovy | 11 ++ .../com/netflix/asgard/mock/linux-od.json | 152 +++++++++++++++++- .../netflix/asgard/model/InstanceType.groovy | 3 + 4 files changed, 166 insertions(+), 2 deletions(-) diff --git a/grails-app/conf/BuildConfig.groovy b/grails-app/conf/BuildConfig.groovy index 0fcdf8e8..6baa96c9 100644 --- a/grails-app/conf/BuildConfig.groovy +++ b/grails-app/conf/BuildConfig.groovy @@ -92,7 +92,7 @@ grails.project.dependency.resolution = { compile( // Amazon Web Services programmatic interface. Transitive dependency of glisten, but also used directly. - 'com.amazonaws:aws-java-sdk:1.7.5', + 'com.amazonaws:aws-java-sdk:1.8.3', // Enables publication of a health check URL for deploying Asgard, and an on/off switch for activities. // Transitive dependencies include: diff --git a/grails-app/services/com/netflix/asgard/InstanceTypeService.groovy b/grails-app/services/com/netflix/asgard/InstanceTypeService.groovy index 3c5ccbe8..2d8599f0 100644 --- a/grails-app/services/com/netflix/asgard/InstanceTypeService.groovy +++ b/grails-app/services/com/netflix/asgard/InstanceTypeService.groovy @@ -151,6 +151,7 @@ class InstanceTypeService implements CacheInitializer { String memOpt = 'Memory optimized' String hiMem = 'High-Memory' String compOpt = 'Compute optimized' + String bInst = 'Burstable Performance Instances' String six4 = '64-bit' String three2OrSix4 = '32-bit or 64-bit' String hcpu = 'High-CPU' @@ -158,13 +159,23 @@ class InstanceTypeService implements CacheInitializer { new HardwareProfile(instanceType: 't1.micro', family: 'Micro instances', group: 'Micro', size: 'Micro', arch: three2OrSix4, vCpu: '1', ecu: 'Variable', mem: '0.615', storage: 'EBS only', ebsOptim: '-', netPerf: 'Very Low'), + new HardwareProfile(instanceType: 't2.micro', family: bInst, group: gen, size: 'Micro', + arch: three2OrSix4, vCpu: '1', ecu: 'Variable', mem: '1', storage: 'EBS only', + ebsOptim: '-', netPerf: 'Low to Moderate'), new HardwareProfile(instanceType: 'm1.small', family: gen, group: 'Standard', size: 'Small (Default)', arch: three2OrSix4, vCpu: '1', ecu: '1', mem: '1.7', storage: '1 x 160', ebsOptim: '-', netPerf: 'Low'), + new HardwareProfile(instanceType: 't2.small', family: bInst, group: gen, size: 'Small', + arch: three2OrSix4, vCpu: '1', ecu: '1', mem: '2', storage: 'EBS only', ebsOptim: '-', + netPerf: 'Low to Moderate'), + new HardwareProfile(instanceType: 'm1.medium', family: gen, group: 'Standard', size: 'Medium', arch: three2OrSix4, vCpu: '1', ecu: '2', mem: '3.75', storage: '1 x 410', ebsOptim: '-', netPerf: 'Moderate'), + new HardwareProfile(instanceType: 't2.medium', family: bInst, group: gen, size: 'Medium', + arch: three2OrSix4, vCpu: '2', ecu: '2', mem: '4', storage: 'EBS only', ebsOptim: '-', + netPerf: 'Low to Moderate'), new HardwareProfile(instanceType: 'm1.large', family: gen, group: 'Standard', size: 'Large', arch: six4, vCpu: '2', ecu: '4', mem: '7.5', storage: '2 x 420', ebsOptim: 'Yes', netPerf: 'Moderate'), diff --git a/src/groovy/com/netflix/asgard/mock/linux-od.json b/src/groovy/com/netflix/asgard/mock/linux-od.json index 948cfed3..2bf48c10 100644 --- a/src/groovy/com/netflix/asgard/mock/linux-od.json +++ b/src/groovy/com/netflix/asgard/mock/linux-od.json @@ -375,6 +375,56 @@ ] } ] + }, + { + "type": "Burstable Performance Instances", + "sizes": [ + { + "size": "t2.micro", + "vCPU": "1", + "ECU": "variable", + "memoryGiB": "1", + "storageGB": "ebsonly", + "valueColumns": [ + { + "name": "os", + "prices": { + "USD": "0.013" + } + } + ] + }, + { + "size": "t2.small", + "vCPU": "1", + "ECU": "variable", + "memoryGiB": "2", + "storageGB": "ebsonly", + "valueColumns": [ + { + "name": "os", + "prices": { + "USD": "0.026" + } + } + ] + }, + { + "size": "t2.medium", + "vCPU": "2", + "ECU": "variable", + "memoryGiB": "4", + "storageGB": "ebsonly", + "valueColumns": [ + { + "name": "os", + "prices": { + "USD": "0.052" + } + } + ] + } + ] } ] }, @@ -740,6 +790,56 @@ ] } ] + }, + { + "type": "Burstable Performance Instances", + "sizes": [ + { + "size": "t2.micro", + "vCPU": "1", + "ECU": "variable", + "memoryGiB": "1", + "storageGB": "ebsonly", + "valueColumns": [ + { + "name": "os", + "prices": { + "USD": "0.013" + } + } + ] + }, + { + "size": "t2.small", + "vCPU": "1", + "ECU": "variable", + "memoryGiB": "2", + "storageGB": "ebsonly", + "valueColumns": [ + { + "name": "os", + "prices": { + "USD": "0.026" + } + } + ] + }, + { + "size": "t2.medium", + "vCPU": "2", + "ECU": "variable", + "memoryGiB": "4", + "storageGB": "ebsonly", + "valueColumns": [ + { + "name": "os", + "prices": { + "USD": "0.052" + } + } + ] + } + ] } ] }, @@ -1090,6 +1190,56 @@ ] } ] + }, + { + "type": "Burstable Performance Instances", + "sizes": [ + { + "size": "t2.micro", + "vCPU": "1", + "ECU": "variable", + "memoryGiB": "1", + "storageGB": "ebsonly", + "valueColumns": [ + { + "name": "os", + "prices": { + "USD": "0.013" + } + } + ] + }, + { + "size": "t2.small", + "vCPU": "1", + "ECU": "variable", + "memoryGiB": "2", + "storageGB": "ebsonly", + "valueColumns": [ + { + "name": "os", + "prices": { + "USD": "0.026" + } + } + ] + }, + { + "size": "t2.medium", + "vCPU": "2", + "ECU": "variable", + "memoryGiB": "4", + "storageGB": "ebsonly", + "valueColumns": [ + { + "name": "os", + "prices": { + "USD": "0.052" + } + } + ] + } + ] } ] }, @@ -2620,4 +2770,4 @@ } ] } -} \ No newline at end of file +} diff --git a/src/groovy/com/netflix/asgard/model/InstanceType.groovy b/src/groovy/com/netflix/asgard/model/InstanceType.groovy index 79dc78bb..4a18f0fd 100644 --- a/src/groovy/com/netflix/asgard/model/InstanceType.groovy +++ b/src/groovy/com/netflix/asgard/model/InstanceType.groovy @@ -20,6 +20,9 @@ enum InstanceType { T1Micro("t1.micro"), M1Small("m1.small"), M1Medium("m1.medium"), + T2Micro("t2.micro"), + T2Small("t2.small"), + T2Medium("t2.medium"), M1Large("m1.large"), M1Xlarge("m1.xlarge"), M3Medium("m3.medium"), From 6e298ab9bcd54aed15b05db18f5173aa18441f4e Mon Sep 17 00:00:00 2001 From: David Date: Mon, 4 Aug 2014 10:47:43 -0400 Subject: [PATCH 2/3] Tests fixed --- .../netflix/asgard/AutoScalingControllerSpec.groovy | 6 +++--- .../com/netflix/asgard/EmailerServiceUnitSpec.groovy | 7 +++---- .../netflix/asgard/HostedZoneControllerSpec.groovy | 12 ++++++------ .../netflix/asgard/InstanceTypeServiceSpec.groovy | 2 +- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/test/unit/com/netflix/asgard/AutoScalingControllerSpec.groovy b/test/unit/com/netflix/asgard/AutoScalingControllerSpec.groovy index 5d62ad68..c6c69146 100644 --- a/test/unit/com/netflix/asgard/AutoScalingControllerSpec.groovy +++ b/test/unit/com/netflix/asgard/AutoScalingControllerSpec.groovy @@ -329,9 +329,9 @@ class AutoScalingControllerSpec extends Specification { ['akms', 'helloworld', 'helloworld-frontend', 'helloworld-asgardtest', 'helloworld-tmp', 'ntsuiboot']) //note: attrs['instanceTypes'] is sorted by price - cheapest to most expensive - attrs['instanceTypes'][0].getMonthlyLinuxOnDemandPrice() == '$14.40' - ['t1.micro', 'm1.small', 'm3.medium', 'c3.large', 'm3.large', 'r3.large', 'c3.xlarge', 'm3.xlarge', 'r3.xlarge', - 'c3.2xlarge', 'm3.2xlarge', 'r3.2xlarge', 'c3.4xlarge', 'i2.xlarge', 'r3.4xlarge', 'c3.8xlarge', 'i2.2xlarge', + attrs['instanceTypes'][0].getMonthlyLinuxOnDemandPrice() == '$9.36' + ['t2.micro', 't1.micro', 't2.small', 'm1.small', 't2.medium', 'm3.medium', 'c3.large', 'm3.large', 'r3.large', 'c3.xlarge', + 'm3.xlarge', 'r3.xlarge', 'c3.2xlarge', 'm3.2xlarge', 'r3.2xlarge', 'c3.4xlarge', 'i2.xlarge', 'r3.4xlarge', 'c3.8xlarge', 'i2.2xlarge', 'r3.8xlarge', 'i2.4xlarge', 'hs1.8xlarge', 'i2.8xlarge', 'huge.mainframe', 'c1.medium', 'c1.xlarge', 'cc1.4xlarge', 'cc2.8xlarge', 'cg1.4xlarge', 'cr1.8xlarge', 'g2.2xlarge', 'hi1.4xlarge', 'm1.large', 'm1.medium', 'm1.xlarge', 'm2.2xlarge', 'm2.4xlarge', 'm2.xlarge' diff --git a/test/unit/com/netflix/asgard/EmailerServiceUnitSpec.groovy b/test/unit/com/netflix/asgard/EmailerServiceUnitSpec.groovy index e984fcfa..d6cced30 100644 --- a/test/unit/com/netflix/asgard/EmailerServiceUnitSpec.groovy +++ b/test/unit/com/netflix/asgard/EmailerServiceUnitSpec.groovy @@ -182,10 +182,9 @@ java.io.IOException: Unable to reach Internet due to comet Exception grailsException = new GrailsRuntimeException('Something went wrong', deleteConflictException) String expectedSubject = "Trouble: HalService HalKnowsBest DeleteConflictException" String expectedBodyStart = """You tried to terminate HAL, yet he lives -com.amazonaws.services.identitymanagement.model.DeleteConflictException: Status Code: 403, AWS Service: HalService, \ -AWS Request ID: deadbeef, AWS Error Code: HalKnowsBest, \ -AWS Error Message: I'm sorry, Dave. I'm afraid I can't do that. -\tat""" +com.amazonaws.services.identitymanagement.model.DeleteConflictException: I'm sorry, Dave. I'm afraid I can't do that. \ +(Service: HalService; Status Code: 403; \ +Error Code: HalKnowsBest; Request ID: deadbeef)""" when: String body = emailerService.sendExceptionEmail('You tried to terminate HAL, yet he lives', grailsException) diff --git a/test/unit/com/netflix/asgard/HostedZoneControllerSpec.groovy b/test/unit/com/netflix/asgard/HostedZoneControllerSpec.groovy index 382107bf..ec699334 100644 --- a/test/unit/com/netflix/asgard/HostedZoneControllerSpec.groovy +++ b/test/unit/com/netflix/asgard/HostedZoneControllerSpec.groovy @@ -111,8 +111,8 @@ class HostedZoneControllerSpec extends Specification { e.statusCode = 503 throw e } - controller.flash.message == 'Status Code: 503, AWS Service: Route53, AWS Request ID: BOOGIEBOOGIE, ' + - 'AWS Error Code: DontLikeYou, AWS Error Message: Sorry, pal.' + controller.flash.message == 'Sorry, pal. (Service: Route53; Status Code: 503; ' + + 'Error Code: DontLikeYou; Request ID: BOOGIEBOOGIE)' response.redirectUrl == '/hostedZone/create?name=test.example.com' 0 * _ } @@ -195,8 +195,8 @@ class HostedZoneControllerSpec extends Specification { } controller.flash.message == 'Could not add resource record set: ' + 'com.amazonaws.services.route53.model.InvalidInputException: ' + - 'Status Code: 503, AWS Service: Route53, AWS Request ID: BOOGIEBOOGIE, ' + - 'AWS Error Code: DontLikeYou, AWS Error Message: Sorry, pal.' + 'Sorry, pal. (Service: Route53; Status Code: 503; Error Code: DontLikeYou; ' + + 'Request ID: BOOGIEBOOGIE)' response.redirectUrl == '/hostedZone/prepareResourceRecordSet?hostedZoneId=ZATANNA&resourceRecordSetName=plain.example.com.' 0 * _ @@ -256,8 +256,8 @@ class HostedZoneControllerSpec extends Specification { } controller.flash.message == 'Could not delete resource record set: ' + 'com.amazonaws.services.route53.model.InvalidInputException: ' + - 'Status Code: 503, AWS Service: Route53, AWS Request ID: BOOGIEBOOGIE, ' + - 'AWS Error Code: DontLikeYou, AWS Error Message: Sorry, pal.' + 'Sorry, pal. (Service: Route53; Status Code: 503; ' + + 'Error Code: DontLikeYou; Request ID: BOOGIEBOOGIE)' response.redirectUrl == '/hostedZone/show/ZATANNA' 0 * _ noExceptionThrown() diff --git a/test/unit/com/netflix/asgard/InstanceTypeServiceSpec.groovy b/test/unit/com/netflix/asgard/InstanceTypeServiceSpec.groovy index ba370847..49dc3817 100644 --- a/test/unit/com/netflix/asgard/InstanceTypeServiceSpec.groovy +++ b/test/unit/com/netflix/asgard/InstanceTypeServiceSpec.groovy @@ -79,7 +79,7 @@ class InstanceTypeServiceSpec extends Specification { 'i2.4xlarge', 'i2.8xlarge', 'i2.xlarge', 'm1.large', 'm1.medium', 'm1.small', 'm1.xlarge', 'm2.2xlarge', 'm2.4xlarge', 'm2.xlarge', 'm3.2xlarge', 'm3.large', 'm3.medium', 'm3.xlarge', 'r3.2xlarge', 'r3.4xlarge', 'r3.8xlarge', 'r3.large', 'r3.xlarge', 'superduper.4xlarge', - 't1.micro'] == instanceTypes*.name.sort() + 't1.micro', 't2.medium', 't2.micro', 't2.small'] == instanceTypes*.name.sort() //each list contains mostly nulls def allSizes = instanceTypes*.hardwareProfile*.size allSizes.removeAll { it == null } From ae6a9d36487887384144e3a2f15d4e95cdd2c294 Mon Sep 17 00:00:00 2001 From: e0d Date: Wed, 6 Aug 2014 09:18:44 -0400 Subject: [PATCH 3/3] trivial code style fix --- .../asgard/AutoScalingControllerSpec.groovy | 45 ++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/test/unit/com/netflix/asgard/AutoScalingControllerSpec.groovy b/test/unit/com/netflix/asgard/AutoScalingControllerSpec.groovy index c6c69146..d9aacd90 100644 --- a/test/unit/com/netflix/asgard/AutoScalingControllerSpec.groovy +++ b/test/unit/com/netflix/asgard/AutoScalingControllerSpec.groovy @@ -330,11 +330,46 @@ class AutoScalingControllerSpec extends Specification { //note: attrs['instanceTypes'] is sorted by price - cheapest to most expensive attrs['instanceTypes'][0].getMonthlyLinuxOnDemandPrice() == '$9.36' - ['t2.micro', 't1.micro', 't2.small', 'm1.small', 't2.medium', 'm3.medium', 'c3.large', 'm3.large', 'r3.large', 'c3.xlarge', - 'm3.xlarge', 'r3.xlarge', 'c3.2xlarge', 'm3.2xlarge', 'r3.2xlarge', 'c3.4xlarge', 'i2.xlarge', 'r3.4xlarge', 'c3.8xlarge', 'i2.2xlarge', - 'r3.8xlarge', 'i2.4xlarge', 'hs1.8xlarge', 'i2.8xlarge', 'huge.mainframe', 'c1.medium', 'c1.xlarge', - 'cc1.4xlarge', 'cc2.8xlarge', 'cg1.4xlarge', 'cr1.8xlarge', 'g2.2xlarge', 'hi1.4xlarge', 'm1.large', - 'm1.medium', 'm1.xlarge', 'm2.2xlarge', 'm2.4xlarge', 'm2.xlarge' + [ + 't2.micro', + 't1.micro', + 't2.small', + 'm1.small', + 't2.medium', + 'm3.medium', + 'c3.large', + 'm3.large', + 'r3.large', + 'c3.xlarge', + 'm3.xlarge', + 'r3.xlarge', + 'c3.2xlarge', + 'm3.2xlarge', + 'r3.2xlarge', + 'c3.4xlarge', + 'i2.xlarge', + 'r3.4xlarge', + 'c3.8xlarge', + 'i2.2xlarge', + 'r3.8xlarge', + 'i2.4xlarge', + 'hs1.8xlarge', + 'i2.8xlarge', + 'huge.mainframe', + 'c1.medium', + 'c1.xlarge', + 'cc1.4xlarge', + 'cc2.8xlarge', + 'cg1.4xlarge', + 'cr1.8xlarge', + 'g2.2xlarge', + 'hi1.4xlarge', + 'm1.large', + 'm1.medium', + 'm1.xlarge', + 'm2.2xlarge', + 'm2.4xlarge', + 'm2.xlarge' ] == attrs['instanceTypes']*.name }