Esempio n. 1
0
 def format_network_configuration(self, network_config):
     result = dict()
     if network_config['subnets'] is not None:
         result['subnets'] = network_config['subnets']
     else:
         self.module.fail_json(
             msg="Network configuration must include subnets")
     if network_config['security_groups'] is not None:
         groups = network_config['security_groups']
         if any(not sg.startswith('sg-') for sg in groups):
             try:
                 vpc_id = self.ec2.describe_subnets(
                     SubnetIds=[result['subnets'][0]
                                ])['Subnets'][0]['VpcId']
                 groups = get_ec2_security_group_ids_from_names(
                     groups, self.ec2, vpc_id)
             except (botocore.exceptions.ClientError,
                     botocore.exceptions.BotoCoreError) as e:
                 self.module.fail_json_aws(
                     e, msg="Couldn't look up security groups")
         result['securityGroups'] = groups
     if network_config['assign_public_ip'] is not None:
         if self.module.botocore_at_least('1.8.4'):
             if network_config['assign_public_ip'] is True:
                 result['assignPublicIp'] = "ENABLED"
             else:
                 result['assignPublicIp'] = "DISABLED"
         else:
             self.module.fail_json(
                 msg=
                 'botocore needs to be version 1.8.4 or higher to use assign_public_ip in network_configuration'
             )
     return dict(awsvpcConfiguration=result)
Esempio n. 2
0
def create_eni(connection, vpc_id, module):

    instance_id = module.params.get("instance_id")
    attached = module.params.get("attached")
    if instance_id == 'None':
        instance_id = None
    device_index = module.params.get("device_index")
    subnet_id = module.params.get('subnet_id')
    private_ip_address = module.params.get('private_ip_address')
    description = module.params.get('description')
    security_groups = get_ec2_security_group_ids_from_names(
        module.params.get('security_groups'),
        connection,
        vpc_id=vpc_id,
        boto3=False)
    secondary_private_ip_addresses = module.params.get(
        "secondary_private_ip_addresses")
    secondary_private_ip_address_count = module.params.get(
        "secondary_private_ip_address_count")
    changed = False

    try:
        eni = connection.create_network_interface(subnet_id,
                                                  private_ip_address,
                                                  description, security_groups)
        if attached and instance_id is not None:
            try:
                eni.attach(instance_id, device_index)
            except BotoServerError:
                eni.delete()
                raise
            # Wait to allow creation / attachment to finish
            wait_for_eni(eni, "attached")
            eni.update()

        if secondary_private_ip_address_count is not None:
            try:
                connection.assign_private_ip_addresses(
                    network_interface_id=eni.id,
                    secondary_private_ip_address_count=
                    secondary_private_ip_address_count)
            except BotoServerError:
                eni.delete()
                raise

        if secondary_private_ip_addresses is not None:
            try:
                connection.assign_private_ip_addresses(
                    network_interface_id=eni.id,
                    private_ip_addresses=secondary_private_ip_addresses)
            except BotoServerError:
                eni.delete()
                raise

        changed = True

    except BotoServerError as e:
        module.fail_json_aws(e)

    module.exit_json(changed=changed, interface=get_eni_info(eni))
