Process feedback; make it possible to install monitoring
This commit is contained in:
parent
6529636b3d
commit
4c57f92c8a
4 changed files with 84 additions and 59 deletions
|
|
@ -24,13 +24,6 @@ APPS_DATA = [
|
|||
|
||||
APP_DATA = {"id": 1, "name": "Nextcloud", "selected": True, "status": "ON for everyone", "config": CONFIG_DATA},
|
||||
|
||||
# Apps that should not get oauth variables when they are installed
|
||||
APPS_WITHOUT_OAUTH = [
|
||||
"single-sign-on",
|
||||
"prometheus",
|
||||
"alertmanager",
|
||||
]
|
||||
|
||||
APP_NOT_INSTALLED_STATUS = "Not installed"
|
||||
|
||||
@api_v1.route('/apps', methods=['GET'])
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from sqlalchemy import ForeignKey, Integer, String
|
|||
from sqlalchemy.orm import relationship
|
||||
from database import db
|
||||
import helpers.kubernetes as k8s
|
||||
from .apps import APPS_WITHOUT_OAUTH, APP_NOT_INSTALLED_STATUS
|
||||
from .apps import APP_NOT_INSTALLED_STATUS
|
||||
|
||||
|
||||
class App(db.Model):
|
||||
|
|
@ -22,32 +22,21 @@ class App(db.Model):
|
|||
def __repr__(self):
|
||||
return f"{self.id} <{self.name}>"
|
||||
|
||||
def get_kustomization_status(self):
|
||||
"""Returns True if the kustomization for this App is ready"""
|
||||
kustomization = k8s.get_kustomization(self.slug)
|
||||
if kustomization is None:
|
||||
return None
|
||||
return kustomization['status']
|
||||
|
||||
def get_helmrelease_status(self):
|
||||
"""Returns True if the kustomization for this App is ready"""
|
||||
helmrelease = k8s.get_helmrelease(self.slug, self.namespace)
|
||||
if helmrelease is None:
|
||||
return None
|
||||
return helmrelease['status']
|
||||
|
||||
def get_status(self):
|
||||
"""Returns a string that describes the app state in the cluster"""
|
||||
ks_status = self.get_kustomization_status()
|
||||
if ks_status is not None:
|
||||
ks_ready, ks_message = App.check_condition(ks_status)
|
||||
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
|
||||
hr_status = self.get_helmrelease_status()
|
||||
if hr_status is not None:
|
||||
for helmrelease in self.helmreleases['items']:
|
||||
hr_status = helmrelease['status']
|
||||
hr_ready, hr_message = App.check_condition(hr_status)
|
||||
else:
|
||||
hr_ready = None
|
||||
|
||||
# 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:
|
||||
|
|
@ -71,6 +60,15 @@ class App(db.Model):
|
|||
# Create add-<app> kustomization
|
||||
self.__create_kustomization()
|
||||
|
||||
def uninstall(self):
|
||||
"""
|
||||
Delete the app kustomization.
|
||||
|
||||
This triggers a deletion of the app's PVCs (so deletes all data), as
|
||||
well as any other Kustomizations and HelmReleases related to the app
|
||||
"""
|
||||
self.__delete_kustomization()
|
||||
|
||||
def delete(self):
|
||||
"""
|
||||
Fully deletes an application
|
||||
|
|
@ -80,34 +78,16 @@ class App(db.Model):
|
|||
"""
|
||||
# Delete all roles first
|
||||
for role in self.roles:
|
||||
db.session.delete(role)
|
||||
role.delete()
|
||||
|
||||
# Delete the kustomization
|
||||
if self.__delete_kustomization():
|
||||
|
||||
# TODO: This is where we might want to poll for status changes in the
|
||||
# app, so that only once the kustomization and all its stuff (other ks,
|
||||
# helmrelease, etc.) is deleted, we continue
|
||||
|
||||
# If the kustomization delete went well, commit DB changes.
|
||||
db.session.commit()
|
||||
# Then delete the app
|
||||
db.session.delete(self)
|
||||
db.session.commit()
|
||||
return True
|
||||
return False
|
||||
db.session.delete(self)
|
||||
return db.session.commit()
|
||||
|
||||
def __generate_secrets(self):
|
||||
"""Generates passwords for app installation"""
|
||||
# Create app variables secret
|
||||
if self.variables_template_filepath:
|
||||
k8s.create_variables_secret(self.slug, self.variables_template_filepath)
|
||||
# Create a secret that contains the oauth variables for Hydra Maester
|
||||
if self.slug not in APPS_WITHOUT_OAUTH:
|
||||
k8s.create_variables_secret(
|
||||
self.slug,
|
||||
os.path.join(self.__get_templates_dir(),
|
||||
"stackspin-oauth-variables.yaml.jinja"))
|
||||
|
||||
def __create_kustomization(self):
|
||||
"""Creates the `add-{app_slug}` kustomization in the Kubernetes cluster"""
|
||||
|
|
@ -150,6 +130,18 @@ class App(db.Model):
|
|||
app_id=self.id
|
||||
).all()
|
||||
|
||||
@property
|
||||
def kustomization(self):
|
||||
"""Returns the kustomization object for this app"""
|
||||
return k8s.get_kustomization(self.slug)
|
||||
|
||||
|
||||
@property
|
||||
def helmreleases(self):
|
||||
"""Returns the helmreleases associated with the kustomization for this app"""
|
||||
return k8s.list_helmreleases(self.namespace,
|
||||
f"kustomize.toolkit.fluxcd.io/name={self.slug}")
|
||||
|
||||
@staticmethod
|
||||
def __get_templates_dir():
|
||||
"""Returns directory that contains the Jinja templates used to create app secrets."""
|
||||
|
|
@ -161,7 +153,7 @@ class App(db.Model):
|
|||
Returns a tuple that has true/false for readiness and a message
|
||||
|
||||
Ready, in this case means that the condition's type == "Ready" and its
|
||||
status == "True". If the condition type "Ready" does not exist, the
|
||||
status == "True". If the condition type "Ready" does not occur, the
|
||||
status is interpreted as not ready.
|
||||
|
||||
The message that is returned is the message that comes with the
|
||||
|
|
@ -173,7 +165,7 @@ class App(db.Model):
|
|||
for condition in status["conditions"]:
|
||||
if condition["type"] == "Ready":
|
||||
return condition["status"] == "True", condition["message"]
|
||||
return False
|
||||
return False, "Condition with type 'Ready' not found"
|
||||
|
||||
|
||||
class AppRole(db.Model): # pylint: disable=too-few-public-methods
|
||||
|
|
|
|||
Reference in a new issue