django-cfg 1.2.17__py3-none-any.whl → 1.2.19__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 +4 -0
- django_cfg/core/config.py +4 -6
- django_cfg/modules/django_unfold/dashboard.py +4 -5
- {django_cfg-1.2.17.dist-info → django_cfg-1.2.19.dist-info}/METADATA +52 -1
- {django_cfg-1.2.17.dist-info → django_cfg-1.2.19.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.17.dist-info → django_cfg-1.2.19.dist-info}/WHEEL +0 -0
- {django_cfg-1.2.17.dist-info → django_cfg-1.2.19.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.2.17.dist-info → django_cfg-1.2.19.dist-info}/licenses/LICENSE +0 -0
@@ -1,22 +1,18 @@
|
|
1
|
-
# Generated by Django 5.2.6 on 2025-09-
|
1
|
+
# Generated by Django 5.2.6 on 2025-09-23 07:44
|
2
2
|
|
3
|
+
import datetime
|
3
4
|
import django.db.models.deletion
|
4
|
-
import django.utils.timezone
|
5
|
-
from django.conf import settings
|
6
5
|
from django.db import migrations, models
|
7
6
|
|
8
7
|
|
9
8
|
class Migration(migrations.Migration):
|
10
|
-
|
11
9
|
initial = True
|
12
10
|
|
13
|
-
dependencies = [
|
14
|
-
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
15
|
-
]
|
11
|
+
dependencies = []
|
16
12
|
|
17
13
|
operations = [
|
18
14
|
migrations.CreateModel(
|
19
|
-
name="
|
15
|
+
name="CloudflareApiKey",
|
20
16
|
fields=[
|
21
17
|
(
|
22
18
|
"id",
|
@@ -27,157 +23,56 @@ class Migration(migrations.Migration):
|
|
27
23
|
(
|
28
24
|
"name",
|
29
25
|
models.CharField(
|
30
|
-
help_text="Friendly
|
31
|
-
|
32
|
-
),
|
33
|
-
(
|
34
|
-
"domain",
|
35
|
-
models.CharField(
|
36
|
-
help_text="Domain name (e.g., example.com)", max_length=253, unique=True
|
26
|
+
help_text="Friendly name for this API key (e.g., 'Production', 'Staging')",
|
27
|
+
max_length=100,
|
37
28
|
),
|
38
29
|
),
|
39
30
|
(
|
40
31
|
"description",
|
41
|
-
models.TextField(
|
42
|
-
|
43
|
-
(
|
44
|
-
"zone_id",
|
45
|
-
models.CharField(help_text="Cloudflare Zone ID", max_length=32, unique=True),
|
46
|
-
),
|
47
|
-
("account_id", models.CharField(help_text="Cloudflare Account ID", max_length=32)),
|
48
|
-
(
|
49
|
-
"api_token",
|
50
|
-
models.CharField(
|
51
|
-
help_text="Site-specific or account API token", max_length=200
|
52
|
-
),
|
53
|
-
),
|
54
|
-
(
|
55
|
-
"environment",
|
56
|
-
models.CharField(
|
57
|
-
choices=[
|
58
|
-
("production", "Production"),
|
59
|
-
("staging", "Staging"),
|
60
|
-
("development", "Development"),
|
61
|
-
("testing", "Testing"),
|
62
|
-
],
|
63
|
-
default="production",
|
64
|
-
help_text="Site environment type",
|
65
|
-
max_length=20,
|
32
|
+
models.TextField(
|
33
|
+
blank=True, help_text="Optional description of what this key is used for"
|
66
34
|
),
|
67
35
|
),
|
36
|
+
("api_token", models.CharField(help_text="Cloudflare API token", max_length=255)),
|
68
37
|
(
|
69
|
-
"
|
38
|
+
"account_id",
|
70
39
|
models.CharField(
|
71
|
-
blank=True, help_text="Project or client name", max_length=100
|
72
|
-
),
|
73
|
-
),
|
74
|
-
(
|
75
|
-
"tags",
|
76
|
-
models.JSONField(
|
77
40
|
blank=True,
|
78
|
-
|
79
|
-
|
80
|
-
),
|
81
|
-
),
|
82
|
-
(
|
83
|
-
"current_status",
|
84
|
-
models.CharField(
|
85
|
-
choices=[
|
86
|
-
("active", "Active"),
|
87
|
-
("maintenance", "Under Maintenance"),
|
88
|
-
("offline", "Offline"),
|
89
|
-
("unknown", "Unknown"),
|
90
|
-
],
|
91
|
-
default="unknown",
|
92
|
-
help_text="Current operational status",
|
93
|
-
max_length=20,
|
94
|
-
),
|
95
|
-
),
|
96
|
-
(
|
97
|
-
"maintenance_active",
|
98
|
-
models.BooleanField(
|
99
|
-
default=False, help_text="Whether maintenance mode is currently active"
|
100
|
-
),
|
101
|
-
),
|
102
|
-
(
|
103
|
-
"last_status_check",
|
104
|
-
models.DateTimeField(
|
105
|
-
blank=True, help_text="When status was last checked", null=True
|
106
|
-
),
|
107
|
-
),
|
108
|
-
(
|
109
|
-
"worker_name",
|
110
|
-
models.CharField(
|
111
|
-
default="maintenance-mode",
|
112
|
-
help_text="Cloudflare Worker name for maintenance mode",
|
113
|
-
max_length=100,
|
114
|
-
),
|
115
|
-
),
|
116
|
-
(
|
117
|
-
"maintenance_template",
|
118
|
-
models.CharField(
|
119
|
-
default="modern", help_text="Maintenance page template", max_length=50
|
41
|
+
help_text="Cloudflare Account ID (auto-discovered if empty)",
|
42
|
+
max_length=32,
|
120
43
|
),
|
121
44
|
),
|
122
45
|
(
|
123
|
-
"
|
124
|
-
models.
|
125
|
-
blank=True, help_text="Custom maintenance message for this site"
|
126
|
-
),
|
46
|
+
"is_active",
|
47
|
+
models.BooleanField(default=True, help_text="Whether this API key is active"),
|
127
48
|
),
|
128
49
|
(
|
129
|
-
"
|
50
|
+
"is_default",
|
130
51
|
models.BooleanField(
|
131
|
-
default=
|
132
|
-
),
|
133
|
-
),
|
134
|
-
(
|
135
|
-
"health_check_url",
|
136
|
-
models.URLField(
|
137
|
-
blank=True, help_text="Custom health check URL (defaults to domain/health/)"
|
138
|
-
),
|
139
|
-
),
|
140
|
-
(
|
141
|
-
"check_interval",
|
142
|
-
models.PositiveIntegerField(
|
143
|
-
default=300, help_text="Health check interval in seconds"
|
52
|
+
default=False, help_text="Whether this is the default API key to use"
|
144
53
|
),
|
145
54
|
),
|
146
55
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
147
56
|
("updated_at", models.DateTimeField(auto_now=True)),
|
148
57
|
(
|
149
|
-
"
|
58
|
+
"last_used_at",
|
150
59
|
models.DateTimeField(
|
151
|
-
blank=True, help_text="When
|
152
|
-
),
|
153
|
-
),
|
154
|
-
(
|
155
|
-
"allowed_users",
|
156
|
-
models.ManyToManyField(
|
157
|
-
blank=True,
|
158
|
-
help_text="Users with access to manage this site",
|
159
|
-
related_name="accessible_sites",
|
160
|
-
to=settings.AUTH_USER_MODEL,
|
161
|
-
),
|
162
|
-
),
|
163
|
-
(
|
164
|
-
"owner",
|
165
|
-
models.ForeignKey(
|
166
|
-
help_text="Site owner",
|
167
|
-
on_delete=django.db.models.deletion.CASCADE,
|
168
|
-
related_name="owned_sites",
|
169
|
-
to=settings.AUTH_USER_MODEL,
|
60
|
+
blank=True, help_text="When this API key was last used", null=True
|
170
61
|
),
|
171
62
|
),
|
172
63
|
],
|
173
64
|
options={
|
174
|
-
"verbose_name": "Cloudflare
|
175
|
-
"verbose_name_plural": "Cloudflare
|
176
|
-
"ordering": ["name"],
|
65
|
+
"verbose_name": "Cloudflare API Key",
|
66
|
+
"verbose_name_plural": "Cloudflare API Keys",
|
67
|
+
"ordering": ["-is_default", "name"],
|
68
|
+
"indexes": [
|
69
|
+
models.Index(fields=["is_active"], name="maintenance_is_acti_a3fc7a_idx"),
|
70
|
+
models.Index(fields=["is_default"], name="maintenance_is_defa_10fec0_idx"),
|
71
|
+
],
|
177
72
|
},
|
178
73
|
),
|
179
74
|
migrations.CreateModel(
|
180
|
-
name="
|
75
|
+
name="CloudflareSite",
|
181
76
|
fields=[
|
182
77
|
(
|
183
78
|
"id",
|
@@ -186,146 +81,59 @@ class Migration(migrations.Migration):
|
|
186
81
|
),
|
187
82
|
),
|
188
83
|
(
|
189
|
-
"
|
190
|
-
models.CharField(
|
191
|
-
help_text="Human-readable maintenance event title", max_length=200
|
192
|
-
),
|
193
|
-
),
|
194
|
-
(
|
195
|
-
"description",
|
196
|
-
models.TextField(
|
197
|
-
blank=True, help_text="Detailed description of maintenance work"
|
198
|
-
),
|
199
|
-
),
|
200
|
-
(
|
201
|
-
"reason",
|
84
|
+
"name",
|
202
85
|
models.CharField(
|
203
|
-
|
204
|
-
("manual", "Manual Activation"),
|
205
|
-
("server_down", "Server Unreachable"),
|
206
|
-
("high_error_rate", "High Error Rate"),
|
207
|
-
("database_issues", "Database Issues"),
|
208
|
-
("deployment", "Deployment"),
|
209
|
-
("security_update", "Security Update"),
|
210
|
-
("scheduled", "Scheduled Maintenance"),
|
211
|
-
("emergency", "Emergency Maintenance"),
|
212
|
-
],
|
213
|
-
default="manual",
|
214
|
-
help_text="Reason for maintenance activation",
|
215
|
-
max_length=50,
|
86
|
+
help_text="Friendly site name for identification", max_length=100
|
216
87
|
),
|
217
88
|
),
|
218
89
|
(
|
219
|
-
"
|
90
|
+
"domain",
|
220
91
|
models.CharField(
|
221
|
-
|
222
|
-
("scheduled", "Scheduled"),
|
223
|
-
("active", "Active"),
|
224
|
-
("completed", "Completed"),
|
225
|
-
("failed", "Failed"),
|
226
|
-
("cancelled", "Cancelled"),
|
227
|
-
],
|
228
|
-
default="active",
|
229
|
-
help_text="Current maintenance status",
|
230
|
-
max_length=20,
|
231
|
-
),
|
232
|
-
),
|
233
|
-
(
|
234
|
-
"started_at",
|
235
|
-
models.DateTimeField(
|
236
|
-
default=django.utils.timezone.now, help_text="When maintenance was started"
|
92
|
+
help_text="Domain name (e.g., vamcar.com)", max_length=255, unique=True
|
237
93
|
),
|
238
94
|
),
|
239
95
|
(
|
240
|
-
"
|
241
|
-
models.
|
242
|
-
blank=True, help_text="When maintenance was completed", null=True
|
243
|
-
),
|
244
|
-
),
|
245
|
-
(
|
246
|
-
"estimated_duration",
|
247
|
-
models.DurationField(
|
248
|
-
blank=True, help_text="Estimated maintenance duration", null=True
|
249
|
-
),
|
96
|
+
"zone_id",
|
97
|
+
models.CharField(help_text="Cloudflare Zone ID", max_length=32, unique=True),
|
250
98
|
),
|
99
|
+
("account_id", models.CharField(help_text="Cloudflare Account ID", max_length=32)),
|
251
100
|
(
|
252
|
-
"
|
101
|
+
"maintenance_active",
|
253
102
|
models.BooleanField(
|
254
|
-
default=False, help_text="Whether
|
255
|
-
),
|
256
|
-
),
|
257
|
-
(
|
258
|
-
"cloudflare_deployment_id",
|
259
|
-
models.CharField(
|
260
|
-
blank=True, help_text="Cloudflare deployment identifier", max_length=100
|
103
|
+
default=False, help_text="Whether maintenance mode is currently active"
|
261
104
|
),
|
262
105
|
),
|
263
106
|
(
|
264
|
-
"
|
107
|
+
"is_active",
|
265
108
|
models.BooleanField(
|
266
|
-
default=
|
267
|
-
),
|
268
|
-
),
|
269
|
-
(
|
270
|
-
"affected_requests",
|
271
|
-
models.PositiveIntegerField(
|
272
|
-
default=0, help_text="Number of requests affected during maintenance"
|
273
|
-
),
|
274
|
-
),
|
275
|
-
(
|
276
|
-
"error_count_before",
|
277
|
-
models.PositiveIntegerField(
|
278
|
-
default=0, help_text="Error count before maintenance"
|
279
|
-
),
|
280
|
-
),
|
281
|
-
(
|
282
|
-
"error_count_during",
|
283
|
-
models.PositiveIntegerField(
|
284
|
-
default=0, help_text="Error count during maintenance"
|
109
|
+
default=True, help_text="Whether this site is active in our system"
|
285
110
|
),
|
286
111
|
),
|
287
112
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
288
113
|
("updated_at", models.DateTimeField(auto_now=True)),
|
289
114
|
(
|
290
|
-
"
|
291
|
-
models.
|
292
|
-
blank=True,
|
293
|
-
help_text="User who completed maintenance",
|
294
|
-
null=True,
|
295
|
-
on_delete=django.db.models.deletion.SET_NULL,
|
296
|
-
related_name="completed_maintenance_events",
|
297
|
-
to=settings.AUTH_USER_MODEL,
|
115
|
+
"last_maintenance_at",
|
116
|
+
models.DateTimeField(
|
117
|
+
blank=True, help_text="When maintenance was last activated", null=True
|
298
118
|
),
|
299
119
|
),
|
300
120
|
(
|
301
|
-
"
|
121
|
+
"api_key",
|
302
122
|
models.ForeignKey(
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
on_delete=django.db.models.deletion.SET_NULL,
|
307
|
-
related_name="initiated_maintenance_events",
|
308
|
-
to=settings.AUTH_USER_MODEL,
|
309
|
-
),
|
310
|
-
),
|
311
|
-
(
|
312
|
-
"sites",
|
313
|
-
models.ManyToManyField(
|
314
|
-
blank=True,
|
315
|
-
help_text="Sites affected by this maintenance event",
|
316
|
-
related_name="maintenance_events",
|
317
|
-
to="django_cfg_maintenance.cloudflaresite",
|
123
|
+
help_text="API key to use for this site",
|
124
|
+
on_delete=django.db.models.deletion.PROTECT,
|
125
|
+
to="maintenance.cloudflareapikey",
|
318
126
|
),
|
319
127
|
),
|
320
128
|
],
|
321
129
|
options={
|
322
|
-
"verbose_name": "
|
323
|
-
"verbose_name_plural": "
|
324
|
-
"ordering": ["
|
130
|
+
"verbose_name": "Cloudflare Site",
|
131
|
+
"verbose_name_plural": "Cloudflare Sites",
|
132
|
+
"ordering": ["name"],
|
325
133
|
},
|
326
134
|
),
|
327
135
|
migrations.CreateModel(
|
328
|
-
name="
|
136
|
+
name="MaintenanceLog",
|
329
137
|
fields=[
|
330
138
|
(
|
331
139
|
"id",
|
@@ -334,211 +142,71 @@ class Migration(migrations.Migration):
|
|
334
142
|
),
|
335
143
|
),
|
336
144
|
(
|
337
|
-
"
|
145
|
+
"action",
|
338
146
|
models.CharField(
|
339
147
|
choices=[
|
340
|
-
("
|
341
|
-
("
|
342
|
-
("
|
343
|
-
("
|
344
|
-
("custom_error_page", "Custom Error Page"),
|
148
|
+
("enable", "Enable Maintenance"),
|
149
|
+
("disable", "Disable Maintenance"),
|
150
|
+
("error", "Error"),
|
151
|
+
("sync", "Sync from Cloudflare"),
|
345
152
|
],
|
346
|
-
|
347
|
-
|
348
|
-
max_length=50,
|
349
|
-
),
|
350
|
-
),
|
351
|
-
(
|
352
|
-
"resource_name",
|
353
|
-
models.CharField(
|
354
|
-
help_text="Name of the deployed resource (Worker name, Page Rule, etc.)",
|
355
|
-
max_length=200,
|
356
|
-
),
|
357
|
-
),
|
358
|
-
(
|
359
|
-
"resource_id",
|
360
|
-
models.CharField(
|
361
|
-
blank=True,
|
362
|
-
help_text="Cloudflare resource ID after deployment",
|
363
|
-
max_length=100,
|
153
|
+
help_text="What action was performed",
|
154
|
+
max_length=20,
|
364
155
|
),
|
365
156
|
),
|
366
157
|
(
|
367
158
|
"status",
|
368
159
|
models.CharField(
|
369
160
|
choices=[
|
370
|
-
("
|
371
|
-
("deploying", "Deploying"),
|
372
|
-
("deployed", "Deployed"),
|
161
|
+
("success", "Success"),
|
373
162
|
("failed", "Failed"),
|
374
|
-
("
|
163
|
+
("pending", "Pending"),
|
375
164
|
],
|
376
|
-
|
377
|
-
help_text="Current deployment status",
|
165
|
+
help_text="Result of the operation",
|
378
166
|
max_length=20,
|
379
167
|
),
|
380
168
|
),
|
381
169
|
(
|
382
|
-
"
|
383
|
-
models.
|
384
|
-
auto_now_add=True, help_text="When deployment was initiated"
|
385
|
-
),
|
386
|
-
),
|
387
|
-
(
|
388
|
-
"deployed_at",
|
389
|
-
models.DateTimeField(
|
390
|
-
blank=True, help_text="When deployment completed successfully", null=True
|
391
|
-
),
|
392
|
-
),
|
393
|
-
(
|
394
|
-
"failed_at",
|
395
|
-
models.DateTimeField(blank=True, help_text="When deployment failed", null=True),
|
396
|
-
),
|
397
|
-
(
|
398
|
-
"configuration",
|
399
|
-
models.JSONField(
|
400
|
-
default=dict,
|
401
|
-
help_text="Deployment configuration (Worker script, Page Rule settings, etc.)",
|
402
|
-
),
|
403
|
-
),
|
404
|
-
(
|
405
|
-
"cloudflare_response",
|
406
|
-
models.JSONField(
|
407
|
-
blank=True, default=dict, help_text="Full response from Cloudflare API"
|
408
|
-
),
|
170
|
+
"reason",
|
171
|
+
models.TextField(blank=True, help_text="Why maintenance was enabled/disabled"),
|
409
172
|
),
|
410
173
|
(
|
411
174
|
"error_message",
|
412
|
-
models.TextField(blank=True, help_text="Error
|
175
|
+
models.TextField(blank=True, help_text="Error details if operation failed"),
|
413
176
|
),
|
414
177
|
(
|
415
|
-
"
|
178
|
+
"cloudflare_response",
|
416
179
|
models.JSONField(
|
417
180
|
blank=True,
|
418
|
-
|
419
|
-
help_text="Data needed for rollback (previous configuration, etc.)",
|
420
|
-
),
|
421
|
-
),
|
422
|
-
(
|
423
|
-
"previous_deployment",
|
424
|
-
models.ForeignKey(
|
425
|
-
blank=True,
|
426
|
-
help_text="Previous deployment for rollback",
|
181
|
+
help_text="Full Cloudflare API response for debugging",
|
427
182
|
null=True,
|
428
|
-
on_delete=django.db.models.deletion.SET_NULL,
|
429
|
-
related_name="rollback_deployments",
|
430
|
-
to="django_cfg_maintenance.cloudflaredeployment",
|
431
|
-
),
|
432
|
-
),
|
433
|
-
(
|
434
|
-
"site",
|
435
|
-
models.ForeignKey(
|
436
|
-
help_text="Site this deployment belongs to",
|
437
|
-
on_delete=django.db.models.deletion.CASCADE,
|
438
|
-
related_name="deployments",
|
439
|
-
to="django_cfg_maintenance.cloudflaresite",
|
440
|
-
),
|
441
|
-
),
|
442
|
-
(
|
443
|
-
"maintenance_event",
|
444
|
-
models.ForeignKey(
|
445
|
-
blank=True,
|
446
|
-
help_text="Related maintenance event",
|
447
|
-
null=True,
|
448
|
-
on_delete=django.db.models.deletion.SET_NULL,
|
449
|
-
related_name="cloudflare_deployments",
|
450
|
-
to="django_cfg_maintenance.maintenanceevent",
|
451
|
-
),
|
452
|
-
),
|
453
|
-
],
|
454
|
-
options={
|
455
|
-
"verbose_name": "Cloudflare Deployment",
|
456
|
-
"verbose_name_plural": "Cloudflare Deployments",
|
457
|
-
"ordering": ["-created_at"],
|
458
|
-
},
|
459
|
-
),
|
460
|
-
migrations.CreateModel(
|
461
|
-
name="MaintenanceLog",
|
462
|
-
fields=[
|
463
|
-
(
|
464
|
-
"id",
|
465
|
-
models.BigAutoField(
|
466
|
-
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
467
|
-
),
|
468
|
-
),
|
469
|
-
(
|
470
|
-
"level",
|
471
|
-
models.CharField(
|
472
|
-
choices=[
|
473
|
-
("debug", "Debug"),
|
474
|
-
("info", "Info"),
|
475
|
-
("warning", "Warning"),
|
476
|
-
("error", "Error"),
|
477
|
-
("critical", "Critical"),
|
478
|
-
],
|
479
|
-
default="info",
|
480
|
-
help_text="Log level",
|
481
|
-
max_length=20,
|
482
|
-
),
|
483
|
-
),
|
484
|
-
("message", models.TextField(help_text="Log message")),
|
485
|
-
(
|
486
|
-
"details",
|
487
|
-
models.JSONField(
|
488
|
-
blank=True, default=dict, help_text="Additional log details (JSON)"
|
489
|
-
),
|
490
|
-
),
|
491
|
-
(
|
492
|
-
"component",
|
493
|
-
models.CharField(
|
494
|
-
blank=True,
|
495
|
-
help_text="Component that generated the log (e.g., 'cloudflare', 'monitoring')",
|
496
|
-
max_length=100,
|
497
|
-
),
|
498
|
-
),
|
499
|
-
(
|
500
|
-
"operation",
|
501
|
-
models.CharField(
|
502
|
-
blank=True,
|
503
|
-
help_text="Operation being performed (e.g., 'deploy_worker', 'health_check')",
|
504
|
-
max_length=100,
|
505
183
|
),
|
506
184
|
),
|
185
|
+
("created_at", models.DateTimeField(auto_now_add=True)),
|
507
186
|
(
|
508
|
-
"
|
509
|
-
models.
|
510
|
-
|
511
|
-
help_text="When the log entry was created",
|
187
|
+
"duration_seconds",
|
188
|
+
models.IntegerField(
|
189
|
+
blank=True, help_text="How long the operation took", null=True
|
512
190
|
),
|
513
191
|
),
|
514
192
|
(
|
515
|
-
"
|
193
|
+
"site",
|
516
194
|
models.ForeignKey(
|
517
|
-
help_text="
|
195
|
+
help_text="Site this log entry belongs to",
|
518
196
|
on_delete=django.db.models.deletion.CASCADE,
|
519
197
|
related_name="logs",
|
520
|
-
to="
|
521
|
-
),
|
522
|
-
),
|
523
|
-
(
|
524
|
-
"user",
|
525
|
-
models.ForeignKey(
|
526
|
-
blank=True,
|
527
|
-
help_text="User associated with this log entry",
|
528
|
-
null=True,
|
529
|
-
on_delete=django.db.models.deletion.SET_NULL,
|
530
|
-
to=settings.AUTH_USER_MODEL,
|
198
|
+
to="maintenance.cloudflaresite",
|
531
199
|
),
|
532
200
|
),
|
533
201
|
],
|
534
202
|
options={
|
535
203
|
"verbose_name": "Maintenance Log",
|
536
204
|
"verbose_name_plural": "Maintenance Logs",
|
537
|
-
"ordering": ["-
|
205
|
+
"ordering": ["-created_at"],
|
538
206
|
},
|
539
207
|
),
|
540
208
|
migrations.CreateModel(
|
541
|
-
name="
|
209
|
+
name="ScheduledMaintenance",
|
542
210
|
fields=[
|
543
211
|
(
|
544
212
|
"id",
|
@@ -546,394 +214,166 @@ class Migration(migrations.Migration):
|
|
546
214
|
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
547
215
|
),
|
548
216
|
),
|
549
|
-
("
|
550
|
-
(
|
551
|
-
"check_interval",
|
552
|
-
models.PositiveIntegerField(default=60, help_text="Check interval in seconds"),
|
553
|
-
),
|
554
|
-
(
|
555
|
-
"timeout",
|
556
|
-
models.PositiveIntegerField(default=10, help_text="Request timeout in seconds"),
|
557
|
-
),
|
217
|
+
("title", models.CharField(help_text="Maintenance event title", max_length=200)),
|
558
218
|
(
|
559
|
-
"
|
560
|
-
models.
|
561
|
-
default=list, help_text="Expected HTTP status codes (e.g., [200, 201])"
|
562
|
-
),
|
563
|
-
),
|
564
|
-
(
|
565
|
-
"expected_response_time_ms",
|
566
|
-
models.PositiveIntegerField(
|
567
|
-
blank=True,
|
568
|
-
help_text="Maximum expected response time in milliseconds",
|
569
|
-
null=True,
|
570
|
-
),
|
219
|
+
"description",
|
220
|
+
models.TextField(blank=True, help_text="Detailed description of maintenance"),
|
571
221
|
),
|
572
222
|
(
|
573
|
-
"
|
574
|
-
models.
|
575
|
-
blank=True, help_text="Expected content in response body (substring match)"
|
576
|
-
),
|
223
|
+
"scheduled_start",
|
224
|
+
models.DateTimeField(help_text="When maintenance should start"),
|
577
225
|
),
|
578
226
|
(
|
579
|
-
"
|
580
|
-
models.
|
581
|
-
default=3, help_text="Consecutive failures before triggering maintenance"
|
582
|
-
),
|
227
|
+
"estimated_duration",
|
228
|
+
models.DurationField(help_text="Expected duration of maintenance"),
|
583
229
|
),
|
584
230
|
(
|
585
|
-
"
|
586
|
-
models.
|
587
|
-
default=2, help_text="Consecutive successes before disabling maintenance"
|
588
|
-
),
|
231
|
+
"scheduled_end",
|
232
|
+
models.DateTimeField(editable=False, help_text="Auto-calculated end time"),
|
589
233
|
),
|
590
234
|
(
|
591
235
|
"status",
|
592
236
|
models.CharField(
|
593
237
|
choices=[
|
238
|
+
("scheduled", "Scheduled"),
|
594
239
|
("active", "Active"),
|
595
|
-
("
|
596
|
-
("
|
597
|
-
("
|
240
|
+
("completed", "Completed"),
|
241
|
+
("cancelled", "Cancelled"),
|
242
|
+
("failed", "Failed"),
|
598
243
|
],
|
599
|
-
default="
|
600
|
-
help_text="Current monitoring status",
|
244
|
+
default="scheduled",
|
601
245
|
max_length=20,
|
602
246
|
),
|
603
247
|
),
|
604
248
|
(
|
605
|
-
"
|
606
|
-
models.
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
default=
|
614
|
-
|
615
|
-
),
|
616
|
-
(
|
617
|
-
"last_check_at",
|
618
|
-
models.DateTimeField(
|
619
|
-
blank=True, help_text="When last health check was performed", null=True
|
620
|
-
),
|
621
|
-
),
|
622
|
-
(
|
623
|
-
"last_check_success",
|
624
|
-
models.BooleanField(
|
625
|
-
default=True, help_text="Whether last check was successful"
|
249
|
+
"priority",
|
250
|
+
models.CharField(
|
251
|
+
choices=[
|
252
|
+
("low", "Low"),
|
253
|
+
("normal", "Normal"),
|
254
|
+
("high", "High"),
|
255
|
+
("critical", "Critical"),
|
256
|
+
],
|
257
|
+
default="normal",
|
258
|
+
max_length=20,
|
626
259
|
),
|
627
260
|
),
|
261
|
+
("actual_start", models.DateTimeField(blank=True, null=True)),
|
262
|
+
("actual_end", models.DateTimeField(blank=True, null=True)),
|
628
263
|
(
|
629
|
-
"
|
630
|
-
models.
|
631
|
-
blank=True,
|
632
|
-
help_text="Response time of last check in milliseconds",
|
633
|
-
null=True,
|
264
|
+
"maintenance_message",
|
265
|
+
models.TextField(
|
266
|
+
blank=True, help_text="Custom message to display during maintenance"
|
634
267
|
),
|
635
268
|
),
|
636
269
|
(
|
637
|
-
"
|
638
|
-
models.
|
639
|
-
|
640
|
-
|
270
|
+
"template",
|
271
|
+
models.CharField(
|
272
|
+
choices=[
|
273
|
+
("modern", "Modern"),
|
274
|
+
("simple", "Simple"),
|
275
|
+
("premium", "Premium"),
|
276
|
+
("minimal", "Minimal"),
|
277
|
+
],
|
278
|
+
default="modern",
|
279
|
+
help_text="Maintenance page template",
|
280
|
+
max_length=50,
|
641
281
|
),
|
642
282
|
),
|
643
283
|
(
|
644
|
-
"
|
284
|
+
"auto_enable",
|
645
285
|
models.BooleanField(
|
646
|
-
default=True,
|
647
|
-
help_text="Automatically disable maintenance on recovery threshold",
|
648
|
-
),
|
649
|
-
),
|
650
|
-
(
|
651
|
-
"maintenance_triggered_at",
|
652
|
-
models.DateTimeField(
|
653
|
-
blank=True, help_text="When maintenance was last auto-triggered", null=True
|
654
|
-
),
|
655
|
-
),
|
656
|
-
(
|
657
|
-
"user_agent",
|
658
|
-
models.CharField(
|
659
|
-
default="Django-CFG-Monitor/1.0",
|
660
|
-
help_text="User agent for health checks",
|
661
|
-
max_length=200,
|
286
|
+
default=True, help_text="Automatically enable maintenance at scheduled time"
|
662
287
|
),
|
663
288
|
),
|
664
289
|
(
|
665
|
-
"
|
290
|
+
"auto_disable",
|
666
291
|
models.BooleanField(
|
667
|
-
default=True, help_text="
|
292
|
+
default=True, help_text="Automatically disable maintenance after duration"
|
668
293
|
),
|
669
294
|
),
|
670
295
|
(
|
671
|
-
"
|
672
|
-
models.
|
673
|
-
|
674
|
-
|
675
|
-
"custom_headers",
|
676
|
-
models.JSONField(
|
677
|
-
blank=True,
|
678
|
-
default=dict,
|
679
|
-
help_text="Custom headers for health check requests",
|
296
|
+
"notify_before",
|
297
|
+
models.DurationField(
|
298
|
+
default=datetime.timedelta(seconds=3600),
|
299
|
+
help_text="Send notification before maintenance starts",
|
680
300
|
),
|
681
301
|
),
|
302
|
+
("notify_on_start", models.BooleanField(default=True)),
|
303
|
+
("notify_on_complete", models.BooleanField(default=True)),
|
682
304
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
683
305
|
("updated_at", models.DateTimeField(auto_now=True)),
|
684
306
|
(
|
685
|
-
"
|
686
|
-
models.OneToOneField(
|
687
|
-
help_text="Site being monitored",
|
688
|
-
on_delete=django.db.models.deletion.CASCADE,
|
689
|
-
related_name="monitoring_target",
|
690
|
-
to="django_cfg_maintenance.cloudflaresite",
|
691
|
-
),
|
692
|
-
),
|
693
|
-
],
|
694
|
-
options={
|
695
|
-
"verbose_name": "Monitoring Target",
|
696
|
-
"verbose_name_plural": "Monitoring Targets",
|
697
|
-
},
|
698
|
-
),
|
699
|
-
migrations.CreateModel(
|
700
|
-
name="HealthCheckResult",
|
701
|
-
fields=[
|
702
|
-
(
|
703
|
-
"id",
|
704
|
-
models.BigAutoField(
|
705
|
-
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
706
|
-
),
|
707
|
-
),
|
708
|
-
(
|
709
|
-
"timestamp",
|
710
|
-
models.DateTimeField(
|
711
|
-
default=django.utils.timezone.now, help_text="When the check was performed"
|
712
|
-
),
|
713
|
-
),
|
714
|
-
("success", models.BooleanField(help_text="Whether the check was successful")),
|
715
|
-
(
|
716
|
-
"status_code",
|
717
|
-
models.PositiveIntegerField(
|
718
|
-
blank=True, help_text="HTTP response status code", null=True
|
719
|
-
),
|
720
|
-
),
|
721
|
-
(
|
722
|
-
"response_time_ms",
|
723
|
-
models.PositiveIntegerField(
|
724
|
-
blank=True, help_text="Response time in milliseconds", null=True
|
725
|
-
),
|
726
|
-
),
|
727
|
-
(
|
728
|
-
"response_size_bytes",
|
729
|
-
models.PositiveIntegerField(
|
730
|
-
blank=True, help_text="Response size in bytes", null=True
|
731
|
-
),
|
732
|
-
),
|
733
|
-
(
|
734
|
-
"error_message",
|
735
|
-
models.TextField(blank=True, help_text="Error message if check failed"),
|
736
|
-
),
|
737
|
-
(
|
738
|
-
"error_type",
|
307
|
+
"created_by",
|
739
308
|
models.CharField(
|
740
|
-
blank=True,
|
741
|
-
help_text="Type of error (timeout, connection, etc.)",
|
742
|
-
max_length=100,
|
743
|
-
),
|
744
|
-
),
|
745
|
-
(
|
746
|
-
"details",
|
747
|
-
models.JSONField(
|
748
|
-
blank=True,
|
749
|
-
default=dict,
|
750
|
-
help_text="Additional check details (headers, content, etc.)",
|
309
|
+
blank=True, help_text="Who created this maintenance", max_length=100
|
751
310
|
),
|
752
311
|
),
|
753
312
|
(
|
754
|
-
"
|
755
|
-
models.ForeignKey(
|
756
|
-
help_text="Monitoring target this result belongs to",
|
757
|
-
on_delete=django.db.models.deletion.CASCADE,
|
758
|
-
related_name="results",
|
759
|
-
to="django_cfg_maintenance.monitoringtarget",
|
760
|
-
),
|
761
|
-
),
|
762
|
-
],
|
763
|
-
options={
|
764
|
-
"verbose_name": "Health Check Result",
|
765
|
-
"verbose_name_plural": "Health Check Results",
|
766
|
-
"ordering": ["-timestamp"],
|
767
|
-
},
|
768
|
-
),
|
769
|
-
migrations.CreateModel(
|
770
|
-
name="SiteGroup",
|
771
|
-
fields=[
|
772
|
-
(
|
773
|
-
"id",
|
774
|
-
models.BigAutoField(
|
775
|
-
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
776
|
-
),
|
777
|
-
),
|
778
|
-
("name", models.CharField(help_text="Group name", max_length=100)),
|
779
|
-
("description", models.TextField(blank=True, help_text="Group description")),
|
780
|
-
(
|
781
|
-
"auto_maintenance_rules",
|
313
|
+
"execution_log",
|
782
314
|
models.JSONField(
|
783
|
-
blank=True,
|
784
|
-
default=dict,
|
785
|
-
help_text="Automatic maintenance rules for this group",
|
786
|
-
),
|
787
|
-
),
|
788
|
-
(
|
789
|
-
"notification_settings",
|
790
|
-
models.JSONField(
|
791
|
-
blank=True,
|
792
|
-
default=dict,
|
793
|
-
help_text="Notification preferences for group events",
|
794
|
-
),
|
795
|
-
),
|
796
|
-
("created_at", models.DateTimeField(auto_now_add=True)),
|
797
|
-
("updated_at", models.DateTimeField(auto_now=True)),
|
798
|
-
(
|
799
|
-
"owner",
|
800
|
-
models.ForeignKey(
|
801
|
-
help_text="Group owner",
|
802
|
-
on_delete=django.db.models.deletion.CASCADE,
|
803
|
-
to=settings.AUTH_USER_MODEL,
|
315
|
+
blank=True, default=dict, help_text="Log of execution steps and results"
|
804
316
|
),
|
805
317
|
),
|
806
318
|
(
|
807
319
|
"sites",
|
808
320
|
models.ManyToManyField(
|
809
|
-
help_text="Sites
|
810
|
-
related_name="
|
811
|
-
to="
|
321
|
+
help_text="Sites affected by this maintenance",
|
322
|
+
related_name="scheduled_maintenances",
|
323
|
+
to="maintenance.cloudflaresite",
|
812
324
|
),
|
813
325
|
),
|
814
326
|
],
|
815
327
|
options={
|
816
|
-
"verbose_name": "
|
817
|
-
"verbose_name_plural": "
|
818
|
-
"ordering": ["
|
328
|
+
"verbose_name": "Scheduled Maintenance",
|
329
|
+
"verbose_name_plural": "Scheduled Maintenances",
|
330
|
+
"ordering": ["scheduled_start"],
|
819
331
|
},
|
820
332
|
),
|
821
333
|
migrations.AddIndex(
|
822
334
|
model_name="cloudflaresite",
|
823
|
-
index=models.Index(
|
824
|
-
fields=["owner", "environment"], name="django_cfg__owner_i_5d4060_idx"
|
825
|
-
),
|
335
|
+
index=models.Index(fields=["domain"], name="maintenance_domain_b9a739_idx"),
|
826
336
|
),
|
827
337
|
migrations.AddIndex(
|
828
338
|
model_name="cloudflaresite",
|
829
339
|
index=models.Index(
|
830
|
-
fields=["
|
340
|
+
fields=["maintenance_active"], name="maintenance_mainten_26f0c1_idx"
|
831
341
|
),
|
832
342
|
),
|
833
343
|
migrations.AddIndex(
|
834
344
|
model_name="cloudflaresite",
|
835
|
-
index=models.Index(fields=["
|
836
|
-
),
|
837
|
-
migrations.AddIndex(
|
838
|
-
model_name="cloudflaresite",
|
839
|
-
index=models.Index(
|
840
|
-
fields=["maintenance_active"], name="django_cfg__mainten_0c725d_idx"
|
841
|
-
),
|
842
|
-
),
|
843
|
-
migrations.AddIndex(
|
844
|
-
model_name="cloudflaresite",
|
845
|
-
index=models.Index(fields=["domain"], name="django_cfg__domain_179845_idx"),
|
846
|
-
),
|
847
|
-
migrations.AddIndex(
|
848
|
-
model_name="maintenanceevent",
|
849
|
-
index=models.Index(
|
850
|
-
fields=["status", "-started_at"], name="django_cfg__status_a7d5f3_idx"
|
851
|
-
),
|
852
|
-
),
|
853
|
-
migrations.AddIndex(
|
854
|
-
model_name="maintenanceevent",
|
855
|
-
index=models.Index(
|
856
|
-
fields=["reason", "-started_at"], name="django_cfg__reason_214648_idx"
|
857
|
-
),
|
858
|
-
),
|
859
|
-
migrations.AddIndex(
|
860
|
-
model_name="maintenanceevent",
|
861
|
-
index=models.Index(
|
862
|
-
fields=["initiated_by", "-started_at"], name="django_cfg__initiat_7ad0ad_idx"
|
863
|
-
),
|
864
|
-
),
|
865
|
-
migrations.AddIndex(
|
866
|
-
model_name="cloudflaredeployment",
|
867
|
-
index=models.Index(
|
868
|
-
fields=["site", "-created_at"], name="django_cfg__site_id_7414e8_idx"
|
869
|
-
),
|
870
|
-
),
|
871
|
-
migrations.AddIndex(
|
872
|
-
model_name="cloudflaredeployment",
|
873
|
-
index=models.Index(
|
874
|
-
fields=["status", "-created_at"], name="django_cfg__status_ee1f80_idx"
|
875
|
-
),
|
876
|
-
),
|
877
|
-
migrations.AddIndex(
|
878
|
-
model_name="cloudflaredeployment",
|
879
|
-
index=models.Index(
|
880
|
-
fields=["deployment_type", "-created_at"], name="django_cfg__deploym_bc24ff_idx"
|
881
|
-
),
|
882
|
-
),
|
883
|
-
migrations.AddIndex(
|
884
|
-
model_name="cloudflaredeployment",
|
885
|
-
index=models.Index(fields=["resource_id"], name="django_cfg__resourc_fab8ca_idx"),
|
345
|
+
index=models.Index(fields=["is_active"], name="maintenance_is_acti_335998_idx"),
|
886
346
|
),
|
887
347
|
migrations.AddIndex(
|
888
348
|
model_name="maintenancelog",
|
889
349
|
index=models.Index(
|
890
|
-
fields=["
|
350
|
+
fields=["site", "-created_at"], name="maintenance_site_id_c57d8c_idx"
|
891
351
|
),
|
892
352
|
),
|
893
353
|
migrations.AddIndex(
|
894
354
|
model_name="maintenancelog",
|
895
|
-
index=models.Index(fields=["level", "-timestamp"], name="django_cfg__level_b66e18_idx"),
|
896
|
-
),
|
897
|
-
migrations.AddIndex(
|
898
|
-
model_name="maintenancelog",
|
899
|
-
index=models.Index(
|
900
|
-
fields=["component", "-timestamp"], name="django_cfg__compone_35dbe4_idx"
|
901
|
-
),
|
902
|
-
),
|
903
|
-
migrations.AddIndex(
|
904
|
-
model_name="monitoringtarget",
|
905
355
|
index=models.Index(
|
906
|
-
fields=["
|
356
|
+
fields=["action", "-created_at"], name="maintenance_action_1676f8_idx"
|
907
357
|
),
|
908
358
|
),
|
909
359
|
migrations.AddIndex(
|
910
|
-
model_name="
|
911
|
-
index=models.Index(
|
912
|
-
fields=["site", "-last_check_at"], name="django_cfg__site_id_37651c_idx"
|
913
|
-
),
|
914
|
-
),
|
915
|
-
migrations.AddIndex(
|
916
|
-
model_name="healthcheckresult",
|
360
|
+
model_name="maintenancelog",
|
917
361
|
index=models.Index(
|
918
|
-
fields=["
|
362
|
+
fields=["status", "-created_at"], name="maintenance_status_47eaad_idx"
|
919
363
|
),
|
920
364
|
),
|
921
365
|
migrations.AddIndex(
|
922
|
-
model_name="
|
366
|
+
model_name="scheduledmaintenance",
|
923
367
|
index=models.Index(
|
924
|
-
fields=["
|
368
|
+
fields=["status", "scheduled_start"], name="maintenance_status_77021b_idx"
|
925
369
|
),
|
926
370
|
),
|
927
371
|
migrations.AddIndex(
|
928
|
-
model_name="
|
929
|
-
index=models.Index(fields=["
|
372
|
+
model_name="scheduledmaintenance",
|
373
|
+
index=models.Index(fields=["scheduled_start"], name="maintenance_schedul_7c49c4_idx"),
|
930
374
|
),
|
931
375
|
migrations.AddIndex(
|
932
|
-
model_name="
|
933
|
-
index=models.Index(fields=["
|
934
|
-
),
|
935
|
-
migrations.AlterUniqueTogether(
|
936
|
-
name="sitegroup",
|
937
|
-
unique_together={("name", "owner")},
|
376
|
+
model_name="scheduledmaintenance",
|
377
|
+
index=models.Index(fields=["status"], name="maintenance_status_92c0e9_idx"),
|
938
378
|
),
|
939
379
|
]
|