return op_id on asynchronous delete
[osm/NBI.git] / osm_nbi / admin_topics.py
index 90c5d08..df31e90 100644 (file)
@@ -320,26 +320,25 @@ class CommonVimWimSdn(BaseTopic):
         if dry_run:
             return None
 
-        # remove reference from project_read. If not last delete
-        if session["project_id"]:
-            for project_id in session["project_id"]:
-                if project_id in db_content["_admin"]["projects_read"]:
-                    db_content["_admin"]["projects_read"].remove(project_id)
-                if project_id in db_content["_admin"]["projects_write"]:
-                    db_content["_admin"]["projects_write"].remove(project_id)
-        else:
-            db_content["_admin"]["projects_read"].clear()
-            db_content["_admin"]["projects_write"].clear()
-
-        update_dict = {"_admin.projects_read": db_content["_admin"]["projects_read"],
-                       "_admin.projects_write": db_content["_admin"]["projects_write"]
-                       }
-
-        # check if there are projects referencing it (apart from ANY that means public)....
-        if db_content["_admin"]["projects_read"] and (len(db_content["_admin"]["projects_read"]) > 1 or
-                                                      db_content["_admin"]["projects_read"][0] != "ANY"):
-            self.db.set_one(self.topic, filter_q, update_dict=update_dict)  # remove references but not delete
-            return None
+        # remove reference from project_read if there are more projects referencing it. If it last one,
+        # do not remove reference, but order via kafka to delete it
+        if session["project_id"] and session["project_id"]:
+            other_projects_referencing = next((p for p in db_content["_admin"]["projects_read"]
+                                               if p not in session["project_id"]), None)
+
+            # check if there are projects referencing it (apart from ANY, that means, public)....
+            if other_projects_referencing:
+                # remove references but not delete
+                update_dict_pull = {"_admin.projects_read.{}".format(p): None for p in session["project_id"]}
+                update_dict_pull.update({"_admin.projects_write.{}".format(p): None for p in session["project_id"]})
+                self.db.set_one(self.topic, filter_q, update_dict=None, pull=update_dict_pull)
+                return None
+            else:
+                can_write = next((p for p in db_content["_admin"]["projects_write"] if p == "ANY" or
+                                  p in session["project_id"]), None)
+                if not can_write:
+                    raise EngineException("You have not write permission to delete it",
+                                          http_code=HTTPStatus.UNAUTHORIZED)
 
         # It must be deleted
         if session["force"]:
@@ -347,7 +346,7 @@ class CommonVimWimSdn(BaseTopic):
             op_id = None
             self._send_msg("deleted", {"_id": _id, "op_id": op_id}, not_send_msg=not_send_msg)
         else:
-            update_dict["_admin.to_delete"] = True
+            update_dict = {"_admin.to_delete": True}
             self.db.set_one(self.topic, {"_id": _id},
                             update_dict=update_dict,
                             push={"_admin.operations": self._create_operation("delete")}
@@ -437,6 +436,15 @@ class K8sClusterTopic(CommonVimWimSdn):
         oid = super().format_on_new(content, project_id, make_public)
         self.db.encrypt_decrypt_fields(content["credentials"], 'encrypt', ['password', 'secret'],
                                        schema_version=content["schema_version"], salt=content["_id"])
+        # Add Helm/Juju Repo lists
+        repos = {"helm-chart": [], "juju-bundle": []}
+        for proj in content["_admin"]["projects_read"]:
+            if proj != 'ANY':
+                for repo in self.db.get_list("k8srepos", {"_admin.projects_read": proj}):
+                    if repo["_id"] not in repos[repo["type"]]:
+                        repos[repo["type"]].append(repo["_id"])
+        for k in repos:
+            content["_admin"][k.replace('-', '_')+"_repos"] = repos[k]
         return oid
 
     def format_on_edit(self, final_content, edit_content):
@@ -447,6 +455,22 @@ class K8sClusterTopic(CommonVimWimSdn):
         oid = super().format_on_edit(final_content, edit_content)
         return oid
 
+    def check_conflict_on_edit(self, session, final_content, edit_content, _id):
+        super(CommonVimWimSdn, self).check_conflict_on_edit(session, final_content, edit_content, _id)
+        super().check_conflict_on_edit(session, final_content, edit_content, _id)
+        # Update Helm/Juju Repo lists
+        repos = {"helm-chart": [], "juju-bundle": []}
+        for proj in session.get("set_project", []):
+            if proj != 'ANY':
+                for repo in self.db.get_list("k8srepos", {"_admin.projects_read": proj}):
+                    if repo["_id"] not in repos[repo["type"]]:
+                        repos[repo["type"]].append(repo["_id"])
+        for k in repos:
+            rlist = k.replace('-', '_') + "_repos"
+            if rlist not in final_content["_admin"]:
+                final_content["_admin"][rlist] = []
+            final_content["_admin"][rlist] += repos[k]
+
 
 class K8sRepoTopic(CommonVimWimSdn):
     topic = "k8srepos"
@@ -457,6 +481,26 @@ class K8sRepoTopic(CommonVimWimSdn):
     password_to_encrypt = None
     config_to_encrypt = {}
 
+    def format_on_new(self, content, project_id=None, make_public=False):
+        oid = super().format_on_new(content, project_id, make_public)
+        # Update Helm/Juju Repo lists
+        repo_list = content["type"].replace('-', '_')+"_repos"
+        for proj in content["_admin"]["projects_read"]:
+            if proj != 'ANY':
+                self.db.set_list("k8sclusters",
+                                 {"_admin.projects_read": proj, "_admin."+repo_list+".ne": content["_id"]}, {},
+                                 push={"_admin."+repo_list: content["_id"]})
+        return oid
+
+    def delete(self, session, _id, dry_run=False, not_send_msg=None):
+        type = self.db.get_one("k8srepos", {"_id": _id})["type"]
+        oid = super().delete(session, _id, dry_run, not_send_msg)
+        if oid:
+            # Remove from Helm/Juju Repo lists
+            repo_list = type.replace('-', '_') + "_repos"
+            self.db.set_list("k8sclusters", {"_admin."+repo_list: _id}, {}, pull={"_admin."+repo_list: _id})
+        return oid
+
 
 class UserTopicAuth(UserTopic):
     # topic = "users"
@@ -611,19 +655,19 @@ class UserTopicAuth(UserTopic):
         Get complete information on an topic
 
         :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
-        :param _id: server internal id
+        :param _id: server internal id or username
         :return: dictionary, raise exception if not found.
         """
         # Allow _id to be a name or uuid
-        filter_q = {self.id_field(self.topic, _id): _id}
+        filter_q = {"username": _id}
         # users = self.auth.get_user_list(filter_q)
         users = self.list(session, filter_q)   # To allow default filtering (Bug 853)
         if len(users) == 1:
             return users[0]
         elif len(users) > 1:
-            raise EngineException("Too many users found", HTTPStatus.CONFLICT)
+            raise EngineException("Too many users found for '{}'".format(_id), HTTPStatus.CONFLICT)
         else:
-            raise EngineException("User not found", HTTPStatus.NOT_FOUND)
+            raise EngineException("User '{}' not found".format(_id), HTTPStatus.NOT_FOUND)
 
     def edit(self, session, _id, indata=None, kwargs=None, content=None):
         """
@@ -982,10 +1026,10 @@ class RoleTopicAuth(BaseTopic):
     schema_edit = roles_edit_schema
     multiproject = False
 
-    def __init__(self, db, fs, msg, auth, ops):
+    def __init__(self, db, fs, msg, auth):
         BaseTopic.__init__(self, db, fs, msg, auth)
         # self.auth = auth
-        self.operations = ops
+        self.operations = auth.role_permissions
         # self.topic = "roles_operations" if isinstance(auth, AuthconnKeystone) else "roles"
 
     @staticmethod