Path: blob/develop/tests/unit/customizations/emr/test_create_cluster_ami_version.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.1213import copy14import json15import os1617from awscli.testutils import mock, unittest18from tests.unit.customizations.emr import (19EMRBaseAWSCommandParamsTest as BaseAWSCommandParamsTest,20)21from tests.unit.customizations.emr import test_constants as CONSTANTS22from tests.unit.customizations.emr import (23test_constants_instance_fleets as CONSTANTS_FLEET,24)2526DEFAULT_CLUSTER_NAME = "Development Cluster"2728DEFAULT_INSTANCE_GROUPS_ARG = (29'InstanceGroupType=MASTER,Name=MASTER,'30'InstanceCount=1,InstanceType=m1.large,CustomAmiId=ami-deadbeef '31'InstanceGroupType=CORE,Name=CORE,'32'InstanceCount=1,InstanceType=m1.large,CustomAmiId=ami-deadbeef '33'InstanceGroupType=TASK,Name=TASK,'34'InstanceCount=1,InstanceType=m1.large,CustomAmiId=ami-deadpork '35)3637DEFAULT_INSTANCE_GROUPS = [38{39'InstanceRole': 'MASTER',40'InstanceCount': 1,41'Name': 'MASTER',42'CustomAmiId': 'ami-deadbeef',43'Market': 'ON_DEMAND',44'InstanceType': 'm1.large',45},46{47'InstanceRole': 'CORE',48'InstanceCount': 1,49'Name': 'CORE',50'CustomAmiId': 'ami-deadbeef',51'Market': 'ON_DEMAND',52'InstanceType': 'm1.large',53},54{55'InstanceRole': 'TASK',56'InstanceCount': 1,57'Name': 'TASK',58'CustomAmiId': 'ami-deadpork',59'Market': 'ON_DEMAND',60'InstanceType': 'm1.large',61},62]6364DEFAULT_CMD = (65'emr create-cluster --ami-version 3.0.4 --use-default-roles'66' --instance-groups ' + DEFAULT_INSTANCE_GROUPS_ARG + ' '67)6869DEFAULT_INSTANCES = {70'KeepJobFlowAliveWhenNoSteps': True,71'TerminationProtected': False,72'InstanceGroups': DEFAULT_INSTANCE_GROUPS,73}7475EC2_ROLE_NAME = "EMR_EC2_DefaultRole"76EMR_ROLE_NAME = "EMR_DefaultRole"7778TEST_BA = [79{80'ScriptBootstrapAction': {81'Path': 's3://test/ba1',82'Args': ['arg1', 'arg2', 'arg3'],83},84'Name': 'ba1',85},86{87'ScriptBootstrapAction': {88'Path': 's3://test/ba2',89'Args': ['arg1', 'arg2', 'arg3'],90},91'Name': 'ba2',92},93]9495INSTALL_HIVE_STEP = {96'HadoopJarStep': {97'Args': [98's3://us-east-1.elasticmapreduce/libs/hive/hive-script',99'--install-hive',100'--base-path',101's3://us-east-1.elasticmapreduce/libs/hive',102'--hive-versions',103'latest',104],105'Jar': (106's3://us-east-1.elasticmapreduce/libs/'107'script-runner/script-runner.jar'108),109},110'Name': 'Install Hive',111'ActionOnFailure': 'TERMINATE_CLUSTER',112}113114INSTALL_HIVE_SITE_STEP = {115'HadoopJarStep': {116'Args': [117's3://us-east-1.elasticmapreduce/libs/hive/hive-script',118'--base-path',119's3://us-east-1.elasticmapreduce/libs/hive',120'--install-hive-site',121'--hive-site=s3://test/hive-conf/hive-site.xml',122'--hive-versions',123'latest',124],125'Jar': (126's3://us-east-1.elasticmapreduce/libs/'127'script-runner/script-runner.jar'128),129},130'Name': 'Install Hive Site Configuration',131'ActionOnFailure': 'CANCEL_AND_WAIT',132}133134INSTALL_PIG_STEP = {135'HadoopJarStep': {136'Args': [137's3://us-east-1.elasticmapreduce/libs/pig/pig-script',138'--install-pig',139'--base-path',140's3://us-east-1.elasticmapreduce/libs/pig',141'--pig-versions',142'latest',143],144'Jar': (145's3://us-east-1.elasticmapreduce/libs/'146'script-runner/script-runner.jar'147),148},149'Name': 'Install Pig',150'ActionOnFailure': 'TERMINATE_CLUSTER',151}152153INSTALL_HBASE_STEP = {154'HadoopJarStep': {155'Args': ['emr.hbase.backup.Main', '--start-master'],156'Jar': '/home/hadoop/lib/hbase.jar',157},158'Name': 'Start HBase',159'ActionOnFailure': 'TERMINATE_CLUSTER',160}161162INSTALL_GANGLIA_BA = {163'ScriptBootstrapAction': {164'Path': (165's3://us-east-1.elasticmapreduce/'166'bootstrap-actions/install-ganglia'167)168},169'Name': 'Install Ganglia',170}171172INSTALL_HBASE_BA = {173'ScriptBootstrapAction': {174'Path': 's3://us-east-1.elasticmapreduce/bootstrap-actions/setup-hbase'175},176'Name': 'Install HBase',177}178179INSTALL_IMPALA_BA = {180'ScriptBootstrapAction': {181'Path': 's3://us-east-1.elasticmapreduce/libs/impala/setup-impala',182'Args': [183'--base-path',184's3://us-east-1.elasticmapreduce',185'--impala-version',186'latest',187],188},189'Name': 'Install Impala',190}191192INSTALL_MAPR_PRODUCT = {193'Name': 'mapr',194'Args': ['--edition', 'm5', '--version', '3.0.2'],195}196197INSTALL_SUPPORTED_PRODUCTS = [198{199'Name': 'hue',200'Args': ['--hue-config', 's3://elasticmapreduce/hue-config'],201},202{'Name': 'mapr', 'Args': ['--edition', 'm7']},203{'Name': 'unknown', 'Args': ['arg1', 'k1=v1']},204]205206CUSTOM_JAR_STEP = {207'Name': 'Custom JAR',208'ActionOnFailure': 'CONTINUE',209'HadoopJarStep': {'Jar': 's3://mybucket/mytest.jar'},210}211212STREAMING_ARGS = (213'Args=-files,'214's3://elasticmapreduce/samples/wordcount/wordSplitter.py,'215'-mapper,wordSplitter.py,'216'-reducer,aggregate,'217'-input,s3://elasticmapreduce/samples/wordcount/input,'218'-output,s3://mybucket/wordcount/output/2014-04-18/12-15-24'219)220221STREAMING_HADOOP_JAR_STEP = {222'Jar': '/home/hadoop/contrib/streaming/hadoop-streaming.jar',223'Args': [224'-files',225's3://elasticmapreduce/samples/wordcount/wordSplitter.py',226'-mapper',227'wordSplitter.py',228'-reducer',229'aggregate',230'-input',231's3://elasticmapreduce/samples/wordcount/input',232'-output',233's3://mybucket/wordcount/output/2014-04-18/12-15-24',234],235}236237HIVE_BASIC_ARGS = (238'Args=-f,s3://elasticmapreduce/samples/hive-ads/libs/model-build.q'239)240241HIVE_DEFAULT_STEP = {242'Name': 'Hive program',243'ActionOnFailure': 'CONTINUE',244'HadoopJarStep': {245'Jar': (246's3://us-east-1.elasticmapreduce/libs/'247'script-runner/script-runner.jar'248),249'Args': [250's3://us-east-1.elasticmapreduce/libs/hive/hive-script',251'--run-hive-script',252'--hive-versions',253'latest',254'--args',255'-f',256's3://elasticmapreduce/samples/hive-ads/libs/model-build.q',257],258},259}260261HIVE_BASIC_STEP = {262'Name': 'HiveBasicStep',263'ActionOnFailure': 'CANCEL_AND_WAIT',264'HadoopJarStep': {265'Jar': (266's3://us-east-1.elasticmapreduce/libs/'267'script-runner/script-runner.jar'268),269'Args': [270's3://us-east-1.elasticmapreduce/libs/hive/hive-script',271'--run-hive-script',272'--hive-versions',273'latest',274'--args',275'-f',276's3://elasticmapreduce/samples/hive-ads/libs/model-build.q',277],278},279}280281PIG_BASIC_ARGS = (282'Args=-f,' + 's3://elasticmapreduce/samples/pig-apache/do-reports2.pig'283)284285PIG_DEFAULT_STEP = {286'Name': 'Pig program',287'ActionOnFailure': 'CONTINUE',288'HadoopJarStep': {289'Jar': (290's3://us-east-1.elasticmapreduce/libs/'291'script-runner/script-runner.jar'292),293'Args': [294's3://us-east-1.elasticmapreduce/libs/pig/pig-script',295'--run-pig-script',296'--pig-versions',297'latest',298'--args',299'-f',300's3://elasticmapreduce/samples/' 'pig-apache/do-reports2.pig',301],302},303}304305PIG_BASIC_STEP = {306'Name': 'PigBasicStep',307'ActionOnFailure': 'CANCEL_AND_WAIT',308'HadoopJarStep': {309'Jar': (310's3://us-east-1.elasticmapreduce/libs/'311'script-runner/script-runner.jar'312),313'Args': [314's3://us-east-1.elasticmapreduce/libs/pig/pig-script',315'--run-pig-script',316'--pig-versions',317'latest',318'--args',319'-f',320's3://elasticmapreduce/samples/' 'pig-apache/do-reports2.pig',321],322},323}324IMPALA_BASIC_ARGS = (325'Args=--impala-script,s3://myimpala/input,'326'--console-output-path,s3://myimpala/output'327)328329IMPALA_DEFAULT_STEP = {330'Name': 'Impala program',331'ActionOnFailure': 'CONTINUE',332'HadoopJarStep': {333'Jar': (334's3://us-east-1.elasticmapreduce/libs/'335'script-runner/script-runner.jar'336),337'Args': [338's3://us-east-1.elasticmapreduce/libs/impala/setup-impala',339'--run-impala-script',340'--impala-script',341's3://myimpala/input',342'--console-output-path',343's3://myimpala/output',344],345},346}347348CREATE_CLUSTER_RESULT = {349"JobFlowId": "j-XXXX",350"ClusterArn": "arn:aws:elasticmapreduce:region:012345678910:cluster/j-XXXX",351}352353CONSTRUCTED_RESULT = {354"ClusterId": "j-XXXX",355"ClusterArn": "arn:aws:elasticmapreduce:region:012345678910:cluster/j-XXXX",356}357358DEFAULT_RESULT = {359'Name': DEFAULT_CLUSTER_NAME,360'Instances': DEFAULT_INSTANCES,361'AmiVersion': '3.0.4',362'VisibleToAllUsers': True,363'JobFlowRole': EC2_ROLE_NAME,364'ServiceRole': EMR_ROLE_NAME,365'Tags': [],366}367368EMR_MANAGED_MASTER_SECURITY_GROUP = 'sg-master1'369370EMR_MANAGED_SLAVE_SECURITY_GROUP = 'sg-slave1'371372SERVICE_ACCESS_SECURITY_GROUP = "sg-service-access"373374ADDITIONAL_MASTER_SECURITY_GROUPS = [375'sg-addMaster1',376'sg-addMaster2',377'sg-addMaster3',378'sg-addMaster4',379]380381ADDITIONAL_SLAVE_SECURITY_GROUPS = [382'sg-addSlave1',383'sg-addSlave2',384'sg-addSlave3',385'sg-addSlave4',386]387388389class TestCreateCluster(BaseAWSCommandParamsTest):390prefix = 'emr create-cluster '391392def test_quick_start(self):393cmd = (394self.prefix395+ '--ami-version 3.1.0 --instance-groups '396+ DEFAULT_INSTANCE_GROUPS_ARG397)398result = {399'Name': DEFAULT_CLUSTER_NAME,400'Instances': DEFAULT_INSTANCES,401'AmiVersion': '3.1.0',402'VisibleToAllUsers': True,403'Tags': [],404}405self.assert_params_for_cmd(cmd, result)406407def assert_error_message_has_field_name(self, error_msg, field_name):408self.assertIn('Missing required parameter', error_msg)409self.assertIn(field_name, error_msg)410411def test_default_cmd(self):412self.assert_params_for_cmd(DEFAULT_CMD, DEFAULT_RESULT)413414def test_cluster_without_service_role_and_instance_profile(self):415cmd = (416'emr create-cluster --ami-version 3.0.4 '417'--instance-groups ' + DEFAULT_INSTANCE_GROUPS_ARG418)419result = copy.deepcopy(DEFAULT_RESULT)420del result['JobFlowRole']421del result['ServiceRole']422self.assert_params_for_cmd(cmd, result)423424def test_cluster_with_service_role_and_instance_profile(self):425cmd = (426'emr create-cluster --ami-version 3.0.4'427' --service-role ServiceRole --ec2-attributes '428'InstanceProfile=Ec2_InstanceProfile '429'--instance-groups ' + DEFAULT_INSTANCE_GROUPS_ARG430)431result = copy.deepcopy(DEFAULT_RESULT)432result['JobFlowRole'] = 'Ec2_InstanceProfile'433result['ServiceRole'] = 'ServiceRole'434self.assert_params_for_cmd(cmd, result)435436def test_mutual_exclusive_use_default_roles_and_service_role(self):437cmd = (438DEFAULT_CMD439+ '--ec2-attributes InstanceProfile=Ec2_InstanceProfile'440)441expected_error_msg = (442'\naws: error: You cannot specify both --use-default-roles '443'and --ec2-attributes InstanceProfile options together. Either '444'choose --use-default-roles or use both --service-role <roleName>'445' and --ec2-attributes InstanceProfile=<profileName>.\n'446)447result = self.run_cmd(cmd, 255)448self.assertEqual(expected_error_msg, result[1])449450def test_mutual_exclusive_use_default_roles_and_instance_profile(self):451cmd = (452DEFAULT_CMD + '--service-role ServiceRole '453'--ec2-attributes InstanceProfile=Ec2_InstanceProfile'454)455expected_error_msg = (456'\naws: error: You cannot specify both --use-default-roles '457'and --service-role options together. Either choose '458'--use-default-roles or use both --service-role <roleName> '459'and --ec2-attributes InstanceProfile=<profileName>.\n'460)461result = self.run_cmd(cmd, 255)462self.assertEqual(expected_error_msg, result[1])463464def test_cluster_name_no_space(self):465cmd = DEFAULT_CMD + '--name MyCluster'466result = copy.deepcopy(DEFAULT_RESULT)467result['Name'] = 'MyCluster'468self.assert_params_for_cmd(cmd, result)469470def test_cluster_name_with_space(self):471cmd = DEFAULT_CMD.split() + ['--name', 'My Cluster']472result = copy.deepcopy(DEFAULT_RESULT)473result['Name'] = 'My Cluster'474self.assert_params_for_cmd(cmd, result)475476def test_ami_version(self):477cmd = DEFAULT_CMD + '--ami-version 3.0.4'478result = copy.deepcopy(DEFAULT_RESULT)479result['AmiVersion'] = '3.0.4'480self.assert_params_for_cmd(cmd, result)481482def test_log_uri(self):483test_log_uri = 's3://test/logs'484cmd = DEFAULT_CMD + '--log-uri ' + test_log_uri485result = copy.deepcopy(DEFAULT_RESULT)486result['LogUri'] = test_log_uri487self.assert_params_for_cmd(cmd, result)488489def test_additional_info(self):490test_info = '{ami32: "ami-82e305f5"}'491cmd = DEFAULT_CMD.split() + ['--additional-info', test_info]492result = copy.deepcopy(DEFAULT_RESULT)493result['AdditionalInfo'] = test_info494self.assert_params_for_cmd(cmd, result)495496def test_auto_terminte(self):497cmd = (498'emr create-cluster --use-default-roles --ami-version 3.0.4 '499'--auto-terminate --instance-groups ' + DEFAULT_INSTANCE_GROUPS_ARG500)501result = copy.deepcopy(DEFAULT_RESULT)502instances = copy.deepcopy(DEFAULT_INSTANCES)503instances['KeepJobFlowAliveWhenNoSteps'] = False504result['Instances'] = instances505self.assert_params_for_cmd(cmd, result)506507def test_auto_terminate_and_no_auto_terminate(self):508cmd = (509DEFAULT_CMD510+ '--ami-version 3.0.4 '511+ '--auto-terminate --no-auto-terminate'512)513expected_error_msg = (514'\naws: error: cannot use both --no-auto-terminate and'515' --auto-terminate options together.\n'516)517result = self.run_cmd(cmd, 255)518self.assertEqual(expected_error_msg, result[1])519520def test_termination_protected(self):521cmd = DEFAULT_CMD + '--termination-protected'522result = copy.deepcopy(DEFAULT_RESULT)523instances = copy.deepcopy(DEFAULT_INSTANCES)524instances['TerminationProtected'] = True525result['Instances'] = instances526self.assert_params_for_cmd(cmd, result)527528def test_no_termination_protected(self):529cmd = DEFAULT_CMD + '--no-termination-protected'530self.assert_params_for_cmd(cmd, DEFAULT_RESULT)531532def test_termination_protected_and_no_termination_protected(self):533cmd = (534DEFAULT_CMD + '--termination-protected --no-termination-protected'535)536expected_error_msg = (537'\naws: error: cannot use both --termination-protected'538' and --no-termination-protected options together.\n'539)540result = self.run_cmd(cmd, 255)541self.assertEqual(expected_error_msg, result[1])542543def test_unhealthy_node_replacement(self):544cmd = DEFAULT_CMD + '--unhealthy-node-replacement'545result = copy.deepcopy(DEFAULT_RESULT)546instances = copy.deepcopy(DEFAULT_INSTANCES)547instances['UnhealthyNodeReplacement'] = True548result['Instances'] = instances549self.assert_params_for_cmd(cmd, result)550551def test_no_unhealthy_node_replacement(self):552cmd = DEFAULT_CMD + '--no-unhealthy-node-replacement'553result = copy.deepcopy(DEFAULT_RESULT)554instances = copy.deepcopy(DEFAULT_INSTANCES)555instances['UnhealthyNodeReplacement'] = False556result['Instances'] = instances557self.assert_params_for_cmd(cmd, result)558559def test_unhealthy_node_replacement_and_no_unhealthy_node_replacement(560self,561):562cmd = (563DEFAULT_CMD564+ '--unhealthy-node-replacement --no-unhealthy-node-replacement'565)566expected_error_msg = (567'\naws: error: cannot use both --unhealthy-node-replacement'568' and --no-unhealthy-node-replacement options together.\n'569)570result = self.run_cmd(cmd, 255)571self.assertEqual(expected_error_msg, result[1])572573def test_visible_to_all_users(self):574cmd = DEFAULT_CMD + '--visible-to-all-users'575self.assert_params_for_cmd(cmd, DEFAULT_RESULT)576577def test_no_visible_to_all_users(self):578cmd = DEFAULT_CMD + '--no-visible-to-all-users'579result = copy.deepcopy(DEFAULT_RESULT)580result['VisibleToAllUsers'] = False581self.assert_params_for_cmd(cmd, result)582583def test_visible_to_all_users_and_no_visible_to_all_users(self):584cmd = DEFAULT_CMD + '--visible-to-all-users --no-visible-to-all-users'585expected_error_msg = (586'\naws: error: cannot use both --visible-to-all-users and '587'--no-visible-to-all-users options together.\n'588)589result = self.run_cmd(cmd, 255)590self.assertEqual(expected_error_msg, result[1])591592def test_extended_support(self):593cmd = DEFAULT_CMD + '--extended-support'594result = copy.deepcopy(DEFAULT_RESULT)595result['ExtendedSupport'] = True596self.assert_params_for_cmd(cmd, result)597598def test_no_extended_support(self):599cmd = DEFAULT_CMD + '--no-extended-support'600result = copy.deepcopy(DEFAULT_RESULT)601result['ExtendedSupport'] = False602self.assert_params_for_cmd(cmd, result)603604def test_extended_support_and_no_extended_support(self):605cmd = DEFAULT_CMD + '--extended-support --no-extended-support'606expected_error_msg = (607'\naws: error: cannot use both --extended-support'608' and --no-extended-support options together.\n'609)610result = self.run_cmd(cmd, 255)611self.assertEqual(expected_error_msg, result[1])612613def test_tags(self):614cmd = DEFAULT_CMD.split() + ['--tags', 'k1=v1', 'k2', 'k3=spaces v3']615result = copy.deepcopy(DEFAULT_RESULT)616tags = [617{'Key': 'k1', 'Value': 'v1'},618{'Key': 'k2', 'Value': ''},619{'Key': 'k3', 'Value': 'spaces v3'},620]621result['Tags'] = tags622self.assert_params_for_cmd(cmd, result)623624def test_enable_debugging(self):625cmd = DEFAULT_CMD + '--log-uri s3://test/logs --enable-debugging'626result = copy.deepcopy(DEFAULT_RESULT)627result['LogUri'] = 's3://test/logs'628debugging_config = [629{630'Name': 'Setup Hadoop Debugging',631'ActionOnFailure': 'TERMINATE_CLUSTER',632'HadoopJarStep': {633'Args': [634(635's3://us-east-1.elasticmapreduce/libs/'636'state-pusher/0.1/fetch'637)638],639'Jar': 's3://us-east-1.elasticmapreduce/libs/'640+ 'script-runner/script-runner.jar',641},642}643]644result['Steps'] = debugging_config645self.assert_params_for_cmd(cmd, result)646647cmd = DEFAULT_CMD + (648'--log-uri s3://test/logs --enable-debugging ' '--region us-west-2'649)650debugging_config = [651{652'Name': 'Setup Hadoop Debugging',653'ActionOnFailure': 'TERMINATE_CLUSTER',654'HadoopJarStep': {655'Args': [656(657's3://us-west-2.elasticmapreduce/libs/'658'state-pusher/0.1/fetch'659)660],661'Jar': 's3://us-west-2.elasticmapreduce/libs/'662+ 'script-runner/script-runner.jar',663},664}665]666result['Steps'] = debugging_config667self.assert_params_for_cmd(cmd, result)668669def test_enable_debugging_no_log_uri(self):670cmd = DEFAULT_CMD + '--enable-debugging'671expected_error_msg = (672'\naws: error: LogUri not specified. You must specify a logUri'673' if you enable debugging when creating a cluster.\n'674)675result = self.run_cmd(cmd, 255)676self.assertEqual(expected_error_msg, result[1])677678def test_enable_debugging_and_no_enable_debugging(self):679cmd = (680DEFAULT_CMD681+ '--enable-debugging --no-enable-debugging'682+ ' --log-uri s3://test/logs'683)684expected_error_msg = (685'\naws: error: cannot use both --enable-debugging and '686'--no-enable-debugging options together.\n'687)688result = self.run_cmd(cmd, 255)689self.assertEqual(expected_error_msg, result[1])690691def test_instance_groups_default_name_market(self):692cmd = (693'emr create-cluster --use-default-roles --ami-version 3.0.4 '694'--instance-groups '695'InstanceGroupType=MASTER,InstanceCount=1,InstanceType=m1.large,CustomAmiId=ami-deadbeef '696'InstanceGroupType=CORE,InstanceCount=1,InstanceType=m1.large,CustomAmiId=ami-deadbeef '697'InstanceGroupType=TASK,InstanceCount=1,InstanceType=m1.large,CustomAmiId=ami-deadpork '698)699self.assert_params_for_cmd(cmd, DEFAULT_RESULT)700701def test_instance_groups_instance_group_type_mismatch_cases(self):702cmd = (703'emr create-cluster --use-default-roles --ami-version 3.0.4 '704'--instance-groups '705'Name=MASTER,InstanceGroupType=MaSter,InstanceCount=1,'706'InstanceType=m1.large,CustomAmiId=ami-deadbeef Name=CORE,InstanceGroupType=cORE,'707'InstanceCount=1,InstanceType=m1.large,CustomAmiId=ami-deadbeef Name=TASK,'708'InstanceGroupType=tAsK,InstanceCount=1,InstanceType=m1.large,CustomAmiId=ami-deadpork'709)710self.assert_params_for_cmd(cmd, DEFAULT_RESULT)711712def test_instance_groups_instance_type_and_count(self):713cmd = (714'emr create-cluster --use-default-roles --ami-version 3.0.4 '715'--instance-type m1.large'716)717expected_result = copy.deepcopy(DEFAULT_RESULT)718expected_result['Instances'] = {719'KeepJobFlowAliveWhenNoSteps': True,720'TerminationProtected': False,721'InstanceGroups': [722{723'InstanceRole': 'MASTER',724'InstanceCount': 1,725'Name': 'MASTER',726'Market': 'ON_DEMAND',727'InstanceType': 'm1.large',728}729],730}731self.assert_params_for_cmd(cmd, expected_result)732cmd = (733'emr create-cluster --use-default-roles --ami-version 3.0.4 '734'--instance-type m1.large --instance-count 3'735)736expected_result = copy.deepcopy(DEFAULT_RESULT)737expected_result['Instances'] = {738'KeepJobFlowAliveWhenNoSteps': True,739'TerminationProtected': False,740'InstanceGroups': [741{742'InstanceRole': 'MASTER',743'InstanceCount': 1,744'Name': 'MASTER',745'Market': 'ON_DEMAND',746'InstanceType': 'm1.large',747},748{749'InstanceRole': 'CORE',750'InstanceCount': 2,751'Name': 'CORE',752'Market': 'ON_DEMAND',753'InstanceType': 'm1.large',754},755],756}757self.assert_params_for_cmd(cmd, expected_result)758759def test_instance_groups_missing_required_parameter_error(self):760cmd = 'emr create-cluster --use-default-roles --ami-version 3.0.4 '761expect_error_msg = (762'\naws: error: Must specify either --instance-groups or '763'--instance-type with --instance-count(optional) to '764'configure instance groups.\n'765)766result = self.run_cmd(cmd, 255)767self.assertEqual(expect_error_msg, result[1])768769cmd = (770'emr create-cluster --use-default-roles --ami-version 3.0.4 '771'--instance-count 2'772)773expect_error_msg = (774'\naws: error: Must specify either --instance-groups or '775'--instance-type with --instance-count(optional) to '776'configure instance groups.\n'777)778result = self.run_cmd(cmd, 255)779self.assertEqual(expect_error_msg, result[1])780781def test_instance_groups_exclusive_parameter_validation_error(self):782cmd = (783'emr create-cluster --use-default-roles --ami-version 3.0.4 '784'--instance-type m1.large --instance-groups '785+ DEFAULT_INSTANCE_GROUPS_ARG786)787expect_error_msg = (788'\naws: error: You may not specify --instance-type '789'or --instance-count with --instance-groups, '790'because --instance-type and --instance-count are '791'shortcut options for --instance-groups.\n'792)793result = self.run_cmd(cmd, 255)794self.assertEqual(expect_error_msg, result[1])795796cmd = (797'emr create-cluster --use-default-roles --ami-version 3.0.4 '798'--instance-type m1.large --instance-count 2 '799'--instance-groups ' + DEFAULT_INSTANCE_GROUPS_ARG800)801expect_error_msg = (802'\naws: error: You may not specify --instance-type '803'or --instance-count with --instance-groups, '804'because --instance-type and --instance-count are '805'shortcut options for --instance-groups.\n'806)807result = self.run_cmd(cmd, 255)808self.assertEqual(expect_error_msg, result[1])809810def test_instance_groups_missing_instance_group_type_error(self):811cmd = (812'emr create-cluster --use-default-roles --ami-version 3.0.4 '813'--auto-terminate '814'--instance-groups '815'Name=Master,InstanceCount=1,InstanceType=m1.small'816)817stderr = self.run_cmd(cmd, 255)[1]818self.assert_error_message_has_field_name(stderr, 'InstanceGroupType')819820def test_instance_groups_missing_instance_type_error(self):821cmd = (822'emr create-cluster --use-default-roles --ami-version 3.0.4 '823'--auto-terminate '824'--instance-groups '825'Name=Master,InstanceGroupType=MASTER,InstanceCount=1'826)827stderr = self.run_cmd(cmd, 255)[1]828self.assert_error_message_has_field_name(stderr, 'InstanceType')829830def test_instance_groups_missing_instance_count_error(self):831cmd = (832'emr create-cluster --use-default-roles --ami-version 3.0.4 '833'--auto-terminate '834'--instance-groups '835'Name=Master,InstanceGroupType=MASTER,InstanceType=m1.xlarge'836)837stderr = self.run_cmd(cmd, 255)[1]838self.assert_error_message_has_field_name(stderr, 'InstanceCount')839840def test_instance_groups_from_json_file(self):841data_path = os.path.join(842os.path.dirname(__file__), 'input_instance_groups.json'843)844cmd = (845'emr create-cluster --use-default-roles --ami-version 3.0.4 '846'--instance-groups file://' + data_path847)848result = copy.deepcopy(DEFAULT_RESULT)849result['Instances']['InstanceGroups'] = [850{851'InstanceRole': 'MASTER',852'InstanceCount': 1,853'Name': 'Master Instance Group',854'Market': 'ON_DEMAND',855'InstanceType': 'm1.large',856},857{858'InstanceRole': 'CORE',859'InstanceCount': 2,860'Name': 'Core Instance Group',861'Market': 'ON_DEMAND',862'InstanceType': 'm1.xlarge',863},864{865'InstanceRole': 'TASK',866'InstanceCount': 3,867'Name': 'Task Instance Group',868'Market': 'SPOT',869'BidPrice': '3.45',870'InstanceType': 'm1.xlarge',871},872]873self.assert_params_for_cmd(cmd, result)874875def test_instance_groups_from_json_file_spot_bidprice_equals_ondemandprice(876self,877):878data_path = os.path.join(879os.path.dirname(__file__),880'input_instance_groups_spot_bidprice_equals_ondemandprice.json',881)882cmd = (883'emr create-cluster --use-default-roles --ami-version 3.0.4 '884'--instance-groups file://' + data_path885)886result = copy.deepcopy(DEFAULT_RESULT)887result['Instances']['InstanceGroups'] = [888{889'InstanceRole': 'MASTER',890'InstanceCount': 1,891'Name': 'Master Instance Group',892'Market': 'SPOT',893'InstanceType': 'm1.large',894},895{896'InstanceRole': 'CORE',897'InstanceCount': 2,898'Name': 'Core Instance Group',899'Market': 'SPOT',900'InstanceType': 'm1.xlarge',901},902{903'InstanceRole': 'TASK',904'InstanceCount': 3,905'Name': 'Task Instance Group',906'Market': 'SPOT',907'InstanceType': 'm1.xlarge',908},909]910self.assert_params_for_cmd(cmd, result)911912def test_ec2_attributes_no_az(self):913cmd = (914'emr create-cluster --ami-version 3.0.4 '915'--instance-groups '916+ DEFAULT_INSTANCE_GROUPS_ARG917+ ' --ec2-attributes KeyName=testkey,SubnetId=subnet-123456,'918'InstanceProfile=EMR_EC2_DefaultRole '919'--service-role EMR_DefaultRole'920)921result = copy.deepcopy(DEFAULT_RESULT)922result['Instances']['Ec2KeyName'] = 'testkey'923result['Instances']['Ec2SubnetId'] = 'subnet-123456'924result['JobFlowRole'] = 'EMR_EC2_DefaultRole'925self.assert_params_for_cmd(cmd, result)926927def test_ec2_attributes_az(self):928cmd = DEFAULT_CMD + '--ec2-attributes AvailabilityZone=us-east-1a'929result = copy.deepcopy(DEFAULT_RESULT)930result['Instances']['Placement'] = {'AvailabilityZone': 'us-east-1a'}931self.assert_params_for_cmd(cmd, result)932933def test_ec2_attributes_subnet_az_error(self):934cmd = (935DEFAULT_CMD936+ '--ec2-attributes '937+ 'SubnetId=subnet-123456,AvailabilityZone=us-east-1a'938)939expect_error_msg = (940'\naws: error: You may not specify both a SubnetId and an Availab'941'ilityZone (placement) because ec2SubnetId implies a placement.\n'942)943result = self.run_cmd(cmd, 255)944self.assertEqual(expect_error_msg, result[1])945946def test_ec2_attributes_with_subnet_from_json_file(self):947data_path = os.path.join(948os.path.dirname(__file__), 'input_ec2_attributes_with_subnet.json'949)950cmd = (951'emr create-cluster --ami-version 3.0.4 '952'--instance-groups '953+ DEFAULT_INSTANCE_GROUPS_ARG954+ ' --ec2-attributes file://'955+ data_path956+ ' --service-role EMR_DefaultRole'957)958result = copy.deepcopy(DEFAULT_RESULT)959result['Instances']['Ec2KeyName'] = 'testkey'960result['Instances']['Ec2SubnetId'] = 'subnet-123456'961result['JobFlowRole'] = 'EMR_EC2_DefaultRole'962self.assert_params_for_cmd(cmd, result)963964def test_ec2_attributes_with_az_from_json_file(self):965data_path = os.path.join(966os.path.dirname(__file__), 'input_ec2_attributes_with_az.json'967)968cmd = (969'emr create-cluster --ami-version 3.0.4 '970'--instance-groups '971+ DEFAULT_INSTANCE_GROUPS_ARG972+ ' --ec2-attributes file://'973+ data_path974+ ' --service-role EMR_DefaultRole'975)976result = copy.deepcopy(DEFAULT_RESULT)977result['Instances']['Ec2KeyName'] = 'testkey'978result['Instances']['Placement'] = {'AvailabilityZone': 'us-east-1a'}979result['JobFlowRole'] = 'EMR_EC2_DefaultRole'980self.assert_params_for_cmd(cmd, result)981982# Bootstrap Actions test cases983def test_bootstrap_actions_missing_path_error(self):984cmd = DEFAULT_CMD + '--bootstrap-actions Name=ba1,Args=arg1,arg2'985stderr = self.run_cmd(cmd, 255)[1]986self.assert_error_message_has_field_name(stderr, 'Path')987988def test_bootstrap_actions_with_all_fields(self):989cmd = DEFAULT_CMD + (990' --bootstrap-actions '991'Path=s3://test/ba1,Name=ba1,Args=arg1,arg2,arg3 '992'Path=s3://test/ba2,Name=ba2,Args=arg1,arg2,arg3'993)994result = copy.deepcopy(DEFAULT_RESULT)995result['BootstrapActions'] = TEST_BA996997self.assert_params_for_cmd(cmd, result)998999def test_bootstrap_actions_exceed_maximum_error(self):1000cmd = DEFAULT_CMD + ' --bootstrap-actions'1001ba_cmd = ' Path=s3://test/ba1,Name=ba1,Args=arg1,arg2,arg3'1002for i in range(1, 18):1003cmd += ba_cmd10041005expected_error_msg = (1006'\naws: error: maximum number of '1007+ 'bootstrap actions for a cluster exceeded.\n'1008)1009result = self.run_cmd(cmd, 255)10101011self.assertEqual(expected_error_msg, result[1])10121013def test_bootstrap_actions_exceed_maximum_with_applications_error(self):1014cmd = (1015DEFAULT_CMD1016+ ' --applications Name=GANGLIA Name=HBASE'1017+ ' Name=IMPALA,Args=arg1,arg2 --bootstrap-actions'1018)1019ba_cmd = ' Path=s3://test/ba1,Name=ba1,Args=arg1,arg2,arg3'1020for i in range(1, 15):1021cmd += ba_cmd1022expected_error_msg = (1023'\naws: error: maximum number of '1024+ 'bootstrap actions for a cluster exceeded.\n'1025)1026result = self.run_cmd(cmd, 255)1027self.assertEqual(expected_error_msg, result[1])10281029def test_boostrap_actions_with_default_fields(self):1030cmd = DEFAULT_CMD + (1031' --bootstrap-actions Path=s3://test/ba1 Path=s3://test/ba2'1032)1033result = copy.deepcopy(DEFAULT_RESULT)1034result['BootstrapActions'] = [1035{1036'Name': 'Bootstrap action',1037'ScriptBootstrapAction': {'Path': 's3://test/ba1'},1038},1039{1040'Name': 'Bootstrap action',1041'ScriptBootstrapAction': {'Path': 's3://test/ba2'},1042},1043]1044self.assert_params_for_cmd(cmd, result)10451046def test_bootstrap_actions_from_json_file(self):1047data_path = os.path.join(1048os.path.dirname(__file__), 'input_bootstrap_actions.json'1049)1050cmd = DEFAULT_CMD + ' --bootstrap-actions file://' + data_path1051result = copy.deepcopy(DEFAULT_RESULT)1052result['BootstrapActions'] = [1053{1054"Name": "Bootstrap Action 1",1055"ScriptBootstrapAction": {1056"Path": "s3://mybucket/test1",1057"Args": ["arg1", "arg2"],1058},1059},1060{1061"Name": "Bootstrap Action 2",1062"ScriptBootstrapAction": {1063"Path": "s3://mybucket/test2",1064"Args": ["arg1", "arg2"],1065},1066},1067]1068self.assert_params_for_cmd(cmd, result)10691070# Applications test cases1071def test_install_hive_with_defaults(self):1072cmd = DEFAULT_CMD + '--applications Name=Hive'1073result = copy.deepcopy(DEFAULT_RESULT)1074result['Steps'] = [INSTALL_HIVE_STEP]1075self.assert_params_for_cmd(cmd, result)10761077def test_install_hive_with_profile_region(self):1078self.driver.session.set_config_variable('region', 'cn-north-1')1079cmd = DEFAULT_CMD + '--applications Name=Hive'1080HIVE_STEP = json.dumps(INSTALL_HIVE_STEP).replace(1081'us-east-1', 'cn-north-1'1082)1083result = copy.deepcopy(DEFAULT_RESULT)1084result['Steps'] = [json.loads(HIVE_STEP)]1085self.assert_params_for_cmd(cmd, result)10861087def test_install_hive_site(self):1088cmdline = (1089DEFAULT_CMD + '--applications Name=Hive,'1090'Args=[--hive-site=s3://test/hive-conf/hive-site.xml]'1091)1092result = copy.deepcopy(DEFAULT_RESULT)1093result['Steps'] = [INSTALL_HIVE_STEP, INSTALL_HIVE_SITE_STEP]1094self.assert_params_for_cmd(cmdline, result)1095cmdline = (1096DEFAULT_CMD + '--applications Name=Hive,'1097'Args=[--hive-site=s3://test/hive-conf/hive-site.xml,k1]'1098)1099self.assert_params_for_cmd(cmdline, result)11001101def test_install_pig_with_defaults(self):1102cmd = DEFAULT_CMD + '--applications Name=Pig'1103result = copy.deepcopy(DEFAULT_RESULT)1104result['Steps'] = [INSTALL_PIG_STEP]1105self.assert_params_for_cmd(cmd, result)11061107def test_install_ganglia(self):1108cmd = DEFAULT_CMD + '--applications Name=Ganglia'1109result = copy.deepcopy(DEFAULT_RESULT)1110result['BootstrapActions'] = [INSTALL_GANGLIA_BA]1111self.assert_params_for_cmd(cmd, result)11121113def test_install_impala_with_defaults(self):1114cmd = DEFAULT_CMD + '--applications Name=Impala'1115result = copy.deepcopy(DEFAULT_RESULT)1116result['BootstrapActions'] = [INSTALL_IMPALA_BA]1117self.assert_params_for_cmd(cmd, result)11181119def test_install_impala_with_all_fields(self):1120cmd = DEFAULT_CMD + '--applications Name=Impala,Args=arg1,arg2'1121result = copy.deepcopy(DEFAULT_RESULT)1122ba = copy.deepcopy(INSTALL_IMPALA_BA)1123ba['ScriptBootstrapAction']['Args'] += ['--impala-conf', 'arg1,arg2']1124result['BootstrapActions'] = [ba]1125self.assert_params_for_cmd(cmd, result)11261127def test_install_hbase(self):1128cmd = DEFAULT_CMD + '--applications Name=hbase'1129result = copy.deepcopy(DEFAULT_RESULT)1130result['BootstrapActions'] = [INSTALL_HBASE_BA]1131result['Steps'] = [INSTALL_HBASE_STEP]1132self.assert_params_for_cmd(cmd, result)11331134def test_install_mapr_with_args(self):1135cmd = (1136DEFAULT_CMD1137+ '--applications Name=mapr,Args=--edition,m5,--version,3.0.2'1138)1139result = copy.deepcopy(DEFAULT_RESULT)1140result['NewSupportedProducts'] = [INSTALL_MAPR_PRODUCT]1141self.assert_params_for_cmd(cmd, result)11421143def test_install_mapr_without_args(self):1144cmd = DEFAULT_CMD + '--applications Name=mapr'1145result = copy.deepcopy(DEFAULT_RESULT)1146result['NewSupportedProducts'] = [{'Name': 'mapr', 'Args': []}]1147self.assert_params_for_cmd(cmd, result)11481149def test_supported_products(self):1150cmd = DEFAULT_CMD + (1151'--applications '1152'Name=hue,Args=--hue-config,s3://elasticmapreduce/hue-config '1153'Name=mapr,Args=--edition,m7 '1154'Name=unknown,Args=[arg1,k1=v1]'1155)1156result = copy.deepcopy(DEFAULT_RESULT)1157result['NewSupportedProducts'] = INSTALL_SUPPORTED_PRODUCTS1158self.assert_params_for_cmd(cmd, result)11591160def test_applications_all_types(self):1161cmd = DEFAULT_CMD + (1162'--applications '1163'Name=hive Name=pig Name=ganglia Name=hbase Name=impala '1164'Name=mapr,Args=--edition,m5,--version,3.0.2'1165)1166ba_list = [INSTALL_GANGLIA_BA, INSTALL_HBASE_BA, INSTALL_IMPALA_BA]1167step_list = [INSTALL_HIVE_STEP, INSTALL_PIG_STEP, INSTALL_HBASE_STEP]1168result = copy.deepcopy(DEFAULT_RESULT)1169result['Steps'] = step_list1170result['BootstrapActions'] = ba_list1171result['NewSupportedProducts'] = [INSTALL_MAPR_PRODUCT]1172self.assert_params_for_cmd(cmd, result)11731174def test_applications_all_types_from_json_file(self):1175data_path = os.path.join(1176os.path.dirname(__file__), 'input_applications.json'1177)1178cmd = DEFAULT_CMD + '--applications file://' + data_path1179impala_ba = copy.deepcopy(INSTALL_IMPALA_BA)1180impala_ba['ScriptBootstrapAction']['Args'] += [1181'--impala-conf',1182'IMPALA_BACKEND_PORT=22001,IMPALA_MEM_LIMIT=70%',1183]1184ba_list = [INSTALL_GANGLIA_BA, INSTALL_HBASE_BA, impala_ba]1185step_list = [INSTALL_HIVE_STEP, INSTALL_PIG_STEP, INSTALL_HBASE_STEP]1186result = copy.deepcopy(DEFAULT_RESULT)1187result['Steps'] = step_list1188result['BootstrapActions'] = ba_list1189result['NewSupportedProducts'] = [INSTALL_MAPR_PRODUCT]1190self.assert_params_for_cmd(cmd, result)11911192# Steps test cases1193def test_wrong_step_type_error(self):1194cmd = DEFAULT_CMD + '--steps Type=unknown'1195expected_error_msg = (1196'\naws: error: The step type unknown is not supported.\n'1197)1198result = self.run_cmd(cmd, 255)1199self.assertEqual(expected_error_msg, result[1])12001201def test_default_step_type_name_action_on_failure(self):1202cmd = DEFAULT_CMD + '--steps Jar=s3://mybucket/mytest.jar'1203result = copy.deepcopy(DEFAULT_RESULT)1204result['Steps'] = [CUSTOM_JAR_STEP]1205self.assert_params_for_cmd(cmd, result)12061207def test_custom_jar_step_missing_jar(self):1208cmd = DEFAULT_CMD + '--steps Name=CustomJarMissingJar'1209expect_error_msg = (1210'\naws: error: The following '1211+ 'required parameters are missing for CustomJARStepConfig: Jar.\n'1212)1213result = self.run_cmd(cmd, 255)1214self.assertEqual(expect_error_msg, result[1])12151216def test_custom_jar_step_with_all_fields(self):1217cmd = (1218DEFAULT_CMD1219+ '--steps '1220+ (1221'Name=Custom,Type=Custom_JAR,'1222'Jar=s3://mybucket/mytest.jar,'1223'Args=arg1,arg2,MainClass=mymainclass,'1224'ActionOnFailure=TERMINATE_CLUSTER'1225)1226)1227expected_steps = [1228{1229'Name': 'Custom',1230'ActionOnFailure': 'TERMINATE_CLUSTER',1231'HadoopJarStep': {1232'Jar': 's3://mybucket/mytest.jar',1233'Args': ['arg1', 'arg2'],1234'MainClass': 'mymainclass',1235},1236}1237]1238result = copy.deepcopy(DEFAULT_RESULT)1239result['Steps'] = expected_steps1240self.assert_params_for_cmd(cmd, result)12411242def test_streaming_step_with_default_fields(self):1243cmd = DEFAULT_CMD + '--steps Type=Streaming,' + STREAMING_ARGS1244result = copy.deepcopy(DEFAULT_RESULT)1245result['Steps'] = [1246{1247'Name': 'Streaming program',1248'ActionOnFailure': 'CONTINUE',1249'HadoopJarStep': STREAMING_HADOOP_JAR_STEP,1250}1251]1252self.assert_params_for_cmd(cmd, result)12531254def test_streaming_step_missing_args(self):1255cmd = DEFAULT_CMD + '--steps Type=Streaming'1256expect_error_msg = (1257'\naws: error: The following '1258+ 'required parameters are missing for StreamingStepConfig: Args.\n'1259)1260result = self.run_cmd(cmd, 255)1261self.assertEqual(expect_error_msg, result[1])12621263def test_streaming_jar_with_all_fields(self):1264test_step_config = (1265'--steps Type=Streaming,Name=StreamingStepAllFields,'1266'ActionOnFailure=CANCEL_AND_WAIT,' + STREAMING_ARGS1267)1268cmd = DEFAULT_CMD + test_step_config1269result = copy.deepcopy(DEFAULT_RESULT)1270result['Steps'] = [1271{1272'Name': 'StreamingStepAllFields',1273'ActionOnFailure': 'CANCEL_AND_WAIT',1274'HadoopJarStep': STREAMING_HADOOP_JAR_STEP,1275}1276]1277self.assert_params_for_cmd(cmd, result)12781279def test_hive_step_with_default_fields(self):1280cmd = DEFAULT_CMD + (1281'--applications Name=Hive --steps Type=Hive,' + HIVE_BASIC_ARGS1282)1283result = copy.deepcopy(DEFAULT_RESULT)1284result['Steps'] = [INSTALL_HIVE_STEP, HIVE_DEFAULT_STEP]1285self.assert_params_for_cmd(cmd, result)12861287def test_hive_step_missing_args(self):1288cmd = DEFAULT_CMD + '--applications Name=Hive --steps Type=Hive'1289expect_error_msg = (1290'\naws: error: The following '1291+ 'required parameters are missing for HiveStepConfig: Args.\n'1292)1293result = self.run_cmd(cmd, 255)1294self.assertEqual(expect_error_msg, result[1])12951296def test_hive_step_with_all_fields(self):1297test_step_config = (1298'Type=Hive,ActionOnFailure=CANCEL_AND_WAIT,'1299'Name=HiveBasicStep,' + HIVE_BASIC_ARGS1300)1301cmd = DEFAULT_CMD + (1302'--applications Name=Hive --steps ' + test_step_config1303)1304result = copy.deepcopy(DEFAULT_RESULT)1305install_step = copy.deepcopy(INSTALL_HIVE_STEP)1306result['Steps'] = [install_step, HIVE_BASIC_STEP]1307self.assert_params_for_cmd(cmd, result)13081309def test_pig_step_with_default_fields(self):1310cmd = DEFAULT_CMD + (1311'--applications Name=Pig --steps Type=Pig,' + PIG_BASIC_ARGS1312)1313result = copy.deepcopy(DEFAULT_RESULT)1314result['Steps'] = [INSTALL_PIG_STEP, PIG_DEFAULT_STEP]1315self.assert_params_for_cmd(cmd, result)13161317def test_pig_missing_args(self):1318cmd = DEFAULT_CMD + '--applications Name=Pig --steps Type=Pig'1319expect_error_msg = (1320'\naws: error: The following '1321+ 'required parameters are missing for PigStepConfig: Args.\n'1322)1323result = self.run_cmd(cmd, 255)1324self.assertEqual(expect_error_msg, result[1])13251326def test_pig_step_with_all_fields(self):1327test_step_config = (1328'Name=PigBasicStep,Type=Pig,'1329+ PIG_BASIC_ARGS1330+ ',ActionOnFailure=CANCEL_AND_WAIT'1331)1332cmd = DEFAULT_CMD + (1333'--applications Name=Pig --steps ' + test_step_config1334)1335result = copy.deepcopy(DEFAULT_RESULT)1336install_step = copy.deepcopy(INSTALL_PIG_STEP)1337result['Steps'] = [install_step, PIG_BASIC_STEP]1338self.assert_params_for_cmd(cmd, result)13391340def test_impala_step_with_default_fields(self):1341cmd = DEFAULT_CMD + (1342'--applications Name=Impala --steps Type=Impala,'1343+ IMPALA_BASIC_ARGS1344)1345result = copy.deepcopy(DEFAULT_RESULT)1346result['BootstrapActions'] = [INSTALL_IMPALA_BA]1347result['Steps'] = [IMPALA_DEFAULT_STEP]1348self.assert_params_for_cmd(cmd, result)13491350def test_impala_missing_args(self):1351cmd = DEFAULT_CMD + '--applications Name=Impala --steps Type=Impala'1352expect_error_msg = (1353'\naws: error: The following '1354+ 'required parameters are missing for ImpalaStepConfig: Args.\n'1355)1356result = self.run_cmd(cmd, 255)1357self.assertEqual(expect_error_msg, result[1])13581359def test_impala_step_with_all_fields(self):1360test_step_config = (1361'Name=ImpalaBasicStep,Type=Impala,'1362+ IMPALA_BASIC_ARGS1363+ ',ActionOnFailure=CANCEL_AND_WAIT'1364)1365cmd = DEFAULT_CMD + (1366'--applications Name=Impala --steps ' + test_step_config1367)1368result = copy.deepcopy(DEFAULT_RESULT)1369result['BootstrapActions'] = [INSTALL_IMPALA_BA]1370step = copy.deepcopy(IMPALA_DEFAULT_STEP)1371step['Name'] = 'ImpalaBasicStep'1372step['ActionOnFailure'] = 'CANCEL_AND_WAIT'1373result['Steps'] = [step]1374self.assert_params_for_cmd(cmd, result)13751376def test_restore_from_hbase(self):1377cmd = DEFAULT_CMD + (1378'--applications Name=hbase --restore-from-hbase-backup '1379'Dir=s3://mybucket/test,BackupVersion=test_version'1380)1381result = copy.deepcopy(DEFAULT_RESULT)1382result['BootstrapActions'] = [INSTALL_HBASE_BA]1383result['Steps'] = [1384INSTALL_HBASE_STEP,1385{1386'Name': 'Restore HBase',1387'ActionOnFailure': 'CANCEL_AND_WAIT',1388'HadoopJarStep': {1389'Args': [1390'emr.hbase.backup.Main',1391'--restore',1392'--backup-dir',1393's3://mybucket/test',1394'--backup-version',1395'test_version',1396],1397'Jar': '/home/hadoop/lib/hbase.jar',1398},1399},1400]1401self.assert_params_for_cmd(cmd, result)1402data_path = os.path.join(1403os.path.dirname(__file__), 'input_hbase_restore_from_backup.json'1404)1405cmd = DEFAULT_CMD + (1406'--applications Name=hbase --restore-from-hbase-backup '1407'file://' + data_path1408)1409self.assert_params_for_cmd(cmd, result)14101411def test_empty_step_args(self):1412cmd = DEFAULT_CMD + '--steps Type=Streaming,Args= '1413expect_error_msg = (1414'\naws: error: The prameter Args cannot ' 'be an empty list.\n'1415)1416result = self.run_cmd(cmd, 255)1417self.assertEqual(expect_error_msg, result[1])14181419cmd = DEFAULT_CMD + '--steps Type=Pig,Args= '1420result = self.run_cmd(cmd, 255)1421self.assertEqual(expect_error_msg, result[1])14221423cmd = DEFAULT_CMD + '--steps Type=Hive,Args= '1424result = self.run_cmd(cmd, 255)1425self.assertEqual(expect_error_msg, result[1])14261427cmd = DEFAULT_CMD + '--steps Args= '1428expect_error_msg = (1429'\naws: error: The following required parameters '1430'are missing for CustomJARStepConfig: Jar.\n'1431)1432result = self.run_cmd(cmd, 255)1433self.assertEqual(expect_error_msg, result[1])14341435def test_missing_applications_for_steps(self):1436cmd = (1437DEFAULT_CMD1438+ '--steps Jar=s3://test/customJar.jar '1439+ 'Type=HIVE,Args=-f,s3://test/hive '1440+ 'Type=PIG,Args=-f,s3://test/pig '1441+ 'Type=IMPALA,Args=--impala-script,s3://test/impala '1442+ 'Type=Streaming,Args=-files,s3://test/mapper.py,-mapper,'1443+ 'mapper.py,-reducer,aggregator,-input,s3://test/input,-output,'1444+ 's3://test/output '1445+ 'Type=PIG,Args=-f,s3://test/pig2 '1446+ 'Type=IMPALA,Args=--impala-script,s3://test/impala2 '1447+ 'Type=PIG,Args=-f,s3://test/pig3 '1448+ ' Jar=s3://test/customJar2.jar '1449+ ' --applications Name=Hive'1450)14511452expected_error_msg1 = (1453'\naws: error: Some of the steps require the following'1454' applications to be installed: Impala, Pig. '1455'Please install the applications using --applications.\n'1456)1457expected_error_msg2 = (1458'\naws: error: Some of the steps require the following'1459' applications to be installed: Pig, Impala. '1460'Please install the applications using --applications.\n'1461)1462result = self.run_cmd(cmd, 255)14631464if (1465result[1] == expected_error_msg11466or result[1] == expected_error_msg21467):1468self.assertTrue(True)1469else:1470self.assertTrue(False)14711472def test_missing_applications_with_hbase(self):1473cmd = (1474DEFAULT_CMD1475+ '--steps Jar=s3://test/customJar.jar '1476+ 'Type=HIVE,Args=-f,s3://test/hive '1477+ 'Type=PIG,Args=-f,s3://test/pig '1478+ 'Type=IMPALA,Args=--impala-script,s3://test/impala '1479+ 'Type=Streaming,Args=-files,s3://test/mapper.py,-mapper,'1480+ 'mapper.py,-reducer,aggregator,-input,s3://test/input,-output,'1481+ 's3://test/output'1482+ ' --applications Name=Hive Name=Pig'1483+ ' --restore-from-hbase-backup Dir=s3://myBucket/myDir'1484)14851486expected_error_msg1 = (1487'\naws: error: Some of the steps require the following'1488' applications to be installed: Hbase, Impala. '1489'Please install the applications using --applications.\n'1490)1491expected_error_msg2 = (1492'\naws: error: Some of the steps require the following'1493' applications to be installed: Impala, Hbase. '1494'Please install the applications using --applications.\n'1495)1496result = self.run_cmd(cmd, 255)14971498if (1499result[1] == expected_error_msg11500or result[1] == expected_error_msg21501):1502self.assertTrue(True)1503else:1504self.assertTrue(False)15051506@mock.patch('awscli.customizations.emr.emrutils.call')1507def test_constructed_result(self, call_patch):1508call_patch.return_value = CREATE_CLUSTER_RESULT1509cmd = DEFAULT_CMD1510result = self.run_cmd(cmd, expected_rc=0)1511result_json = json.loads(result[0])1512self.assertEqual(result_json, CONSTRUCTED_RESULT)15131514def test_all_security_groups(self):1515cmd = DEFAULT_CMD + (1516'--ec2-attributes EmrManagedMasterSecurityGroup=sg-master1,'1517'EmrManagedSlaveSecurityGroup=sg-slave1,'1518'ServiceAccessSecurityGroup=sg-service-access,'1519'AdditionalMasterSecurityGroups='1520'[sg-addMaster1,sg-addMaster2,sg-addMaster3,'1521'sg-addMaster4],AdditionalSlaveSecurityGroups=[sg-addSlave1,'1522'sg-addSlave2,sg-addSlave3,sg-addSlave4]'1523)15241525result = copy.deepcopy(DEFAULT_RESULT)1526instances = result['Instances']1527instances['EmrManagedMasterSecurityGroup'] = (1528EMR_MANAGED_MASTER_SECURITY_GROUP1529)1530instances['EmrManagedSlaveSecurityGroup'] = (1531EMR_MANAGED_SLAVE_SECURITY_GROUP1532)1533instances['AdditionalMasterSecurityGroups'] = (1534ADDITIONAL_MASTER_SECURITY_GROUPS1535)1536instances['ServiceAccessSecurityGroup'] = SERVICE_ACCESS_SECURITY_GROUP1537instances['AdditionalSlaveSecurityGroups'] = (1538ADDITIONAL_SLAVE_SECURITY_GROUPS1539)15401541self.assert_params_for_cmd(cmd, result)15421543def test_emr_managed_security_groups(self):1544cmd = DEFAULT_CMD + (1545'--ec2-attributes EmrManagedMasterSecurityGroup=sg-master1,'1546'EmrManagedSlaveSecurityGroup=sg-slave1,'1547'ServiceAccessSecurityGroup=sg-service-access'1548)15491550result = copy.deepcopy(DEFAULT_RESULT)1551instances = result['Instances']1552instances['EmrManagedMasterSecurityGroup'] = (1553EMR_MANAGED_MASTER_SECURITY_GROUP1554)1555instances['EmrManagedSlaveSecurityGroup'] = (1556EMR_MANAGED_SLAVE_SECURITY_GROUP1557)1558instances['ServiceAccessSecurityGroup'] = SERVICE_ACCESS_SECURITY_GROUP15591560self.assert_params_for_cmd(cmd, result)15611562def test_additional_security_groups(self):1563cmd = DEFAULT_CMD + (1564'--ec2-attributes AdditionalMasterSecurityGroups=[sg-addMaster1'1565',sg-addMaster2,sg-addMaster3,sg-addMaster4],AdditionalSlaveSecu'1566'rityGroups=[sg-addSlave1,sg-addSlave2,sg-addSlave3,sg-addSlave4]'1567)15681569result = copy.deepcopy(DEFAULT_RESULT)1570instances = result['Instances']1571instances['AdditionalMasterSecurityGroups'] = (1572ADDITIONAL_MASTER_SECURITY_GROUPS1573)1574instances['AdditionalSlaveSecurityGroups'] = (1575ADDITIONAL_SLAVE_SECURITY_GROUPS1576)15771578self.assert_params_for_cmd(cmd, result)15791580def test_security_groups_from_json_file(self):1581data_path = os.path.join(1582os.path.dirname(__file__),1583'input_ec2_attributes_with_security_groups.json',1584)1585cmd = DEFAULT_CMD + '--ec2-attributes file://' + data_path15861587result = copy.deepcopy(DEFAULT_RESULT)1588instances = result['Instances']1589instances['EmrManagedMasterSecurityGroup'] = (1590EMR_MANAGED_MASTER_SECURITY_GROUP1591)1592instances['EmrManagedSlaveSecurityGroup'] = (1593EMR_MANAGED_SLAVE_SECURITY_GROUP1594)1595instances['ServiceAccessSecurityGroup'] = SERVICE_ACCESS_SECURITY_GROUP1596instances['AdditionalMasterSecurityGroups'] = (1597ADDITIONAL_MASTER_SECURITY_GROUPS1598)1599instances['AdditionalSlaveSecurityGroups'] = (1600ADDITIONAL_SLAVE_SECURITY_GROUPS1601)16021603self.assert_params_for_cmd(cmd, result)16041605def test_instance_group_with_autoscaling_policy(self):1606cmd = (1607self.prefix1608+ '--ami-version 3.1.0 --auto-scaling-role EMR_AUTOSCALING_ROLE --instance-groups '1609+ CONSTANTS.INSTANCE_GROUPS_WITH_AUTOSCALING_POLICY_ARG1610)1611result = {1612'Name': DEFAULT_CLUSTER_NAME,1613'Instances': {1614'KeepJobFlowAliveWhenNoSteps': True,1615'TerminationProtected': False,1616'InstanceGroups': CONSTANTS.INSTANCE_GROUPS_WITH_AUTOSCALING_POLICY,1617},1618'AmiVersion': '3.1.0',1619'AutoScalingRole': 'EMR_AUTOSCALING_ROLE',1620'VisibleToAllUsers': True,1621'Tags': [],1622}1623self.assert_params_for_cmd(cmd, result)16241625def test_instance_group_with_autoscaling_policy_missing_autoscaling_role(1626self,1627):1628cmd = (1629self.prefix1630+ '--ami-version 3.1.0 --instance-groups '1631+ CONSTANTS.INSTANCE_GROUPS_WITH_AUTOSCALING_POLICY_ARG1632)1633expected_error_msg = (1634'\naws: error: Must specify --auto-scaling-role when'1635' configuring an AutoScaling policy for an instance group.\n'1636)1637result = self.run_cmd(cmd, 255)1638self.assertEqual(expected_error_msg, result[1])16391640def test_scale_down_behavior(self):1641cmd = (1642self.prefix1643+ '--ami-version 3.1.0 --scale-down-behavior TERMINATE_AT_TASK_COMPLETION '1644'--instance-groups ' + DEFAULT_INSTANCE_GROUPS_ARG1645)1646result = {1647'Name': DEFAULT_CLUSTER_NAME,1648'Instances': DEFAULT_INSTANCES,1649'AmiVersion': '3.1.0',1650'VisibleToAllUsers': True,1651'ScaleDownBehavior': 'TERMINATE_AT_TASK_COMPLETION',1652'Tags': [],1653}1654self.assert_params_for_cmd(cmd, result)16551656def test_instance_group_with_ebs_config(self):1657cmd = (1658self.prefix1659+ '--ami-version 3.1.0 --instance-groups '1660+ CONSTANTS.INSTANCE_GROUPS_WITH_EBS_VOLUME_ARG1661)1662result = {1663'Name': DEFAULT_CLUSTER_NAME,1664'Instances': {1665'KeepJobFlowAliveWhenNoSteps': True,1666'TerminationProtected': False,1667'InstanceGroups': CONSTANTS.INSTANCE_GROUPS_WITH_EBS,1668},1669'AmiVersion': '3.1.0',1670'VisibleToAllUsers': True,1671'Tags': [],1672}1673self.assert_params_for_cmd(cmd, result)16741675def test_instance_groups_with_ebs_config_missing_volume_type(self):1676cmd = (1677self.prefix1678+ '--ami-version 3.1.0 --instance-groups '1679+ CONSTANTS.INSTANCE_GROUPS_WITH_EBS_VOLUME_MISSING_VOLTYPE_ARG1680)1681stderr = self.run_cmd(cmd, 255)[1]1682self.assert_error_message_has_field_name(stderr, 'VolumeType')16831684def test_instance_groups_with_ebs_config_missing_size(self):1685cmd = (1686self.prefix1687+ '--ami-version 3.1.0 --instance-groups '1688+ CONSTANTS.INSTANCE_GROUPS_WITH_EBS_VOLUME_MISSING_SIZE_ARG1689)1690stderr = self.run_cmd(cmd, 255)[1]1691self.assert_error_message_has_field_name(stderr, 'SizeInGB')16921693def test_instance_groups_with_ebs_config_missing_volume_spec(self):1694cmd = (1695self.prefix1696+ '--ami-version 3.1.0 --instance-groups '1697+ CONSTANTS.INSTANCE_GROUPS_WITH_EBS_VOLUME_MISSING_VOLSPEC_ARG1698)1699result = {1700'Name': DEFAULT_CLUSTER_NAME,1701'Instances': {1702'KeepJobFlowAliveWhenNoSteps': True,1703'TerminationProtected': False,1704'InstanceGroups': CONSTANTS.INSTANCE_GROUPS_WITH_EBS_VOLUME_MISSING_VOLSPEC,1705},1706'AmiVersion': '3.1.0',1707'VisibleToAllUsers': True,1708'Tags': [],1709}1710self.assert_params_for_cmd(cmd, result)17111712def test_instance_groups_with_ebs_config_missing_iops(self):1713cmd = (1714self.prefix1715+ '--ami-version 3.1.0 --instance-groups '1716+ CONSTANTS.INSTANCE_GROUPS_WITH_EBS_VOLUME_MISSING_IOPS_ARG1717)1718result = {1719'Name': DEFAULT_CLUSTER_NAME,1720'Instances': {1721'KeepJobFlowAliveWhenNoSteps': True,1722'TerminationProtected': False,1723'InstanceGroups': CONSTANTS.INSTANCE_GROUPS_WITH_EBS_VOLUME_MISSING_IOPS,1724},1725'AmiVersion': '3.1.0',1726'VisibleToAllUsers': True,1727'Tags': [],1728}1729self.assert_params_for_cmd(cmd, result)17301731def test_instance_groups_with_ebs_config_multiple_instance_groups(self):1732cmd = (1733self.prefix1734+ '--ami-version 3.1.0 --instance-groups '1735+ CONSTANTS.MULTIPLE_INSTANCE_GROUPS_WITH_EBS_VOLUMES_VOLUME_ARG1736)1737result = {1738'Name': DEFAULT_CLUSTER_NAME,1739'Instances': {1740'KeepJobFlowAliveWhenNoSteps': True,1741'TerminationProtected': False,1742'InstanceGroups': CONSTANTS.MULTIPLE_INSTANCE_GROUPS_WITH_EBS_VOLUMES,1743},1744'AmiVersion': '3.1.0',1745'VisibleToAllUsers': True,1746'Tags': [],1747}1748self.assert_params_for_cmd(cmd, result)17491750def test_instance_group_with_ebs_config_from_json(self):1751data_path = os.path.join(1752os.path.dirname(__file__), 'input_instance_groups_ebs_config.json'1753)1754cmd = (1755'emr create-cluster --use-default-roles --ami-version 3.0.4 '1756'--instance-groups file://' + data_path1757)1758result = copy.deepcopy(DEFAULT_RESULT)1759result['Instances']['InstanceGroups'] = [1760{1761'InstanceRole': 'MASTER',1762'InstanceCount': 1,1763'Name': 'Master Instance Group',1764'Market': 'ON_DEMAND',1765'InstanceType': 'd2.xlarge',1766'EbsConfiguration': {1767'EbsBlockDeviceConfigs': [1768{1769'VolumeSpecification': {1770'VolumeType': 'standard',1771'SizeInGB': 10,1772},1773'VolumesPerInstance': 4,1774}1775],1776'EbsOptimized': True,1777},1778},1779{1780'InstanceRole': 'CORE',1781'InstanceCount': 2,1782'Name': 'Core Instance Group',1783'Market': 'ON_DEMAND',1784'InstanceType': 'd2.xlarge',1785},1786{1787'InstanceRole': 'TASK',1788'InstanceCount': 3,1789'Name': 'Task Instance Group',1790'Market': 'SPOT',1791'BidPrice': '3.45',1792'InstanceType': 'd2.xlarge',1793},1794]1795self.assert_params_for_cmd(cmd, result)17961797def test_instance_fleets_with_on_demand_master_only(self):1798cmd = (1799self.prefix1800+ '--ami-version 3.1.0 --instance-fleets '1801+ CONSTANTS_FLEET.INSTANCE_FLEETS_WITH_ON_DEMAND_MASTER_ONLY1802)1803result = {1804'Name': DEFAULT_CLUSTER_NAME,1805'Instances': {1806'KeepJobFlowAliveWhenNoSteps': True,1807'TerminationProtected': False,1808'InstanceFleets': CONSTANTS_FLEET.RES_INSTANCE_FLEETS_WITH_ON_DEMAND_MASTER_ONLY,1809},1810'AmiVersion': '3.1.0',1811'VisibleToAllUsers': True,1812'Tags': [],1813}1814self.assert_params_for_cmd(cmd, result)18151816def test_instance_fleets_with_on_demand_master_only_with_targeted_odcr(1817self,1818):1819cmd = (1820self.prefix1821+ '--ami-version 3.1.0 --instance-fleets '1822+ CONSTANTS_FLEET.INSTANCE_FLEETS_WITH_ON_DEMAND_MASTER_ONLY_WITH_TARGETED_ODCR1823)1824result = {1825'Name': DEFAULT_CLUSTER_NAME,1826'Instances': {1827'KeepJobFlowAliveWhenNoSteps': True,1828'TerminationProtected': False,1829'InstanceFleets': CONSTANTS_FLEET.RES_INSTANCE_FLEETS_WITH_ON_DEMAND_MASTER_ONLY_WITH_TARGETED_ODCR,1830},1831'AmiVersion': '3.1.0',1832'VisibleToAllUsers': True,1833'Tags': [],1834}1835self.assert_params_for_cmd(cmd, result)18361837def test_instance_fleets_with_spot_master_only(self):1838cmd = (1839self.prefix1840+ '--ami-version 3.1.0 --instance-fleets '1841+ CONSTANTS_FLEET.INSTANCE_FLEETS_WITH_SPOT_MASTER_ONLY1842)1843result = {1844'Name': DEFAULT_CLUSTER_NAME,1845'Instances': {1846'KeepJobFlowAliveWhenNoSteps': True,1847'TerminationProtected': False,1848'InstanceFleets': CONSTANTS_FLEET.RES_INSTANCE_FLEETS_WITH_SPOT_MASTER_ONLY,1849},1850'AmiVersion': '3.1.0',1851'VisibleToAllUsers': True,1852'Tags': [],1853}1854self.assert_params_for_cmd(cmd, result)18551856def test_instance_fleets_with_spot_master_only_with_ebs_conf(self):1857cmd = (1858self.prefix1859+ '--ami-version 3.1.0 --instance-fleets '1860+ CONSTANTS_FLEET.INSTANCE_FLEETS_WITH_SPOT_MASTER_ONLY_WITH_EBS_CONF1861)1862result = {1863'Name': DEFAULT_CLUSTER_NAME,1864'Instances': {1865'KeepJobFlowAliveWhenNoSteps': True,1866'TerminationProtected': False,1867'InstanceFleets': CONSTANTS_FLEET.RES_INSTANCE_FLEETS_WITH_SPOT_MASTER_ONLY_WITH_EBS_CONF,1868},1869'AmiVersion': '3.1.0',1870'VisibleToAllUsers': True,1871'Tags': [],1872}1873self.assert_params_for_cmd(cmd, result)18741875def test_instance_fleets_with_spot_master_specific_azs(self):1876cmd = (1877self.prefix1878+ '--ami-version 3.1.0 --instance-fleets '1879+ CONSTANTS_FLEET.INSTANCE_FLEETS_WITH_SPOT_MASTER_ONLY1880+ ' --ec2-attributes AvailabilityZones=[us-east-1a,us-east-1b]'1881)1882result = {1883'Name': DEFAULT_CLUSTER_NAME,1884'Instances': {1885'KeepJobFlowAliveWhenNoSteps': True,1886'TerminationProtected': False,1887'InstanceFleets': CONSTANTS_FLEET.RES_INSTANCE_FLEETS_WITH_SPOT_MASTER_ONLY,1888'Placement': {1889'AvailabilityZones': ['us-east-1a', 'us-east-1b']1890},1891},1892'AmiVersion': '3.1.0',1893'VisibleToAllUsers': True,1894'Tags': [],1895}1896self.assert_params_for_cmd(cmd, result)18971898def test_instance_fleets_with_spot_master_subnet_ids(self):1899cmd = (1900self.prefix1901+ '--ami-version 3.1.0 --instance-fleets '1902+ CONSTANTS_FLEET.INSTANCE_FLEETS_WITH_SPOT_MASTER_ONLY1903+ ' --ec2-attributes SubnetIds=[subnetid-1,subnetid-2]'1904)1905result = {1906'Name': DEFAULT_CLUSTER_NAME,1907'Instances': {1908'KeepJobFlowAliveWhenNoSteps': True,1909'TerminationProtected': False,1910'InstanceFleets': CONSTANTS_FLEET.RES_INSTANCE_FLEETS_WITH_SPOT_MASTER_ONLY,1911'Ec2SubnetIds': ['subnetid-1', 'subnetid-2'],1912},1913'AmiVersion': '3.1.0',1914'VisibleToAllUsers': True,1915'Tags': [],1916}1917self.assert_params_for_cmd(cmd, result)19181919def test_instance_fleets_with_spot_master_core_cluster_multiple_instance_types(1920self,1921):1922cmd = (1923self.prefix1924+ '--ami-version 3.1.0 --instance-fleets '1925+ CONSTANTS_FLEET.INSTANCE_FLEETS_WITH_SPOT_MASTER_CORE_CLUSTER1926)1927result = {1928'Name': DEFAULT_CLUSTER_NAME,1929'Instances': {1930'KeepJobFlowAliveWhenNoSteps': True,1931'TerminationProtected': False,1932'InstanceFleets': CONSTANTS_FLEET.RES_INSTANCE_FLEETS_WITH_SPOT_MASTER_CORE_CLUSTER,1933},1934'AmiVersion': '3.1.0',1935'VisibleToAllUsers': True,1936'Tags': [],1937}1938self.assert_params_for_cmd(cmd, result)19391940def test_instance_fleets_with_spot_master_core_cluster_multiple_custom_amis(1941self,1942):1943cmd = (1944self.prefix1945+ '--ami-version 3.1.0 --instance-fleets '1946+ CONSTANTS_FLEET.INSTANCE_FLEETS_WITH_SPOT_MASTER_CORE_CLUSTER_WITH_CUSTOM_AMI1947)1948result = {1949'Name': DEFAULT_CLUSTER_NAME,1950'Instances': {1951'KeepJobFlowAliveWhenNoSteps': True,1952'TerminationProtected': False,1953'InstanceFleets': CONSTANTS_FLEET.RES_INSTANCE_FLEETS_WITH_SPOT_MASTER_CORE_CLUSTER_WITH_CUSTOM_AMI,1954},1955'AmiVersion': '3.1.0',1956'VisibleToAllUsers': True,1957'Tags': [],1958}1959self.assert_params_for_cmd(cmd, result)19601961def test_instance_fleets_with_complex_config_from_json(self):1962data_path = os.path.join(1963os.path.dirname(__file__), 'input_instance_fleets.json'1964)1965cmd = (1966'emr create-cluster --use-default-roles --ami-version 3.1.0 '1967'--instance-fleets file://' + data_path1968)1969result = {1970'Name': DEFAULT_CLUSTER_NAME,1971'Instances': {1972'KeepJobFlowAliveWhenNoSteps': True,1973'TerminationProtected': False,1974'InstanceFleets': CONSTANTS_FLEET.RES_INSTANCE_FLEETS_WITH_COMPLEX_CONFIG_FROM_JSON,1975},1976'AmiVersion': '3.1.0',1977'VisibleToAllUsers': True,1978'Tags': [],1979'JobFlowRole': 'EMR_EC2_DefaultRole',1980'ServiceRole': 'EMR_DefaultRole',1981}1982self.assert_params_for_cmd(cmd, result)19831984def test_instance_fleets_with_both_az_azs_specified(self):1985cmd = (1986self.prefix1987+ '--ami-version 3.1.0 --instance-fleets '1988+ CONSTANTS_FLEET.INSTANCE_FLEETS_WITH_SPOT_MASTER_ONLY1989+ ' --ec2-attributes AvailabilityZone=us-east-1a,AvailabilityZones=[us-east-1a,us-east-1b]'1990)1991expected_error_msg = (1992'\naws: error: You cannot specify both AvailabilityZone'1993' and AvailabilityZones options together.\n'1994)1995result = self.run_cmd(cmd, 255)1996self.assertEqual(expected_error_msg, result[1])199719981999if __name__ == "__main__":2000unittest.main()200120022003