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

Switch to run command #2022

Merged
merged 21 commits into from
Oct 7, 2020
Merged

Conversation

kevinclark19a
Copy link
Contributor

Description

Switched a set of shellutil.run_get_output and shellutil.run callers to the new shellutil.run_command function.


PR information

  • The title of the PR is clear and informative.
  • There are a small number of commits, each of which has an informative message. This means that previously merged commits do not appear in the history of the PR. For information on cleaning up the commits in your pull request, see this page.
  • Except for special cases involving multiple contributors, the PR is started from a fork of the main repository, not a branch.
  • If applicable, the PR references the bug/issue that it fixes in the description.
  • New Unit tests were added for the changes made and Travis.CI is passing.

Quality of Code and Contribution Guidelines

shellutil.run_command(["eject", dvd])
except shellutil.CommandError as cmd_err:
if chk_err:
raise OSUtilError("Failed to eject dvd: ret={0}".format(cmd_err.returncode))
Copy link
Member

Choose a reason for hiding this comment

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

we should probably add the stdout/stderr of the command (the original code was logging errors)

else:
logger.warn("exceeded restart retries")
except shellutil.CommandError as cmd_err:
logger.warn("failed to restart {0}: return code {1}".format(ifname, cmd_err.returncode))
Copy link
Member

Choose a reason for hiding this comment

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

we should add the stdout/stderr of the command

Copy link
Member

Choose a reason for hiding this comment

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

There is small difference here in that the previous code would log commands errors as INFO if the return code was 1, and as ERROR otherwise.
Since anyways we are logging a WARN regardless of the return code, I think we are OK here (as long as we add stderr/stdout to the message)

"-days", "730", "-newkey", "rsa:2048", "-keyout", prv_file, "-out", crt_file]
try:
shellutil.run_command(cmd)
except shellutil.CommandError:
Copy link
Member

Choose a reason for hiding this comment

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

log stdout/stderr

second_proc = subprocess.Popen(second_cmd, stdin=first_proc.stdout, stdout=subprocess.PIPE)
second_proc.wait()

if first_proc.returncode or second_proc.returncode:
Copy link
Member

Choose a reason for hiding this comment

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

let's do an explicit comparison against 0


first_proc = subprocess.Popen(first_cmd, stdout=subprocess.PIPE)
second_proc = subprocess.Popen(second_cmd, stdin=first_proc.stdout, stdout=subprocess.PIPE)
second_proc.wait()
Copy link
Member

Choose a reason for hiding this comment

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

we should use communicate() instead to get stdout/stderr and log it on failure

output_file))
try:
with open(output_file, "a") as file_out:
output = shellutil.run_command(["ssh-keygen", "-i -m PKCS8 -f", input_file])
Copy link
Member

Choose a reason for hiding this comment

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

I would feel more comfortable if we use Popen directly here (as we did in the previous function). run_command has some extra code to encode the command's output and, though I do not see any issue right now, I think it would be safer to use Popen.

Copy link
Member

@narrieta narrieta left a comment

Choose a reason for hiding this comment

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

Added comments

narrieta
narrieta previously approved these changes Sep 29, 2020
[stderr]
{3}
""".format(ifname, cmd_err.returncode, cmd_err.stdout, cmd_err.stderr)
logger.warn(msg)
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 previous implementation, the exit_code:1 was logged as an info if there were retries available and then as an error. Now you're just logging it as a warning, not sure if you want to keep them consistent or not.

Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't this logged in L1154?

Copy link
Contributor

@larohra larohra Oct 6, 2020

Choose a reason for hiding this comment

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

Nope that's a different log line. I was comparing the previous implementation with the new one

Copy link
Contributor

Choose a reason for hiding this comment

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

Basically this parameter for expected_errors=[1] in the previous implementation -

 return_code=shellutil.run("ifdown {0} && ifup {0}".format(ifname), expected_errors=[1] if attempt < retries else [])

The shellutil.run function would've logged it as an info if the exit_code was 1 but now it would be logged as an error.

Not sure how big of a difference it makes, just noticed it so figured I'd point it out. I'm personally fine as is too

Copy link
Member

Choose a reason for hiding this comment

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

@larohra I posted a similar comment here, not sure why it doesn't show up.

In any case, I added the 'expected_errors' parameter some time back as a stopgap to avoid logging an error when the error code is 1. This seems to be relatively common and was logged as an error due to the way the run() function is defined, and this was confusing people looking at the log. From the caller, any error code executing the command is clearly a warning.

The new implementation drops the INFO (which was there just because run logs all failures in the command it execurtes), but keeps the warning. This should be fine.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ahh ok ok, makes sense. Thanks for the clarification

azurelinuxagent/common/osutil/ubuntu.py Outdated Show resolved Hide resolved
"-out", pem_file]

first_proc = subprocess.Popen(first_cmd, stdout=subprocess.PIPE)
second_proc = subprocess.Popen(second_cmd, stdin=first_proc.stdout, stdout=subprocess.PIPE)
Copy link
Contributor

Choose a reason for hiding this comment

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

Good way of solving the problem! I'm sure you must've already done this, but you confirmed this has no regressions right? And DCR passed too?

Copy link
Member

Choose a reason for hiding this comment

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

@kevinclark19a DCR ok?


[stderr]
{2}
""".format(p7m_file, stdout, stderr)
Copy link
Contributor

