2
2
import pulumi_cloudflare as cloudflare
3
3
import yaml
4
4
from pathlib import Path
5
+ from pulumi .log import warn , error
5
6
6
7
config = pulumi .Config ()
7
8
cloudflare_config = config .require_object ("cloudflare" )
8
9
9
10
cloudflare_provider = cloudflare .Provider (
10
11
"cloudflare-provider" ,
11
12
api_token = cloudflare_config .get ("apiToken" ), # Get from object
12
- opts = pulumi . ResourceOptions ( version = "5.49.1" )
13
+ version = "5.49.1"
13
14
)
14
15
15
16
def load_dns_records (record_type ):
16
- records = []
17
17
try :
18
18
with open (f"resources/{ record_type } .yaml" ) as f :
19
19
records = yaml .safe_load (f ) or []
20
+ for record in records :
21
+ if 'name' not in record :
22
+ raise ValueError (f"Record missing required field 'name' in { record_type } .yaml" )
23
+ if not record .get ('content' ) and not record .get ('value' ):
24
+ raise ValueError (f"Record { record ['name' ]} missing 'content' or 'value'" )
25
+ return records
20
26
except FileNotFoundError :
21
- pulumi .log .warn (f"No { record_type } records file found at resources/{ record_type } .yaml" )
22
- return records
27
+ warn (f"No { record_type } records file found at resources/{ record_type } .yaml" )
28
+ return []
29
+ except Exception as e :
30
+ error (f"Error loading { record_type } .yaml: { str (e )} " )
31
+ return []
32
+
33
+ def create_or_update_record (record_type , record ):
34
+ try :
35
+ # Normalize input
36
+ record_name = record ['name' ]
37
+ content = record .get ('content' ) or record .get ('value' )
38
+ record_type = record .get ('type' , record_type .upper ().replace ('RECORD' , '' ))
39
+ proxied = record .get ('proxied' , False )
40
+ ttl = 1 if proxied else record .get ('ttl' , 300 )
41
+
42
+ existing_records = cloudflare .get_record_output (
43
+ zone_id = cloudflare_config .get ("zoneId" ),
44
+ hostname = record_name ,
45
+ type = record_type
46
+ )
47
+
48
+ if existing_records .id :
49
+ return cloudflare .Record (
50
+ f"{ record_type } -{ record_name } " ,
51
+ zone_id = cloudflare_config .get ("zoneId" ),
52
+ name = record_name ,
53
+ type = record_type ,
54
+ content = content ,
55
+ ttl = ttl ,
56
+ proxied = proxied ,
57
+ comment = record .get ('comment' , "Managed by Pulumi" ),
58
+ opts = pulumi .ResourceOptions (
59
+ provider = cloudflare_provider ,
60
+ retain_on_delete = True
61
+ )
62
+ )
63
+ else :
64
+ return cloudflare .Record (
65
+ f"{ record_type } -{ record_name } " ,
66
+ zone_id = cloudflare_config .get ("zoneId" ),
67
+ name = record_name ,
68
+ type = record_type ,
69
+ content = content ,
70
+ ttl = ttl ,
71
+ proxied = proxied ,
72
+ comment = record .get ('comment' , "Managed by Pulumi" ),
73
+ opts = pulumi .ResourceOptions (provider = cloudflare_provider )
74
+ )
75
+
76
+ except Exception as e :
77
+ error (f"Failed to process record { record_name } : { str (e )} " )
78
+ return None
23
79
24
80
def create_dns_records (record_type ):
25
81
records = load_dns_records (record_type )
82
+ successful_records = 0
83
+
26
84
for record in records :
27
- # TTL must be 1 when proxied is True
28
- ttl = 1 if record .get ('proxied' , False ) else record .get ('ttl' , 300 )
29
- cloudflare .Record (
30
- f"{ record_type } -{ record ['name' ]} " ,
31
- zone_id = cloudflare_config .get ("zoneId" ),
32
- name = record ['name' ],
33
- type = record .get ('type' , record_type .upper ().replace ('RECORD' , '' )),
34
- content = record .get ('content' ) or record .get ('value' ),
35
- ttl = ttl ,
36
- proxied = record .get ('proxied' , False ),
37
- comment = record .get ('comment' , "Managed by Pulumi" ),
38
- opts = pulumi .ResourceOptions (provider = cloudflare_provider )
39
- )
85
+ result = create_or_update_record (record_type , record )
86
+ if result :
87
+ successful_records += 1
88
+
89
+ if successful_records > 0 :
90
+ pulumi .export (f"{ record_type } _records_created" , successful_records )
91
+ else :
92
+ warn (f"No { record_type } records were processed successfully" )
40
93
41
94
create_dns_records ("arecord" )
42
95
create_dns_records ("cname" )
0 commit comments