Skip to content

Commit

Permalink
Merge pull request #46 from cloudblue/LITE-30057-invited-accounts-can…
Browse files Browse the repository at this point in the history
…-not-create-schedule-tasks

LITE-30057 Invited accounts can not create schedule tasks
  • Loading branch information
jonatrios authored Apr 25, 2024
2 parents fadf953 + 0d1ae56 commit ff2c593
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 89 deletions.
12 changes: 10 additions & 2 deletions connect_bi_reporter/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from connect.eaas.core.decorators import event, variables
from connect.eaas.core.extension import EventsApplicationBase
from connect.eaas.core.responses import BackgroundResponse
from connect.eaas.core.inject.models import Context
from connect_extension_utils.connect_services.base import get_extension_owner_client

from connect_bi_reporter.uploads.tasks import UploadTaskApplicationMixin
from connect_bi_reporter.scheduler import genererate_default_recurring_schedule_task
Expand Down Expand Up @@ -45,9 +47,15 @@ def handle_installation_status_change(self, request):
f"This extension has been installed by {account}: "
f"id={request['id']}, environment={request['environment']['id']}",
)
client = get_extension_owner_client(self.logger)
return genererate_default_recurring_schedule_task(
self.installation_client,
self.context,
client,
Context(
extension_id=self.context.extension_id,
environment_id=self.context.environment_id,
installation_id=request['id'],
account_id=request['owner']['id'],
),
self.logger,
BackgroundResponse,
)
Expand Down
14 changes: 11 additions & 3 deletions connect_bi_reporter/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
from connect.eaas.core.inject.models import Context

from connect_bi_reporter.connect_services.devops import create_schedule_task, get_schedule_tasks
from connect_bi_reporter.constants import DEFAULT_RECURRING_EAAS_SCHEDULE_TASK_DATA
from connect_bi_reporter.constants import (
CREATE_UPLOADS_METHOD_NAME,
DEFAULT_RECURRING_EAAS_SCHEDULE_TASK_DATA,
)


class TriggerTypeEnum(str, enum.Enum):
Expand Down Expand Up @@ -121,7 +124,11 @@ def genererate_default_recurring_schedule_task(
):
try:
scheduler = Scheduler(client, context, logger)
schedule_tasks = scheduler.get_schedule_tasks()
schedule_tasks = [
task for task in scheduler.get_schedule_tasks()
if task['method'] == CREATE_UPLOADS_METHOD_NAME
and task['parameter']['installation_id'] == context.installation_id
]
if schedule_tasks:
task_ids = ', '.join(task['id'] for task in schedule_tasks)
logger.info(
Expand All @@ -136,11 +143,12 @@ def genererate_default_recurring_schedule_task(
datetime.utcnow() + timedelta(days=1)
).replace(hour=0, minute=0, second=0, microsecond=0)
method_payload = {
'method': 'create_uploads',
'method': CREATE_UPLOADS_METHOD_NAME,
'name': f'Create Uploads - {context.account_id}',
'description': 'Create Uploads for recurrent processing.',
'parameter': {
'installation_id': context.installation_id,
'account_id': context.account_id,
},
}
trigger_data = {
Expand Down
14 changes: 9 additions & 5 deletions connect_bi_reporter/settings/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from connect.eaas.core.decorators import router
from connect.eaas.core.inject.common import get_call_context, get_logger
from connect.eaas.core.inject.models import Context
from connect.eaas.core.inject.synchronous import get_installation_client
from connect.eaas.core.inject.synchronous import get_extension_client
from connect_extension_utils.api.errors import Http404
from fastapi import Depends, status

Expand All @@ -24,14 +24,18 @@ class SettingsWebAppMixin:
)
def get_create_upload_task_info(
self,
client: ConnectClient = Depends(get_installation_client),
client: ConnectClient = Depends(get_extension_client),
context: Context = Depends(get_call_context),
logger: Logger = Depends(get_logger),
):
scheduler = Scheduler(client, context, logger)

task = scheduler.get_schedule_task_by_method_name(CREATE_UPLOADS_METHOD_NAME)
tasks = [
task for task in scheduler.get_schedule_tasks()
if task['method'] == CREATE_UPLOADS_METHOD_NAME
and task['parameter']['installation_id'] == context.installation_id
]

if not task:
if not tasks:
raise Http404(obj_id=CREATE_UPLOADS_METHOD_NAME)
return EaasScheduleTaskSchema(**task)
return EaasScheduleTaskSchema(**tasks[0])
29 changes: 20 additions & 9 deletions connect_bi_reporter/uploads/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
ScheduledExecutionResponse,
)
from connect_extension_utils.db.models import get_db_ctx_manager
from connect_extension_utils.connect_services.base import get_extension_owner_client
from sqlalchemy.exc import DBAPIError

