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

WOR-1823 part 3: workspace deletion refactoring #3049

Open
wants to merge 38 commits into
base: develop
Choose a base branch
from

Conversation

blakery
Copy link
Contributor

@blakery blakery commented Sep 27, 2024

Ticket: https://broadworkbench.atlassian.net/browse/WOR-1823

Refactors workspace deletion and adds unit tests.


PR checklist

  • Include the JIRA issue number in the PR description and title
  • Make sure Swagger is updated if API changes
    • ...and Orchestration's Swagger too!
  • If you changed anything in model/, then you should publish a new official rawls-model and update rawls-model in Orchestration's dependencies.
  • Get two thumbsworth of PR review
  • Verify all tests go green, including CI tests
  • Squash commits and merge to develop (branches are automatically deleted after merging)
  • Inform other teams of any substantial changes via Slack and/or email

@@ -43,19 +46,6 @@ trait LibraryPermissionsSupport extends RoleSupport {
case _ => changeMetadataChecker(workspaceId) _
}

def withLibraryAttributeNamespaceCheck[T](attributeNames: Iterable[AttributeName])(op: => T): T = {
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 moved to WorkspaceService, since it is only called there.

val samDAO: SamDAO
val gcsDAO: GoogleServicesDAO
val ctx: RawlsRequestContext
Copy link
Contributor Author

Choose a reason for hiding this comment

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

These were being inherited by RoleSupport, but there's no real reason for this trait to be connected to it.

@@ -28,20 +28,4 @@ trait RoleSupport {
new RawlsExceptionWithErrorReport(errorReport = ErrorReport(StatusCodes.Forbidden, "You must be an admin."))
)
}

