Merge pull request #1062 from dod-ccpo/env-provisioning-task
Environment provisioning background jobs
This commit is contained in:
@@ -21,7 +21,7 @@ from tests.factories import (
|
||||
def test_create_application_with_multiple_environments():
|
||||
portfolio = PortfolioFactory.create()
|
||||
application = Applications.create(
|
||||
portfolio, "My Test Application", "Test", ["dev", "prod"]
|
||||
portfolio.owner, portfolio, "My Test Application", "Test", ["dev", "prod"]
|
||||
)
|
||||
|
||||
assert application.portfolio == portfolio
|
||||
|
@@ -1,4 +1,6 @@
|
||||
import pytest
|
||||
import pendulum
|
||||
from uuid import uuid4
|
||||
|
||||
from atst.domain.environments import Environments
|
||||
from atst.domain.environment_roles import EnvironmentRoles
|
||||
@@ -7,7 +9,6 @@ from atst.models.environment_role import CSPRole
|
||||
|
||||
from tests.factories import (
|
||||
ApplicationFactory,
|
||||
UserFactory,
|
||||
PortfolioFactory,
|
||||
EnvironmentFactory,
|
||||
EnvironmentRoleFactory,
|
||||
@@ -15,12 +16,13 @@ from tests.factories import (
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="Reinstate and update once jobs api is up")
|
||||
def test_create_environments():
|
||||
application = ApplicationFactory.create()
|
||||
environments = Environments.create_many(application, ["Staging", "Production"])
|
||||
environments = Environments.create_many(
|
||||
application.portfolio.owner, application, ["Staging", "Production"]
|
||||
)
|
||||
for env in environments:
|
||||
assert env.cloud_id is not None
|
||||
assert env.cloud_id is None
|
||||
|
||||
|
||||
def test_update_env_role():
|
||||
@@ -87,3 +89,125 @@ def test_update_environment():
|
||||
assert environment.name is not "name 2"
|
||||
Environments.update(environment, name="name 2")
|
||||
assert environment.name == "name 2"
|
||||
|
||||
|
||||
class EnvQueryTest:
|
||||
@property
|
||||
def NOW(self):
|
||||
return pendulum.now()
|
||||
|
||||
@property
|
||||
def YESTERDAY(self):
|
||||
return self.NOW.subtract(days=1)
|
||||
|
||||
@property
|
||||
def TOMORROW(self):
|
||||
return self.NOW.add(days=1)
|
||||
|
||||
def create_portfolio_with_clins(self, start_and_end_dates, env_data=None):
|
||||
env_data = env_data or {}
|
||||
return PortfolioFactory.create(
|
||||
applications=[
|
||||
{
|
||||
"name": "Mos Eisley",
|
||||
"description": "Where Han shot first",
|
||||
"environments": [{"name": "thebar", **env_data}],
|
||||
}
|
||||
],
|
||||
task_orders=[
|
||||
{
|
||||
"create_clins": [
|
||||
{"start_date": start_date, "end_date": end_date}
|
||||
for (start_date, end_date) in start_and_end_dates
|
||||
]
|
||||
}
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
class TestGetEnvironmentsPendingCreate(EnvQueryTest):
|
||||
def test_with_expired_clins(self, session):
|
||||
self.create_portfolio_with_clins([(self.YESTERDAY, self.YESTERDAY)])
|
||||
assert len(Environments.get_environments_pending_creation(self.NOW)) == 0
|
||||
|
||||
def test_with_active_clins(self, session):
|
||||
portfolio = self.create_portfolio_with_clins([(self.YESTERDAY, self.TOMORROW)])
|
||||
Environments.get_environments_pending_creation(self.NOW) == [
|
||||
portfolio.applications[0].environments[0].id
|
||||
]
|
||||
|
||||
def test_with_future_clins(self, session):
|
||||
self.create_portfolio_with_clins([(self.TOMORROW, self.TOMORROW)])
|
||||
assert len(Environments.get_environments_pending_creation(self.NOW)) == 0
|
||||
|
||||
def test_with_already_provisioned_env(self, session):
|
||||
self.create_portfolio_with_clins(
|
||||
[(self.YESTERDAY, self.TOMORROW)], env_data={"cloud_id": uuid4().hex}
|
||||
)
|
||||
assert len(Environments.get_environments_pending_creation(self.NOW)) == 0
|
||||
|
||||
|
||||
class TestGetEnvironmentsPendingAtatUserCreation(EnvQueryTest):
|
||||
def test_with_provisioned_environment(self):
|
||||
self.create_portfolio_with_clins(
|
||||
[(self.YESTERDAY, self.TOMORROW)],
|
||||
{"cloud_id": uuid4().hex, "root_user_info": {}},
|
||||
)
|
||||
assert (
|
||||
len(Environments.get_environments_pending_atat_user_creation(self.NOW)) == 0
|
||||
)
|
||||
|
||||
def test_with_unprovisioned_environment(self):
|
||||
self.create_portfolio_with_clins(
|
||||
[(self.YESTERDAY, self.TOMORROW)],
|
||||
{"cloud_id": uuid4().hex, "root_user_info": None},
|
||||
)
|
||||
assert (
|
||||
len(Environments.get_environments_pending_atat_user_creation(self.NOW)) == 1
|
||||
)
|
||||
|
||||
def test_with_unprovisioned_expired_clins_environment(self):
|
||||
self.create_portfolio_with_clins(
|
||||
[(self.YESTERDAY, self.YESTERDAY)],
|
||||
{"cloud_id": uuid4().hex, "root_user_info": None},
|
||||
)
|
||||
assert (
|
||||
len(Environments.get_environments_pending_atat_user_creation(self.NOW)) == 0
|
||||
)
|
||||
|
||||
|
||||
class TestGetEnvironmentsPendingBaselineCreation(EnvQueryTest):
|
||||
def test_with_provisioned_environment(self):
|
||||
self.create_portfolio_with_clins(
|
||||
[(self.YESTERDAY, self.TOMORROW)],
|
||||
{
|
||||
"cloud_id": uuid4().hex,
|
||||
"root_user_info": {"foo": "bar"},
|
||||
"baseline_info": {"foo": "bar"},
|
||||
},
|
||||
)
|
||||
assert (
|
||||
len(Environments.get_environments_pending_baseline_creation(self.NOW)) == 0
|
||||
)
|
||||
|
||||
def test_with_unprovisioned_environment(self):
|
||||
self.create_portfolio_with_clins(
|
||||
[(self.YESTERDAY, self.TOMORROW)],
|
||||
{
|
||||
"cloud_id": uuid4().hex,
|
||||
"root_user_info": {"foo": "bar"},
|
||||
"baseline_info": None,
|
||||
},
|
||||
)
|
||||
assert (
|
||||
len(Environments.get_environments_pending_baseline_creation(self.NOW)) == 1
|
||||
)
|
||||
|
||||
def test_with_unprovisioned_expired_clins_environment(self):
|
||||
self.create_portfolio_with_clins(
|
||||
[(self.YESTERDAY, self.YESTERDAY)],
|
||||
{"cloud_id": uuid4().hex, "root_user_info": {"foo": "bar"}},
|
||||
)
|
||||
assert (
|
||||
len(Environments.get_environments_pending_baseline_creation(self.NOW)) == 0
|
||||
)
|
||||
|
@@ -71,7 +71,11 @@ def test_update_portfolio_role_role(portfolio, portfolio_owner):
|
||||
|
||||
def test_scoped_portfolio_for_admin_missing_view_apps_perms(portfolio_owner, portfolio):
|
||||
Applications.create(
|
||||
portfolio, "My Application 2", "My application 2", ["dev", "staging", "prod"]
|
||||
portfolio.owner,
|
||||
portfolio,
|
||||
"My Application 2",
|
||||
"My application 2",
|
||||
["dev", "staging", "prod"],
|
||||
)
|
||||
restricted_admin = UserFactory.create()
|
||||
PortfolioRoleFactory.create(
|
||||
@@ -90,7 +94,11 @@ def test_scoped_portfolio_returns_all_applications_for_portfolio_admin(
|
||||
):
|
||||
for _ in range(5):
|
||||
Applications.create(
|
||||
portfolio, "My Application", "My application", ["dev", "staging", "prod"]
|
||||
portfolio.owner,
|
||||
portfolio,
|
||||
"My Application",
|
||||
"My application",
|
||||
["dev", "staging", "prod"],
|
||||
)
|
||||
|
||||
admin = UserFactory.create()
|
||||
@@ -109,7 +117,11 @@ def test_scoped_portfolio_returns_all_applications_for_portfolio_owner(
|
||||
):
|
||||
for _ in range(5):
|
||||
Applications.create(
|
||||
portfolio, "My Application", "My application", ["dev", "staging", "prod"]
|
||||
portfolio.owner,
|
||||
portfolio,
|
||||
"My Application",
|
||||
"My application",
|
||||
["dev", "staging", "prod"],
|
||||
)
|
||||
|
||||
scoped_portfolio = Portfolios.get(portfolio_owner, portfolio.id)
|
||||
|
@@ -139,7 +139,7 @@ def test_update_adds_clins():
|
||||
|
||||
def test_update_does_not_duplicate_clins():
|
||||
task_order = TaskOrderFactory.create(
|
||||
number="3453453456", create_clins=["123", "456"]
|
||||
number="3453453456", create_clins=[{"number": "123"}, {"number": "456"}]
|
||||
)
|
||||
clins = [
|
||||
{
|
||||
@@ -171,7 +171,9 @@ def test_update_does_not_duplicate_clins():
|
||||
|
||||
|
||||
def test_delete_task_order_with_clins(session):
|
||||
task_order = TaskOrderFactory.create(create_clins=[1, 2, 3])
|
||||
task_order = TaskOrderFactory.create(
|
||||
create_clins=[{"number": 1}, {"number": 2}, {"number": 3}]
|
||||
)
|
||||
TaskOrders.delete(task_order.id)
|
||||
|
||||
assert not session.query(
|
||||
|
@@ -118,6 +118,7 @@ class PortfolioFactory(Base):
|
||||
with_applications = kwargs.pop("applications", [])
|
||||
owner = kwargs.pop("owner", UserFactory.create())
|
||||
members = kwargs.pop("members", [])
|
||||
with_task_orders = kwargs.pop("task_orders", [])
|
||||
|
||||
portfolio = super()._create(model_class, *args, **kwargs)
|
||||
|
||||
@@ -126,6 +127,11 @@ class PortfolioFactory(Base):
|
||||
for p in with_applications
|
||||
]
|
||||
|
||||
task_orders = [
|
||||
TaskOrderFactory.create(portfolio=portfolio, **to)
|
||||
for to in with_task_orders
|
||||
]
|
||||
|
||||
PortfolioRoleFactory.create(
|
||||
portfolio=portfolio,
|
||||
user=owner,
|
||||
@@ -154,6 +160,7 @@ class PortfolioFactory(Base):
|
||||
)
|
||||
|
||||
portfolio.applications = applications
|
||||
portfolio.task_orders = task_orders
|
||||
return portfolio
|
||||
|
||||
|
||||
@@ -185,6 +192,7 @@ class EnvironmentFactory(Base):
|
||||
|
||||
name = factory.Faker("domain_word")
|
||||
application = factory.SubFactory(ApplicationFactory)
|
||||
creator = factory.SubFactory(UserFactory)
|
||||
|
||||
@classmethod
|
||||
def _create(cls, model_class, *args, **kwargs):
|
||||
@@ -278,7 +286,7 @@ class TaskOrderFactory(Base):
|
||||
task_order = super()._create(model_class, *args, **kwargs)
|
||||
|
||||
for clin in create_clins:
|
||||
CLINFactory.create(task_order=task_order, number=clin)
|
||||
CLINFactory.create(task_order=task_order, **clin)
|
||||
|
||||
return task_order
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import pytest
|
||||
|
||||
from atst.models import AuditEvent
|
||||
from atst.models.environment_role import CSPRole
|
||||
from atst.domain.environments import Environments
|
||||
from atst.domain.applications import Applications
|
||||
|
||||
from tests.factories import *
|
||||
@@ -12,7 +13,11 @@ def test_add_user_to_environment():
|
||||
|
||||
portfolio = PortfolioFactory.create(owner=owner)
|
||||
application = Applications.create(
|
||||
portfolio, "my test application", "It's mine.", ["dev", "staging", "prod"]
|
||||
portfolio.owner,
|
||||
portfolio,
|
||||
"my test application",
|
||||
"It's mine.",
|
||||
["dev", "staging", "prod"],
|
||||
)
|
||||
dev_environment = application.environments[0]
|
||||
|
||||
@@ -42,3 +47,29 @@ def test_audit_event_for_environment_deletion(session):
|
||||
before, after = update_event.changed_state["deleted"]
|
||||
assert not before
|
||||
assert after
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"env_data,expected_status",
|
||||
[
|
||||
[
|
||||
{"cloud_id": None, "root_user_info": None, "baseline_info": None},
|
||||
Environment.ProvisioningStatus.PENDING,
|
||||
],
|
||||
[
|
||||
{"cloud_id": 1, "root_user_info": None, "baseline_info": None},
|
||||
Environment.ProvisioningStatus.PENDING,
|
||||
],
|
||||
[
|
||||
{"cloud_id": 1, "root_user_info": {}, "baseline_info": None},
|
||||
Environment.ProvisioningStatus.PENDING,
|
||||
],
|
||||
[
|
||||
{"cloud_id": 1, "root_user_info": {}, "baseline_info": {}},
|
||||
Environment.ProvisioningStatus.COMPLETED,
|
||||
],
|
||||
],
|
||||
)
|
||||
def test_environment_provisioning_status(env_data, expected_status):
|
||||
environment = EnvironmentFactory.create(**env_data)
|
||||
assert environment.provisioning_status == expected_status
|
||||
|
@@ -70,6 +70,7 @@ def test_update_environment_failure(client, user_session):
|
||||
def test_application_settings(client, user_session):
|
||||
portfolio = PortfolioFactory.create()
|
||||
application = Applications.create(
|
||||
portfolio.owner,
|
||||
portfolio,
|
||||
"Snazzy Application",
|
||||
"A new application for me and my friends",
|
||||
@@ -85,6 +86,7 @@ def test_application_settings(client, user_session):
|
||||
def test_edit_application_environments_obj(app, client, user_session):
|
||||
portfolio = PortfolioFactory.create()
|
||||
application = Applications.create(
|
||||
portfolio.owner,
|
||||
portfolio,
|
||||
"Snazzy Application",
|
||||
"A new application for me and my friends",
|
||||
@@ -125,6 +127,7 @@ def test_edit_application_environments_obj(app, client, user_session):
|
||||
def test_data_for_app_env_roles_form(app, client, user_session):
|
||||
portfolio = PortfolioFactory.create()
|
||||
application = Applications.create(
|
||||
portfolio.owner,
|
||||
portfolio,
|
||||
"Snazzy Application",
|
||||
"A new application for me and my friends",
|
||||
|
@@ -29,7 +29,7 @@ def completed_task_order():
|
||||
task_order = TaskOrderFactory.create(
|
||||
creator=portfolio.owner,
|
||||
portfolio=portfolio,
|
||||
create_clins=["1234567890123456789012345678901234567890123"],
|
||||
create_clins=[{"number": "1234567890123456789012345678901234567890123"}],
|
||||
)
|
||||
|
||||
return task_order
|
||||
@@ -334,7 +334,7 @@ def test_task_orders_submit_task_order(client, user_session, task_order):
|
||||
({"_pdf": None, "number": "", "clins": []}, "step_1"),
|
||||
({"number": "", "clins": []}, "step_2"),
|
||||
({"number": "1234567890123", "clins": []}, "step_3"),
|
||||
({"number": "1234567890123", "create_clins": [1]}, "step_4"),
|
||||
({"number": "1234567890123", "create_clins": [{"number": 1}]}, "step_4"),
|
||||
],
|
||||
)
|
||||
def test_task_orders_edit_redirects_to_latest_incomplete_step(
|
||||
|
@@ -504,7 +504,7 @@ def test_task_orders_new_get_routes(get_url_assert_status):
|
||||
task_order = TaskOrderFactory.create(
|
||||
creator=owner,
|
||||
portfolio=portfolio,
|
||||
create_clins=["1234567890123456789012345678901234567890123"],
|
||||
create_clins=[{"number": "1234567890123456789012345678901234567890123"}],
|
||||
)
|
||||
|
||||
for route in get_routes:
|
||||
|
@@ -1,8 +1,26 @@
|
||||
import pendulum
|
||||
import pytest
|
||||
from uuid import uuid4
|
||||
from unittest.mock import Mock
|
||||
|
||||
from atst.jobs import RecordEnvironmentFailure, RecordEnvironmentRoleFailure
|
||||
|
||||
from tests.factories import EnvironmentFactory, EnvironmentRoleFactory
|
||||
from atst.models import Environment
|
||||
from atst.domain.csp.cloud import MockCloudProvider
|
||||
from atst.jobs import (
|
||||
RecordEnvironmentFailure,
|
||||
RecordEnvironmentRoleFailure,
|
||||
do_create_environment,
|
||||
do_create_atat_admin_user,
|
||||
do_create_environment_baseline,
|
||||
dispatch_create_environment,
|
||||
dispatch_create_atat_admin_user,
|
||||
dispatch_create_environment_baseline,
|
||||
)
|
||||
from tests.factories import (
|
||||
EnvironmentFactory,
|
||||
EnvironmentRoleFactory,
|
||||
UserFactory,
|
||||
PortfolioFactory,
|
||||
)
|
||||
|
||||
|
||||
def test_environment_job_failure(celery_app, celery_worker):
|
||||
@@ -39,3 +57,142 @@ def test_environment_role_job_failure(celery_app, celery_worker):
|
||||
assert role.job_failures
|
||||
job_failure = role.job_failures[0]
|
||||
assert job_failure.task == task
|
||||
|
||||
|
||||
now = pendulum.now()
|
||||
yesterday = now.subtract(days=1)
|
||||
tomorrow = now.add(days=1)
|
||||
from atst.domain.environments import Environments
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="function")
|
||||
def csp():
|
||||
return Mock(wraps=MockCloudProvider({}, with_delay=False, with_failure=False))
|
||||
|
||||
|
||||
def test_create_environment_job(session, csp):
|
||||
user = UserFactory.create()
|
||||
environment = EnvironmentFactory.create()
|
||||
do_create_environment(csp, environment.id, user.id)
|
||||
|
||||
environment_id = environment.id
|
||||
del environment
|
||||
|
||||
updated_environment = session.query(Environment).get(environment_id)
|
||||
|
||||
assert updated_environment.cloud_id
|
||||
|
||||
|
||||
def test_create_environment_job_is_idempotent(csp, session):
|
||||
user = UserFactory.create()
|
||||
environment = EnvironmentFactory.create(cloud_id=uuid4().hex)
|
||||
do_create_environment(csp, environment.id, user.id)
|
||||
|
||||
csp.create_environment.assert_not_called()
|
||||
|
||||
|
||||
def test_create_atat_admin_user(csp, session):
|
||||
environment = EnvironmentFactory.create(cloud_id="something")
|
||||
do_create_atat_admin_user(csp, environment.id)
|
||||
|
||||
environment_id = environment.id
|
||||
del environment
|
||||
updated_environment = session.query(Environment).get(environment_id)
|
||||
|
||||
assert updated_environment.root_user_info
|
||||
|
||||
|
||||
def test_create_environment_baseline(csp, session):
|
||||
environment = EnvironmentFactory.create(
|
||||
root_user_info={"credentials": csp.root_creds()}
|
||||
)
|
||||
do_create_environment_baseline(csp, environment.id)
|
||||
|
||||
environment_id = environment.id
|
||||
del environment
|
||||
updated_environment = session.query(Environment).get(environment_id)
|
||||
|
||||
assert updated_environment.baseline_info
|
||||
|
||||
|
||||
def test_dispatch_create_environment(session, monkeypatch):
|
||||
portfolio = PortfolioFactory.create(
|
||||
applications=[{"environments": [{}]}],
|
||||
task_orders=[
|
||||
{
|
||||
"create_clins": [
|
||||
{
|
||||
"start_date": pendulum.now().subtract(days=1),
|
||||
"end_date": pendulum.now().add(days=1),
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
)
|
||||
mock = Mock()
|
||||
monkeypatch.setattr("atst.jobs.create_environment", mock)
|
||||
environment = portfolio.applications[0].environments[0]
|
||||
|
||||
dispatch_create_environment.run()
|
||||
|
||||
mock.delay.assert_called_once_with(
|
||||
environment_id=environment.id, atat_user_id=environment.creator_id
|
||||
)
|
||||
|
||||
|
||||
def test_dispatch_create_atat_admin_user(session, monkeypatch):
|
||||
portfolio = PortfolioFactory.create(
|
||||
applications=[
|
||||
{"environments": [{"cloud_id": uuid4().hex, "root_user_info": None}]}
|
||||
],
|
||||
task_orders=[
|
||||
{
|
||||
"create_clins": [
|
||||
{
|
||||
"start_date": pendulum.now().subtract(days=1),
|
||||
"end_date": pendulum.now().add(days=1),
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
)
|
||||
mock = Mock()
|
||||
monkeypatch.setattr("atst.jobs.create_atat_admin_user", mock)
|
||||
environment = portfolio.applications[0].environments[0]
|
||||
|
||||
dispatch_create_atat_admin_user.run()
|
||||
|
||||
mock.delay.assert_called_once_with(environment_id=environment.id)
|
||||
|
||||
|
||||
def test_dispatch_create_environment_baseline(session, monkeypatch):
|
||||
portfolio = PortfolioFactory.create(
|
||||
applications=[
|
||||
{
|
||||
"environments": [
|
||||
{
|
||||
"cloud_id": uuid4().hex,
|
||||
"root_user_info": {},
|
||||
"baseline_info": None,
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
task_orders=[
|
||||
{
|
||||
"create_clins": [
|
||||
{
|
||||
"start_date": pendulum.now().subtract(days=1),
|
||||
"end_date": pendulum.now().add(days=1),
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
)
|
||||
mock = Mock()
|
||||
monkeypatch.setattr("atst.jobs.create_environment_baseline", mock)
|
||||
environment = portfolio.applications[0].environments[0]
|
||||
|
||||
dispatch_create_environment_baseline.run()
|
||||
|
||||
mock.delay.assert_called_once_with(environment_id=environment.id)
|
||||
|
Reference in New Issue
Block a user