Choose a reason for hiding this comment

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

Make sure to encode the stdout/stderr before writing it to log (the run_command function always does that for you)

self.assertEqual(cmd_queue.pop(0), ["ifdown", ifname])
# We don't expect the following command to be called because 'dummy' does
# not exist.
# self.assertEqual(cmd_queue.pop(0), ["ifup", ifname])
Copy link
Contributor

Choose a reason for hiding this comment

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

If you dont expect this, you should add an assert that it's actually not called rather than a comment :)

with patch.object(os, 'makedirs'):
try:
osutil.DefaultOSUtil().mount_dvd()
self.fail('OSUtilError was not raised')
except OSUtilError as ose:
self.assertTrue(msg in ustr(ose))
self.assertTrue(patch_run.call_count == 6)
self.assertEqual(patch_run.call_count, 5)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why did the number of calls change if we didn't change the retry number (6)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The range has always been [1..6), so I'm not quite sure how this test was passing before. Any ideas?

Copy link
Contributor Author

@kevinclark19a kevinclark19a Oct 2, 2020

Choose a reason for hiding this comment

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

Ah, ok I figured it out. Before, we were mocking run_get_output, because that's what self.mount used before. There is a run_get_output call in mount_dvd that we decided not to bother changing as a part of this PR (as it uses a constant string), which was the 6th call before. Since our mock is now for run_command, that run_get_output call obviously doesn't get counted anymore, bringing the total number of calls from 6 (5 run_get_output calls in self.mount + 1 run_get_output in mount_dvd itself) to 5 (just the five run_command calls in self.mount).

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for checking! Makes sense now.

pgombar
pgombar previously approved these changes Oct 2, 2020
Copy link
Contributor

@pgombar pgombar left a comment

Choose a reason for hiding this comment

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

Minor comments, else LGTM

@kevinclark19a kevinclark19a dismissed stale reviews from pgombar and narrieta via 9863b72 October 6, 2020 18:29
@@ -96,6 +96,9 @@ def decrypt_p7m(self, p7m_file, trans_prv_file, trans_cert_file, pem_file):
stdout, stderr = second_proc.communicate()

if first_proc.returncode != 0 or second_proc.returncode != 0:
stdout = ustr(stdout, encoding='utf-8', errors="backslashreplace") if stdout else ""
Copy link
Contributor

@larohra larohra Oct 6, 2020

Choose a reason for hiding this comment

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

NIT: How about making this function public and using this instead -

def _encode_command_output(output):
    return ustr(output, encoding='utf-8', errors="backslashreplace")

Its in the shellutils.py

@kevinclark19a kevinclark19a merged commit 7c8ed71 into Azure:develop Oct 7, 2020
@kevinclark19a kevinclark19a deleted the SwitchToRunCommand branch October 7, 2020 16:58
narrieta pushed a commit to narrieta/WALinuxAgent that referenced this pull request Oct 12, 2020
narrieta added a commit that referenced this pull request Oct 13, 2020
This reverts commit 7c8ed71.

Co-authored-by: narrieta <narrieta>
kevinclark19a pushed a commit to kevinclark19a/WALinuxAgent that referenced this pull request Oct 23, 2020
kevinclark19a added a commit that referenced this pull request Nov 2, 2020
… reverted. (#2050)

* Temporarily removing the depreciated functions to let the linter find everything that needs changing.

* Migrated run_get_output to run_command

* Fixed typo

* Fixed arg formatting issues.

* Fixed file mode.

* fixed some unit tests

* Potentially fixed unit tests?

* Fixed file name

* Addressed comments

* Fixed comments

* fixed tests.

* Added logging

* Potentially fixed bug

* Removing debugging log.

* Fixed bug with run_command needing a list instead of a string.

* Added logging statement for debugging.

* Fixed tests

* Revert "Revert "Switch to run command (#2022)" (#2039)"

This reverts commit f90227f.

* Reverted unneeded changes.

* Potential fix for DCR provisioning failure.

* added logging for errors.

* Addressed PR comments.
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.

4 participants