33
44# (c) 2016 Michael Gruener <[email protected] > 55#
6- # This file is (intends to be) part of Ansible
6+ # This file is part of Ansible
77#
88# Ansible is free software: you can redistribute it and/or modify
99# it under the terms of the GNU General Public License as published by
114114'''
115115
116116EXAMPLES = '''
117- # create a test.my.com A record to point to 127.0.0.01
117+ # create a test.my.com A record to point to 127.0.0.1
118118- cloudflare_dns:
119119 zone: my.com
120120 record: test
177177'''
178178
179179RETURN = '''
180- records:
181- description: >
182- List containing the records for a zone or the data for a newly created record.
183- For details see https://api.cloudflare.com/#dns-records-for-a-zone-properties.
184- returned: success/changed after record creation
185- type: list
180+ record:
181+ description: dictionary containing the record data
182+ returned: success, except on record deletion
183+ type: dictionary
184+ contains:
185+ content:
186+ description: the record content (details depend on record type)
187+ returned: success
188+ type: string
189+ sample: 192.168.100.20
190+ created_on:
191+ description: the record creation date
192+ returned: success
193+ type: string
194+ sample: 2016-03-25T19:09:42.516553Z
195+ data:
196+ description: additional record data
197+ returned: success, if type is SRV
198+ type: dictionary
199+ sample: {
200+ name: "jabber",
201+ port: 8080,
202+ priority: 10,
203+ proto: "_tcp",
204+ service: "_xmpp",
205+ target: "jabberhost.sample.com",
206+ weight: 5,
207+ }
208+ id:
209+ description: the record id
210+ returned: success
211+ type: string
212+ sample: f9efb0549e96abcb750de63b38c9576e
213+ locked:
214+ description: No documentation available
215+ returned: success
216+ type: boolean
217+ sample: False
218+ meta:
219+ description: No documentation available
220+ returned: success
221+ type: dictionary
222+ sample: { auto_added: false }
223+ modified_on:
224+ description: record modification date
225+ returned: success
226+ type: string
227+ sample: 2016-03-25T19:09:42.516553Z
228+ name:
229+ description: the record name as FQDN (including _service and _proto for SRV)
230+ returned: success
231+ type: string
232+ sample: www.sample.com
233+ priority:
234+ description: priority of the MX record
235+ returned: success, if type is MX
236+ type: int
237+ sample: 10
238+ proxiable:
239+ description: whether this record can be proxied through cloudflare
240+ returned: success
241+ type: boolean
242+ sample: False
243+ proxied:
244+ description: whether the record is proxied through cloudflare
245+ returned: success
246+ type: boolean
247+ sample: False
248+ ttl:
249+ description: the time-to-live for the record
250+ returned: success
251+ type: int
252+ sample: 300
253+ type:
254+ description: the record type
255+ returned: success
256+ type: string
257+ sample: A
258+ zone_id:
259+ description: the id of the zone containing the record
260+ returned: success
261+ type: string
262+ sample: abcede0bf9f0066f94029d2e6b73856a
263+ zone_name:
264+ description: the name of the zone containing the record
265+ returned: success
266+ type: string
267+ sample: sample.com
186268'''
187269
188270class CloudflareAPI (object ):
@@ -346,7 +428,6 @@ def get_dns_records(self,zone_name=None,type=None,record=None,value=''):
346428 if (not value ) and (value is not None ):
347429 value = self .value
348430
349-
350431 zone_id = self ._get_zone_id ()
351432 api_call = '/zones/{0}/dns_records' .format (zone_id )
352433 query = {}
@@ -371,19 +452,21 @@ def delete_dns_records(self,**kwargs):
371452 params [param ] = getattr (self ,param )
372453
373454 records = []
374- search_value = params ['value' ]
455+ content = params ['value' ]
375456 search_record = params ['record' ]
376457 if params ['type' ] == 'SRV' :
377- search_value = str (params ['weight' ]) + '\t ' + str (params ['port' ]) + '\t ' + params ['value' ]
458+ content = str (params ['weight' ]) + '\t ' + str (params ['port' ]) + '\t ' + params ['value' ]
378459 search_record = params ['service' ] + '.' + params ['proto' ] + '.' + params ['record' ]
379460 if params ['solo' ]:
380461 search_value = None
462+ else :
463+ search_value = content
381464
382465 records = self .get_dns_records (params ['zone' ],params ['type' ],search_record ,search_value )
383466
384467 for rr in records :
385468 if params ['solo' ]:
386- if not ((rr ['type' ] == params ['type' ]) and (rr ['name' ] == params [ 'record' ] ) and (rr ['content' ] == params [ 'value' ] )):
469+ if not ((rr ['type' ] == params ['type' ]) and (rr ['name' ] == search_record ) and (rr ['content' ] == content )):
387470 self .changed = True
388471 if not self .module .check_mode :
389472 result , info = self ._cf_api_call ('/zones/{0}/dns_records/{1}' .format (rr ['zone_id' ],rr ['id' ]),'DELETE' )
@@ -410,6 +493,14 @@ def ensure_dns_record(self,**kwargs):
410493 if (params ['type' ] in [ 'A' ,'AAAA' ,'CNAME' ,'TXT' ,'MX' ,'NS' ,'SPF' ]):
411494 if not params ['value' ]:
412495 self .module .fail_json (msg = "You must provide a non-empty value to create this record type" )
496+
497+ # there can only be one CNAME per record
498+ # ignoring the value when searching for existing
499+ # CNAME records allows us to update the value if it
500+ # changes
501+ if params ['type' ] == 'CNAME' :
502+ search_value = None
503+
413504 new_record = {
414505 "type" : params ['type' ],
415506 "name" : params ['record' ],
@@ -438,7 +529,7 @@ def ensure_dns_record(self,**kwargs):
438529 "port" : params ['port' ],
439530 "weight" : params ['weight' ],
440531 "priority" : params ['priority' ],
441- "name" : params ['record' ],
532+ "name" : params ['record' ][: - len ( '.' + params [ 'zone' ])] ,
442533 "proto" : params ['proto' ],
443534 "service" : params ['service' ]
444535 }
@@ -451,21 +542,20 @@ def ensure_dns_record(self,**kwargs):
451542 # in theory this should be impossible as cloudflare does not allow
452543 # the creation of duplicate records but lets cover it anyways
453544 if len (records ) > 1 :
454- return records , self .changed
455- # record already exists, check if ttl must be updated
545+ self .module . fail_json ( msg = "More than one record already exists for the given attributes. That should be impossible, please open an issue!" )
546+ # record already exists, check if it must be updated
456547 if len (records ) == 1 :
457548 cur_record = records [0 ]
458549 do_update = False
459550 if (params ['ttl' ] is not None ) and (cur_record ['ttl' ] != params ['ttl' ] ):
460- cur_record ['ttl' ] = params ['ttl' ]
461551 do_update = True
462552 if (params ['priority' ] is not None ) and ('priority' in cur_record ) and (cur_record ['priority' ] != params ['priority' ]):
463- cur_record ['priority' ] = params ['priority' ]
464553 do_update = True
465554 if ('data' in new_record ) and ('data' in cur_record ):
466555 if (cur_record ['data' ] > new_record ['data' ]) - (cur_record ['data' ] < new_record ['data' ]):
467- cur_record ['data' ] = new_record ['data' ]
468556 do_update = True
557+ if (type == 'CNAME' ) and (cur_record ['content' ] != new_record ['content' ]):
558+ do_update = True
469559 if do_update :
470560 if not self .module .check_mode :
471561 result , info = self ._cf_api_call ('/zones/{0}/dns_records/{1}' .format (zone_id ,records [0 ]['id' ]),'PUT' ,new_record )
@@ -529,7 +619,10 @@ def main():
529619 if cf_api .is_solo :
530620 changed = cf_api .delete_dns_records (solo = cf_api .is_solo )
531621 result ,changed = cf_api .ensure_dns_record ()
532- module .exit_json (changed = changed ,result = {'records' : result })
622+ if isinstance (result ,list ):
623+ module .exit_json (changed = changed ,result = {'record' : result [0 ]})
624+ else :
625+ module .exit_json (changed = changed ,result = {'record' : result })
533626 else :
534627 # force solo to False, just to be sure
535628 changed = cf_api .delete_dns_records (solo = False )
0 commit comments