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

feat: Basic Windows support #35

Merged
merged 1 commit into from
Nov 8, 2023
Merged

Conversation

gmchale79
Copy link
Contributor

@gmchale79 gmchale79 commented Sep 18, 2023

What was the problem/requirement? (What/Why)

The DLC worker agent did not start on Windows, and numerous unit tests did not pass.

What was the solution? (How)

Numerous small changes related to removing NotImplemented exceptions, using more appropriate file paths etc.

User impersonation is not intended to work in this branch at this time, and several of the changes relate to ensuring tests pass when impersonation is not used.

As of 11/6/23 this is targeted at a feature branch, not mainline.

What is the impact of this change?

The worker agent starts, then receives and executes jobs on Windows.

How was this change tested?

Submitting jobs to gamma and ensuring they are picked up and executed by a Windows worker.

Was this change documented?

No currently.

Is this a breaking change?

It is not intended to be.

@jusiskin jusiskin added the enhancement New feature or request label Sep 18, 2023
Copy link
Contributor

@jusiskin jusiskin left a comment

Choose a reason for hiding this comment

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

Thank you for taking on the first pass of adding Windows support to the worker agent. This is a great first step towards an important feature. It seems like this is a partial implementation, which is fine.

The biggest blocker to shipping this code is setting expectations for those using it. Specifically, if we don't yet support isolation of OS users then that limitation and its associated risks need to be made clear

EDIT: Sorry, I missed that this was targeting the feature_windows branch. I presume that we will have OS user impersonation when we merge this feature branch into mainline. On that basis, we can disregard my concern above.

