Skip to content
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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@
* `ui-` for ones imported from Connect UI Toolkit
* Table columns now may be styled directly with a column descriptor `style` property
* 0.2.3: Better handling of DB and Client Server errors
* 0.3.0: Administrative UI
* 0.3.0: Administrative UI
* 0.3.1: Helpdesk Cases are automatically resolved in administrative actions
6 changes: 3 additions & 3 deletions dbaas/extension.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"name": "DBaaS",
"description": "On-demand provisioning of cloud-based database storages as a service.",
"version": "0.3.0",
"version": "0.3.1",
"audience": ["reseller", "distributor", "vendor"],
"readme_url": "https://github.com/cloudblue/connect-extension-dbaas/blob/0.3.0/README.md",
"changelog_url": "https://github.com/cloudblue/connect-extension-dbaas/blob/0.3.0/CHANGELOG.md",
"readme_url": "https://github.com/cloudblue/connect-extension-dbaas/blob/0.3.1/README.md",
"changelog_url": "https://github.com/cloudblue/connect-extension-dbaas/blob/0.3.1/CHANGELOG.md",
"icon": "googleExtensionBaseline"
}
38 changes: 32 additions & 6 deletions dbaas/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# All rights reserved.
#

import asyncio
import random
import string
from copy import copy
Expand Down Expand Up @@ -107,6 +108,7 @@ async def delete(
cls,
db_document: dict,
db: AsyncIOMotorDatabase,
client: AsyncConnectClient,
**kwargs,
) -> dict:
updated_db_document = copy(db_document)
Expand All @@ -121,8 +123,10 @@ async def delete(
{'id': db_document['id']},
{'$set': updates},
)

updated_db_document.update(updates)

cls._resolve_last_db_document_case(db_document, client)

return cls._db_document_repr(updated_db_document)

@classmethod
Expand Down Expand Up @@ -181,9 +185,10 @@ async def activate(
data: dict,
db: AsyncIOMotorDatabase,
config: dict,
client: AsyncConnectClient,
**kwargs,
) -> dict:
updated_db_document = await cls._activate(db_document, data, db, config)
updated_db_document = await cls._activate(db_document, data, db, config, client)

return cls._db_document_repr(updated_db_document, config=config)

Expand All @@ -194,6 +199,7 @@ async def _activate(
data: dict,
db: AsyncIOMotorDatabase,
config: dict,
client: AsyncConnectClient,
):
status = db_document.get('status')
credentials = data.get('credentials')
Expand Down Expand Up @@ -226,8 +232,10 @@ async def _activate(
{'id': db_document['id']},
{'$set': updates},
)

updated_db_document.update(updates)

cls._resolve_last_db_document_case(db_document, client)

return updated_db_document

