diff --git a/atst/domain/csp/cloud.py b/atst/domain/csp/cloud.py index 9f764da0..b04ed91f 100644 --- a/atst/domain/csp/cloud.py +++ b/atst/domain/csp/cloud.py @@ -341,6 +341,12 @@ class CloudProviderInterface: """ raise NotImplementedError() + def create_subscription(self, environment): + """Returns True if a new subscription has been created or raises an + exception if an error occurs while creating a subscription. + """ + raise NotImplementedError() + class MockCloudProvider(CloudProviderInterface): @@ -508,6 +514,11 @@ class MockCloudProvider(CloudProviderInterface): return self._maybe(12) + def create_subscription(self, environment): + self._maybe_raise(self.UNAUTHORIZED_RATE, GeneralCSPException) + + return True + def get_calculator_url(self): return "https://www.rackspace.com/en-us/calculator" diff --git a/atst/routes/applications/settings.py b/atst/routes/applications/settings.py index da04bc84..137af0d7 100644 --- a/atst/routes/applications/settings.py +++ b/atst/routes/applications/settings.py @@ -1,9 +1,10 @@ from flask import ( + current_app as app, + g, redirect, render_template, request as http_request, url_for, - g, ) from .blueprint import applications_bp @@ -522,3 +523,31 @@ def resend_invite(application_id, application_role_id): _anchor="application-members", ) ) + + +@applications_bp.route( + "/environments//add_subscription", methods=["POST"] +) +# TODO: decide what perms are needed to create a subscription +@user_can(Permissions.EDIT_ENVIRONMENT, message="create new environment subscription") +def create_subscription(environment_id): + environment = Environments.get(environment_id) + + try: + app.csp.cloud.create_subscription(environment) + + except GeneralCSPException: + flash("environment_subscription_failure") + return ( + render_settings_page(application=environment.application, show_flash=True), + 400, + ) + + return redirect( + url_for( + "applications.settings", + application_id=environment.application.id, + fragment="application-environments", + _anchor="application-environments", + ) + ) diff --git a/atst/utils/flash.py b/atst/utils/flash.py index 02a74cb2..8caf7ed8 100644 --- a/atst/utils/flash.py +++ b/atst/utils/flash.py @@ -83,6 +83,11 @@ MESSAGES = { "message": "flash.environment.deleted.message", "category": "success", }, + "environment_subscription_failure": { + "title": "flash.environment.subscription_failure.title", + "message": "flash.environment.subscription_failure.message", + "category": "error", + }, "form_errors": { "title": "flash.form.errors.title", "message": "flash.form.errors.message", diff --git a/tests/routes/applications/test_settings.py b/tests/routes/applications/test_settings.py index fe9823ab..37c71878 100644 --- a/tests/routes/applications/test_settings.py +++ b/tests/routes/applications/test_settings.py @@ -777,3 +777,40 @@ def test_handle_update_member_with_error(set_g, monkeypatch, mock_logger): handle_update_member(application.id, app_role.id, form_data) assert mock_logger.messages[-1] == exception + + +def test_create_subscription_success(client, user_session): + environment = EnvironmentFactory.create() + + user_session(environment.portfolio.owner) + response = client.post( + url_for("applications.create_subscription", environment_id=environment.id), + ) + + assert response.status_code == 302 + assert response.location == url_for( + "applications.settings", + application_id=environment.application.id, + _external=True, + fragment="application-environments", + _anchor="application-environments", + ) + + +def test_create_subscription_failure(client, user_session, monkeypatch): + environment = EnvironmentFactory.create() + + def _raise_csp_exception(*args, **kwargs): + raise GeneralCSPException("An error occurred.") + + monkeypatch.setattr( + "atst.domain.csp.cloud.MockCloudProvider.create_subscription", + _raise_csp_exception, + ) + + user_session(environment.portfolio.owner) + response = client.post( + url_for("applications.create_subscription", environment_id=environment.id), + ) + + assert response.status_code == 400 diff --git a/translations.yaml b/translations.yaml index 22165fb9..c6d3dbbc 100644 --- a/translations.yaml +++ b/translations.yaml @@ -127,6 +127,9 @@ flash: deleted: title: "{environment_name} deleted" message: The environment "{environment_name}" has been deleted + subscription_failure: + title: Environment subscription error + message: An unexpected problem occurred with your request, please try again. If the problem persists, contact an administrator. form: errors: title: There were some errors