From 8a7a9f1386788d2d4e00ab4156c10f1d0cc729df Mon Sep 17 00:00:00 2001 From: Jacob Zufelt Date: Fri, 22 Nov 2024 13:26:54 -0700 Subject: [PATCH 1/6] Handle when jira is behind a proxy --- jira/resources.py | 30 ++++++++++++++++++++++++++++++ tests/resources/test_issue.py | 26 ++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/jira/resources.py b/jira/resources.py index c138974b3..ce81cc5e6 100644 --- a/jira/resources.py +++ b/jira/resources.py @@ -14,6 +14,7 @@ from requests import Response from requests.structures import CaseInsensitiveDict +from urllib.parse import urlparse, urlunparse, ParseResult from jira.resilientsession import ResilientSession, parse_errors from jira.utils import json_loads, remove_empty_attributes, threaded_requests @@ -292,6 +293,32 @@ def _get_url(self, path: str) -> str: options.update({"path": path}) return self._base_url.format(**options) + def _validate_self_self_url(self): + """In the case of a proxy, use the configured base URL + and not the one returned from JIRA. + + Args: + self (Resource): self + + Returns: + None + + """ + + self_parsed = urlparse(self.self) + server_parsed = urlparse(self._options['server']) + if self_parsed.netloc != server_parsed.netloc: + self.self = urlunparse( + ParseResult( + scheme=self_parsed.scheme, + netloc=server_parsed.netloc, + path=self_parsed.path, + params=self_parsed.params, + query=self_parsed.query, + fragment= self_parsed.fragment + ) + ) + def update( self, fields: dict[str, Any] | None = None, @@ -326,6 +353,7 @@ def update( else: querystring = "" + self._validate_self_self_url() r = self._session.put(self.self + querystring, data=json.dumps(data)) if "autofix" in self._options and r.status_code == 400: user = None @@ -420,6 +448,8 @@ def delete(self, params: dict[str, Any] | None = None) -> Response | None: Returns: Optional[Response]: Returns None if async """ + + self._validate_self_self_url() if self._options["async"]: # FIXME: mypy doesn't think this should work if not hasattr(self._session, "_async_jobs"): diff --git a/tests/resources/test_issue.py b/tests/resources/test_issue.py index a496edb2e..33eb927b7 100644 --- a/tests/resources/test_issue.py +++ b/tests/resources/test_issue.py @@ -337,6 +337,20 @@ def test_update_with_label(self): issue.update(fields=fields) self.assertEqual(issue.fields.labels, ["testLabel"]) + def test_update_label_with_proxy(self): + issue = self.jira.create_issue( + summary="Test issue for updating labels", + project=self.project_b, + description="Label testing", + issuetype=self.test_manager.CI_JIRA_ISSUE, + ) + + labelarray = ["testLabel"] + fields = {"labels": labelarray} + issue.self = f"http://foo.bar/jira/rest/api/2/issue/{issue.id}" + issue.update(fields=fields) + self.assertEqual(issue.fields.labels, ["testLabel"]) + def test_update_with_bad_label(self): issue = self.jira.create_issue( summary="Test issue for updating bad labels", @@ -373,6 +387,18 @@ def test_delete(self): issue.delete() self.assertRaises(JIRAError, self.jira.issue, key) + def test_delete_with_proxy(self): + issue = self.jira.create_issue( + summary="Test issue created", + project=self.project_b, + description="Not long for this world", + issuetype=self.test_manager.CI_JIRA_ISSUE, + ) + key = issue.key + issue.self = f"http://foo.bar/jira/rest/api/2/issue/{issue.id}" + issue.delete() + self.assertRaises(JIRAError, self.jira.issue, key) + def test_createmeta(self): meta = self.jira.createmeta() proj = find_by_key(meta["projects"], self.project_b) From 9e8e8bc0382aaa02de8d0cc1688320f294ffeb34 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 22 Nov 2024 20:31:37 +0000 Subject: [PATCH 2/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- jira/resources.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/jira/resources.py b/jira/resources.py index ce81cc5e6..5d3ddbc74 100644 --- a/jira/resources.py +++ b/jira/resources.py @@ -11,10 +11,10 @@ import re import time from typing import TYPE_CHECKING, Any, cast +from urllib.parse import ParseResult, urlparse, urlunparse from requests import Response from requests.structures import CaseInsensitiveDict -from urllib.parse import urlparse, urlunparse, ParseResult from jira.resilientsession import ResilientSession, parse_errors from jira.utils import json_loads, remove_empty_attributes, threaded_requests @@ -296,17 +296,16 @@ def _get_url(self, path: str) -> str: def _validate_self_self_url(self): """In the case of a proxy, use the configured base URL and not the one returned from JIRA. - + Args: self (Resource): self Returns: None - - """ + """ self_parsed = urlparse(self.self) - server_parsed = urlparse(self._options['server']) + server_parsed = urlparse(self._options["server"]) if self_parsed.netloc != server_parsed.netloc: self.self = urlunparse( ParseResult( @@ -314,8 +313,8 @@ def _validate_self_self_url(self): netloc=server_parsed.netloc, path=self_parsed.path, params=self_parsed.params, - query=self_parsed.query, - fragment= self_parsed.fragment + query=self_parsed.query, + fragment=self_parsed.fragment, ) ) @@ -448,7 +447,6 @@ def delete(self, params: dict[str, Any] | None = None) -> Response | None: Returns: Optional[Response]: Returns None if async """ - self._validate_self_self_url() if self._options["async"]: # FIXME: mypy doesn't think this should work From d7430605ef4475bf0bce43a1cf54dac75bf41bd7 Mon Sep 17 00:00:00 2001 From: Jacob Zufelt Date: Fri, 22 Nov 2024 13:33:33 -0700 Subject: [PATCH 3/6] Use the proxy scheme in case it is different --- jira/resources.py | 2 +- tests/resources/test_issue.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/jira/resources.py b/jira/resources.py index 5d3ddbc74..ae8d9a332 100644 --- a/jira/resources.py +++ b/jira/resources.py @@ -309,7 +309,7 @@ def _validate_self_self_url(self): if self_parsed.netloc != server_parsed.netloc: self.self = urlunparse( ParseResult( - scheme=self_parsed.scheme, + scheme=server_parsed.scheme, netloc=server_parsed.netloc, path=self_parsed.path, params=self_parsed.params, diff --git a/tests/resources/test_issue.py b/tests/resources/test_issue.py index 33eb927b7..f80722f7e 100644 --- a/tests/resources/test_issue.py +++ b/tests/resources/test_issue.py @@ -347,7 +347,7 @@ def test_update_label_with_proxy(self): labelarray = ["testLabel"] fields = {"labels": labelarray} - issue.self = f"http://foo.bar/jira/rest/api/2/issue/{issue.id}" + issue.self = f"https://foo.bar/jira/rest/api/2/issue/{issue.id}" issue.update(fields=fields) self.assertEqual(issue.fields.labels, ["testLabel"]) @@ -395,7 +395,7 @@ def test_delete_with_proxy(self): issuetype=self.test_manager.CI_JIRA_ISSUE, ) key = issue.key - issue.self = f"http://foo.bar/jira/rest/api/2/issue/{issue.id}" + issue.self = f"https://foo.bar/jira/rest/api/2/issue/{issue.id}" issue.delete() self.assertRaises(JIRAError, self.jira.issue, key) From 3dfaa9dac1ca07b5743c8352f7aeb15a7f081965 Mon Sep 17 00:00:00 2001 From: Jacob Zufelt Date: Fri, 22 Nov 2024 13:44:24 -0700 Subject: [PATCH 4/6] mypy --- jira/resources.py | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/jira/resources.py b/jira/resources.py index ae8d9a332..6523d0cbf 100644 --- a/jira/resources.py +++ b/jira/resources.py @@ -293,17 +293,8 @@ def _get_url(self, path: str) -> str: options.update({"path": path}) return self._base_url.format(**options) - def _validate_self_self_url(self): - """In the case of a proxy, use the configured base URL - and not the one returned from JIRA. - - Args: - self (Resource): self - - Returns: - None - - """ + def _validate_self_self_url(self) -> None: + """In the case of a proxy, use the configured option server URL.""" self_parsed = urlparse(self.self) server_parsed = urlparse(self._options["server"]) if self_parsed.netloc != server_parsed.netloc: From 4633ee5860906cc24b8a6df9377cea9cb858903d Mon Sep 17 00:00:00 2001 From: Jacob Zufelt Date: Fri, 22 Nov 2024 15:02:23 -0700 Subject: [PATCH 5/6] linting --- jira/resources.py | 28 +++++++++++++++------------- tests/resources/test_issue.py | 4 ++++ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/jira/resources.py b/jira/resources.py index 6523d0cbf..7127e2402 100644 --- a/jira/resources.py +++ b/jira/resources.py @@ -295,19 +295,21 @@ def _get_url(self, path: str) -> str: def _validate_self_self_url(self) -> None: """In the case of a proxy, use the configured option server URL.""" - self_parsed = urlparse(self.self) - server_parsed = urlparse(self._options["server"]) - if self_parsed.netloc != server_parsed.netloc: - self.self = urlunparse( - ParseResult( - scheme=server_parsed.scheme, - netloc=server_parsed.netloc, - path=self_parsed.path, - params=self_parsed.params, - query=self_parsed.query, - fragment=self_parsed.fragment, + if getattr(self, "self", None): + self.self: str + self_parsed = urlparse(self.self) + server_parsed = urlparse(self._options["server"]) + if self_parsed.netloc != server_parsed.netloc: + self.self = urlunparse( + ParseResult( + scheme=server_parsed.scheme, + netloc=server_parsed.netloc, + path=self_parsed.path, + params=self_parsed.params, + query=self_parsed.query, + fragment=self_parsed.fragment, + ) ) - ) def update( self, @@ -1523,7 +1525,7 @@ def __init__( session: ResilientSession, raw: dict[str, Any] | None = None, ): - self.self = None + self.self = "" Resource.__init__(self, path, options, session, self.AGILE_BASE_URL) if raw: diff --git a/tests/resources/test_issue.py b/tests/resources/test_issue.py index f80722f7e..6b36e6275 100644 --- a/tests/resources/test_issue.py +++ b/tests/resources/test_issue.py @@ -347,6 +347,8 @@ def test_update_label_with_proxy(self): labelarray = ["testLabel"] fields = {"labels": labelarray} + #This simulates when your Jira server is behind a proxy + #The self address returned will be different from the configured server issue.self = f"https://foo.bar/jira/rest/api/2/issue/{issue.id}" issue.update(fields=fields) self.assertEqual(issue.fields.labels, ["testLabel"]) @@ -395,6 +397,8 @@ def test_delete_with_proxy(self): issuetype=self.test_manager.CI_JIRA_ISSUE, ) key = issue.key + #This simulates when your Jira server is behind a proxy + #The self address returned will be different from the configured server issue.self = f"https://foo.bar/jira/rest/api/2/issue/{issue.id}" issue.delete() self.assertRaises(JIRAError, self.jira.issue, key) From 36618d5d7625e522e57e68c6b4055e96f1061218 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 22 Nov 2024 22:02:35 +0000 Subject: [PATCH 6/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/resources/test_issue.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/resources/test_issue.py b/tests/resources/test_issue.py index 6b36e6275..27d3d67cd 100644 --- a/tests/resources/test_issue.py +++ b/tests/resources/test_issue.py @@ -347,8 +347,8 @@ def test_update_label_with_proxy(self): labelarray = ["testLabel"] fields = {"labels": labelarray} - #This simulates when your Jira server is behind a proxy - #The self address returned will be different from the configured server + # This simulates when your Jira server is behind a proxy + # The self address returned will be different from the configured server issue.self = f"https://foo.bar/jira/rest/api/2/issue/{issue.id}" issue.update(fields=fields) self.assertEqual(issue.fields.labels, ["testLabel"]) @@ -397,8 +397,8 @@ def test_delete_with_proxy(self): issuetype=self.test_manager.CI_JIRA_ISSUE, ) key = issue.key - #This simulates when your Jira server is behind a proxy - #The self address returned will be different from the configured server + # This simulates when your Jira server is behind a proxy + # The self address returned will be different from the configured server issue.self = f"https://foo.bar/jira/rest/api/2/issue/{issue.id}" issue.delete() self.assertRaises(JIRAError, self.jira.issue, key)