@@ -99,17 +99,25 @@ def update_cloudflare_config():
99
99
with state_lock :
100
100
logging .info ("Constructing desired Cloudflare tunnel configuration from managed rules..." )
101
101
desired_dockflare_rules = []
102
- for hostname , rule_details in managed_rules .items ():
102
+ for rule_key , rule_details in managed_rules .items ():
103
103
if rule_details .get ("status" ) == "active" :
104
104
service_str = rule_details .get ("service" )
105
- path = rule_details .get ("path" )
106
105
107
- if service_str :
106
+ actual_hostname_for_cf = rule_details .get ("hostname_for_dns" )
107
+ actual_path_for_cf = rule_details .get ("path" )
108
+
109
+ if not actual_hostname_for_cf :
110
+ parts = rule_key .split ('|' , 1 )
111
+ actual_hostname_for_cf = parts [0 ]
112
+ if not actual_path_for_cf and len (parts ) > 1 and parts [1 ]:
113
+ actual_path_for_cf = parts [1 ]
114
+
115
+ if service_str and actual_hostname_for_cf :
108
116
no_tls_verify_flag = rule_details .get ("no_tls_verify" , False )
109
- rule_config = {"hostname" : hostname , "service" : service_str }
117
+ rule_config = {"hostname" : actual_hostname_for_cf , "service" : service_str }
110
118
111
- if path and path .strip ():
112
- processed_path = path .strip ()
119
+ if actual_path_for_cf and actual_path_for_cf .strip ():
120
+ processed_path = actual_path_for_cf .strip ()
113
121
if not processed_path .startswith ('/' ):
114
122
processed_path = '/' + processed_path
115
123
if len (processed_path ) > 1 and processed_path .endswith ('/' ):
@@ -120,11 +128,13 @@ def update_cloudflare_config():
120
128
(service_str .lower ().startswith ("http://" ) or service_str .lower ().startswith ("https://" )):
121
129
rule_config ["originRequest" ] = {"noTLSVerify" : True }
122
130
elif no_tls_verify_flag :
123
- logging .debug (f"Rule for { hostname } has no_tls_verify=true, but service '{ service_str } ' is not HTTP/HTTPS. 'noTLSVerify' will be ignored by Cloudflare for this service type." )
131
+ logging .debug (f"Rule for { rule_key } has no_tls_verify=true, but service '{ service_str } ' is not HTTP/HTTPS. 'noTLSVerify' will be ignored by Cloudflare for this service type." )
124
132
125
133
desired_dockflare_rules .append (rule_config )
126
- else :
127
- logging .warning (f"Rule { hostname } is active but missing 'service'. Skipping." )
134
+ elif not service_str :
135
+ logging .warning (f"Rule { rule_key } is active but missing 'service'. Skipping." )
136
+ elif not actual_hostname_for_cf :
137
+ logging .warning (f"Rule { rule_key } is active but could not determine a valid hostname for Cloudflare. Skipping." )
128
138
129
139
try :
130
140
current_api_config_ruleset = cloudflare_api .get_current_cf_config (tunnel_state ["id" ])
@@ -138,7 +148,6 @@ def update_cloudflare_config():
138
148
return False
139
149
140
150
current_api_ingress_rules = current_api_config_ruleset .get ("ingress" , [])
141
-
142
151
preserved_api_rules = []
143
152
catch_all_rule_template = {"service" : "http_status:404" }
144
153
@@ -153,10 +162,18 @@ def update_cloudflare_config():
153
162
154
163
is_actively_managed_by_dockflare = False
155
164
if not is_catch_all :
156
- for df_hostname , df_rule_details in managed_rules .items ():
165
+ for df_rule_key , df_rule_details in managed_rules .items ():
166
+ df_hostname_for_cf = df_rule_details .get ("hostname_for_dns" )
167
+ df_path_for_cf = df_rule_details .get ("path" )
168
+ if not df_hostname_for_cf :
169
+ parts = df_rule_key .split ('|' ,1 )
170
+ df_hostname_for_cf = parts [0 ]
171
+ if not df_path_for_cf and len (parts ) > 1 and parts [1 ]:
172
+ df_path_for_cf = parts [1 ]
173
+
157
174
if df_rule_details .get ("status" ) == "active" and \
158
- df_hostname == api_hostname and \
159
- (df_rule_details . get ( "path" ) or None ) == (api_path or None ):
175
+ df_hostname_for_cf == api_hostname and \
176
+ (df_path_for_cf or None ) == (api_path or None ):
160
177
is_actively_managed_by_dockflare = True
161
178
break
162
179
@@ -172,13 +189,11 @@ def update_cloudflare_config():
172
189
logging .info (f"Non-DockFlare managed rule found in API (hostname: { api_hostname } , path: { api_path } , service: { api_service } ). It will be removed by authoritative update." )
173
190
174
191
final_ingress_rules_to_put = list (desired_dockflare_rules )
175
-
176
192
for p_rule in preserved_api_rules :
177
193
is_duplicate = False
178
194
p_hostname = p_rule .get ("hostname" )
179
195
p_service = p_rule .get ("service" )
180
196
p_path = p_rule .get ("path" )
181
-
182
197
for f_rule in final_ingress_rules_to_put :
183
198
if f_rule .get ("hostname" ) == p_hostname and \
184
199
f_rule .get ("service" ) == p_service and \
@@ -202,9 +217,7 @@ def rule_to_comparable_dict(rule):
202
217
comp_dict = {}
203
218
if rule .get ("hostname" ) is not None :
204
219
comp_dict ["hostname" ] = rule .get ("hostname" )
205
-
206
220
comp_dict ["service" ] = rule .get ("service" )
207
-
208
221
path_val = rule .get ("path" )
209
222
if path_val and path_val .strip ():
210
223
processed_path_comp = path_val .strip ()
@@ -213,7 +226,6 @@ def rule_to_comparable_dict(rule):
213
226
if len (processed_path_comp ) > 1 and processed_path_comp .endswith ('/' ):
214
227
processed_path_comp = processed_path_comp .rstrip ('/' )
215
228
comp_dict ["path" ] = processed_path_comp
216
-
217
229
origin_request = rule .get ("originRequest" )
218
230
if isinstance (origin_request , dict ) and origin_request .get ("noTLSVerify" ) is True :
219
231
comp_dict ["noTLSVerify" ] = True
@@ -279,7 +291,7 @@ def rule_to_comparable_dict(rule):
279
291
tunnel_state ["error" ] = f"Failed update tunnel config: { e } "
280
292
return False
281
293
282
- return True
294
+ return True
283
295
284
296
def get_cloudflared_container ():
285
297
if not docker_client :
0 commit comments