Path: blob/develop/tests/unit/customizations/emr/test_add_instance_groups.py
1569 views
# Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.1#2# Licensed under the Apache License, Version 2.0 (the "License"). You3# may not use this file except in compliance with the License. A copy of4# the License is located at5#6# http://aws.amazon.com/apache2.0/7#8# or in the "license" file accompanying this file. This file is9# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF10# ANY KIND, either express or implied. See the License for the specific11# language governing permissions and limitations under the License.1213from tests.unit.customizations.emr import EMRBaseAWSCommandParamsTest as \14BaseAWSCommandParamsTest15from tests.unit.customizations.emr import test_constants as \16CONSTANTS17import json18from awscli.testutils import mock192021INSTANCE_GROUPS_WITH_AUTOSCALING_POLICY = (22' InstanceGroupType=TASK,InstanceType=d2.xlarge,InstanceCount=2,'23'AutoScalingPolicy={Constraints={MinCapacity=1,MaxCapacity=2},'24'Rules=[{Name=TestRule,Description=TestDescription,Action={Market=ON_DEMAND,'25'SimpleScalingPolicyConfiguration={AdjustmentType=EXACT_CAPACITY,ScalingAdjustment=2,CoolDown=5}},'26'Trigger={CloudWatchAlarmDefinition={ComparisonOperator=GREATER_THAN,'27'EvaluationPeriods=5,MetricName=TestMetric,Namespace=EMR,Period=3,Statistic=MAXIMUM,'28'Threshold=4.565,Unit=NONE,Dimensions=[{Key=TestKey,Value=TestValue}]}}}]}'29)3031INSTANCE_GROUPS_WITH_EBS_VOLUME_ARG = (32' InstanceGroupType=TASK,InstanceType=d2.xlarge,InstanceCount=2,EbsConfiguration={EbsOptimized=true,EbsBlockDeviceConfigs=[{VolumeSpecification={VolumeType=gp2,SizeInGB=100,Iops=100},VolumesPerInstance=4},{VolumeSpecification={VolumeType=gp2,SizeInGB=100,Iops=100}}]}')3334INSTANCE_GROUPS_WITH_EBS_VOLUME_MISSING_VOLTYPE_ARG = (35' InstanceGroupType=TASK,InstanceType=d2.xlarge,InstanceCount=2,EbsConfiguration={EbsOptimized=true,EbsBlockDeviceConfigs=[{VolumeSpecification={SizeInGB=100,Iops=100},VolumesPerInstance=4},{VolumeSpecification={VolumeType=gp2,SizeInGB=100,Iops=100}}]}')3637INSTANCE_GROUPS_WITH_EBS_VOLUME_MISSING_SIZE_ARG = (38' InstanceGroupType=TASK,InstanceType=d2.xlarge,InstanceCount=2,EbsConfiguration={EbsOptimized=true,EbsBlockDeviceConfigs=[{VolumeSpecification={VolumeType=gp2,Iops=100},VolumesPerInstance=4},{VolumeSpecification={VolumeType=gp2,SizeInGB=100,Iops=100}}]}')3940INSTANCE_GROUPS_WITH_EBS_VOLUME_MISSING_VOLSPEC_ARG = (41' InstanceGroupType=TASK,InstanceType=d2.xlarge,InstanceCount=2,EbsConfiguration={EbsOptimized=true}')4243INSTANCE_GROUPS_WITH_EBS_VOLUME_MISSING_IOPS_ARG = (44' InstanceGroupType=TASK,InstanceType=d2.xlarge,InstanceCount=2,EbsConfiguration={EbsOptimized=true,EbsBlockDeviceConfigs=[{VolumeSpecification={VolumeType=gp2,SizeInGB=100},VolumesPerInstance=4}]}')4546MULTIPLE_INSTANCE_GROUPS_WITH_EBS_VOLUMES_VOLUME_ARG = (47' InstanceGroupType=TASK,InstanceType=d2.xlarge,InstanceCount=2,EbsConfiguration={EbsOptimized=true,EbsBlockDeviceConfigs=[{VolumeSpecification={VolumeType=gp2,SizeInGB=100},VolumesPerInstance=4}]} InstanceGroupType=CORE,InstanceType=d2.xlarge,InstanceCount=2,EbsConfiguration={EbsOptimized=true,EbsBlockDeviceConfigs=[{VolumeSpecification={VolumeType=gp2,SizeInGB=100,Iops=20}},{VolumeSpecification={VolumeType=gp2,SizeInGB=100,Iops=40}}]}')4849INSTANCE_GROUPS_WITH_CUSTOM_AMI_ARG = (50' InstanceGroupType=TASK,InstanceType=d2.xlarge,InstanceCount=2,CustomAmiId=ami-deadbeef'51)5253DEFAULT_INSTANCE_GROUPS = [{'InstanceRole': 'TASK',54'InstanceCount': 10,55'Name': 'TASK',56'Market': 'ON_DEMAND',57'InstanceType': 'm2.large'58}]596061DEFAULT_INSTANCE_GROUPS_WITH_CUSTOM_AMI = \62[{'CustomAmiId':'ami-deadbeef',63'InstanceRole': 'TASK',64'InstanceCount': 2,65'Name': 'TASK',66'Market': 'ON_DEMAND',67'InstanceType': 'd2.xlarge'}]6869DEFAULT_INSTANCE_GROUPS_WITH_EBS_CONFIG = \70[{'EbsConfiguration':71{'EbsOptimized': True,72'EbsBlockDeviceConfigs':73[74{'VolumeSpecification':75{'Iops': 100,76'SizeInGB': 100,77'VolumeType': 'gp2'},78'VolumesPerInstance': 4},79{'VolumeSpecification':80{'Iops': 100,81'SizeInGB': 100,82'VolumeType': 'gp2'}}]},83'InstanceCount': 2,84'InstanceRole': 'TASK',85'InstanceType': 'd2.xlarge',86'Market': 'ON_DEMAND',87'Name': 'TASK'}]8889DEFAULT_INSTANCE_GROUPS_WITH_EBS_CONFIG_MISSING_IOPS = \90[{'EbsConfiguration':91{'EbsOptimized': True,92'EbsBlockDeviceConfigs':93[{'VolumeSpecification':94{'SizeInGB': 100,95'VolumeType': 'gp2'},96'VolumesPerInstance': 4}]},9798'InstanceCount': 2,99'InstanceRole': 'TASK',100'InstanceType': 'd2.xlarge',101'Market': 'ON_DEMAND',102'Name': 'TASK'}]103104DEFAULT_INSTANCE_GROUPS_WITH_EBS_CONFIG_MISSING_VOLSPEC = \105[{'EbsConfiguration': {'EbsOptimized': True},106'InstanceCount': 2,107'InstanceRole': 'TASK',108'InstanceType': 'd2.xlarge',109'Market': 'ON_DEMAND',110'Name': 'TASK'}]111112DEFAULT_INSTANCE_GROUPS_WITH_AUTOSCALING_POLICY = \113[{'InstanceCount': 2,114'InstanceRole': 'TASK',115'InstanceType': 'd2.xlarge',116'Market': 'ON_DEMAND',117'Name': 'TASK',118'AutoScalingPolicy': {119'Constraints': {120'MinCapacity': 1,121'MaxCapacity': 2122},123'Rules': [124{125'Name': 'TestRule',126'Description': 'TestDescription',127'Action': {128'Market': 'ON_DEMAND',129'SimpleScalingPolicyConfiguration': {130'AdjustmentType': 'EXACT_CAPACITY',131'ScalingAdjustment': 2,132'CoolDown': 5133}134},135'Trigger': {136'CloudWatchAlarmDefinition': {137'ComparisonOperator': 'GREATER_THAN',138'Dimensions': [139{140'Key': 'TestKey',141'Value': 'TestValue'142}],143'EvaluationPeriods': 5,144'MetricName': 'TestMetric',145'Namespace': 'EMR',146'Period': 3,147'Statistic': 'MAXIMUM',148'Threshold': 4.565,149'Unit': 'NONE'150}151}152}153]154}155}]156157DEFAULT_MULTIPLE_INSTANCE_GROUPS_WITH_EBS_CONFIG = \158[{'EbsConfiguration':159{'EbsOptimized': True,160'EbsBlockDeviceConfigs':161[{'VolumeSpecification':162{'SizeInGB': 100,163'VolumeType': 'gp2'},164'VolumesPerInstance': 4}]},165'InstanceCount': 2,166'InstanceRole': 'TASK',167'InstanceType': 'd2.xlarge',168'Market': 'ON_DEMAND',169'Name': 'TASK'},170{'EbsConfiguration':171{'EbsOptimized': True,172'EbsBlockDeviceConfigs':173[{'VolumeSpecification':174{'Iops': 20,175'SizeInGB': 100,176'VolumeType': 'gp2'177}},178{'VolumeSpecification':179{'Iops': 40,180'SizeInGB': 100,181'VolumeType': 'gp2'}}]},182'InstanceCount': 2,183'InstanceRole': 'CORE',184'InstanceType': 'd2.xlarge',185'Market': 'ON_DEMAND',186'Name': 'CORE'}]187188189ADD_INSTANCE_GROUPS_RESULT = {190"InstanceGroupIds": [191"ig-XXXX"192],193"ClusterArn": "arn:aws:elasticmapreduce:region:012345678910:cluster/j-XXXX",194"JobFlowId": "j-YYYY"195}196197CONSTRUCTED_RESULT = {198"InstanceGroupIds": [199"ig-XXXX"200],201"ClusterArn": "arn:aws:elasticmapreduce:region:012345678910:cluster/j-XXXX",202"ClusterId": "j-YYYY"203}204205206class TestAddInstanceGroups(BaseAWSCommandParamsTest):207prefix = 'emr add-instance-groups --cluster-id J-ABCD --instance-groups'208209def test_instance_groups_with_autoscaling_policy(self):210cmd = self.prefix211cmd += INSTANCE_GROUPS_WITH_AUTOSCALING_POLICY212result = {'JobFlowId': 'J-ABCD',213'InstanceGroups': DEFAULT_INSTANCE_GROUPS_WITH_AUTOSCALING_POLICY}214self.assert_params_for_cmd(cmd, result)215216def assert_error_message_has_field_name(self, error_msg, field_name):217self.assertIn('Missing required parameter', error_msg)218self.assertIn(field_name, error_msg)219220def test_instance_groups_default_name_market(self):221cmd = self.prefix222cmd += ' InstanceGroupType=TASK,InstanceCount=10,InstanceType=m2.large'223result = {'JobFlowId': 'J-ABCD',224'InstanceGroups': DEFAULT_INSTANCE_GROUPS}225226self.assert_params_for_cmd(cmd, result)227228def test_instance_groups_missing_instance_group_type_error(self):229cmd = self.prefix + ' Name=Task,InstanceType=m1.small,' +\230'InstanceCount=5'231result = self.run_cmd(cmd, 255)232self.assert_error_message_has_field_name(result[1],233'InstanceGroupType')234235def test_instance_groups_missing_instance_type_error(self):236cmd = self.prefix + ' Name=Task,InstanceGroupType=Task,' +\237'InstanceCount=5'238stderr = self.run_cmd(cmd, 255)[1]239self.assert_error_message_has_field_name(stderr, 'InstanceType')240241def test_instance_groups_missing_instance_count_error(self):242cmd = self.prefix + ' Name=Task,InstanceGroupType=Task,' +\243'InstanceType=m1.xlarge'244stderr = self.run_cmd(cmd, 255)[1]245self.assert_error_message_has_field_name(stderr, 'InstanceCount')246247def test_instance_groups_all_fields(self):248cmd = self.prefix + ' InstanceGroupType=MASTER,Name="MasterGroup",' +\249'InstanceCount=1,InstanceType=m1.large'250cmd += ' InstanceGroupType=CORE,Name="CoreGroup",InstanceCount=1,' +\251'InstanceType=m1.xlarge,BidPrice=1.234'252cmd += ' InstanceGroupType=TASK,Name="TaskGroup",InstanceCount=2,' +\253'InstanceType=m1.large'254255expected_instance_groups = [256{'InstanceRole': 'MASTER',257'InstanceCount': 1,258'Name': 'MasterGroup',259'Market': 'ON_DEMAND',260'InstanceType': 'm1.large'261},262{'InstanceRole': 'CORE',263'InstanceCount': 1,264'Name': 'CoreGroup',265'Market': 'SPOT',266'BidPrice': '1.234',267'InstanceType': 'm1.xlarge'268},269{'InstanceRole': 'TASK',270'InstanceCount': 2,271'Name': 'TaskGroup',272'Market': 'ON_DEMAND',273'InstanceType': 'm1.large'274}275]276result = {'JobFlowId': 'J-ABCD',277'InstanceGroups': expected_instance_groups}278279self.assert_params_for_cmd(cmd, result)280281def test_instance_groups_spot_bidprice_equals_ondemandprice(self):282cmd = self.prefix + ' InstanceGroupType=MASTER,Name="MasterGroup",' +\283'InstanceCount=1,InstanceType=m1.large,BidPrice=OnDemandPrice'284cmd += ' InstanceGroupType=CORE,Name="CoreGroup",InstanceCount=1,' +\285'InstanceType=m1.xlarge,BidPrice=OnDemandPrice'286cmd += ' InstanceGroupType=TASK,Name="TaskGroup",InstanceCount=2,' +\287'InstanceType=m1.large,BidPrice=OnDemandPrice'288289expected_instance_groups = [290{'InstanceRole': 'MASTER',291'InstanceCount': 1,292'Name': 'MasterGroup',293'Market': 'SPOT',294'InstanceType': 'm1.large'295},296{'InstanceRole': 'CORE',297'InstanceCount': 1,298'Name': 'CoreGroup',299'Market': 'SPOT',300'InstanceType': 'm1.xlarge'301},302{'InstanceRole': 'TASK',303'InstanceCount': 2,304'Name': 'TaskGroup',305'Market': 'SPOT',306'InstanceType': 'm1.large'307}308]309result = {'JobFlowId': 'J-ABCD',310'InstanceGroups': expected_instance_groups}311312self.assert_params_for_cmd(cmd, result)313314def test_instance_groups_with_ebs_config(self):315cmd = self.prefix316cmd += INSTANCE_GROUPS_WITH_EBS_VOLUME_ARG317result = {'JobFlowId': 'J-ABCD',318'InstanceGroups': DEFAULT_INSTANCE_GROUPS_WITH_EBS_CONFIG}319self.assert_params_for_cmd(cmd, result)320321def test_instance_groups_with_ebs_config_missing_volume_type(self):322cmd = self.prefix323cmd += INSTANCE_GROUPS_WITH_EBS_VOLUME_MISSING_VOLTYPE_ARG324stderr = self.run_cmd(cmd, 255)[1]325self.assert_error_message_has_field_name(stderr, 'VolumeType')326327def test_instance_groups_with_ebs_config_missing_size(self):328cmd = self.prefix329cmd += INSTANCE_GROUPS_WITH_EBS_VOLUME_MISSING_SIZE_ARG330stderr = self.run_cmd(cmd, 255)[1]331self.assert_error_message_has_field_name(stderr, 'SizeInGB')332333def test_instance_groups_with_ebs_config_missing_volume_spec(self):334cmd = self.prefix335cmd += INSTANCE_GROUPS_WITH_EBS_VOLUME_MISSING_VOLSPEC_ARG336result = {'JobFlowId': 'J-ABCD',337'InstanceGroups': DEFAULT_INSTANCE_GROUPS_WITH_EBS_CONFIG_MISSING_VOLSPEC}338self.assert_params_for_cmd(cmd, result)339340def test_instance_groups_with_ebs_config_missing_iops(self):341cmd = self.prefix342cmd += INSTANCE_GROUPS_WITH_EBS_VOLUME_MISSING_IOPS_ARG343result = {'JobFlowId': 'J-ABCD',344'InstanceGroups': DEFAULT_INSTANCE_GROUPS_WITH_EBS_CONFIG_MISSING_IOPS}345self.assert_params_for_cmd(cmd, result)346347def test_instance_groups_with_ebs_config_multiple_instance_groups(self):348cmd = self.prefix349cmd += MULTIPLE_INSTANCE_GROUPS_WITH_EBS_VOLUMES_VOLUME_ARG350result = {'JobFlowId': 'J-ABCD',351'InstanceGroups': DEFAULT_MULTIPLE_INSTANCE_GROUPS_WITH_EBS_CONFIG}352self.assert_params_for_cmd(cmd, result)353354def test_instance_groups_with_custom_ami_instance_groups(self):355cmd = self.prefix356cmd += INSTANCE_GROUPS_WITH_CUSTOM_AMI_ARG357result = {'JobFlowId': 'J-ABCD',358'InstanceGroups': DEFAULT_INSTANCE_GROUPS_WITH_CUSTOM_AMI}359self.assert_params_for_cmd(cmd, result)360361@mock.patch('awscli.customizations.emr.emrutils.call')362def test_constructed_result(self, call_patch):363call_patch.return_value = ADD_INSTANCE_GROUPS_RESULT364cmd = self.prefix365cmd += ' InstanceGroupType=TASK,InstanceCount=10,InstanceType=m2.large'366367result = self.run_cmd(cmd, expected_rc=0)368result_json = json.loads(result[0])369370self.assertEqual(result_json, CONSTRUCTED_RESULT)371372if __name__ == "__main__":373unittest.main()374375376