Skip to content

Commit 581bead

Browse files
committed
feat(rootfs/api): implement main termination grace period support.
main feature code
1 parent 2bf9a23 commit 581bead

6 files changed

Lines changed: 33 additions & 5 deletions

File tree

rootfs/api/models/app.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,7 @@ def _gather_app_settings(self, release, app_settings, process_type, replicas):
11071107
'deployment_revision_history_limit': deployment_history,
11081108
'release_summary': release.summary,
11091109
'pod_termination_grace_period_seconds': pod_termination_grace_period_seconds,
1110+
'pod_termination_grace_period_each': config.termination_grace_period,
11101111
'image_pull_secret_name': image_pull_secret_name,
11111112
'image_pull_policy': image_pull_policy
11121113
}

rootfs/api/models/config.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class Config(UuidAuditedModel):
2424
tags = JSONField(default={}, blank=True)
2525
registry = JSONField(default={}, blank=True)
2626
healthcheck = JSONField(default={}, blank=True)
27+
termination_grace_period = JSONField(default={}, blank=True)
2728

2829
class Meta:
2930
get_latest_by = 'created'
@@ -165,7 +166,8 @@ def save(self, **kwargs):
165166
previous_config = self.app.config_set.latest()
166167

167168
for attr in ['cpu', 'memory', 'tags', 'registry', 'values',
168-
'lifecycle_post_start', 'lifecycle_pre_stop']:
169+
'lifecycle_post_start', 'lifecycle_pre_stop',
170+
'termination_grace_period']:
169171
data = getattr(previous_config, attr, {}).copy()
170172
new_data = getattr(self, attr, {}).copy()
171173

rootfs/api/serializers.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
r'^(?P<cpu>(([-+]?[0-9]*\.?[0-9]+[m]?)(/([-+]?[0-9]*\.?[0-9]+[m]?))?))$')
2727
TAGVAL_MATCH = re.compile(r'^(?:[a-zA-Z\d][-\.\w]{0,61})?[a-zA-Z\d]$')
2828
CONFIGKEY_MATCH = re.compile(r'^[a-z_]+[a-z0-9_]*$', re.IGNORECASE)
29+
TERMINATION_GRACE_PERIOD_MATCH = re.compile(r'^[0-9]*$')
2930
PROBE_SCHEMA = {
3031
"$schema": "http://json-schema.org/schema#",
3132

@@ -218,6 +219,7 @@ class ConfigSerializer(serializers.ModelSerializer):
218219
registry = JSONFieldSerializer(required=False, binary=True)
219220
healthcheck = JSONFieldSerializer(convert_to_str=False, required=False, binary=True)
220221
routable = serializers.BooleanField(required=False)
222+
termination_grace_period = JSONFieldSerializer(required=False, binary=True)
221223

222224
class Meta:
223225
"""Metadata options for a :class:`ConfigSerializer`."""
@@ -372,6 +374,21 @@ def validate_healthcheck(self, data):
372374

373375
return data
374376

377+
def validate_termination_grace_period(self, data):
378+
for key, value in data.items():
379+
if value is None: # use NoneType to unset an item
380+
continue
381+
382+
if not re.match(PROCTYPE_MATCH, key):
383+
raise serializers.ValidationError(PROCTYPE_MISMATCH_MSG)
384+
385+
timeout = re.match(TERMINATION_GRACE_PERIOD_MATCH, value)
386+
if not timeout:
387+
raise serializers.ValidationError(
388+
"Termination Grace Period format: <value>, where value must be a numeric")
389+
390+
return data
391+
375392

376393
class ReleaseSerializer(serializers.ModelSerializer):
377394
"""Serialize a :class:`~api.models.Release` model."""

rootfs/api/tests/test_config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ def test_response_data(self, mock_requests):
166166
for key in response.data:
167167
self.assertIn(key, ['uuid', 'owner', 'created', 'updated', 'app', 'values', 'memory',
168168
'cpu', 'tags', 'registry', 'healthcheck', 'lifecycle_post_start',
169-
'lifecycle_pre_stop'])
169+
'lifecycle_pre_stop', 'termination_grace_period'])
170170
expected = {
171171
'owner': self.user.username,
172172
'app': app_id,
@@ -190,7 +190,7 @@ def test_response_data_types_converted(self, mock_requests):
190190
for key in response.data:
191191
self.assertIn(key, ['uuid', 'owner', 'created', 'updated', 'app', 'values', 'memory',
192192
'cpu', 'tags', 'registry', 'healthcheck', 'lifecycle_post_start',
193-
'lifecycle_pre_stop'])
193+
'lifecycle_pre_stop', 'termination_grace_period'])
194194
expected = {
195195
'owner': self.user.username,
196196
'app': app_id,

rootfs/bin/test-style

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@
66
# fail hard and fast even on pipelines
77
set -eou pipefail
88

9-
flake8 --show-source
9+
flake8 --show-source --max-line-length=128

rootfs/scheduler/resources/pod.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def manifest(self, namespace, name, image, **kwargs):
130130
spec['nodeSelector'] = kwargs.get('tags', {})
131131

132132
# How long until a pod is forcefully terminated. 30 is kubernetes default
133-
spec['terminationGracePeriodSeconds'] = kwargs.get('pod_termination_grace_period_seconds', 30) # noqa
133+
spec['terminationGracePeriodSeconds'] = self._get_termination_grace_period(kwargs) # noqa
134134

135135
# Check if it is a slug builder image.
136136
if build_type == "buildpack":
@@ -255,6 +255,14 @@ def _set_resources(self, container, kwargs):
255255
if resources:
256256
container["resources"] = dict(resources)
257257

258+
def _get_termination_grace_period(self, kwargs):
259+
""" return termination grace period """
260+
app_type = kwargs.get("app_type")
261+
timeout_global = kwargs.get('pod_termination_grace_period_seconds', 30)
262+
timeout_local = kwargs.get("pod_termination_grace_period_each", {}).get(app_type)
263+
264+
return timeout_global if timeout_local is None else timeout_local
265+
258266
def _format_memory(self, mem):
259267
""" Format memory limit value """
260268
if mem[-2:-1].isalpha() and mem[-1].isalpha():

0 commit comments

Comments
 (0)