Skip to content

Commit c6c4e5b

Browse files
committed
OAuth 2.0 Password Grant authentication
1 parent a2dadcc commit c6c4e5b

4 files changed

Lines changed: 48 additions & 56 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Changelog
22

33
## [Unreleased]
4+
### Added
5+
- OAuth 2.0 Password Grant authentication, by @HardNorth
46
### Changed
57
- Client version updated to [5.6.6](https://github.com/reportportal/client-Python/releases/tag/5.6.6), by @HardNorth
68
### Fixed

pytest_reportportal/config.py

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
class AgentConfig:
3333
"""Storage for the RP agent initialization attributes."""
3434

35+
rp_enabled: bool
3536
rp_client_type: Optional[ClientType]
3637
rp_rerun: Optional[bool]
3738
pconfig: Config
@@ -61,8 +62,18 @@ class AgentConfig:
6162
rp_project: str
6263
rp_rerun_of: Optional[str]
6364
rp_api_retries: int
64-
rp_skip_connection_test: bool
65-
rp_api_key: str
65+
66+
# API key auth parameter
67+
rp_api_key: Optional[str]
68+
69+
# OAuth 2.0 parameters
70+
rp_oauth_uri: Optional[str]
71+
rp_oauth_username: Optional[str]
72+
rp_oauth_password: Optional[str]
73+
rp_oauth_client_id: Optional[str]
74+
rp_oauth_client_secret: Optional[str]
75+
rp_oauth_scope: Optional[str]
76+
6677
rp_verify_ssl: Union[bool, str]
6778
rp_launch_timeout: int
6879
rp_launch_uuid_print: bool
@@ -72,6 +83,7 @@ class AgentConfig:
7283

7384
def __init__(self, pytest_config: Config) -> None:
7485
"""Initialize required attributes."""
86+
self.rp_enabled = to_bool(self.find_option(pytest_config, "rp_enabled", True))
7587
self.rp_rerun = pytest_config.option.rp_rerun or pytest_config.getini("rp_rerun")
7688
self.rp_endpoint = getenv("RP_ENDPOINT") or self.find_option(pytest_config, "rp_endpoint")
7789
self.rp_hierarchy_code = to_bool(self.find_option(pytest_config, "rp_hierarchy_code"))
@@ -112,7 +124,6 @@ def __init__(self, pytest_config: Config) -> None:
112124
self.rp_parent_item_id = self.find_option(pytest_config, "rp_parent_item_id")
113125
self.rp_project = self.find_option(pytest_config, "rp_project")
114126
self.rp_rerun_of = self.find_option(pytest_config, "rp_rerun_of")
115-
self.rp_skip_connection_test = to_bool(self.find_option(pytest_config, "rp_skip_connection_test"))
116127

117128
rp_api_retries_str = self.find_option(pytest_config, "rp_api_retries")
118129
rp_api_retries = rp_api_retries_str and int(rp_api_retries_str)
@@ -134,6 +145,7 @@ def __init__(self, pytest_config: Config) -> None:
134145
else:
135146
self.rp_api_retries = 0
136147

148+
# API key auth parameter
137149
self.rp_api_key = getenv("RP_API_KEY") or self.find_option(pytest_config, "rp_api_key")
138150
if not self.rp_api_key:
139151
self.rp_api_key = getenv("RP_UUID") or self.find_option(pytest_config, "rp_uuid")
@@ -146,15 +158,14 @@ def __init__(self, pytest_config: Config) -> None:
146158
DeprecationWarning,
147159
2,
148160
)
149-
else:
150-
warnings.warn(
151-
"Argument `rp_api_key` is `None` or empty string, "
152-
"that is not supposed to happen because Report "
153-
"Portal is usually requires an authorization key. "
154-
"Please check your configuration.",
155-
RuntimeWarning,
156-
2,
157-
)
161+
162+
# OAuth 2.0 parameters
163+
self.rp_oauth_uri = self.find_option(pytest_config, "rp_oauth_uri")
164+
self.rp_oauth_username = self.find_option(pytest_config, "rp_oauth_username")
165+
self.rp_oauth_password = self.find_option(pytest_config, "rp_oauth_password")
166+
self.rp_oauth_client_id = self.find_option(pytest_config, "rp_oauth_client_id")
167+
self.rp_oauth_client_secret = self.find_option(pytest_config, "rp_oauth_client_secret")
168+
self.rp_oauth_scope = self.find_option(pytest_config, "rp_oauth_scope")
158169

159170
rp_verify_ssl = self.find_option(pytest_config, "rp_verify_ssl", True)
160171
try:

pytest_reportportal/plugin.py

Lines changed: 16 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import pytest
2525

2626
# noinspection PyPackageRequirements
27-
import requests
2827
from pytest import Item, Session
2928
from reportportal_client import RP, RPLogHandler
3029
from reportportal_client.errors import ResponseError
@@ -48,13 +47,6 @@
4847

4948
LOGGER: Logger = logging.getLogger(__name__)
5049