def tryIsCurator(userEmail: RawlsUserEmail): Future[Boolean] =
gcsDAO.isLibraryCurator(userEmail.value) recoverWith { case t =>
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 only used once, So I just moved it inline.

* @param f the operation to execute within the trace
* @return the result of the operation `f`
*/
def trace[T](name: String, parentContext: RawlsRequestContext)(f: RawlsRequestContext => T): T =
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not having this was pushing a lot of different places to use a Future where it wasn't really necessary.

Copy link
Contributor

Choose a reason for hiding this comment

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

This appears to be equivalent to traceNakedWithParent below

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's using RawlsTracingContext not RawlsRequestContext.

It's arguable that the better approach would be an overload or something, but we have similar divergence between others, such as between traceFutureWithParent and traceFuture.
Also, this is the most common/basic/unembellished instance of this, and therefore worth giving the most basic name. But I didn't feel like renaming usages of traceNakedWithParent in what is already a substantial PR.

@@ -17,19 +17,15 @@ import org.broadinstitute.dsde.rawls.entities.exceptions.{
import org.broadinstitute.dsde.rawls.expressions.ExpressionEvaluator
import org.broadinstitute.dsde.rawls.metrics.RawlsInstrumented
import org.broadinstitute.dsde.rawls.model.AttributeUpdateOperations.{AttributeUpdateOperation, EntityUpdateDefinition}
import org.broadinstitute.dsde.rawls.model.{
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The changes in this file are just from moving an exception definition to the place where it's thrown.

count: Int = 1,
labels: Map[String, String] = Map.empty,
description: Option[String] = None
): IO[Unit] = {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unneccesary IO wrapping - only called in one place anyway.


import dataSource.dataAccess.driver.api._

def getActiveWorkflowsAndSetStatusToAborted(
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 moved in wholesale from WorkspaceService.

* @throws AttributeUpdateOperationException when adding or removing from an attribute that is not a list
* @return the updated entity
*/
def applyOperationsToEntity(entity: Entity, operations: Seq[AttributeUpdateOperation]): Entity =
entity.copy(attributes = applyAttributeUpdateOperations(entity, operations))
}

class AttributeUpdateOperationException(message: String) extends RawlsException(message)
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 is the only place these are thrown, so it makes sense for them to be defined here.

val defaultRequestContext: RawlsRequestContext =
RawlsRequestContext(
UserInfo(RawlsUserEmail("test"), OAuth2BearerToken("Bearer 123"), 123, RawlsUserSubjectId("abc"))
val ctx: RawlsRequestContext = RawlsRequestContext(
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 got tired of having defaultRequestContext making practically every mock require a line break. Sorry about the resulting diff size.

@@ -79,7 +84,6 @@ import scala.jdk.DurationConverters.JavaDurationOps
import scala.language.postfixOps
import scala.util.Try

//noinspection NameBooleanParameters,TypeAnnotation,EmptyParenMethodAccessedAsParameterless,ScalaUnnecessaryParentheses,RedundantNewCaseClass,ScalaUnusedSymbol
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nearly all of the changes in this file are fixing ide warnings from removing this.

// Delete Google Project
_ <- traceFutureWithParent("deleteGoogleProject", ctx)(_ => deleteGoogleProject(workspace.googleProjectId))
// attempt to delete workspace in WSM, in case thsi is a TDR snapshot - but don't fail on it
_ = Try(workspaceManagerDAO.deleteWorkspace(workspace.workspaceIdAsUUID, ctx)).recover {
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 is the same behavior we had before, because we would only fail if it was a McWorkspace we were trying to delete, which would never happen, since those are handled by MultiCloudWorkspaceService.

@blakery blakery marked this pull request as ready for review September 30, 2024 14:52
@blakery blakery requested review from a team, cahrens and marctalbott and removed request for a team September 30, 2024 14:52
The only permission below WorkspaceAccessLevels.Read is NoAccess, which isn't realistic, since the user has at least read permissions to get this far.
Also, not making the additional call to Sam is purely an optimization - so better to just make the call to Sam.
this should be done by the MC workspace service
there's no longer any point keeping them separate, now that it's more concise
commit a793aa0
Author: Blake Geno <[email protected]>
Date:   Fri Sep 27 17:00:11 2024 -0400

    WOR-1823 part 2: listWorkspaces refactors (#3048)

    * break out shared processing of workspace response

    This allows getWorkspace and getWorkspaceById to share the processing logic, without getWorkspaceById calling getWorkspace directly.

    * refactor getWorkspaceDetails to use for comprehension

    * remove pointless transaction when getting bucket options

    * remove inspection supression, fix resulting issues

    * clean up getBucketUsage and add unit tests

    * clean up context parameters to reflect actual usage

    * disabled invalidated tests for getWorkspace(workspaceId)

    * move getBucketOptions next to getBucketUsage and use for comprehension for consistency

    * add test for getBucketOptions

    * move raw datasource calls to repository

    It's arguable we should create a new type of repository for this, but this will work for now. We can always split it out later.

    * eliminate some raw usages of datasource

    * moved admin methods to separate service

    * only retrieve transfers from queried workspace

    * move database operations for lock/unlock into repository

    * fixed unit tests for getWorkspaceById

    * removed unused method

    * clean up

    * moved only method usage of tryIsCurator inline

    * move only usage of withLibraryAttributeNamespaceCheck to calling service

    * decoupled LibraryPermissionsSupport from RoleSupport

    * simplified canShare resolution

    The only permission below WorkspaceAccessLevels.Read is NoAccess, which isn't realistic, since the user has at least read permissions to get this far.
    Also, not making the additional call to Sam is purely an optimization - so better to just make the call to Sam.

    * add method to list submissions, change single query to return an option

    * add convenience apply method to RawlsExceptionWithErrorReport

    * refactor list workspaces

    * add unit tests for listWorkspaces

    * scalafmt

    * fixed WorkspaceServiceSpec organization headers, clean up tests

    * updates from PR review

commit 729bb64
Author: Bria Morgan <[email protected]>
Date:   Fri Sep 27 13:03:32 2024 -0400

    AJ-2002 Render local-dev config with gsm instead of vault (#3044)

    * new render without .ctmpl
    * use dsde-dev
* @param f the operation to execute within the trace
* @return the result of the operation `f`
*/
def trace[T](name: String, parentContext: RawlsRequestContext)(f: RawlsRequestContext => T): T =
Copy link
Contributor

Choose a reason for hiding this comment

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

This appears to be equivalent to traceNakedWithParent below

leonardoService.cleanupResources(workspace.googleProjectId, workspace.workspaceIdAsUUID, ctx)
)
// Delete Google Project
_ <- traceFutureWithParent("deleteGoogleProject", ctx)(_ => deleteGoogleProject(workspace.googleProjectId))
Copy link
Contributor

Choose a reason for hiding this comment

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

There are technically still v1 workspaces in Rawls and this would bork all other v1 workspaces in a billing project by deleting the billing project's google project. Painful to have to leave it in given our stance on v1 workspaces, but as long as they're still around we probably need to keep the check

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If it was a v1 workspace, we'd never have gotten this far.
The first operation is getWorkspaceContextAndPermissions, which only returns v2 workspaces. So calling this endpoint on a v1 workspace would already return a NoSuchWorkspace exception.

Note: IIRC, v1 workspaces are not returned or treated as valid targets for any user-facing operation at this point.

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.

3 participants