src/deadline_worker_agent/aws_credentials/aws_configs.py Outdated Show resolved Hide resolved
src/deadline_worker_agent/startup/config_file.py Outdated Show resolved Hide resolved
test/unit/conftest.py Outdated Show resolved Hide resolved
test/unit/scheduler/test_session_cleanup.py Outdated Show resolved Hide resolved
test/unit/scheduler/test_session_cleanup.py Outdated Show resolved Hide resolved
test/unit/startup/test_config.py Outdated Show resolved Hide resolved
test/unit/test_worker.py Outdated Show resolved Hide resolved
src/deadline_worker_agent/aws_credentials/aws_configs.py Outdated Show resolved Hide resolved
src/deadline_worker_agent/aws_credentials/aws_configs.py Outdated Show resolved Hide resolved
src/deadline_worker_agent/scheduler/scheduler.py Outdated Show resolved Hide resolved
src/deadline_worker_agent/startup/config_file.py Outdated Show resolved Hide resolved
src/deadline_worker_agent/startup/settings.py Outdated Show resolved Hide resolved
src/deadline_worker_agent/worker.py Outdated Show resolved Hide resolved
test/unit/aws_credentials/test_aws_configs.py Show resolved Hide resolved
@gmchale79 gmchale79 force-pushed the gmchale79/windows_dev branch from b0b3bad to 815735f Compare September 20, 2023 23:26
pyproject.toml Outdated Show resolved Hide resolved
@gmchale79 gmchale79 force-pushed the gmchale79/windows_dev branch 2 times, most recently from f4a4ae4 to e5862ae Compare September 27, 2023 22:37
@gmchale79 gmchale79 changed the base branch from feature_windows to mainline September 27, 2023 22:40
@gmchale79 gmchale79 marked this pull request as ready for review September 27, 2023 22:41
@gmchale79 gmchale79 requested a review from a team as a code owner September 27, 2023 22:41
@gmchale79 gmchale79 changed the title wip: First pass Windows support feat: Basic Windows support Sep 27, 2023
@gmchale79 gmchale79 force-pushed the gmchale79/windows_dev branch 2 times, most recently from 2316e7a to e6a880f Compare September 28, 2023 23:34
@gmchale79 gmchale79 force-pushed the gmchale79/windows_dev branch 2 times, most recently from 771280c to 7bf56bf Compare October 2, 2023 18:49
@gmchale79 gmchale79 requested a review from ddneilson October 2, 2023 19:02
src/deadline_worker_agent/set_windows_permissions.py Outdated Show resolved Hide resolved
src/deadline_worker_agent/worker.py Outdated Show resolved Hide resolved
test/unit/aws_credentials/test_aws_configs.py Show resolved Hide resolved
@@ -821,9 +853,10 @@ def test_uses_worker_settings(
assert config.capabilities is mock_worker_settings.capabilities
assert config.impersonation.inactive == (not mock_worker_settings.impersonation)
if expected_config_posix_job_user:
posix_user: PosixSessionUser = request.getfixturevalue(expected_config_posix_job_user)
Copy link
Contributor

Choose a reason for hiding this comment

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

I was somewhat confused by this change. Could we instead switch to obtaining the os_user fixture from normally (as an argument to the test method) and remove the usage of expected_config_posix_job_user entirely?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the only approach I found that worked for using a fixture in a parameterize call, but I'm pretty much a python novice so I'll keep experimenting for a little longer.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because it's a parameterized test, I can't find a cleaner way to get at the fixture as of now. I have added a TODO to revisit whether this can be simplified when we add impersonation on Windows (which is in progress right now).

Copy link
Contributor

Choose a reason for hiding this comment

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

Did it not work to add the os_user fixture as an argument to the test function along-side the parameterized arguments?

test/unit/conftest.py Outdated Show resolved Hide resolved
test/unit/scheduler/test_scheduler.py Show resolved Hide resolved
test/unit/scheduler/test_session_cleanup.py Outdated Show resolved Hide resolved
test/unit/test_set_windows_permissions.py Outdated Show resolved Hide resolved
@gmchale79 gmchale79 force-pushed the gmchale79/windows_dev branch 3 times, most recently from 7fc8386 to f67f6ae Compare October 11, 2023 21:19
@gmchale79 gmchale79 requested a review from jusiskin October 11, 2023 21:35
ddneilson
ddneilson previously approved these changes Oct 12, 2023
@@ -28,8 +29,12 @@ def _run_cmd_as(*, user: PosixSessionUser, cmd: list[str]) -> None:

def _setup_parent_dir(*, dir_path: Path, owner: SessionUser | None = None) -> None:
if owner is None:
create_perms: int = stat.S_IRWXU
dir_path.mkdir(mode=create_perms, exist_ok=True)
if os.name == "posix":
Copy link
Contributor

Choose a reason for hiding this comment

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

should there be a try catch here for the possible CalledProcessError?

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

@@ -20,6 +21,7 @@
DEFAULT_CONFIG_PATH: dict[str, Path] = {
"darwin": Path("/etc/amazon/deadline/worker.toml"),
"linux": Path("/etc/amazon/deadline/worker.toml"),
"win32": Path(os.path.expandvars(r"%PROGRAMDATA%/Amazon/Deadline/Config/worker.toml")),
Copy link
Contributor

Choose a reason for hiding this comment

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

Did you look at how to avoid relying on an environment variable for this path? A brief look suggests SHGetFolderPath is what to use, but I don't see PROGRAMDATA in the enum list.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why?

Copy link
Contributor

Choose a reason for hiding this comment

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

Because users can change the environment variables, but not the system API calls. Reducing reliance on env variables makes things more robust.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point! :)

But without meaning to be overly argumentative, isn't there a counter argument that a user may change an env var for good reason and would want our code to respect their change?

src/deadline_worker_agent/worker.py Show resolved Hide resolved
@gmchale79 gmchale79 force-pushed the gmchale79/windows_dev branch from ade5a04 to cf7bc6f Compare October 19, 2023 00:01
@gmchale79 gmchale79 requested review from ddneilson and mwiebe October 19, 2023 23:48
@gmchale79 gmchale79 force-pushed the gmchale79/windows_dev branch from cf7bc6f to fc3d58f Compare October 21, 2023 22:40
@gmchale79 gmchale79 changed the base branch from mainline to feature_windows November 2, 2023 17:58
@gmchale79 gmchale79 dismissed ddneilson’s stale review November 2, 2023 17:58

The base branch was changed.

Signed-off-by: Graeme McHale <[email protected]>
@gmchale79 gmchale79 force-pushed the gmchale79/windows_dev branch from fc3d58f to f4b0db6 Compare November 6, 2023 17:35
@gmchale79 gmchale79 requested review from Honglichenn, anandgo1 and mwiebe and removed request for mwiebe November 6, 2023 17:40

subprocess.run(
[
"icacls",
Copy link
Contributor

Choose a reason for hiding this comment

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

In the job attachments code, they were able to remove the subprocess calls to icacls by using pywin32. IMO we should do the same thing here.

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, I agree. Consistency would be nice, as would skipping the overhead of using subprocess.

For the record, the reason that I went with this approach in the first place is that I figured Windows IT Admin curious about our code what find it easier to interpret icacls calls and may be unfamiliar with pywin32.

@@ -20,6 +21,7 @@
DEFAULT_CONFIG_PATH: dict[str, Path] = {
"darwin": Path("/etc/amazon/deadline/worker.toml"),
"linux": Path("/etc/amazon/deadline/worker.toml"),
"win32": Path(os.path.expandvars(r"%PROGRAMDATA%/Amazon/Deadline/Config/worker.toml")),
Copy link
Contributor

Choose a reason for hiding this comment

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

Because users can change the environment variables, but not the system API calls. Reducing reliance on env variables makes things more robust.

Copy link
Contributor

@jusiskin jusiskin left a comment

Choose a reason for hiding this comment

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

This looks good to me.

A few small remaining nit-picks but they are not critical for merging

Comment on lines +47 to +49
@pytest.fixture
def set_windows_permissions(self) -> MagicMock:
return MagicMock()
Copy link
Contributor

Choose a reason for hiding this comment

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

This fixture does not appear to be used. It looks like you may have intended to use this on lines 63-68, but ended up using a local mock instead.

@@ -821,9 +853,10 @@ def test_uses_worker_settings(
assert config.capabilities is mock_worker_settings.capabilities
assert config.impersonation.inactive == (not mock_worker_settings.impersonation)
if expected_config_posix_job_user:
posix_user: PosixSessionUser = request.getfixturevalue(expected_config_posix_job_user)
Copy link
Contributor

Choose a reason for hiding this comment

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

Did it not work to add the os_user fixture as an argument to the test function along-side the parameterized arguments?

from deadline_worker_agent.set_windows_permissions import set_user_restricted_path_permissions


class TestSetWindowsPermissions(unittest.TestCase):
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Since we use pytest, we don't need to derive from unittest.TestCase, although pytest allows this for compatibility to make migrating to pytest easier.

Suggested change
class TestSetWindowsPermissions(unittest.TestCase):
class TestSetWindowsPermissions:

@gmchale79 gmchale79 merged commit a59e2b9 into feature_windows Nov 8, 2023
2 checks passed
@ddneilson ddneilson added the security Pull requests that could impact security label Jan 30, 2024
jusiskin added a commit to jusiskin/deadline-cloud-worker-agent that referenced this pull request Sep 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request security Pull requests that could impact security
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants