Skip to content

Commit b2c75b2

Browse files
committed
Add integration tests for the Pulsar ARC job runner
These tests verify that the ARC endpoint URL and OIDC provider selection logic works correctly when queuing jobs. They do not test actual job execution, as that is covered by Pulsar's own tests.
1 parent 583a405 commit b2c75b2

File tree

3 files changed

+366
-32
lines changed

3 files changed

+366
-32
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"""Dynamic job rule for the Pulsar ARC (Advanced Resource Connector) job runner integration tests.
2+
3+
This file contains a dynamic job rule for the Pulsar ARC job runner integration tests in
4+
`test/integration/test_pulsar_arc.py`. The rule allows selecting a job destination based on a dynamic reference that can
5+
be read and updated during the tests using `test_pulsar_arc_get_job_destination()` and
6+
`test_pulsar_arc_set_job_destination()` respectively.
7+
"""
8+
9+
from typing import Optional
10+
11+
from galaxy.app import UniverseApplication
12+
from galaxy.jobs import JobMappingException # type: ignore[attr-defined]
13+
from galaxy.jobs import (
14+
JobDestination,
15+
)
16+
from galaxy.model import (
17+
Job,
18+
User as GalaxyUser,
19+
)
20+
from galaxy.tools import Tool as GalaxyTool
21+
22+
__all__ = ("test_pulsar_arc", "test_pulsar_arc_get_job_destination", "test_pulsar_arc_set_job_destination")
23+
24+
25+
test_pulsar_arc_job_destination_ref: list[JobDestination] = []
26+
27+
28+
def test_pulsar_arc_get_job_destination() -> Optional[JobDestination]:
29+
"""
30+
Return the last stored job destination (if any).
31+
"""
32+
return test_pulsar_arc_job_destination_ref[0] if test_pulsar_arc_job_destination_ref else None
33+
34+
35+
def test_pulsar_arc_set_job_destination(job_destination: JobDestination) -> None:
36+
"""
37+
Store a job destination, overwriting any previous one.
38+
"""
39+
test_pulsar_arc_job_destination_ref[:] = [job_destination]
40+
41+
42+
def test_pulsar_arc(app: UniverseApplication, job: Job, tool: GalaxyTool, user: GalaxyUser) -> JobDestination:
43+
"""
44+
Dynamic job rule that maps jobs to the stored job destination.
45+
"""
46+
job_destination = test_pulsar_arc_get_job_destination()
47+
if not job_destination:
48+
raise JobMappingException("No job destination set for dynamic job rule.")
49+
50+
return job_destination

test/integration/oidc/test_auth_oidc.py

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ class BaseKeycloakIntegrationTestCase(integration_util.IntegrationTestCase):
9393
backend_config_file: ClassVar[str]
9494
saved_oauthlib_insecure_transport: ClassVar[bool]
9595

96+
REGEX_KEYCLOAK_LOGIN_ACTION = re.compile(r"action=\"(.*)\"\s+")
97+
REGEX_GALAXY_CSRF_TOKEN = re.compile(r"session_csrf_token\": \"(.*)\"")
98+
9699
@classmethod
97100
def setUpClass(cls):
98101
# By default, the oidc callback must be done over a secure transport, so
@@ -158,40 +161,38 @@ def handle_galaxy_oidc_config_kwds(cls, config):
158161
def _get_interactor(self, api_key=None, allow_anonymous=False) -> "ApiTestInteractor":
159162
return super()._get_interactor(api_key=None, allow_anonymous=True)
160163

164+
def _login_via_keycloak(self, username, password, expected_codes=None, save_cookies=False, session=None):
165+
if expected_codes is None:
166+
expected_codes = [200, 404]
167+
session = session or requests.Session()
168+
response = session.get(f"{self.url}authnz/keycloak/login")
169+
provider_url = response.json()["redirect_uri"]
170+
response = session.get(provider_url, verify=False)
171+
matches = self.REGEX_KEYCLOAK_LOGIN_ACTION.search(response.text)
172+
assert matches
173+
auth_url = html.unescape(str(matches.groups(1)[0]))
174+
response = session.post(auth_url, data={"username": username, "password": password}, verify=False)
175+
assert response.status_code in expected_codes, response
176+
if save_cookies:
177+
self.galaxy_interactor.cookies = session.cookies
178+
return session, response
179+
180+
def _get_keycloak_access_token(
181+
self, client_id="gxyclient", username=KEYCLOAK_TEST_USERNAME, password=KEYCLOAK_TEST_PASSWORD, scopes=None
182+
):
183+
data = {
184+
"client_id": client_id,
185+
"client_secret": "dummyclientsecret",
186+
"grant_type": "password",
187+
"username": username,
188+
"password": password,
189+
"scope": scopes or [],
190+
}
191+
response = requests.post(f"{KEYCLOAK_URL}/protocol/openid-connect/token", data=data, verify=False)
192+
return response.json()["access_token"]
193+
161194

162195
class TestGalaxyOIDCLoginIntegration(AbstractTestCases.BaseKeycloakIntegrationTestCase):
163-
REGEX_KEYCLOAK_LOGIN_ACTION = re.compile(r"action=\"(.*)\"\s+")
164-
REGEX_GALAXY_CSRF_TOKEN = re.compile(r"session_csrf_token\": \"(.*)\"")
165-
166-
def _login_via_keycloak(self, username, password, expected_codes=None, save_cookies=False, session=None):
167-
if expected_codes is None:
168-
expected_codes = [200, 404]
169-
session = session or requests.Session()
170-
response = session.get(f"{self.url}authnz/keycloak/login")
171-
provider_url = response.json()["redirect_uri"]
172-
response = session.get(provider_url, verify=False)
173-
matches = self.REGEX_KEYCLOAK_LOGIN_ACTION.search(response.text)
174-
assert matches
175-
auth_url = html.unescape(str(matches.groups(1)[0]))
176-
response = session.post(auth_url, data={"username": username, "password": password}, verify=False)
177-
assert response.status_code in expected_codes, response
178-
if save_cookies:
179-
self.galaxy_interactor.cookies = session.cookies
180-
return session, response
181-
182-
def _get_keycloak_access_token(
183-
self, client_id="gxyclient", username=KEYCLOAK_TEST_USERNAME, password=KEYCLOAK_TEST_PASSWORD, scopes=None
184-
):
185-
data = {
186-
"client_id": client_id,
187-
"client_secret": "dummyclientsecret",
188-
"grant_type": "password",
189-
"username": username,
190-
"password": password,
191-
"scope": scopes or [],
192-
}
193-
response = requests.post(f"{KEYCLOAK_URL}/protocol/openid-connect/token", data=data, verify=False)
194-
return response.json()["access_token"]
195196

196197
def test_oidc_login_new_user(self):
197198
_, response = self._login_via_keycloak(KEYCLOAK_TEST_USERNAME, KEYCLOAK_TEST_PASSWORD, save_cookies=True)

0 commit comments

Comments
 (0)