51-
MANDATORY_PARAMETER_MISSED_PATTERN: str = (
52-
"One of the following mandatory parameters is unset: "
53-
+ "rp_project: {}, "
54-
+ "rp_endpoint: {}, "
55-
+ "rp_api_key: {}"
56-
)
57-
5850
FAILED_LAUNCH_WAIT: str = (
5951
"Failed to initialize reportportal-client service. "
6052
+ "Waiting for Launch start timed out. "
@@ -182,25 +174,6 @@ def register_markers(config) -> None:
182174
config.addinivalue_line("markers", "name(name): report the test case with a custom Name.")
183175

184176

185-
def check_connection(agent_config: AgentConfig):
186-
"""Check connection to RP using provided options.
187-
188-
If connection is successful returns True either False.
189-
:param agent_config: Instance of the AgentConfig class
190-
:return True on successful connection check, either False
191-
"""
192-
url = "{0}/api/v1/project/{1}".format(agent_config.rp_endpoint, agent_config.rp_project)
193-
headers = {"Authorization": "bearer {0}".format(agent_config.rp_api_key)}
194-
try:
195-
resp = requests.get(url, headers=headers, verify=agent_config.rp_verify_ssl)
196-
resp.raise_for_status()
197-
return True
198-
except requests.exceptions.RequestException as exc:
199-
LOGGER.exception(exc)
200-
LOGGER.error("Unable to connect to Report Portal, the launch won't be reported")
201-
return False
202-
203-
204177
# no 'config' type for backward compatibility for older pytest versions
205178
# noinspection PyProtectedMember
206179
def pytest_configure(config) -> None:
@@ -210,30 +183,17 @@ def pytest_configure(config) -> None:
210183
"""
211184
register_markers(config)
212185

186+
agent_config = AgentConfig(config)
187+
213188
config._rp_enabled = not (
214189
config.getoption("--collect-only", default=False)
215190
or config.getoption("--setup-plan", default=False)
216-
or not config.option.rp_enabled
191+
or not agent_config.rp_enabled
217192
)
218193
if not config._rp_enabled:
219-
return
220-
221-
agent_config = AgentConfig(config)
222-
223-
cond = (agent_config.rp_project, agent_config.rp_endpoint, agent_config.rp_api_key)
224-
config._rp_enabled = all(cond)
225-
if not config._rp_enabled:
226-
LOGGER.debug(MANDATORY_PARAMETER_MISSED_PATTERN.format(*cond))
227194
LOGGER.debug("Disabling reporting to RP.")
228195
return
229196

230-
if not agent_config.rp_skip_connection_test:
231-
config._rp_enabled = check_connection(agent_config)
232-
233-
if not config._rp_enabled:
234-
LOGGER.debug("Failed to establish connection with RP. " "Disabling reporting.")
235-
return
236-
237197
config._reporter_config = agent_config
238198

239199
if is_control(config):
@@ -612,6 +572,19 @@ def add_shared_option(name, help_str, default=None, action="store"):
612572
name="rp_launch_uuid_print_output",
613573
help_str="Launch UUID print output. Default `stdout`. Possible values: [stderr, stdout]",
614574
)
575+
add_shared_option(
576+
name="rp_enabled",
577+
help_str="Enable reportportal plugin",
578+
default=True,
579+
)
580+
581+
# OAuth 2.0 parameters
582+
parser.addini("rp_oauth_uri", type="args", help="OAuth 2.0 token endpoint URL for password grant authentication")
583+
parser.addini("rp_oauth_username", type="args", help="OAuth 2.0 username for password grant authentication")
584+
parser.addini("rp_oauth_password", type="args", help="OAuth 2.0 password for password grant authentication")
585+
parser.addini("rp_oauth_client_id", type="args", help="OAuth 2.0 client identifier")
586+
parser.addini("rp_oauth_client_secret", type="args", help="OAuth 2.0 client secret")
587+
parser.addini("rp_oauth_scope", type="args", help="OAuth 2.0 access token scope")
615588

616589
parser.addini("rp_launch_attributes", type="args", help="Launch attributes, i.e Performance Regression")
617590
parser.addini("rp_tests_attributes", type="args", help="Attributes for all tests items, e.g. Smoke")
@@ -669,7 +642,6 @@ def add_shared_option(name, help_str, default=None, action="store"):
669642
parser.addini("rp_issue_id_marks", type="bool", default=True, help="Add tag with issue id to the test")
670643
parser.addini("retries", default="0", help="Deprecated: use `rp_api_retries` instead")
671644
parser.addini("rp_api_retries", default="0", help="Amount of retries for performing REST calls to RP server")
672-
parser.addini("rp_skip_connection_test", default=False, type="bool", help="Skip Report Portal connection test")
673645
parser.addini(
674646
"rp_launch_timeout",
675647
default=86400,

pytest_reportportal/service.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,6 +1398,13 @@ def start(self) -> None:
13981398
print_output=self._config.rp_launch_uuid_print_output,
13991399
http_timeout=self._config.rp_http_timeout,
14001400
mode=self._config.rp_mode,
1401+
# OAuth 2.0 parameters
1402+
oauth_uri=self._config.rp_oauth_uri,
1403+
oauth_username=self._config.rp_oauth_username,
1404+
oauth_password=self._config.rp_oauth_password,
1405+
oauth_client_id=self._config.rp_oauth_client_id,
1406+
oauth_client_secret=self._config.rp_oauth_client_secret,
1407+
oauth_scope=self._config.rp_oauth_scope,
14011408
)
14021409
if hasattr(self.rp, "get_project_settings"):
14031410
self.project_settings = self.rp.get_project_settings()

0 commit comments

Comments
 (0)