def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( vpc_id=dict(), service=dict(), policy=dict(type='json'), policy_file=dict(type='path'), state=dict(default='present', choices=['present', 'absent']), wait=dict(type='bool', default=False), wait_timeout=dict(type='int', default=320, required=False), route_table_ids=dict(type='list'), vpc_endpoint_id=dict(), client_token=dict(), ) ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, mutually_exclusive=[['policy', 'policy_file']], required_if=[ ['state', 'present', ['vpc_id', 'service']], ['state', 'absent', ['vpc_endpoint_id']], ] ) # Validate Requirements if not HAS_BOTO3: module.fail_json(msg='botocore and boto3 are required for this module') state = module.params.get('state') try: region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) except NameError as e: # Getting around the get_aws_connection_info boto reliance for region if "global name 'boto' is not defined" in e.message: module.params['region'] = botocore.session.get_session().get_config_variable('region') if not module.params['region']: module.fail_json(msg="Error - no region provided") else: module.fail_json(msg="Can't retrieve connection information - " + str(e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) try: region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) ec2 = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_kwargs) except botocore.exceptions.NoCredentialsError as e: module.fail_json(msg="Failed to connect to AWS due to wrong or missing credentials: %s" % str(e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) # Ensure resource is present if state == 'present': (changed, results) = setup_creation(ec2, module) else: (changed, results) = setup_removal(ec2, module) module.exit_json(changed=changed, result=results)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( filters = dict(default=None, type='dict') ) ) module = AnsibleModule(argument_spec=argument_spec) if not HAS_BOTO: module.fail_json(msg='boto required for this module') if HAS_BOTO3: region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) if region: connection = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_params) else: module.fail_json(msg="region must be specified") list_ec2_snapshots_boto3(connection, module) else: region, ec2_url, aws_connect_params = get_aws_connection_info(module) if region: try: connection = connect_to_aws(boto.ec2, region, **aws_connect_params) except (boto.exception.NoAuthHandlerFound, AnsibleAWSError) as e: module.fail_json(msg=str(e)) else: module.fail_json(msg="region must be specified") list_eni(connection, module)
def main(): argument_spec = ec2_argument_spec() argument_spec.update(dict( state=dict(default='present', choices=['present', 'absent']), name=dict(required=True, type='str'), hash_key_name=dict(type='str'), hash_key_type=dict(default='STRING', type='str', choices=['STRING', 'NUMBER', 'BINARY']), range_key_name=dict(type='str'), range_key_type=dict(default='STRING', type='str', choices=['STRING', 'NUMBER', 'BINARY']), read_capacity=dict(default=1, type='int'), write_capacity=dict(default=1, type='int'), indexes=dict(default=[], type='list'), tags=dict(type='dict'), wait_for_active_timeout=dict(default=60, type='int'), )) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True) if not HAS_BOTO: module.fail_json(msg='boto required for this module') if not HAS_BOTO3 and module.params.get('tags'): module.fail_json(msg='boto3 required when using tags for this module') region, ec2_url, aws_connect_params = get_aws_connection_info(module) if not region: module.fail_json(msg='region must be specified') try: connection = connect_to_aws(boto.dynamodb2, region, **aws_connect_params) except (NoAuthHandlerFound, AnsibleAWSError) as e: module.fail_json(msg=str(e)) if module.params.get('tags'): try: region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) boto3_dynamodb = boto3_conn(module, conn_type='client', resource='dynamodb', region=region, endpoint=ec2_url, **aws_connect_kwargs) if not hasattr(boto3_dynamodb, 'tag_resource'): module.fail_json(msg='boto3 connection does not have tag_resource(), likely due to using an old version') boto3_sts = boto3_conn(module, conn_type='client', resource='sts', region=region, endpoint=ec2_url, **aws_connect_kwargs) except botocore.exceptions.NoCredentialsError as e: module.fail_json(msg='cannot connect to AWS', exception=traceback.format_exc(e)) else: boto3_dynamodb = None boto3_sts = None state = module.params.get('state') if state == 'present': create_or_update_dynamo_table(connection, module, boto3_dynamodb, boto3_sts, region) elif state == 'absent': delete_dynamo_table(connection, module)
def main(): argument_spec = ec2_argument_spec() argument_spec.update(dict( source_region=dict(required=True), source_snapshot_id=dict(required=True), description=dict(default=''), encrypted=dict(type='bool', default=False, required=False), kms_key_id=dict(type='str', required=False), wait=dict(type='bool', default=False), tags=dict(type='dict'))) module = AnsibleModule(argument_spec=argument_spec) if not HAS_BOTO3: module.fail_json(msg='botocore and boto3 are required.') region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) if not region: module.fail_json(msg="Region must be provided.") try: client = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_kwargs) except (NoCredentialsError, ProfileNotFound) as e: module.fail_json(msg="Can't authorize connection - %s" % to_native(e)) copy_snapshot(module, client)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( vpc_id=dict(), peer_vpc_id=dict(), peer_region=dict(), peering_id=dict(), peer_owner_id=dict(), tags=dict(required=False, type='dict'), profile=dict(), state=dict(default='present', choices=['present', 'absent', 'accept', 'reject']) ) ) module = AnsibleModule(argument_spec=argument_spec) if not HAS_BOTO3: module.fail_json(msg='json, botocore and boto3 are required.') state = module.params.get('state') try: region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) client = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_kwargs) except botocore.exceptions.NoCredentialsError as e: module.fail_json(msg="Can't authorize connection - " + str(e)) if state == 'present': (changed, results) = create_peer_connection(client, module) module.exit_json(changed=changed, peering_id=results) elif state == 'absent': remove_peer_connection(client, module) else: (changed, results) = accept_reject(state, client, module) module.exit_json(changed=changed, peering_id=results)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( name=dict(required=True, type='str'), adjustment_type=dict(type='str', choices=['ChangeInCapacity', 'ExactCapacity', 'PercentChangeInCapacity']), asg_name=dict(required=True, type='str'), scaling_adjustment=dict(type='int'), min_adjustment_step=dict(type='int'), cooldown=dict(type='int'), state=dict(default='present', choices=['present', 'absent']), ) ) module = AnsibleModule(argument_spec=argument_spec) if not HAS_BOTO: module.fail_json(msg='boto required for this module') region, ec2_url, aws_connect_params = get_aws_connection_info(module) state = module.params.get('state') try: connection = connect_to_aws(boto.ec2.autoscale, region, **aws_connect_params) except (boto.exception.NoAuthHandlerFound, AnsibleAWSError) as e: module.fail_json(msg=str(e)) if state == 'present': create_scaling_policy(connection, module) elif state == 'absent': delete_scaling_policy(connection, module)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( load_balancer_arn=dict(type='str'), target_group_arns=dict(type='list'), names=dict(type='list') ) ) module = AnsibleModule(argument_spec=argument_spec, mutually_exclusive=['load_balancer_arn', 'target_group_arns', 'names'], supports_check_mode=True ) if not HAS_BOTO3: module.fail_json(msg='boto3 required for this module') region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) if region: connection = boto3_conn(module, conn_type='client', resource='elbv2', region=region, endpoint=ec2_url, **aws_connect_params) else: module.fail_json(msg="region must be specified") list_target_groups(connection, module)
def main(): argument_spec = ec2_argument_spec() argument_spec.update(dict( vpc_id=dict(), name=dict(), nacl_id=dict(), subnets=dict(required=False, type='list', default=list()), tags=dict(required=False, type='dict'), ingress=dict(required=False, type='list', default=list()), egress=dict(required=False, type='list', default=list()), state=dict(default='present', choices=['present', 'absent']), ), ) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True, required_one_of=[['name', 'nacl_id']], required_if=[['state', 'present', ['vpc_id']]]) if not HAS_BOTO3: module.fail_json(msg='json, botocore and boto3 are required.') state = module.params.get('state').lower() try: region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) client = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_kwargs) except botocore.exceptions.NoCredentialsError as e: module.fail_json(msg="Can't authorize connection - %s" % str(e)) invocations = { "present": setup_network_acl, "absent": remove_network_acl } (changed, results) = invocations[state](client, module) module.exit_json(changed=changed, nacl_id=results)
def main(): """ Module action handler """ argument_spec = ec2_argument_spec() argument_spec.update(dict( id=dict(), name=dict(), tags=dict(type="dict", default={}), targets=dict(type="list", default=[]) )) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) region, _, aws_connect_params = get_aws_connection_info(module, boto3=True) connection = EFSConnection(module, region, **aws_connect_params) name = module.params.get('name') fs_id = module.params.get('id') tags = module.params.get('tags') targets = module.params.get('targets') file_systems_info = connection.get_file_systems(fs_id, name) if tags: file_systems_info = [item for item in file_systems_info if has_tags(item['tags'], tags)] if targets: targets = [(item, prefix_to_attr(item)) for item in targets] file_systems_info = [item for item in file_systems_info if has_targets(item['mount_targets'], targets)] module.exit_json(changed=False, ansible_facts={'efs': file_systems_info})
def main(): argument_spec = ec2_argument_spec() argument_spec.update(dict(state=dict(default='present', choices=['present', 'absent']), name=dict(), amazon_asn=dict(), virtual_gateway_id=dict(), direct_connect_gateway_id=dict(), wait_timeout=dict(type='int', default=320))) required_if = [('state', 'present', ['name', 'amazon_asn']), ('state', 'absent', ['direct_connect_gateway_id'])] module = AnsibleModule(argument_spec=argument_spec, required_if=required_if) if not HAS_BOTO3: module.fail_json(msg='boto3 is required for this module') state = module.params.get('state') region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) client = boto3_conn(module, conn_type='client', resource='directconnect', region=region, endpoint=ec2_url, **aws_connect_kwargs) if state == 'present': (changed, results) = ensure_present(client, module) elif state == 'absent': changed = ensure_absent(client, module) results = {} module.exit_json(changed=changed, **camel_dict_to_snake_dict(results))
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( name=dict(required=True, type='str'), managed_policy=dict(default=[], type='list'), state=dict(choices=['present', 'absent'], required=True), purge_policy=dict(default=False, type='bool') ) ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True ) if not HAS_BOTO3: module.fail_json(msg='boto3 required for this module') region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) connection = boto3_conn(module, conn_type='client', resource='iam', region=region, endpoint=ec2_url, **aws_connect_params) state = module.params.get("state") if state == 'present': create_or_update_user(connection, module) else: destroy_user(connection, module)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( name=dict(required=True), key_material=dict(), force=dict(type='bool', default=True), state=dict(default='present', choices=['present', 'absent']), wait=dict(type='bool', default=False), wait_timeout=dict(default=300) ) ) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) ec2_client = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_params) name = module.params['name'] state = module.params.get('state') key_material = module.params.get('key_material') force = module.params.get('force') if state == 'absent': delete_key_pair(module, ec2_client, name) elif state == 'present': create_key_pair(module, ec2_client, name, key_material, force)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( filters=dict(default=None, type='dict') ) ) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) if not HAS_BOTO: module.fail_json(msg='boto required for this module') region, ec2_url, aws_connect_params = get_aws_connection_info(module) if region: try: connection = connect_to_aws(boto.ec2, region, **aws_connect_params) except (boto.exception.NoAuthHandlerFound, AnsibleAWSError) as e: module.fail_json(msg=str(e)) else: module.fail_json(msg="region must be specified") list_ec2_instances(connection, module)
def main(): argument_spec = ec2_argument_spec() argument_spec.update(dict( state=dict(default='present', choices=['present', 'absent']), name=dict(required=True, type='str'), hash_key_name=dict(required=True, type='str'), hash_key_type=dict(default='STRING', type='str', choices=['STRING', 'NUMBER', 'BINARY']), range_key_name=dict(type='str'), range_key_type=dict(default='STRING', type='str', choices=['STRING', 'NUMBER', 'BINARY']), read_capacity=dict(default=1, type='int'), write_capacity=dict(default=1, type='int'), indexes=dict(default=[], type='list'), )) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True) if not HAS_BOTO: module.fail_json(msg='boto required for this module') region, ec2_url, aws_connect_params = get_aws_connection_info(module) if not region: module.fail_json(msg='region must be specified') try: connection = connect_to_aws(boto.dynamodb2, region, **aws_connect_params) except (NoAuthHandlerFound, AnsibleAWSError) as e: module.fail_json(msg=str(e)) state = module.params.get('state') if state == 'present': create_or_update_dynamo_table(connection, module) elif state == 'absent': delete_dynamo_table(connection, module)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( name=dict(required=False), ) ) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) if not HAS_BOTO3: module.fail_json(msg='boto3 and botocore are required.') try: region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) client = boto3_conn(module, conn_type='client', resource='waf', region=region, endpoint=ec2_url, **aws_connect_kwargs) except botocore.exceptions.NoCredentialsError as e: module.fail_json(msg="Can't authorize connection - " + str(e)) web_acls = list_web_acls(client, module) name = module.params['name'] if name: web_acls = [web_acl for web_acl in web_acls if web_acl['Name'] == name] if not web_acls: module.fail_json(msg="WAF named %s not found" % name) module.exit_json(wafs=[get_web_acl(client, module, web_acl['WebACLId']) for web_acl in web_acls])
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( filters=dict(default={}, type='dict'), nat_gateway_ids=dict(default=[], type='list'), ) ) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) # Validate Requirements if not HAS_BOTO3: module.fail_json(msg='botocore/boto3 is required.') try: region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) if region: connection = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_params) else: module.fail_json(msg="region must be specified") except botocore.exceptions.NoCredentialsError as e: module.fail_json(msg=str(e)) results = get_nat_gateways(connection, module) module.exit_json(result=results)
def main(): """ Main entry point. :return dict: ansible facts """ argument_spec = dict( function_name=dict(required=False, default=None, aliases=['function', 'name']), query=dict(required=False, choices=['aliases', 'all', 'config', 'mappings', 'policy', 'versions'], default='all'), event_source_arn=dict(required=False, default=None) ) module = AnsibleAWSModule( argument_spec=argument_spec, supports_check_mode=True, mutually_exclusive=[], required_together=[] ) # validate function_name if present function_name = module.params['function_name'] if function_name: if not re.search(r"^[\w\-:]+$", function_name): module.fail_json( msg='Function name {0} is invalid. Names must contain only alphanumeric characters and hyphens.'.format(function_name) ) if len(function_name) > 64: module.fail_json(msg='Function name "{0}" exceeds 64 character limit'.format(function_name)) try: region, endpoint, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) aws_connect_kwargs.update(dict(region=region, endpoint=endpoint, conn_type='client', resource='lambda' )) client = boto3_conn(module, **aws_connect_kwargs) except ClientError as e: module.fail_json_aws(e, "trying to set up boto connection") this_module = sys.modules[__name__] invocations = dict( aliases='alias_details', all='all_details', config='config_details', mappings='mapping_details', policy='policy_details', versions='version_details', ) this_module_function = getattr(this_module, invocations[module.params['query']]) all_facts = fix_return(this_module_function(client, module)) results = dict(ansible_facts={'lambda_facts': {'function': all_facts}}, changed=False) if module.check_mode: results['msg'] = 'Check mode set but ignored for fact gathering only.' module.exit_json(**results)
def main(): argument_spec = ec2_argument_spec() argument_spec.update(dict( source_region=dict(required=True), source_image_id=dict(required=True), name=dict(required=True), description=dict(default=''), encrypted=dict(type='bool', required=False), kms_key_id=dict(type='str', required=False), wait=dict(type='bool', default=False, required=False), tags=dict(type='dict'))) module = AnsibleModule(argument_spec=argument_spec) if not HAS_BOTO: module.fail_json(msg='boto required for this module') # TODO: Check botocore version region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) if HAS_BOTO3: try: ec2 = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_params) except NoRegionError: module.fail_json(msg='AWS Region is required') else: module.fail_json(msg='boto3 required for this module') copy_image(ec2, module)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( autoscaling_group_name=dict(required=True, type='str'), lifecycle_hook_name=dict(required=True, type='str'), transition=dict(type='str', choices=['autoscaling:EC2_INSTANCE_TERMINATING', 'autoscaling:EC2_INSTANCE_LAUNCHING']), role_arn=dict(type='str'), notification_target_arn=dict(type='str'), notification_meta_data=dict(type='str'), heartbeat_timeout=dict(type='int'), default_result=dict(default='ABANDON', choices=['ABANDON', 'CONTINUE']), state=dict(default='present', choices=['present', 'absent']) ) ) module = AnsibleAWSModule(argument_spec=argument_spec, required_if=[['state', 'present', ['transition']]]) state = module.params.get('state') region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) connection = boto3_conn(module, conn_type='client', resource='autoscaling', region=region, endpoint=ec2_url, **aws_connect_params) changed = False if state == 'present': changed = create_lifecycle_hook(connection, module) elif state == 'absent': changed = delete_lifecycle_hook(connection, module) module.exit_json(changed=changed)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( name=dict(required=True, type='str'), rules=dict(type='list'), state=dict(type='str', choices=['present', 'absent'], required=True) ) ) module = AnsibleModule(argument_spec=argument_spec) if not HAS_BOTO3: module.fail_json(msg='boto3 is required.') region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) client = boto3_conn(module, conn_type='client', resource='s3', region=region, endpoint=ec2_url, **aws_connect_kwargs) state = module.params.get("state") if state == 'present': create_or_update_bucket_cors(client, module) elif state == 'absent': destroy_bucket_cors(client, module)
def main(): argument_spec = ec2_argument_spec() module = AnsibleModule(argument_spec=argument_spec) if not HAS_BOTO3: module.fail_json(msg='Python module "boto3" is missing, please install it') if not HAS_BOTOCORE: module.fail_json(msg='Python module "botocore" is missing, please install it') try: region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) client = None try: client = boto3_conn(module, conn_type='client', resource='lightsail', region=region, endpoint=ec2_url, **aws_connect_kwargs) except (botocore.exceptions.ClientError, botocore.exceptions.ValidationError) as e: module.fail_json(msg='Failed while connecting to the lightsail service: %s' % e, exception=traceback.format_exc()) response = client.get_regions( includeAvailabilityZones=False ) module.exit_json(changed=False, results=response) except (botocore.exceptions.ClientError, Exception) as e: module.fail_json(msg=str(e), exception=traceback.format_exc())
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( name=dict(type='str', required=True), path=dict(type='str', default="/"), assume_role_policy_document=dict(type='json'), managed_policy=dict(type='list', aliases=['managed_policies']), state=dict(type='str', choices=['present', 'absent'], default='present'), description=dict(type='str'), create_instance_profile=dict(type='bool', default=True), purge_policies=dict(type='bool', default=True), ) ) module = AnsibleModule(argument_spec=argument_spec, required_if=[('state', 'present', ['assume_role_policy_document'])], supports_check_mode=True) if not HAS_BOTO3: module.fail_json(msg='boto3 required for this module') region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) connection = boto3_conn(module, conn_type='client', resource='iam', region=region, endpoint=ec2_url, **aws_connect_params) state = module.params.get("state") if state == 'present': create_or_update_role(connection, module) else: destroy_role(connection, module)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( query=dict(choices=['services', 'endpoints'], required=True), filters=dict(default={}, type='dict'), vpc_endpoint_ids=dict(type='list'), ) ) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) # Validate Requirements if not HAS_BOTO3: module.fail_json(msg='botocore and boto3 are required.') try: region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) if region: connection = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_params) else: module.fail_json(msg="region must be specified") except botocore.exceptions.NoCredentialsError as e: module.fail_json(msg=str(e)) invocations = { 'services': get_supported_services, 'endpoints': get_endpoints, } results = invocations[module.params.get('query')](connection, module) module.exit_json(**results)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( role_arn=dict(required=True, default=None), role_session_name=dict(required=True, default=None), duration_seconds=dict(required=False, default=None, type='int'), external_id=dict(required=False, default=None), policy=dict(required=False, default=None), mfa_serial_number=dict(required=False, default=None), mfa_token=dict(required=False, default=None) ) ) module = AnsibleAWSModule(argument_spec=argument_spec) region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) if region: connection = boto3_conn(module, conn_type='client', resource='sts', region=region, endpoint=ec2_url, **aws_connect_kwargs) else: module.fail_json(msg="region must be specified") assume_role_policy(connection, module)
def core(module): region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) if not region: module.fail_json(msg='region must be specified') client = None try: client = boto3_conn(module, conn_type='client', resource='lightsail', region=region, endpoint=ec2_url, **aws_connect_kwargs) except (botocore.exceptions.ClientError, botocore.exceptions.ValidationError) as e: module.fail_json('Failed while connecting to the lightsail service: %s' % e, exception=traceback.format_exc()) changed = False state = module.params['state'] name = module.params['name'] if state == 'absent': changed, instance_dict = delete_instance(module, client, name) elif state in ('running', 'stopped'): changed, instance_dict = startstop_instance(module, client, name, state) elif state == 'restarted': changed, instance_dict = restart_instance(module, client, name) elif state == 'present': changed, instance_dict = create_instance(module, client, name) module.exit_json(changed=changed, instance=camel_dict_to_snake_dict(instance_dict))
def main(): """ Get list of S3 buckets :return: """ # Ensure we have an empty dict result = {} # Including ec2 argument spec module = AnsibleModule(argument_spec=ec2_argument_spec(), supports_check_mode=True) # Verify Boto3 is used if not HAS_BOTO3: module.fail_json(msg='boto3 required for this module') # Set up connection region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=HAS_BOTO3) # Set up connection if region: try: connection = boto3_conn(module, conn_type='client', resource='s3', region=region, endpoint=ec2_url, **aws_connect_params) except (botocore.exceptions.NoCredentialsError, botocore.exceptions.ProfileNotFound) as e: module.fail_json(msg=e.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) else: module.fail_json(msg="AWS region must be specified (like: us-east-1)") # Gather results result['buckets'] = get_bucket_list(module, connection) # Send exit module.exit_json(msg="Retrieved s3 facts.", ansible_facts=result)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( snapshot_ids=dict(default=[], type='list'), owner_ids=dict(default=[], type='list'), restorable_by_user_ids=dict(default=[], type='list'), filters=dict(default={}, type='dict') ) ) module = AnsibleModule(argument_spec=argument_spec, mutually_exclusive=[ ['snapshot_ids', 'owner_ids', 'restorable_by_user_ids', 'filters'] ] ) if not HAS_BOTO3: module.fail_json(msg='boto3 required for this module') region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) if region: connection = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_params) else: module.fail_json(msg="region must be specified") list_ec2_snapshots(connection, module)
def setup_client(module): region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) if region: connection = boto3_conn(module, conn_type='client', resource='lambda', region=region, endpoint=ec2_url, **aws_connect_params) else: module.fail_json(msg="region must be specified") return connection
def __init__(self, module): self.module = module region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) self.client = boto3_conn(module, conn_type='client', resource='cloudfront', region=region, endpoint=ec2_url, **aws_connect_kwargs)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( name=dict(required=True), default_action=dict(choices=['block', 'allow', 'count']), metric_name=dict(), state=dict(default='present', choices=['present', 'absent']), rules=dict(type='list'), purge_rules=dict(type='bool', default=False) ), ) module = AnsibleAWSModule(argument_spec=argument_spec, required_if=[['state', 'present', ['default_action', 'rules']]]) state = module.params.get('state') region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) client = boto3_conn(module, conn_type='client', resource='waf', region=region, endpoint=ec2_url, **aws_connect_kwargs) if state == 'present': (changed, results) = ensure_web_acl_present(client, module) else: (changed, results) = ensure_web_acl_absent(client, module) module.exit_json(changed=changed, web_acl=camel_dict_to_snake_dict(results))
def main(): argument_spec = ec2_argument_spec() argument_spec.update(dict( name = dict(), function_arn = dict(), wait = dict(default=True, type='bool'), tail_log = dict(default=False, type='bool'), dry_run = dict(default=False, type='bool'), version_qualifier = dict(), payload = dict(default={}, type='dict'), )) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, mutually_exclusive=[ ['name', 'function_arn'], ] ) if not HAS_BOTO3: module.fail_json(msg='boto3 required for this module') name = module.params.get('name') function_arn = module.params.get('function_arn') await_return = module.params.get('wait') dry_run = module.params.get('dry_run') tail_log = module.params.get('tail_log') version_qualifier = module.params.get('version_qualifier') payload = module.params.get('payload') if not HAS_BOTO3: module.fail_json(msg='Python module "boto3" is missing, please install it') if not (name or function_arn): module.fail_json(msg="Must provide either a function_arn or a name to invoke.") region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=HAS_BOTO3) if not region: module.fail_json(msg="The AWS region must be specified as an " "environment variable or in the AWS credentials " "profile.") try: client = boto3_conn(module, conn_type='client', resource='lambda', region=region, endpoint=ec2_url, **aws_connect_kwargs) except (botocore.exceptions.ClientError, botocore.exceptions.ValidationError) as e: module.fail_json(msg="Failure connecting boto3 to AWS: %s" % to_native(e), exception=traceback.format_exc()) invoke_params = {} if await_return: # await response invoke_params['InvocationType'] = 'RequestResponse' else: # fire and forget invoke_params['InvocationType'] = 'Event' if dry_run or module.check_mode: # dry_run overrides invocation type invoke_params['InvocationType'] = 'DryRun' if tail_log and await_return: invoke_params['LogType'] = 'Tail' elif tail_log and not await_return: module.fail_json(msg="The `tail_log` parameter is only available if " "the invocation waits for the function to complete. " "Set `wait` to true or turn off `tail_log`.") else: invoke_params['LogType'] = 'None' if version_qualifier: invoke_params['Qualifier'] = version_qualifier if payload: invoke_params['Payload'] = json.dumps(payload) if function_arn: invoke_params['FunctionName'] = function_arn elif name: invoke_params['FunctionName'] = name try: response = client.invoke(**invoke_params) except botocore.exceptions.ClientError as ce: if ce.response['Error']['Code'] == 'ResourceNotFoundException': module.fail_json(msg="Could not find Lambda to execute. Make sure " "the ARN is correct and your profile has " "permissions to execute this function.", exception=traceback.format_exc()) module.fail_json(msg="Client-side error when invoking Lambda, check inputs and specific error", exception=traceback.format_exc()) except botocore.exceptions.ParamValidationError as ve: module.fail_json(msg="Parameters to `invoke` failed to validate", exception=traceback.format_exc(ve)) except Exception as e: module.fail_json(msg="Unexpected failure while invoking Lambda function", exception=traceback.format_exc()) results ={ 'logs': '', 'status': response['StatusCode'], 'output': '', } if response.get('LogResult'): try: # logs are base64 encoded in the API response results['logs'] = base64.b64decode(response.get('LogResult', '')) except Exception as e: module.fail_json(msg="Failed while decoding logs", exception=traceback.format_exc()) if invoke_params['InvocationType'] == 'RequestResponse': try: results['output'] = json.loads(response['Payload'].read().decode('utf8')) except Exception as e: module.fail_json(msg="Failed while decoding function return value", exception=traceback.format_exc()) if isinstance(results.get('output'), dict) and any( [results['output'].get('stackTrace'), results['output'].get('errorMessage')]): # AWS sends back stack traces and error messages when a function failed # in a RequestResponse (synchronous) context. template = ("Function executed, but there was an error in the Lambda function. " "Message: {errmsg}, Type: {type}, Stack Trace: {trace}") error_data = { # format the stacktrace sent back as an array into a multiline string 'trace': '\n'.join( [' '.join([ str(x) for x in line # cast line numbers to strings ]) for line in results.get('output', {}).get('stackTrace', [])] ), 'errmsg': results['output'].get('errorMessage'), 'type': results['output'].get('errorType') } module.fail_json(msg=template.format(**error_data), result=results) module.exit_json(changed=True, result=results)
def main(): """ Main entry point. :return dict: ansible facts """ argument_spec = dict(function_name=dict(required=False, default=None, aliases=['function', 'name']), query=dict(required=False, choices=[ 'aliases', 'all', 'config', 'mappings', 'policy', 'versions' ], default='all'), event_source_arn=dict(required=False, default=None)) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True, mutually_exclusive=[], required_together=[]) # validate function_name if present function_name = module.params['function_name'] if function_name: if not re.search(r"^[\w\-:]+$", function_name): module.fail_json( msg= 'Function name {0} is invalid. Names must contain only alphanumeric characters and hyphens.' .format(function_name)) if len(function_name) > 64: module.fail_json( msg='Function name "{0}" exceeds 64 character limit'.format( function_name)) try: region, endpoint, aws_connect_kwargs = get_aws_connection_info( module, boto3=True) aws_connect_kwargs.update( dict(region=region, endpoint=endpoint, conn_type='client', resource='lambda')) client = boto3_conn(module, **aws_connect_kwargs) except ClientError as e: module.fail_json_aws(e, "trying to set up boto connection") this_module = sys.modules[__name__] invocations = dict( aliases='alias_details', all='all_details', config='config_details', mappings='mapping_details', policy='policy_details', versions='version_details', ) this_module_function = getattr(this_module, invocations[module.params['query']]) all_facts = fix_return(this_module_function(client, module)) results = dict(ansible_facts={'lambda_facts': { 'function': all_facts }}, changed=False) if module.check_mode: results['msg'] = 'Check mode set but ignored for fact gathering only.' module.exit_json(**results)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( msg=dict(type='str', required=True, aliases=['default']), subject=dict(type='str', default=None), topic=dict(type='str', required=True), email=dict(type='str', default=None), sqs=dict(type='str', default=None), sms=dict(type='str', default=None), http=dict(type='str', default=None), https=dict(type='str', default=None), message_attributes=dict(type='dict', default=None), message_structure=dict(type='str', choices=['json', 'string'], default='json'), )) module = AnsibleModule(argument_spec=argument_spec) if not HAS_BOTO: module.fail_json(msg='boto required for this module') msg = module.params['msg'] subject = module.params['subject'] topic = module.params['topic'] email = module.params['email'] sqs = module.params['sqs'] sms = module.params['sms'] http = module.params['http'] https = module.params['https'] message_attributes = module.params['message_attributes'] message_structure = module.params['message_structure'] region, ec2_url, aws_connect_params = get_aws_connection_info(module) if not region: module.fail_json(msg="region must be specified") try: connection = connect_to_aws(boto.sns, region, **aws_connect_params) except boto.exception.NoAuthHandlerFound: e = get_exception() module.fail_json(msg=str(e)) if not message_structure == 'string' and message_attributes: module.fail_json( msg= "when specifying message_attributes, the message_structure must be set to 'string'; otherwise the attributes will not be sent." ) elif message_structure == 'string' and (email or sqs or sms or http or https): module.fail_json( msg= "do not specify non-default message formats when using the 'string' message_structure. they can only be used with the 'json' message_structure." ) # .publish() takes full ARN topic id, but I'm lazy and type shortnames # so do a lookup (topics cannot contain ':', so thats the decider) if ':' in topic: arn_topic = topic else: arn_topic = arn_topic_lookup(connection, topic) if not arn_topic: module.fail_json(msg='Could not find topic: {}'.format(topic)) dict_msg = {'default': msg} if email: dict_msg.update(email=email) if sqs: dict_msg.update(sqs=sqs) if sms: dict_msg.update(sms=sms) if http: dict_msg.update(http=http) if https: dict_msg.update(https=https) if not message_structure == 'json': json_msg = msg else: json_msg = json.dumps(dict_msg) try: connection.publish(topic=arn_topic, subject=subject, message_structure=message_structure, message=json_msg, message_attributes=message_attributes) except boto.exception.BotoServerError: e = get_exception() module.fail_json(msg=str(e)) module.exit_json(msg="OK")
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( force=dict(required=False, default='no', type='bool'), policy=dict(required=False, default=None, type='json'), name=dict(required=True, type='str'), requester_pays=dict(default='no', type='bool'), s3_url=dict(aliases=['S3_URL'], type='str'), state=dict(default='present', type='str', choices=['present', 'absent']), tags=dict(required=False, default=None, type='dict'), versioning=dict(default=None, type='bool'), ceph=dict(default='no', type='bool') ) ) module = AnsibleModule(argument_spec=argument_spec) if not HAS_BOTO: module.fail_json(msg='boto required for this module') region, ec2_url, aws_connect_params = get_aws_connection_info(module) if region in ('us-east-1', '', None): # S3ism for the US Standard region location = Location.DEFAULT else: # Boto uses symbolic names for locations but region strings will # actually work fine for everything except us-east-1 (US Standard) location = region s3_url = module.params.get('s3_url') # allow eucarc environment variables to be used if ansible vars aren't set if not s3_url and 'S3_URL' in os.environ: s3_url = os.environ['S3_URL'] ceph = module.params.get('ceph') if ceph and not s3_url: module.fail_json(msg='ceph flavour requires s3_url') flavour = 'aws' # bucket names with .'s in them need to use the calling_format option, # otherwise the connection will fail. See https://github.com/boto/boto/issues/2836 # for more details. aws_connect_params['calling_format'] = OrdinaryCallingFormat() # Look at s3_url and tweak connection settings # if connecting to Walrus or fakes3 try: if s3_url and ceph: ceph = urlparse.urlparse(s3_url) connection = boto.connect_s3( host=ceph.hostname, port=ceph.port, is_secure=ceph.scheme == 'https', **aws_connect_params ) flavour = 'ceph' elif is_fakes3(s3_url): fakes3 = urlparse.urlparse(s3_url) connection = S3Connection( is_secure=fakes3.scheme == 'fakes3s', host=fakes3.hostname, port=fakes3.port, **aws_connect_params ) elif is_walrus(s3_url): del aws_connect_params['calling_format'] walrus = urlparse.urlparse(s3_url).hostname connection = boto.connect_walrus(walrus, **aws_connect_params) else: connection = boto.s3.connect_to_region(location, is_secure=True, **aws_connect_params) # use this as fallback because connect_to_region seems to fail in boto + non 'classic' aws accounts in some cases if connection is None: connection = boto.connect_s3(**aws_connect_params) except boto.exception.NoAuthHandlerFound as e: module.fail_json(msg='No Authentication Handler found: %s ' % str(e)) except Exception as e: module.fail_json(msg='Failed to connect to S3: %s' % str(e)) if connection is None: # this should never happen module.fail_json(msg='Unknown error, failed to create s3 connection, no information from boto.') state = module.params.get("state") if state == 'present': create_or_update_bucket(connection, module, location, flavour=flavour) elif state == 'absent': destroy_bucket(connection, module, flavour=flavour)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( name=dict(required=True), cidr_block=dict(type='list', required=True), tenancy=dict(choices=['default', 'dedicated'], default='default'), dns_support=dict(type='bool', default=True), dns_hostnames=dict(type='bool', default=True), dhcp_opts_id=dict(), tags=dict(type='dict', aliases=['resource_tags']), state=dict(choices=['present', 'absent'], default='present'), multi_ok=dict(type='bool', default=False), purge_cidrs=dict(type='bool', default=False), )) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) name = module.params.get('name') cidr_block = module.params.get('cidr_block') purge_cidrs = module.params.get('purge_cidrs') tenancy = module.params.get('tenancy') dns_support = module.params.get('dns_support') dns_hostnames = module.params.get('dns_hostnames') dhcp_id = module.params.get('dhcp_opts_id') tags = module.params.get('tags') state = module.params.get('state') multi = module.params.get('multi_ok') changed = False region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) connection = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_params) if dns_hostnames and not dns_support: module.fail_json( msg= 'In order to enable DNS Hostnames you must also enable DNS support' ) if state == 'present': # Check if VPC exists vpc_id = vpc_exists(module, connection, name, cidr_block, multi) if vpc_id is None: vpc_id = create_vpc(connection, module, cidr_block[0], tenancy) changed = True vpc_obj = get_vpc(module, connection, vpc_id) associated_cidrs = dict( (cidr['CidrBlock'], cidr['AssociationId']) for cidr in vpc_obj.get('CidrBlockAssociationSet', []) if cidr['CidrBlockState']['State'] != 'disassociated') to_add = [cidr for cidr in cidr_block if cidr not in associated_cidrs] to_remove = [ associated_cidrs[cidr] for cidr in associated_cidrs if cidr not in cidr_block ] expected_cidrs = [ cidr for cidr in associated_cidrs if associated_cidrs[cidr] not in to_remove ] + to_add if len(cidr_block) > 1: for cidr in to_add: changed = True connection.associate_vpc_cidr_block(CidrBlock=cidr, VpcId=vpc_id) if purge_cidrs: for association_id in to_remove: changed = True try: connection.disassociate_vpc_cidr_block( AssociationId=association_id) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws( e, "Unable to disassociate {0}. You must detach or delete all gateways and resources that " "are associated with the CIDR block before you can disassociate it." .format(association_id)) if dhcp_id is not None: try: if update_dhcp_opts(connection, module, vpc_obj, dhcp_id): changed = True except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, "Failed to update DHCP options") if tags is not None or name is not None: try: if update_vpc_tags(connection, module, vpc_id, tags, name): changed = True except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Failed to update tags") current_dns_enabled = connection.describe_vpc_attribute( Attribute='enableDnsSupport', VpcId=vpc_id)['EnableDnsSupport']['Value'] current_dns_hostnames = connection.describe_vpc_attribute( Attribute='enableDnsHostnames', VpcId=vpc_id)['EnableDnsHostnames']['Value'] if current_dns_enabled != dns_support: changed = True if not module.check_mode: try: connection.modify_vpc_attribute( VpcId=vpc_id, EnableDnsSupport={'Value': dns_support}) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws( e, "Failed to update enabled dns support attribute") if current_dns_hostnames != dns_hostnames: changed = True if not module.check_mode: try: connection.modify_vpc_attribute( VpcId=vpc_id, EnableDnsHostnames={'Value': dns_hostnames}) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws( e, "Failed to update enabled dns hostnames attribute") # wait for associated cidrs to match if to_add or to_remove: try: connection.get_waiter('vpc_available').wait( VpcIds=[vpc_id], Filters=[{ 'Name': 'cidr-block-association.cidr-block', 'Values': expected_cidrs }]) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, "Failed to wait for CIDRs to update") # try to wait for enableDnsSupport and enableDnsHostnames to match wait_for_vpc_attribute(connection, module, vpc_id, 'enableDnsSupport', dns_support) wait_for_vpc_attribute(connection, module, vpc_id, 'enableDnsHostnames', dns_hostnames) final_state = camel_dict_to_snake_dict( get_vpc(module, connection, vpc_id)) final_state['tags'] = boto3_tag_list_to_ansible_dict( final_state.get('tags', [])) final_state['id'] = final_state.pop('vpc_id') module.exit_json(changed=changed, vpc=final_state) elif state == 'absent': # Check if VPC exists vpc_id = vpc_exists(module, connection, name, cidr_block, multi) if vpc_id is not None: try: if not module.check_mode: connection.delete_vpc(VpcId=vpc_id) changed = True except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws( e, msg= "Failed to delete VPC {0} You may want to use the ec2_vpc_subnet, ec2_vpc_igw, " "and/or ec2_vpc_route_table modules to ensure the other components are absent." .format(vpc_id)) module.exit_json(changed=changed, vpc={})
def main(): argument_spec = ec2_argument_spec() argument_spec.update(dict( state=dict(aliases=['command'], choices=['present', 'absent', 'get', 'create', 'delete'], required=True), zone=dict(required=True), hosted_zone_id=dict(required=False, default=None), record=dict(required=True), ttl=dict(required=False, type='int', default=3600), type=dict(choices=['A', 'CNAME', 'MX', 'AAAA', 'TXT', 'PTR', 'SRV', 'SPF', 'NS', 'SOA'], required=True), alias=dict(required=False, type='bool'), alias_hosted_zone_id=dict(required=False), alias_evaluate_target_health=dict(required=False, type='bool', default=False), value=dict(required=False, type='list', default=[]), overwrite=dict(required=False, type='bool'), retry_interval=dict(required=False, default=500), private_zone=dict(required=False, type='bool', default=False), identifier=dict(required=False, default=None), weight=dict(required=False, type='int'), region=dict(required=False), health_check=dict(required=False), failover=dict(required=False, choices=['PRIMARY', 'SECONDARY']), vpc_id=dict(required=False), wait=dict(required=False, type='bool', default=False), wait_timeout=dict(required=False, type='int', default=300), )) # state=present, absent, create, delete THEN value is required required_if = [('state', 'present', ['value']), ('state', 'create', ['value'])] required_if.extend([('state', 'absent', ['value']), ('state', 'delete', ['value'])]) # If alias is True then you must specify alias_hosted_zone as well required_together = [['alias', 'alias_hosted_zone_id']] # failover, region, and weight are mutually exclusive mutually_exclusive = [('failover', 'region', 'weight')] module = AnsibleModule(argument_spec=argument_spec, required_together=required_together, required_if=required_if, mutually_exclusive=mutually_exclusive) if not HAS_BOTO: module.fail_json(msg='boto required for this module') if distutils.version.StrictVersion(boto.__version__) < distutils.version.StrictVersion(MINIMUM_BOTO_VERSION): module.fail_json(msg='Found boto in version %s, but >= %s is required' % (boto.__version__, MINIMUM_BOTO_VERSION)) if module.params['state'] in ('present', 'create'): command_in = 'create' elif module.params['state'] in ('absent', 'delete'): command_in = 'delete' elif module.params['state'] == 'get': command_in = 'get' zone_in = module.params.get('zone').lower() hosted_zone_id_in = module.params.get('hosted_zone_id') ttl_in = module.params.get('ttl') record_in = module.params.get('record').lower() type_in = module.params.get('type') value_in = module.params.get('value') alias_in = module.params.get('alias') alias_hosted_zone_id_in = module.params.get('alias_hosted_zone_id') alias_evaluate_target_health_in = module.params.get('alias_evaluate_target_health') retry_interval_in = module.params.get('retry_interval') if module.params['vpc_id'] is not None: private_zone_in = True else: private_zone_in = module.params.get('private_zone') identifier_in = module.params.get('identifier') weight_in = module.params.get('weight') region_in = module.params.get('region') health_check_in = module.params.get('health_check') failover_in = module.params.get('failover') vpc_id_in = module.params.get('vpc_id') wait_in = module.params.get('wait') wait_timeout_in = module.params.get('wait_timeout') region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module) if zone_in[-1:] != '.': zone_in += "." if record_in[-1:] != '.': record_in += "." if command_in == 'create' or command_in == 'delete': if alias_in and len(value_in) != 1: module.fail_json(msg="parameter 'value' must contain a single dns name for alias records") if (weight_in is not None or region_in is not None or failover_in is not None) and identifier_in is None: module.fail_json(msg="If you specify failover, region or weight you must also specify identifier") if (weight_in is None and region_in is None and failover_in is None) and identifier_in is not None: module.fail_json(msg="You have specified identifier which makes sense only if you specify one of: weight, region or failover.") # connect to the route53 endpoint try: conn = Route53Connection(**aws_connect_kwargs) except boto.exception.BotoServerError as e: module.fail_json(msg=e.error_message) # Find the named zone ID zone = get_zone_by_name(conn, module, zone_in, private_zone_in, hosted_zone_id_in, vpc_id_in) # Verify that the requested zone is already defined in Route53 if zone is None: errmsg = "Zone %s does not exist in Route53" % zone_in module.fail_json(msg=errmsg) record = {} found_record = False wanted_rset = Record(name=record_in, type=type_in, ttl=ttl_in, identifier=identifier_in, weight=weight_in, region=region_in, health_check=health_check_in, failover=failover_in) for v in value_in: if alias_in: wanted_rset.set_alias(alias_hosted_zone_id_in, v, alias_evaluate_target_health_in) else: wanted_rset.add_value(v) sets = invoke_with_throttling_retries(conn.get_all_rrsets, zone.id, name=record_in, type=type_in, identifier=identifier_in) for rset in sets: # Due to a bug in either AWS or Boto, "special" characters are returned as octals, preventing round # tripping of things like * and @. decoded_name = rset.name.replace(r'\052', '*') decoded_name = decoded_name.replace(r'\100', '@') # Need to save this changes in rset, because of comparing rset.to_xml() == wanted_rset.to_xml() in next block rset.name = decoded_name if identifier_in is not None: identifier_in = str(identifier_in) if rset.type == type_in and decoded_name.lower() == record_in.lower() and rset.identifier == identifier_in: found_record = True record['zone'] = zone_in record['type'] = rset.type record['record'] = decoded_name record['ttl'] = rset.ttl record['value'] = ','.join(sorted(rset.resource_records)) record['values'] = sorted(rset.resource_records) if hosted_zone_id_in: record['hosted_zone_id'] = hosted_zone_id_in record['identifier'] = rset.identifier record['weight'] = rset.weight record['region'] = rset.region record['failover'] = rset.failover record['health_check'] = rset.health_check if hosted_zone_id_in: record['hosted_zone_id'] = hosted_zone_id_in if rset.alias_dns_name: record['alias'] = True record['value'] = rset.alias_dns_name record['values'] = [rset.alias_dns_name] record['alias_hosted_zone_id'] = rset.alias_hosted_zone_id record['alias_evaluate_target_health'] = rset.alias_evaluate_target_health else: record['alias'] = False record['value'] = ','.join(sorted(rset.resource_records)) record['values'] = sorted(rset.resource_records) if command_in == 'create' and rset.to_xml() == wanted_rset.to_xml(): module.exit_json(changed=False) # We need to look only at the first rrset returned by the above call, # so break here. The returned elements begin with the one matching our # requested name, type, and identifier, if such an element exists, # followed by all others that come after it in alphabetical order. # Therefore, if the first set does not match, no subsequent set will # match either. break if command_in == 'get': if type_in == 'NS': ns = record.get('values', []) else: # Retrieve name servers associated to the zone. z = invoke_with_throttling_retries(conn.get_zone, zone_in) ns = invoke_with_throttling_retries(z.get_nameservers) module.exit_json(changed=False, set=record, nameservers=ns) if command_in == 'delete' and not found_record: module.exit_json(changed=False) changes = ResourceRecordSets(conn, zone.id) if command_in == 'create' or command_in == 'delete': if command_in == 'create' and found_record: if not module.params['overwrite']: module.fail_json(msg="Record already exists with different value. Set 'overwrite' to replace it") command = 'UPSERT' else: command = command_in.upper() changes.add_change_record(command, wanted_rset) try: result = invoke_with_throttling_retries(commit, changes, retry_interval_in, wait_in, wait_timeout_in) except boto.route53.exception.DNSServerError as e: txt = e.body.split("<Message>")[1] txt = txt.split("</Message>")[0] if "but it already exists" in txt: module.exit_json(changed=False) else: module.fail_json(msg=txt) except TimeoutError: module.fail_json(msg='Timeout waiting for changes to replicate') module.exit_json(changed=True)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict(dhcp_options_id=dict(type='str', default=None), domain_name=dict(type='str', default=None), dns_servers=dict(type='list', default=None), ntp_servers=dict(type='list', default=None), netbios_name_servers=dict(type='list', default=None), netbios_node_type=dict(type='int', default=None), vpc_id=dict(type='str', default=None), delete_old=dict(type='bool', default=True), inherit_existing=dict(type='bool', default=False), tags=dict(type='dict', default=None, aliases=['resource_tags']), state=dict(type='str', default='present', choices=['present', 'absent']))) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) params = module.params found = False changed = False new_options = collections.defaultdict(lambda: None) if not HAS_BOTO: module.fail_json(msg='boto is required for this module') region, ec2_url, boto_params = get_aws_connection_info(module) connection = connect_to_aws(boto.vpc, region, **boto_params) existing_options = None # First check if we were given a dhcp_options_id if not params['dhcp_options_id']: # No, so create new_options from the parameters if params['dns_servers'] is not None: new_options['domain-name-servers'] = params['dns_servers'] if params['netbios_name_servers'] is not None: new_options['netbios-name-servers'] = params[ 'netbios_name_servers'] if params['ntp_servers'] is not None: new_options['ntp-servers'] = params['ntp_servers'] if params['domain_name'] is not None: # needs to be a list for comparison with boto objects later new_options['domain-name'] = [params['domain_name']] if params['netbios_node_type'] is not None: # needs to be a list for comparison with boto objects later new_options['netbios-node-type'] = [ str(params['netbios_node_type']) ] # If we were given a vpc_id then we need to look at the options on that if params['vpc_id']: existing_options = fetch_dhcp_options_for_vpc( connection, params['vpc_id']) # if we've been asked to inherit existing options, do that now if params['inherit_existing']: if existing_options: for option in [ 'domain-name-servers', 'netbios-name-servers', 'ntp-servers', 'domain-name', 'netbios-node-type' ]: if existing_options.options.get( option) and new_options[option] != [] and ( not new_options[option] or [''] == new_options[option]): new_options[option] = existing_options.options.get( option) # Do the vpc's dhcp options already match what we're asked for? if so we are done if existing_options and new_options == existing_options.options: module.exit_json(changed=changed, new_options=new_options, dhcp_options_id=existing_options.id) # If no vpc_id was given, or the options don't match then look for an existing set using tags found, dhcp_option = match_dhcp_options(connection, params['tags'], new_options) # Now let's cover the case where there are existing options that we were told about by id # If a dhcp_options_id was supplied we don't look at options inside, just set tags (if given) else: supplied_options = connection.get_all_dhcp_options( filters={'dhcp-options-id': params['dhcp_options_id']}) if len(supplied_options) != 1: if params['state'] != 'absent': module.fail_json( msg=" a dhcp_options_id was supplied, but does not exist") else: found = True dhcp_option = supplied_options[0] if params['state'] != 'absent' and params['tags']: ensure_tags(module, connection, dhcp_option.id, params['tags'], False, module.check_mode) # Now we have the dhcp options set, let's do the necessary # if we found options we were asked to remove then try to do so if params['state'] == 'absent': if not module.check_mode: if found: changed = remove_dhcp_options_by_id(connection, dhcp_option.id) module.exit_json(changed=changed, new_options={}) # otherwise if we haven't found the required options we have something to do elif not module.check_mode and not found: # create some dhcp options if we weren't able to use existing ones if not found: # Convert netbios-node-type and domain-name back to strings if new_options['netbios-node-type']: new_options['netbios-node-type'] = new_options[ 'netbios-node-type'][0] if new_options['domain-name']: new_options['domain-name'] = new_options['domain-name'][0] # create the new dhcp options set requested dhcp_option = connection.create_dhcp_options( new_options['domain-name'], new_options['domain-name-servers'], new_options['ntp-servers'], new_options['netbios-name-servers'], new_options['netbios-node-type']) # wait for dhcp option to be accessible found_dhcp_opt = False start_time = time() try: found_dhcp_opt = retry_not_found( connection.get_all_dhcp_options, dhcp_options_ids=[dhcp_option.id]) except EC2ResponseError as e: module.fail_json(msg="Failed to describe DHCP options", exception=traceback.format_exc) if not found_dhcp_opt: module.fail_json(msg="Failed to wait for {0} to be available.". format(dhcp_option.id)) changed = True if params['tags']: ensure_tags(module, connection, dhcp_option.id, params['tags'], False, module.check_mode) # If we were given a vpc_id, then attach the options we now have to that before we finish if params['vpc_id'] and not module.check_mode: changed = True connection.associate_dhcp_options(dhcp_option.id, params['vpc_id']) # and remove old ones if that was requested if params['delete_old'] and existing_options: remove_dhcp_options_by_id(connection, existing_options.id) module.exit_json(changed=changed, new_options=new_options, dhcp_options_id=dhcp_option.id)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict(log_group_name=dict(required=True, type='str'), state=dict(choices=['present', 'absent'], default='present'), kms_key_id=dict(required=False, type='str'), tags=dict(required=False, type='dict'), retention=dict(required=False, type='int'), overwrite=dict(required=False, type='bool', default=False))) module = AnsibleModule(argument_spec=argument_spec) if not HAS_BOTO3: module.fail_json(msg='boto3 is required.') region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) logs = boto3_conn(module, conn_type='client', resource='logs', region=region, endpoint=ec2_url, **aws_connect_kwargs) state = module.params.get('state') changed = False # Determine if the log group exists desc_log_group = describe_log_group( client=logs, log_group_name=module.params['log_group_name'], module=module) found_log_group = {} for i in desc_log_group.get('logGroups', []): if module.params['log_group_name'] == i['logGroupName']: found_log_group = i break if state == 'present': if found_log_group and module.params['overwrite'] is True: changed = True delete_log_group(client=logs, log_group_name=module.params['log_group_name'], module=module) found_log_group = create_log_group( client=logs, log_group_name=module.params['log_group_name'], kms_key_id=module.params['kms_key_id'], tags=module.params['tags'], retention=module.params['retention'], module=module) elif not found_log_group: changed = True found_log_group = create_log_group( client=logs, log_group_name=module.params['log_group_name'], kms_key_id=module.params['kms_key_id'], tags=module.params['tags'], retention=module.params['retention'], module=module) elif found_log_group: if module.params['retention'] != found_log_group['retentionInDays']: changed = True input_retention_policy( client=logs, log_group_name=module.params['log_group_name'], retention=module.params['retention'], module=module) found_log_group['retentionInDays'] = module.params['retention'] module.exit_json(changed=changed, **camel_dict_to_snake_dict(found_log_group)) elif state == 'absent': if found_log_group: changed = True delete_log_group(client=logs, log_group_name=module.params['log_group_name'], module=module) module.exit_json(changed=changed)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( name=dict(required=True, type='str'), state=dict(required=True, type='str', choices=['present', 'absent', 'copy']), replication_id=dict(type='str'), cluster_id=dict(type='str'), target=dict(type='str'), bucket=dict(type='str'), )) module = AnsibleModule(argument_spec=argument_spec) if not HAS_BOTO3: module.fail_json(msg='boto required for this module') name = module.params.get('name') state = module.params.get('state') replication_id = module.params.get('replication_id') cluster_id = module.params.get('cluster_id') target = module.params.get('target') bucket = module.params.get('bucket') # Retrieve any AWS settings from the environment. region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) if not region: module.fail_json(msg=str( "Either region or AWS_REGION or EC2_REGION environment variable or boto config aws_region or ec2_region must be set." )) connection = boto3_conn(module, conn_type='client', resource='elasticache', region=region, endpoint=ec2_url, **aws_connect_kwargs) changed = False response = {} if state == 'present': if not all((replication_id, cluster_id)): module.fail_json( msg= "The state 'present' requires options: 'replication_id' and 'cluster_id'" ) response, changed = create(module, connection, replication_id, cluster_id, name) elif state == 'absent': response, changed = delete(module, connection, name) elif state == 'copy': if not all((target, bucket)): module.fail_json( msg="The state 'copy' requires options: 'target' and 'bucket'." ) response, changed = copy(module, connection, name, target, bucket) facts_result = dict(changed=changed, **camel_dict_to_snake_dict(response)) module.exit_json(**facts_result)
def find_asgs(conn, module, name=None, tags=None): """ Args: conn (boto3.AutoScaling.Client): Valid Boto3 ASG client. name (str): Optional name of the ASG you are looking for. tags (dict): Optional dictionary of tags and values to search for. Basic Usage: >>> name = 'public-webapp-production' >>> tags = { 'env': 'production' } >>> conn = boto3.client('autoscaling', region_name='us-west-2') >>> results = find_asgs(name, conn) Returns: List [ { "auto_scaling_group_arn": ( "arn:aws:autoscaling:us-west-2:275977225706:autoScalingGroup:58abc686-9783-4528-b338-3ad6f1cbbbaf:" "autoScalingGroupName/public-webapp-production" ), "auto_scaling_group_name": "public-webapp-production", "availability_zones": ["us-west-2c", "us-west-2b", "us-west-2a"], "created_time": "2016-02-02T23:28:42.481000+00:00", "default_cooldown": 300, "desired_capacity": 2, "enabled_metrics": [], "health_check_grace_period": 300, "health_check_type": "ELB", "instances": [ { "availability_zone": "us-west-2c", "health_status": "Healthy", "instance_id": "i-047a12cb", "launch_configuration_name": "public-webapp-production-1", "lifecycle_state": "InService", "protected_from_scale_in": false }, { "availability_zone": "us-west-2a", "health_status": "Healthy", "instance_id": "i-7a29df2c", "launch_configuration_name": "public-webapp-production-1", "lifecycle_state": "InService", "protected_from_scale_in": false } ], "launch_config_name": "public-webapp-production-1", "launch_configuration_name": "public-webapp-production-1", "load_balancer_names": ["public-webapp-production-lb"], "max_size": 4, "min_size": 2, "new_instances_protected_from_scale_in": false, "placement_group": None, "status": None, "suspended_processes": [], "tags": [ { "key": "Name", "propagate_at_launch": true, "resource_id": "public-webapp-production", "resource_type": "auto-scaling-group", "value": "public-webapp-production" }, { "key": "env", "propagate_at_launch": true, "resource_id": "public-webapp-production", "resource_type": "auto-scaling-group", "value": "production" } ], "target_group_names": [], "target_group_arns": [], "termination_policies": [ "Default" ], "vpc_zone_identifier": [ "subnet-a1b1c1d1", "subnet-a2b2c2d2", "subnet-a3b3c3d3" ] } ] """ try: asgs_paginator = conn.get_paginator('describe_auto_scaling_groups') asgs = asgs_paginator.paginate().build_full_result() except ClientError as e: module.fail_json(msg=e.message, **camel_dict_to_snake_dict(e.response)) if not asgs: return asgs try: region, ec2_url, aws_connect_kwargs = get_aws_connection_info( module, boto3=True) elbv2 = boto3_conn(module, conn_type='client', resource='elbv2', region=region, endpoint=ec2_url, **aws_connect_kwargs) except ClientError as e: # This is nice to have, not essential elbv2 = None matched_asgs = [] if name is not None: # if the user didn't specify a name name_prog = re.compile(r'^' + name) for asg in asgs['AutoScalingGroups']: if name: matched_name = name_prog.search(asg['AutoScalingGroupName']) else: matched_name = True if tags: matched_tags = match_asg_tags(tags, asg) else: matched_tags = True if matched_name and matched_tags: asg = camel_dict_to_snake_dict(asg) # compatibility with ec2_asg module asg['launch_config_name'] = asg['launch_configuration_name'] # workaround for https://github.com/ansible/ansible/pull/25015 if 'target_group_ar_ns' in asg: asg['target_group_arns'] = asg['target_group_ar_ns'] del (asg['target_group_ar_ns']) if asg.get('target_group_arns'): if elbv2: try: tg_paginator = elbv2.get_paginator( 'describe_target_groups') tg_result = tg_paginator.paginate( TargetGroupArns=asg['target_group_arns'] ).build_full_result() asg['target_group_names'] = [ tg['TargetGroupName'] for tg in tg_result['TargetGroups'] ] except ClientError as e: if e.response['Error'][ 'Code'] == 'TargetGroupNotFound': asg['target_group_names'] = [] else: asg['target_group_names'] = [] matched_asgs.append(asg) return matched_asgs
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( command=dict(choices=['create', 'facts', 'delete', 'modify'], required=True), identifier=dict(required=True), node_type=dict(choices=[ 'ds1.xlarge', 'ds1.8xlarge', 'ds2.xlarge', 'ds2.8xlarge', 'dc1.large', 'dc2.large', 'dc1.8xlarge', 'dw1.xlarge', 'dw1.8xlarge', 'dw2.large', 'dw2.8xlarge' ], required=False), username=dict(required=False), password=dict(no_log=True, required=False), db_name=dict(require=False), cluster_type=dict(choices=[ 'multi-node', 'single-node', ], default='single-node'), cluster_security_groups=dict(aliases=['security_groups'], type='list'), vpc_security_group_ids=dict(aliases=['vpc_security_groups'], type='list'), skip_final_cluster_snapshot=dict(aliases=['skip_final_snapshot'], type='bool', default=False), final_cluster_snapshot_identifier=dict( aliases=['final_snapshot_id'], required=False), cluster_subnet_group_name=dict(aliases=['subnet']), availability_zone=dict(aliases=['aws_zone', 'zone']), preferred_maintenance_window=dict( aliases=['maintance_window', 'maint_window']), cluster_parameter_group_name=dict(aliases=['param_group_name']), automated_snapshot_retention_period=dict( aliases=['retention_period']), port=dict(type='int'), cluster_version=dict(aliases=['version'], choices=['1.0']), allow_version_upgrade=dict(aliases=['version_upgrade'], type='bool', default=True), number_of_nodes=dict(type='int'), publicly_accessible=dict(type='bool', default=False), encrypted=dict(type='bool', default=False), elastic_ip=dict(required=False), new_cluster_identifier=dict(aliases=['new_identifier']), wait=dict(type='bool', default=False), wait_timeout=dict(type='int', default=300), )) required_if = [('command', 'delete', ['skip_final_cluster_snapshot']), ('skip_final_cluster_snapshot', False, ['final_cluster_snapshot_identifier'])] module = AnsibleModule(argument_spec=argument_spec, required_if=required_if) if not HAS_BOTO: module.fail_json(msg='boto v2.9.0+ required for this module') command = module.params.get('command') region, ec2_url, aws_connect_params = get_aws_connection_info(module) if not region: module.fail_json(msg=str( "region not specified and unable to determine region from EC2_REGION." )) # connect to the rds endpoint try: conn = connect_to_aws(boto.redshift, region, **aws_connect_params) except boto.exception.JSONResponseError as e: module.fail_json(msg=str(e)) changed = True if command == 'create': (changed, cluster) = create_cluster(module, conn) elif command == 'facts': (changed, cluster) = describe_cluster(module, conn) elif command == 'delete': (changed, cluster) = delete_cluster(module, conn) elif command == 'modify': (changed, cluster) = modify_cluster(module, conn) module.exit_json(changed=changed, cluster=cluster)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( policy_name=dict(required=True), policy_description=dict(default=''), policy=dict(type='json'), make_default=dict(type='bool', default=True), only_version=dict(type='bool', default=False), fail_on_delete=dict(type='bool', default=True), state=dict(required=True, choices=['present', 'absent']), )) module = AnsibleModule(argument_spec=argument_spec, required_if=[['state', 'present', ['policy']]]) if not HAS_BOTO3: module.fail_json(msg='boto3 is required for this module') name = module.params.get('policy_name') description = module.params.get('policy_description') state = module.params.get('state') default = module.params.get('make_default') only = module.params.get('only_version') policy = None if module.params.get('policy') is not None: policy = json.dumps(json.loads(module.params.get('policy'))) try: region, ec2_url, aws_connect_kwargs = get_aws_connection_info( module, boto3=True) iam = boto3_conn(module, conn_type='client', resource='iam', region=region, endpoint=ec2_url, **aws_connect_kwargs) except (botocore.exceptions.NoCredentialsError, botocore.exceptions.ProfileNotFound) as e: module.fail_json( msg= "Can't authorize connection. Check your credentials and profile.", exceptions=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) p = get_policy_by_name(module, iam, name) if state == 'present': if p is None: # No Policy so just create one try: rvalue = iam.create_policy(PolicyName=name, Path='/', PolicyDocument=policy, Description=description) except Exception as e: module.fail_json(msg="Couldn't create policy %s: %s" % (name, to_native(e)), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) module.exit_json(changed=True, policy=camel_dict_to_snake_dict(rvalue['Policy'])) else: policy_version, changed = get_or_create_policy_version( module, iam, p, policy) changed = set_if_default(module, iam, p, policy_version, default) or changed changed = set_if_only(module, iam, p, policy_version, only) or changed # If anything has changed we needto refresh the policy if changed: try: p = iam.get_policy(PolicyArn=p['Arn'])['Policy'] except Exception as e: module.fail_json(msg="Couldn't get policy: %s" % to_native(e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) module.exit_json(changed=changed, policy=camel_dict_to_snake_dict(p)) else: # Check for existing policy if p: # Detach policy detach_all_entities(module, iam, p) # Delete Versions try: versions = iam.list_policy_versions( PolicyArn=p['Arn'])['Versions'] except botocore.exceptions.ClientError as e: module.fail_json(msg="Couldn't list policy versions: %s" % to_native(e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) for v in versions: if not v['IsDefaultVersion']: try: iam.delete_policy_version(PolicyArn=p['Arn'], VersionId=v['VersionId']) except botocore.exceptions.ClientError as e: module.fail_json( msg="Couldn't delete policy version %s: %s" % (v['VersionId'], to_native(e)), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) # Delete policy try: iam.delete_policy(PolicyArn=p['Arn']) except Exception as e: module.fail_json(msg="Couldn't delete policy %s: %s" % (p['PolicyName'], to_native(e)), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) # This is the one case where we will return the old policy module.exit_json(changed=True, policy=camel_dict_to_snake_dict(p)) else: module.exit_json(changed=False, policy=None)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict(access_logs_enabled=dict(required=False, type='bool'), access_logs_s3_bucket=dict(required=False, type='str'), access_logs_s3_prefix=dict(required=False, type='str'), deletion_protection=dict(required=False, default=False, type='bool'), idle_timeout=dict(required=False, type='int'), listeners=dict(required=False, type='list'), name=dict(required=True, type='str'), purge_tags=dict(required=False, default=True, type='bool'), subnets=dict(required=False, type='list'), security_groups=dict(required=False, type='list'), scheme=dict(required=False, default='internet-facing', choices=['internet-facing', 'internal']), state=dict(required=True, choices=['present', 'absent'], type='str'), tags=dict(required=False, default={}, type='dict'), wait_timeout=dict(required=False, type='int'), wait=dict(required=False, type='bool'))) module = AnsibleModule(argument_spec=argument_spec, required_if=[('state', 'present', ['subnets', 'security_groups'])], required_together=([ 'access_logs_enabled', 'access_logs_s3_bucket', 'access_logs_s3_prefix' ])) # Quick check of listeners parameters listeners = module.params.get("listeners") if listeners is not None: for listener in listeners: for key in listener.keys(): if key not in [ 'Protocol', 'Port', 'SslPolicy', 'Certificates', 'DefaultActions', 'Rules' ]: module.fail_json( msg= "listeners parameter contains invalid dict keys. Should be one of 'Protocol', " "'Port', 'SslPolicy', 'Certificates', 'DefaultActions', 'Rules'." ) if not HAS_BOTO3: module.fail_json(msg='boto3 required for this module') region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) if region: connection = boto3_conn(module, conn_type='client', resource='elbv2', region=region, endpoint=ec2_url, **aws_connect_params) connection_ec2 = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_params) else: module.fail_json(msg="region must be specified") state = module.params.get("state") if state == 'present': create_or_update_elb(connection, connection_ec2, module) else: delete_elb(connection, module)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( query=dict(choices=[ 'change', 'checker_ip_range', 'health_check', 'hosted_zone', 'record_sets', 'reusable_delegation_set', ], required=True), change_id=dict(), hosted_zone_id=dict(), max_items=dict(type='int'), next_marker=dict(type='int'), delegation_set_id=dict(), start_record_name=dict(), type=dict(choices=[ 'A', 'CNAME', 'MX', 'AAAA', 'TXT', 'PTR', 'SRV', 'SPF', 'CAA', 'NS' ]), dns_name=dict(), resource_id=dict(type='list', aliases=['resource_ids']), health_check_id=dict(), hosted_zone_method=dict( choices=['details', 'list', 'list_by_name', 'count', 'tags'], default='list'), health_check_method=dict(choices=[ 'list', 'details', 'status', 'failure_reason', 'count', 'tags', ], default='list'), )) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, mutually_exclusive=[ ['hosted_zone_method', 'health_check_method'], ], ) if module._name == 'route53_facts': module.deprecate( "The 'route53_facts' module has been renamed to 'route53_info'", version='2.13') # Validate Requirements if not (HAS_BOTO or HAS_BOTO3): module.fail_json(msg='json and boto/boto3 is required.') region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) route53 = boto3_conn(module, conn_type='client', resource='route53', region=region, endpoint=ec2_url, **aws_connect_kwargs) invocations = { 'change': change_details, 'checker_ip_range': checker_ip_range_details, 'health_check': health_check_details, 'hosted_zone': hosted_zone_details, 'record_sets': record_sets_details, 'reusable_delegation_set': reusable_delegation_set_details, } results = dict(changed=False) try: results = invocations[module.params.get('query')](route53, module) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json(msg=to_native(e)) module.exit_json(**results)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( mode=dict(choices=['push'], default='push'), file_change_strategy=dict( choices=['force', 'date_size', 'checksum'], default='date_size'), bucket=dict(required=True), key_prefix=dict(required=False, default=''), file_root=dict(required=True, type='path'), permission=dict(required=False, choices=[ 'private', 'public-read', 'public-read-write', 'authenticated-read', 'aws-exec-read', 'bucket-owner-read', 'bucket-owner-full-control' ]), retries=dict(required=False), mime_map=dict(required=False, type='dict'), exclude=dict(required=False, default=".*"), include=dict(required=False, default="*"), cache_control=dict(required=False, default=''), # future options: encoding, metadata, storage_class, retries )) module = AnsibleModule(argument_spec=argument_spec, ) if not HAS_BOTO3: module.fail_json(msg='boto3 required for this module') result = {} mode = module.params['mode'] region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) if not region: module.fail_json(msg="Region must be specified") s3 = boto3_conn(module, conn_type='client', resource='s3', region=region, endpoint=ec2_url, **aws_connect_kwargs) if mode == 'push': try: result['filelist_initial'] = gather_files( module.params['file_root'], exclude=module.params['exclude'], include=module.params['include']) result['filelist_typed'] = determine_mimetypes( result['filelist_initial'], module.params.get('mime_map')) result['filelist_s3'] = calculate_s3_path( result['filelist_typed'], module.params['key_prefix']) result['filelist_local_etag'] = calculate_local_etag( result['filelist_s3']) result['filelist_actionable'] = filter_list( s3, module.params['bucket'], result['filelist_local_etag'], module.params['file_change_strategy']) result['uploads'] = upload_files(s3, module.params['bucket'], result['filelist_actionable'], module.params) # mark changed if we actually upload something. if result.get('uploads') and len(result.get('uploads')): result['changed'] = True # result.update(filelist=actionable_filelist) except botocore.exceptions.ClientError as err: error_msg = boto_exception(err) module.fail_json(msg=error_msg, exception=traceback.format_exc(), **camel_dict_to_snake_dict(err.response)) module.exit_json(**result)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict(state=dict(required=True, choices=['present', 'absent']), name=dict(), cert=dict(), key=dict(no_log=True), cert_chain=dict(), new_name=dict(), path=dict(default='/'), new_path=dict(), dup_ok=dict(type='bool'))) module = AnsibleModule( argument_spec=argument_spec, mutually_exclusive=[ ['new_path', 'key'], ['new_path', 'cert'], ['new_path', 'cert_chain'], ['new_name', 'key'], ['new_name', 'cert'], ['new_name', 'cert_chain'], ], ) if not HAS_BOTO: module.fail_json(msg="Boto is required for this module") region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module) try: if region: iam = connect_to_aws(boto.iam, region, **aws_connect_kwargs) else: iam = boto.iam.connection.IAMConnection(**aws_connect_kwargs) except boto.exception.NoAuthHandlerFound as e: module.fail_json(msg=str(e)) state = module.params.get('state') name = module.params.get('name') path = module.params.get('path') new_name = module.params.get('new_name') new_path = module.params.get('new_path') dup_ok = module.params.get('dup_ok') if state == 'present' and not new_name and not new_path: cert, key, cert_chain = load_data( cert=module.params.get('cert'), key=module.params.get('key'), cert_chain=module.params.get('cert_chain')) else: cert = key = cert_chain = None orig_cert_names = [ ctb['server_certificate_name'] for ctb in iam.get_all_server_certs(). list_server_certificates_result.server_certificate_metadata_list ] orig_cert_bodies = [ iam.get_server_certificate( thing).get_server_certificate_result.certificate_body for thing in orig_cert_names ] if new_name == name: new_name = None if new_path == path: new_path = None changed = False try: cert_action(module, iam, name, path, new_name, new_path, state, cert, key, cert_chain, orig_cert_names, orig_cert_bodies, dup_ok) except boto.exception.BotoServerError as err: module.fail_json(changed=changed, msg=str(err), debug=[cert, key])
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict(state={ 'required': True, 'choices': ['present', 'absent'] }, instance_id={'required': True}, ec2_elbs={ 'default': None, 'required': False, 'type': 'list' }, enable_availability_zone={ 'default': True, 'required': False, 'type': 'bool' }, wait={ 'required': False, 'default': True, 'type': 'bool' }, wait_timeout={ 'required': False, 'default': 0, 'type': 'int' })) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) if not HAS_BOTO: module.fail_json(msg='boto required for this module') region, ec2_url, aws_connect_params = get_aws_connection_info(module) if not region: module.fail_json( msg= "Region must be specified as a parameter, in EC2_REGION or AWS_REGION environment variables or in boto configuration file" ) ec2_elbs = module.params['ec2_elbs'] wait = module.params['wait'] enable_availability_zone = module.params['enable_availability_zone'] timeout = module.params['wait_timeout'] if module.params['state'] == 'present' and 'ec2_elbs' not in module.params: module.fail_json(msg="ELBs are required for registration") instance_id = module.params['instance_id'] elb_man = ElbManager(module, instance_id, ec2_elbs, region=region, **aws_connect_params) if ec2_elbs is not None: for elb in ec2_elbs: if not elb_man.exists(elb): msg = "ELB %s does not exist" % elb module.fail_json(msg=msg) if not module.check_mode: if module.params['state'] == 'present': elb_man.register(wait, enable_availability_zone, timeout) elif module.params['state'] == 'absent': elb_man.deregister(wait, timeout) ansible_facts = {'ec2_elbs': [lb.name for lb in elb_man.lbs]} ec2_facts_result = dict(changed=elb_man.changed, ansible_facts=ansible_facts) module.exit_json(**ec2_facts_result)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict(name=dict(), group_id=dict(), description=dict(), vpc_id=dict(), rules=dict(type='list'), rules_egress=dict(type='list'), state=dict(default='present', type='str', choices=['present', 'absent']), purge_rules=dict(default=True, required=False, type='bool'), purge_rules_egress=dict(default=True, required=False, type='bool'), tags=dict(required=False, type='dict', aliases=['resource_tags']), purge_tags=dict(default=True, required=False, type='bool'))) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, required_one_of=[['name', 'group_id']], required_if=[['state', 'present', ['name']]], ) if not HAS_BOTO3: module.fail_json(msg='boto3 required for this module') name = module.params['name'] group_id = module.params['group_id'] description = module.params['description'] vpc_id = module.params['vpc_id'] rules = deduplicate_rules_args( rules_expand_sources(rules_expand_ports(module.params['rules']))) rules_egress = deduplicate_rules_args( rules_expand_sources(rules_expand_ports( module.params['rules_egress']))) state = module.params.get('state') purge_rules = module.params['purge_rules'] purge_rules_egress = module.params['purge_rules_egress'] tags = module.params['tags'] purge_tags = module.params['purge_tags'] if state == 'present' and not description: module.fail_json(msg='Must provide description when state is present.') changed = False region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) if not region: module.fail_json(msg="The AWS region must be specified as an " "environment variable or in the AWS credentials " "profile.") client = boto3_conn(module, conn_type='client', resource='ec2', endpoint=ec2_url, region=region, **aws_connect_params) if not has_rule_description_attr(client): all_rules = rules if rules else [] + rules_egress if rules_egress else [] if any('rule_desc' in rule for rule in all_rules): module.fail_json( msg= "Using rule descriptions requires botocore version >= 1.7.2.") group = None groups = dict() security_groups = [] # do get all security groups # find if the group is present try: response = get_security_groups_with_backoff(client) security_groups = response.get('SecurityGroups', []) except botocore.exceptions.NoCredentialsError as e: module.fail_json(msg="Error in describe_security_groups: %s" % "Unable to locate credentials", exception=traceback.format_exc()) except botocore.exceptions.ClientError as e: module.fail_json(msg="Error in describe_security_groups: %s" % e, exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) for sg in security_groups: groups[sg['GroupId']] = sg groupName = sg['GroupName'] if groupName in groups: # Prioritise groups from the current VPC # even if current VPC is EC2-Classic if groups[groupName].get('VpcId') == vpc_id: # Group saved already matches current VPC, change nothing pass elif vpc_id is None and groups[groupName].get('VpcId') is None: # We're in EC2 classic, and the group already saved is as well # No VPC groups can be used alongside EC2 classic groups pass else: # the current SG stored has no direct match, so we can replace it groups[groupName] = sg else: groups[groupName] = sg if group_id and sg['GroupId'] == group_id: group = sg elif groupName == name and (vpc_id is None or sg.get('VpcId') == vpc_id): group = sg # Ensure requested group is absent if state == 'absent': if group: # found a match, delete it try: if not module.check_mode: client.delete_security_group(GroupId=group['GroupId']) except botocore.exceptions.ClientError as e: module.fail_json( msg="Unable to delete security group '%s' - %s" % (group, e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) else: group = None changed = True else: # no match found, no changes required pass # Ensure requested group is present elif state == 'present': if group: # existing group if group['Description'] != description: module.warn( "Group description does not match existing group. Descriptions cannot be changed without deleting " "and re-creating the security group. Try using state=absent to delete, then rerunning this task." ) # if the group doesn't exist, create it now else: # no match found, create it if not module.check_mode: params = dict(GroupName=name, Description=description) if vpc_id: params['VpcId'] = vpc_id group = client.create_security_group(**params) # When a group is created, an egress_rule ALLOW ALL # to 0.0.0.0/0 is added automatically but it's not # reflected in the object returned by the AWS API # call. We re-read the group for getting an updated object # amazon sometimes takes a couple seconds to update the security group so wait till it exists while True: group = get_security_groups_with_backoff( client, GroupIds=[group['GroupId']])['SecurityGroups'][0] if group.get( 'VpcId') and not group.get('IpPermissionsEgress'): pass else: break changed = True if tags is not None: current_tags = boto3_tag_list_to_ansible_dict(group.get( 'Tags', [])) tags_need_modify, tags_to_delete = compare_aws_tags( current_tags, tags, purge_tags) if tags_to_delete: try: client.delete_tags(Resources=[group['GroupId']], Tags=[{ 'Key': tag } for tag in tags_to_delete]) except botocore.exceptions.ClientError as e: module.fail_json(msg=e.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) changed = True # Add/update tags if tags_need_modify: try: client.create_tags( Resources=[group['GroupId']], Tags=ansible_dict_to_boto3_tag_list(tags_need_modify)) except botocore.exceptions.ClientError as e: module.fail_json(msg=e.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) changed = True else: module.fail_json(msg="Unsupported state requested: %s" % state) # create a lookup for all existing rules on the group ip_permission = [] if group: # Manage ingress rules groupRules = {} add_rules_to_lookup(group['IpPermissions'], group['GroupId'], 'in', groupRules) # Now, go through all provided rules and ensure they are there. if rules is not None: for rule in rules: validate_rule(module, rule) group_id, ip, ipv6, target_group_created = get_target_from_rule( module, client, rule, name, group, groups, vpc_id) if target_group_created: changed = True if rule['proto'] in ('all', '-1', -1): rule['proto'] = -1 rule['from_port'] = None rule['to_port'] = None if group_id: rule_id = make_rule_key('in', rule, group['GroupId'], group_id) if rule_id in groupRules: changed = check_rule_desc_update_for_group_grant( client, module, rule, group, groupRules, rule_id, group_id, rule_type='in', changed=changed) del groupRules[rule_id] else: if not module.check_mode: ip_permission = serialize_group_grant( group_id, rule) if ip_permission: ips = ip_permission if vpc_id: [ useridpair.update({'VpcId': vpc_id}) for useridpair in ip_permission.get( 'UserIdGroupPairs', []) ] try: client.authorize_security_group_ingress( GroupId=group['GroupId'], IpPermissions=[ips]) except botocore.exceptions.ClientError as e: module.fail_json( msg= "Unable to authorize ingress for group %s security group '%s' - %s" % (group_id, group['GroupName'], e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) changed = True elif ip: # Convert ip to list we can iterate over if ip and not isinstance(ip, list): ip = [ip] changed, ip_permission = authorize_ip( "in", changed, client, group, groupRules, ip, ip_permission, module, rule, "ipv4") elif ipv6: # Convert ip to list we can iterate over if not isinstance(ipv6, list): ipv6 = [ipv6] # If rule already exists, don't later delete it changed, ip_permission = authorize_ip( "in", changed, client, group, groupRules, ipv6, ip_permission, module, rule, "ipv6") # Finally, remove anything left in the groupRules -- these will be defunct rules if purge_rules: for (rule, grant) in groupRules.values(): ip_permission = serialize_revoke(grant, rule) if not module.check_mode: try: client.revoke_security_group_ingress( GroupId=group['GroupId'], IpPermissions=[ip_permission]) except botocore.exceptions.ClientError as e: module.fail_json( msg= "Unable to revoke ingress for security group '%s' - %s" % (group['GroupName'], e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) changed = True # Manage egress rules groupRules = {} add_rules_to_lookup(group['IpPermissionsEgress'], group['GroupId'], 'out', groupRules) # Now, go through all provided rules and ensure they are there. if rules_egress is not None: for rule in rules_egress: validate_rule(module, rule) group_id, ip, ipv6, target_group_created = get_target_from_rule( module, client, rule, name, group, groups, vpc_id) if target_group_created: changed = True if rule['proto'] in ('all', '-1', -1): rule['proto'] = -1 rule['from_port'] = None rule['to_port'] = None if group_id: rule_id = make_rule_key('out', rule, group['GroupId'], group_id) if rule_id in groupRules: changed = check_rule_desc_update_for_group_grant( client, module, rule, group, groupRules, rule_id, group_id, rule_type='out', changed=changed) del groupRules[rule_id] else: if not module.check_mode: ip_permission = serialize_group_grant( group_id, rule) if ip_permission: ips = ip_permission if vpc_id: [ useridpair.update({'VpcId': vpc_id}) for useridpair in ip_permission.get( 'UserIdGroupPairs', []) ] try: client.authorize_security_group_egress( GroupId=group['GroupId'], IpPermissions=[ips]) except botocore.exceptions.ClientError as e: module.fail_json( msg= "Unable to authorize egress for group %s security group '%s' - %s" % (group_id, group['GroupName'], e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) changed = True elif ip: # Convert ip to list we can iterate over if not isinstance(ip, list): ip = [ip] changed, ip_permission = authorize_ip( "out", changed, client, group, groupRules, ip, ip_permission, module, rule, "ipv4") elif ipv6: # Convert ip to list we can iterate over if not isinstance(ipv6, list): ipv6 = [ipv6] # If rule already exists, don't later delete it changed, ip_permission = authorize_ip( "out", changed, client, group, groupRules, ipv6, ip_permission, module, rule, "ipv6") elif vpc_id is not None: # when no egress rules are specified and we're in a VPC, # we add in a default allow all out rule, which was the # default behavior before egress rules were added default_egress_rule = 'out--1-None-None-' + group[ 'GroupId'] + '-0.0.0.0/0' if default_egress_rule not in groupRules: if not module.check_mode: ip_permission = [{ 'IpProtocol': '-1', 'IpRanges': [{ 'CidrIp': '0.0.0.0/0' }] }] try: client.authorize_security_group_egress( GroupId=group['GroupId'], IpPermissions=ip_permission) except botocore.exceptions.ClientError as e: module.fail_json( msg= "Unable to authorize egress for ip %s security group '%s' - %s" % ('0.0.0.0/0', group['GroupName'], e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) changed = True else: # make sure the default egress rule is not removed del groupRules[default_egress_rule] # Finally, remove anything left in the groupRules -- these will be defunct rules if purge_rules_egress and vpc_id is not None: for (rule, grant) in groupRules.values(): # we shouldn't be revoking 0.0.0.0 egress if grant != '0.0.0.0/0': ip_permission = serialize_revoke(grant, rule) if not module.check_mode: try: client.revoke_security_group_egress( GroupId=group['GroupId'], IpPermissions=[ip_permission]) except botocore.exceptions.ClientError as e: module.fail_json( msg= "Unable to revoke egress for ip %s security group '%s' - %s" % (grant, group['GroupName'], e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) changed = True if group: security_group = get_security_groups_with_backoff( client, GroupIds=[group['GroupId']])['SecurityGroups'][0] security_group = camel_dict_to_snake_dict(security_group) security_group['tags'] = boto3_tag_list_to_ansible_dict( security_group.get('tags', []), tag_name_key_name='key', tag_value_key_name='value') module.exit_json(changed=changed, **security_group) else: module.exit_json(changed=changed, group_id=None)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict(bucket=dict(required=True), dest=dict(default=None), encrypt=dict(default=True, type='bool'), expiry=dict(default=600, type='int', aliases=['expiration']), headers=dict(type='dict'), marker=dict(default=""), max_keys=dict(default=1000, type='int'), metadata=dict(type='dict'), mode=dict(choices=[ 'get', 'put', 'delete', 'create', 'geturl', 'getstr', 'delobj', 'list' ], required=True), object=dict(), permission=dict(type='list', default=['private']), version=dict(default=None), overwrite=dict(aliases=['force'], default='always'), prefix=dict(default=""), retries=dict(aliases=['retry'], type='int', default=0), s3_url=dict(aliases=['S3_URL']), rgw=dict(default='no', type='bool'), src=dict(), ignore_nonexistent_bucket=dict(default=False, type='bool')), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) if module._name == 's3': module.deprecate("The 's3' module is being renamed 'aws_s3'", version=2.7) if not HAS_BOTO3: module.fail_json(msg='boto3 and botocore required for this module') bucket = module.params.get('bucket') encrypt = module.params.get('encrypt') expiry = module.params.get('expiry') dest = module.params.get('dest', '') headers = module.params.get('headers') marker = module.params.get('marker') max_keys = module.params.get('max_keys') metadata = module.params.get('metadata') mode = module.params.get('mode') obj = module.params.get('object') version = module.params.get('version') overwrite = module.params.get('overwrite') prefix = module.params.get('prefix') retries = module.params.get('retries') s3_url = module.params.get('s3_url') rgw = module.params.get('rgw') src = module.params.get('src') ignore_nonexistent_bucket = module.params.get('ignore_nonexistent_bucket') if dest: dest = os.path.expanduser(dest) object_canned_acl = [ "private", "public-read", "public-read-write", "aws-exec-read", "authenticated-read", "bucket-owner-read", "bucket-owner-full-control" ] bucket_canned_acl = [ "private", "public-read", "public-read-write", "authenticated-read" ] if overwrite not in ['always', 'never', 'different']: if module.boolean(overwrite): overwrite = 'always' else: overwrite = 'never' region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) if region in ('us-east-1', '', None): # default to US Standard region location = 'us-east-1' else: # Boto uses symbolic names for locations but region strings will # actually work fine for everything except us-east-1 (US Standard) location = region if module.params.get('object'): obj = module.params['object'] # If there is a top level object, do nothing - if the object starts with / # remove the leading character to maintain compatibility with Ansible versions < 2.4 if obj.startswith('/'): obj = obj[1:] # Bucket deletion does not require obj. Prevents ambiguity with delobj. if obj and mode == "delete": module.fail_json(msg='Parameter obj cannot be used with mode=delete') # allow eucarc environment variables to be used if ansible vars aren't set if not s3_url and 'S3_URL' in os.environ: s3_url = os.environ['S3_URL'] # rgw requires an explicit url if rgw and not s3_url: module.fail_json(msg='rgw flavour requires s3_url') # Look at s3_url and tweak connection settings # if connecting to RGW, Walrus or fakes3 if s3_url: for key in ['validate_certs', 'security_token', 'profile_name']: aws_connect_kwargs.pop(key, None) try: s3 = get_s3_connection(module, aws_connect_kwargs, location, rgw, s3_url) except (botocore.exceptions.NoCredentialsError, botocore.exceptions.ProfileNotFound) as e: module.fail_json( msg= "Can't authorize connection. Check your credentials and profile.", exceptions=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) validate = not ignore_nonexistent_bucket # separate types of ACLs bucket_acl = [ acl for acl in module.params.get('permission') if acl in bucket_canned_acl ] object_acl = [ acl for acl in module.params.get('permission') if acl in object_canned_acl ] error_acl = [ acl for acl in module.params.get('permission') if acl not in bucket_canned_acl and acl not in object_canned_acl ] if error_acl: module.fail_json(msg='Unknown permission specified: %s' % error_acl) # First, we check to see if the bucket exists, we get "bucket" returned. bucketrtn = bucket_check(module, s3, bucket, validate=validate) if validate and mode not in ('create', 'put', 'delete') and not bucketrtn: module.fail_json(msg="Source bucket cannot be found.") # If our mode is a GET operation (download), go through the procedure as appropriate ... if mode == 'get': # Next, we check to see if the key in the bucket exists. If it exists, it also returns key_matches md5sum check. keyrtn = key_check(module, s3, bucket, obj, version=version, validate=validate) if keyrtn is False: module.fail_json(msg="Key %s with version id %s does not exist." % (obj, version)) # If the destination path doesn't exist or overwrite is True, no need to do the md5um etag check, so just download. # Compare the remote MD5 sum of the object with the local dest md5sum, if it already exists. if path_check(dest): # Determine if the remote and local object are identical if keysum(module, s3, bucket, obj, version=version) == module.md5(dest): sum_matches = True if overwrite == 'always': download_s3file(module, s3, bucket, obj, dest, retries, version=version) else: module.exit_json( msg= "Local and remote object are identical, ignoring. Use overwrite=always parameter to force.", changed=False) else: sum_matches = False if overwrite in ('always', 'different'): download_s3file(module, s3, bucket, obj, dest, retries, version=version) else: module.exit_json( msg= "WARNING: Checksums do not match. Use overwrite parameter to force download." ) else: download_s3file(module, s3, bucket, obj, dest, retries, version=version) # if our mode is a PUT operation (upload), go through the procedure as appropriate ... if mode == 'put': # if putting an object in a bucket yet to be created, acls for the bucket and/or the object may be specified # these were separated into the variables bucket_acl and object_acl above # Lets check the src path. if not path_check(src): module.fail_json(msg="Local object for PUT does not exist") # Lets check to see if bucket exists to get ground truth. if bucketrtn: keyrtn = key_check(module, s3, bucket, obj, version=version, validate=validate) # Lets check key state. Does it exist and if it does, compute the etag md5sum. if bucketrtn and keyrtn: # Compare the local and remote object if module.md5(src) == keysum(module, s3, bucket, obj): sum_matches = True if overwrite == 'always': # only use valid object acls for the upload_s3file function module.params['permission'] = object_acl upload_s3file(module, s3, bucket, obj, src, expiry, metadata, encrypt, headers) else: get_download_url(module, s3, bucket, obj, expiry, changed=False) else: sum_matches = False if overwrite in ('always', 'different'): # only use valid object acls for the upload_s3file function module.params['permission'] = object_acl upload_s3file(module, s3, bucket, obj, src, expiry, metadata, encrypt, headers) else: module.exit_json( msg= "WARNING: Checksums do not match. Use overwrite parameter to force upload." ) # If neither exist (based on bucket existence), we can create both. if not bucketrtn: # only use valid bucket acls for create_bucket function module.params['permission'] = bucket_acl create_bucket(module, s3, bucket, location) # only use valid object acls for the upload_s3file function module.params['permission'] = object_acl upload_s3file(module, s3, bucket, obj, src, expiry, metadata, encrypt, headers) # If bucket exists but key doesn't, just upload. if bucketrtn and not keyrtn: # only use valid object acls for the upload_s3file function module.params['permission'] = object_acl upload_s3file(module, s3, bucket, obj, src, expiry, metadata, encrypt, headers) # Delete an object from a bucket, not the entire bucket if mode == 'delobj': if obj is None: module.fail_json(msg="object parameter is required") if bucket: deletertn = delete_key(module, s3, bucket, obj) if deletertn is True: module.exit_json(msg="Object deleted from bucket %s." % bucket, changed=True) else: module.fail_json(msg="Bucket parameter is required.") # Delete an entire bucket, including all objects in the bucket if mode == 'delete': if bucket: deletertn = delete_bucket(module, s3, bucket) if deletertn is True: module.exit_json( msg="Bucket %s and all keys have been deleted." % bucket, changed=True) else: module.fail_json(msg="Bucket parameter is required.") # Support for listing a set of keys if mode == 'list': exists = bucket_check(module, s3, bucket) # If the bucket does not exist then bail out if not exists: module.fail_json(msg="Target bucket (%s) cannot be found" % bucket) list_keys(module, s3, bucket, prefix, marker, max_keys) # Need to research how to create directories without "populating" a key, so this should just do bucket creation for now. # WE SHOULD ENABLE SOME WAY OF CREATING AN EMPTY KEY TO CREATE "DIRECTORY" STRUCTURE, AWS CONSOLE DOES THIS. if mode == 'create': # if both creating a bucket and putting an object in it, acls for the bucket and/or the object may be specified # these were separated above into the variables bucket_acl and object_acl if bucket and not obj: if bucketrtn: module.exit_json(msg="Bucket already exists.", changed=False) else: # only use valid bucket acls when creating the bucket module.params['permission'] = bucket_acl module.exit_json(msg="Bucket created successfully", changed=create_bucket(module, s3, bucket, location)) if bucket and obj: if obj.endswith('/'): dirobj = obj else: dirobj = obj + "/" if bucketrtn: if key_check(module, s3, bucket, dirobj): module.exit_json( msg="Bucket %s and key %s already exists." % (bucket, obj), changed=False) else: # setting valid object acls for the create_dirkey function module.params['permission'] = object_acl create_dirkey(module, s3, bucket, dirobj) else: # only use valid bucket acls for the create_bucket function module.params['permission'] = bucket_acl created = create_bucket(module, s3, bucket, location) # only use valid object acls for the create_dirkey function module.params['permission'] = object_acl create_dirkey(module, s3, bucket, dirobj) # Support for grabbing the time-expired URL for an object in S3/Walrus. if mode == 'geturl': if not bucket and not obj: module.fail_json(msg="Bucket and Object parameters must be set") keyrtn = key_check(module, s3, bucket, obj, version=version, validate=validate) if keyrtn: get_download_url(module, s3, bucket, obj, expiry) else: module.fail_json(msg="Key %s does not exist." % obj) if mode == 'getstr': if bucket and obj: keyrtn = key_check(module, s3, bucket, obj, version=version, validate=validate) if keyrtn: download_s3str(module, s3, bucket, obj, version=version) elif version is not None: module.fail_json( msg="Key %s with version id %s does not exist." % (obj, version)) else: module.fail_json(msg="Key %s does not exist." % obj) module.exit_json(failed=False)
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 1GB. 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: 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))
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict(name=dict(), group_id=dict(), description=dict(), vpc_id=dict(), rules=dict(type='list'), rules_egress=dict(type='list'), state=dict(default='present', type='str', choices=['present', 'absent']), purge_rules=dict(default=True, required=False, type='bool'), purge_rules_egress=dict(default=True, required=False, type='bool'))) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, required_one_of=[['name', 'group_id']], required_if=[['state', 'present', ['name']]], ) if not HAS_BOTO3: module.fail_json(msg='boto3 required for this module') name = module.params['name'] group_id = module.params['group_id'] description = module.params['description'] vpc_id = module.params['vpc_id'] rules = deduplicate_rules_args( rules_expand_sources(rules_expand_ports(module.params['rules']))) rules_egress = deduplicate_rules_args( rules_expand_sources(rules_expand_ports( module.params['rules_egress']))) state = module.params.get('state') purge_rules = module.params['purge_rules'] purge_rules_egress = module.params['purge_rules_egress'] if state == 'present' and not description: module.fail_json(msg='Must provide description when state is present.') changed = False region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) if not region: module.fail_json(msg="The AWS region must be specified as an " "environment variable or in the AWS credentials " "profile.") client, ec2 = boto3_conn(module, conn_type='both', resource='ec2', endpoint=ec2_url, region=region, **aws_connect_params) group = None groups = dict() security_groups = [] # do get all security groups # find if the group is present try: response = client.describe_security_groups() if 'SecurityGroups' in response: security_groups = response.get('SecurityGroups') except botocore.exceptions.NoCredentialsError as e: module.fail_json(msg="Error in describe_security_groups: %s" % "Unable to locate credentials", exception=traceback.format_exc()) except botocore.exceptions.ClientError as e: module.fail_json(msg="Error in describe_security_groups: %s" % e, exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) for sg in security_groups: curGroup = ec2.SecurityGroup(sg['GroupId']) groups[curGroup.id] = ec2.SecurityGroup(curGroup.id) groupName = curGroup.group_name if groupName in groups: # Prioritise groups from the current VPC if vpc_id is None or curGroup.vpc_id == vpc_id: groups[groupName] = curGroup else: groups[groupName] = curGroup if group_id: if curGroup.id == group_id: group = curGroup else: if groupName == name and (vpc_id is None or curGroup.vpc_id == vpc_id): group = curGroup # Ensure requested group is absent if state == 'absent': if group: # found a match, delete it try: if not module.check_mode: group.delete() except botocore.exceptions.ClientError as e: module.fail_json( msg="Unable to delete security group '%s' - %s" % (group, e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) else: group = None changed = True else: # no match found, no changes required pass # Ensure requested group is present elif state == 'present': if group: # existing group if group.description != description: module.fail_json( msg= "Group description does not match existing group. ec2_group does not support this case." ) # if the group doesn't exist, create it now else: # no match found, create it if not module.check_mode: group = client.create_security_group(GroupName=name, Description=description) groupId = group.get('GroupId') # When a group is created, an egress_rule ALLOW ALL # to 0.0.0.0/0 is added automatically but it's not # reflected in the object returned by the AWS API # call. We re-read the group for getting an updated object # amazon sometimes takes a couple seconds to update the security group so wait till it exists while len( client.describe_security_groups(GroupIds=[groupId]) ['SecurityGroups'][0]['IpPermissionsEgress']) == 0: time.sleep(0.1) group = ec2.SecurityGroup(groupId) changed = True else: module.fail_json(msg="Unsupported state requested: %s" % state) # create a lookup for all existing rules on the group if group: # Manage ingress rules groupRules = {} add_rules_to_loopkup(group.ip_permissions, group.id, 'in', groupRules) # Now, go through all provided rules and ensure they are there. if rules is not None: ip_permission = [] for rule in rules: validate_rule(module, rule) group_id, ip, ipv6, target_group_created = get_target_from_rule( module, ec2, rule, name, group, groups, vpc_id) if target_group_created: changed = True if rule['proto'] in ('all', '-1', -1): rule['proto'] = -1 rule['from_port'] = None rule['to_port'] = None if group_id: rule_id = make_rule_key('in', rule, group.id, group_id) if rule_id in groupRules: del groupRules[rule_id] else: if not module.check_mode: ip_permission = serialize_group_grant( group_id, rule) if ip_permission: ips = ip_permission if vpc_id: [ useridpair.update({'VpcId': vpc_id}) for useridpair in ip_permission.get( 'UserIdGroupPairs') ] try: client.authorize_security_group_ingress( GroupId=group.group_id, IpPermissions=[ips]) except botocore.exceptions.ClientError as e: module.fail_json( msg= "Unable to authorize ingress for group %s security group '%s' - %s" % (group_id, group.group_name, e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) changed = True elif ip: # Convert ip to list we can iterate over if ip and not isinstance(ip, list): ip = [ip] changed, ip_permission = authorize_ip( "in", changed, client, group, groupRules, ip, ip_permission, module, rule, "ipv4") elif ipv6: # Convert ip to list we can iterate over if not isinstance(ipv6, list): ipv6 = [ipv6] # If rule already exists, don't later delete it changed, ip_permission = authorize_ip( "in", changed, client, group, groupRules, ipv6, ip_permission, module, rule, "ipv6") # Finally, remove anything left in the groupRules -- these will be defunct rules if purge_rules: for (rule, grant) in groupRules.values(): ip_permission = serialize_revoke(grant, rule) if not module.check_mode: try: client.revoke_security_group_ingress( GroupId=group.group_id, IpPermissions=[ip_permission]) except botocore.exceptions.ClientError as e: module.fail_json( msg= "Unable to revoke ingress for security group '%s' - %s" % (group.group_name, e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) changed = True # Manage egress rules groupRules = {} add_rules_to_loopkup(group.ip_permissions_egress, group.id, 'out', groupRules) # Now, go through all provided rules and ensure they are there. if rules_egress is not None: for rule in rules_egress: validate_rule(module, rule) group_id, ip, ipv6, target_group_created = get_target_from_rule( module, ec2, rule, name, group, groups, vpc_id) if target_group_created: changed = True if rule['proto'] in ('all', '-1', -1): rule['proto'] = -1 rule['from_port'] = None rule['to_port'] = None if group_id: rule_id = make_rule_key('out', rule, group.id, group_id) if rule_id in groupRules: del groupRules[rule_id] else: if not module.check_mode: ip_permission = serialize_group_grant( group_id, rule) if ip_permission: ips = ip_permission if vpc_id: [ useridpair.update({'VpcId': vpc_id}) for useridpair in ip_permission.get( 'UserIdGroupPairs') ] try: client.authorize_security_group_egress( GroupId=group.group_id, IpPermissions=[ips]) except botocore.exceptions.ClientError as e: module.fail_json( msg= "Unable to authorize egress for group %s security group '%s' - %s" % (group_id, group.group_name, e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) changed = True elif ip: # Convert ip to list we can iterate over if not isinstance(ip, list): ip = [ip] changed, ip_permission = authorize_ip( "out", changed, client, group, groupRules, ip, ip_permission, module, rule, "ipv4") elif ipv6: # Convert ip to list we can iterate over if not isinstance(ipv6, list): ipv6 = [ipv6] # If rule already exists, don't later delete it changed, ip_permission = authorize_ip( "out", changed, client, group, groupRules, ipv6, ip_permission, module, rule, "ipv6") else: # when no egress rules are specified, # we add in a default allow all out rule, which was the # default behavior before egress rules were added default_egress_rule = 'out--1-None-None-' + group.id + '-0.0.0.0/0' if default_egress_rule not in groupRules: if not module.check_mode: ip_permission = [{ 'IpProtocol': '-1', 'IpRanges': [{ 'CidrIp': '0.0.0.0/0' }] }] try: client.authorize_security_group_egress( GroupId=group.group_id, IpPermissions=ip_permission) except botocore.exceptions.ClientError as e: module.fail_json( msg= "Unable to authorize egress for ip %s security group '%s' - %s" % ('0.0.0.0/0', group.group_name, e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) changed = True else: # make sure the default egress rule is not removed del groupRules[default_egress_rule] # Finally, remove anything left in the groupRules -- these will be defunct rules if purge_rules_egress: for (rule, grant) in groupRules.values(): # we shouldn't be revoking 0.0.0.0 egress if grant != '0.0.0.0/0': ip_permission = serialize_revoke(grant, rule) if not module.check_mode: try: client.revoke_security_group_egress( GroupId=group.group_id, IpPermissions=[ip_permission]) except botocore.exceptions.ClientError as e: module.fail_json( msg= "Unable to revoke egress for ip %s security group '%s' - %s" % (grant, group.group_name, e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) changed = True if group: module.exit_json(changed=changed, group_id=group.id) else: module.exit_json(changed=changed, group_id=None)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( group_family=dict(type='str', choices=['memcached1.4', 'redis2.6', 'redis2.8', 'redis3.2']), name=dict(required=True, type='str'), description=dict(type='str'), state=dict(required=True), values=dict(type='dict'), ) ) module = AnsibleModule(argument_spec=argument_spec) if not HAS_BOTO3: module.fail_json(msg='boto required for this module') parameter_group_family = module.params.get('group_family') parameter_group_name = module.params.get('name') group_description = module.params.get('description') state = module.params.get('state') values = module.params.get('values') # Retrieve any AWS settings from the environment. region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) if not region: module.fail_json(msg="Either region or AWS_REGION or EC2_REGION environment variable or boto config aws_region or ec2_region must be set.") connection = boto3_conn(module, conn_type='client', resource='elasticache', region=region, endpoint=ec2_url, **aws_connect_kwargs) exists = get_info(connection, parameter_group_name) # check that the needed requirements are available if state == 'present' and not (exists and parameter_group_family and group_description): module.fail_json(msg="Creating a group requires a family group and a description.") elif state == 'reset' and not exists: module.fail_json(msg="No group %s to reset. Please create the group before using the state 'reset'." % parameter_group_name) # Taking action changed = False if state == 'present': if exists: # confirm that the group exists without any actions if not values: response = exists changed = False # modify existing group else: modifiable_params = make_current_modifiable_param_dict(module, connection, parameter_group_name) changed = check_valid_modification(module, values, modifiable_params) response = modify(module, connection, parameter_group_name, values) # create group else: response, changed = create(module, connection, parameter_group_name, parameter_group_family, group_description) if values: modifiable_params = make_current_modifiable_param_dict(module, connection, parameter_group_name) changed = check_valid_modification(module, values, modifiable_params) response = modify(module, connection, parameter_group_name, values) elif state == 'absent': if exists: # delete group response, changed = delete(module, connection, parameter_group_name) else: response = {} changed = False elif state == 'reset': response, changed = reset(module, connection, parameter_group_name, values) facts_result = dict(changed=changed, elasticache=camel_dict_to_snake_dict(response)) module.exit_json(**facts_result)
def resource(self, service): region, ec2_url, aws_connect_kwargs = get_aws_connection_info(self, boto3=True) return boto3_conn(self, conn_type='resource', resource=service, region=region, endpoint=ec2_url, **aws_connect_kwargs)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict(state=dict(required=True, choices=['present', 'absent']), name=dict(), location=dict(), bandwidth=dict(choices=['1Gbps', '10Gbps']), link_aggregation_group=dict(), connection_id=dict(), forced_update=dict(type='bool', default=False))) module = AnsibleModule(argument_spec=argument_spec, required_one_of=[('connection_id', 'name')], required_if=[('state', 'present', ('location', 'bandwidth'))]) if not HAS_BOTO3: module.fail_json(msg='boto3 required for this module') region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) if not region: module.fail_json( msg= "Either region or AWS_REGION or EC2_REGION environment variable or boto config aws_region or ec2_region must be set." ) connection = boto3_conn(module, conn_type='client', resource='directconnect', region=region, endpoint=ec2_url, **aws_connect_kwargs) connection_id = connection_exists( connection, connection_id=module.params.get('connection_id'), connection_name=module.params.get('name')) if not connection_id and module.params.get('connection_id'): module.fail_json( msg="The Direct Connect connection {0} does not exist.".format( module.params.get('connection_id'))) state = module.params.get('state') try: if state == 'present': changed, connection_id = ensure_present( connection, connection_id=connection_id, connection_name=module.params.get('name'), location=module.params.get('location'), bandwidth=module.params.get('bandwidth'), lag_id=module.params.get('link_aggregation_group'), forced_update=module.params.get('forced_update')) response = connection_status(connection, connection_id) elif state == 'absent': changed = ensure_absent(connection, connection_id) response = {} except DirectConnectError as e: if e.last_traceback: module.fail_json(msg=e.msg, exception=e.last_traceback, **camel_dict_to_snake_dict(e.exception.response)) else: module.fail_json(msg=e.msg) module.exit_json(changed=changed, **camel_dict_to_snake_dict(response))
def main(): """ Module action handler """ argument_spec = ec2_argument_spec() argument_spec.update(dict( encrypt=dict(required=False, type="bool", default=False), state=dict(required=False, type='str', choices=["present", "absent"], default="present"), kms_key_id=dict(required=False, type='str', default=None), purge_tags=dict(default=True, type='bool'), id=dict(required=False, type='str', default=None), name=dict(required=False, type='str', default=None), tags=dict(required=False, type="dict", default={}), targets=dict(required=False, type="list", default=[]), performance_mode=dict(required=False, type='str', choices=["general_purpose", "max_io"], default="general_purpose"), throughput_mode=dict(required=False, type='str', choices=["bursting", "provisioned"], default=None), provisioned_throughput_in_mibps=dict(required=False, type='float'), wait=dict(required=False, type="bool", default=False), wait_timeout=dict(required=False, type="int", default=0) )) module = AnsibleModule(argument_spec=argument_spec) if not HAS_BOTO3: module.fail_json(msg='boto3 required for this module') region, _, aws_connect_params = get_aws_connection_info(module, boto3=True) connection = EFSConnection(module, region, **aws_connect_params) name = module.params.get('name') fs_id = module.params.get('id') tags = module.params.get('tags') target_translations = { 'ip_address': 'IpAddress', 'security_groups': 'SecurityGroups', 'subnet_id': 'SubnetId' } targets = [dict((target_translations[key], value) for (key, value) in x.items()) for x in module.params.get('targets')] performance_mode_translations = { 'general_purpose': 'generalPurpose', 'max_io': 'maxIO' } encrypt = module.params.get('encrypt') kms_key_id = module.params.get('kms_key_id') performance_mode = performance_mode_translations[module.params.get('performance_mode')] purge_tags = module.params.get('purge_tags') throughput_mode = module.params.get('throughput_mode') provisioned_throughput_in_mibps = module.params.get('provisioned_throughput_in_mibps') state = str(module.params.get('state')).lower() changed = False if state == 'present': if not name: module.fail_json(msg='Name parameter is required for create') changed = connection.create_file_system(name, performance_mode, encrypt, kms_key_id, throughput_mode, provisioned_throughput_in_mibps) if connection.supports_provisioned_mode(): changed = connection.update_file_system(name, throughput_mode, provisioned_throughput_in_mibps) or changed changed = connection.converge_file_system(name=name, tags=tags, purge_tags=purge_tags, targets=targets, throughput_mode=throughput_mode, provisioned_throughput_in_mibps=provisioned_throughput_in_mibps) or changed result = first_or_default(connection.get_file_systems(CreationToken=name)) elif state == 'absent': if not name and not fs_id: module.fail_json(msg='Either name or id parameter is required for delete') changed = connection.delete_file_system(name, fs_id) result = None if result: result = camel_dict_to_snake_dict(result) module.exit_json(changed=changed, efs=result)
def client(self, service, retry_decorator=None): region, ec2_url, aws_connect_kwargs = get_aws_connection_info(self, boto3=True) conn = boto3_conn(self, conn_type='client', resource=service, region=region, endpoint=ec2_url, **aws_connect_kwargs) return conn if retry_decorator is None else _RetryingBotoClientWrapper(conn, retry_decorator)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( query=dict(choices=[ 'change', 'checker_ip_range', 'health_check', 'hosted_zone', 'record_sets', 'reusable_delegation_set', ], required=True), change_id=dict(), hosted_zone_id=dict(), max_items=dict(type='str'), next_marker=dict(), delegation_set_id=dict(), start_record_name=dict(), type=dict(choices=[ 'A', 'CNAME', 'MX', 'AAAA', 'TXT', 'PTR', 'SRV', 'SPF', 'CAA', 'NS' ]), dns_name=dict(), resource_id=dict(type='list', aliases=['resource_ids']), health_check_id=dict(), hosted_zone_method=dict( choices=['details', 'list', 'list_by_name', 'count', 'tags'], default='list'), health_check_method=dict(choices=[ 'list', 'details', 'status', 'failure_reason', 'count', 'tags', ], default='list'), )) module = AnsibleAWSModule( argument_spec=argument_spec, supports_check_mode=True, mutually_exclusive=[ ['hosted_zone_method', 'health_check_method'], ], ) resource_id = module.params.get('resource_id') if resource_id: if len(resource_id) > 1: module.fail_json( msg= 'Using multiple resource_ids is no longer supported. Use a loop' ) module.deprecate( 'resource_id is deprecated. Use hosted_zone_id or health_check_id', version=2.9) # inject proper parameters into module.params if module.params.get('query') == 'hosted_zone': module.params['hosted_zone_id'] = '/hostedzone/%s' % resource_id[0] if module.params.get('query') == 'health_check': module.params['health_check_id'] = resource_id[0] if module.params.get('health_check_method') == 'tags' or module.params.get( 'hosted_zone_method') == 'tags': module.deprecate( 'Using tags with health_check_method or hosted_zone_method is no longer necessary - use details instead', version=2.9) try: region, ec2_url, aws_connect_kwargs = get_aws_connection_info( module, boto3=True) route53 = boto3_conn(module, conn_type='client', resource='route53', region=region, endpoint=ec2_url, **aws_connect_kwargs) except botocore.exceptions.ProfileNotFound as e: module.fail_json_aws(e) invocations = { 'change': change_details, 'checker_ip_range': checker_ip_range_details, 'health_check': health_check_details, 'hosted_zone': hosted_zone_details, 'record_sets': record_sets_details, 'reusable_delegation_set': reusable_delegation_set_details, } results = invocations[module.params.get('query')](route53, module) # tidy up results for field in ['ResponseMetadata', 'MaxItems', 'IsTruncated']: if field in results: del (results[field]) tags = results.get('Tags') results = camel_dict_to_snake_dict(results) if tags is not None: results['tags'] = tags module.exit_json(**results)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( state=dict(required=True, choices=['present', 'absent']), group_name=dict(required=True, aliases=['name']), group_description=dict(required=False, aliases=['description']), group_subnets=dict(required=False, aliases=['subnets'], type='list'), )) module = AnsibleModule(argument_spec=argument_spec) if not HAS_BOTO: module.fail_json(msg='boto v2.9.0+ required for this module') state = module.params.get('state') group_name = module.params.get('group_name') group_description = module.params.get('group_description') group_subnets = module.params.get('group_subnets') if state == 'present': for required in ('group_name', 'group_description', 'group_subnets'): if not module.params.get(required): module.fail_json( msg=str("parameter %s required for state='present'" % required)) else: for not_allowed in ('group_description', 'group_subnets'): if module.params.get(not_allowed): module.fail_json( msg=str("parameter %s not allowed for state='absent'" % not_allowed)) region, ec2_url, aws_connect_params = get_aws_connection_info(module) if not region: module.fail_json(msg=str( "Region must be specified as a parameter, in EC2_REGION or AWS_REGION environment variables or in boto configuration file" )) # Connect to the Redshift endpoint. try: conn = connect_to_aws(boto.redshift, region, **aws_connect_params) except boto.exception.JSONResponseError as e: module.fail_json(msg=str(e)) try: changed = False exists = False group = None try: matching_groups = conn.describe_cluster_subnet_groups( group_name, max_records=100) exists = len(matching_groups) > 0 except boto.exception.JSONResponseError as e: if e.body['Error']['Code'] != 'ClusterSubnetGroupNotFoundFault': # if e.code != 'ClusterSubnetGroupNotFoundFault': module.fail_json(msg=str(e)) if state == 'absent': if exists: conn.delete_cluster_subnet_group(group_name) changed = True else: if not exists: new_group = conn.create_cluster_subnet_group( group_name, group_description, group_subnets) group = { 'name': new_group['CreateClusterSubnetGroupResponse'] ['CreateClusterSubnetGroupResult']['ClusterSubnetGroup'] ['ClusterSubnetGroupName'], 'vpc_id': new_group['CreateClusterSubnetGroupResponse'] ['CreateClusterSubnetGroupResult']['ClusterSubnetGroup'] ['VpcId'], } else: changed_group = conn.modify_cluster_subnet_group( group_name, group_subnets, description=group_description) group = { 'name': changed_group['ModifyClusterSubnetGroupResponse'] ['ModifyClusterSubnetGroupResult']['ClusterSubnetGroup'] ['ClusterSubnetGroupName'], 'vpc_id': changed_group['ModifyClusterSubnetGroupResponse'] ['ModifyClusterSubnetGroupResult']['ClusterSubnetGroup'] ['VpcId'], } changed = True except boto.exception.JSONResponseError as e: module.fail_json(msg=str(e)) module.exit_json(changed=changed, group=group)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict(az=dict(default=None, required=False), cidr=dict(default=None, required=True), state=dict(default='present', choices=['present', 'absent']), tags=dict(default={}, required=False, type='dict', aliases=['resource_tags']), vpc_id=dict(default=None, required=True), map_public=dict(default=False, required=False, type='bool'))) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) if not HAS_BOTO3: module.fail_json(msg='boto3 and botocore are required for this module') region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) if region: connection = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_params) else: module.fail_json(msg="region must be specified") vpc_id = module.params.get('vpc_id') tags = module.params.get('tags') cidr = module.params.get('cidr') az = module.params.get('az') state = module.params.get('state') map_public = module.params.get('map_public') try: if state == 'present': result = ensure_subnet_present(connection, module, vpc_id, cidr, az, tags, map_public, check_mode=module.check_mode) elif state == 'absent': result = ensure_subnet_absent(connection, module, vpc_id, cidr, check_mode=module.check_mode) except botocore.exceptions.ClientError as e: module.fail_json(msg=e.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) module.exit_json(**result)
def setup_client(module): region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) connection = boto3_conn(module, conn_type='client', resource='ssm', region=region, endpoint=ec2_url, **aws_connect_params) return connection