from connect_bi_reporter.connect_services.reports import download_report
Expand All @@ -26,28 +27,38 @@ class UploadTaskApplicationMixin:
'Create Upload objects base on Connect Report files',
)
def create_uploads(self, schedule):
if 'installation_id' not in schedule['parameter']:
return ScheduledExecutionResponse.fail(output='Parameter installation_id is missing.')
missing_params = [
param for param in ['installation_id', 'account_id']
if param not in schedule['parameter']
]
if missing_params:
params = ', '.join(missing_params)
return ScheduledExecutionResponse.fail(
output=f'The following required schedule parameters are missing: `{params}`.',
)

installation_id = schedule['parameter']['installation_id']
account_id = schedule['parameter']['account_id']

extension_owner_client = get_extension_owner_client(self.logger)
installation_client = self.get_installation_admin_client(installation_id)
try:
client = self.get_installation_admin_client(installation_id)
installation = client('devops').installations[installation_id].get()

with get_db_ctx_manager(self.config) as db:
feeds = db.query(Feed).filter(
Feed.account_id == installation['owner']['id'],
Feed.account_id == account_id,
Feed.status == FeedStatusChoices.enabled,
).all()
if not feeds:
self.logger.info(Info.no_feeds_to_process)
return ScheduledExecutionResponse.done()
uploads = create_uploads(db, client, self.logger, feeds)
scheduler = Scheduler(client, self.context, self.logger)
uploads = create_uploads(db, installation_client, self.logger, feeds)
scheduler = Scheduler(extension_owner_client, self.context, self.logger)
create_process_upload_tasks(
uploads,
scheduler,
installation_id=installation['id'],
account_id=installation['owner']['id'],
installation_id=installation_id,
account_id=account_id,
)
except (ClientError, DBAPIError) as exc:
output = Errors.connect_client_error
Expand Down
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ services:
DATABASE_URL: postgresql+psycopg2://postgres:1q2w3e@db/bi_reporter
depends_on:
- db
links:
- "db_ram:db"

connect_bi_reporter_test:
container_name: connect_bi_reporter_test
Expand Down
17 changes: 13 additions & 4 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from pytest_factoryboy import register
from connect.client import AsyncConnectClient, ConnectClient
from connect.eaas.core.inject.models import Context
from connect.eaas.core.inject.common import get_call_context
from connect_extension_utils.db.models import get_db

from .factories import CredentialFactory, FeedFactory, UploadFactory
Expand Down Expand Up @@ -46,8 +47,13 @@ def logger(mocker):


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


@pytest.fixture(autouse=True)
Expand All @@ -64,10 +70,11 @@ def mocked_context(config):


@pytest.fixture
def api_client(test_client_factory, dbsession):
def api_client(test_client_factory, dbsession, common_context):
client = test_client_factory(ConnectBiReporterWebApplication)
client.app.dependency_overrides = {
get_db: lambda: dbsession,
get_call_context: lambda: common_context,
}
yield client

