File: //lib/python3/dist-packages/awscli/customizations/ec2/runinstances.py
# Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
"""
This customization adds two new parameters to the ``ec2 run-instance``
command. The first, ``--secondary-private-ip-addresses`` allows a list
of IP addresses within the specified subnet to be associated with the
new instance. The second, ``--secondary-ip-address-count`` allows you
to specify how many additional IP addresses you want but the actual
address will be assigned for you.
This functionality (and much more) is also available using the
``--network-interfaces`` complex argument. This just makes two of
the most commonly used features available more easily.
"""
from awscli.arguments import CustomArgument
# --secondary-private-ip-address
SECONDARY_PRIVATE_IP_ADDRESSES_DOCS = (
'[EC2-VPC] A secondary private IP address for the network interface '
'or instance. You can specify this multiple times to assign multiple '
'secondary IP addresses. If you want additional private IP addresses '
'but do not need a specific address, use the '
'--secondary-private-ip-address-count option.')
# --secondary-private-ip-address-count
SECONDARY_PRIVATE_IP_ADDRESS_COUNT_DOCS = (
'[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, **kwargs):
arg = SecondaryPrivateIpAddressesArgument(
name='secondary-private-ip-addresses',
help_text=SECONDARY_PRIVATE_IP_ADDRESSES_DOCS)
argument_table['secondary-private-ip-addresses'] = arg
arg = SecondaryPrivateIpAddressCountArgument(
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):
# This function checks the parsed args. If the user specified
# the --network-interfaces option with any of the scalar options we
# raise an error.
arg_dict = vars(parsed_args)
if arg_dict['network_interfaces']:
for key in ('secondary_private_ip_addresses',
'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 '
'not supported.')
raise ValueError(msg)
def _fix_args(params, **kwargs):
# The RunInstances request provides some parameters
# such as --subnet-id and --security-group-id that can be specified
# as separate options only if the request DOES NOT include a
# NetworkInterfaces structure. In those cases, the values for
# these parameters must be specified inside the NetworkInterfaces
# structure. This function checks for those parameters
# and fixes them if necessary.
# NOTE: If the user is a default VPC customer, RunInstances
# allows them to specify the security group by name or by id.
# However, in this scenario we can only support id because
# we can't place a group name in the NetworkInterfaces structure.
network_interface_params = [
'PrivateIpAddresses',
'SecondaryPrivateIpAddressCount',
'AssociatePublicIpAddress'
]
if 'NetworkInterfaces' in params:
interface = params['NetworkInterfaces'][0]
if any(param in interface for param in network_interface_params):
if 'SubnetId' in params:
interface['SubnetId'] = params['SubnetId']
del params['SubnetId']
if 'SecurityGroupIds' in params:
interface['Groups'] = params['SecurityGroupIds']
del params['SecurityGroupIds']
if 'PrivateIpAddress' in params:
ip_addr = {'PrivateIpAddress': params['PrivateIpAddress'],
'Primary': True}
interface['PrivateIpAddresses'] = [ip_addr]
del params['PrivateIpAddress']
if 'Ipv6AddressCount' in params:
interface['Ipv6AddressCount'] = params['Ipv6AddressCount']
del params['Ipv6AddressCount']
if 'Ipv6Addresses' in params:
interface['Ipv6Addresses'] = params['Ipv6Addresses']
del params['Ipv6Addresses']
EVENTS = [
('building-argument-table.ec2.run-instances', _add_params),
('operation-args-parsed.ec2.run-instances', _check_args),
('before-parameter-build.ec2.RunInstances', _fix_args),
]
def register_runinstances(event_handler):
# Register all of the events for customizing BundleInstance
for event, handler in EVENTS:
event_handler.register(event, handler)
def _build_network_interfaces(params, key, value):
# Build up the NetworkInterfaces data structure
if 'NetworkInterfaces' not in params:
params['NetworkInterfaces'] = [{'DeviceIndex': 0}]
if key == 'PrivateIpAddresses':
if 'PrivateIpAddresses' not in params['NetworkInterfaces'][0]:
params['NetworkInterfaces'][0]['PrivateIpAddresses'] = value
else:
params['NetworkInterfaces'][0][key] = value
class SecondaryPrivateIpAddressesArgument(CustomArgument):
def add_to_parser(self, parser, cli_name=None):
parser.add_argument(self.cli_name, dest=self.py_name,
default=self._default, nargs='*')
def add_to_params(self, parameters, value):
if value:
value = [{'PrivateIpAddress': v, 'Primary': False} for v in value]
_build_network_interfaces(
parameters, 'PrivateIpAddresses', value)
class SecondaryPrivateIpAddressCountArgument(CustomArgument):
def add_to_parser(self, parser, cli_name=None):
parser.add_argument(self.cli_name, dest=self.py_name,
default=self._default, type=int)
def add_to_params(self, parameters, value):
if 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)