Skip to content

Commit

Permalink
LITE-28160 Regenerate ppr when product version change
Browse files Browse the repository at this point in the history
  • Loading branch information
jonatrios committed Jul 25, 2023
1 parent 786ee1c commit 1820dfe
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 51 deletions.
11 changes: 9 additions & 2 deletions connect_ext_ppr/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from connect.eaas.core.responses import BackgroundResponse
from sqlalchemy.exc import DBAPIError

from connect_ext_ppr.service import add_deployments, update_product
from connect_ext_ppr.service import add_deployments, process_ppr_from_product_update
from connect_ext_ppr.utils import get_all_info, get_marketplaces, get_products


Expand Down Expand Up @@ -74,7 +74,14 @@ def handle_product_changed(self, request):
db, create a new one.
'''
self.logger.info(f"Product {request['id']} changed.")
update_product(request, self.config, self.logger)
self.context.account_id = self.installation['owner']['id']
self.context.user_id = self.installation['events']['installed']['by']['id']
try:
process_ppr_from_product_update(
request, self.config, self.context, self.installation_client, self.logger,
)
except (ClientError, DBAPIError):
return BackgroundResponse.reschedule()
return BackgroundResponse.done()

@event(
Expand Down
2 changes: 1 addition & 1 deletion connect_ext_ppr/models/deployment.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class Deployment(Model):
created_at = db.Column(db.DateTime(), default=datetime.utcnow)
updated_at = db.Column(db.DateTime(), onupdate=datetime.utcnow, default=datetime.utcnow)

product = relationship('Product', foreign_keys="Deployment.product_id")
product = relationship("Product", back_populates="deployment")


class DeploymentRequest(Model):
Expand Down
3 changes: 3 additions & 0 deletions connect_ext_ppr/models/replicas.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import sqlalchemy as db
from sqlalchemy.orm import relationship

from connect_ext_ppr.db import Model

Expand All @@ -11,3 +12,5 @@ class Product(Model):
logo = db.Column(db.String(2000), nullable=True)
version = db.Column(db.SmallInteger(), nullable=True)
owner_id = db.Column(db.String(255))

deployment = relationship("Deployment", back_populates="product", lazy="dynamic")
49 changes: 31 additions & 18 deletions connect_ext_ppr/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from connect_ext_ppr.models.file import File
from connect_ext_ppr.models.ppr import PPRVersion
from connect_ext_ppr.models.replicas import Product
from connect_ext_ppr.schemas import FileSchema
from connect_ext_ppr.schemas import FileSchema, PPRCreateSchema
from connect_ext_ppr.utils import (
create_ppr_to_media,
get_base_workbook,
Expand Down Expand Up @@ -85,18 +85,28 @@ def add_deployments(installation, listings, config, logger):
logger.info(f"The following Deployments have been created: {dep_ids}.")


def update_product(data, config, logger):
product_id = data['id']
def process_ppr_from_product_update(data, config, context, client, logger):
with get_db_ctx_manager(config) as db:
q = db.query(Product).filter_by(id=product_id)
q = db.query(Product).filter_by(id=data['id'])
if db.query(q.exists()).scalar():
logger.info(f"Updating product: {product_id}.")
product = q.first()
product.name = data['name']
product.logo = data.get('icon')
product.version = data['version']
db.add(product)
db.commit()
older_version = product.version
update_product(data, db, product, logger)
if data['version'] > older_version:
ppr = PPRCreateSchema()
dep_qs = product.deployment.filter_by(account_id=context.account_id)
logger.info(f"Product version changed: {older_version} -> {data['version']}.")
for dep in dep_qs:
create_ppr(ppr, context, dep, db, client, logger)


def update_product(data, db, product, logger):
logger.info(f"Updating product: {product.id}.")
product.name = data['name']
product.logo = data.get('icon')
product.version = data['version']
db.add(product)
db.commit()


def get_ppr_new_version(db, deployment):
Expand All @@ -116,6 +126,7 @@ def create_ppr(ppr, context, deployment, db, client, logger):
file_data = ppr.file
new_version = get_ppr_new_version(db, deployment)
config_kwargs = {}
config_json = {}
status = PPRVersion.STATUS.ready
if not file_data:
active_configuration = (
Expand All @@ -125,11 +136,11 @@ def create_ppr(ppr, context, deployment, db, client, logger):
state=Configuration.STATE.active,
).one_or_none()
)
if not active_configuration:
raise ExtensionHttpError.EXT_006(
format_kwargs={'deployment_id': deployment.id},
if active_configuration:
config_kwargs.update({'configuration': active_configuration.id})
config_json = get_configuration_from_media(
client, deployment.account_id, deployment.id, active_configuration.file,
)
config_kwargs.update({'configuration': active_configuration.id})
previous_ppr = (
db.query(PPRVersion)
.filter_by(
Expand All @@ -140,9 +151,6 @@ def create_ppr(ppr, context, deployment, db, client, logger):
.first()
)
data = None
config_json = get_configuration_from_media(
client, deployment.account_id, deployment.id, active_configuration.file,
)
product_info = (
f"(product_id={deployment.product_id}, "
f"product_version={deployment.product.version})"
Expand All @@ -158,7 +166,7 @@ def create_ppr(ppr, context, deployment, db, client, logger):
else:
logger.info(
f"Start creation of PPR version {product_info}"
f" based on previous product information.",
f" based on product information.",
)
items = list(get_product_items(client, deployment.product.id))

Expand Down Expand Up @@ -223,6 +231,11 @@ def create_ppr(ppr, context, deployment, db, client, logger):
)
db.set_verbose(new_ppr)
db.commit()

logger.info(
f"New PPR version created: (id={new_ppr.id}, version={new_ppr.version}"
f", product_version={new_ppr.product_version}, file={new_ppr.file}).",
)
return new_ppr

except DBAPIError as ex:
Expand Down
4 changes: 2 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def _build_deployment(
vendor_id='VA-000-000',
hub_id='HB-0000-0000',
):
product = product_factory(id=product_id)
product = product_factory(id=product_id, owner_id=vendor_id)
product_id = product.id

dep = Deployment(
Expand Down Expand Up @@ -284,7 +284,7 @@ def logger(mocker):

@pytest.fixture
def common_context():
return Context(call_type='user', user_id='UR-000-000-000')
return Context(call_type='user', user_id='UR-000-000-000', account_id='PA-000-000')


@pytest.fixture
Expand Down
92 changes: 90 additions & 2 deletions tests/test_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
# Copyright (c) 2023, Ingram Micro
# All rights reserved.
#
import json

from connect.client import ClientError
from connect.client.rql import R
import pytest

from connect_ext_ppr.events import ConnectExtensionXvsEventsApplication
from connect_ext_ppr.models.ppr import PPRVersion
from connect_ext_ppr.models.replicas import Product


Expand Down Expand Up @@ -109,14 +112,17 @@ def test_handle_product_changed(
logger,
installation,
product,
product_factory,
common_context,
deployment_factory,
):
config = {}
product_obj = product_factory(id=product['id'], owner_id='VA-123-123')
deployment = deployment_factory(product_id=product['id'], vendor_id='VA-123-123')
product_obj = deployment.product
ext = ConnectExtensionXvsEventsApplication(
connect_client, logger, config,
installation=installation,
installation_client=connect_client,
context=common_context,
)
result = ext.handle_product_changed(product)
assert result.status == 'success'
Expand All @@ -133,20 +139,102 @@ def test_ignore_product_changed(
logger,
installation,
product,
common_context,
):
config = {}

ext = ConnectExtensionXvsEventsApplication(
connect_client, logger, config,
installation=installation,
installation_client=connect_client,
context=common_context,
)
result = ext.handle_product_changed(product)
assert result.status == 'success'
q = dbsession.query(Product).filter_by(id=product['id'])
assert not dbsession.query(q.exists()).scalar()


def test_handle_ppr_creation_from_product_update(
product,
item_response,
media_response,
dbsession,
logger,
installation,
common_context,
connect_client,
deployment_factory,
configuration_factory,
configuration_json,
client_mocker_factory,
file_factory,
):
config = {}
new_product_version = product['version'] = 4
dep1 = deployment_factory(product_id=product['id'])
prod_obj = dep1.product
dep2 = deployment_factory(product_id=product['id'], hub_id='HB-1111-3333')
config_file = file_factory(
id='MFL-YYY',
mime_type='application/json',
)
for dep, media_id in ((dep1, 'MFL-WWW'), (dep2, 'MFL-ZZZ')):
configuration_factory(file=config_file.id, deployment=dep.id)
client_mocker = client_mocker_factory(base_url=connect_client.endpoint)
client_mocker.ns('media').ns('folders').ns('accounts').collection(
f'{dep.account_id}/{dep.id}/configurations/files',
)[config_file.id].get(
return_value=configuration_json,
)

client_mocker.products[dep.product_id].items.all().mock(
return_value=[item_response],
)
media_response['id'] = media_id
client_mocker.ns('media').ns('folders').ns('accounts').collection(
f'{dep.account_id}/{dep.id}/pprs/files',
).create(
return_value=json.dumps(media_response),
)

ext = ConnectExtensionXvsEventsApplication(
connect_client, logger, config,
installation=installation,
installation_client=connect_client,
context=common_context,
)
qs = dbsession.query(PPRVersion).filter_by(product_version=new_product_version)
result = ext.handle_product_changed(product)
assert result.status == 'success'
assert qs.count() == 2
assert prod_obj.version == new_product_version


def test_reschedule_product_change(
product,
dbsession,
logger,
installation,
common_context,
connect_client,
mocker,
):
config = {}
ext = ConnectExtensionXvsEventsApplication(
connect_client, logger, config,
installation=installation,
installation_client=connect_client,
context=common_context,
)
mocker.patch(
'connect_ext_ppr.events.process_ppr_from_product_update',
side_effect=ClientError,
)
result = ext.handle_product_changed(product)
assert result.status == 'reschedule'


@pytest.mark.parametrize(
'status',
('installed', 'uninstalled'),
Expand Down
Loading

0 comments on commit 1820dfe

Please sign in to comment.