Esempio n. 3
0
def ensure_present(client, module):
    name = module.params.get('name')
    subnets = module.params['subnets']
    groups = module.params['security_groups']
    wait = module.params.get('wait')
    cluster = get_cluster(client, module)
    try:
        ec2 = module.client('ec2')
        vpc_id = ec2.describe_subnets(
            SubnetIds=[subnets[0]])['Subnets'][0]['VpcId']
        groups = get_ec2_security_group_ids_from_names(groups, ec2, vpc_id)
    except (botocore.exceptions.BotoCoreError,
            botocore.exceptions.ClientError) as e:
        module.fail_json_aws(e, msg="Couldn't lookup security groups")

    if cluster:
        if set(cluster['resourcesVpcConfig']['subnetIds']) != set(subnets):
            module.fail_json(msg="Cannot modify subnets of existing cluster")
        if set(cluster['resourcesVpcConfig']['securityGroupIds']) != set(
                groups):
            module.fail_json(
                msg="Cannot modify security groups of existing cluster")
        if module.params.get('version') and module.params.get(
                'version') != cluster['version']:
            module.fail_json(msg="Cannot modify version of existing cluster")

        if wait:
            wait_until(client, module, 'cluster_active')
            # Ensure that fields that are only available for active clusters are
            # included in the returned value
            cluster = get_cluster(client, module)

        module.exit_json(changed=False, **camel_dict_to_snake_dict(cluster))

    if module.check_mode:
        module.exit_json(changed=True)
    try:
        params = dict(name=name,
                      roleArn=module.params['role_arn'],
                      resourcesVpcConfig=dict(subnetIds=subnets,
                                              securityGroupIds=groups),
                      clientRequestToken='ansible-create-%s' % name)
        if module.params['version']:
            params['version'] = module.params['version']
        cluster = client.create_cluster(**params)['cluster']
    except botocore.exceptions.EndpointConnectionError as e:
        module.fail_json(msg="Region %s is not supported by EKS" %
                         client.meta.region_name)
    except (botocore.exceptions.BotoCoreError,
            botocore.exceptions.ClientError) as e:
        module.fail_json_aws(e, msg="Couldn't create cluster %s" % name)

    if wait:
        wait_until(client, module, 'cluster_active')
        # Ensure that fields that are only available for active clusters are
        # included in the returned value
        cluster = get_cluster(client, module)

    module.exit_json(changed=True, **camel_dict_to_snake_dict(cluster))
def create_or_update_glue_connection(connection, connection_ec2, module, glue_connection):
    """
    Create or update an AWS Glue connection

    :param connection: AWS boto3 glue connection
    :param module: Ansible module
    :param glue_connection: a dict of AWS Glue connection parameters or None
    :return:
    """
    changed = False

    params = dict()
    params['ConnectionInput'] = dict()
    params['ConnectionInput']['Name'] = module.params.get("name")
    params['ConnectionInput']['ConnectionType'] = module.params.get("connection_type")
    params['ConnectionInput']['ConnectionProperties'] = module.params.get("connection_properties")
    if module.params.get("catalog_id") is not None:
        params['CatalogId'] = module.params.get("catalog_id")
    if module.params.get("description") is not None:
        params['ConnectionInput']['Description'] = module.params.get("description")
    if module.params.get("match_criteria") is not None:
        params['ConnectionInput']['MatchCriteria'] = module.params.get("match_criteria")
    if module.params.get("security_groups") is not None or module.params.get("subnet_id") is not None:
        params['ConnectionInput']['PhysicalConnectionRequirements'] = dict()
    if module.params.get("security_groups") is not None:
        # Get security group IDs from names
        security_group_ids = get_ec2_security_group_ids_from_names(module.params.get('security_groups'), connection_ec2, boto3=True)
        params['ConnectionInput']['PhysicalConnectionRequirements']['SecurityGroupIdList'] = security_group_ids
    if module.params.get("subnet_id") is not None:
        params['ConnectionInput']['PhysicalConnectionRequirements']['SubnetId'] = module.params.get("subnet_id")
    if module.params.get("availability_zone") is not None:
        params['ConnectionInput']['PhysicalConnectionRequirements']['AvailabilityZone'] = module.params.get("availability_zone")

    # If glue_connection is not None then check if it needs to be modified, else create it
    if glue_connection:
        if _compare_glue_connection_params(params, glue_connection):
            try:
                # We need to slightly modify the params for an update
                update_params = copy.deepcopy(params)
                update_params['Name'] = update_params['ConnectionInput']['Name']
                if not module.check_mode:
                    connection.update_connection(aws_retry=True, **update_params)
                changed = True
            except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
                module.fail_json_aws(e)
    else:
        try:
            if not module.check_mode:
                connection.create_connection(aws_retry=True, **params)
            changed = True
        except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e)

    # If changed, get the Glue connection again
    if changed and not module.check_mode:
        glue_connection = _await_glue_connection(connection, module)

    module.exit_json(changed=changed, **camel_dict_to_snake_dict(glue_connection or {}))
Esempio n. 5
0
 def format_network_configuration(self, network_config):
     result = dict()
     if 'subnets' in network_config:
         result['subnets'] = network_config['subnets']
     else:
         self.module.fail_json(
             msg="Network configuration must include subnets")
     if 'security_groups' in network_config:
         groups = network_config['security_groups']
         if any(not sg.startswith('sg-') for sg in groups):
             try:
                 vpc_id = self.ec2.describe_subnets(
                     SubnetIds=[result['subnets'][0]
                                ])['Subnets'][0]['VpcId']
                 groups = get_ec2_security_group_ids_from_names(
                     groups, self.ec2, vpc_id)
             except (botocore.exceptions.ClientError,
                     botocore.exceptions.BotoCoreError) as e:
                 self.module.fail_json_aws(
                     e, msg="Couldn't look up security groups")
         result['securityGroups'] = groups
     return dict(awsvpcConfiguration=result)
Esempio n. 6
0
def create_launch_config(connection, module):
    name = module.params.get('name')
    vpc_id = module.params.get('vpc_id')
    try:
        region, ec2_url, aws_connect_kwargs = get_aws_connection_info(
            module, boto3=True)
        ec2_connection = boto3_conn(module, 'client', 'ec2', region, ec2_url,
                                    **aws_connect_kwargs)
        security_groups = get_ec2_security_group_ids_from_names(
            module.params.get('security_groups'),
            ec2_connection,
            vpc_id=vpc_id,
            boto3=True)
    except botocore.exceptions.ClientError as e:
        module.fail_json(msg="Failed to get Security Group IDs",
                         exception=traceback.format_exc(),
                         **camel_dict_to_snake_dict(e.response))
    except ValueError as e:
        module.fail_json(msg="Failed to get Security Group IDs",
                         exception=traceback.format_exc())
    user_data = module.params.get('user_data')
    user_data_path = module.params.get('user_data_path')
    volumes = module.params['volumes']
    instance_monitoring = module.params.get('instance_monitoring')
    assign_public_ip = module.params.get('assign_public_ip')
    instance_profile_name = module.params.get('instance_profile_name')
    ebs_optimized = module.params.get('ebs_optimized')
    classic_link_vpc_id = module.params.get('classic_link_vpc_id')
    classic_link_vpc_security_groups = module.params.get(
        'classic_link_vpc_security_groups')

    block_device_mapping = []

    convert_list = [
        'image_id', 'instance_type', 'instance_type', 'instance_id',
        'placement_tenancy', 'key_name', 'kernel_id', 'ramdisk_id',
        'spot_price'
    ]

    launch_config = (snake_dict_to_camel_dict(
        dict((k.capitalize(), str(v)) for k, v in module.params.items()
             if v is not None and k in convert_list)))

    if user_data_path:
        try:
            with open(user_data_path, 'r') as user_data_file:
                user_data = user_data_file.read()
        except IOError as e:
            module.fail_json(msg="Failed to open file for reading",
                             exception=traceback.format_exc())

    if volumes:
        for volume in volumes:
            if 'device_name' not in volume:
                module.fail_json(msg='Device name must be set for volume')
            # Minimum volume size is 1GiB. We'll use volume size explicitly set to 0 to be a signal not to create this volume
            if 'volume_size' not in volume or int(volume['volume_size']) > 0:
                block_device_mapping.append(
                    create_block_device_meta(module, volume))

    try:
        launch_configs = connection.describe_launch_configurations(
            LaunchConfigurationNames=[name]).get('LaunchConfigurations')
    except botocore.exceptions.ClientError as e:
        module.fail_json(msg="Failed to describe launch configuration by name",
                         exception=traceback.format_exc(),
                         **camel_dict_to_snake_dict(e.response))

    changed = False
    result = {}

    launch_config['LaunchConfigurationName'] = name

    if security_groups is not None:
        launch_config['SecurityGroups'] = security_groups

    if classic_link_vpc_id is not None:
        launch_config['ClassicLinkVPCId'] = classic_link_vpc_id

    if instance_monitoring is not None:
        launch_config['InstanceMonitoring'] = {'Enabled': instance_monitoring}

    if classic_link_vpc_security_groups is not None:
        launch_config[
            'ClassicLinkVPCSecurityGroups'] = classic_link_vpc_security_groups

    if block_device_mapping:
        launch_config['BlockDeviceMappings'] = block_device_mapping

    if instance_profile_name is not None:
        launch_config['IamInstanceProfile'] = instance_profile_name

    if assign_public_ip is not None:
        launch_config['AssociatePublicIpAddress'] = assign_public_ip

    if user_data is not None:
        launch_config['UserData'] = user_data

    if ebs_optimized is not None:
        launch_config['EbsOptimized'] = ebs_optimized

    if len(launch_configs) == 0:
        try:
            connection.create_launch_configuration(**launch_config)
            launch_configs = connection.describe_launch_configurations(
                LaunchConfigurationNames=[name]).get('LaunchConfigurations')
            changed = True
            if launch_configs:
                launch_config = launch_configs[0]
        except botocore.exceptions.ClientError as e:
            module.fail_json(msg="Failed to create launch configuration",
                             exception=traceback.format_exc(),
                             **camel_dict_to_snake_dict(e.response))

    result = (dict((k, v) for k, v in launch_config.items() if k not in [
        'Connection', 'CreatedTime', 'InstanceMonitoring',
        'BlockDeviceMappings'
    ]))

    result['CreatedTime'] = to_text(launch_config.get('CreatedTime'))

    try:
        result['InstanceMonitoring'] = module.boolean(
            launch_config.get('InstanceMonitoring').get('Enabled'))
    except AttributeError:
        result['InstanceMonitoring'] = False

    result['BlockDeviceMappings'] = []

    for block_device_mapping in launch_config.get('BlockDeviceMappings', []):
        result['BlockDeviceMappings'].append(
            dict(device_name=block_device_mapping.get('DeviceName'),
                 virtual_name=block_device_mapping.get('VirtualName')))
        if block_device_mapping.get('Ebs') is not None:
            result['BlockDeviceMappings'][-1]['ebs'] = dict(
                snapshot_id=block_device_mapping.get('Ebs').get('SnapshotId'),
                volume_size=block_device_mapping.get('Ebs').get('VolumeSize'))

    if user_data_path:
        result[
            'UserData'] = "hidden"  # Otherwise, we dump binary to the user's terminal

    return_object = {
        'Name': result.get('LaunchConfigurationName'),
        'CreatedTime': result.get('CreatedTime'),
        'ImageId': result.get('ImageId'),
        'Arn': result.get('LaunchConfigurationARN'),
        'SecurityGroups': result.get('SecurityGroups'),
        'InstanceType': result.get('InstanceType'),
        'Result': result
    }

    module.exit_json(changed=changed,
                     **camel_dict_to_snake_dict(return_object))
