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

Add support for setting redis username #1351

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion kombu/transport/redis.py
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,7 @@ def _connparams(self, asynchronous=False):
'host': conninfo.hostname or '127.0.0.1',
'port': conninfo.port or self.connection.default_port,
'virtual_host': conninfo.virtual_host,
'username': conninfo.userid,
Copy link
Member

Choose a reason for hiding this comment

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

should we also update the related docs?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@auvipy Actually, this is a good question. I'd say yes if the documentation explicitly says that the username part of the connection URL won't be parsed (before this change), otherwise, I'd say that this should be "mainstream" that a connection URL can contain a username.

If you would like me, I'm happy to find the relevant section in the documentation and explicitly state that, from now on, usernames will be parsed too.

Copy link
Member

Choose a reason for hiding this comment

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

Please do.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@thedrow @auvipy I'm happy to extend any documentation, if you could advise a bit. The documentation has no mention at all about usernames in terms of the Redis transport. In fact, the documentation is defined as

.. code-block::

    redis://REDIS_ADDRESS[:PORT][/VIRTUALHOST]
    rediss://REDIS_ADDRESS[:PORT][/VIRTUALHOST]

To use sentinel for dynamic Redis discovery,
the connection string has the following format:

.. code-block::

    sentinel://SENTINEL_ADDRESS[:PORT]

I do believe -- but correct me if I'm wrong -- the reason behind this is that the host parameter (REDIS_ADDRESS) may contain username and password as per RFC 2617. If you would like me, I can describe that in the inline documentation, though that would be a bit verbose.

If you would like me to extend another documentation that I did not find (yet), please help me with the link.

Copy link
Member

Choose a reason for hiding this comment

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

The documentation is not 100% complete. I am not 100% whether is good idea to refer to some standard because URL parsing is done by urllib.parse.urlparse but some magic is involved during the parsing - see kombu/utils/url.py:url_to_parts(). Let it keep simple. Please extend the documentation as follows:

redis://[USER:PASSWORD@]REDIS_ADDRESS[:PORT][/VIRTUALHOST]
rediss://[USER:PASSWORD@]REDIS_ADDRESS[:PORT][/VIRTUALHOST]

Maybe we can also add some examples to the documentation.

Otherwise, the PR seems to be fine for me.

'password': conninfo.password,
'max_connections': self.max_connections,
'socket_timeout': self.socket_timeout,
Expand Down Expand Up @@ -974,7 +975,7 @@ def _connparams(self, asynchronous=False):
pass
host = connparams['host']
if '://' in host:
scheme, _, _, _, password, path, query = _parse_url(host)
scheme, _, _, username, password, path, query = _parse_url(host)
if scheme == 'socket':
connparams = self._filter_tcp_connparams(**connparams)
connparams.update({
Expand All @@ -984,6 +985,7 @@ def _connparams(self, asynchronous=False):
connparams.pop('socket_connect_timeout', None)
connparams.pop('socket_keepalive', None)
connparams.pop('socket_keepalive_options', None)
connparams['username'] = username
connparams['password'] = password

connparams.pop('host', None)
Expand Down
8 changes: 6 additions & 2 deletions t/unit/transport/test_redis.py
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,10 @@ def test_connparams_regular_hostname(self):
self.channel.connection.client.hostname = 'george.vandelay.com'
assert self.channel._connparams()['host'] == 'george.vandelay.com'

def test_connparams_username(self):
self.channel.connection.client.userid = 'kombu'
assert self.channel._connparams()['username'] == 'kombu'

def test_connparams_password_for_unix_socket(self):
self.channel.connection.client.hostname = \
'socket://:foo@/var/run/redis.sock'
gabor-boros marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -1414,7 +1418,7 @@ def test_getting_master_from_sentinel(self):
min_other_sentinels=0, password=None, sentinel_kwargs=None,
socket_connect_timeout=None, socket_keepalive=None,
socket_keepalive_options=None, socket_timeout=None,
retry_on_timeout=None)
username=None, retry_on_timeout=None)

master_for = patched.return_value.master_for
master_for.assert_called()
Expand All @@ -1437,7 +1441,7 @@ def test_getting_master_from_sentinel_single_node(self):
min_other_sentinels=0, password=None, sentinel_kwargs=None,
socket_connect_timeout=None, socket_keepalive=None,
socket_keepalive_options=None, socket_timeout=None,
retry_on_timeout=None)
username=None, retry_on_timeout=None)

master_for = patched.return_value.master_for
master_for.assert_called()
Expand Down