-
Notifications
You must be signed in to change notification settings - Fork 23.8k
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
Fix http_request for IPv6-only machines #17644
Conversation
the issue you point at in the title seems to have been closed a long time |
If you look down throught the comments you will find that there are another (unreported) issues messing with that one. Also, see #17645. |
But you are right, I should probably remove its mention from the commit message. |
@@ -686,7 +685,7 @@ def http_request(self, req): | |||
else: | |||
raise ProxyError('Unsupported proxy scheme: %s. Currently ansible only supports HTTP proxies.' % proxy_parts.get('scheme')) | |||
else: | |||
s.connect((self.hostname, self.port)) | |||
s = socket.create_connection((self.hostname, self.port)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this breaks 2.4 compatibility as it was added in 2.6
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bcoca is there a common practice to backport such things?
Should I just copy it to ansible.module_utils.urls
?
https://github.com/python/cpython/blob/master/Lib/socket.py#L688
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jimi-c made the following suggestion:
Since we're going to be stopping support of python-2.4 in new versions of Ansible in April of next year, perhaps it makes sense to use create_connection() if it's available, otherwise using socket.connect(). Would also need a note that the code won't work with ipv6 on python-2.4.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 4e19451878779023bba0679baa35baba1d9e96d7
c1d6c6b
to
4e19451
Compare
def create_connection(address): | ||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | ||
sock.connect(address) | ||
return sock |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not really a fan of this approach, and generally speaking, we have tried to stay away from it.
I am more in favor of just doing:
try:
sock = socket.create_connection(address)
except AttributeError:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(address)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And I'm definitely is not fan of abusing try/except for non-exceptional situations. Your code would raise and handle exception every time on python 2.4. This is not something that could be called "python 2.4" support...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have a huge preference here but I think @sivel's code is slightly better. We do use try: except (Ask forgiveness) quite a lot for compatibility between python versions. Asking forgiveness seems to be the accepted idiomatice way to write python versus look before you leap.
Since this is for python-2.4 only it makes even more sense. In the large picture there's only a few users running python-2.4 and we're going to be getting rid of support for it in less than a year.
Probably the major problem with the approach currently in the code is that it creates an ambiguity in what happens when create_connection() is called that isn't apparent when you are looking at the caller. This can be worked around by adding the new function under a different name and then putting the conditional into the calling code to select which of the two functions to call or putting the condition and the implementing code into the caller (The latter repeats itself once but for this specific case is probably okay -- it adds less lines of code which often indicates that the function can be considered too trivial to warrant being moved outside the caller). That will be slower for the common case of operating on non-python-2.4 (exceptions are faster than conditionals when following the happy path) but may be a good compromise. @sivel is the exception vs conditional the major thing you're looking at or the obfuscation of create_connection's meaning and the relative burden between caller and called?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the slow response, I am concerned both with pythonic implementations, speed and obfuscation combined.
Creating a function named the same as the original method, by which it is hard to tell in the calling location which is happening will often lead to confusion.
hasattr can also sometimes work in strange ways such as what is described in https://hynek.me/articles/hasattr/
Additionally, with hasattr you are performing the lookup multiple times, instead of just trying to use it and handle the exception. In the majority of cases, just trying to use it and handling the exception will be the faster way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't create a function named the same as original method, I just use it if it is available, and define a fallback if it is not available (in which case there is no original method). For python>=2.6 this function would be the original method. There is no confusion.
The problem with hasattr
is not a problem since we use it not on a custom class instance but on a module.
Also, it doesn't perform lookup multiple times, since it is called on module import.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handling exception each time on python2.4 definitely would not be the faster way. The try/except block also has its own little overhead, so it would be slower even on python>=2.6.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to leave this in needs_revision. My requirements for considering this change have been outlined above.
ansible.module_utils.urls creates socket with AF_INET family, which doesn't work for IPv6-only machine.
4e19451
to
80e16d9
Compare
Sidestepping the whole question of how to make compatibility code... We've just branched stable-2.3 which means that devel is now open for developing Ansible-2.4. Ansible-2.4 drops support for python-2.4 and python-2.5 so we can go back to the code that simply assumes that socket.create_connection is available. |
@ei-grad Greetings! Thanks for taking the time to open this pullrequest. In order for the community to handle your pullrequest effectively, we need a bit more information. Here are the items we could not find in your description:
Please set the description of this pullrequest with this template: |
#17999 is a simplified fix expected to be in 2.4.2, which does not require Python 2.4 support. |
ansible.module_utils.urls creates socket with AF_INET family, which
doesn't work for IPv6-only machine.