django-cfg 1.2.16__py3-none-any.whl → 1.2.18__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- django_cfg/__init__.py +1 -1
- django_cfg/apps/accounts/models/__init__.py +68 -0
- django_cfg/apps/accounts/models/activity.py +34 -0
- django_cfg/apps/accounts/models/auth.py +50 -0
- django_cfg/apps/accounts/models/base.py +8 -0
- django_cfg/apps/accounts/models/choices.py +32 -0
- django_cfg/apps/accounts/models/integrations.py +75 -0
- django_cfg/apps/accounts/models/registration.py +52 -0
- django_cfg/apps/accounts/models/user.py +80 -0
- django_cfg/apps/maintenance/__init__.py +53 -24
- django_cfg/apps/maintenance/admin/__init__.py +7 -18
- django_cfg/apps/maintenance/admin/api_key_admin.py +185 -0
- django_cfg/apps/maintenance/admin/log_admin.py +156 -0
- django_cfg/apps/maintenance/admin/scheduled_admin.py +390 -0
- django_cfg/apps/maintenance/admin/site_admin.py +448 -0
- django_cfg/apps/maintenance/apps.py +9 -96
- django_cfg/apps/maintenance/management/commands/maintenance.py +193 -307
- django_cfg/apps/maintenance/management/commands/process_scheduled_maintenance.py +241 -0
- django_cfg/apps/maintenance/management/commands/sync_cloudflare.py +152 -111
- django_cfg/apps/maintenance/managers/__init__.py +7 -12
- django_cfg/apps/maintenance/managers/cloudflare_site_manager.py +192 -0
- django_cfg/apps/maintenance/managers/maintenance_log_manager.py +151 -0
- django_cfg/apps/maintenance/migrations/0001_initial.py +145 -705
- django_cfg/apps/maintenance/migrations/0002_cloudflaresite_maintenance_url.py +21 -0
- django_cfg/apps/maintenance/models/__init__.py +23 -21
- django_cfg/apps/maintenance/models/cloudflare_api_key.py +109 -0
- django_cfg/apps/maintenance/models/cloudflare_site.py +125 -0
- django_cfg/apps/maintenance/models/maintenance_log.py +131 -0
- django_cfg/apps/maintenance/models/scheduled_maintenance.py +307 -0
- django_cfg/apps/maintenance/services/__init__.py +37 -16
- django_cfg/apps/maintenance/services/bulk_operations_service.py +400 -0
- django_cfg/apps/maintenance/services/maintenance_service.py +230 -0
- django_cfg/apps/maintenance/services/scheduled_maintenance_service.py +381 -0
- django_cfg/apps/maintenance/services/site_sync_service.py +390 -0
- django_cfg/apps/maintenance/utils/__init__.py +12 -0
- django_cfg/apps/maintenance/utils/retry_utils.py +109 -0
- django_cfg/config.py +3 -0
- django_cfg/core/config.py +4 -6
- django_cfg/modules/django_unfold/dashboard.py +4 -5
- {django_cfg-1.2.16.dist-info → django_cfg-1.2.18.dist-info}/METADATA +52 -1
- {django_cfg-1.2.16.dist-info → django_cfg-1.2.18.dist-info}/RECORD +45 -55
- django_cfg/apps/maintenance/README.md +0 -305
- django_cfg/apps/maintenance/admin/deployments_admin.py +0 -251
- django_cfg/apps/maintenance/admin/events_admin.py +0 -374
- django_cfg/apps/maintenance/admin/monitoring_admin.py +0 -215
- django_cfg/apps/maintenance/admin/sites_admin.py +0 -464
- django_cfg/apps/maintenance/managers/deployments.py +0 -287
- django_cfg/apps/maintenance/managers/events.py +0 -374
- django_cfg/apps/maintenance/managers/monitoring.py +0 -301
- django_cfg/apps/maintenance/managers/sites.py +0 -335
- django_cfg/apps/maintenance/models/cloudflare.py +0 -316
- django_cfg/apps/maintenance/models/maintenance.py +0 -334
- django_cfg/apps/maintenance/models/monitoring.py +0 -393
- django_cfg/apps/maintenance/models/sites.py +0 -419
- django_cfg/apps/maintenance/serializers/__init__.py +0 -60
- django_cfg/apps/maintenance/serializers/actions.py +0 -310
- django_cfg/apps/maintenance/serializers/base.py +0 -44
- django_cfg/apps/maintenance/serializers/deployments.py +0 -209
- django_cfg/apps/maintenance/serializers/events.py +0 -210
- django_cfg/apps/maintenance/serializers/monitoring.py +0 -278
- django_cfg/apps/maintenance/serializers/sites.py +0 -213
- django_cfg/apps/maintenance/services/README.md +0 -168
- django_cfg/apps/maintenance/services/cloudflare_client.py +0 -441
- django_cfg/apps/maintenance/services/dns_manager.py +0 -497
- django_cfg/apps/maintenance/services/maintenance_manager.py +0 -504
- django_cfg/apps/maintenance/services/site_sync.py +0 -448
- django_cfg/apps/maintenance/services/sync_command_service.py +0 -330
- django_cfg/apps/maintenance/services/worker_manager.py +0 -264
- django_cfg/apps/maintenance/signals.py +0 -38
- django_cfg/apps/maintenance/urls.py +0 -36
- django_cfg/apps/maintenance/views/__init__.py +0 -18
- django_cfg/apps/maintenance/views/base.py +0 -61
- django_cfg/apps/maintenance/views/deployments.py +0 -175
- django_cfg/apps/maintenance/views/events.py +0 -204
- django_cfg/apps/maintenance/views/monitoring.py +0 -213
- django_cfg/apps/maintenance/views/sites.py +0 -338
- django_cfg/models/cloudflare.py +0 -316
- /django_cfg/apps/accounts/{models.py → __models.py} +0 -0
- {django_cfg-1.2.16.dist-info → django_cfg-1.2.18.dist-info}/WHEEL +0 -0
- {django_cfg-1.2.16.dist-info → django_cfg-1.2.18.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.2.16.dist-info → django_cfg-1.2.18.dist-info}/licenses/LICENSE +0 -0
@@ -1,504 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Modern maintenance mode manager using official Cloudflare library.
|
3
|
-
|
4
|
-
Provides clean, reliable maintenance mode management with Workers and Page Rules.
|
5
|
-
"""
|
6
|
-
|
7
|
-
import logging
|
8
|
-
from typing import Dict, List, Optional, Any
|
9
|
-
from datetime import datetime
|
10
|
-
from django.utils import timezone
|
11
|
-
from django.db import transaction
|
12
|
-
|
13
|
-
from .cloudflare_client import CloudflareClient
|
14
|
-
from ..models import CloudflareSite, MaintenanceEvent, CloudflareDeployment
|
15
|
-
from django_cfg.models.cloudflare import CloudflareConfig
|
16
|
-
|
17
|
-
logger = logging.getLogger(__name__)
|
18
|
-
|
19
|
-
|
20
|
-
class MaintenanceManager:
|
21
|
-
"""
|
22
|
-
Modern maintenance mode manager using Cloudflare Workers.
|
23
|
-
|
24
|
-
Provides reliable maintenance mode with automatic rollback capabilities.
|
25
|
-
"""
|
26
|
-
|
27
|
-
# Modern maintenance page template
|
28
|
-
MAINTENANCE_WORKER_TEMPLATE = '''
|
29
|
-
addEventListener('fetch', event => {
|
30
|
-
event.respondWith(handleMaintenanceMode(event.request))
|
31
|
-
})
|
32
|
-
|
33
|
-
async function handleMaintenanceMode(request) {
|
34
|
-
const maintenanceHtml = `
|
35
|
-
<!DOCTYPE html>
|
36
|
-
<html lang="en">
|
37
|
-
<head>
|
38
|
-
<meta charset="UTF-8">
|
39
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
40
|
-
<title>Maintenance Mode - {site_name}</title>
|
41
|
-
<style>
|
42
|
-
* { margin: 0; padding: 0; box-sizing: border-box; }
|
43
|
-
body {
|
44
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
45
|
-
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
46
|
-
color: white;
|
47
|
-
min-height: 100vh;
|
48
|
-
display: flex;
|
49
|
-
align-items: center;
|
50
|
-
justify-content: center;
|
51
|
-
text-align: center;
|
52
|
-
padding: 20px;
|
53
|
-
}
|
54
|
-
.container {
|
55
|
-
max-width: 600px;
|
56
|
-
background: rgba(255, 255, 255, 0.1);
|
57
|
-
backdrop-filter: blur(10px);
|
58
|
-
border-radius: 20px;
|
59
|
-
padding: 60px 40px;
|
60
|
-
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
61
|
-
}
|
62
|
-
h1 {
|
63
|
-
font-size: 3rem;
|
64
|
-
margin-bottom: 20px;
|
65
|
-
font-weight: 300;
|
66
|
-
}
|
67
|
-
.icon {
|
68
|
-
font-size: 4rem;
|
69
|
-
margin-bottom: 30px;
|
70
|
-
opacity: 0.8;
|
71
|
-
}
|
72
|
-
p {
|
73
|
-
font-size: 1.2rem;
|
74
|
-
line-height: 1.6;
|
75
|
-
margin-bottom: 30px;
|
76
|
-
opacity: 0.9;
|
77
|
-
}
|
78
|
-
.message {
|
79
|
-
background: rgba(255, 255, 255, 0.1);
|
80
|
-
border-radius: 10px;
|
81
|
-
padding: 20px;
|
82
|
-
margin: 20px 0;
|
83
|
-
border-left: 4px solid #fff;
|
84
|
-
}
|
85
|
-
.footer {
|
86
|
-
margin-top: 40px;
|
87
|
-
font-size: 0.9rem;
|
88
|
-
opacity: 0.7;
|
89
|
-
}
|
90
|
-
@media (max-width: 768px) {
|
91
|
-
h1 { font-size: 2rem; }
|
92
|
-
.container { padding: 40px 20px; }
|
93
|
-
}
|
94
|
-
</style>
|
95
|
-
</head>
|
96
|
-
<body>
|
97
|
-
<div class="container">
|
98
|
-
<div class="icon">🔧</div>
|
99
|
-
<h1>Under Maintenance</h1>
|
100
|
-
<p>We're currently performing scheduled maintenance to improve your experience.</p>
|
101
|
-
|
102
|
-
<div class="message">
|
103
|
-
<strong>{maintenance_message}</strong>
|
104
|
-
</div>
|
105
|
-
|
106
|
-
<p>We'll be back online shortly. Thank you for your patience!</p>
|
107
|
-
|
108
|
-
<div class="footer">
|
109
|
-
<p>Started: {started_at}<br>
|
110
|
-
Estimated completion: {estimated_completion}</p>
|
111
|
-
</div>
|
112
|
-
</div>
|
113
|
-
</body>
|
114
|
-
</html>
|
115
|
-
`
|
116
|
-
|
117
|
-
return new Response(maintenanceHtml, {
|
118
|
-
status: 503,
|
119
|
-
headers: {
|
120
|
-
'Content-Type': 'text/html; charset=utf-8',
|
121
|
-
'Cache-Control': 'no-cache, no-store, must-revalidate',
|
122
|
-
'Pragma': 'no-cache',
|
123
|
-
'Expires': '0',
|
124
|
-
'Retry-After': '3600'
|
125
|
-
}
|
126
|
-
})
|
127
|
-
}
|
128
|
-
'''
|
129
|
-
|
130
|
-
def __init__(self, config: CloudflareConfig):
|
131
|
-
"""Initialize maintenance manager."""
|
132
|
-
self.config = config
|
133
|
-
self.client = CloudflareClient(config)
|
134
|
-
|
135
|
-
def enable_maintenance(
|
136
|
-
self,
|
137
|
-
site: CloudflareSite,
|
138
|
-
maintenance_event: MaintenanceEvent,
|
139
|
-
custom_message: Optional[str] = None
|
140
|
-
) -> Dict[str, Any]:
|
141
|
-
"""
|
142
|
-
Enable maintenance mode for a site using Cloudflare Workers.
|
143
|
-
|
144
|
-
Args:
|
145
|
-
site: CloudflareSite to enable maintenance for
|
146
|
-
maintenance_event: MaintenanceEvent record
|
147
|
-
custom_message: Custom maintenance message
|
148
|
-
|
149
|
-
Returns:
|
150
|
-
Dict with deployment results
|
151
|
-
"""
|
152
|
-
logger.info(f"Enabling maintenance mode for {site.domain}")
|
153
|
-
|
154
|
-
try:
|
155
|
-
with transaction.atomic():
|
156
|
-
# Get account ID
|
157
|
-
account_id = site.account_id or self.client.get_account_id()
|
158
|
-
if not account_id:
|
159
|
-
raise ValueError("No account ID available")
|
160
|
-
|
161
|
-
# Prepare worker script
|
162
|
-
worker_name = f"maintenance-{site.domain.replace('.', '-')}"
|
163
|
-
worker_script = self._prepare_worker_script(
|
164
|
-
site=site,
|
165
|
-
maintenance_event=maintenance_event,
|
166
|
-
custom_message=custom_message
|
167
|
-
)
|
168
|
-
|
169
|
-
# Deploy worker
|
170
|
-
worker_result = self.client.create_worker(
|
171
|
-
account_id=account_id,
|
172
|
-
script_name=worker_name,
|
173
|
-
script_content=worker_script
|
174
|
-
)
|
175
|
-
|
176
|
-
# Create worker route
|
177
|
-
route_pattern = f"{site.domain}/*"
|
178
|
-
route_result = self.client.create_worker_route(
|
179
|
-
zone_id=site.zone_id,
|
180
|
-
pattern=route_pattern,
|
181
|
-
script_name=worker_name
|
182
|
-
)
|
183
|
-
|
184
|
-
# Create deployment record
|
185
|
-
deployment = CloudflareDeployment.objects.create_deployment(
|
186
|
-
site=site,
|
187
|
-
deployment_type='worker',
|
188
|
-
cloudflare_id=worker_result.id,
|
189
|
-
config={
|
190
|
-
'worker_name': worker_name,
|
191
|
-
'route_pattern': route_pattern,
|
192
|
-
'route_id': route_result.get('id'),
|
193
|
-
'maintenance_event_id': maintenance_event.id,
|
194
|
-
'custom_message': custom_message
|
195
|
-
},
|
196
|
-
maintenance_event=maintenance_event
|
197
|
-
)
|
198
|
-
|
199
|
-
# Update site maintenance status
|
200
|
-
site.maintenance_active = True
|
201
|
-
site.last_maintenance_at = timezone.now()
|
202
|
-
site.save()
|
203
|
-
|
204
|
-
# Update maintenance event
|
205
|
-
maintenance_event.status = MaintenanceEvent.Status.ACTIVE
|
206
|
-
maintenance_event.started_at = timezone.now()
|
207
|
-
maintenance_event.save()
|
208
|
-
|
209
|
-
logger.info(f"Maintenance mode enabled for {site.domain}")
|
210
|
-
|
211
|
-
return {
|
212
|
-
'success': True,
|
213
|
-
'deployment_id': deployment.id,
|
214
|
-
'worker_name': worker_name,
|
215
|
-
'route_pattern': route_pattern,
|
216
|
-
'message': f"Maintenance mode enabled for {site.domain}"
|
217
|
-
}
|
218
|
-
|
219
|
-
except Exception as e:
|
220
|
-
logger.error(f"Failed to enable maintenance for {site.domain}: {e}")
|
221
|
-
|
222
|
-
# Update maintenance event status
|
223
|
-
maintenance_event.status = MaintenanceEvent.Status.FAILED
|
224
|
-
maintenance_event.error_message = str(e)
|
225
|
-
maintenance_event.save()
|
226
|
-
|
227
|
-
return {
|
228
|
-
'success': False,
|
229
|
-
'error': str(e),
|
230
|
-
'message': f"Failed to enable maintenance for {site.domain}"
|
231
|
-
}
|
232
|
-
|
233
|
-
def disable_maintenance(
|
234
|
-
self,
|
235
|
-
site: CloudflareSite,
|
236
|
-
maintenance_event: Optional[MaintenanceEvent] = None
|
237
|
-
) -> Dict[str, Any]:
|
238
|
-
"""
|
239
|
-
Disable maintenance mode for a site.
|
240
|
-
|
241
|
-
Args:
|
242
|
-
site: CloudflareSite to disable maintenance for
|
243
|
-
maintenance_event: Optional MaintenanceEvent to update
|
244
|
-
|
245
|
-
Returns:
|
246
|
-
Dict with results
|
247
|
-
"""
|
248
|
-
logger.info(f"Disabling maintenance mode for {site.domain}")
|
249
|
-
|
250
|
-
try:
|
251
|
-
with transaction.atomic():
|
252
|
-
# Find active maintenance deployments
|
253
|
-
active_deployments = CloudflareDeployment.objects.filter(
|
254
|
-
site=site,
|
255
|
-
deployment_type='worker',
|
256
|
-
status='active'
|
257
|
-
)
|
258
|
-
|
259
|
-
results = []
|
260
|
-
account_id = site.account_id or self.client.get_account_id()
|
261
|
-
|
262
|
-
for deployment in active_deployments:
|
263
|
-
try:
|
264
|
-
config = deployment.config or {}
|
265
|
-
worker_name = config.get('worker_name')
|
266
|
-
route_id = config.get('route_id')
|
267
|
-
|
268
|
-
# Delete worker route
|
269
|
-
if route_id:
|
270
|
-
self.client.delete_worker_route(site.zone_id, route_id)
|
271
|
-
|
272
|
-
# Delete worker script
|
273
|
-
if worker_name and account_id:
|
274
|
-
self.client.delete_worker(account_id, worker_name)
|
275
|
-
|
276
|
-
# Update deployment status
|
277
|
-
deployment.status = 'rolled_back'
|
278
|
-
deployment.save()
|
279
|
-
|
280
|
-
results.append({
|
281
|
-
'deployment_id': deployment.id,
|
282
|
-
'worker_name': worker_name,
|
283
|
-
'success': True
|
284
|
-
})
|
285
|
-
|
286
|
-
except Exception as e:
|
287
|
-
logger.error(f"Failed to cleanup deployment {deployment.id}: {e}")
|
288
|
-
results.append({
|
289
|
-
'deployment_id': deployment.id,
|
290
|
-
'success': False,
|
291
|
-
'error': str(e)
|
292
|
-
})
|
293
|
-
|
294
|
-
# Update site maintenance status
|
295
|
-
site.maintenance_active = False
|
296
|
-
site.save()
|
297
|
-
|
298
|
-
# Update maintenance event if provided
|
299
|
-
if maintenance_event:
|
300
|
-
maintenance_event.status = MaintenanceEvent.Status.COMPLETED
|
301
|
-
maintenance_event.ended_at = timezone.now()
|
302
|
-
maintenance_event.save()
|
303
|
-
|
304
|
-
logger.info(f"Maintenance mode disabled for {site.domain}")
|
305
|
-
|
306
|
-
return {
|
307
|
-
'success': True,
|
308
|
-
'deployments_cleaned': len([r for r in results if r['success']]),
|
309
|
-
'cleanup_results': results,
|
310
|
-
'message': f"Maintenance mode disabled for {site.domain}"
|
311
|
-
}
|
312
|
-
|
313
|
-
except Exception as e:
|
314
|
-
logger.error(f"Failed to disable maintenance for {site.domain}: {e}")
|
315
|
-
|
316
|
-
if maintenance_event:
|
317
|
-
maintenance_event.status = MaintenanceEvent.Status.FAILED
|
318
|
-
maintenance_event.error_message = str(e)
|
319
|
-
maintenance_event.save()
|
320
|
-
|
321
|
-
return {
|
322
|
-
'success': False,
|
323
|
-
'error': str(e),
|
324
|
-
'message': f"Failed to disable maintenance for {site.domain}"
|
325
|
-
}
|
326
|
-
|
327
|
-
def bulk_enable_maintenance(
|
328
|
-
self,
|
329
|
-
sites: List[CloudflareSite],
|
330
|
-
maintenance_event: MaintenanceEvent,
|
331
|
-
custom_message: Optional[str] = None
|
332
|
-
) -> Dict[str, Any]:
|
333
|
-
"""
|
334
|
-
Enable maintenance mode for multiple sites.
|
335
|
-
|
336
|
-
Args:
|
337
|
-
sites: List of CloudflareSite objects
|
338
|
-
maintenance_event: MaintenanceEvent record
|
339
|
-
custom_message: Custom maintenance message
|
340
|
-
|
341
|
-
Returns:
|
342
|
-
Dict with bulk operation results
|
343
|
-
"""
|
344
|
-
logger.info(f"Enabling maintenance mode for {len(sites)} sites")
|
345
|
-
|
346
|
-
results = {
|
347
|
-
'success': 0,
|
348
|
-
'failed': 0,
|
349
|
-
'sites': []
|
350
|
-
}
|
351
|
-
|
352
|
-
for site in sites:
|
353
|
-
try:
|
354
|
-
result = self.enable_maintenance(
|
355
|
-
site=site,
|
356
|
-
maintenance_event=maintenance_event,
|
357
|
-
custom_message=custom_message
|
358
|
-
)
|
359
|
-
|
360
|
-
if result['success']:
|
361
|
-
results['success'] += 1
|
362
|
-
else:
|
363
|
-
results['failed'] += 1
|
364
|
-
|
365
|
-
results['sites'].append({
|
366
|
-
'site_id': site.id,
|
367
|
-
'domain': site.domain,
|
368
|
-
'result': result
|
369
|
-
})
|
370
|
-
|
371
|
-
except Exception as e:
|
372
|
-
logger.error(f"Bulk maintenance failed for {site.domain}: {e}")
|
373
|
-
results['failed'] += 1
|
374
|
-
results['sites'].append({
|
375
|
-
'site_id': site.id,
|
376
|
-
'domain': site.domain,
|
377
|
-
'result': {
|
378
|
-
'success': False,
|
379
|
-
'error': str(e)
|
380
|
-
}
|
381
|
-
})
|
382
|
-
|
383
|
-
logger.info(f"Bulk maintenance completed: {results['success']} success, {results['failed']} failed")
|
384
|
-
return results
|
385
|
-
|
386
|
-
def bulk_disable_maintenance(
|
387
|
-
self,
|
388
|
-
sites: List[CloudflareSite],
|
389
|
-
maintenance_event: Optional[MaintenanceEvent] = None
|
390
|
-
) -> Dict[str, Any]:
|
391
|
-
"""
|
392
|
-
Disable maintenance mode for multiple sites.
|
393
|
-
|
394
|
-
Args:
|
395
|
-
sites: List of CloudflareSite objects
|
396
|
-
maintenance_event: Optional MaintenanceEvent to update
|
397
|
-
|
398
|
-
Returns:
|
399
|
-
Dict with bulk operation results
|
400
|
-
"""
|
401
|
-
logger.info(f"Disabling maintenance mode for {len(sites)} sites")
|
402
|
-
|
403
|
-
results = {
|
404
|
-
'success': 0,
|
405
|
-
'failed': 0,
|
406
|
-
'sites': []
|
407
|
-
}
|
408
|
-
|
409
|
-
for site in sites:
|
410
|
-
try:
|
411
|
-
result = self.disable_maintenance(
|
412
|
-
site=site,
|
413
|
-
maintenance_event=maintenance_event
|
414
|
-
)
|
415
|
-
|
416
|
-
if result['success']:
|
417
|
-
results['success'] += 1
|
418
|
-
else:
|
419
|
-
results['failed'] += 1
|
420
|
-
|
421
|
-
results['sites'].append({
|
422
|
-
'site_id': site.id,
|
423
|
-
'domain': site.domain,
|
424
|
-
'result': result
|
425
|
-
})
|
426
|
-
|
427
|
-
except Exception as e:
|
428
|
-
logger.error(f"Bulk maintenance disable failed for {site.domain}: {e}")
|
429
|
-
results['failed'] += 1
|
430
|
-
results['sites'].append({
|
431
|
-
'site_id': site.id,
|
432
|
-
'domain': site.domain,
|
433
|
-
'result': {
|
434
|
-
'success': False,
|
435
|
-
'error': str(e)
|
436
|
-
}
|
437
|
-
})
|
438
|
-
|
439
|
-
logger.info(f"Bulk maintenance disable completed: {results['success']} success, {results['failed']} failed")
|
440
|
-
return results
|
441
|
-
|
442
|
-
def _prepare_worker_script(
|
443
|
-
self,
|
444
|
-
site: CloudflareSite,
|
445
|
-
maintenance_event: MaintenanceEvent,
|
446
|
-
custom_message: Optional[str] = None
|
447
|
-
) -> str:
|
448
|
-
"""Prepare Worker script with site-specific content."""
|
449
|
-
message = custom_message or maintenance_event.maintenance_message or "Scheduled maintenance in progress"
|
450
|
-
|
451
|
-
started_at = maintenance_event.started_at or timezone.now()
|
452
|
-
estimated_completion = "Soon"
|
453
|
-
|
454
|
-
if maintenance_event.estimated_duration:
|
455
|
-
completion_time = started_at + maintenance_event.estimated_duration
|
456
|
-
estimated_completion = completion_time.strftime("%Y-%m-%d %H:%M UTC")
|
457
|
-
|
458
|
-
return self.MAINTENANCE_WORKER_TEMPLATE.format(
|
459
|
-
site_name=site.name or site.domain,
|
460
|
-
maintenance_message=message,
|
461
|
-
started_at=started_at.strftime("%Y-%m-%d %H:%M UTC"),
|
462
|
-
estimated_completion=estimated_completion
|
463
|
-
)
|
464
|
-
|
465
|
-
def get_maintenance_status(self, site: CloudflareSite) -> Dict[str, Any]:
|
466
|
-
"""
|
467
|
-
Get current maintenance status for a site.
|
468
|
-
|
469
|
-
Args:
|
470
|
-
site: CloudflareSite to check
|
471
|
-
|
472
|
-
Returns:
|
473
|
-
Dict with maintenance status
|
474
|
-
"""
|
475
|
-
active_deployments = CloudflareDeployment.objects.filter(
|
476
|
-
site=site,
|
477
|
-
deployment_type='worker',
|
478
|
-
status='active'
|
479
|
-
).with_maintenance_event()
|
480
|
-
|
481
|
-
if not active_deployments.exists():
|
482
|
-
return {
|
483
|
-
'maintenance_active': False,
|
484
|
-
'site_id': site.id,
|
485
|
-
'domain': site.domain
|
486
|
-
}
|
487
|
-
|
488
|
-
deployment = active_deployments.first()
|
489
|
-
maintenance_event = deployment.maintenance_event
|
490
|
-
|
491
|
-
return {
|
492
|
-
'maintenance_active': True,
|
493
|
-
'site_id': site.id,
|
494
|
-
'domain': site.domain,
|
495
|
-
'deployment_id': deployment.id,
|
496
|
-
'started_at': deployment.deployed_at.isoformat(),
|
497
|
-
'maintenance_event': {
|
498
|
-
'id': maintenance_event.id if maintenance_event else None,
|
499
|
-
'title': maintenance_event.title if maintenance_event else None,
|
500
|
-
'status': maintenance_event.status if maintenance_event else None,
|
501
|
-
'estimated_duration': str(maintenance_event.estimated_duration) if maintenance_event and maintenance_event.estimated_duration else None
|
502
|
-
} if maintenance_event else None,
|
503
|
-
'worker_config': deployment.config
|
504
|
-
}
|