CLI interface for external apps
This commit is contained in:
parent
6e427f275f
commit
a2019a32d0
5 changed files with 113 additions and 8 deletions
|
@ -1,7 +1,12 @@
|
|||
from flask import jsonify
|
||||
from flask import jsonify, current_app
|
||||
from flask_jwt_extended import jwt_required
|
||||
from flask_cors import cross_origin
|
||||
|
||||
from sqlalchemy import func
|
||||
from config import *
|
||||
from .apps_service import AppsService
|
||||
from database import db
|
||||
|
||||
from areas import api_v1
|
||||
|
||||
CONFIG_DATA = [
|
||||
|
@ -26,17 +31,24 @@ APP_DATA = {"id": 1, "name": "Nextcloud", "selected": True, "status": "ON for ev
|
|||
|
||||
APP_NOT_INSTALLED_STATUS = "Not installed"
|
||||
|
||||
|
||||
@api_v1.route('/apps', methods=['GET'])
|
||||
@jwt_required()
|
||||
@cross_origin()
|
||||
def get_apps():
|
||||
return jsonify(APPS_DATA)
|
||||
apps = AppsService.get_all_apps()
|
||||
for obj in apps:
|
||||
current_app.logger.info(obj['slug'])
|
||||
current_app.logger.info(str(obj))
|
||||
return jsonify(apps)
|
||||
|
||||
|
||||
@api_v1.route('/apps/<string:slug>', methods=['GET'])
|
||||
@jwt_required()
|
||||
#@jwt_required()
|
||||
def get_app(slug):
|
||||
return jsonify(APPS_DATA[0])
|
||||
|
||||
app = AppsService.get_app(slug)
|
||||
return jsonify(app)
|
||||
|
||||
|
||||
@api_v1.route('/apps', methods=['POST'])
|
||||
|
|
|
@ -4,7 +4,13 @@ class AppsService:
|
|||
@staticmethod
|
||||
def get_all_apps():
|
||||
apps = App.query.all()
|
||||
return [{"id": app.id, "name": app.name, "slug": app.slug} for app in apps]
|
||||
return [{"id": app.id, "name": app.name, "slug": app.slug, "external": app.external, "url": app.get_url(), "status": app.get_status()} for app in apps]
|
||||
|
||||
@staticmethod
|
||||
def get_app(slug):
|
||||
app = App.query.filter_by(slug=slug).first()
|
||||
return {"id": app.id, "name": app.name, "slug": app.slug, "external": app.external, "url": app.get_url(), "status": app.get_status()}
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_app_roles():
|
||||
|
|
|
@ -2,12 +2,15 @@
|
|||
|
||||
import os
|
||||
|
||||
from sqlalchemy import ForeignKey, Integer, String
|
||||
from sqlalchemy import ForeignKey, Integer, String, Boolean
|
||||
from sqlalchemy.orm import relationship
|
||||
from database import db
|
||||
import helpers.kubernetes as k8s
|
||||
from .apps import APP_NOT_INSTALLED_STATUS
|
||||
|
||||
# Circular import, need fixing
|
||||
#from .apps import APP_NOT_INSTALLED_STATUS
|
||||
|
||||
APP_NOT_INSTALLED_STATUS = "Not installed"
|
||||
|
||||
class App(db.Model):
|
||||
"""
|
||||
|
@ -18,12 +21,31 @@ class App(db.Model):
|
|||
id = db.Column(Integer, primary_key=True)
|
||||
name = db.Column(String(length=64))
|
||||
slug = db.Column(String(length=64), unique=True)
|
||||
external = db.Column(Boolean, unique=False, nullable=False, default=True, server_default='0')
|
||||
url = db.Column(String(length=128), unique=False)
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.id} <{self.name}>"
|
||||
|
||||
def get_url(self):
|
||||
"""Returns the URL where this application is running"""
|
||||
|
||||
if self.external:
|
||||
return self.url
|
||||
|
||||
# TODO: Get URL from Kubernetes
|
||||
return "unknown"
|
||||
|
||||
def get_status(self):
|
||||
"""Returns a string that describes the app state in the cluster"""
|
||||
|
||||
if self.external:
|
||||
return("External app")
|
||||
|
||||
|
||||
# TODO: Get some kind of caching for those values, as this is called
|
||||
# on every app list, causing significant delays in the interface
|
||||
|
||||
kustomization = self.kustomization
|
||||
if kustomization is not None and "status" in kustomization:
|
||||
ks_ready, ks_message = App.check_condition(kustomization['status'])
|
||||
|
@ -78,7 +100,9 @@ class App(db.Model):
|
|||
"""
|
||||
# Delete all roles first
|
||||
for role in self.roles:
|
||||
role.delete()
|
||||
db.session.delete(role)
|
||||
#role.delete()
|
||||
db.session.commit()
|
||||
|
||||
db.session.delete(self)
|
||||
return db.session.commit()
|
||||
|
|
|
@ -71,6 +71,34 @@ def create_app(slug, name):
|
|||
db.session.commit()
|
||||
current_app.logger.info(f"App definition: {name} ({slug}) created")
|
||||
|
||||
@app_cli.command("create-external")
|
||||
@click.argument("slug")
|
||||
@click.argument("name")
|
||||
@click.argument("url")
|
||||
def create_external_app(slug, name, url):
|
||||
"""Create an app for external access
|
||||
:param slug: str short name of the app
|
||||
:param name: str name of the application
|
||||
:param url: str URL of application
|
||||
"""
|
||||
|
||||
obj = App()
|
||||
obj.name = name
|
||||
obj.slug = slug
|
||||
obj.external = True
|
||||
obj.url = url
|
||||
|
||||
app_obj = App.query.filter_by(slug=slug).first()
|
||||
|
||||
if app_obj:
|
||||
current_app.logger.info(f"App definition: {name} ({slug}) already exists in database")
|
||||
return
|
||||
|
||||
db.session.add(obj)
|
||||
db.session.commit()
|
||||
current_app.logger.info(f"App definition: {name} ({slug}) created")
|
||||
|
||||
|
||||
|
||||
|
||||
@app_cli.command("list")
|
||||
|
@ -151,6 +179,11 @@ def install_app(slug):
|
|||
current_app.logger.error(f"App {slug} does not exist")
|
||||
return
|
||||
|
||||
if app.external:
|
||||
current_app.logger.info(
|
||||
f"App {slug} is an external app and can not be provisioned automatically")
|
||||
return
|
||||
|
||||
current_status = app.get_status()
|
||||
if current_status == APP_NOT_INSTALLED_STATUS:
|
||||
app.install()
|
||||
|
|
30
migrations/versions/e08df0bef76f_.py
Normal file
30
migrations/versions/e08df0bef76f_.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
"""Add fields for external apps
|
||||
|
||||
Revision ID: e08df0bef76f
|
||||
Revises: b514cca2d47b
|
||||
Create Date: 2022-09-23 16:38:06.557307
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'e08df0bef76f'
|
||||
down_revision = 'b514cca2d47b'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('app', sa.Column('external', sa.Boolean(), server_default='0', nullable=False))
|
||||
op.add_column('app', sa.Column('url', sa.String(length=128), nullable=True))
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_column('app', 'url')
|
||||
op.drop_column('app', 'external')
|
||||
# ### end Alembic commands ###
|
Loading…
Reference in a new issue