risotto/src/risotto/services/source/source.py

166 lines
8.6 KiB
Python

from typing import Dict, List
from ...controller import Controller
from ...register import register
from ...context import Context
import requests
import yaml
import os
from ...utils import _
from ...config import get_config
class Risotto(Controller):
@register('v1.source.create')
async def source_create(self,
risotto_context: Context,
source_name: str,
source_url: str) -> Dict:
source_upsert = """INSERT INTO Source(SourceName, SourceURL) VALUES ($1, $2)
ON CONFLICT (SourceName) DO UPDATE SET SourceURL = $2
RETURNING SourceId
"""
# If given url is not 'none' (a.k.a internal source)
# Look for file releases.yml at given url
# If such a file exists, consider source a valid one and create source in database.
if source_url != 'none':
try:
releases = yaml.load(requests.get(source_url.rstrip('/') + '/releases.yml').content, Loader=yaml.SafeLoader)
except requests.exceptions.ConnectionError as err:
raise Exception(_('Invalid URL'))
except yaml.scanner.ScannerError as err:
raise Exception(_('Invalid releases.yml file'))
except:
raise Exception(_('Invalid source'))
else:
releases = {'1.0.0': {'distribution': 'last'}}
os.makedirs(os.path.join(get_config().get('source').get('root_path'), source_name), exist_ok=True)
with open(os.path.join(get_config().get('source').get('root_path'), source_name, 'releases.yml'), 'w') as release_file:
yaml.dump(releases, release_file)
source_id = await risotto_context.connection.fetchval(source_upsert,
source_name,
source_url)
return {'source_name': source_name,
'source_url': source_url,
'source_id': source_id}
@register('v1.source.describe')
async def source_describe(self,
risotto_context: Context,
source_name: str) -> Dict:
source_get = """SELECT SourceId as source_id, SourceName as source_name, SourceURL as source_url
FROM Source
WHERE SourceName = $1
"""
source = await risotto_context.connection.fetchrow(source_get,
source_name)
if not source:
raise Exception(_(f'unknown source with name {source_name}'))
return dict(source)
@register('v1.source.list')
async def source_list(self,
risotto_context: Context) -> List[Dict]:
source_list = """SELECT SourceId as source_id, SourceName as source_name, SourceURL as source_url
FROM Source
"""
result = await risotto_context.connection.fetch(source_list)
return [dict(r) for r in result]
@register('v1.source.dataset.update')
async def version_update(self,
risotto_context: Context,
source_id: int,
release_name: str):
# source.release.create is an upsert, do not using it
release_insert = """INSERT INTO Release(ReleaseName, ReleaseSourceId) VALUES ($1, $2)
RETURNING ReleaseId
"""
release_id = await risotto_context.connection.fetchval(release_insert,
release_name,
source_id)
return {'release_id': release_id,
'release_name': release_name}
@register('v1.source.release.create')
async def source_release_create(self,
risotto_context: Context,
source_name: str,
release_name: str,
release_distribution: str) -> Dict:
source_get = """SELECT SourceId as source_id, SourceName as source_name, SourceURL as source_url
FROM Source
WHERE SourceName = $1
"""
release_upsert = """INSERT INTO Release(ReleaseName, ReleaseSourceId, ReleaseDistribution) VALUES ($1, $2, $3)
ON CONFLICT (ReleaseName, ReleaseSourceId) DO UPDATE SET ReleaseName = $1
RETURNING ReleaseId
"""
source_obj = await risotto_context.connection.fetchrow(source_get,
source_name)
if not source_obj:
raise Exception(_(f'unable to find a source with name {source_name}'))
source = dict(source_obj)
release_id = await risotto_context.connection.fetchval(release_upsert,
release_name,
source['source_id'],
release_distribution)
del source['source_id']
source['release_id'] = release_id
source['release_name'] = release_name
source['release_distribution'] = release_distribution
return source
@register('v1.source.release.list')
async def release_list(self,
risotto_context,
source_name: str) -> Dict:
release_query = """SELECT ReleaseId as release_id, SourceName as source_name, SourceURL as source_url, ReleaseName as release_name, ReleaseDistribution as release_distribution
FROM Release, Source
WHERE Source.SourceName=$1 AND Source.SourceId=Release.ReleaseSourceId"""
result = await risotto_context.connection.fetch(release_query,
source_name)
return [dict(r) for r in result]
@register('v1.source.release.describe')
async def release_list(self,
risotto_context,
source_name: str,
release_distribution: str) -> Dict:
release_query = """SELECT ReleaseId as release_id, SourceName as source_name, SourceURL as source_url, ReleaseName as release_name, ReleaseDistribution as release_distribution
FROM Release, Source
WHERE Source.SourceName=$1 AND Source.SourceId=Release.ReleaseSourceId AND Release.ReleaseDistribution=$2"""
result = await risotto_context.connection.fetchrow(release_query,
source_name,
release_distribution)
if not result:
raise Exception(_(f'unknown release distribution {release_distribution} in source {source_name}'))
return dict(result)
@register('v1.source.release.get_by_id')
async def release_get_by_id(self,
risotto_context: Context,
release_id: int) -> Dict:
release_query = """SELECT ReleaseId as release_id, SourceName as source_name, SourceURL as source_url, ReleaseName as release_name, ReleaseDistribution as release_distribution
FROM Release, Source
WHERE Release.ReleaseId = $1 AND Source.SourceId = Release.ReleaseSourceId"""
result = await risotto_context.connection.fetchrow(release_query,
release_id)
if not result:
raise Exception(_(f'unknown release id {release_id}'))
return dict(result)
@register('v1.source.release.get_by_distribution')
async def release_get_by_distribution(self,
risotto_context: Context,
source_id: int,
release_distribution: str) -> Dict:
release_query = """SELECT ReleaseId as release_id, SourceName as source_name, SourceURL as source_url, ReleaseName as release_name, ReleaseDistribution as release_distribution
FROM Release, Source
WHERE Release.ReleaseSourceId = $1 AND Release.ReleaseDistribution = $2 AND Source.SourceId = Release.ReleaseSourceId"""
result = await risotto_context.connection.fetchrow(release_query,
source_id,
release_distribution)
if not result:
raise Exception(_(f'unknown distribution {release_distribution} with source {source_id}'))
return dict(result)