Skip to content

Commit

Permalink
Ensure that a failed deployment is not created (#172)
Browse files Browse the repository at this point in the history
* tests: add a test to make sure that a failed deployment is not created

* fix: rollback the whole changes in a Design Job if something fails
  • Loading branch information
chadell authored and abates committed Jun 24, 2024
1 parent 5d086b3 commit a120bcb
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 3 deletions.
4 changes: 2 additions & 2 deletions nautobot_design_builder/design_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,8 @@ def _run_in_transaction(self, dryrun: bool, **data): # pylint: disable=too-many
This version of `run` is wrapped in a transaction and will roll back database changes
on error. In general, this method should only be called by the `run` method.
"""
sid = transaction.savepoint()

self.log_info(message=f"Building {getattr(self.Meta, 'name')}")
extensions = getattr(self.Meta, "extensions", [])

Expand Down Expand Up @@ -303,8 +305,6 @@ def _run_in_transaction(self, dryrun: bool, **data): # pylint: disable=too-many
self.log_failure(message="No design template specified for design.")
raise DesignImplementationError("No design template specified for design.")

sid = transaction.savepoint()

try:
for design_file in design_files:
self.implement_design(context, design_file, not dryrun)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
manufacturers:
name: "Test Manufacturer"
wrong: "attribute"
13 changes: 12 additions & 1 deletion nautobot_design_builder/tests/designs/test_designs.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,20 @@ class Meta: # pylint: disable=too-few-public-methods
]


class MultiDesignJobWithError(DesignJob):
class DesignJobModeDeploymentWithError(DesignJob):
"""Design job that includes an error (for unit testing)."""

class Meta: # pylint: disable=too-few-public-methods
name = "File Design with Error"
design_files = [
"templates/simple_design_with_error.yaml.j2",
]
design_mode = DesignModeChoices.DEPLOYMENT


class MultiDesignJobWithError(DesignJob):
"""Multi Design job that includes an error (for unit testing)."""

class Meta: # pylint: disable=too-few-public-methods
name = "Multi File Design with Error"
design_files = [
Expand Down
9 changes: 9 additions & 0 deletions nautobot_design_builder/tests/test_design_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from nautobot.ipam.models import VRF, Prefix, IPAddress

from nautobot.extras.models import Status
from nautobot_design_builder.models import Deployment
from nautobot_design_builder.errors import DesignImplementationError, DesignValidationError
from nautobot_design_builder.tests import DesignTestCase
from nautobot_design_builder.tests.designs import test_designs
Expand Down Expand Up @@ -51,6 +52,14 @@ def test_simple_design_with_post_implementation(self):
job.run(dryrun=False, **self.data)
self.assertTrue(getattr(job, "post_implementation_called"))

def test_simple_design_rollback_deployment_mode(self):
"""Confirm that database changes are rolled back when an exception is raised and no Design Deployment is created."""
self.assertEqual(0, Manufacturer.objects.all().count())
job = self.get_mocked_job(test_designs.DesignJobModeDeploymentWithError)
job.run(data={**self.data, **{"deployment_name": "whatever"}}, commit=True)
self.assertEqual(0, Manufacturer.objects.all().count())
self.assertEqual(0, Deployment.objects.all().count())

def test_simple_design_report(self):
job = self.get_mocked_job(test_designs.SimpleDesignReport)
job.run(data={}, dryrun=False)
Expand Down

0 comments on commit a120bcb

Please sign in to comment.