From 4d94d389cd2ee478f79246fc0ccbed05ce6e2c54 Mon Sep 17 00:00:00 2001
From: Maarten de Waard <maarten@greenhost.nl>
Date: Tue, 4 Oct 2022 12:35:56 +0200
Subject: [PATCH] include status in apps endpoint

---
 areas/apps/apps_service.py |  4 ++--
 areas/apps/models.py       | 43 ++++++++++++++++++++++----------------
 2 files changed, 27 insertions(+), 20 deletions(-)

diff --git a/areas/apps/apps_service.py b/areas/apps/apps_service.py
index 1e4f232f..665b4fed 100644
--- a/areas/apps/apps_service.py
+++ b/areas/apps/apps_service.py
@@ -4,12 +4,12 @@ class AppsService:
     @staticmethod
     def get_all_apps():
         apps = App.query.all()
-        return [app.to_json() for app in apps]
+        return [app.to_dict() for app in apps]
 
     @staticmethod
     def get_app(slug):
         app = App.query.filter_by(slug=slug).first()
-        return app.to_json()
+        return app.to_dict()
 
     @staticmethod
     def get_app_roles():
diff --git a/areas/apps/models.py b/areas/apps/models.py
index 71cedf48..851c8108 100644
--- a/areas/apps/models.py
+++ b/areas/apps/models.py
@@ -5,10 +5,10 @@ import base64
 
 from sqlalchemy import ForeignKey, Integer, String, Boolean
 from sqlalchemy.orm import relationship
+
 from database import db
 import helpers.kubernetes as k8s
 
-from flask import current_app
 
 DEFAULT_APP_SUBDOMAINS = {
     "nextcloud": "files",
@@ -76,7 +76,7 @@ class App(db.Model):
 
     def get_status(self):
         """Returns an AppStatus object that describes the current cluster state"""
-        return AppStatus(self.kustomization, self.helmreleases)
+        return AppStatus(self)
 
     def install(self):
         """Creates a Kustomization in the Kubernetes cluster that installs this application"""
@@ -172,7 +172,7 @@ class App(db.Model):
         """Returns the kustomization object for this app"""
         return k8s.get_kustomization(self.slug)
 
-    def to_json(self):
+    def to_dict(self):
         """
         represent this object as a json object. Return JSON object
         """
@@ -181,9 +181,9 @@ class App(db.Model):
                 "name": self.name,
                 "slug": self.slug,
                 "external": self.external,
+                "status": self.get_status().to_dict(),
                 "url": self.get_url()}
 
-
     @property
     def helmreleases(self):
         """Returns the helmreleases associated with the kustomization for this app"""
@@ -196,7 +196,6 @@ class App(db.Model):
         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
@@ -225,16 +224,19 @@ class AppStatus():  # pylint: disable=too-few-public-methods
     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[]
+    :param app: An app of which the kustomization and helmreleases
+        property will be used.
+    :type app: App
     """
-    def __init__(self, kustomization, helmreleases):
-        self.helmreleases = {}
+    def __init__(self, app):
+        kustomization = app.kustomization
         if kustomization is not None and "status" in kustomization:
             ks_ready, ks_message = AppStatus.check_condition(kustomization['status'])
             self.installed = True
+            if ks_ready:
+                self.ready = ks_ready
+                self.message = "Installed"
+                return
         else:
             ks_ready = None
             ks_message = "Kustomization does not exist"
@@ -243,6 +245,7 @@ class AppStatus():  # pylint: disable=too-few-public-methods
             self.message = "Not installed"
             return
 
+        helmreleases = app.helmreleases
         for helmrelease in helmreleases:
             hr_status = helmrelease['status']
             hr_ready, hr_message = AppStatus.check_condition(hr_status)
@@ -253,13 +256,9 @@ class AppStatus():  # pylint: disable=too-few-public-methods
                 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}"
+        # If we end up here, all HRs are ready, but the kustomization is not
+        self.ready = ks_ready
+        self.message = f"App Kustomization status: {ks_message}"
 
     def __repr__(self):
         return f"Installed: {self.installed}\tReady: {self.ready}\tMessage: {self.message}"
@@ -283,3 +282,11 @@ class AppStatus():  # pylint: disable=too-few-public-methods
             if condition["type"] == "Ready":
                 return condition["status"] == "True", condition["message"]
         return False, "Condition with type 'Ready' not found"
+
+    def to_dict(self):
+        """Represents this app status as a dict"""
+        return {
+            "installed": self.installed,
+            "ready": self.ready,
+            "message": self.message,
+        }
-- 
GitLab