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

Implement xattr support on Windows #800

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open

Conversation

NickETH
Copy link

@NickETH NickETH commented Apr 20, 2022

Implementing xattr support on Windows by gluing ETAG to File with ADS (alternate data stream).
Changing the config file loacation to %APPDATA%, instead of %LOCALAPPDATA%. This change is not strictly necessary, but would be good policy.

@NickETH NickETH marked this pull request as ready for review April 21, 2022 09:43
@nmcspadden
Copy link
Contributor

This seems reasonable, but can you please provide some output from AutoPkg on both macOS and Windows to show that this actually works as intended? I'd like to see what the relevant output is, where the data is stored on Windows, and how it tracks etags.

@@ -806,6 +807,9 @@ def repo_delete(argv):
recipe_search_dirs.remove(repo_path)
# now remove the repo files
try:
if is_windows():
# we need to remove readonly, hidden and system bits
os.system("attrib.exe -r -h -s " + repo_path + "\\*.* /S /D")
Copy link
Contributor

Choose a reason for hiding this comment

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

Why os.system here instead of subprocess?

Copy link
Author

Choose a reason for hiding this comment

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

Just simplicity, i think. It is working with os.system, but could of course use subprocess too.

@NickETH
Copy link
Author

NickETH commented Apr 24, 2022

Ok, here is an output from a Windows machine:
https://gist.github.com/NickETH/d99ce98224e01189cc893995bce59762
Do not have a Mac around here, but could ask Graham next week to do it.
What is the reason, the unittests failed? Did not make any changes in the part, where it complains.

@NickETH
Copy link
Author

NickETH commented May 13, 2022

Hi Nick,
do you see a chance to correct this failing test in the next few days?
Would be cool, to get this done.
Thanks

@jgstew
Copy link
Contributor

jgstew commented Oct 2, 2022

The step of the test that is failing is the e2e test, running the following:

python Code/autopkg info Firefox.munki --prefs tests/preferences.plist

and it is not finding the Firefox.munki recipe. I am not sure why. I wonder if it has to do with --prefs tests/preferences.plist?

@jgstew
Copy link
Contributor

jgstew commented Oct 2, 2022

Also, this PR has changes in it that are NOT only "Implement xattr support on Windows" and seems to contain 3 different sets of changes, and a new processor.

Instead of adding pyads as a PIP dependency, it is actually putting pyads.py into the project, which seems bad.

Comment on lines +1 to +19
# -*- coding: utf-8 -*-
"""
Copyright © 2015, Robin David - MIT-Licensed
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
The Software is provided "as is", without warranty of any kind, express or implied, including but not limited
to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall
the authors or copyright holders X be liable for any claim, damages or other liability, whether in an action
of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other
dealings in the Software.
Except as contained in this notice, the name of the Robin David shall not be used in advertising or otherwise
to promote the sale, use or other dealings in this Software without prior written authorization from the Robin David.
"""
import os
import sys
from ctypes import *
Copy link
Contributor

@jgstew jgstew Oct 2, 2022

Choose a reason for hiding this comment

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

This doesn't belong as a folder/file in the project itself, but rather a pip dependency that is windows only.

Copy link
Author

Choose a reason for hiding this comment

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

Bad idea...
This module does a complete different thing (it is for PLC API)!
Unfortunateley, they are both named the same.
There is no module for pyads for alternate data streams, i am aware of.

Copy link
Contributor

Choose a reason for hiding this comment

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

oh you are right, this is a different pip library. So where is this one you are using from?

Comment on lines +810 to +812
if is_windows():
# we need to remove readonly, hidden and system bits
os.system("attrib.exe -r -h -s " + repo_path + "\\*.* /S /D")
Copy link
Contributor

@jgstew jgstew Oct 2, 2022

Choose a reason for hiding this comment

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

This seems to be to fix a bug that is unrelated to fixing xattr. What is the issue this is solving? Is there a pythonic way to solve this using Pathlib or similar, rather than calling attrib.exe?

I use autopkg a ton on windows, and I have never hit the problem that this seems to be fixing. What autopkg command causes this problem? How can this be reproduced?

Copy link
Author

Choose a reason for hiding this comment

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

This changes came into this PR, after i issued it.
Was not intend to do so...

Copy link
Contributor

@jgstew jgstew Oct 2, 2022

