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

Fix http_request for IPv6-only machines #17644

Closed
wants to merge 1 commit into from

Conversation

ei-grad
Copy link
Contributor

@ei-grad ei-grad commented Sep 19, 2016

ansible.module_utils.urls creates socket with AF_INET family, which
doesn't work for IPv6-only machine.

@bcoca bcoca added bugfix_pull_request needs_info This issue requires further information. Please answer any outstanding questions. labels Sep 19, 2016
@bcoca
Copy link
Member

bcoca commented Sep 19, 2016

the issue you point at in the title seems to have been closed a long time

@ei-grad
Copy link
Contributor Author

ei-grad commented Sep 19, 2016

If you look down throught the comments you will find that there are another (unreported) issues messing with that one. Also, see #17645.

@ei-grad
Copy link
Contributor Author

ei-grad commented Sep 19, 2016

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))
Copy link
Member

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

Copy link
Contributor Author

@ei-grad ei-grad Sep 19, 2016

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

Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 4e19451878779023bba0679baa35baba1d9e96d7

@bcoca bcoca added needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. and removed needs_info This issue requires further information. Please answer any outstanding questions. labels Sep 19, 2016
@ei-grad ei-grad changed the title Fix #7218 for IPv6-only machines Fix http_request for IPv6-only machines Sep 19, 2016
@ei-grad ei-grad force-pushed the fix-ipv6-urls-connect branch 2 times, most recently from c1d6c6b to 4e19451 Compare September 20, 2016 14:36
def create_connection(address):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(address)
return sock
Copy link
Member

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)

Copy link
Contributor Author

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

Copy link
Contributor

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?

Copy link
Member

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.

Copy link
Contributor Author

@ei-grad ei-grad Dec 15, 2016

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.

Copy link
Contributor Author

@ei-grad ei-grad Dec 15, 2016

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.

Copy link
Member

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.
@ei-grad
Copy link
Contributor Author

ei-grad commented Dec 15, 2016

@bcoca @sivel I rebased this on current devel, and replaced hasattr by try/except block in import scope. Does it look better for you now?

@ansibot ansibot added needs_rebase https://docs.ansible.com/ansible/devel/dev_guide/developing_rebasing.html and removed needs_rebase https://docs.ansible.com/ansible/devel/dev_guide/developing_rebasing.html labels Dec 16, 2016
@ansibot ansibot added module_util needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. and removed needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. labels Jan 5, 2017
@abadger
Copy link
Contributor

abadger commented Mar 16, 2017

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.

@ansibot
Copy link
Contributor

ansibot commented Apr 11, 2017

@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:

  • issue type

Please set the description of this pullrequest with this template:
https://raw.githubusercontent.com/ansible/ansible/devel/.github/PULL_REQUEST_TEMPLATE.md

click here for bot help

@ansibot ansibot added needs_info This issue requires further information. Please answer any outstanding questions. needs_template This issue/PR has an incomplete description. Please fill in the proposed template correctly. stale_ci This PR has been tested by CI more than one week ago. Close and re-open this PR to get it retested. labels Apr 11, 2017
@ansibot ansibot added support:core This issue/PR relates to code supported by the Ansible Engineering Team. stale_review Updates were made after the last review and the last review is more than 7 days old. labels Jun 29, 2017
@ansibot ansibot added needs_rebase https://docs.ansible.com/ansible/devel/dev_guide/developing_rebasing.html and removed stale_review Updates were made after the last review and the last review is more than 7 days old. labels Jul 19, 2017
@mattclay
Copy link
Member

mattclay commented Oct 9, 2017

#17999 is a simplified fix expected to be in 2.4.2, which does not require Python 2.4 support.

@mattclay mattclay closed this Oct 9, 2017
@ansibot ansibot added bug This issue/PR relates to a bug. and removed bugfix_pull_request labels Mar 5, 2018
@ansible ansible locked and limited conversation to collaborators Apr 26, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
affects_2.3 This issue/PR affects Ansible v2.3 bug This issue/PR relates to a bug. c:module_utils/urls c:module_utils/ module_util needs_info This issue requires further information. Please answer any outstanding questions. needs_rebase https://docs.ansible.com/ansible/devel/dev_guide/developing_rebasing.html needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. needs_template This issue/PR has an incomplete description. Please fill in the proposed template correctly. stale_ci This PR has been tested by CI more than one week ago. Close and re-open this PR to get it retested. support:core This issue/PR relates to code supported by the Ansible Engineering Team.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants