Skip to content
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

Conversation

ddl-awroblicky
Copy link
Contributor

@ddl-awroblicky ddl-awroblicky commented Jan 14, 2022

still working on adding tests

@ddl-awroblicky ddl-awroblicky requested a review from a team January 14, 2022 00:32
Copy link
Collaborator

@dknupp dknupp left a 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):
Copy link
Collaborator

@dknupp dknupp Jan 14, 2022

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).

Copy link
Collaborator

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.

Copy link
Contributor Author

@ddl-awroblicky ddl-awroblicky Jan 14, 2022

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.

Copy link
Contributor Author

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?

Copy link
Collaborator

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 ddl-awroblicky marked this pull request as draft January 14, 2022 01:01
@ddl-awroblicky ddl-awroblicky marked this pull request as ready for review January 24, 2022 23:07
@dknupp
Copy link
Collaborator

dknupp commented Jan 26, 2022

@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)
Copy link
Collaborator

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...

Suggested change
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'
Copy link
Collaborator

@dknupp dknupp Jan 27, 2022

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.

Copy link
Contributor Author

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

"""
Confirm that the python-domino client can create a new project.
"""
new_project_name = f"project-{str(uuid.uuid4())}"
Copy link
Collaborator

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?

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):
Copy link
Collaborator

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.

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:
Copy link
Collaborator

@dknupp dknupp Jan 27, 2022

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()

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)
Copy link
Collaborator

@dknupp dknupp Jan 27, 2022

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...

Suggested change
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"]]

Copy link
Collaborator

@dknupp dknupp left a 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.

tests/test_jobs.py Outdated Show resolved Hide resolved
tests/test_jobs.py Show resolved Hide resolved
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")
Copy link
Collaborator

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.

Suggested change
@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")

Copy link
Contributor

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
Copy link
Collaborator

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.

Suggested change
# deprecated but ensuring it still works for now
# deprecated but ensuring it still works for now

Comment on lines 114 to 119
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
Copy link
Collaborator

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.

Suggested change
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

"""
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:
Copy link
Collaborator

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.

"""
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:
Copy link
Collaborator

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().

Copy link
Collaborator

@dknupp dknupp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ddl-awroblicky!

@dknupp
Copy link
Collaborator

dknupp commented Mar 14, 2022

@ddl-alexpanin -- still needs code owner approval.

Copy link
Contributor

@ddl-alexpanin ddl-alexpanin left a 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.

@ddl-awroblicky ddl-awroblicky force-pushed the fix_hardware_tier_name_override branch from 920b8f2 to b7160d5 Compare March 14, 2022 22:59
@ddl-alexpanin ddl-alexpanin merged commit 5e5ad64 into dominodatalab:master Mar 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants