Fix for bug 1447 Grafana user not associated with team 51/10351/13
authorAtul Agarwal <Atul.Agarwal@Altran.com>
Mon, 15 Mar 2021 09:16:09 +0000 (09:16 +0000)
committerpalsus <subhankar.pal@aricent.com>
Tue, 16 Mar 2021 14:31:40 +0000 (15:31 +0100)
Change-Id: I69aced0620b1bbf8d79f862ee9bf352d1ea9b4d5
Signed-off-by: palsus <subhankar.pal@aricent.com>
Signed-off-by: Atul Agarwal <Atul.Agarwal@Altran.com>
osm_mon/core/common_db.py
osm_mon/core/keystone.py
osm_mon/dashboarder/backends/grafana.py
osm_mon/dashboarder/dashboarder.py
osm_mon/dashboarder/service.py

index ce44d4d..aa65388 100644 (file)
@@ -162,3 +162,6 @@ class CommonDbClient:
 
     def get_role_by_name(self, name: str):
         return self.common_db.get_one('roles', {'name': name})
+
+    def get_role_by_id(self, role_id: str):
+        return self.common_db.get_one('roles', {'_id': role_id})
index 98a8d78..f389085 100644 (file)
@@ -57,8 +57,38 @@ class KeystoneConnection:
         """
         return self.keystone_client.projects.list()
 
+    def getProjectsById(self, user_id):
+        """
+        Grabs projects filtered by user ID from keystone using the client and session build in the constructor
+        """
+        return self.keystone_client.projects.list(user=user_id)
+
     def getUserById(self, user_id):
         """
         Grabs user object from keystone using user id
         """
         return self.keystone_client.users.get(user_id)
+
+    def getRoleById(self, role_id):
+        """
+        Grabs role object from keystone using id
+        """
+        return self.keystone_client.roles.get(role_id)
+
+    def getRoleByName(self, role):
+        """
+        Grabs role object from keystone using name
+        """
+        return self.keystone_client.roles.list(name=role)
+
+    def getProjectsByProjectId(self, project_id):
+        """
+        Grabs projects object from keystone using id
+        """
+        return self.keystone_client.projects.get(project_id)
+
+    def getProjectsByProjectName(self, project):
+        """
+        Grabs projects object from keystone name
+        """
+        return self.keystone_client.projects.list(name=project)
index eeb5e75..a1cbcba 100644 (file)
@@ -207,6 +207,7 @@ class GrafanaBackend:
         requests.request("POST", self.url + "/api/folders/{}/permissions".format(folder_name),
                          json=permission_data, headers=self.headers)
 
+    # delete user from grafana
     def delete_grafana_users(self, user_name):
         # Get user id
         response_id = requests.request("GET", self.url + "/api/users/lookup?loginOrEmail={}".format(user_name),
@@ -220,6 +221,7 @@ class GrafanaBackend:
         log.info("User %s deleted in Grafana", user_name)
         return response
 
+    # delete team from grafana
     def delete_grafana_team(self, project_name):
         # Delete Grafana folder
         requests.request("DELETE", self.url + "/api/folders/{}".format(project_name),
@@ -232,6 +234,7 @@ class GrafanaBackend:
         log.info("Team %s deleted in Grafana", project_name)
         return response
 
+    # update grafana team
     def update_grafana_teams(self, project_new_name, project_old_name):
         team_obj = requests.request("GET", self.url + "/api/teams/search?name={}".format(project_old_name),
                                     headers=self.headers)
@@ -240,3 +243,18 @@ class GrafanaBackend:
         response = requests.request("PUT", self.url + "/api/teams/{}".format(team_id), json=data, headers=self.headers)
         log.info("Grafana team updated %s", response.text)
         return response
+
+    # remove member from grafana team
+    def remove_grafana_team_member(self, user_name, project_data):
+        # Get user id
+        response_id = requests.request("GET", self.url + "/api/users/lookup?loginOrEmail={}".format(user_name),
+                                       headers=self.headers)
+        user_id = json.loads(response_id.text)["id"]
+        for project in project_data:
+            # Get team id
+            team_obj = requests.request("GET", self.url + "/api/teams/search?name={}".format(project['project']),
+                                        headers=self.headers)
+            team_id = json.loads(team_obj.text)["teams"][0]["id"]
+            response = requests.request("DELETE", self.url + "/api/teams/{}/members/{}".format(team_id, user_id),
+                                        headers=self.headers)
+        return response
index a6ff5bc..35364d6 100644 (file)
@@ -55,8 +55,28 @@ class Dashboarder:
         try:
             if topic == "users" and key == "created":
                 log.debug("Received message from kafka for creating user")
-                user = values['username']
+                if values.get('username'):
+                    user = values['username']
+                else:
+                    user = values['changes']['username']
                 self.service.create_grafana_user(user)
+                # user-created and mapping is done with osm cli
+                if values.get('changes'):
+                    # user-project-role mapping is included in change
+                    if values['changes'].get('project_role_mappings'):
+                        user_id = values["_id"]
+                        project_data = values["changes"]["project_role_mappings"]
+                        project_list = values["changes"].get("projects")
+                        self.service.create_grafana_team_member(project_data, user_id, project_list)
+                elif values.get('project_role_mappings'):
+                    # for fresh project-role-mapping
+                    user_id = values.get("_id")
+                    project_data = values["project_role_mappings"]
+                    if user_id:
+                        self.service.create_grafana_team_member(project_data, user_id)
+                    else:
+                        # for keystone we will get username
+                        self.service.create_grafana_team_member(project_data, user=values['username'])
             elif topic == "users" and key == "deleted":
                 log.debug("Received message from kafka for deleting user")
                 user = values['username']
@@ -64,8 +84,18 @@ class Dashboarder:
             elif topic == "users" and key == "edited":
                 log.debug("Received message from kafka for associating user to team")
                 user_id = values["_id"]
-                project_data = values["changes"]["project_role_mappings"]
-                self.service.create_grafana_team_member(project_data, user_id)
+                if values["changes"].get("remove_project_role_mappings") and not \
+                        values["changes"].get("add_project_role_mappings"):
+                    # Removing user-project role mapping
+                    self.service.remove_grafana_team_members(user_id,
+                                                             values["changes"].get("remove_project_role_mappings"))
+                else:
+                    # Changing user project role mapping
+                    if values["changes"].get("project_role_mappings"):
+                        project_data = values["changes"]["project_role_mappings"]
+                    else:
+                        project_data = values["changes"]["add_project_role_mappings"]
+                    self.service.create_grafana_team_member(project_data, user_id)
             elif topic == "project" and key == "created":
                 log.debug("Received message from kafka for creating team")
                 team_name = values["name"]
index 79cccb4..d791fa9 100644 (file)
@@ -135,27 +135,72 @@ class DashboarderService:
     def create_grafana_user(self, user):
         self.grafana.create_grafana_users(user)
 
-    def create_grafana_team_member(self, project_data, userid):
-        try:
-            # Get user details from  commondb
-            user = self.common_db.get_user_by_id(userid)
-            user_name = user["username"]
-        except Exception as e:
-            # User not found in commondb
+    def create_grafana_team_member(self, project_data, userid=None, project_list=None, user=None):
+        if user:
+            user_name = user
+        else:
+            try:
+                # Get user details from  commondb
+                user = self.common_db.get_user_by_id(userid)
+                user_name = user["username"]
+            except Exception as e:
+                # User not found in commondb
+                if self.keystone:
+                    # Search user in keystone
+                    user = self.keystone.getUserById(userid)
+                    user_name = user.name
+                else:
+                    log.info('User %s not found', userid)
+                    log.debug('Exception %s' % e)
+        if project_list:
+            # user-project mapping is done by osm cli
+            for proj in project_data:
+                project = self.common_db.get_project(proj["project"])
+                proj_name = project['name']
+                role_obj = self.common_db.get_role_by_id(proj["role"])
+                is_admin = role_obj["permissions"].get("admin")
+                self.grafana.create_grafana_teams_members(proj_name, user_name, is_admin, project_list)
+        else:
+            # user-project mapping is done by osm ui
+            proj_list = []
             if self.keystone:
-                # Serach user in keystone
-                user = self.keystone.getUserById(userid)
-                user_name = user.name
+                users_proj_list = self.keystone.getProjectsById(userid)
+                for project in users_proj_list:
+                    proj_list.append(project.name)
             else:
-                log.info('User %s not found', userid)
-                log.debug('Exception %s' % e)
-        proj_list = []
-        for project in project_data:
-            proj_list.append(project["project"])
-        for proj in project_data:
-            role_obj = self.common_db.get_role_by_name(proj["role"])
-            is_admin = role_obj["permissions"].get("admin")
-            self.grafana.create_grafana_teams_members(proj["project"], user_name, is_admin, proj_list)
+                users_proj_list = user.get("project_role_mappings")
+                for project in users_proj_list:
+                    proj_data = self.common_db.get_project(project["project"])
+                    proj_list.append(proj_data['name'])
+            for proj in project_data:
+                if self.keystone:
+                    # Backend authentication type is keystone
+                    try:
+                        # Getting project and role objects from keystone using ids
+                        role_obj = self.keystone.getRoleById(proj["role"])
+                        proj_data = self.keystone.getProjectsByProjectId(proj["project"])
+                        log.info('role object {} {}'.format(role_obj.permissions, proj_data.name))
+                        is_admin = role_obj.permissions['admin']
+                    except Exception:
+                        # Getting project and role objects from keystone using names
+                        role_obj = self.keystone.getRoleByName(proj["role"])[0]
+                        proj_data = self.keystone.getProjectsByProjectName(proj["project"])[0]
+                        is_admin = role_obj.to_dict().get("permissions").get('admin')
+                        log.info('role object {} {}'.format(role_obj.to_dict(), proj_data.name))
+                    proj_name = proj_data.name
+                else:
+                    # Backend authentication type is internal
+                    try:
+                        # Getting project and role object from commondb using names
+                        role_obj = self.common_db.get_role_by_name(proj["role"])
+                        proj_name = proj["project"]
+                    except Exception:
+                        # Getting project and role object from commondb using ids
+                        role_obj = self.common_db.get_role_by_id(proj["role"])
+                        proj_data = self.common_db.get_project(proj["project"])
+                        proj_name = proj_data['name']
+                    is_admin = role_obj["permissions"].get("admin")
+                self.grafana.create_grafana_teams_members(proj_name, user_name, is_admin, proj_list)
 
     def create_grafana_team(self, team_name):
         self.grafana.create_grafana_teams(team_name)
@@ -168,3 +213,19 @@ class DashboarderService:
 
     def update_grafana_team(self, project_new_name, project_old_name):
         self.grafana.update_grafana_teams(project_new_name, project_old_name)
+
+    def remove_grafana_team_members(self, user_id, proj_data):
+        try:
+            # Get user details from  commondb
+            user = self.common_db.get_user_by_id(user_id)
+            user_name = user["username"]
+        except Exception as e:
+            # User not found in commondb
+            if self.keystone:
+                # Find user in keystone
+                user = self.keystone.getUserById(user_id)
+                user_name = user.name
+            else:
+                log.info('User %s not found', user_id)
+                log.debug('Exception %s' % e)
+        self.grafana.remove_grafana_team_member(user_name, proj_data)