@classmethod
Expand Down Expand Up @@ -272,6 +280,12 @@ async def _update(
updated_db_document.update(updates)
return updated_db_document

@classmethod
def _resolve_last_db_document_case(cls, db_document: dict, client: AsyncConnectClient):
case = cls._get_last_db_document_case(db_document)
if case:
asyncio.create_task(ConnectHelpdeskCase.resolve(case['id'], client))

@classmethod
def _default_query(cls, context: Context) -> dict:
q = {'status': {'$ne': DBStatus.DELETED}}
Expand All @@ -285,9 +299,9 @@ def _default_query(cls, context: Context) -> dict:
def _db_document_repr(cls, db_document: dict, config: dict = None) -> dict:
document = copy(db_document)

cases = document.get('cases')
if cases:
document['case'] = cases[-1]
case = cls._get_last_db_document_case(document)
if case:
document['case'] = case

status = document.get('status')
credentials = db_document.get('credentials')
Expand All @@ -300,6 +314,11 @@ def _db_document_repr(cls, db_document: dict, config: dict = None) -> dict:

return document

@classmethod
def _get_last_db_document_case(cls, db_document: dict) -> Optional[dict]:
cases = db_document.get('cases')
return cases[-1] if cases else None

@classmethod
async def _get_validated_region_document(
cls,
Expand Down Expand Up @@ -605,3 +624,10 @@ async def create(
helpdesk_case = await client('helpdesk').cases.create(payload=data)

return helpdesk_case

@classmethod
async def resolve(cls, case_id: str, client: AsyncConnectClient):
try:
await client('helpdesk').cases[case_id]('resolve').post()
except ClientError:
client.logger.logger.warning('Could not resolve case %s.', case_id)

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dbaas/static/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<html><head><title>Lorem ipsum</title><link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Roboto+Mono:400,500|Material+Icons" rel="stylesheet"><link id="mock-favicon" rel="shortcut icon" href="#"><script defer="defer" src="6c5bb1bba5eebb952b58.js"></script><link href="main.css" rel="stylesheet"></head><body><div id="app"></div></body></html>
<html><head><title>Lorem ipsum</title><link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Roboto+Mono:400,500|Material+Icons" rel="stylesheet"><link id="mock-favicon" rel="shortcut icon" href="#"><script defer="defer" src="b7d579a519616740b116.js"></script><link href="main.css" rel="stylesheet"></head><body><div id="app"></div></body></html>
2 changes: 1 addition & 1 deletion dbaas/static/main.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion dbaas/webapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,11 @@ async def delete_database(
self,
db_id: _db_id_type,
context: Context = Depends(get_call_context),
client: AsyncConnectClient = Depends(get_installation_client),
db=Depends(get_db),
):
result = await self._action(
db_id, action=DB.delete, is_admin_action=True, context=context, db=db,
db_id, action=DB.delete, is_admin_action=True, context=context, db=db, client=client,
)

return responses.Response(status_code=204) if isinstance(result, BaseModel) else result
Expand Down Expand Up @@ -209,6 +210,7 @@ async def activate_database(
data: DatabaseActivate,
context: Context = Depends(get_call_context),
config: dict = Depends(get_config),
client: AsyncConnectClient = Depends(get_installation_client),
db=Depends(get_db),
):
result = await self._action(
Expand All @@ -219,6 +221,7 @@ async def activate_database(
context=context,
db=db,
config=config,
client=client,
)

return result
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 16 additions & 17 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 7 additions & 6 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,16 @@ def default_endpoint():


@pytest.fixture
def async_connect_client(default_endpoint):
def logger(mocker):
return mocker.MagicMock()


@pytest.fixture
def async_connect_client(default_endpoint, logger):
return AsyncConnectClient(
'ApiKey fake_api_key',
endpoint=default_endpoint,
logger=logger,
)


Expand All @@ -36,11 +42,6 @@ def async_client_mocker(async_client_mocker_factory, default_endpoint):
return async_client_mocker_factory(base_url=default_endpoint)


@pytest.fixture
def logger(mocker):
return mocker.MagicMock()


@pytest.fixture
def config():
return {
Expand Down
23 changes: 23 additions & 0 deletions tests/services/test_connect_helpdesk_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,26 @@ async def test_create_ok(async_client_mocker, async_connect_client):
result = await ConnectHelpdeskCase.create(data, async_connect_client)

assert result == helpdesk_case


@pytest.mark.asyncio
@pytest.mark.parametrize('status_code', (400, 404, 503))
async def test_resolve_bad_response_from_connect_api(
async_client_mocker, status_code, async_connect_client,
):
async_client_mocker('helpdesk').cases['CS-123']('resolve').post(status_code=status_code)

await ConnectHelpdeskCase.resolve('CS-123', async_connect_client)

async_connect_client.logger.logger.warning.assert_called_once_with(
'Could not resolve case %s.', 'CS-123',
)


@pytest.mark.asyncio
async def test_resolve_ok(async_client_mocker, async_connect_client):
async_client_mocker('helpdesk').cases['CS-456']('resolve').post(return_value={'x': True})

assert await ConnectHelpdeskCase.resolve('CS-456', async_connect_client) is None

async_connect_client.logger.logger.warning.assert_not_called()
Loading