Repository: aws/aws-cli

Issue:
Option to associate public ip address in ec2 run-instance
There doesn't seem to be any way to associate a public ip address without also adding a network interface with the --network-interfaces parameter. Is it possible for this to be a top level parameter?



Discussion:
Yes, I agree that would be useful.


Resolving patch:
diff --git a/awscli/customizations/ec2runinstances.py b/awscli/customizations/ec2runinstances.py
--- a/awscli/customizations/ec2runinstances.py
+++ b/awscli/customizations/ec2runinstances.py
@@ -38,6 +38,12 @@
     '[EC2-VPC] The number of secondary IP addresses to assign to '
     'the network interface or instance.')
 
+# --associate-public-ip-address
+ASSOCIATE_PUBLIC_IP_ADDRESS_DOCS = (
+    '[EC2-VPC] If specified a public IP address will be assigned '
+    'to the new instance in a VPC.')
+
+
 
 def _add_params(argument_table, operation, **kwargs):
     arg = SecondaryPrivateIpAddressesArgument(
@@ -48,6 +54,16 @@ def _add_params(argument_table, operation, **kwargs):
         name='secondary-private-ip-address-count',
         help_text=SECONDARY_PRIVATE_IP_ADDRESS_COUNT_DOCS)
     argument_table['secondary-private-ip-address-count'] = arg
+    arg = AssociatePublicIpAddressArgument(
+        name='associate-public-ip-address',
+        help_text=ASSOCIATE_PUBLIC_IP_ADDRESS_DOCS,
+        action='store_true', group_name='associate_public_ip')
+    argument_table['associate-public-ip-address'] = arg
+    arg = NoAssociatePublicIpAddressArgument(
+        name='no-associate-public-ip-address',
+        help_text=ASSOCIATE_PUBLIC_IP_ADDRESS_DOCS,
+        action='store_false', group_name='associate_public_ip')
+    argument_table['no-associate-public-ip-address'] = arg
 
 
 def _check_args(parsed_args, **kwargs):
@@ -57,7 +73,8 @@ def _check_args(parsed_args, **kwargs):
     arg_dict = vars(parsed_args)
     if arg_dict['network_interfaces']:
         for key in ('secondary_private_ip_addresses',
-                    'secondary_private_ip_address_count'):
+                    'secondary_private_ip_address_count',
+                    'associate_public_ip_address'):
             if arg_dict[key]:
                 msg = ('Mixing the --network-interfaces option '
                        'with the simple, scalar options is '
@@ -114,3 +131,21 @@ def add_to_params(self, parameters, value):
             _build_network_interfaces(parameters,
                                       'SecondaryPrivateIpAddressCount',
                                       value)
+
+
+class AssociatePublicIpAddressArgument(CustomArgument):
+
+    def add_to_params(self, parameters, value):
+        if value is True:
+            _build_network_interfaces(parameters,
+                                      'AssociatePublicIpAddress',
+                                      value)
+
+
+class NoAssociatePublicIpAddressArgument(CustomArgument):
+
+    def add_to_params(self, parameters, value):
+        if value is False:
+            _build_network_interfaces(parameters,
+                                      'AssociatePublicIpAddress',
+                                      value)


Test patch:
diff --git a/tests/unit/ec2/test_run_instances.py b/tests/unit/ec2/test_run_instances.py
--- a/tests/unit/ec2/test_run_instances.py
+++ b/tests/unit/ec2/test_run_instances.py
@@ -110,3 +110,29 @@ def test_secondary_ip_address_count(self):
         }
         self.assert_params_for_cmd(args_list, result)
 
+    def test_associate_public_ip_address(self):
+        args = ' --image-id ami-foobar --count 1 '
+        args += '--associate-public-ip-address'
+        args_list = (self.prefix + args).split()
+        result = {
+            'NetworkInterface.1.DeviceIndex': '0',
+            'NetworkInterface.1.AssociatePublicIpAddress': 'true',
+            'ImageId': 'ami-foobar',
+            'MaxCount': '1',
+            'MinCount': '1'
+        }
+        self.assert_params_for_cmd(args_list, result)
+
+    def test_no_associate_public_ip_address(self):
+        args = ' --image-id ami-foobar --count 1 '
+        args += '--no-associate-public-ip-address'
+        args_list = (self.prefix + args).split()
+        result = {
+            'NetworkInterface.1.DeviceIndex': '0',
+            'NetworkInterface.1.AssociatePublicIpAddress': 'false',
+            'ImageId': 'ami-foobar',
+            'MaxCount': '1',
+            'MinCount': '1'
+        }
+        self.assert_params_for_cmd(args_list, result)
+