297 lines
10 KiB
Python
297 lines
10 KiB
Python
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
from aiohttp import web
|
|
|
|
from aioservice.http import controller
|
|
from aioservice.http import requests
|
|
|
|
from ...common import config
|
|
from ...models import app as app_model
|
|
from ..views import app as app_view
|
|
|
|
|
|
class AppV1Controller(controller.ServiceController):
|
|
|
|
controller_name = "apps"
|
|
version = "v1"
|
|
|
|
@requests.api_action(method='GET', route='{project_id}/apps')
|
|
async def list(self, request, **kwargs):
|
|
"""
|
|
---
|
|
description: Listing project-scoped apps
|
|
tags:
|
|
- Apps
|
|
produces:
|
|
- application/json
|
|
responses:
|
|
"200":
|
|
description: Successful operation\
|
|
"401":
|
|
description: Not authorized
|
|
"""
|
|
c = config.Config.config_instance()
|
|
log, fnclient = c.logger, c.functions_client
|
|
project_id = request.match_info.get('project_id')
|
|
log.info("[{}] - Listing apps".format(project_id))
|
|
stored_apps = await app_model.Apps.find_by(project_id=project_id)
|
|
final = []
|
|
for app in stored_apps:
|
|
fn_app = await fnclient.apps.show(app.name, loop=c.event_loop)
|
|
final.append(app_view.AppView(app, fn_app).view())
|
|
log.info("[{}] - Apps found: {}".format(project_id, final))
|
|
return web.json_response(
|
|
data={
|
|
self.controller_name: final,
|
|
'message': "Successfully listed applications"
|
|
},
|
|
status=200
|
|
)
|
|
|
|
@requests.api_action(method='POST', route='{project_id}/apps')
|
|
async def create(self, request, **kwargs):
|
|
"""
|
|
---
|
|
description: Creating project-scoped app
|
|
tags:
|
|
- Apps
|
|
produces:
|
|
- application/json
|
|
parameters:
|
|
- in: body
|
|
name: app
|
|
description: Created project-scoped app
|
|
required: true
|
|
schema:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
responses:
|
|
"200":
|
|
description: Successful operation
|
|
"401":
|
|
description: Not authorized
|
|
"409":
|
|
description: App exists
|
|
"""
|
|
c = config.Config.config_instance()
|
|
log, fnclient = c.logger, c.functions_client
|
|
project_id = request.match_info.get('project_id')
|
|
data = await request.json()
|
|
log.info("[{}] - Creating app with data '{}'"
|
|
.format(project_id, str(data)))
|
|
app_name = "{}-{}".format(
|
|
data["app"]["name"],
|
|
project_id)[:30]
|
|
|
|
if await app_model.Apps.exists(app_name, project_id):
|
|
log.info("[{}] - Similar app was found, "
|
|
"aborting".format(project_id))
|
|
return web.json_response(data={
|
|
"error": {
|
|
"message": "App {0} already exists".format(app_name)
|
|
}
|
|
}, status=409)
|
|
|
|
fn_app = await fnclient.apps.create(app_name, loop=c.event_loop)
|
|
log.debug("[{}] - Fn app created".format(project_id))
|
|
stored_app = await app_model.Apps(
|
|
name=app_name, project_id=project_id,
|
|
description=data["app"].get(
|
|
"description",
|
|
"App for project {}".format(
|
|
project_id))).save()
|
|
log.debug("[{}] - App created".format(project_id))
|
|
return web.json_response(
|
|
data={
|
|
"app": app_view.AppView(stored_app, fn_app).view(),
|
|
"message": "App successfully created",
|
|
}, status=200
|
|
)
|
|
|
|
@requests.api_action(method='GET', route='{project_id}/apps/{app}')
|
|
async def get(self, request, **kwargs):
|
|
"""
|
|
---
|
|
description: Pulling project-scoped app
|
|
tags:
|
|
- Apps
|
|
produces:
|
|
- application/json
|
|
responses:
|
|
"200":
|
|
description: Successful operation
|
|
"401":
|
|
description: Not authorized
|
|
"404":
|
|
description: App not found
|
|
"""
|
|
c = config.Config.config_instance()
|
|
log, fnclient = c.logger, c.functions_client
|
|
project_id = request.match_info.get('project_id')
|
|
app = request.match_info.get('app')
|
|
log.info("[{}] - Searching for app with name {}"
|
|
.format(project_id, app))
|
|
|
|
if not (await app_model.Apps.exists(app, project_id)):
|
|
log.info("[{}] - App not found, "
|
|
"aborting".format(project_id))
|
|
return web.json_response(data={
|
|
"error": {
|
|
"message": "App {0} not found".format(app),
|
|
}
|
|
}, status=404)
|
|
|
|
stored_app = (await app_model.Apps.find_by(
|
|
project_id=project_id, name=app)).pop()
|
|
try:
|
|
fn_app = await fnclient.apps.show(app, loop=c.event_loop)
|
|
log.debug("[{}] - Fn app '{}' found".format(project_id, app))
|
|
except Exception as ex:
|
|
log.error("[{}] - Fn app '{}' was not found."
|
|
"Reason: \n{}".format(project_id, app, str(ex)))
|
|
return web.json_response(data={
|
|
"error": {
|
|
"message": getattr(ex, "reason", str(ex)),
|
|
}
|
|
}, status=getattr(ex, "status", 500))
|
|
log.debug("[{}] - App '{}' found".format(project_id, app))
|
|
return web.json_response(
|
|
data={
|
|
"app": app_view.AppView(stored_app, fn_app).view(),
|
|
"message": "Successfully loaded app",
|
|
},
|
|
status=200
|
|
)
|
|
|
|
@requests.api_action(method='PUT', route='{project_id}/apps/{app}')
|
|
async def update(self, request, **kwargs):
|
|
"""
|
|
---
|
|
description: Updating project-scoped app
|
|
tags:
|
|
- Apps
|
|
produces:
|
|
- application/json
|
|
responses:
|
|
"200":
|
|
description: Successful operation
|
|
"401":
|
|
description: Not authorized
|
|
"404":
|
|
description: App not found
|
|
"""
|
|
c = config.Config.config_instance()
|
|
log, fnclient = c.logger, c.functions_client
|
|
project_id = request.match_info.get('project_id')
|
|
app_name = request.match_info.get('app')
|
|
data = await request.json()
|
|
log.info("[{}] - Setting up update procedure "
|
|
"with data '{}'".format(project_id, data))
|
|
if not (await app_model.Apps.exists(app_name, project_id)):
|
|
log.info("[{}] - App not found, "
|
|
"aborting".format(project_id))
|
|
return web.json_response(data={
|
|
"error": {
|
|
"message": "App {0} not found".format(app_name),
|
|
}
|
|
}, status=404)
|
|
|
|
try:
|
|
fn_app = await fnclient.apps.update(
|
|
app_name, loop=c.event_loop, **data)
|
|
except Exception as ex:
|
|
log.info("[{}] - Unable to update app, "
|
|
"aborting. Reason: \n{}".format(project_id, str(ex)))
|
|
return web.json_response(data={
|
|
"error": {
|
|
"message": getattr(ex, "reason", str(ex)),
|
|
}
|
|
}, status=getattr(ex, "status", 500))
|
|
|
|
stored_app = (await app_model.Apps.find_by(
|
|
project_id=project_id, name=app_name)).pop()
|
|
log.info("[{}] - Updating app {} with data {}"
|
|
.format(project_id, app_name, str(data)))
|
|
return web.json_response(
|
|
data={
|
|
"app": app_view.AppView(stored_app, fn_app).view(),
|
|
"message": "App successfully updated"
|
|
},
|
|
status=200
|
|
)
|
|
|
|
@requests.api_action(method='DELETE', route='{project_id}/apps/{app}')
|
|
async def delete(self, request, **kwargs):
|
|
"""
|
|
---
|
|
description: Deleting project-scoped app
|
|
tags:
|
|
- Apps
|
|
produces:
|
|
- application/json
|
|
responses:
|
|
"200":
|
|
description: Successful operation
|
|
"401":
|
|
description: Not authorized
|
|
"404":
|
|
description: App not found
|
|
"""
|
|
project_id = request.match_info.get('project_id')
|
|
app = request.match_info.get('app')
|
|
c = config.Config.config_instance()
|
|
log, fnclient = c.logger, c.functions_client
|
|
if not (await app_model.Apps.exists(app, project_id)):
|
|
log.info("[{}] - App not found, "
|
|
"aborting".format(project_id))
|
|
return web.json_response(data={
|
|
"error": {
|
|
"message": "App {0} not found".format(app),
|
|
}
|
|
}, status=404)
|
|
try:
|
|
fn_app = await fnclient.apps.show(app, loop=c.event_loop)
|
|
fn_app_routes = await fn_app.routes.list(loop=c.event_loop)
|
|
except Exception as ex:
|
|
log.info("[{}] - Unable to get app, "
|
|
"aborting. Reason: \n{}".format(project_id, str(ex)))
|
|
return web.json_response(data={
|
|
"error": {
|
|
"message": getattr(ex, "reason", str(ex)),
|
|
}
|
|
}, status=getattr(ex, "status", 500))
|
|
|
|
if fn_app_routes:
|
|
log.info("[{}] - App has routes, unable to delete it, "
|
|
"aborting".format(project_id))
|
|
return web.json_response(data={
|
|
"error": {
|
|
"message": ("Unable to delete app {} "
|
|
"with routes".format(app))
|
|
}
|
|
}, status=403)
|
|
|
|
await app_model.Apps.delete(
|
|
project_id=project_id, name=app)
|
|
log.debug("[{}] - App model entry gone".format(project_id))
|
|
await fnclient.apps.delete(app, loop=c.event_loop)
|
|
log.debug("[{}] - Fn app deleted".format(project_id))
|
|
return web.json_response(
|
|
data={
|
|
"message": "App successfully deleted",
|
|
}, status=200)
|