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

feat(AclFamily): load/store aclfile #1820

Merged
merged 3 commits into from Sep 8, 2023
Merged

feat(AclFamily): load/store aclfile #1820

merged 3 commits into from Sep 8, 2023

Conversation

kostasrim
Copy link
Contributor

@kostasrim kostasrim commented Sep 7, 2023

  • add ACL LOAD
  • add ACL SAVE
  • add --aclfile command

@dranikpg

  1. I need to polish a little bit and fix the pytest. I am a little tired atm and I will do it in the morning, it's basically 3 small fixes.
  2. Some parts of the PR are not very polished and can be simplified (I duplicate some parts). These will be fixed after the PRs tha add the filtering based on acl commands && and the acl logs since I expect there will be some changes there as well.

Feel free to review, but I would advice to do it tomorrow after I fix the tests.

Closes: #1807

dispatch_q_.push_front(std::move(msg));
// We need to reorder the queue, since multiple updates might happen before we
// pop the message, invalidating the correct order since we always push at the front
maybe_reorder_dispatch_q(std::move(msg));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was a bug if we pushed two messages one after the other before the queue is saturated (because the order would be messed up). This is fixed now :)

@@ -80,8 +80,8 @@ class Connection : public util::Connection {
struct MonitorMessage : public std::string {};

struct AclUpdateMessage {
std::string_view username;
uint64_t categories{0};
std::vector<std::string> 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.

This was also a bug, std::string_view could have been deleted if the queue item was not consumed and the string_view associated with the name got deallocated (e.g, user deletion)

Copy link
Contributor

Choose a reason for hiding this comment

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

I remember I asked in the previous PR 😆

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes and I replied wrongly because I did not think about this case. It's fine, we caught it and I now know better.

P.s. you don't forget do you ? 👀

Copy link
Contributor

Choose a reason for hiding this comment

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

No 🤣

Copy link
Contributor

@dranikpg dranikpg left a comment

Choose a reason for hiding this comment

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

Just a few general comments 🧚🏻‍♂️

Comment on lines 999 to 1009
auto maybe_reorder_dispatch_q = [this](MessageHandle msg) {
std::vector<MessageHandle> updates;
while (std::holds_alternative<AclUpdateMessage>(dispatch_q_.front().handle)) {
updates.push_back(std::move(dispatch_q_.front()));
dispatch_q_.pop_front();
}
updates.push_back(std::move(msg));
for (auto elem = updates.rbegin(); elem != updates.rend(); ++elem) {
dispatch_q_.push_front(std::move(*elem));
}
};
Copy link
Contributor

Choose a reason for hiding this comment

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

you can insert into a deque with an iterator 🤓

@@ -80,8 +80,8 @@ class Connection : public util::Connection {
struct MonitorMessage : public std::string {};

struct AclUpdateMessage {
std::string_view username;
uint64_t categories{0};
std::vector<std::string> username;
Copy link
Contributor

Choose a reason for hiding this comment

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

I remember I asked in the previous PR 😆

Comment on lines 455 to 458
auto acl_file = absl::GetFlag(FLAGS_aclfile);
if (!acl_file.empty()) {
Load({}, nullptr);
}
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 don't want to add wrapper functions for this only case you can pass a capturing reply builder into ti

Copy link
Contributor

Choose a reason for hiding this comment

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

But I suggest not to and instead make an error-reply returning internal function 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just overloaded Load :)

Comment on lines 231 to 232
@pytest.mark.asyncio
async def test_bad_acl_file(df_local_factory):
Copy link
Contributor

Choose a reason for hiding this comment

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

you can use @dfly_args to pass an acl path

Copy link
Contributor

Choose a reason for hiding this comment

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

and lets create a data folder inside the tests folder for your test acl configs

@kostasrim kostasrim self-assigned this Sep 8, 2023
Comment on lines +990 to +994
for (; it < dispatch_q_.end(); ++it) {
if (!std::holds_alternative<AclUpdateMessage>(it->handle)) {
break;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

while (it < end && holds<Acl>(it)>) ++it would be simpler 🙂

@@ -80,8 +80,8 @@ class Connection : public util::Connection {
struct MonitorMessage : public std::string {};

struct AclUpdateMessage {
std::string_view username;
uint64_t categories{0};
std::vector<std::string> username;
Copy link
Contributor

Choose a reason for hiding this comment

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

No 🤣

Comment on lines +262 to +264
"aclfile": os.environ.get(
"DRAGONFLY_PATH", os.path.join(SCRIPTS_DIR, "../../build-dbg/ok.acl")
),
Copy link
Contributor

@dranikpg dranikpg Sep 8, 2023

Choose a reason for hiding this comment

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

I meant keeping it inside the pytests folder... It looks kinda fragile. What if its not run from build-dbg? What if I want to edit it? Then I have to search it. And once I edit it the next re-build will overwrite it. So I need to update it in the src/folder... and re-build to apply 🤯

Copy link
Contributor

Choose a reason for hiding this comment

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

Btw ok.acl is empty 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Btw ok.acl is empty

yes it's meant to be like that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It looks kinda fragile. What if its not run from build-dbg?

It is fragile but we use the exact same thing to run the tests so I guess it's fine ? (See df_factory fixture)

Any other recommendation ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also you can set the env variable DRAGONFLY_PATH which overwrites this, so it's fine. We do the exact same thing in the CI as well:

34 export DRAGONFLY_PATH="${GITHUB_WORKSPACE}/${{inputs.build-folder-name}}/${{inputs.dfly-executable}}"

Comment on lines +213 to +214
void AclFamily::StreamUpdatesToAllProactorConnections(const std::vector<std::string>& user,
const std::vector<uint32_t>& update_cat) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is called for load and acl changes that occur rarely right? If it ever becomes a bottleneck you can pass the message data inside a shared_ptr so you don't have to copy the vectors every time

Copy link
Contributor

Choose a reason for hiding this comment

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

and single changes are now propagated with a vector...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Single changes are indeed a vector with a single element, this is insignificant....

This is called for load and acl changes that occur rarely right? If it ever becomes a bottleneck you can pass the message data inside a shared_ptr so you don't have to copy the vectors every time

Yes but I don't think it will so I opted in for the simplest change!

Comment on lines +391 to +394
void AclFamily::Load() {
auto acl_file = absl::GetFlag(FLAGS_aclfile);
LoadToRegistryFromFile(acl_file, true);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

So what if it fails? The instance will wrongfully start without acl

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nope, it's fine, this is what Redis is doing. Otherwise we have to crash, I don't want to crash DF for that.

Moreover, you can set the ACL file dynamically, via CONFIG SET

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We issue a warning and that's enough information :)

Comment on lines +147 to +148
template <typename T>
std::variant<User::UpdateRequest, ErrorReply> ParseAclSetUser(T args, bool hashed = false) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Small nit: Maybe use absl::Span<T>

Just a random thought, using the parser would solve the problem because it could hide the mutability (if an argslice constructor is added)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will refactor it at some point, I am expecting to add some changes here so I don't want to refactor right now

@kostasrim kostasrim merged commit 48488c5 into main Sep 8, 2023
7 checks passed
@kostasrim kostasrim deleted the acl_part_9_load_store branch September 8, 2023 11:20
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.

Add persistence via load/store
2 participants