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

Added "ACL LOG" command new in Redis 6 RC2 #1307

Closed
wants to merge 12 commits into from
Closed

Added "ACL LOG" command new in Redis 6 RC2 #1307

wants to merge 12 commits into from

Conversation

jiekun
Copy link
Contributor

@jiekun jiekun commented Mar 15, 2020

Pull Request check-list

Please make sure to review and check all of these items:

  • Does $ tox pass with this change (including linting)?
  • Does travis tests pass with this change (enable it first in your forked repo and wait for the travis build to finish)?
  • Is the new or changed code fully tested?
  • Is a documentation update included (if this change modifies existing APIs, or introduces new ones)?

NOTE: these things are not required to open a PR and can be done
afterwards / while the PR is open.

Description of change

Hi. First of all thanks for checking this.
There is an "ACL LOG" command added in Redis 6 RC2. I tried to add it to redis-py.

The "ACL LOG" command supports two kind of arguments: ACL LOG [<count> | RESET]. For <count>, it returns a acl log list. For RESET, it returns 'OK'. So I parsed it into:

The original response for 'ACL LOG':
[[b'count', 1, b'reason', b'command', b'context', b'toplevel', b'object', b'set', b'username', b'duck', b'age-seconds', b'1.958', b'client-info', b'id=3180 addr=127.0.0.1:59566 fd=9 name= age=105 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=30 qbuf-free=32738 obl=0 oll=0 omem=0 events=r cmd=set user=duck']]

The redis-py output for 'ACL LOG':
[{'count': 1, 'reason': 'command', 'context': 'toplevel', 'object': 'set', 'username': 'duck', 'age-seconds': 1.958, 'client-info': {'id': 3180, 'addr': '127.0.0.1:59566', 'fd': '9', 'name': '', 'age': 105, 'idle': 0, 'flags': 'N', 'db': 0, 'sub': 0, 'psub': 0, 'multi': -1, 'qbuf': 30, 'qbuf-free': 32738, 'obl': 0, 'oll': 0, 'omem': 0, 'events': 'r', 'cmd': 'set', 'user': 'duck'}}]

-------------------- break --------------------

The original response for 'ACL LOG RESET':
b'OK'

The redis-py output for 'ACL LOG RESET':
True

Note that the wget link in .travis.yml is changed as well since the RC1 does not have a LOG sub-command for ACL.

Please take a look. It's my first PR for open-source project. Thank you.

@codecov-io
Copy link

codecov-io commented Mar 15, 2020

Codecov Report

Merging #1307 into master will increase coverage by 0.09%.
The diff coverage is 92.98%.

Impacted file tree graph

@@            Coverage Diff            @@
##           master   #1307      +/-   ##
=========================================
+ Coverage   92.81%   92.9%   +0.09%     
=========================================
  Files          19      19              
  Lines        6526    6583      +57     
=========================================
+ Hits         6057    6116      +59     
+ Misses        469     467       -2
Impacted Files Coverage Δ
tests/test_commands.py 99.94% <100%> (ø) ⬆️
redis/client.py 86.32% <88.57%> (+0.04%) ⬆️
redis/connection.py 82.82% <0%> (+0.79%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f2f470e...e53a8c0. Read the comment docs.

@jiekun jiekun changed the title Added "ACL LOG" command in Redis 6 RC2 Added "ACL LOG" command new in Redis 6 RC2 Mar 15, 2020
@andymccurdy
Copy link
Contributor

I skimmed the code and this initially looks well done. Thanks!

Is there any documentation for ACL LOG on redis.io or elsewhere? I looked at the ACL section of the redis.io website and found no mention of this.

@itamarhaber
Copy link
Member

It has yet to be documented

@jiekun
Copy link
Contributor Author

jiekun commented Mar 15, 2020

Is there any documentation for ACL LOG on redis.io or elsewhere?

Yes the ACL doc is not updated.
This pull request is based on Antirez's videos and source code and some redis-cli test myself.

2014bduck added 2 commits March 16, 2020 00:58
The return type may change to boolean, base on what argument is used. I am thinking about splitting them into two methods like `acl_log()` and `acl_log_reset()`.
But that will not match the Redis command usage which is `ACL LOG [<count> | RESET]`.
@jiekun
Copy link
Contributor Author

jiekun commented Mar 15, 2020

The return type may change from list to boolean, based on what argument is used. I am thinking about splitting them into two methods like acl_log() and acl_log_reset().
But that will not match the Redis command usage which is ACL LOG [<count> | RESET].

@jiekun
Copy link
Contributor Author

jiekun commented May 6, 2020

Hi. Any idea about this one? @andymccurdy
https://redis.io/commands/acl-log

@RoeyPrat
Copy link

The return type may change from list to boolean, based on what argument is used. I am thinking about splitting them into two methods like acl_log() and acl_log_reset().
But that will not match the Redis command usage which is ACL LOG [<count> | RESET].

Hi @2014BDuck, great work!
I think it would be better to split the method into two methods as you've suggested.
acl_log and acl_log_reset have different use cases, as well as returning different types.

Also note you can drop the commit to change redis version in travis, as we are now using version 6.0.5 on master.

@jiekun
Copy link
Contributor Author

jiekun commented Jul 2, 2020

The return type may change from list to boolean, based on what argument is used. I am thinking about splitting them into two methods like acl_log() and acl_log_reset().
But that will not match the Redis command usage which is ACL LOG [<count> | RESET].

Hi @2014BDuck, great work!
I think it would be better to split the method into two methods as you've suggested.
acl_log and acl_log_reset have different use cases, as well as returning different types.

Also note you can drop the commit to change redis version in travis, as we are now using version 6.0.5 on master.

  • For 6.0.5: Cool let me merge the master first so that old commit will be covered
  • For seperated it into 2 method: OK Will do

@codecov-commenter
Copy link

codecov-commenter commented Jul 6, 2020

Codecov Report

Merging #1307 into master will decrease coverage by 7.00%.
The diff coverage is 87.71%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1307      +/-   ##
==========================================
- Coverage   92.76%   85.76%   -7.01%     
==========================================
  Files          20        7      -13     
  Lines        6581     3049    -3532     
==========================================
- Hits         6105     2615    -3490     
+ Misses        476      434      -42     
Impacted Files Coverage Δ
redis/client.py 86.13% <86.27%> (+0.04%) ⬆️
redis/connection.py 82.18% <100.00%> (+0.43%) ⬆️
redis/exceptions.py 100.00% <100.00%> (ø)
redis/_compat.py 86.99% <0.00%> (-0.11%) ⬇️
redis/lock.py 100.00% <0.00%> (ø)
tests/test_monitor.py
tests/test_scripting.py
redis/__init__.py
tests/test_connection.py
tests/test_pipeline.py
... and 5 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 20ec5d7...7995723. Read the comment docs.

@andymccurdy
Copy link
Contributor

@2014BDuck Awesome, thanks. Ping me when you get this split into two separate functions and we'll get it merged.

@jiekun
Copy link
Contributor Author

jiekun commented Jul 8, 2020

@andymccurdy Hi ptal one more time. Thanks

@RoeyPrat RoeyPrat requested a review from andymccurdy July 8, 2020 08:46
Copy link
Contributor

@andymccurdy andymccurdy left a comment

Choose a reason for hiding this comment

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

This is really close. Thanks for splitting up the command. A few inline notes below and then we'll get this merged. Thanks!

r_test.set("cache:0", 1)
r_test.get("cache:0")
# Invalid key
try:
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be:

with pytest.raises(exceptions.NoPermissionError):
    r_test.get('violated_cache:0')

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. Thanks.

except exceptions.NoPermissionError:
pass
# Invalid operation
try:
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above:

with pytest.raises(exceptions.NoPermissionError):
    r_test.hset('cache:0', 'hkey', 'hval')

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. Thanks.

pass

assert len(r.acl_log()) == 2
assert len(r.acl_log(count=1)) == 1
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be nice to assert that acl_log() returns a dict and that a common set of keys exist. Additionally we should check that the 'click-info' value is a dict as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added few return type assertion now.

keys=['cache:*'], nopass=True)
r.acl_log_reset()

