-
Notifications
You must be signed in to change notification settings - Fork 1
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: Scan files when a single server is online #42
Conversation
This commits makes sure that even when a single server is online, the plugin is available. This commit also makes sure that a random and online server is chosen when using with_session without any specified socket. It used to use the first one.
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.
Any chances this could be tested? 🤔
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 is more or less what I had in mind but we need some more changes. Right now, #with_session
closes the socket, so the available socket you find cannot be used to scan a file.
We should change Besides any test we could write for this, we need to try it locally just to be sure it will work as we expect. We completely mock ClamAV on tests. |
I do not think testing would help because we would have to mock all the socket-related logic and thus lose a lot of the benefits of testing. In other words, the tests would just check that the mocks behave as we want.
This is interesting, you mean pinging without a session and then reusing the same socket to do the scan, right? I will also try to run ClamAV in Docker and test it with that. |
Yes, doing the PING without going through I believe we'll also need a timeout In our |
I am not sure it works using the same socket for PING and some other commands. I tried it like this, but the last response looks empty.
|
@romanrizzi, I looked into this further and I have found out that only one command can be sent on a socket and then we must close it and reopen it unless we use the sessions. This is strange because it means we must put the PING inside the session and make sure we don't close the session if we want to scan a file. |
We'll have to organize things differently to iterate over different connections and use it only if ClamAV is online. Here's how I imagine this should work:
class ClamAVServicesPool
def on_online_target
response = nil
service_instance.targets.each do |target|
socket = build_socket(target)
next if socket.nil?
response = yield(socket)
break if response
end
response
end
end
class ClamAV
def ping(socket)
write_in_socket(socket, "zPING\0")
end
def accepting_connections?
response = clamav_services_pool.on_online_target do |socket|
with_session(socket) { ping(socket) }
end
available = response.present? && clean_msg(response) == "PONG"
update_status(!available)
available
end
end Of course, this is the easiest part but the spirit of the example is that we separate responsabilities: |
I think I have a better suggestion and that is to refactor However, I did not get yet to fix the specs, but I manually tested it and it works well. |
@nbianca - I reorganized the code a bit following your suggestion! Although they are a multiple entities playing different roles, I think this makes the code easier to follow. Please feel free to revert or make any changes you want if you think there's a better solution. |
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.
@romanrizzi, I like the changes. Do you think we can merge it?
This change builds upon Bianca's idea of create the `ClamAVService` class and reorganized the code based on the following rationale: `ClamAV` is what glues everything together. It knows how to talk to the S3 store, the plugin store and the `ClamAVService` to display the version, check availability, and scan files. It gets the raw response from ClamAV and translates to a different format which the rest of the plugin relies on. `ClamAVService` defines an interface of which operations are possible (`online?`, `scan_file`, `version`) and takes care of the socket and session managemente, as well as writting/reading from the socket. `ClamAVServicePool` resolves the SRV record and instantiates existing services. It tells them how to open a connection. While working on this, I tried to remove the latter and do everything using only the first two, but I decided to keep it in the end because this design is handy for testing. We rely on the `FakeTCPSocket` for spying on the communication and returning specific responses, and this design let us use without relying on a mocking framework, just dependency injection.
This commits makes sure that even when a single server is online, the plugin is available. This commit also makes sure that a random and online server is chosen when using with_session without any specified socket. It used to use the first one.