def main(): argument_spec = dict( state=dict(type='str', default='present', choices=['present', 'absent']), filters=dict(type='dict', default={}), vpn_gateway_id=dict(type='str'), tags=dict(default={}, type='dict'), connection_type=dict(default='ipsec.1', type='str'), tunnel_options=dict(no_log=True, type='list', default=[]), static_only=dict(default=False, type='bool'), customer_gateway_id=dict(type='str'), vpn_connection_id=dict(type='str'), purge_tags=dict(type='bool', default=False), routes=dict(type='list', default=[]), purge_routes=dict(type='bool', default=False), wait_timeout=dict(type='int', default=600), delay=dict(type='int', default=15), ) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) connection = module.client('ec2') state = module.params.get('state') parameters = dict(module.params) try: if state == 'present': changed, response = ensure_present(connection, parameters, module.check_mode) elif state == 'absent': changed, response = ensure_absent(connection, parameters, module.check_mode) except VPNConnectionException as e: if e.exception: module.fail_json_aws(e.exception, msg=e.msg) else: module.fail_json(msg=e.msg) module.exit_json(changed=changed, **camel_dict_to_snake_dict(response))
def main(): argument_spec = dict(instance_id=dict(), image_id=dict(), architecture=dict(default='x86_64'), kernel_id=dict(), virtualization_type=dict(default='hvm'), root_device_name=dict(), delete_snapshot=dict(default=False, type='bool'), name=dict(), wait=dict(type='bool', default=False), wait_timeout=dict(default=900, type='int'), description=dict(default=''), no_reboot=dict(default=False, type='bool'), state=dict(default='present', choices=['present', 'absent']), device_mapping=dict(type='list'), tags=dict(type='dict'), launch_permissions=dict(type='dict'), image_location=dict(), enhanced_networking=dict(type='bool'), billing_products=dict(type='list'), ramdisk_id=dict(), sriov_net_support=dict(), purge_tags=dict(type='bool', default=False)) module = AnsibleAWSModule(argument_spec=argument_spec, required_if=[ ['state', 'absent', ['image_id']], ]) # Using a required_one_of=[['name', 'image_id']] overrides the message that should be provided by # the required_if for state=absent, so check manually instead if not any([module.params['image_id'], module.params['name']]): module.fail_json( msg="one of the following is required: name, image_id") connection = module.client('ec2') if module.params.get('state') == 'absent': deregister_image(module, connection) elif module.params.get('state') == 'present': if module.params.get('image_id'): update_image(module, connection, module.params.get('image_id')) if not module.params.get('instance_id') and not module.params.get( 'device_mapping'): module.fail_json( msg= "The parameters instance_id or device_mapping (register from EBS snapshot) are required for a new image." ) create_image(module, connection)
def main(): argument_spec = dict( name=dict(required=True, type='str'), state=dict(default='present', choices=['present', 'absent']), strategy=dict(default='cluster', choices=['cluster', 'spread']) ) module = AnsibleAWSModule( argument_spec=argument_spec, supports_check_mode=True ) connection = module.client('ec2') state = module.params.get("state") if state == 'present': placement_group = get_placement_group_details(connection, module) if placement_group is None: create_placement_group(connection, module) else: strategy = module.params.get("strategy") if placement_group['strategy'] == strategy: module.exit_json( changed=False, placement_group=placement_group) else: name = module.params.get("name") module.fail_json( msg=("Placement group '{}' exists, can't change strategy" + " from '{}' to '{}'").format( name, placement_group['strategy'], strategy)) elif state == 'absent': placement_group = get_placement_group_details(connection, module) if placement_group is None: module.exit_json(changed=False) else: delete_placement_group(connection, module)
def main(): argument_spec = dict(name=dict(required=False), waf_regional=dict(type='bool', default=False)) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) if module._name == 'aws_waf_facts': module.deprecate( "The 'aws_waf_facts' module has been renamed to 'aws_waf_info'", version='2.13') resource = 'waf' if not module.params['waf_regional'] else 'waf-regional' client = module.client(resource) 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(name=dict(type='str'), state=dict(default='present', choices=['present', 'absent']), strategy=dict(default='cluster', choices=['cluster', 'spread']))) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) connection = boto3_conn(module, resource='ec2', conn_type='client', region=region, endpoint=ec2_url, **aws_connect_params) state = module.params.get("state") if state == 'present': placement_group = get_placement_group_details(connection, module) if placement_group is None: create_placement_group(connection, module) else: strategy = module.params.get("strategy") if placement_group['strategy'] == strategy: module.exit_json(changed=False, placement_group=placement_group) else: name = module.params.get("name") module.fail_json( msg=("Placement group '{}' exists, can't change strategy" + " from '{}' to '{}'" ).format(name, placement_group['strategy'], strategy)) elif state == 'absent': placement_group = get_placement_group_details(connection, module) if placement_group is None: module.exit_json(changed=False) else: delete_placement_group(connection, module)
def setup_module_object(): """ merge argument spec and create Ansible module object :return: Ansible module object """ argument_spec = dict( transit_gateway_ids=dict(type='list', default=[], elements='str', aliases=['transit_gateway_id']), filters=dict(type='dict', default={}) ) module = AnsibleAWSModule( argument_spec=argument_spec, supports_check_mode=True, ) return module
def main(): argument_spec = dict( resource=dict(required=True), ) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) resource = module.params['resource'] ec2 = module.client('ec2') try: current_tags = get_tags(ec2, module, resource) except (BotoCoreError, ClientError) as e: module.fail_json_aws(e, msg='Failed to fetch tags for resource {0}'.format(resource)) module.exit_json(changed=False, tags=current_tags)
def main(): event_types = ['s3:ObjectCreated:*', 's3:ObjectCreated:Put', 's3:ObjectCreated:Post', 's3:ObjectCreated:Copy', 's3:ObjectCreated:CompleteMultipartUpload', 's3:ObjectRemoved:*', 's3:ObjectRemoved:Delete', 's3:ObjectRemoved:DeleteMarkerCreated', 's3:ObjectRestore:Post', 's3:ObjectRestore:Completed', 's3:ReducedRedundancyLostObject'] argument_spec = dict( state=dict(default='present', choices=['present', 'absent']), event_name=dict(required=True), lambda_function_arn=dict(aliases=['function_arn']), bucket_name=dict(required=True), events=dict(type='list', default=[], choices=event_types), prefix=dict(default=''), suffix=dict(default=''), lambda_alias=dict(), lambda_version=dict(type='int', default=0), ) module = AnsibleAWSModule( argument_spec=argument_spec, supports_check_mode=True, mutually_exclusive=[['lambda_alias', 'lambda_version']], required_if=[['state', 'present', ['events']]] ) bucket = AmazonBucket(module.client('s3'), module.params['bucket_name']) current = bucket.current_config(module.params['event_name']) desired = Config.from_params(**module.params) notification_configuration = [cfg.raw for cfg in bucket.full_config()] state = module.params['state'] try: if (state == 'present' and current == desired) or (state == 'absent' and not current): changed = False elif module.check_mode: changed = True elif state == 'present': changed = True notification_configuration = bucket.apply_config(desired) elif state == 'absent': changed = True notification_configuration = bucket.delete_config(desired) except (ClientError, BotoCoreError) as e: module.fail_json(msg='{0}'.format(e)) module.exit_json(**dict(changed=changed, notification_configuration=[camel_dict_to_snake_dict(cfg) for cfg in notification_configuration]))
def main(): argument_spec = dict() result = dict(changed=False, original_message='') module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=False) cloudformation_client = module.client('cloudformation') try: result['export_items'] = list_exports(cloudformation_client) except (ClientError, BotoCoreError) as e: module.fail_json_aws(e) result.update() module.exit_json(**result)
def main(): argument_spec = dict( db_instance_identifier=dict(aliases=['id']), filters=dict(type='dict') ) module = AnsibleAWSModule( argument_spec=argument_spec, supports_check_mode=True, ) if module._name == 'rds_instance_facts': module.deprecate("The 'rds_instance_facts' module has been renamed to 'rds_instance_info'", version='2.13') conn = module.client('rds', retry_decorator=AWSRetry.jittered_backoff(retries=10)) module.exit_json(**instance_info(module, conn))
def main(): argument_spec = dict(name=dict(required=True), version=dict(), role_arn=dict(), subnets=dict(type='list'), security_groups=dict(type='list'), state=dict(choices=['absent', 'present'], default='present'), wait=dict(default=False, type='bool'), wait_timeout=dict(default=1200, type='int')) module = AnsibleAWSModule( argument_spec=argument_spec, required_if=[[ 'state', 'present', ['role_arn', 'subnets', 'security_groups'] ]], supports_check_mode=True, ) if not module.botocore_at_least("1.10.32"): module.fail_json( msg='aws_eks_cluster module requires botocore >= 1.10.32') if (not module.botocore_at_least("1.12.38") and module.params.get('state') == 'absent' and module.params.get('wait')): module.fail_json( msg= 'aws_eks_cluster: wait=yes when state=absent requires botocore >= 1.12.38' ) client = module.client('eks') if module.params.get('state') == 'present': ensure_present(client, module) else: ensure_absent(client, module)
def main(): argument_spec = dict( task_definition=dict(required=True, type='str') ) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) if module._name == 'ecs_taskdefinition_facts': module.deprecate("The 'ecs_taskdefinition_facts' module has been renamed to 'ecs_taskdefinition_info'", version='2.13') ecs = module.client('ecs') try: ecs_td = ecs.describe_task_definition(taskDefinition=module.params['task_definition'])['taskDefinition'] except botocore.exceptions.ClientError: ecs_td = {} module.exit_json(changed=False, **camel_dict_to_snake_dict(ecs_td))
def main(): argument_spec = dict( state=dict(required=True, choices=['present', 'absent']), id_to_associate=dict(required=True, aliases=['link_aggregation_group_id', 'connection_id']), public=dict(type='bool'), name=dict(), vlan=dict(type='int', default=100), bgp_asn=dict(type='int', default=65000), authentication_key=dict(), amazon_address=dict(), customer_address=dict(), address_type=dict(), cidr=dict(type='list'), virtual_gateway_id=dict(), virtual_interface_id=dict() ) module = AnsibleAWSModule(argument_spec=argument_spec, required_one_of=[['virtual_interface_id', 'name']], required_if=[['state', 'present', ['public']], ['public', False, ['virtual_gateway_id']], ['public', True, ['amazon_address']], ['public', True, ['customer_address']], ['public', True, ['cidr']]]) connection = module.client('directconnect') try: changed, latest_state = ensure_state(connection, module) except DirectConnectError as e: if e.exception: module.fail_json_aws(exception=e.exception, msg=e.msg) else: module.fail_json(msg=e.msg) module.exit_json(changed=changed, **camel_dict_to_snake_dict(latest_state))
def main(): argument_spec = dict(filters=dict(default={}, type='dict')) module = AnsibleAWSModule(argument_spec=argument_spec) if module._name == 'aws_region_facts': module.deprecate( "The 'aws_region_facts' module has been renamed to 'aws_region_info'", version='2.13') connection = module.client('ec2', retry_decorator=AWSRetry.jittered_backoff()) # Replace filter key underscores with dashes, for compatibility sanitized_filters = dict((k.replace('_', '-'), v) for k, v in module.params.get('filters').items()) try: regions = connection.describe_regions( Filters=ansible_dict_to_boto3_filter_list(sanitized_filters)) except (BotoCoreError, ClientError) as e: module.fail_json_aws(e, msg="Unable to describe regions.") module.exit_json( regions=[camel_dict_to_snake_dict(r) for r in regions['Regions']])
def main(): """ Module action handler """ argument_spec = dict( id=dict(), name=dict(aliases=['creation_token']), tags=dict(type="dict", default={}), targets=dict(type="list", default=[]) ) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) is_old_facts = module._name == 'efs_facts' if is_old_facts: module.deprecate("The 'efs_facts' module has been renamed to 'efs_info', " "and the renamed one no longer returns ansible_facts", version='2.13') connection = EFSConnection(module) 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)] file_systems_info = connection.get_mount_targets_data(file_systems_info) file_systems_info = connection.get_security_groups_data(file_systems_info) 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)] if is_old_facts: module.exit_json(changed=False, ansible_facts={'efs': file_systems_info}) else: module.exit_json(changed=False, efs=file_systems_info)
def main(): """ Module action handler """ argument_spec = dict( name=dict(aliases=['role_name']), path_prefix=dict(), ) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True, mutually_exclusive=[['name', 'path_prefix']]) if module._name == 'iam_role_facts': module.deprecate("The 'iam_role_facts' module has been renamed to 'iam_role_info'", version='2.13') client = module.client('iam') module.exit_json(changed=False, iam_roles=describe_iam_roles(module, client))
def main(): argument_spec = dict( zone=dict(required=True), state=dict(default='present', choices=['present', 'absent']), vpc_id=dict(default=None), vpc_region=dict(default=None), comment=dict(default=''), hosted_zone_id=dict(), delegation_set_id=dict(), ) mutually_exclusive = [ ['delegation_set_id', 'vpc_id'], ['delegation_set_id', 'vpc_region'], ] module = AnsibleAWSModule( argument_spec=argument_spec, mutually_exclusive=mutually_exclusive, supports_check_mode=True, ) zone_in = module.params.get('zone').lower() state = module.params.get('state').lower() vpc_id = module.params.get('vpc_id') vpc_region = module.params.get('vpc_region') if not zone_in.endswith('.'): zone_in += "." private_zone = bool(vpc_id and vpc_region) client = module.client('route53') zones = find_zones(module, client, zone_in, private_zone) if state == 'present': changed, result = create(module, client, matching_zones=zones) elif state == 'absent': changed, result = delete(module, client, matching_zones=zones) if isinstance(result, dict): module.exit_json(changed=changed, result=result, **result) else: module.exit_json(changed=changed, result=result)
def main(): argument_spec = dict(details=dict(type='bool', default=False), events=dict(type='bool', default=True), cluster=dict(), service=dict(type='list')) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) is_old_facts = module._name == 'ecs_service_facts' if is_old_facts: module.deprecate( "The 'ecs_service_facts' module has been renamed to 'ecs_service_info', " "and the renamed one no longer returns ansible_facts", version='2.13') show_details = module.params.get('details') task_mgr = EcsServiceManager(module) if show_details: if module.params['service']: services = module.params['service'] else: services = task_mgr.list_services( module.params['cluster'])['services'] ecs_info = dict(services=[], services_not_running=[]) for chunk in chunks(services, 10): running_services, services_not_running = task_mgr.describe_services( module.params['cluster'], chunk) ecs_info['services'].extend(running_services) ecs_info['services_not_running'].extend(services_not_running) else: ecs_info = task_mgr.list_services(module.params['cluster']) if is_old_facts: module.exit_json(changed=False, ansible_facts=ecs_info, **ecs_info) else: module.exit_json(changed=False, **ecs_info)
def main(): argument_spec = dict( name=dict(type='str'), tags=dict(type='dict'), ) module = AnsibleAWSModule(argument_spec=argument_spec) if module._name == 'ec2_asg_facts': module.deprecate( "The 'ec2_asg_facts' module has been renamed to 'ec2_asg_info'", version='2.13') asg_name = module.params.get('name') asg_tags = module.params.get('tags') autoscaling = module.client('autoscaling') results = find_asgs(autoscaling, module, name=asg_name, tags=asg_tags) module.exit_json(results=results)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( customer_gateway_ids=dict(default=[], type='list'), filters=dict(default={}, type='dict') ) ) module = AnsibleAWSModule(argument_spec=argument_spec, mutually_exclusive=[['customer_gateway_ids', 'filters']], supports_check_mode=True) if module._module._name == 'ec2_customer_gateway_facts': module._module.deprecate("The 'ec2_customer_gateway_facts' module has been renamed to 'ec2_customer_gateway_info'", version='2.13') 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) list_customer_gateways(connection, module)
def main(): argument_spec = dict( state=dict(type='str', default='present', choices=['present', 'absent']), name=dict(type='str', required=True), queue_type=dict(type='str', default='standard', choices=['standard', 'fifo']), delay_seconds=dict(type='int', aliases=['delivery_delay']), maximum_message_size=dict(type='int'), message_retention_period=dict(type='int'), policy=dict(type='dict'), receive_message_wait_time_seconds=dict( type='int', aliases=['receive_message_wait_time']), redrive_policy=dict(type='dict'), visibility_timeout=dict(type='int', aliases=['default_visibility_timeout']), kms_master_key_id=dict(type='str'), kms_data_key_reuse_period_seconds=dict( type='int', aliases=['kms_data_key_reuse_period']), content_based_deduplication=dict(type='bool'), tags=dict(type='dict'), purge_tags=dict(type='bool', default=False), ) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) state = module.params.get('state') retry_decorator = AWSRetry.jittered_backoff( catch_extra_error_codes=['AWS.SimpleQueueService.NonExistentQueue']) try: client = module.client('sqs', retry_decorator=retry_decorator) if state == 'present': result = create_or_update_sqs_queue(client, module) elif state == 'absent': result = delete_sqs_queue(client, module) except (BotoCoreError, ClientError, ParamValidationError) as e: module.fail_json_aws(e, msg='Failed to control sqs queue') else: module.exit_json(**result)
def main(): module = AnsibleAWSModule( argument_spec={ 'state': dict(choices=['present', 'absent'], required=True), 'min_pw_length': dict(type='int', aliases=['minimum_password_length'], default=6), 'require_symbols': dict(type='bool', default=False), 'require_numbers': dict(type='bool', default=False), 'require_uppercase': dict(type='bool', default=False), 'require_lowercase': dict(type='bool', default=False), 'allow_pw_change': dict(type='bool', aliases=['allow_password_change'], default=False), 'pw_max_age': dict(type='int', aliases=['password_max_age'], default=0), 'pw_reuse_prevent': dict(type='int', aliases=['password_reuse_prevent', 'prevent_reuse'], default=0), 'pw_expire': dict(type='bool', aliases=['password_expire', 'expire'], default=False), }, supports_check_mode=True, ) resource = IAMConnection(module) policy = resource.connection.AccountPasswordPolicy() state = module.params.get('state') if state == 'present': (changed, new_policy, update_result) = resource.update_password_policy(module, policy) module.exit_json(changed=changed, task_status={'IAM': update_result}, policy=new_policy) if state == 'absent': delete_result = resource.delete_password_policy(policy) module.exit_json(changed=True, task_status={'IAM': delete_result})
def setup_module_object(): argument_spec = dict( state=dict(default='present', choices=['present', 'absent']), function_name=dict(required=True, aliases=['lambda_function_arn', 'function_arn']), statement_id=dict(required=True, aliases=['sid']), alias=dict(), version=dict(type='int'), action=dict(required=True, ), principal=dict(required=True, ), source_arn=dict(), source_account=dict(), event_source_token=dict(), ) return AnsibleAWSModule( argument_spec=argument_spec, supports_check_mode=True, mutually_exclusive=[['alias', 'version'], ['event_source_token', 'source_arn'], ['event_source_token', 'source_account']], )
def main(): argument_spec = dict(gather_local_disks=dict(type='bool', default=True), gather_tapes=dict(type='bool', default=True), gather_file_shares=dict(type='bool', default=True), gather_volumes=dict(type='bool', default=True)) module = AnsibleAWSModule(argument_spec=argument_spec) if module._name == 'aws_sgw_facts': module.deprecate( "The 'aws_sgw_facts' module has been renamed to 'aws_sgw_info'", version='2.13') client = module.client('storagegateway') if client is None: # this should never happen module.fail_json( msg= 'Unknown error, failed to create storagegateway client, no information from boto.' ) SGWInformationManager(client, module).fetch()
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( name=dict(required=False), waf_regional=dict(type='bool', default=False), ) ) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) if module._name == 'aws_waf_facts': module.deprecate("The 'aws_waf_facts' module has been renamed to 'aws_waf_info'", version='2.13') region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) resource = 'waf' if not module.params['waf_regional'] else 'waf-regional' client = boto3_conn(module, conn_type='client', resource=resource, region=region, endpoint=ec2_url, **aws_connect_kwargs) 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 = dict(cluster_identifier=dict( type='str', aliases=['identifier', 'name']), tags=dict(type='dict')) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) if module._name == 'redshift_facts': module.deprecate( "The 'redshift_facts' module has been renamed to 'redshift_info'", version='2.13') cluster_identifier = module.params.get('cluster_identifier') cluster_tags = module.params.get('tags') redshift = module.client('redshift') results = find_clusters(redshift, module, identifier=cluster_identifier, tags=cluster_tags) module.exit_json(results=results)
def main(): argument_spec = dict( name=dict(required=True), saml_metadata_document=dict(default=None, required=False), state=dict(default='present', required=False, choices=['present', 'absent']), ) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True, required_if=[('state', 'present', ['saml_metadata_document'])]) name = module.params['name'] state = module.params.get('state') saml_metadata_document = module.params.get('saml_metadata_document') sp_man = SAMLProviderManager(module) if state == 'present': sp_man.create_or_update_saml_provider(name, saml_metadata_document) elif state == 'absent': sp_man.delete_saml_provider(name)
def main(): argument_spec = ec2_argument_spec() argument_spec.update( dict( name=dict(required=True), schedule_expression=dict(), event_pattern=dict(), state=dict(choices=['present', 'disabled', 'absent'], default='present'), description=dict(), role_arn=dict(), targets=dict(type='list', default=[]), ) ) module = AnsibleAWSModule(argument_spec=argument_spec) rule_data = dict( [(rf, module.params.get(rf)) for rf in CloudWatchEventRuleManager.RULE_FIELDS] ) targets = module.params.get('targets') state = module.params.get('state') cwe_rule = CloudWatchEventRule(module, client=get_cloudwatchevents_client(module), **rule_data) cwe_rule_manager = CloudWatchEventRuleManager(cwe_rule, targets) if state == 'present': cwe_rule_manager.ensure_present() elif state == 'disabled': cwe_rule_manager.ensure_disabled() elif state == 'absent': cwe_rule_manager.ensure_absent() else: module.fail_json(msg="Invalid state '{0}' provided".format(state)) module.exit_json(**cwe_rule_manager.fetch_aws_state())
def main(): argument_spec = dict( stack_name=dict(), all_facts=dict(required=False, default=False, type='bool'), stack_policy=dict(required=False, default=False, type='bool'), stack_events=dict(required=False, default=False, type='bool'), stack_resources=dict(required=False, default=False, type='bool'), stack_template=dict(required=False, default=False, type='bool'), stack_change_sets=dict(required=False, default=False, type='bool'), ) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) is_old_facts = module._name == 'cloudformation_facts' if is_old_facts: module.deprecate( "The 'cloudformation_facts' module has been renamed to 'cloudformation_info', " "and the renamed one no longer returns ansible_facts", version='2.13') service_mgr = CloudFormationServiceManager(module) if is_old_facts: result = {'ansible_facts': {'cloudformation': {}}} else: result = {'cloudformation': {}} for stack_description in service_mgr.describe_stacks( module.params.get('stack_name')): facts = {'stack_description': stack_description} stack_name = stack_description.get('StackName') # Create stack output and stack parameter dictionaries if facts['stack_description']: facts['stack_outputs'] = to_dict( facts['stack_description'].get('Outputs'), 'OutputKey', 'OutputValue') facts['stack_parameters'] = to_dict( facts['stack_description'].get('Parameters'), 'ParameterKey', 'ParameterValue') facts['stack_tags'] = boto3_tag_list_to_ansible_dict( facts['stack_description'].get('Tags')) # Create optional stack outputs all_facts = module.params.get('all_facts') if all_facts or module.params.get('stack_resources'): facts['stack_resource_list'] = service_mgr.list_stack_resources( stack_name) facts['stack_resources'] = to_dict( facts.get('stack_resource_list'), 'LogicalResourceId', 'PhysicalResourceId') if all_facts or module.params.get('stack_template'): facts['stack_template'] = service_mgr.get_template(stack_name) if all_facts or module.params.get('stack_policy'): facts['stack_policy'] = service_mgr.get_stack_policy(stack_name) if all_facts or module.params.get('stack_events'): facts['stack_events'] = service_mgr.describe_stack_events( stack_name) if all_facts or module.params.get('stack_change_sets'): facts[ 'stack_change_sets'] = service_mgr.describe_stack_change_sets( stack_name) if is_old_facts: result['ansible_facts']['cloudformation'][stack_name] = facts else: result['cloudformation'][stack_name] = camel_dict_to_snake_dict( facts, ignore_list=('stack_outputs', 'stack_parameters', 'stack_policy', 'stack_resources', 'stack_tags', 'stack_template')) module.exit_json(changed=False, **result)
def main(): argument_spec = dict(certificate=dict(), certificate_arn=dict(aliases=['arn']), certificate_chain=dict(), domain_name=dict(aliases=['domain']), name_tag=dict(aliases=['name']), private_key=dict(no_log=True), state=dict(default='present', choices=['present', 'absent'])) required_if = [ ['state', 'present', ['certificate', 'name_tag', 'private_key']], ] module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True, required_if=required_if) acm = ACMServiceManager(module) # Check argument requirements if module.params['state'] == 'present': if module.params['certificate_arn']: module.fail_json( msg= "Parameter 'certificate_arn' is only valid if parameter 'state' is specified as 'absent'" ) else: # absent # exactly one of these should be specified absent_args = ['certificate_arn', 'domain_name', 'name_tag'] if sum([(module.params[a] is not None) for a in absent_args]) != 1: for a in absent_args: module.debug("%s is %s" % (a, module.params[a])) module.fail_json( msg= "If 'state' is specified as 'absent' then exactly one of 'name_tag', certificate_arn' or 'domain_name' must be specified" ) if module.params['name_tag']: tags = dict(Name=module.params['name_tag']) else: tags = None client = module.client('acm') # fetch the list of certificates currently in ACM certificates = acm.get_certificates( client=client, module=module, domain_name=module.params['domain_name'], arn=module.params['certificate_arn'], only_tags=tags) module.debug("Found %d corresponding certificates in ACM" % len(certificates)) if module.params['state'] == 'present': if len(certificates) > 1: msg = "More than one certificate with Name=%s exists in ACM in this region" % module.params[ 'name_tag'] module.fail_json(msg=msg, certificates=certificates) elif len(certificates) == 1: # update the existing certificate module.debug("Existing certificate found in ACM") old_cert = certificates[0] # existing cert in ACM if ('tags' not in old_cert) or ('Name' not in old_cert['tags']) or ( old_cert['tags']['Name'] != module.params['name_tag']): # shouldn't happen module.fail_json( msg="Internal error, unsure which certificate to update", certificate=old_cert) if 'certificate' not in old_cert: # shouldn't happen module.fail_json( msg= "Internal error, unsure what the existing cert in ACM is", certificate=old_cert) # Are the existing certificate in ACM and the local certificate the same? same = True same &= chain_compare(module, old_cert['certificate'], module.params['certificate']) if module.params['certificate_chain']: # Need to test this # not sure if Amazon appends the cert itself to the chain when self-signed same &= chain_compare(module, old_cert['certificate_chain'], module.params['certificate_chain']) else: # When there is no chain with a cert # it seems Amazon returns the cert itself as the chain same &= chain_compare(module, old_cert['certificate_chain'], module.params['certificate']) if same: module.debug( "Existing certificate in ACM is the same, doing nothing") domain = acm.get_domain_of_cert( client=client, module=module, arn=old_cert['certificate_arn']) module.exit_json(certificate=dict( domain_name=domain, arn=old_cert['certificate_arn']), changed=False) else: module.debug( "Existing certificate in ACM is different, overwriting") # update cert in ACM arn = acm.import_certificate( client, module, certificate=module.params['certificate'], private_key=module.params['private_key'], certificate_chain=module.params['certificate_chain'], arn=old_cert['certificate_arn'], tags=tags) domain = acm.get_domain_of_cert(client=client, module=module, arn=arn) module.exit_json(certificate=dict(domain_name=domain, arn=arn), changed=True) else: # len(certificates) == 0 module.debug("No certificate in ACM. Creating new one.") arn = acm.import_certificate( client=client, module=module, certificate=module.params['certificate'], private_key=module.params['private_key'], certificate_chain=module.params['certificate_chain'], tags=tags) domain = acm.get_domain_of_cert(client=client, module=module, arn=arn) module.exit_json(certificate=dict(domain_name=domain, arn=arn), changed=True) else: # state == absent for cert in certificates: acm.delete_certificate(client, module, cert['certificate_arn']) module.exit_json( arns=[cert['certificate_arn'] for cert in certificates], changed=(len(certificates) > 0))