-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
[BUG] file.replace and file.search false change when looking for //
#60055
Comments
I have reproduced your issue. I created a salt state with your exact file.comment state, but operating on my own test file. As you indicate, file.comment does work correctly and comment out all the lines when you run it the first time. This is not the problem. The problem is on successive runs when the file really needs no changes. When I run with test=true, We get the message "File /var/tmp/comment is set to be updated":
We should instead get a message "Pattern already commented". I can also see that when the state has already been applied, running it without test=true gives us a 'bad' response, indicating a change was made, but no change was made, because the file was already good:
I believe both these problems are related and are likely due to the following lines in salt/salt/states/file.py:comment() method not working correctly, at least for your regex:
If this code doesn't intercept the 'no changes' case, it will flow to the code underneath, which assumes there are changes to be made, and then will return values indicating that the changes were made successfully. I will investigate further. |
OK, in attempting to narrow down the problem, I've determined file.comment works 100% fine with a simpler regex such as "^foobar" and your comment string '//' -- running again correctly indicates no changes will be made. So file.comment works perfectly for simpler scenarios, but not 100% perfect for your specific test case. I think it is very likely that the state is not properly handling your more complex regex which contains a negative lookahead "(?!...)". I believe that this is the issue. This issue can be caused by a couple of things. First, there is a pre-processing of the regex that happens inside the comment state itself (see More investigation required to determine root cause. |
I think I found the issue, and it has to do with your regex.
I think you want to replace
So this appears to be a quirk of how your specific regex works, which is confusing. Let me know your results with the minor regex change and if now things work as expected. You will see that even though your regex makes no changes to the data, it actually registers a match! This is why it's so confusing. Possibly we could test against this specific case by looking to see if the replacement data is any different from the new data, rather than looking for number of matches, which is problematic, since some matches may be 'null' matches like this. |
Thank you for taking the time to look at this @danielrobbins ! I'm guessing it matched the last "empty" line of any file , but i would have expected the file.comment state i use to append It no longer return wrong change by changing the regex, but it also won't add comment to empty line in the middle of the text block. Once again sorry for the false bug report |
@Vaarlion you are very welcome! This is actually a weird behavior of the python regex implementation, which is also discussed here: rust-lang/regex#355 It may actually be a good idea to look into some fix/tweak for this so salt users don't have to deal with this strange peculiarity of the multiline regex implementation in Python. I would like to look into the possibility of making this better and getting your original regex working correctly -- because I think others may write your regex expecting the result you expected, but also be surprised by this behavior. So I am going to re-open the issue and will continue to look into it. |
I believe this change to the source code will resolve the issue. It works perfectly in my limited testing and causes your original regex to be treated as expected by salt:
|
Please note that my fix above needs further testing. I hope it will work for everyone and not introduce any unexpected changes of behavior for existing users of this function who may want a zero-length match to show up a match. I think it's unlikely that people want |
thank you for looking into it danielrobbins. I can quickly think of a case where you want to fill empty line between 2 block of text for example. or remove them |
Description
I have a file i wish to fully comment. The comment flag for it is
//
.for this i used this state
my file now look like this
It worked well but always reported a future change when running in test=true. So i started digging.
states.file.comment
callmodules.file.search
, which is a wrapper formodules.files.replace
modules.files.replace
usere.search
whensearch_only
is True, which is what is used bymodules.file.search
.So i tested it locally.
since it does return something i tried to run the other part of
modules.files.replace
that usere.subn
The output is identical, but there was a match. So i printed r_data to make a diff.
it look like when loading the file in memory, the first 2
//
are missing, and that is whatre
match . My guess is that there is something wrong with the way we work with the file, but this is over my reach.One weird thing that could counter this idea is that when i try to match something that doesn't exist, the output of
re.subn
still contain the first 2//
, while not present in r_dataSetup
simplified setup
Steps to Reproduce the behavior
Expected behavior
modules.file.replace
in search_only andmodules.file.search
should not return True when nothing need to be changedScreenshots
If applicable, add screenshots to help explain your problem.
Versions Report
salt --versions-report
(Provided by running salt --versions-report. Please also mention any differences in master/minion versions.)Additional context
Add any other context about the problem here.
The text was updated successfully, but these errors were encountered: