-
Notifications
You must be signed in to change notification settings - Fork 5
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
[DCJ-386] Register Azure Managed Resource Group with SAM #1697
base: develop
Are you sure you want to change the base?
Changes from 4 commits
a16e7ca
1b8e36b
4f259e0
bc7c019
9a693ca
7cd628e
57bef66
06a1409
dc28b86
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -30,6 +30,7 @@ | |||||||||||||||||
import java.util.List; | ||||||||||||||||||
import java.util.Set; | ||||||||||||||||||
import java.util.UUID; | ||||||||||||||||||
import org.broadinstitute.dsde.workbench.client.sam.model.ManagedResourceGroupCoordinates; | ||||||||||||||||||
import org.slf4j.Logger; | ||||||||||||||||||
import org.slf4j.LoggerFactory; | ||||||||||||||||||
import org.springframework.beans.factory.annotation.Autowired; | ||||||||||||||||||
|
@@ -303,4 +304,17 @@ public void verifyDeployedApplication( | |||||||||||||||||
+ "operation"); | ||||||||||||||||||
} | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
public void registerManagedResourceGroup( | ||||||||||||||||||
BillingProfileRequestModel request, AuthenticatedUserRequest user) { | ||||||||||||||||||
String billingProfileId = request.getBillingAccountId(); | ||||||||||||||||||
ManagedResourceGroupCoordinates managedResourceGroupCoordinates = | ||||||||||||||||||
new ManagedResourceGroupCoordinates() | ||||||||||||||||||
.tenantId(request.getTenantId().toString()) | ||||||||||||||||||
.subscriptionId(request.getSubscriptionId().toString()) | ||||||||||||||||||
.managedResourceGroupName(request.getResourceGroupName()); | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had left this remark in the ticket:
I was specifically wondering if TDR's There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not really sure how to address this issue. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Azure service has the following:
I'm not sure if this is safe to access from the running steps, however. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you are on the right track. The request body may not contain the MRG name, but this is something TDR can obtain through interactions with the Azure SDK… and the snippet you found shows that there is precedence elsewhere in the code for doing just that. (BTW -- where possible to link to snippets from the existing codebase, that would be much appreciated to make sure that we're looking at the same thing, and leave a trail of breadcrumbs for those perusing this PR in the future.) The snippet you shared looks to come from Line 88 in 3198570
I may be missing historical reasoning, but it makes more sense to me to register an application deployment as part of creating an Azure billing profile, as a step within the flight that can also delete the application deployment registration in its Any future attempts to create billing profiles from the same MRG would fail fast at billing profile creation rather than later on at dataset creation, which seems to be the desired effect: Lines 75 to 81 in 3198570
|
||||||||||||||||||
|
||||||||||||||||||
iamService.registerManagedResourceGroup( | ||||||||||||||||||
user, billingProfileId, managedResourceGroupCoordinates); | ||||||||||||||||||
} | ||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package bio.terra.service.profile.flight.create; | ||
|
||
import bio.terra.common.iam.AuthenticatedUserRequest; | ||
import bio.terra.model.BillingProfileRequestModel; | ||
import bio.terra.service.profile.ProfileService; | ||
import bio.terra.stairway.FlightContext; | ||
import bio.terra.stairway.Step; | ||
import bio.terra.stairway.StepResult; | ||
import bio.terra.stairway.exception.RetryException; | ||
|
||
public class CreateProfileManagedResourceGroup implements Step { | ||
|
||
private final ProfileService profileService; | ||
private final BillingProfileRequestModel request; | ||
private final AuthenticatedUserRequest user; | ||
|
||
public CreateProfileManagedResourceGroup( | ||
ProfileService profileService, | ||
BillingProfileRequestModel request, | ||
AuthenticatedUserRequest user) { | ||
this.profileService = profileService; | ||
this.request = request; | ||
this.user = user; | ||
} | ||
|
||
@Override | ||
public StepResult doStep(FlightContext flightContext) | ||
throws InterruptedException, RetryException { | ||
profileService.registerManagedResourceGroup(request, user); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had left this question in the ticket:
Looking at the documented responses, it will return a 409: https://sam.dsde-prod.broadinstitute.org/#/Azure/createManagedResourceGroup Flagging this as I'm not sure if this will end up proving problematic in the current setup for our |
||
return StepResult.getStepResultSuccess(); | ||
} | ||
|
||
@Override | ||
public StepResult undoStep(FlightContext flightContext) throws InterruptedException { | ||
// Registering the Managed Resource Group has no side effects to clean up | ||
return StepResult.getStepResultSuccess(); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There actually is a side effect to clean up: you can call Sam to delete the MRG registration. Here's that endpoint: https://sam.dsde-prod.broadinstitute.org/#/Azure/deleteManagedResourceGroup But you could ask in #dsp-identiteam if deleting the Sam profile resource would also delete any MRG registration associated with that billing profile. If that's the case, then a no-op There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have a larger problem with making the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this is a problem, but we do need to change where this step runs. The Then when a flight is moving forward:
If a flight is rolled back, it walks backwards through the steps to undo:
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package bio.terra.service.profile.azure; | ||
|
||
import static org.hamcrest.MatcherAssert.assertThat; | ||
import static org.hamcrest.Matchers.equalTo; | ||
import static org.mockito.Mockito.verify; | ||
|
||
import bio.terra.common.category.Unit; | ||
import bio.terra.common.fixtures.AuthenticationFixtures; | ||
import bio.terra.common.iam.AuthenticatedUserRequest; | ||
import bio.terra.model.BillingProfileRequestModel; | ||
import bio.terra.service.profile.ProfileService; | ||
import bio.terra.service.profile.flight.create.CreateProfileManagedResourceGroup; | ||
import bio.terra.stairway.FlightContext; | ||
import bio.terra.stairway.StepResult; | ||
import bio.terra.stairway.StepStatus; | ||
import java.util.UUID; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Tag; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.mockito.Mock; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
|
||
@ExtendWith(MockitoExtension.class) | ||
@Tag(Unit.TAG) | ||
public class CreateProfileManagedResourceGroupStepTest { | ||
@Mock private ProfileService profileService; | ||
@Mock private FlightContext flightContext; | ||
|
||
private static final AuthenticatedUserRequest TEST_USER = | ||
AuthenticationFixtures.randomUserRequest(); | ||
|
||
private static final UUID BILLING_PROFILE_ID = UUID.randomUUID(); | ||
|
||
private BillingProfileRequestModel request; | ||
private CreateProfileManagedResourceGroup step; | ||
|
||
@BeforeEach | ||
void setup() { | ||
request = new BillingProfileRequestModel().id(BILLING_PROFILE_ID); | ||
step = new CreateProfileManagedResourceGroup(profileService, request, TEST_USER); | ||
} | ||
|
||
@Test | ||
void testDoAndUndoStep() throws InterruptedException { | ||
StepResult doResult = step.doStep(flightContext); | ||
assertThat(doResult.getStepStatus(), equalTo(StepStatus.STEP_RESULT_SUCCESS)); | ||
verify(profileService).registerManagedResourceGroup(request, TEST_USER); | ||
StepResult undoResult = step.undoStep(flightContext); | ||
assertThat(undoResult.getStepStatus(), equalTo(StepStatus.STEP_RESULT_SUCCESS)); | ||
} | ||
} |
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.
A
BillingProfileRequestModel
only has abillingAccountId
supplied when a GCP billing profile is being created -- it's the ID of the GCP billing account to wrap. For Azure billing profile creation, it is unspecified. I suspect this is why yourAzureIntegrationTests
are failing with this error:https://scans.gradle.com/s/da5olvhqbaima/tests/overview?outcome=FAILED
What this endpoint is expecting is the ID of the Sam
spend-profile
resource created in this flight. I believe that it needs the Sam resource to already exist. Do you know where that Sam resource creation takes place in the flight?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.
CreateProfileAuthzIamStep
seems to ultimately callsamResourceApi.createResourceV2(IamResourceType.SPEND_PROFILE.toString(), req);
.req
usesrequest.getId().toString()
as theprofileId
. However,.getId()
is deprecated, so this is a bit confusing to me.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.
I agree, it's a bit confusing!
Here's the past PR where we deprecated this ID in the request, with more context on the history: #1370
The first step in the billing profile creation flight will generate a UUID for the
sam-profile
and stores it in the request object if one doesn't already exist:jade-data-repo/src/main/java/bio/terra/service/profile/flight/create/GetOrCreateProfileIdStep.java
Lines 18 to 21 in d8d53ce
But the ID is only supplied to Sam to create the resource in Sam later in the flight, which looks to happen in
CreateProfileAuthzIamStep
.