def main(): provider_information = create_hetzner_provider_information() argument_spec = create_hetzner_argument_spec() argument_spec.merge( create_module_argument_spec(provider_information=provider_information)) module = AnsibleModule(supports_check_mode=True, **argument_spec.to_kwargs()) run_module(module, lambda: create_hetzner_api(ModuleOptionProvider(module), ModuleHTTPHelper(module)), provider_information=provider_information)
def main(): provider_information = create_hetzner_provider_information() argument_spec = create_hetzner_argument_spec() argument_spec.merge( create_module_argument_spec(provider_information=provider_information)) argument_spec.argument_spec['prefix']['aliases'] = ['name'] argument_spec.argument_spec['prefix']['deprecated_aliases'] = [ dict(name='name', version='3.0.0', collection_name='community.dns') ] module = AnsibleModule(supports_check_mode=True, **argument_spec.to_kwargs()) run_module(module, lambda: create_hetzner_api(ModuleOptionProvider(module), ModuleHTTPHelper(module)), provider_information=provider_information)
def run_module(module, create_api, provider_information): option_provider = ModuleOptionProvider(module) record_converter = RecordConverter(provider_information, option_provider) filter_record_type = NOT_PROVIDED filter_prefix = NOT_PROVIDED if module.params.get('what') == 'single_record': filter_record_type = module.params.get('type') if module.params.get('prefix') is not None: filter_prefix = provider_information.normalize_prefix( module.params.get('prefix')) elif module.params.get('what') == 'all_types_for_record': if module.params.get('prefix') is not None: filter_prefix = provider_information.normalize_prefix( module.params.get('prefix')) try: # Create API api = create_api() # Get zone information if module.params.get('zone_name') is not None: zone_in = normalize_dns_name(module.params.get('zone_name')) zone = api.get_zone_with_records_by_name( zone_in, prefix=filter_prefix, record_type=filter_record_type) if zone is None: module.fail_json(msg='Zone not found') else: zone = api.get_zone_with_records_by_id( module.params.get('zone_id'), prefix=filter_prefix, record_type=filter_record_type) if zone is None: module.fail_json(msg='Zone not found') zone_in = normalize_dns_name(zone.zone.name) # Retrieve requested information records = [] if module.params.get('what') in ('single_record', 'all_types_for_record'): check_prefix = True record_in = normalize_dns_name(module.params.get('record')) prefix_in = module.params.get('prefix') record_in, prefix = get_prefix( normalized_zone=zone_in, normalized_record=record_in, prefix=prefix_in, provider_information=provider_information) else: check_prefix = False prefix = None # Find matching records records = [] for record in zone.records: if check_prefix: if record.prefix != prefix: continue records.append(( (record.prefix + '.' + zone_in) if record.prefix else zone_in, record, )) # Convert records only_records = [record for record_name, record in records] record_converter.process_multiple_from_api(only_records) record_converter.process_multiple_to_user(only_records) # Format output data = [ format_record_for_output(record, record_name, prefix=record.prefix) for record_name, record in records ] module.exit_json( changed=False, records=data, zone_id=zone.zone.id, ) except DNSConversionError as e: module.fail_json(msg='Error while converting DNS values: {0}'.format( e.error_message), error=e.error_message, exception=traceback.format_exc()) except DNSAPIAuthenticationError as e: module.fail_json(msg='Cannot authenticate: {0}'.format(e), error=to_text(e), exception=traceback.format_exc()) except DNSAPIError as e: module.fail_json(msg='Error: {0}'.format(e), error=to_text(e), exception=traceback.format_exc())
def run_module(module, create_api, provider_information): option_provider = ModuleOptionProvider(module) record_converter = RecordConverter(provider_information, option_provider) record_in = normalize_dns_name(module.params.get('record')) prefix_in = module.params.get('prefix') type_in = module.params.get('type') try: # Create API api = create_api() # Get zone information if module.params.get('zone_name') is not None: zone_in = normalize_dns_name(module.params.get('zone_name')) record_in, prefix = get_prefix( normalized_zone=zone_in, normalized_record=record_in, prefix=prefix_in, provider_information=provider_information) zone = api.get_zone_with_records_by_name(zone_in, prefix=prefix, record_type=type_in) if zone is None: module.fail_json(msg='Zone not found') zone_id = zone.zone.id records = zone.records elif record_in is not None: zone = api.get_zone_with_records_by_id( module.params.get('zone_id'), record_type=type_in, prefix=provider_information.normalize_prefix(prefix_in) if prefix_in is not None else NOT_PROVIDED, ) if zone is None: module.fail_json(msg='Zone not found') zone_in = normalize_dns_name(zone.zone.name) record_in, prefix = get_prefix( normalized_zone=zone_in, normalized_record=record_in, prefix=prefix_in, provider_information=provider_information) zone_id = zone.zone.id records = zone.records else: zone_id = module.params.get('zone_id') prefix = provider_information.normalize_prefix(prefix_in) records = api.get_zone_records( zone_id, record_type=type_in, prefix=prefix, ) if records is None: module.fail_json(msg='Zone not found') zone_in = None record_in = None # Find matching records records = filter_records(records, prefix=prefix) record_converter.process_multiple_from_api(records) # Parse records value_in = module.params.get('value') value_in = record_converter.process_value_from_user(type_in, value_in) # Compare records existing_record = None exact_match = False ttl_in = module.params.get('ttl') for record in records: if record.target == value_in: existing_record = record exact_match = record.ttl == ttl_in break before = existing_record.clone() if existing_record else None after = before changed = False if module.params.get('state') == 'present': if existing_record is None: # Create record record = DNSRecord() record.prefix = prefix record.type = type_in record.ttl = ttl_in record.target = value_in api_record = record_converter.clone_to_api(record) if not module.check_mode: new_api_record = api.add_record(zone_id, api_record) record = record_converter.clone_from_api(new_api_record) after = record changed = True elif not exact_match: # Update record record = existing_record record.ttl = ttl_in api_record = record_converter.clone_to_api(record) if not module.check_mode: new_api_record = api.update_record(zone_id, api_record) record = record_converter.clone_from_api(new_api_record) after = record changed = True else: if existing_record is not None: # Delete record api_record = record_converter.clone_to_api(record) if not module.check_mode: api.delete_record(zone_id, api_record) after = None changed = True # Compose result result = dict( changed=changed, zone_id=zone_id, ) if module._diff: result['diff'] = dict( before=format_record_for_output( before, record_in, prefix, record_converter=record_converter) if before else {}, after=format_record_for_output( after, record_in, prefix, record_converter=record_converter) if after else {}, ) module.exit_json(**result) except DNSConversionError as e: module.fail_json(msg='Error while converting DNS values: {0}'.format( e.error_message), error=e.error_message, exception=traceback.format_exc()) except DNSAPIAuthenticationError as e: module.fail_json(msg='Cannot authenticate: {0}'.format(e), error=to_text(e), exception=traceback.format_exc()) except DNSAPIError as e: module.fail_json(msg='Error: {0}'.format(e), error=to_text(e), exception=traceback.format_exc())
def run_module(module, create_api, provider_information): option_provider = ModuleOptionProvider(module) record_converter = RecordConverter(provider_information, option_provider) record_in = normalize_dns_name(module.params.get('record')) prefix_in = module.params.get('prefix') type_in = module.params.get('type') try: # Create API api = create_api() # Get zone information if module.params.get('zone_name') is not None: zone_in = normalize_dns_name(module.params.get('zone_name')) record_in, prefix = get_prefix( normalized_zone=zone_in, normalized_record=record_in, prefix=prefix_in, provider_information=provider_information) zone = api.get_zone_with_records_by_name(zone_in, prefix=prefix, record_type=type_in) if zone is None: module.fail_json(msg='Zone not found') zone_id = zone.zone.id records = zone.records elif record_in is not None: zone = api.get_zone_with_records_by_id( module.params.get('zone_id'), record_type=type_in, prefix=provider_information.normalize_prefix(prefix_in) if prefix_in is not None else NOT_PROVIDED, ) if zone is None: module.fail_json(msg='Zone not found') zone_in = normalize_dns_name(zone.zone.name) record_in, prefix = get_prefix( normalized_zone=zone_in, normalized_record=record_in, prefix=prefix_in, provider_information=provider_information) zone_id = zone.zone.id records = zone.records else: zone_id = module.params.get('zone_id') prefix = provider_information.normalize_prefix(prefix_in) records = api.get_zone_records( zone_id, record_type=type_in, prefix=prefix, ) if records is None: module.fail_json(msg='Zone not found') zone_in = None record_in = None # Find matching records records = filter_records(records, prefix=prefix) record_converter.process_multiple_from_api(records) # Parse records values = [] value_in = module.params.get('value') or [] value_in = record_converter.process_values_from_user(type_in, value_in) values = value_in[:] # Compare records ttl_in = module.params.get('ttl') mismatch = False mismatch_records = [] keep_records = [] for record in records: if record.ttl != ttl_in: mismatch = True mismatch_records.append(record) continue val = record.target if val in values: values.remove(val) keep_records.append(record) else: mismatch = True mismatch_records.append(record) continue if values: mismatch = True before = [record.clone() for record in records] after = keep_records[:] # Determine what to do to_create = [] to_delete = [] to_change = [] on_existing = module.params.get('on_existing') no_mod = False if module.params.get('state') == 'present': if records and mismatch: # Mismatch: user wants to overwrite? if on_existing == 'replace': to_delete.extend(mismatch_records) elif on_existing == 'keep_and_fail': module.fail_json( msg= "Record already exists with different value. Set on_existing=replace to replace it" ) elif on_existing == 'keep_and_warn': module.warn( "Record already exists with different value. Set on_existing=replace to replace it" ) no_mod = True else: # on_existing == 'keep' no_mod = True if no_mod: after = before[:] else: for target in values: if to_delete: # If there's a record to delete, change it to new record record = to_delete.pop() to_change.append(record) else: # Otherwise create new record record = DNSRecord() to_create.append(record) record.prefix = prefix record.type = type_in record.ttl = ttl_in record.target = target after.append(record) if module.params.get('state') == 'absent': if mismatch: # Mismatch: user wants to overwrite? if on_existing == 'replace': no_mod = False elif on_existing == 'keep_and_fail': module.fail_json( msg= "Record already exists with different value. Set on_existing=replace to remove it" ) elif on_existing == 'keep_and_warn': module.warn( "Record already exists with different value. Set on_existing=replace to remove it" ) no_mod = True else: # on_existing == 'keep' no_mod = True if no_mod: after = before[:] else: to_delete.extend(records) after = [] # Compose result result = dict( changed=False, zone_id=zone_id, ) # Determine whether there's something to do if to_create or to_delete or to_change: # Actually do something records_to_delete = record_converter.clone_multiple_to_api( to_delete) records_to_change = record_converter.clone_multiple_to_api( to_change) records_to_create = record_converter.clone_multiple_to_api( to_create) result['changed'] = True if not module.check_mode: dummy, errors, success = bulk_apply_changes( api, zone_id=zone_id, records_to_delete=records_to_delete, records_to_change=records_to_change, records_to_create=records_to_create, provider_information=provider_information, options=option_provider, ) if errors: if len(errors) == 1: raise errors[0] module.fail_json( msg='Errors: {0}'.format('; '.join( [str(e) for e in errors])), errors=[str(e) for e in errors], ) # Include diff information if module._diff: result['diff'] = dict( before=(format_records_for_output( sorted(before, key=lambda record: record.target), record_in, prefix, record_converter=record_converter) if before else dict()), after=(format_records_for_output( sorted(after, key=lambda record: record.target), record_in, prefix, record_converter=record_converter) if after else dict()), ) module.exit_json(**result) except DNSConversionError as e: module.fail_json(msg='Error while converting DNS values: {0}'.format( e.error_message), error=e.error_message, exception=traceback.format_exc()) except DNSAPIAuthenticationError as e: module.fail_json(msg='Cannot authenticate: {0}'.format(e), error=to_text(e), exception=traceback.format_exc()) except DNSAPIError as e: module.fail_json(msg='Error: {0}'.format(e), error=to_text(e), exception=traceback.format_exc())