From 1378fcfc15b2e7a4bc0fc28bf252259204fbbe95 Mon Sep 17 00:00:00 2001 From: Philip Kalinsky Date: Tue, 28 Jan 2020 15:06:48 -0500 Subject: [PATCH] merge conflict --- atst/domain/csp/cloud/azure_cloud_provider.py | 35 ++++++++++-------- atst/domain/csp/cloud/mock_cloud_provider.py | 37 +++++-------------- atst/domain/csp/cloud/models.py | 8 ++++ atst/domain/environments.py | 2 +- atst/jobs.py | 36 +++++++----------- tests/domain/cloud/test_azure_csp.py | 10 +++-- 6 files changed, 57 insertions(+), 71 deletions(-) diff --git a/atst/domain/csp/cloud/azure_cloud_provider.py b/atst/domain/csp/cloud/azure_cloud_provider.py index d5ef5204..908474ab 100644 --- a/atst/domain/csp/cloud/azure_cloud_provider.py +++ b/atst/domain/csp/cloud/azure_cloud_provider.py @@ -24,6 +24,8 @@ from .models import ( BillingProfileTenantAccessCSPResult, BillingProfileVerificationCSPPayload, BillingProfileVerificationCSPResult, + EnvironmentCSPPayload, + EnvironmentCSPResult, KeyVaultCredentials, ManagementGroupCSPResponse, ProductPurchaseCSPPayload, @@ -135,24 +137,25 @@ class AzureCloudProvider(CloudProviderInterface): exc_info=1, ) - def create_environment(self, auth_credentials: Dict, user, environment): - # since this operation would only occur within a tenant, should we source the tenant - # via lookup from environment once we've created the portfolio csp data schema - # something like this: - # environment_tenant = environment.application.portfolio.csp_data.get('tenant_id', None) - # though we'd probably source the whole credentials for these calls from the portfolio csp - # data, as it would have to be where we store the creds for the at-at user within the portfolio tenant - # credentials = self._get_credential_obj(environment.application.portfolio.csp_data.get_creds()) - credentials = self._get_credential_obj(self._root_creds) - display_name = f"{environment.application.name}_{environment.name}_{environment.id}" # proposed format - management_group_id = "?" # management group id chained from environment - parent_id = "?" # from environment.application - - management_group = self._create_management_group( - credentials, management_group_id, display_name, parent_id, + def create_environment(self, payload: EnvironmentCSPPayload): + creds = self._source_creds(payload.tenant_id) + credentials = self._get_credential_obj( + { + "client_id": creds.root_sp_client_id, + "secret_key": creds.root_sp_key, + "tenant_id": creds.root_tenant_id, + }, + resource=AZURE_MANAGEMENT_API, ) - return ManagementGroupCSPResponse(**management_group) + response = self._create_management_group( + credentials, + payload.management_group_name, + payload.display_name, + payload.parent_id, + ) + + return EnvironmentCSPResult(**response) def create_atat_admin_user( self, auth_credentials: Dict, csp_environment_id: str diff --git a/atst/domain/csp/cloud/mock_cloud_provider.py b/atst/domain/csp/cloud/mock_cloud_provider.py index ec730a3b..5b9a8b34 100644 --- a/atst/domain/csp/cloud/mock_cloud_provider.py +++ b/atst/domain/csp/cloud/mock_cloud_provider.py @@ -35,6 +35,8 @@ from .models import ( SubscriptionCreationCSPResult, SubscriptionVerificationCSPPayload, SuscriptionVerificationCSPResult, + EnvironmentCSPPayload, + EnvironmentCSPResult, TaskOrderBillingCreationCSPPayload, TaskOrderBillingCreationCSPResult, TaskOrderBillingVerificationCSPPayload, @@ -91,34 +93,6 @@ class MockCloudProvider(CloudProviderInterface): def get_secret(self, secret_key: str, default=dict()): return default - def create_environment(self, auth_credentials, user, environment): - self._authorize(auth_credentials) - - self._delay(1, 5) - self._maybe_raise(self.NETWORK_FAILURE_PCT, self.NETWORK_EXCEPTION) - self._maybe_raise(self.SERVER_FAILURE_PCT, self.SERVER_EXCEPTION) - self._maybe_raise( - self.ENV_CREATE_FAILURE_PCT, - EnvironmentCreationException( - environment.id, "Could not create environment." - ), - ) - - csp_environment_id = self._id() - - self._delay(1, 5) - self._maybe_raise(self.NETWORK_FAILURE_PCT, self.NETWORK_EXCEPTION) - self._maybe_raise(self.SERVER_FAILURE_PCT, self.SERVER_EXCEPTION) - self._maybe_raise( - self.ATAT_ADMIN_CREATE_FAILURE_PCT, - BaselineProvisionException( - csp_environment_id, "Could not create environment baseline." - ), - ) - self._maybe_raise(self.UNAUTHORIZED_RATE, self.AUTHORIZATION_EXCEPTION) - - return csp_environment_id - def create_subscription(self, payload: SubscriptionCreationCSPPayload): return self.create_subscription_creation(payload) @@ -482,6 +456,13 @@ class MockCloudProvider(CloudProviderInterface): return UserCSPResult(id=str(uuid4())) + def create_environment(self, payload: EnvironmentCSPPayload): + self._maybe_raise(self.UNAUTHORIZED_RATE, GeneralCSPException) + + return EnvironmentCSPResult( + id=f"{AZURE_MGMNT_PATH}{payload.management_group_name}" + ) + def get_credentials(self, scope="portfolio", tenant_id=None): return self.root_creds() diff --git a/atst/domain/csp/cloud/models.py b/atst/domain/csp/cloud/models.py index 188c2cc7..05f3c866 100644 --- a/atst/domain/csp/cloud/models.py +++ b/atst/domain/csp/cloud/models.py @@ -358,6 +358,14 @@ class ApplicationCSPResult(ManagementGroupCSPResponse): pass +class EnvironmentCSPPayload(ManagementGroupCSPPayload): + pass + + +class EnvironmentCSPResult(ManagementGroupCSPResponse): + pass + + class KeyVaultCredentials(BaseModel): root_sp_client_id: Optional[str] root_sp_key: Optional[str] diff --git a/atst/domain/environments.py b/atst/domain/environments.py index b8a59485..78aa2af3 100644 --- a/atst/domain/environments.py +++ b/atst/domain/environments.py @@ -124,7 +124,7 @@ class Environments(object): Any environment with an active CLIN that doesn't yet have a `cloud_id`. """ results = ( - cls.base_provision_query(now).filter(Environment.cloud_id == None).all() + cls.base_provision_query(now).filter(Application.cloud_id != None).all() ) return [id_ for id_, in results] diff --git a/atst/jobs.py b/atst/jobs.py index 986b2004..c2e2d03e 100644 --- a/atst/jobs.py +++ b/atst/jobs.py @@ -12,7 +12,11 @@ from atst.domain.portfolios import Portfolios from atst.domain.application_roles import ApplicationRoles from atst.models.utils import claim_for_update, claim_many_for_update from atst.utils.localization import translate -from atst.domain.csp.cloud.models import ApplicationCSPPayload, UserCSPPayload +from atst.domain.csp.cloud.models import ( + ApplicationCSPPayload, + EnvironmentCSPPayload, + UserCSPPayload, +) class RecordFailure(celery.Task): @@ -109,34 +113,20 @@ def do_create_environment(csp: CloudProviderInterface, environment_id=None): with claim_for_update(environment) as environment: if environment.cloud_id is not None: - # TODO: Return value for this? return - user = environment.creator + csp_details = environment.application.portfolio.csp_data + parent_id = environment.application.cloud_id + tenant_id = csp_details.get("tenant_id") + payload = EnvironmentCSPPayload( + tenant_id=tenant_id, display_name=application.name, parent_id=parent_id + ) - # we'll need to do some checking in this job for cases where it's retrying - # when a failure occured after some successful steps - # (e.g. if environment.cloud_id is not None, then we can skip first step) - - # credentials either from a given user or pulled from config? - # if using global creds, do we need to log what user authorized action? - atat_root_creds = csp.root_creds() - - # user is needed because baseline root account in the environment will - # be assigned to the requesting user, open question how to handle duplicate - # email addresses across new environments - csp_environment_id = csp.create_environment(atat_root_creds, user, environment) - environment.cloud_id = csp_environment_id + env_result = csp.create_environment(payload) + environment.cloud_id = env_result.id db.session.add(environment) db.session.commit() - body = render_email( - "emails/application/environment_ready.txt", {"environment": environment} - ) - app.mailer.send( - [environment.creator.email], translate("email.environment_ready"), body - ) - def do_create_atat_admin_user(csp: CloudProviderInterface, environment_id=None): environment = Environments.get(environment_id) diff --git a/tests/domain/cloud/test_azure_csp.py b/tests/domain/cloud/test_azure_csp.py index eef5620e..639997b3 100644 --- a/tests/domain/cloud/test_azure_csp.py +++ b/tests/domain/cloud/test_azure_csp.py @@ -20,6 +20,8 @@ from atst.domain.csp.cloud.models import ( BillingProfileTenantAccessCSPResult, BillingProfileVerificationCSPPayload, BillingProfileVerificationCSPResult, + EnvironmentCSPPayload, + EnvironmentCSPResult, ProductPurchaseCSPPayload, ProductPurchaseCSPResult, ProductPurchaseVerificationCSPPayload, @@ -57,12 +59,14 @@ def mock_management_group_create(mock_azure, spec_dict): def test_create_environment_succeeds(mock_azure: AzureCloudProvider): environment = EnvironmentFactory.create() - mock_management_group_create(mock_azure, {"id": "Test Id"}) - result = mock_azure.create_environment( - AUTH_CREDENTIALS, environment.creator, environment + mock_azure = mock_get_secret(mock_azure, lambda *a, **k: json.dumps(MOCK_CREDS)) + + payload = EnvironmentCSPPayload( + tenant_id="1234", display_name=environment.name, parent_id=str(uuid4()) ) + result = mock_azure.create_environment(payload) assert result.id == "Test Id"