Choose a reason for hiding this comment

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

ah, I see. That is a pain. Once you create the PR from a branch, if you make any further changes to that branch, then it gets included.

It is best to create a custom branch only for the purposes of the PR, which is a bit annoying, but it is the way to cleanly avoid this, especially since this PR has been open for a very long time.

result = False
try:
# result = eval(predicate_string)
splitted_ops = predicate_string.split()
Copy link
Contributor

@jgstew jgstew Oct 2, 2022

Choose a reason for hiding this comment

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

I think this is assuming that predicates have a space between the left side, the right side, and the operator(s) but I don't think that is always the case. Is download_changed!=True a valid predicate? I don't actually have enough experience with them to know for sure.

Would be good to provide examples of what predicate options are specifically supported on windows. Seems like it is only != and == but only if there is a single space between the operator and the left side / right slide.

Copy link
Contributor

Choose a reason for hiding this comment

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

This isn't a true replacement for StopProcessingIf's use of predicates, but it does work the same way cross platform: https://github.com/jgstew/jgstew-recipes/blob/main/SharedProcessors/StopProcessingIfDownloadUnchanged.py

description = __doc__

def main(self):
if not is_windows():
Copy link
Contributor

Choose a reason for hiding this comment

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

Can powershell core do Get-AuthenticodeSignature on non-windows? I'm not certain, but if so, then the decision not to run this might have more to do with finding a powershell binary to execute than it is to do with is_windows().

I have never tried to use Get-AuthenticodeSignature in Powershell core on non-windows, but I should try it.

self.output("Code signature verification disabled for this recipe " "run.")
return
input_path = self.env["input_path"]
powershell = "C:\\windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a very minor point, not a blocker, but I like the idea of the powershell path being an input variable, but with "C:\\windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" being the default path.

I like to use a Processor that takes an array of paths and looks for the first one it find that is an executable file and returns it, then passes that as input into the next processor like this one, which makes it easier to implement this using PowerShell core instead of Powershell, or non-windows if that works, which I haven't checked to see if it does.

Comment on lines +222 to +223
# Windows configuration files should go to the Appdata\Roaming dir.
config_dir = appdirs.user_config_dir(APP_NAME, appauthor=False, roaming=True)
Copy link
Contributor

@jgstew jgstew Oct 2, 2022

Choose a reason for hiding this comment

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

I wonder if it should be checking roaming first, but then check local as a fallback?

I think this change would break my autopkg prefs on my windows devices until I moved the prefs file from local to roaming to account for this change.

@nmcspadden
Copy link
Contributor

Honestly, I would prefer not to use an equivalent to xattr on Windows. Let's keep it simple and just store the etag information in a JSON file on disk, and read/write to it. Embedding it in the download just to mimic what it does on macOS using extended attributes seems unnecessarily difficult.

@jgstew
Copy link
Contributor

jgstew commented Oct 2, 2022

This currently requires switching over to URLDownloaderPython on windows and non windows in order to achieve the JSON option, but an equivalent JSON file could be used as a fallback on URLDownloader as well, not just on windows, but on any file system that doesn't support xattr.

I kind of prefer checking if xattr is supported, and if it is, using it, but if not, then use JSON, instead of checking is_windows as the gate, because many linux filesystems including docker containers don't support xattr.

@NickETH
Copy link
Author

NickETH commented Oct 2, 2022

Honestly, I would prefer not to use an equivalent to xattr on Windows. Let's keep it simple and just store the etag information in a JSON file on disk, and read/write to it. Embedding it in the download just to mimic what it does on macOS using extended attributes seems unnecessarily difficult.

I see your point.
That is the future, i think and should be implemented globally, IMHO.
But in the meantime, this solution works pretty reliable.
Using it in production on a daily basis.

@nmcspadden
Copy link
Contributor

I'd like to potentially revisit this concept for a future AutoPkg release. Given what we have in 3.0.0RC1 right now, what would need to be done still to accommodate this?

@NickETH
Copy link
Author

NickETH commented Aug 31, 2023

did not follow close on your work in the last few weeks.
Let me get the 3.0 code and test.
But i think, it would still blend in without changes.
Will come back, as soon as i have tested it.

@NickETH
Copy link
Author

NickETH commented Aug 31, 2023

Looks like, the PR would work as expected.
Should i do a new one on 3.0RC1?

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