From 223814f8976fea2410f118b7708ad062d94de5f8 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Fri, 18 Nov 2022 11:30:31 +0800 Subject: [PATCH 1/2] perf: migrate (#9098) Co-authored-by: feng <1304903146@qq.com> --- .../0033_alter_assetpermission_actions.py | 18 +++++++++++++++++ ...0060_alter_applethostdeployment_options.py | 17 ++++++++++++++++ apps/tickets/api/__init__.py | 4 ++-- apps/tickets/api/assignee.py | 0 apps/tickets/api/comment.py | 2 +- apps/tickets/api/flow.py | 1 - apps/tickets/api/relation.py | 8 ++++---- apps/tickets/api/super_ticket.py | 3 +-- apps/tickets/api/ticket.py | 14 ++++++------- apps/tickets/const.py | 20 +++++++++---------- apps/tickets/filters.py | 2 +- apps/tickets/handlers/apply_asset.py | 2 +- ...23_alter_applyassetticket_apply_actions.py | 18 +++++++++++++++++ .../models/ticket/apply_application.py | 13 ++++-------- apps/tickets/models/ticket/general.py | 10 +++++----- apps/tickets/notifications.py | 6 +++--- apps/tickets/serializers/__init__.py | 2 +- apps/tickets/serializers/comment.py | 6 +++--- apps/tickets/serializers/flow.py | 3 ++- apps/tickets/serializers/ticket/__init__.py | 4 ++-- .../tickets/serializers/ticket/apply_asset.py | 4 ++-- apps/tickets/serializers/ticket/ticket.py | 6 +++--- apps/tickets/urls/api_urls.py | 11 +++++----- apps/tickets/views/approve.py | 8 ++++---- 24 files changed, 114 insertions(+), 68 deletions(-) create mode 100644 apps/perms/migrations/0033_alter_assetpermission_actions.py create mode 100644 apps/terminal/migrations/0060_alter_applethostdeployment_options.py delete mode 100644 apps/tickets/api/assignee.py create mode 100644 apps/tickets/migrations/0023_alter_applyassetticket_apply_actions.py diff --git a/apps/perms/migrations/0033_alter_assetpermission_actions.py b/apps/perms/migrations/0033_alter_assetpermission_actions.py new file mode 100644 index 000000000..cfa39f6e3 --- /dev/null +++ b/apps/perms/migrations/0033_alter_assetpermission_actions.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.14 on 2022-11-18 02:55 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('perms', '0032_auto_20221111_1919'), + ] + + operations = [ + migrations.AlterField( + model_name='assetpermission', + name='actions', + field=models.IntegerField(default=1, verbose_name='Actions'), + ), + ] diff --git a/apps/terminal/migrations/0060_alter_applethostdeployment_options.py b/apps/terminal/migrations/0060_alter_applethostdeployment_options.py new file mode 100644 index 000000000..c38e2ba29 --- /dev/null +++ b/apps/terminal/migrations/0060_alter_applethostdeployment_options.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.14 on 2022-11-18 02:55 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('terminal', '0059_applethostdeployment_task'), + ] + + operations = [ + migrations.AlterModelOptions( + name='applethostdeployment', + options={'ordering': ('-date_start',)}, + ), + ] diff --git a/apps/tickets/api/__init__.py b/apps/tickets/api/__init__.py index bec6f21d1..645133d8e 100644 --- a/apps/tickets/api/__init__.py +++ b/apps/tickets/api/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # -from .ticket import * from .flow import * +from .ticket import * from .comment import * -from .super_ticket import * from .relation import * +from .super_ticket import * diff --git a/apps/tickets/api/assignee.py b/apps/tickets/api/assignee.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps/tickets/api/comment.py b/apps/tickets/api/comment.py index 1515f7c9b..e9eaf4ac3 100644 --- a/apps/tickets/api/comment.py +++ b/apps/tickets/api/comment.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # - from rest_framework import viewsets, mixins + from common.exceptions import JMSException from common.utils import lazyproperty from rbac.permissions import RBACPermission diff --git a/apps/tickets/api/flow.py b/apps/tickets/api/flow.py index b45479187..303af6d3f 100644 --- a/apps/tickets/api/flow.py +++ b/apps/tickets/api/flow.py @@ -9,7 +9,6 @@ __all__ = ['TicketFlowViewSet'] class TicketFlowViewSet(JMSBulkModelViewSet): serializer_class = serializers.TicketFlowSerializer - filterset_fields = ['id', 'type'] search_fields = ['id', 'type'] diff --git a/apps/tickets/api/relation.py b/apps/tickets/api/relation.py index 5061e6c00..c442c04ab 100644 --- a/apps/tickets/api/relation.py +++ b/apps/tickets/api/relation.py @@ -1,13 +1,13 @@ -from rest_framework.mixins import CreateModelMixin from rest_framework import views -from rest_framework.response import Response from rest_framework import status +from rest_framework.response import Response +from rest_framework.mixins import CreateModelMixin +from orgs.utils import tmp_to_root_org from common.drf.api import JMSGenericViewSet +from terminal.serializers import SessionSerializer from tickets.models import TicketSession from tickets.serializers import TicketSessionRelationSerializer -from terminal.serializers import SessionSerializer -from orgs.utils import tmp_to_root_org class TicketSessionRelationViewSet(CreateModelMixin, JMSGenericViewSet): diff --git a/apps/tickets/api/super_ticket.py b/apps/tickets/api/super_ticket.py index 32c4a56c0..ebe4c9142 100644 --- a/apps/tickets/api/super_ticket.py +++ b/apps/tickets/api/super_ticket.py @@ -1,9 +1,8 @@ from rest_framework.generics import RetrieveDestroyAPIView from orgs.utils import tmp_to_root_org -from ..serializers import SuperTicketSerializer from ..models import Ticket - +from ..serializers import SuperTicketSerializer __all__ = ['SuperTicketStatusAPI'] diff --git a/apps/tickets/api/ticket.py b/apps/tickets/api/ticket.py index a256c51b5..8cf58bd6e 100644 --- a/apps/tickets/api/ticket.py +++ b/apps/tickets/api/ticket.py @@ -2,13 +2,13 @@ # from rest_framework import viewsets from rest_framework.decorators import action -from rest_framework.exceptions import MethodNotAllowed from rest_framework.response import Response +from rest_framework.exceptions import MethodNotAllowed -from common.const.http import POST, PUT, PATCH -from common.mixins.api import CommonApiMixin from orgs.utils import tmp_to_root_org from rbac.permissions import RBACPermission +from common.mixins.api import CommonApiMixin +from common.const.http import POST, PUT, PATCH from tickets import filters from tickets import serializers from tickets.models import ( @@ -94,9 +94,9 @@ class TicketViewSet(CommonApiMixin, viewsets.ModelViewSet): class ApplyAssetTicketViewSet(TicketViewSet): - serializer_class = serializers.ApplyAssetSerializer model = ApplyAssetTicket filterset_class = filters.ApplyAssetTicketFilter + serializer_class = serializers.ApplyAssetSerializer serializer_classes = { 'open': serializers.ApplyAssetSerializer, 'approve': serializers.ApproveAssetSerializer @@ -104,18 +104,18 @@ class ApplyAssetTicketViewSet(TicketViewSet): class ApplyLoginTicketViewSet(TicketViewSet): - serializer_class = serializers.LoginConfirmSerializer model = ApplyLoginTicket filterset_class = filters.ApplyLoginTicketFilter + serializer_class = serializers.LoginConfirmSerializer class ApplyLoginAssetTicketViewSet(TicketViewSet): - serializer_class = serializers.LoginAssetConfirmSerializer model = ApplyLoginAssetTicket filterset_class = filters.ApplyLoginAssetTicketFilter + serializer_class = serializers.LoginAssetConfirmSerializer class ApplyCommandTicketViewSet(TicketViewSet): - serializer_class = serializers.ApplyCommandConfirmSerializer model = ApplyCommandTicket filterset_class = filters.ApplyCommandTicketFilter + serializer_class = serializers.ApplyCommandConfirmSerializer diff --git a/apps/tickets/const.py b/apps/tickets/const.py index f52c74930..ccd044bbe 100644 --- a/apps/tickets/const.py +++ b/apps/tickets/const.py @@ -6,18 +6,18 @@ TICKET_DETAIL_URL = '/ui/#/tickets/tickets/{id}?type={type}' class TicketType(TextChoices): general = 'general', _("General") - login_confirm = 'login_confirm', _("Login confirm") apply_asset = 'apply_asset', _('Apply for asset') - login_asset_confirm = 'login_asset_confirm', _('Login asset confirm') + login_confirm = 'login_confirm', _("Login confirm") command_confirm = 'command_confirm', _('Command confirm') + login_asset_confirm = 'login_asset_confirm', _('Login asset confirm') class TicketState(TextChoices): pending = 'pending', _('Open') - approved = 'approved', _('Approved') - rejected = 'rejected', _('Rejected') closed = 'closed', _("Cancel") reopen = 'reopen', _("Reopen") + approved = 'approved', _('Approved') + rejected = 'rejected', _('Rejected') class TicketStatus(TextChoices): @@ -27,23 +27,23 @@ class TicketStatus(TextChoices): class StepState(TextChoices): pending = 'pending', _('Pending') - approved = 'approved', _('Approved') - rejected = 'rejected', _('Rejected') closed = 'closed', _("Closed") reopen = 'reopen', _("Reopen") + approved = 'approved', _('Approved') + rejected = 'rejected', _('Rejected') class StepStatus(TextChoices): - pending = 'pending', _('Pending') active = 'active', _('Active') closed = 'closed', _("Closed") + pending = 'pending', _('Pending') class TicketAction(TextChoices): open = 'open', _("Open") close = 'close', _("Close") - approve = 'approve', _('Approve') reject = 'reject', _('Reject') + approve = 'approve', _('Approve') class TicketLevel(IntegerChoices): @@ -52,7 +52,7 @@ class TicketLevel(IntegerChoices): class TicketApprovalStrategy(TextChoices): - super_admin = 'super_admin', _("Super admin") org_admin = 'org_admin', _("Org admin") - super_org_admin = 'super_org_admin', _("Super admin and org admin") custom_user = 'custom_user', _("Custom user") + super_admin = 'super_admin', _("Super admin") + super_org_admin = 'super_org_admin', _("Super admin and org admin") diff --git a/apps/tickets/filters.py b/apps/tickets/filters.py index 536f06b56..e7cd5944c 100644 --- a/apps/tickets/filters.py +++ b/apps/tickets/filters.py @@ -1,5 +1,5 @@ -from django_filters import rest_framework as filters from django.db.models import Subquery, OuterRef +from django_filters import rest_framework as filters from common.drf.filters import BaseFilterSet diff --git a/apps/tickets/handlers/apply_asset.py b/apps/tickets/handlers/apply_asset.py index 2ad50b6df..f2b2ee842 100644 --- a/apps/tickets/handlers/apply_asset.py +++ b/apps/tickets/handlers/apply_asset.py @@ -1,7 +1,7 @@ from django.utils.translation import ugettext as _ -from perms.models import AssetPermission from orgs.utils import tmp_to_org +from perms.models import AssetPermission from tickets.models import ApplyAssetTicket from .base import BaseHandler diff --git a/apps/tickets/migrations/0023_alter_applyassetticket_apply_actions.py b/apps/tickets/migrations/0023_alter_applyassetticket_apply_actions.py new file mode 100644 index 000000000..2c4224c80 --- /dev/null +++ b/apps/tickets/migrations/0023_alter_applyassetticket_apply_actions.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.14 on 2022-11-18 03:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('tickets', '0022_alter_applyassetticket_apply_actions'), + ] + + operations = [ + migrations.AlterField( + model_name='applyassetticket', + name='apply_actions', + field=models.IntegerField(default=31, verbose_name='Actions'), + ), + ] diff --git a/apps/tickets/models/ticket/apply_application.py b/apps/tickets/models/ticket/apply_application.py index 115d45a9f..3c1f4b6f7 100644 --- a/apps/tickets/models/ticket/apply_application.py +++ b/apps/tickets/models/ticket/apply_application.py @@ -1,7 +1,6 @@ from django.db import models from django.utils.translation import gettext_lazy as _ -from perms.models import Action from .general import Ticket __all__ = ['ApplyApplicationTicket'] @@ -23,14 +22,10 @@ class ApplyApplicationTicket(Ticket): 'assets.SystemUser', verbose_name=_('Apply system users'), ) apply_actions = models.IntegerField( - choices=Action.DB_CHOICES, default=Action.ALL, verbose_name=_('Actions') + choices=[ + (255, 'All'), (1, 'Connect'), (2, 'Upload file'), (4, 'Download file'), (6, 'Upload download'), + (8, 'Clipboard copy'), (16, 'Clipboard paste'), (24, 'Clipboard copy paste') + ], default=255, verbose_name=_('Actions') ) apply_date_start = models.DateTimeField(verbose_name=_('Date start'), null=True) apply_date_expired = models.DateTimeField(verbose_name=_('Date expired'), null=True) - - @property - def apply_actions_display(self): - return Action.value_to_choices_display(self.apply_actions) - - def get_apply_actions_display(self): - return ', '.join(self.apply_actions_display) diff --git a/apps/tickets/models/ticket/general.py b/apps/tickets/models/ticket/general.py index 605990040..271b87166 100644 --- a/apps/tickets/models/ticket/general.py +++ b/apps/tickets/models/ticket/general.py @@ -5,23 +5,23 @@ from typing import Callable from django.db import models from django.db.models import Q -from django.utils.translation import ugettext_lazy as _ +from django.forms import model_to_dict from django.db.utils import IntegrityError from django.db.models.fields import related -from django.forms import model_to_dict +from django.utils.translation import ugettext_lazy as _ +from orgs.utils import tmp_to_org +from orgs.models import Organization from common.exceptions import JMSException from common.utils.timezone import as_current_tz from common.mixins.models import CommonModelMixin from common.db.encoder import ModelJSONFieldEncoder -from orgs.models import Organization -from orgs.utils import tmp_to_org from tickets.const import ( TicketType, TicketStatus, TicketState, TicketLevel, StepState, StepStatus ) -from tickets.handlers import get_ticket_handler from tickets.errors import AlreadyClosed +from tickets.handlers import get_ticket_handler from ..flow import TicketFlow __all__ = [ diff --git a/apps/tickets/notifications.py b/apps/tickets/notifications.py index 26997b0dc..7e971f4cf 100644 --- a/apps/tickets/notifications.py +++ b/apps/tickets/notifications.py @@ -1,11 +1,11 @@ -from urllib.parse import urljoin import json +from urllib.parse import urljoin from django.conf import settings from django.core.cache import cache from django.shortcuts import reverse -from django.template.loader import render_to_string from django.forms import model_to_dict +from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ from notifications.notifications import UserMessage @@ -94,9 +94,9 @@ class BaseTicketMessage(UserMessage): class TicketAppliedToAssigneeMessage(BaseTicketMessage): def __init__(self, user, ticket): + self._token = None self.ticket = ticket super().__init__(user) - self._token = None @property def token(self): diff --git a/apps/tickets/serializers/__init__.py b/apps/tickets/serializers/__init__.py index 26a4b9aa6..645133d8e 100644 --- a/apps/tickets/serializers/__init__.py +++ b/apps/tickets/serializers/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # -from .ticket import * from .flow import * +from .ticket import * from .comment import * from .relation import * from .super_ticket import * diff --git a/apps/tickets/serializers/comment.py b/apps/tickets/serializers/comment.py index 6cb8ab9d5..6fa9fa567 100644 --- a/apps/tickets/serializers/comment.py +++ b/apps/tickets/serializers/comment.py @@ -1,6 +1,7 @@ from rest_framework import serializers -from ..models import Comment + from common.drf.fields import ReadableHiddenField +from ..models import Comment __all__ = ['CommentSerializer'] @@ -23,8 +24,7 @@ class CommentSerializer(serializers.ModelSerializer): model = Comment fields_mini = ['id'] fields_small = fields_mini + [ - 'body', 'user_display', - 'date_created', 'date_updated' + 'body', 'user_display', 'date_created', 'date_updated' ] fields_fk = ['ticket', 'user', ] fields = fields_small + fields_fk diff --git a/apps/tickets/serializers/flow.py b/apps/tickets/serializers/flow.py index e949fa8d6..f48e16501 100644 --- a/apps/tickets/serializers/flow.py +++ b/apps/tickets/serializers/flow.py @@ -1,6 +1,7 @@ +from rest_framework import serializers from django.db.transaction import atomic from django.utils.translation import ugettext_lazy as _ -from rest_framework import serializers + from orgs.models import Organization from orgs.utils import get_current_org_id diff --git a/apps/tickets/serializers/ticket/__init__.py b/apps/tickets/serializers/ticket/__init__.py index 7b1bdfe13..73fc3b122 100644 --- a/apps/tickets/serializers/ticket/__init__.py +++ b/apps/tickets/serializers/ticket/__init__.py @@ -1,6 +1,6 @@ +from .common import * from .ticket import * from .apply_asset import * from .login_confirm import * -from .login_asset_confirm import * from .command_confirm import * -from .common import * +from .login_asset_confirm import * diff --git a/apps/tickets/serializers/ticket/apply_asset.py b/apps/tickets/serializers/ticket/apply_asset.py index 4e7fd0f6c..cc4b6aa9a 100644 --- a/apps/tickets/serializers/ticket/apply_asset.py +++ b/apps/tickets/serializers/ticket/apply_asset.py @@ -1,10 +1,10 @@ -from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers +from django.utils.translation import ugettext_lazy as _ from assets.models import Asset, Node -from common.drf.fields import ObjectRelatedField from perms.models import AssetPermission from perms.serializers.permission import ActionChoicesField +from common.drf.fields import ObjectRelatedField from tickets.models import ApplyAssetTicket from .common import BaseApplyAssetSerializer from .ticket import TicketApplySerializer diff --git a/apps/tickets/serializers/ticket/ticket.py b/apps/tickets/serializers/ticket/ticket.py index 7bb168791..dbdf89cc0 100644 --- a/apps/tickets/serializers/ticket/ticket.py +++ b/apps/tickets/serializers/ticket/ticket.py @@ -1,13 +1,13 @@ # -*- coding: utf-8 -*- # -from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers +from django.utils.translation import ugettext_lazy as _ from common.drf.fields import LabeledChoiceField -from orgs.mixins.serializers import OrgResourceModelSerializerMixin from orgs.models import Organization -from tickets.const import TicketType, TicketStatus, TicketState +from orgs.mixins.serializers import OrgResourceModelSerializerMixin from tickets.models import Ticket, TicketFlow +from tickets.const import TicketType, TicketStatus, TicketState __all__ = [ 'TicketApplySerializer', 'TicketApproveSerializer', 'TicketSerializer', diff --git a/apps/tickets/urls/api_urls.py b/apps/tickets/urls/api_urls.py index 6602e207c..9cc72d815 100644 --- a/apps/tickets/urls/api_urls.py +++ b/apps/tickets/urls/api_urls.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- # from django.urls import path - from rest_framework_bulk.routes import BulkRouter from .. import api @@ -10,16 +9,16 @@ app_name = 'tickets' router = BulkRouter() router.register('tickets', api.TicketViewSet, 'ticket') -router.register('apply-asset-tickets', api.ApplyAssetTicketViewSet, 'apply-asset-ticket') -router.register('apply-login-tickets', api.ApplyLoginTicketViewSet, 'apply-login-ticket') -router.register('apply-login-asset-tickets', api.ApplyLoginAssetTicketViewSet, 'apply-login-asset-ticket') -router.register('apply-command-tickets', api.ApplyCommandTicketViewSet, 'apply-command-ticket') router.register('flows', api.TicketFlowViewSet, 'flows') router.register('comments', api.CommentViewSet, 'comment') +router.register('apply-asset-tickets', api.ApplyAssetTicketViewSet, 'apply-asset-ticket') +router.register('apply-login-tickets', api.ApplyLoginTicketViewSet, 'apply-login-ticket') +router.register('apply-command-tickets', api.ApplyCommandTicketViewSet, 'apply-command-ticket') +router.register('apply-login-asset-tickets', api.ApplyLoginAssetTicketViewSet, 'apply-login-asset-ticket') router.register('ticket-session-relation', api.TicketSessionRelationViewSet, 'ticket-session-relation') urlpatterns = [ - path('tickets//session/', api.TicketSessionApi.as_view(), name='ticket-sesion'), + path('tickets//session/', api.TicketSessionApi.as_view(), name='ticket-session'), path('super-tickets//status/', api.SuperTicketStatusAPI.as_view(), name='super-ticket-status'), ] urlpatterns += router.urls diff --git a/apps/tickets/views/approve.py b/apps/tickets/views/approve.py index d742437f8..a3a265005 100644 --- a/apps/tickets/views/approve.py +++ b/apps/tickets/views/approve.py @@ -2,18 +2,18 @@ # from __future__ import unicode_literals -from django.views.generic.base import TemplateView -from django.shortcuts import redirect, reverse from django.core.cache import cache +from django.shortcuts import redirect, reverse +from django.views.generic.base import TemplateView from django.utils.translation import ugettext as _ from orgs.utils import tmp_to_root_org +from tickets.const import TicketType +from tickets.errors import AlreadyClosed from tickets.models import ( Ticket, ApplyAssetTicket, ApplyLoginTicket, ApplyLoginAssetTicket, ApplyCommandTicket ) -from tickets.const import TicketType -from tickets.errors import AlreadyClosed from common.utils import get_logger, FlashMessageUtil logger = get_logger(__name__) From d0de36358ca9d335df3f5f69d676a36d22646452 Mon Sep 17 00:00:00 2001 From: Aaron3S Date: Fri, 18 Nov 2022 18:46:48 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E5=AE=9A?= =?UTF-8?q?=E6=97=B6=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ops/migrations/0033_auto_20221118_1431.py | 28 ++++++++++++ apps/ops/models/job.py | 45 ++++++++++++++++++- apps/ops/serializers/job.py | 12 ++--- apps/ops/tasks.py | 2 +- 4 files changed, 79 insertions(+), 8 deletions(-) create mode 100644 apps/ops/migrations/0033_auto_20221118_1431.py diff --git a/apps/ops/migrations/0033_auto_20221118_1431.py b/apps/ops/migrations/0033_auto_20221118_1431.py new file mode 100644 index 000000000..70518eee6 --- /dev/null +++ b/apps/ops/migrations/0033_auto_20221118_1431.py @@ -0,0 +1,28 @@ +# Generated by Django 3.2.14 on 2022-11-18 06:31 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ops', '0032_auto_20221117_1848'), + ] + + operations = [ + migrations.AddField( + model_name='job', + name='crontab', + field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Regularly perform'), + ), + migrations.AddField( + model_name='job', + name='interval', + field=models.IntegerField(blank=True, default=24, null=True, verbose_name='Cycle perform'), + ), + migrations.AddField( + model_name='job', + name='is_periodic', + field=models.BooleanField(default=False), + ), + ] diff --git a/apps/ops/models/job.py b/apps/ops/models/job.py index 8897d6107..d5542970d 100644 --- a/apps/ops/models/job.py +++ b/apps/ops/models/job.py @@ -9,14 +9,16 @@ from django.utils.translation import gettext_lazy as _ from django.utils import timezone from celery import current_task +from common.const.choices import Trigger from common.db.models import BaseCreateUpdateModel __all__ = ["Job", "JobExecution"] from ops.ansible import JMSInventory, AdHocRunner, PlaybookRunner +from ops.mixin import PeriodTaskModelMixin -class Job(BaseCreateUpdateModel): +class Job(BaseCreateUpdateModel, PeriodTaskModelMixin): class Types(models.TextChoices): adhoc = 'adhoc', _('Adhoc') playbook = 'playbook', _('Playbook') @@ -48,6 +50,42 @@ class Job(BaseCreateUpdateModel): parameters_define = models.JSONField(default=dict, verbose_name=_('Parameters define')) comment = models.CharField(max_length=1024, default='', verbose_name=_('Comment'), null=True, blank=True) + @property + def last_execution(self): + return self.executions.last() + + @property + def date_last_run(self): + return self.last_execution.date_created if self.last_execution else None + + @property + def summary(self): + summary = { + "total": 0, + "success": 0, + } + for execution in self.executions.all(): + summary["total"] += 1 + if execution.is_success: + summary["success"] += 1 + return summary + + @property + def average_time_cost(self): + total_cost = 0 + finished_count = self.executions.filter(status__in=['success', 'failed']).count() + for execution in self.executions.filter(status__in=['success', 'failed']).all(): + total_cost += execution.time_cost + return total_cost / finished_count if finished_count else 0 + + def get_register_task(self): + from ..tasks import run_ops_job + name = "run_ops_job_period_{}".format(str(self.id)[:8]) + task = run_ops_job.name + args = (str(self.id),) + kwargs = {} + return name, task, args, kwargs + @property def inventory(self): return JMSInventory(self.assets.all(), self.runas_policy, self.runas) @@ -72,7 +110,10 @@ class JobExecution(BaseCreateUpdateModel): def get_runner(self): inv = self.job.inventory inv.write_to_file(self.inventory_path) - extra_vars = json.loads(self.parameters) + if isinstance(self.parameters, str): + extra_vars = json.loads(self.parameters) + else: + extra_vars = {} if self.job.type == 'adhoc': runner = AdHocRunner( diff --git a/apps/ops/serializers/job.py b/apps/ops/serializers/job.py index 2771e2a7f..389b92ce2 100644 --- a/apps/ops/serializers/job.py +++ b/apps/ops/serializers/job.py @@ -2,24 +2,26 @@ from django.db import transaction from rest_framework import serializers from common.drf.fields import ReadableHiddenField +from ops.mixin import PeriodTaskSerializerMixin from ops.models import Job, JobExecution _all_ = [] -class JobSerializer(serializers.ModelSerializer): +class JobSerializer(serializers.ModelSerializer, PeriodTaskSerializerMixin): owner = ReadableHiddenField(default=serializers.CurrentUserDefault()) class Meta: model = Job - fields = [ - "id", "name", "instant", "type", "module", "args", "playbook", "assets", "runas_policy", "runas", "owner", + read_only_fields = ["id", "date_last_run", "date_created", "date_updated", "average_time_cost"] + fields = read_only_fields + [ + "name", "instant", "type", "module", "args", "playbook", "assets", "runas_policy", "runas", "owner", "parameters_define", "timeout", "chdir", "comment", - "date_created", - "date_updated" + "summary", + "is_periodic", "interval", "crontab" ] diff --git a/apps/ops/tasks.py b/apps/ops/tasks.py index c350cdb6b..841f759ff 100644 --- a/apps/ops/tasks.py +++ b/apps/ops/tasks.py @@ -25,7 +25,7 @@ logger = get_logger(__file__) @shared_task(soft_time_limit=60, queue="ansible", verbose_name=_("Run ansible task")) -def run_ops_job(job_id, **kwargs): +def run_ops_job(job_id): job = get_object_or_none(Job, id=job_id) execution = job.create_execution() try: