Skip to content

Commit 697fb0d

Browse files
authored
feat(controller): support autorollback config (#154)
1 parent 5a9f5af commit 697fb0d

5 files changed

Lines changed: 59 additions & 2 deletions

File tree

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 4.2.15 on 2024-08-13 07:28
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('api', '0009_remove_appsettings_canaries_remove_release_canary_and_more'),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name='appsettings',
15+
name='autorollback',
16+
field=models.BooleanField(default=True),
17+
),
18+
]

rootfs/api/models/app.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,10 @@ def pipeline(self, release, force_deploy=False, rollback_on_failure=True):
240240
raise DryccException(f'pipeline run state error: {state}')
241241
if procfile_types is None or len(procfile_types) > 0:
242242
self.log(f"{prefix} starts running pipeline.deploy")
243+
app_settings = self.appsettings_set.latest()
244+
if app_settings.autorollback is False:
245+
self.log(f"{prefix} deploy do not rollback on failure")
246+
rollback_on_failure = False
243247
self.deploy(release, procfile_types, force_deploy, rollback_on_failure)
244248
else:
245249
self.log(f"{prefix} no changes, skip executing pipeline.deploy")

rootfs/api/models/appsettings.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class AppSettings(UuidAuditedModel):
2020
owner = models.ForeignKey(User, on_delete=models.PROTECT)
2121
app = models.ForeignKey('App', on_delete=models.CASCADE)
2222
routable = models.BooleanField(default=True)
23+
autorollback = models.BooleanField(default=True)
2324
autoscale = models.JSONField(default=dict, blank=True)
2425
label = models.JSONField(default=dict, blank=True)
2526

@@ -71,6 +72,15 @@ def _update_routable(self, previous_settings):
7172
elif old != new:
7273
self.summary += ["{} changed routablity from {} to {}".format(self.owner, old, new)]
7374

75+
def _update_autorollback(self, previous_settings):
76+
old = getattr(previous_settings, 'autorollback', None)
77+
new = getattr(self, 'autorollback', None)
78+
# if nothing changed copy the settings from previous
79+
if new is None and old is not None:
80+
setattr(self, 'autorollback', old)
81+
elif old != new:
82+
self.summary += ["{} changed autorollback from {} to {}".format(self.owner, old, new)]
83+
7484
def _update_autoscale(self, previous_settings):
7585
data = getattr(previous_settings, 'autoscale', {}).copy()
7686
new = getattr(self, 'autoscale', {}).copy()
@@ -149,7 +159,7 @@ def _update_fields(self, ignore_update_fields=None):
149159
previous_settings = self.app.appsettings_set.latest()
150160
except AppSettings.DoesNotExist:
151161
pass
152-
update_fields = ["routable", "autoscale", "label"]
162+
update_fields = ["routable", "autorollback", "autoscale", "label"]
153163
try:
154164
for update_field in update_fields:
155165
if ignore_update_fields is None or update_field not in ignore_update_fields:

rootfs/api/models/release.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
from django.conf import settings
44
from django.db import models
5+
from django.db.models import Q
56
from django.contrib.auth import get_user_model
67
from api.utils import dict_diff
78
from api.tasks import run_pipeline
89
from api.exceptions import DryccException, AlreadyExists
910
from scheduler import KubeHTTPException
1011
from scheduler.resources.pod import DEFAULT_CONTAINER_PORT
1112
from .base import UuidAuditedModel
13+
from .appsettings import AppSettings
1214

1315

1416
User = get_user_model()
@@ -197,9 +199,16 @@ def previous(self):
197199
if self.pk:
198200
releases = releases.exclude(pk=self.pk)
199201

202+
q = Q(failed=False, state="succeed")
203+
try:
204+
app_settings = self.app.appsettings_set.latest()
205+
if app_settings.autorollback is False:
206+
q = Q(state__in=["crashed", "succeed"])
207+
except AppSettings.DoesNotExist:
208+
pass
200209
try:
201210
# Get the Release previous to this one
202-
prev_release = releases.filter(failed=False, state="succeed").latest()
211+
prev_release = releases.filter(q).latest()
203212
except Release.DoesNotExist:
204213
prev_release = None
205214
return prev_release

rootfs/api/tests/test_app_settings.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,22 @@ def test_settings_routable(self, mock_requests):
4040
self.assertEqual(response.status_code, 201, response.data)
4141
self.assertFalse(app.appsettings_set.latest().routable)
4242

43+
def test_settings_autorollback(self, mock_requests):
44+
"""
45+
Create an application with the autorollback flag turned on or off
46+
"""
47+
# create app, expecting autorollback to be true
48+
app_id = self.create_app()
49+
app = App.objects.get(id=app_id)
50+
self.assertTrue(app.appsettings_set.latest().autorollback)
51+
# Set autorollback to false
52+
response = self.client.post(
53+
f'/v2/apps/{app.id}/settings',
54+
{'autorollback': False}
55+
)
56+
self.assertEqual(response.status_code, 201, response.data)
57+
self.assertFalse(app.appsettings_set.latest().autorollback)
58+
4359
def test_autoscale(self, mock_requests):
4460
"""
4561
Test that autoscale can be applied

0 commit comments

Comments
 (0)