Expand Down Expand Up @@ -217,7 +224,9 @@ def eaas_schedule_task():
"name": "Create Uploads - PA-065-102",
"description": "Create Uploads for recurrent processing.",
"method": "create_uploads",
"parameter": {},
"parameter": {
"installation_id": "EIN-8436-7221-8308",
},
"trigger": {
"type": "recurring",
"start": "2024-01-10T09:35:03+00:00",
Expand Down
82 changes: 56 additions & 26 deletions tests/test_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# Copyright (c) 2024, Ingram Micro
# All rights reserved.
#
from datetime import datetime, timedelta

from connect.client import ClientError
from connect.eaas.core.inject.models import Context

Expand All @@ -11,33 +13,53 @@

def test_handle_installation_status_installed_create_task(
connect_client,
client_mocker_factory,
logger,
installation,
eaas_schedule_task,
mocker,
):
config = {}
client_mocker = client_mocker_factory(base_url=connect_client.endpoint)
mocker.patch(
'connect_bi_reporter.events.get_extension_owner_client',
return_value=connect_client,
)
start = datetime.utcnow()
string_start_date = (
start + timedelta(days=1)
).replace(hour=0, minute=0, second=0, microsecond=0).isoformat()
p_datetime = mocker.patch(
'connect_bi_reporter.scheduler.datetime',
)
p_datetime.utcnow.return_value = start
p_get_connect_task = mocker.patch(
'connect_bi_reporter.scheduler.get_schedule_tasks',
return_value=[],
)
p_create_connect_task = mocker.patch(
'connect_bi_reporter.scheduler.create_schedule_task',
return_value=eaas_schedule_task,
)
ctx = Context(
installation_id=installation['id'],
environment_id=installation['environment']['id'],
extension_id=installation['environment']['extension']['id'],
account_id=installation['environment']['extension']['owner']['id'],
)
(
client_mocker.ns('devops')
.services[ctx.extension_id]
.environments[ctx.environment_id]
.schedules.all().mock(
return_value=[],
)
)
(
client_mocker.ns('devops')
.services[ctx.extension_id]
.environments[ctx.environment_id]
.schedules.create(return_value=eaas_schedule_task)
)
task_payload = {
'description': 'Create Uploads for recurrent processing.',
'method': 'create_uploads',
'name': f'Create Uploads - {ctx.account_id}',
'parameter': {
'installation_id': ctx.installation_id,
'account_id': ctx.account_id,
},
'trigger': {
'amount': 1,
'start': string_start_date,
'type': 'recurring',
'unit': 'days',
},
}
ext = ConnectBiReporterEventsApplication(
connect_client,
logger,
Expand All @@ -46,6 +68,9 @@ def test_handle_installation_status_installed_create_task(
installation_client=connect_client,
)
result = ext.handle_installation_status_change(installation)
p_get_connect_task.assert_called_once_with(connect_client, ctx)
p_create_connect_task.assert_called_once_with(connect_client, ctx, task_payload)

assert result.status == 'success'
assert logger.method_calls[0].args[0] == (
f'This extension has been installed by Provider '
Expand All @@ -59,27 +84,30 @@ def test_handle_installation_status_installed_create_task(

def test_handle_installation_status_installed_task_already_exists(
connect_client,
client_mocker_factory,
logger,
installation,
eaas_schedule_task,
mocker,
):
config = {}
client_mocker = client_mocker_factory(base_url=connect_client.endpoint)
mocker.patch(
'connect_bi_reporter.events.get_extension_owner_client',
return_value=connect_client,
)
p_get_connect_task = mocker.patch(
'connect_bi_reporter.scheduler.get_schedule_tasks',
return_value=[eaas_schedule_task],
)
p_create_connect_task = mocker.patch(
'connect_bi_reporter.scheduler.create_schedule_task',
)
ctx = Context(
installation_id=installation['id'],
environment_id=installation['environment']['id'],
extension_id=installation['environment']['extension']['id'],
account_id=installation['environment']['extension']['owner']['id'],
)
(
client_mocker.ns('devops')
.services[ctx.extension_id]
.environments[ctx.environment_id]
.schedules.all().mock(
return_value=[eaas_schedule_task],
)
)

ext = ConnectBiReporterEventsApplication(
connect_client,
logger,
Expand All @@ -88,6 +116,8 @@ def test_handle_installation_status_installed_task_already_exists(
installation_client=connect_client,
)
result = ext.handle_installation_status_change(installation)
p_get_connect_task.assert_called_once_with(connect_client, ctx)
p_create_connect_task.assert_not_called()
assert result.status == 'success'
assert logger.method_calls[0].args[0] == (
f'This extension has been installed by Provider '
Expand Down
25 changes: 23 additions & 2 deletions tests/test_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,29 @@ def test_scheduler(connect_client, logger, mocker, eaas_schedule_task, installat
@pytest.mark.parametrize(
'response_type, mocker_return_value, expected_response',
(
(None, {'return_value': [{'id': 'test'}]}, None),
(None, {
'return_value': [
{
'id': 'some',
'method': 'create_uploads',
'parameter': {
'installation_id': 'EIN-8436-7221-8308',
},
},
],
}, None),
(None, {'side_effect': ClientError(message='Bad!', status_code=500)}, None),
(BackgroundResponse, {'return_value': [{'id': 'test'}]}, 'success'),
(BackgroundResponse, {
'return_value': [
{
'id': 'some',
'method': 'create_uploads',
'parameter': {
'installation_id': 'EIN-8436-7221-8308',
},
},
],
}, 'success'),
(
BackgroundResponse,
{'side_effect': ClientError(message='Bad!', status_code=500)},
Expand All @@ -110,6 +130,7 @@ def test_genererate_default_recurring_schedule_task(
response_type,
mocker_return_value,
expected_response,

):
ctx = Context(
installation_id=installation['id'],
Expand Down
Loading

0 comments on commit ff2c593

Please sign in to comment.