|
9 | 9 | import random |
10 | 10 | import time |
11 | 11 | import unittest |
| 12 | +from urllib.parse import urlparse, parse_qs |
12 | 13 |
|
13 | 14 | from azure.cli.testsdk.scenario_tests import AllowLargeResponse, live_only |
14 | 15 | from azure.cli.testsdk import ScenarioTest |
@@ -205,38 +206,19 @@ def test_submit(self): |
205 | 206 | self.cmd(f"az quantum workspace set -g {test_resource_group} -w {test_workspace_temp} -l {test_location}") |
206 | 207 |
|
207 | 208 | # Submit a job to Rigetti and look for SAS tokens in URIs in the output |
208 | | - results = self.cmd("az quantum job submit -t rigetti.sim.qvm --job-input-format rigetti.quil.v1 -t rigetti.sim.qvm --job-input-file src/quantum/azext_quantum/tests/latest/input_data/bell-state.quil --job-output-format rigetti.quil-results.v1 -o json").get_output_in_json() |
209 | | - self.assertNotIn("?sv=", results["containerUri"]) |
210 | | - self.assertNotIn("&sig=", results["containerUri"]) |
211 | | - |
212 | | - self.assertNotIn("?sv=", results["inputDataUri"]) |
213 | | - self.assertNotIn("&sig=", results["inputDataUri"]) |
214 | | - |
215 | | - self.assertNotIn("?sv=", results["outputDataUri"]) |
216 | | - self.assertNotIn("&sig=", results["outputDataUri"]) |
| 209 | + results = self.cmd("az quantum job submit -t rigetti.sim.qvm --job-input-format rigetti.quil.v1 --job-input-file src/quantum/azext_quantum/tests/latest/input_data/bell-state.quil --job-output-format rigetti.quil-results.v1 -o json").get_output_in_json() |
| 210 | + self.assert_not_contains_standard_sas_params(results["containerUri"]) |
| 211 | + self.assert_not_contains_standard_sas_params(results["inputDataUri"]) |
| 212 | + self.assert_not_contains_standard_sas_params(results["outputDataUri"]) |
217 | 213 |
|
218 | 214 | job = self.cmd(f"az quantum job show -j {results['id']} -o json").get_output_in_json() |
219 | | - |
220 | | - self.assertIn("?sv=", job["containerUri"]) |
221 | | - self.assertIn("&st=", job["containerUri"]) |
222 | | - self.assertIn("&se=", job["containerUri"]) |
223 | | - self.assertIn("&sp=", job["containerUri"]) |
224 | | - self.assertIn("&sig=", job["containerUri"]) |
225 | | - |
226 | | - self.assertIn("?sv=", job["inputDataUri"]) |
227 | | - self.assertIn("&st=", job["inputDataUri"]) |
228 | | - self.assertIn("&se=", job["inputDataUri"]) |
229 | | - self.assertIn("&sp=", job["inputDataUri"]) |
230 | | - self.assertIn("&sig=", job["inputDataUri"]) |
231 | | - |
232 | | - self.assertIn("?sv=", job["outputDataUri"]) |
233 | | - self.assertIn("&st=", job["outputDataUri"]) |
234 | | - self.assertIn("&se=", job["outputDataUri"]) |
235 | | - self.assertIn("&sp=", job["outputDataUri"]) |
236 | | - self.assertIn("&sig=", job["outputDataUri"]) |
| 215 | + |
| 216 | + self.assert_contains_standard_sas_params(job["containerUri"]) |
| 217 | + self.assert_contains_standard_sas_params(job["inputDataUri"]) |
| 218 | + self.assert_contains_standard_sas_params(job["outputDataUri"]) |
237 | 219 |
|
238 | 220 | # Run a Quil pass-through job on Rigetti |
239 | | - results = self.cmd("az quantum run -t rigetti.sim.qvm --job-input-format rigetti.quil.v1 -t rigetti.sim.qvm --job-input-file src/quantum/azext_quantum/tests/latest/input_data/bell-state.quil --job-output-format rigetti.quil-results.v1 -o json").get_output_in_json() |
| 221 | + results = self.cmd("az quantum run -t rigetti.sim.qvm --job-input-format rigetti.quil.v1 --job-input-file src/quantum/azext_quantum/tests/latest/input_data/bell-state.quil --job-output-format rigetti.quil-results.v1 -o json").get_output_in_json() |
240 | 222 | self.assertIn("ro", results) |
241 | 223 |
|
242 | 224 | # Run an IonQ Circuit pass-through job on IonQ |
@@ -291,17 +273,34 @@ def test_submit_with_disabled_then_enabled_storage_key_access(self): |
291 | 273 | # Test that job submission works with disabled access keys on linked storage (/sasUri returns user delegation SAS) |
292 | 274 | results = self.cmd("az quantum job submit -t rigetti.sim.qvm --job-input-format rigetti.quil.v1 --job-input-file src/quantum/azext_quantum/tests/latest/input_data/bell-state.quil --job-output-format rigetti.quil-results.v1 -o json").get_output_in_json() |
293 | 275 | self.assertIn("id", results) |
294 | | - |
| 276 | + |
| 277 | + job = self.cmd(f"az quantum job show -j {results['id']} -o json").get_output_in_json() |
| 278 | + self.assert_contains_standard_sas_params(job["containerUri"]) |
| 279 | + self.assert_contains_standard_sas_params(job["inputDataUri"]) |
| 280 | + self.assert_contains_standard_sas_params(job["outputDataUri"]) |
| 281 | + self.assert_contains_user_delegation_sas_params(job["containerUri"]) |
| 282 | + self.assert_contains_user_delegation_sas_params(job["inputDataUri"]) |
| 283 | + self.assert_contains_user_delegation_sas_params(job["outputDataUri"]) |
| 284 | + |
295 | 285 | # Enable access keys on the storage account |
296 | 286 | updated = self.cmd(f"az storage account update -g {test_resource_group} -n {test_storage_temp} --allow-shared-key-access true -o json").get_output_in_json() |
297 | 287 | self.assertTrue(updated["allowSharedKeyAccess"], "Access keys should be enabled after update") |
298 | 288 |
|
299 | | - time.sleep(60) # wait for the cache to update |
| 289 | + time.sleep(300) # wait for the cache to update |
300 | 290 |
|
301 | 291 | # Test that job submission works with enabled access keys on linked storage (/sasUri returns container-scoped Service SAS) |
302 | 292 | results = self.cmd("az quantum job submit -t rigetti.sim.qvm --job-input-format rigetti.quil.v1 --job-input-file src/quantum/azext_quantum/tests/latest/input_data/bell-state.quil --job-output-format rigetti.quil-results.v1 -o json").get_output_in_json() |
303 | 293 | self.assertIn("id", results) |
304 | 294 |
|
| 295 | + job = self.cmd(f"az quantum job show -j {results['id']} -o json").get_output_in_json() |
| 296 | + self.assert_contains_standard_sas_params(job["containerUri"]) |
| 297 | + self.assert_contains_standard_sas_params(job["inputDataUri"]) |
| 298 | + self.assert_contains_standard_sas_params(job["outputDataUri"]) |
| 299 | + self.assert_not_contains_user_delegation_sas_params(job["containerUri"]) |
| 300 | + self.assert_not_contains_user_delegation_sas_params(job["inputDataUri"]) |
| 301 | + self.assert_not_contains_user_delegation_sas_params(job["outputDataUri"]) |
| 302 | + |
| 303 | + # Clean up |
305 | 304 | self.cmd(f'az quantum workspace delete -g {test_resource_group} -w {test_workspace_temp}') |
306 | 305 | self.cmd(f'az storage account delete -g {test_resource_group} -n {test_storage_temp} --yes') |
307 | 306 |
|
@@ -397,3 +396,43 @@ def test_job_list_param_formating(self): |
397 | 396 | assert False |
398 | 397 | except RequiredArgumentMissingError as e: |
399 | 398 | assert str(e) == ERROR_MSG_MISSING_ORDERBY_ARGUMENT |
| 399 | + |
| 400 | + def assert_contains_user_delegation_sas_params(self, uri: str): |
| 401 | + """Assert that the given URI contains user delegation SAS parameters.""" |
| 402 | + params = parse_qs(urlparse(uri).query) |
| 403 | + self.assertIn("skoid", params) # signed key object ID (service principal OID) |
| 404 | + self.assertIn("sktid", params) # signed key tenant ID |
| 405 | + self.assertIn("skt", params) # signed key start time |
| 406 | + self.assertIn("ske", params) # signed key expiry time |
| 407 | + self.assertIn("sks", params) # signed key service (b = Blob) |
| 408 | + self.assertIn("skv", params) # signed key version |
| 409 | + |
| 410 | + def assert_not_contains_user_delegation_sas_params(self, uri: str): |
| 411 | + """Assert that the given URI does not contain user delegation SAS parameters.""" |
| 412 | + params = parse_qs(urlparse(uri).query) |
| 413 | + self.assertNotIn("skoid", params) |
| 414 | + self.assertNotIn("sktid", params) |
| 415 | + self.assertNotIn("skt", params) |
| 416 | + self.assertNotIn("ske", params) |
| 417 | + self.assertNotIn("sks", params) |
| 418 | + self.assertNotIn("skv", params) |
| 419 | + |
| 420 | + def assert_contains_standard_sas_params(self, uri: str): |
| 421 | + """Assert that the given URI contains standard SAS parameters.""" |
| 422 | + params = parse_qs(urlparse(uri).query) |
| 423 | + self.assertIn("sv", params) # SAS version |
| 424 | + self.assertIn("st", params) # start time |
| 425 | + self.assertIn("se", params) # expiry time |
| 426 | + self.assertIn("sr", params) # signed resource (e.g. c = container) |
| 427 | + self.assertIn("sp", params) # permissions |
| 428 | + self.assertIn("sig", params) # signature |
| 429 | + |
| 430 | + def assert_not_contains_standard_sas_params(self, uri: str): |
| 431 | + """Assert that the given URI does not contain standard SAS parameters.""" |
| 432 | + params = parse_qs(urlparse(uri).query) |
| 433 | + self.assertNotIn("sv", params) |
| 434 | + self.assertNotIn("st", params) |
| 435 | + self.assertNotIn("se", params) |
| 436 | + self.assertNotIn("sr", params) |
| 437 | + self.assertNotIn("sp", params) |
| 438 | + self.assertNotIn("sig", params) |
0 commit comments