Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LITE-30057 Invited accounts can not create schedule tasks #46

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading