Process lots of feedback

- Add a lot of docstrings
- Add AppStatus class
- Remove unused code
This commit is contained in:
Maarten de Waard 2022-09-28 09:46:56 +02:00
parent 8e41705d39
commit 2e55e2fa39
No known key found for this signature in database
GPG key ID: 1D3E893A657CC8DA
5 changed files with 221 additions and 777 deletions

View file

@ -24,8 +24,6 @@ APPS_DATA = [
APP_DATA = {"id": 1, "name": "Nextcloud", "selected": True, "status": "ON for everyone", "config": CONFIG_DATA},
APP_NOT_INSTALLED_STATUS = "Not installed"
@api_v1.route('/apps', methods=['GET'])
@jwt_required()
@cross_origin()

View file

@ -6,7 +6,6 @@ from sqlalchemy import ForeignKey, Integer, String
from sqlalchemy.orm import relationship
from database import db
import helpers.kubernetes as k8s
from .apps import APP_NOT_INSTALLED_STATUS
class App(db.Model):
@ -23,34 +22,8 @@ class App(db.Model):
return f"{self.id} <{self.name}>"
def get_status(self):
"""Returns a string that describes the app state in the cluster"""
kustomization = self.kustomization
if kustomization is not None and "status" in kustomization:
ks_ready, ks_message = App.check_condition(kustomization['status'])
else:
ks_ready = None
for helmrelease in self.helmreleases['items']:
hr_status = helmrelease['status']
hr_ready, hr_message = App.check_condition(hr_status)
# For now, only show the message of the first HR that isn't ready
if not hr_ready:
break
if ks_ready is None:
return APP_NOT_INSTALLED_STATUS
# *Should* not happen, but just in case:
if (ks_ready is None and hr_ready is not None) or \
(hr_ready is None and ks_ready is not None):
return ("This app is in a strange state. Contact a Stackspin"
" administrator if this status stays for longer than 5 minutes")
if ks_ready and hr_ready:
return "App installed and running"
if not hr_ready:
return f"App HelmRelease status: {hr_message}"
if not ks_ready:
return f"App Kustomization status: {ks_message}"
return "App is installing..."
"""Returns an AppStatus object that describes the current cluster state"""
return AppStatus(self.kustomization, self.helmreleases)
def install(self):
@ -139,7 +112,7 @@ class App(db.Model):
@property
def helmreleases(self):
"""Returns the helmreleases associated with the kustomization for this app"""
return k8s.list_helmreleases(self.namespace,
return k8s.get_all_helmreleases(self.namespace,
f"kustomize.toolkit.fluxcd.io/name={self.slug}")
@staticmethod
@ -147,6 +120,74 @@ class App(db.Model):
"""Returns directory that contains the Jinja templates used to create app secrets."""
return os.path.join(os.path.dirname(os.path.realpath(__file__)), "templates")
class AppRole(db.Model): # pylint: disable=too-few-public-methods
"""
The AppRole object, stores the roles Users have on Apps
"""
user_id = db.Column(String(length=64), primary_key=True)
app_id = db.Column(Integer, ForeignKey("app.id"), primary_key=True)
role_id = db.Column(Integer, ForeignKey("role.id"))
role = relationship("Role")
def __repr__(self):
return (f"role_id: {self.role_id}, user_id: {self.user_id},"
f" app_id: {self.app_id}, role: {self.role}")
class AppStatus(): # pylint: disable=too-few-public-methods
"""
Represents the status of an app in the Kubernetes cluster.
This class can answer a few questions, like "is the app installed?", but
can also return raw status messages from Kustomizations and HelmReleases
This constructor sets three variables:
self.installed (bool): Whether the app should be installed
self.ready (bool): Whether the app is installed correctly
self.message (str): Information about the status
:param kustomization_status: The status of the Kustomization of this app:
:type kustomization_status: str
:param helmrelease_status: The status of the helmreleases of this app
:type helmrelease_status: str[]
"""
def __init__(self, kustomization, helmreleases):
self.helmreleases = {}
if kustomization is not None and "status" in kustomization:
ks_ready, ks_message = AppStatus.check_condition(kustomization['status'])
self.installed = True
else:
ks_ready = None
ks_message = "Kustomization does not exist"
self.installed = False
self.ready = False
self.message = "Not installed"
for helmrelease in helmreleases:
hr_status = helmrelease['status']
hr_ready, hr_message = AppStatus.check_condition(hr_status)
# For now, only show the message of the first HR that isn't ready
if not hr_ready:
self.ready = False
self.message = f"HelmRelease {helmrelease['metadata']['name']} status: {hr_message}"
return
# If we end up here, all HRs are ready
if ks_ready:
self.ready = True
self.message = "Installed"
else:
self.ready = False
self.message = f"App Kustomization status: {ks_message}"
def __repr__(self):
return f"Installed: {self.installed}\tReady: {self.ready}\tMessage: {self.message}"
@staticmethod
def check_condition(status):
"""
@ -166,19 +207,3 @@ class App(db.Model):
if condition["type"] == "Ready":
return condition["status"] == "True", condition["message"]
return False, "Condition with type 'Ready' not found"
class AppRole(db.Model): # pylint: disable=too-few-public-methods
"""
The AppRole object, stores the roles Users have on Apps
"""
user_id = db.Column(String(length=64), primary_key=True)
app_id = db.Column(Integer, ForeignKey("app.id"), primary_key=True)
role_id = db.Column(Integer, ForeignKey("role.id"))
role = relationship("Role")
def __repr__(self):
return (f"role_id: {self.role_id}, user_id: {self.user_id},"
f" app_id: {self.app_id}, role: {self.role}")