mirror of
https://github.com/ansible/awx.git
synced 2026-04-10 20:49:24 -02:30
Add default sysjob days
This commit is contained in:
@@ -3335,9 +3335,11 @@ class AdHocCommandRelaunchSerializer(AdHocCommandSerializer):
|
|||||||
|
|
||||||
class SystemJobTemplateSerializer(UnifiedJobTemplateSerializer):
|
class SystemJobTemplateSerializer(UnifiedJobTemplateSerializer):
|
||||||
|
|
||||||
|
has_configurable_retention = serializers.BooleanField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SystemJobTemplate
|
model = SystemJobTemplate
|
||||||
fields = ('*', 'job_type',)
|
fields = ('*', 'job_type', 'has_configurable_retention', 'default_days',)
|
||||||
|
|
||||||
def get_related(self, obj):
|
def get_related(self, obj):
|
||||||
res = super(SystemJobTemplateSerializer, self).get_related(obj)
|
res = super(SystemJobTemplateSerializer, self).get_related(obj)
|
||||||
@@ -3348,10 +3350,15 @@ class SystemJobTemplateSerializer(UnifiedJobTemplateSerializer):
|
|||||||
notification_templates_started = self.reverse('api:system_job_template_notification_templates_started_list', kwargs={'pk': obj.pk}),
|
notification_templates_started = self.reverse('api:system_job_template_notification_templates_started_list', kwargs={'pk': obj.pk}),
|
||||||
notification_templates_success = self.reverse('api:system_job_template_notification_templates_success_list', kwargs={'pk': obj.pk}),
|
notification_templates_success = self.reverse('api:system_job_template_notification_templates_success_list', kwargs={'pk': obj.pk}),
|
||||||
notification_templates_error = self.reverse('api:system_job_template_notification_templates_error_list', kwargs={'pk': obj.pk}),
|
notification_templates_error = self.reverse('api:system_job_template_notification_templates_error_list', kwargs={'pk': obj.pk}),
|
||||||
|
|
||||||
))
|
))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def to_representation(self, obj):
|
||||||
|
result = super(SystemJobTemplateSerializer, self).to_representation(obj)
|
||||||
|
if not obj.has_configurable_retention:
|
||||||
|
del result['default_days']
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
class SystemJobSerializer(UnifiedJobSerializer):
|
class SystemJobSerializer(UnifiedJobSerializer):
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ from awx.main.utils import (
|
|||||||
get_object_or_400,
|
get_object_or_400,
|
||||||
getattrd,
|
getattrd,
|
||||||
get_pk_from_dict,
|
get_pk_from_dict,
|
||||||
|
parse_yaml_or_json,
|
||||||
schedule_task_manager,
|
schedule_task_manager,
|
||||||
ignore_inventory_computed_fields,
|
ignore_inventory_computed_fields,
|
||||||
set_environ
|
set_environ
|
||||||
@@ -3440,7 +3441,11 @@ class SystemJobTemplateLaunch(GenericAPIView):
|
|||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
obj = self.get_object()
|
obj = self.get_object()
|
||||||
|
|
||||||
new_job = obj.create_unified_job(extra_vars=request.data.get('extra_vars', {}))
|
extra_vars = parse_yaml_or_json(request.data.get('extra_vars', {}))
|
||||||
|
if obj.has_configurable_retention and obj.default_days is not None:
|
||||||
|
extra_vars.setdefault('days', obj.default_days)
|
||||||
|
|
||||||
|
new_job = obj.create_unified_job(extra_vars=extra_vars)
|
||||||
new_job.signal_start()
|
new_job.signal_start()
|
||||||
data = OrderedDict()
|
data = OrderedDict()
|
||||||
data['system_job'] = new_job.id
|
data['system_job'] = new_job.id
|
||||||
|
|||||||
36
awx/main/migrations/0124_sysjob_default_days.py
Normal file
36
awx/main/migrations/0124_sysjob_default_days.py
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
from awx.main.utils.common import set_current_apps
|
||||||
|
from awx.main.models import SystemJobTemplate
|
||||||
|
|
||||||
|
|
||||||
|
def set_default_days(apps, schema_editor):
|
||||||
|
set_current_apps(apps)
|
||||||
|
for sys_template in SystemJobTemplate.objects.all():
|
||||||
|
if sys_template.has_configurable_retention:
|
||||||
|
if sys_template.default_days is None:
|
||||||
|
sys_template.default_days = 30
|
||||||
|
sys_template.save()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('main', '0123_drop_hg_support'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='systemjob',
|
||||||
|
name='default_days',
|
||||||
|
field=models.PositiveIntegerField(blank=True, default=None, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='systemjobtemplate',
|
||||||
|
name='default_days',
|
||||||
|
field=models.PositiveIntegerField(blank=True, default=None, null=True),
|
||||||
|
),
|
||||||
|
migrations.RunPython(set_default_days),
|
||||||
|
]
|
||||||
@@ -1142,22 +1142,58 @@ class SystemJobOptions(BaseModel):
|
|||||||
Common fields for SystemJobTemplate and SystemJob.
|
Common fields for SystemJobTemplate and SystemJob.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
SYSTEM_JOB_TYPE = [
|
|
||||||
('cleanup_jobs', _('Remove jobs older than a certain number of days')),
|
|
||||||
('cleanup_activitystream', _('Remove activity stream entries older than a certain number of days')),
|
|
||||||
('cleanup_sessions', _('Removes expired browser sessions from the database')),
|
|
||||||
('cleanup_tokens', _('Removes expired OAuth 2 access tokens and refresh tokens'))
|
|
||||||
]
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
|
SYSTEM_CLEANUP_JOBS = (
|
||||||
|
'cleanup_jobs',
|
||||||
|
_('Remove jobs older than a certain number of days')
|
||||||
|
)
|
||||||
|
SYSTEM_CLEANUP_ACTIVITY = (
|
||||||
|
'cleanup_activitystream',
|
||||||
|
_('Remove activity stream entries older than a certain number of days')
|
||||||
|
)
|
||||||
|
SYSTEM_CLEANUP_SESSIONS = (
|
||||||
|
'cleanup_sessions',
|
||||||
|
_('Removes expired browser sessions from the database')
|
||||||
|
)
|
||||||
|
SYSTEM_CLEANUP_TOKENS = (
|
||||||
|
'cleanup_tokens',
|
||||||
|
_('Removes expired OAuth 2 access tokens and refresh tokens')
|
||||||
|
)
|
||||||
|
|
||||||
|
SYSTEM_JOB_TYPES = (
|
||||||
|
SYSTEM_CLEANUP_JOBS,
|
||||||
|
SYSTEM_CLEANUP_ACTIVITY,
|
||||||
|
SYSTEM_CLEANUP_SESSIONS,
|
||||||
|
SYSTEM_CLEANUP_TOKENS,
|
||||||
|
)
|
||||||
|
CONFIGURABLE_RETENTION_TYPES = (
|
||||||
|
SYSTEM_CLEANUP_JOBS,
|
||||||
|
SYSTEM_CLEANUP_ACTIVITY,
|
||||||
|
)
|
||||||
|
|
||||||
job_type = models.CharField(
|
job_type = models.CharField(
|
||||||
max_length=32,
|
max_length=32,
|
||||||
choices=SYSTEM_JOB_TYPE,
|
choices=SYSTEM_JOB_TYPES,
|
||||||
blank=True,
|
blank=True,
|
||||||
default='',
|
default='',
|
||||||
)
|
)
|
||||||
|
default_days = models.PositiveIntegerField(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
default=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_configurable_retention(self):
|
||||||
|
return self.job_type in (name for (name, _) in SystemJobTemplate.CONFIGURABLE_RETENTION_TYPES)
|
||||||
|
|
||||||
|
def clean_default_days(self):
|
||||||
|
if not self.has_configurable_retention:
|
||||||
|
if self.default_days is not None:
|
||||||
|
raise ValidationError(_(f'Data retention isn\'t configurable for type {self.job_type}'))
|
||||||
|
return self.default_days
|
||||||
|
|
||||||
|
|
||||||
class SystemJobTemplate(UnifiedJobTemplate, SystemJobOptions):
|
class SystemJobTemplate(UnifiedJobTemplate, SystemJobOptions):
|
||||||
@@ -1221,7 +1257,7 @@ class SystemJobTemplate(UnifiedJobTemplate, SystemJobOptions):
|
|||||||
for key in unallowed_vars:
|
for key in unallowed_vars:
|
||||||
rejected[key] = data.pop(key)
|
rejected[key] = data.pop(key)
|
||||||
|
|
||||||
if self.job_type in ('cleanup_jobs', 'cleanup_activitystream'):
|
if self.has_configurable_retention:
|
||||||
if 'days' in data:
|
if 'days' in data:
|
||||||
try:
|
try:
|
||||||
if isinstance(data['days'], (bool, type(None))):
|
if isinstance(data['days'], (bool, type(None))):
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from collections import namedtuple
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
import pytest
|
import pytest
|
||||||
import yaml
|
import yaml
|
||||||
@@ -6,7 +7,7 @@ import json
|
|||||||
from awx.api.serializers import JobLaunchSerializer
|
from awx.api.serializers import JobLaunchSerializer
|
||||||
from awx.main.models.credential import Credential
|
from awx.main.models.credential import Credential
|
||||||
from awx.main.models.inventory import Inventory, Host
|
from awx.main.models.inventory import Inventory, Host
|
||||||
from awx.main.models.jobs import Job, JobTemplate, UnifiedJobTemplate
|
from awx.main.models.jobs import Job, JobTemplate, UnifiedJobTemplate, SystemJob
|
||||||
|
|
||||||
from awx.api.versioning import reverse
|
from awx.api.versioning import reverse
|
||||||
|
|
||||||
@@ -696,3 +697,28 @@ def test_callback_extra_var_takes_priority_over_host_name(mocker, get, job_templ
|
|||||||
r = get(reverse('api:job_template_callback', kwargs={'pk': job_template.pk}),
|
r = get(reverse('api:job_template_callback', kwargs={'pk': job_template.pk}),
|
||||||
user=admin_user, expect=200)
|
user=admin_user, expect=200)
|
||||||
assert not r.data['matching_hosts']
|
assert not r.data['matching_hosts']
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
@pytest.mark.parametrize('default_days,launch_vars,expected_vars', [
|
||||||
|
(9000, {}, {'days': 9000}),
|
||||||
|
(None, {}, {}),
|
||||||
|
(9000, {'days': 9001}, {'days': 9001}),
|
||||||
|
(None, {'days': 9001}, {'days': 9001}),
|
||||||
|
])
|
||||||
|
def test_system_job_launch_default_retention(system_job_template, admin_user, post,
|
||||||
|
default_days, launch_vars, expected_vars):
|
||||||
|
system_job_template.default_days = default_days
|
||||||
|
system_job_template.save()
|
||||||
|
launch_url = reverse(
|
||||||
|
'api:system_job_template_launch',
|
||||||
|
kwargs={'pk': system_job_template.pk}
|
||||||
|
)
|
||||||
|
mock_stdout = namedtuple('MockHandle', ['read'])(lambda: '')
|
||||||
|
with mock.patch.object(SystemJob, 'result_stdout_raw_handle', return_value=mock_stdout):
|
||||||
|
with mock.patch.object(SystemJob, 'signal_start') as signal_start:
|
||||||
|
res = post(launch_url, {'extra_vars': launch_vars}, admin_user, expect=201)
|
||||||
|
signal_start.assert_called()
|
||||||
|
|
||||||
|
res_vars = SystemJob.objects.get(id=res.data['id']).extra_vars
|
||||||
|
assert json.loads(res_vars) == expected_vars
|
||||||
|
|||||||
@@ -747,7 +747,10 @@ def workflow_job_factory(workflow_job_template, admin):
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def system_job_template():
|
def system_job_template():
|
||||||
sys_jt = SystemJobTemplate(name='test-system_job_template', job_type='cleanup_jobs')
|
sys_jt = SystemJobTemplate(
|
||||||
|
name='test-system_job_template',
|
||||||
|
job_type=SystemJobTemplate.SYSTEM_CLEANUP_JOBS[0]
|
||||||
|
)
|
||||||
sys_jt.save()
|
sys_jt.save()
|
||||||
return sys_jt
|
return sys_jt
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user