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

[CA-1258] Add a status check to LdapRegistrationDAO and use to check openDJ #519

Merged
merged 14 commits into from
May 6, 2021

Conversation

s-rubenstein
Copy link
Contributor

Ticket:


PR checklist

@coveralls
Copy link

coveralls commented Apr 13, 2021

Coverage Status

Coverage decreased (-0.09%) to 78.448% when pulling 4f5fe60 on sr-status-check-open-dj into c34ff18 on develop.

val dbRef = TestSupport.dbRef
val directoryConfig: DirectoryConfig = TestSupport.directoryConfig
val dirURI = new URI(directoryConfig.directoryUrl)
val ldapConnectionPool = new LDAPConnectionPool(new LDAPConnection(dirURI.getHost, dirURI.getPort, directoryConfig.user, directoryConfig.password), directoryConfig.connectionPoolSize)
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'm a bit concerned about this, because there's no close on the pool? But also I don't know another way to ensure we are testing the real logic. Is there an afterAll or something hook in this file where cleanup can happen?

Copy link
Contributor

@gpolumbo-broad gpolumbo-broad left a comment

Choose a reason for hiding this comment

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

Didn't get a chance to finish reviewing before I had to run to meetings, but I had a comment here that I wanted to get out for discussion at least.

@@ -18,6 +17,7 @@ import scala.concurrent.{ExecutionContext, Future}

class StatusService(
val directoryDAO: DirectoryDAO,
val registrationDAO: RegistrationDAO,
Copy link
Contributor

Choose a reason for hiding this comment

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

Wondering if we shouldn't just be explicit here and say:

Suggested change
val registrationDAO: RegistrationDAO,
val ldapRegistrationDAO: LdapRegistrationDAO,

For this class, we don't want a generic RegistrationDAO, we explicitly need it to be an LdapRegistrationDAO in order to satisfy the business requirement. This will require a little refactoring in Boot.scala too I think, but I think it would be worth it. As it is here, I had to trace all the calls back through Boot.scala just to make sure we were passing in the right kind of RegistrationDAO here, which was annoying in itself, and also doesn't prevent anyone from accidentally breaking this again in the future.

I realize this will mess with tests where we use MockRegistrationDAO. I don't know the answer off the top of my head and maybe it's something we can sort out with a discussion/mob/pair to see if we can make this better in some way.

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 don't actually have a MockRegistrationDAO, interestingly enough! That said, I think changing it assumes that LDAP is how we communicate to our registration service. I might rather have it be checkRegistrationDBStatus rather than checkOpenDJStatus? Given that things changed with Postgres, I don't want to assume LDAP will be the way forwards forever.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed that we typically don't want to assume that LDAP will be the way forwards forever (I hope the RegistrationDAO goes away entirely one day). However, in this case, I'd argue that we want the StatusService checks to be implementation-specific. Keeping it generic was how we missed this in the first place and didn't check OpenDJ's status for >1 year. If we change the implementation of the RegistrationDAO, we'd want to be forced to change the StatusService to check the new implementation of it so that we couldn't accidentally leave it checking OpenDJ

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ack. That seems reasonable in rationale to me. I will make the change.

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 went down a rabbit hole on this, specifying it as LDAPRegistrationDao makes mocking it exceptionally hard, because SBT/Mockito doesn't know how to override a class, only the traits that we use. So the best we could do is spy on it and then override the spy. This is going to be super clunky across our tests. I think the best thing we can do is to rename the variable and make a comment, which will be both simpler, and also provide a check for us against future changes.

Comment on lines 768 to 772
if (session.connection.isValid((2 seconds).toSeconds.intValue())) {
true
} else {
false
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This can be simplified by just returning session.connection.isValid((2 seconds).toSeconds.intValue())

private def newStatusService(directoryDAO: DirectoryDAO) = {
new StatusService(directoryDAO, new NoExtensions {
// We need to mock this because Postgres does some automatic setup and gets unhappy with multiple instances of its DAO existing at once.
private def mockDirectoryDAOWithPostgresStatusCheck(dbReferenceOverride: DbReference = dbReference) = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment here re: duplicating the checkStatus implementation

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So, this one we can't use the real postgres db, because postgres makes some assumptions that it will only get stood up once within the whole test suite, and we don't want to use a persistent postgres across all the suites here, because we want to have different DBRef objects to manage bringing it down or up, so we can't actually override directoryDao itself. (or at least, I couldn't figure out how to)

Copy link
Contributor

Choose a reason for hiding this comment

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

Could we fully mock out the DAOs here then? It doesn't feel right to be overriding our mocks with the real implementation. I'd prefer that we either use the real implementation with a real PostgresDirectoryDAO or we use the mock rather than relying on this combination. This goes for the MockDirectoryDAO in TestSamRoutes as well

@@ -18,6 +17,7 @@ import scala.concurrent.{ExecutionContext, Future}

class StatusService(
val directoryDAO: DirectoryDAO,
val registrationDAO: RegistrationDAO,
Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed that we typically don't want to assume that LDAP will be the way forwards forever (I hope the RegistrationDAO goes away entirely one day). However, in this case, I'd argue that we want the StatusService checks to be implementation-specific. Keeping it generic was how we missed this in the first place and didn't check OpenDJ's status for >1 year. If we change the implementation of the RegistrationDAO, we'd want to be forced to change the StatusService to check the new implementation of it so that we couldn't accidentally leave it checking OpenDJ

@s-rubenstein
Copy link
Contributor Author

Jenkins retest

@s-rubenstein
Copy link
Contributor Author

Jenkins retest

@s-rubenstein
Copy link
Contributor Author

Jenkins retest

.travis.yml Outdated
@@ -3,7 +3,7 @@ jdk:
dist: trusty
language: scala
scala:
- 2.13.5
- 2.12.8
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this related to the Github actions stuff?

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, will revert.

private def newStatusService(directoryDAO: DirectoryDAO) = {
new StatusService(directoryDAO, new NoExtensions {
// We need to mock this because Postgres does some automatic setup and gets unhappy with multiple instances of its DAO existing at once.
private def mockDirectoryDAOWithPostgresStatusCheck(dbReferenceOverride: DbReference = dbReference) = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we fully mock out the DAOs here then? It doesn't feel right to be overriding our mocks with the real implementation. I'd prefer that we either use the real implementation with a real PostgresDirectoryDAO or we use the mock rather than relying on this combination. This goes for the MockDirectoryDAO in TestSamRoutes as well

Copy link
Contributor

@gpolumbo-broad gpolumbo-broad left a comment

Choose a reason for hiding this comment

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

One method naming nit, but it's fine.

.travis.yml Outdated Show resolved Hide resolved
@@ -11,6 +12,7 @@ import org.broadinstitute.dsde.workbench.sam.util.SamRequestContext
* away from a solution that requires that the Apache proxies query this group, we can remove the RegistrationDAO.
*/
trait RegistrationDAO {
def getConnectionTarget(): ConnectionType
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not getConnectionType?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because I am bad at naming :D

@s-rubenstein
Copy link
Contributor Author

Jenkins retest

1 similar comment
@s-rubenstein
Copy link
Contributor Author

Jenkins retest

@s-rubenstein s-rubenstein merged commit 80f3066 into develop May 6, 2021
@s-rubenstein s-rubenstein deleted the sr-status-check-open-dj branch May 6, 2021 20:58
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.

None yet

4 participants