-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DOM-35464 convert passed in hardware tier name to hardware tier id #117
DOM-35464 convert passed in hardware tier name to hardware tier id #117
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the quick response on this. I think we need to get away from the hardware tier name entirely, however, for reasons noted.
Also, note that there have been recent efforts to add unit tests for any new changes to the library. My gut is that some testing could be added here:
https://github.com/dominodatalab/python-domino/blob/master/tests/test_jobs.py
domino/domino.py
Outdated
@@ -818,6 +819,12 @@ def hardware_tiers_list(self): | |||
url = self._routes.hardware_tiers_list(self._project_id) | |||
return self._get(url) | |||
|
|||
def get_hardware_tier_id_from_name(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK, hardware tier names are not required to be unique, so this will be an issue. I think this is why overriding by name was probably a mistake in the first place.
It's unfortunate, but I think to address this issue, we really need to change the interface of job_start()
to take hardware ID from the start. At least we know that no customer is using this as is (because it's totally broken, and no one has reported a bug before now).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An alternative to changing the interface would be to accept the name as exists right now, get the ID like you proposed, but throw an error in the event that more than one HWT with the same name is found.
I'm honestly not sure which is the better option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps similar to on_demand_spark_cluster_properties
, I can document HWT name as deprecated and try the best effort approach and fail if multiple HWT with the same name are found. This way if any customer is using it but not noticing it doesn't work, their code will at least still run.
I can also add a new optional property for HWT id that is recommended to be used instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dknupp Does this approach seem ok?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ddl-awroblicky -- ah, I saw this was still marked as a draft, so I didn't know if there were more commits coming. I'll try to have a look later this afternoon or tomorrow.
@ddl-awroblicky -- thanks for adding the unit tests! I'll try to review this today. |
domino/domino.py
Outdated
@@ -425,12 +432,13 @@ def validate_is_external_volume_mounts_supported(): | |||
"masterHardwareTierId": master_hardware_tier_id | |||
} | |||
|
|||
resolved_hardware_tier_id = hardware_tier_id if hardware_tier_id is not None else self.get_hardware_tier_id_from_name(hardware_tier_name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You might be able to shorten this line with...
resolved_hardware_tier_id = hardware_tier_id if hardware_tier_id is not None else self.get_hardware_tier_id_from_name(hardware_tier_name) | |
resolved_hardware_tier_id = hardware_tier_id or self.get_hardware_tier_id_from_name(hardware_tier_name) |
domino/routes.py
Outdated
@@ -150,6 +150,12 @@ def app_get(self, app_id): | |||
return f'{self.host}/v4/modelProducts/{app_id}' | |||
|
|||
# Hardware Tier URLs | |||
def hardware_tier_create(self, hardware_tier_id, hardware_tier_name, node_pool): | |||
return self.host + f'/admin/hwtiers/insert' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can admin endpoints only be called by admin users? I don't honestly know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes that should be the case
if not it is a bug
tests/test_hardware_tiers.py
Outdated
""" | ||
Confirm that the python-domino client can create a new project. | ||
""" | ||
new_project_name = f"project-{str(uuid.uuid4())}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test is creating a project, not a hardware tier. Maybe a copy/paste error?
tests/test_hardware_tiers.py
Outdated
default_domino_client.project_archive(new_project_name) | ||
|
||
@pytest.mark.skipif(not domino_is_reachable(), reason="No access to a live Domino deployment") | ||
def test_archiving_non_existent_hardware_tier_raises_appropriate_error(dummy_hostname, requests_mock): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly, this test still seems to be archiving a project, not a hardware tier.
tests/test_jobs.py
Outdated
hardware_tiers = default_domino_client.hardware_tiers_list(created_project['id']) | ||
non_default_hardware_tiers = (hardware_tier["isDefault"] == False for hardware_tier in hardware_tiers) | ||
|
||
if len(non_default_hardware_tiers) > 0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm surprised len()
isn't throwing an exception here, something like...
>>> num_generator = (n for n in [1,2,3])
>>> len(num_generator)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'generator' has no len()
tests/test_jobs.py
Outdated
created_project = next((p for p in project_list if p['name'] == new_project_name), None) | ||
|
||
hardware_tiers = default_domino_client.hardware_tiers_list(created_project['id']) | ||
non_default_hardware_tiers = (hardware_tier["isDefault"] == False for hardware_tier in hardware_tiers) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test ran and passed? The way I read the current line, non_default_hardware_tiers
is being assigned a python generator that will produce a series of Boolean values. It looks like you wanted a list comprehension instead, something like...
non_default_hardware_tiers = (hardware_tier["isDefault"] == False for hardware_tier in hardware_tiers) | |
non_default_hardware_tiers = [hwt for hwt in hardware_tiers if not hwt["isDefault"]] |
5cb68dd
to
69ddbfc
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a test regression here. On master, if I run the tests which do not require a live host (i.e., pure unit test), they pass.
(venv) /path/to/dominodatalab/python-domino(master|…) % pytest -sv tests/test_jobs.py
[...]
tests/test_jobs.py::test_job_status_completes_with_default_params PASSED
tests/test_jobs.py::test_job_status_ignores_RequestException_and_times_out PASSED
tests/test_jobs.py::test_job_status_without_ignoring_exceptions PASSED
However, if I checkout your branch and run them, they fail.
(venv) /path/to/dominodatalab/python-domino(fix_hardware_tier_name_override↑1|…) % pytest -sv tests/test_jobs.py
[...]
tests/test_jobs.py::test_job_status_completes_with_default_params FAILED
tests/test_jobs.py::test_job_status_ignores_RequestException_and_times_out FAILED
tests/test_jobs.py::test_job_status_without_ignoring_exceptions FAILED
I'm trying to dig into why this is happening.
In the meantime, here are some other minor changes that need to be made.
job_status = default_domino_client.job_start_blocking(command="main.py", hardware_tier_name=override_hardware_tier_name) | ||
assert job_status['statuses']['isCompleted'] is True | ||
job_red = default_domino_client.job_runtime_execution_details(job_status['id']) | ||
assert job_red["hardwareTier"] == override_hardware_tier_name | ||
|
||
@pytest.mark.skipif(not domino_is_reachable(), reason="No access to a live Domino deployment") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PEP-8 requires 2 lines between module-level functions.
@pytest.mark.skipif(not domino_is_reachable(), reason="No access to a live Domino deployment") | |
@pytest.mark.skipif(not domino_is_reachable(), reason="No access to a live Domino deployment") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ddl-awroblicky can you update the CHANGELOG.md
?
job_red = default_domino_client.job_runtime_execution_details(job_status['id']) | ||
assert job_red["hardwareTierId"] == override_hardware_tier_id | ||
|
||
# deprecated but ensuring it still works for now |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PEP-8 requires 2 lines between module-level functions.
# deprecated but ensuring it still works for now | |
# deprecated but ensuring it still works for now |
tests/test_jobs.py
Outdated
if len(list(non_default_hardware_tiers)) > 0: | ||
override_hardware_tier_name = non_default_hardware_tiers[0]["hardwareTier"]["name"] | ||
job_status = default_domino_client.job_start_blocking(command="main.py", hardware_tier_name=override_hardware_tier_name) | ||
assert job_status['statuses']['isCompleted'] is True | ||
job_red = default_domino_client.job_runtime_execution_details(job_status['id']) | ||
assert job_red["hardwareTier"] == override_hardware_tier_name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way this is written, it leaves open the possibility of a falsely passing test. If len(non_default_hardware_tiers) == 0
, then the actual test never runs -- but it will still appear to be "passing." Reverse the logic and xfail()
if the test can't run.
if len(list(non_default_hardware_tiers)) > 0: | |
override_hardware_tier_name = non_default_hardware_tiers[0]["hardwareTier"]["name"] | |
job_status = default_domino_client.job_start_blocking(command="main.py", hardware_tier_name=override_hardware_tier_name) | |
assert job_status['statuses']['isCompleted'] is True | |
job_red = default_domino_client.job_runtime_execution_details(job_status['id']) | |
assert job_red["hardwareTier"] == override_hardware_tier_name | |
if len(list(non_default_hardware_tiers)) > 0: | |
pytest.xfail("No non-default hardware tiers found: cannot run test") | |
override_hardware_tier_name = non_default_hardware_tiers[0]["hardwareTier"]["name"] | |
job_status = default_domino_client.job_start_blocking(command="main.py", | |
hardware_tier_name=override_hardware_tier_name) | |
assert job_status['statuses']['isCompleted'] is True | |
job_red = default_domino_client.job_runtime_execution_details(job_status['id']) | |
assert job_red["hardwareTier"] == override_hardware_tier_name |
tests/test_jobs.py
Outdated
""" | ||
hardware_tiers = default_domino_client.hardware_tiers_list() | ||
non_default_hardware_tiers = [hwt for hwt in hardware_tiers if not hwt["hardwareTier"]["isDefault"]] | ||
if len(list(non_default_hardware_tiers)) > 0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should already be a list, so the call to list()
here is redundant.
tests/test_jobs.py
Outdated
""" | ||
hardware_tiers = default_domino_client.hardware_tiers_list() | ||
non_default_hardware_tiers = [hwt for hwt in hardware_tiers if not hwt["hardwareTier"]["isDefault"]] | ||
if len(list(non_default_hardware_tiers)) > 0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should already be a list, so no need to call list()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @ddl-awroblicky!
@ddl-alexpanin -- still needs code owner approval. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, please update CHANGELOG.md and can merge then.
…ecated and only use as fallback if id is provided
Co-authored-by: David Knupp <dknupp@users.noreply.github.com>
Co-authored-by: David Knupp <dknupp@users.noreply.github.com>
920b8f2
to
b7160d5
Compare
still working on adding tests