r_test = redis.Redis(host='localhost', port=6379, db=9,
Copy link
Contributor

Choose a reason for hiding this comment

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

We don't want to hardcode connection info in a test. Instead, use the _get_client function from conftest.py. Something like:

r_test = _get_client(redis.Redis, request, username=username)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep please check the comment below

@jiekun
Copy link
Contributor Author

jiekun commented Jul 11, 2020

Hi @andymccurdy
I've added some the "assert" cases and changed few cases into "with" pattern, which is more accurate for the testing. Thanks for your guidence & learned a lot.

For the hardcoded connection:

r_test = redis.Redis(host='localhost', port=6379, db=9...

Yep it's not pretty. I tried to find out the correct pattern to new a different client before writting it but haven't found any example.

The get_client way r_test = _get_client(redis.Redis, request, username=username) : Seems like the deeper codes won't use the username variable in **kwargs but from the passed in request object:

# This method passed redus_url string grabbed from request obj. And passed to "from_url" class method.
def _get_client(cls, request, single_connection_client=True, **kwargs):
    redis_url = request.config.getoption("--redis-url")
    client = cls.from_url(redis_url, **kwargs)
    .....


# This method will parse url and use the username in url.
    def from_url(cls, url, db=None, decode_components=False, **kwargs):
        url = urlparse(url)
        url_options = {}

        ...
        # Here. The username is token directly from the url we passed in.
        if decode_components:
            username = unquote(url.username) if url.username else None
            ...
        else:
            username = url.username or None
            ...

So it's not working using r_test = _get_client(redis.Redis, request, username=username). I am thinking about:

  • Altering the attribute of request obj ? like request.config.option.redis_url = ''redis://xxx:localhost:6379/9'. But I think it looks more weird than building a new client with redis.Redis(host='localhost', port=6379, db=9)
  • Altering the deeper method from_url using username in **kwargs if existed. Otherwise following the current pattern.

Actually both of them sound worse from my point of view. Would like to hear more advice from your side. Many thanks.

@jiekun jiekun requested a review from andymccurdy July 12, 2020 03:55
@jiekun
Copy link
Contributor Author

jiekun commented Jul 25, 2020

@andymccurdy Hi. May I request for a review and your suggestion again?

Two things after I merged the current master branch.

  • The coverage test is not passed due to...? Looks like it's not caused by my changes? Should I re-open a new PR or any suggestion?
  • The hardcoded connection. If we need to pass the username as connection param, it would require additional changes on couple methods, which is not graceful enough from my point of view.

@andymccurdy
Copy link
Contributor

@2014BDuck I fixed this in the acl-log branch here: https://github.com/andymccurdy/redis-py/tree/acl-log

I believe that branch is good to go. Let me know if you see anything off. If you want to merge it back into this PR I'll then merge your PR to master. Alternatively I can just merge the acl-log branch to master. Let me know what you prefer.

@jiekun
Copy link
Contributor Author

jiekun commented Aug 19, 2020

Alternatively I can just merge the acl-log branch to master

@andymccurdy Yes please.

And sorry for wasting your time and effort on guiding. Very appreciated.

@andymccurdy
Copy link
Contributor

Merged. Thanks!

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.

6 participants