Esempio n. 7
0
def modify_eni(connection, vpc_id, module, eni):

    instance_id = module.params.get("instance_id")
    attached = module.params.get("attached")
    do_detach = module.params.get('state') == 'detached'
    device_index = module.params.get("device_index")
    description = module.params.get('description')
    security_groups = module.params.get('security_groups')
    force_detach = module.params.get("force_detach")
    source_dest_check = module.params.get("source_dest_check")
    delete_on_termination = module.params.get("delete_on_termination")
    secondary_private_ip_addresses = module.params.get(
        "secondary_private_ip_addresses")
    purge_secondary_private_ip_addresses = module.params.get(
        "purge_secondary_private_ip_addresses")
    secondary_private_ip_address_count = module.params.get(
        "secondary_private_ip_address_count")
    allow_reassignment = module.params.get("allow_reassignment")
    changed = False

    try:
        if description is not None:
            if eni.description != description:
                connection.modify_network_interface_attribute(
                    eni.id, "description", description)
                changed = True
        if len(security_groups) > 0:
            groups = get_ec2_security_group_ids_from_names(security_groups,
                                                           connection,
                                                           vpc_id=vpc_id,
                                                           boto3=False)
            if sorted(get_sec_group_list(eni.groups)) != sorted(groups):
                connection.modify_network_interface_attribute(
                    eni.id, "groupSet", groups)
                changed = True
        if source_dest_check is not None:
            if eni.source_dest_check != source_dest_check:
                connection.modify_network_interface_attribute(
                    eni.id, "sourceDestCheck", source_dest_check)
                changed = True
        if delete_on_termination is not None and eni.attachment is not None:
            if eni.attachment.delete_on_termination is not delete_on_termination:
                connection.modify_network_interface_attribute(
                    eni.id, "deleteOnTermination", delete_on_termination,
                    eni.attachment.id)
                changed = True

        current_secondary_addresses = [
            i.private_ip_address for i in eni.private_ip_addresses
            if not i.primary
        ]
        if secondary_private_ip_addresses is not None:
            secondary_addresses_to_remove = list(
                set(current_secondary_addresses) -
                set(secondary_private_ip_addresses))
            if secondary_addresses_to_remove and purge_secondary_private_ip_addresses:
                connection.unassign_private_ip_addresses(
                    network_interface_id=eni.id,
                    private_ip_addresses=list(
                        set(current_secondary_addresses) -
                        set(secondary_private_ip_addresses)),
                    dry_run=False)
                changed = True

            secondary_addresses_to_add = list(
                set(secondary_private_ip_addresses) -
                set(current_secondary_addresses))
            if secondary_addresses_to_add:
                connection.assign_private_ip_addresses(
                    network_interface_id=eni.id,
                    private_ip_addresses=secondary_addresses_to_add,
                    secondary_private_ip_address_count=None,
                    allow_reassignment=allow_reassignment,
                    dry_run=False)
                changed = True
        if secondary_private_ip_address_count is not None:
            current_secondary_address_count = len(current_secondary_addresses)

            if secondary_private_ip_address_count > current_secondary_address_count:
                connection.assign_private_ip_addresses(
                    network_interface_id=eni.id,
                    private_ip_addresses=None,
                    secondary_private_ip_address_count=(
                        secondary_private_ip_address_count -
                        current_secondary_address_count),
                    allow_reassignment=allow_reassignment,
                    dry_run=False)
                changed = True
            elif secondary_private_ip_address_count < current_secondary_address_count:
                # How many of these addresses do we want to remove
                secondary_addresses_to_remove_count = current_secondary_address_count - secondary_private_ip_address_count
                connection.unassign_private_ip_addresses(
                    network_interface_id=eni.id,
                    private_ip_addresses=
                    current_secondary_addresses[:
                                                secondary_addresses_to_remove_count],
                    dry_run=False)

        if attached is True:
            if eni.attachment and eni.attachment.instance_id != instance_id:
                detach_eni(eni, module)
                eni.attach(instance_id, device_index)
                wait_for_eni(eni, "attached")
                changed = True
            if eni.attachment is None:
                eni.attach(instance_id, device_index)
                wait_for_eni(eni, "attached")
                changed = True
        elif attached is False:
            detach_eni(eni, module)

    except BotoServerError as e:
        module.fail_json_aws(e)

    eni.update()
    module.exit_json(changed=changed, interface=get_eni_info(eni))