Coverage for mindsdb / integrations / handlers / jira_handler / jira_handler.py: 3%

66 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-21 00:36 +0000

1from typing import Any, Dict 

2 

3from atlassian import Jira 

4from requests.exceptions import HTTPError 

5 

6from mindsdb.integrations.handlers.jira_handler.jira_tables import ( 

7 JiraProjectsTable, 

8 JiraIssuesTable, 

9 JiraUsersTable, 

10 JiraGroupsTable, 

11) 

12from mindsdb.integrations.libs.api_handler import APIHandler 

13from mindsdb.integrations.libs.response import ( 

14 HandlerResponse as Response, 

15 HandlerStatusResponse as StatusResponse, 

16 RESPONSE_TYPE, 

17) 

18from mindsdb.utilities import log 

19 

20 

21logger = log.getLogger(__name__) 

22 

23 

24class JiraHandler(APIHandler): 

25 """ 

26 This handler handles the connection and execution of SQL statements on Jira. 

27 """ 

28 

29 def __init__(self, name: str, connection_data: Dict, **kwargs: Any) -> None: 

30 """ 

31 Initializes the handler. 

32 

33 Args: 

34 name (Text): The name of the handler instance. 

35 connection_data (Dict): The connection data required to connect to the Jira API. 

36 kwargs: Arbitrary keyword arguments. 

37 """ 

38 super().__init__(name) 

39 self.connection_data = connection_data 

40 self.kwargs = kwargs 

41 

42 self.connection = None 

43 self.is_connected = False 

44 

45 self._register_table("projects", JiraProjectsTable(self)) 

46 self._register_table("issues", JiraIssuesTable(self)) 

47 self._register_table("groups", JiraGroupsTable(self)) 

48 self._register_table("users", JiraUsersTable(self)) 

49 

50 def connect(self) -> Jira: 

51 """ 

52 Establishes a connection to the Jira API. 

53 

54 Raises: 

55 ValueError: If the required connection parameters are not provided. 

56 AuthenticationError: If an authentication error occurs while connecting to the Salesforce API. 

57 

58 Returns: 

59 atlassian.jira.Jira: A connection object to the Jira API. 

60 """ 

61 if self.is_connected is True: 

62 return self.connection 

63 

64 is_cloud = self.connection_data.get("cloud", True) 

65 

66 if is_cloud: 

67 # Jira Cloud supports API token authentication. 

68 if not all(key in self.connection_data for key in ["username", "api_token", "url"]): 

69 raise ValueError("Required parameters (username, api_token, url) must be provided.") 

70 

71 config = { 

72 "username": self.connection_data["username"], 

73 "password": self.connection_data["api_token"], 

74 "url": self.connection_data["url"], 

75 "cloud": is_cloud, 

76 } 

77 else: 

78 # Jira Server supports personal access token authentication or open access. 

79 if "url" not in self.connection_data: 

80 raise ValueError("Required parameter 'url' must be provided.") 

81 

82 config = {"url": self.connection_data["url"], "cloud": False} 

83 

84 if "personal_access_token" in self.connection_data: 

85 config["session"] = {"Authorization": f"Bearer {self.connection_data['personal_access_token']}"} 

86 

87 try: 

88 self.connection = Jira(**config) 

89 self.is_connected = True 

90 return self.connection 

91 except Exception as unknown_error: 

92 logger.error(f"Unknown error connecting to Jira, {unknown_error}!") 

93 raise 

94 

95 def check_connection(self) -> StatusResponse: 

96 """ 

97 Checks the status of the connection to the Salesforce API. 

98 

99 Returns: 

100 StatusResponse: An object containing the success status and an error message if an error occurs. 

101 """ 

102 response = StatusResponse(False) 

103 

104 try: 

105 connection = self.connect() 

106 connection.myself() 

107 response.success = True 

108 except (HTTPError, ValueError) as known_error: 

109 logger.error(f"Connection check to Jira failed, {known_error}!") 

110 response.error_message = str(known_error) 

111 except Exception as unknown_error: 

112 logger.error(f"Connection check to Jira failed due to an unknown error, {unknown_error}!") 

113 response.error_message = str(unknown_error) 

114 

115 self.is_connected = response.success 

116 

117 return response 

118 

119 def native_query(self, query: str) -> Response: 

120 """ 

121 Executes a native JQL query on Jira and returns the result. 

122 

123 Args: 

124 query (Text): The JQL query to be executed. 

125 

126 Returns: 

127 Response: A response object containing the result of the query or an error message. 

128 """ 

129 connection = self.connect() 

130 

131 try: 

132 results = connection.jql(query) 

133 df = JiraIssuesTable(self).normalize(results["issues"]) 

134 response = Response(RESPONSE_TYPE.TABLE, df) 

135 except HTTPError as http_error: 

136 logger.error(f"Error running query: {query} on Jira, {http_error}!") 

137 response = Response(RESPONSE_TYPE.ERROR, error_code=0, error_message=str(http_error)) 

138 except Exception as unknown_error: 

139 logger.error(f"Error running query: {query} on Jira, {unknown_error}!") 

140 response = Response(RESPONSE_TYPE.ERROR, error_code=0, error_message=str(unknown_error)) 

141 

142 return response