Skip to content

Commit

Permalink
LITE-28075 Add abort action for deployment requests
Browse files Browse the repository at this point in the history
  • Loading branch information
jonatrios committed Aug 2, 2023
1 parent f9042dd commit 1bf7841
Show file tree
Hide file tree
Showing 9 changed files with 342 additions and 7 deletions.
2 changes: 2 additions & 0 deletions connect_ext_ppr/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,6 @@ class ExtensionValidationError(ExtensionErrorBase):
2: "{field}: This values {values} are invalid.",
3: "At least one choice needs to be specified.",
4: "Cannot applied PPR to {entity} {values}.",
5: "Transition not allowed: can not set {field_name} from `{source}` to"
" '{target}', allowed {field_name} sources for '{target}' are '{allowed}'.",
}
18 changes: 18 additions & 0 deletions connect_ext_ppr/models/deployment.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from connect_ext_ppr.models.enums import DeploymentRequestStatusChoices, DeploymentStatusChoices
from connect_ext_ppr.models.ppr import PPRVersion
from connect_ext_ppr.models.replicas import Product
from connect_ext_ppr.models.models_utils import transition


class Deployment(Model):
Expand Down Expand Up @@ -62,6 +63,8 @@ class DeploymentRequest(Model):
finished_at = db.Column(db.DateTime(), nullable=True)
aborted_at = db.Column(db.DateTime(), nullable=True)
aborted_by = db.Column(db.String(20), nullable=True)
aborting_at = db.Column(db.DateTime(), nullable=True)
aborting_by = db.Column(db.String(20), nullable=True)

ppr = relationship('PPRVersion', foreign_keys="DeploymentRequest.ppr_id")
deployment = relationship(
Expand All @@ -70,6 +73,21 @@ class DeploymentRequest(Model):
innerjoin=True,
)

@transition('status', target=STATUSES.aborting, sources=[STATUSES.pending, STATUSES.processing])
def aborting(self, by):
self.aborting_at = datetime.utcnow()
self.aborting_by = by

@transition('status', target=STATUSES.aborted, sources=[STATUSES.aborting])
def abort(self):
self.aborted_at = datetime.utcnow()
self.aborted_by = self.aborting_by

@transition('status', target=STATUSES.aborted, sources=[STATUSES.aborting])
def abort_by_api(self, by):
self.aborted_at = datetime.utcnow()
self.aborted_by = by


class MarketplaceConfiguration(Model):
__tablename__ = 'marketplace_configuration'
Expand Down
34 changes: 34 additions & 0 deletions connect_ext_ppr/models/models_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import types

from connect_ext_ppr.errors import ExtensionValidationError


class transition:

def __init__(self, track_field, target, sources) -> None:
self.track_field = track_field
self.target = target
self.sources = sources if isinstance(sources, list) else [sources]

def __call__(self, fn):
def inner(*args, **kwargs):
self._validate_transition(args[0])
setattr(self.instance, self.track_field, self.target)
return fn(*args, **kwargs)
return inner

def __get__(self, instance, owner=None):
return types.MethodType(self, instance) if instance is not None else self

def _validate_transition(self, instance):
self.instance = instance
current_state = getattr(self.instance, self.track_field)
if current_state not in self.sources:
raise ExtensionValidationError.VAL_005(
format_kwargs={
'source': current_state,
'field_name': self.track_field,
'target': self.target,
'allowed': ', '.join(self.sources),
},
)
6 changes: 6 additions & 0 deletions connect_ext_ppr/models/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from connect_ext_ppr.db import Model
from connect_ext_ppr.models.enums import TasksStatusChoices, TaskTypesChoices
from connect_ext_ppr.models.deployment import DeploymentRequest
from connect_ext_ppr.models.models_utils import transition


class Task(Model):
Expand All @@ -31,3 +32,8 @@ class Task(Model):
finished_at = db.Column(db.DateTime(), nullable=True)
aborted_at = db.Column(db.DateTime(), nullable=True)
aborted_by = db.Column(db.String(20), nullable=True)

@transition('status', target=STATUSES.aborted, sources=[STATUSES.pending])
def abort(self, by):
self.aborted_at = datetime.utcnow()
self.aborted_by = by
2 changes: 1 addition & 1 deletion connect_ext_ppr/tasks_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def main_process(deployment_request_id, config):
db.refresh(deployment_request, with_for_update=True)

if deployment_request.status == DeploymentRequestStatusChoices.aborting:
deployment_request.status = DeploymentRequestStatusChoices.aborted
deployment_request.abort()
elif was_succesfull:
deployment_request.status = DeploymentRequestStatusChoices.done
else:
Expand Down
12 changes: 8 additions & 4 deletions connect_ext_ppr/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
)


class FileColletion:
class FileCollection:
PPR = 'pprs'
CONFIFURATION = 'configurations'

Expand Down Expand Up @@ -131,7 +131,7 @@ def create_media_file(


def create_ppr_to_media(client, account_id, deployment_id, filename, content, file_size=None):
file_collection = FileColletion.PPR
file_collection = FileCollection.PPR
file_type = MimeTypeChoices.application_vnd_ms_xslx
media_file = create_media_file(
client, account_id, deployment_id, file_collection,
Expand All @@ -148,12 +148,12 @@ def get_file_from_media(client, account_id, deployment_id, media_id, file_collec


def get_ppr_from_media(client, account_id, deployment_id, media_id):
file_collection = FileColletion.PPR
file_collection = FileCollection.PPR
return get_file_from_media(client, account_id, deployment_id, media_id, file_collection)


def get_configuration_from_media(client, account_id, deployment_id, media_id):
file_collection = FileColletion.CONFIFURATION
file_collection = FileCollection.CONFIFURATION
return get_file_from_media(client, account_id, deployment_id, media_id, file_collection)


Expand Down Expand Up @@ -248,6 +248,10 @@ def get_deployment_request_schema(deployment_request, hub):
'at': deployment_request.aborted_at,
'by': deployment_request.aborted_by,
},
'aborting': {
'at': deployment_request.aborting_at,
'by': deployment_request.aborting_by,
},
}

return DeploymentRequestSchema(
Expand Down
35 changes: 35 additions & 0 deletions connect_ext_ppr/webapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,41 @@ def list_deployment_request_marketplaces(
)
return marketplaces_list

@router.post(
'/deployments/requests/{depl_req_id}/abort',
summary='Abort a deployment request',
response_model=DeploymentRequestSchema,
)
def abort(
self,
depl_req_id: str,
db: VerboseBaseSession = Depends(get_db),
client: ConnectClient = Depends(get_installation_client),
installation: dict = Depends(get_installation),
request: Request = None,
):
dr = get_deployment_request_by_id(depl_req_id, db, installation)
origin_state = dr.status

tasks = (
db
.query(Task)
.filter_by(deployment_request=dr.id, status=Task.STATUSES.pending)
.with_for_update()
)
user_data = get_user_data_from_auth_token(request.headers['connect-auth'])
by = user_data['id']
dr.aborting(by)
db.flush()
for task in tasks:
task.abort(by)
db.flush()
if origin_state == DeploymentRequest.STATUSES.pending:
dr.abort_by_api(by)
db.commit()
hub = get_hub(client, dr.deployment.hub_id)
return get_deployment_request_schema(dr, hub)

@router.get(
'/deployments/{deployment_id}',
summary='Deployment details',
Expand Down
Loading

0 comments on commit 1bf7841

Please sign in to comment.