Skip to content

Commit

Permalink
Bring TestLaunchStack tests back.
Browse files Browse the repository at this point in the history
  • Loading branch information
ejholmes committed Jan 27, 2018
1 parent 6d81099 commit 1fba1c8
Show file tree
Hide file tree
Showing 2 changed files with 174 additions and 2 deletions.
8 changes: 6 additions & 2 deletions stacker/plan2.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,18 @@ def run(self):
self.status_changed_func()

while not self.done:
status = self.fn(self.stack, status=self.status)
self.set_status(status)
self._run_once()
finally:
if watcher and watcher.is_alive():
watcher.terminate()
watcher.join()
return self.ok

def _run_once(self):
status = self.fn(self.stack, status=self.status)
self.set_status(status)
return status

@property
def name(self):
return self.stack.fqn
Expand Down
168 changes: 168 additions & 0 deletions stacker/tests/actions/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,17 @@
)
from stacker.blueprints.variables.types import CFNString
from stacker.context import Context, Config
from stacker.exceptions import StackDidNotChange, StackDoesNotExist
from stacker.providers.base import BaseProvider
from stacker.providers.aws.default import Provider
from stacker.status import (
NotSubmittedStatus,
COMPLETE,
PENDING,
SKIPPED,
SUBMITTED,
FAILED
)


def mock_stack(parameters):
Expand Down Expand Up @@ -154,6 +164,164 @@ def test_should_submit(self):
self.assertEqual(build.should_submit(mock_stack), t.result)


class TestLaunchStack(TestBuildAction):
def setUp(self):
self.context = self._get_context()
self.provider = Provider(None, interactive=False,
recreate_failed=False)
self.build_action = build.Action(self.context, provider=self.provider)

self.stack = mock.MagicMock()
self.stack.name = 'vpc'
self.stack.fqn = 'vpc'
self.stack.blueprint.rendered = '{}'
self.stack.locked = False
self.stack_status = None

plan = self.build_action._generate_plan()
self.step = plan.steps[0]
self.step.stack = self.stack

def patch_object(*args, **kwargs):
m = mock.patch.object(*args, **kwargs)
self.addCleanup(m.stop)
m.start()

def get_stack(name, *args, **kwargs):
if name != self.stack.name or not self.stack_status:
raise StackDoesNotExist(name)

return {'StackName': self.stack.name,
'StackStatus': self.stack_status,
'Tags': []}

patch_object(self.provider, 'get_stack', side_effect=get_stack)
patch_object(self.provider, 'update_stack')
patch_object(self.provider, 'create_stack')
patch_object(self.provider, 'destroy_stack')

patch_object(self.build_action, "s3_stack_push")

def _advance(self, new_provider_status, expected_status, expected_reason):
self.stack_status = new_provider_status
status = self.step._run_once()
self.assertEqual(status, expected_status)
self.assertEqual(status.reason, expected_reason)

def test_launch_stack_disabled(self):
self.assertEqual(self.step.status, PENDING)

self.stack.enabled = False
self._advance(None, NotSubmittedStatus(), "disabled")

def test_launch_stack_create(self):
# initial status should be PENDING
self.assertEqual(self.step.status, PENDING)

# initial run should return SUBMITTED since we've passed off to CF
self._advance(None, SUBMITTED, "creating new stack")

# status should stay as SUBMITTED when the stack becomes available
self._advance('CREATE_IN_PROGRESS', SUBMITTED, "creating new stack")

# status should become COMPLETE once the stack finishes
self._advance('CREATE_COMPLETE', COMPLETE, "creating new stack")

def test_launch_stack_create_rollback(self):
# initial status should be PENDING
self.assertEqual(self.step.status, PENDING)

# initial run should return SUBMITTED since we've passed off to CF
self._advance(None, SUBMITTED, "creating new stack")

# provider should now return the CF stack since it exists
self._advance("CREATE_IN_PROGRESS", SUBMITTED,
"creating new stack")

# rollback should be noticed
self._advance("ROLLBACK_IN_PROGRESS", SUBMITTED,
"rolling back new stack")

# rollback should not be added twice to the reason
self._advance("ROLLBACK_IN_PROGRESS", SUBMITTED,
"rolling back new stack")

# rollback should finish with failure
self._advance("ROLLBACK_COMPLETE", FAILED,
"rolled back new stack")

def test_launch_stack_recreate(self):
self.provider.recreate_failed = True

# initial status should be PENDING
self.assertEqual(self.step.status, PENDING)

# first action with an existing failed stack should be deleting it
self._advance("ROLLBACK_COMPLETE", SUBMITTED,
"destroying stack for re-creation")

# status should stay as submitted during deletion
self._advance("DELETE_IN_PROGRESS", SUBMITTED,
"destroying stack for re-creation")

# deletion being complete must trigger re-creation
self._advance("DELETE_COMPLETE", SUBMITTED,
"re-creating stack")

# re-creation should continue as SUBMITTED
self._advance("CREATE_IN_PROGRESS", SUBMITTED,
"re-creating stack")

# re-creation should finish with success
self._advance("CREATE_COMPLETE", COMPLETE,
"re-creating stack")

def test_launch_stack_update_skipped(self):
# initial status should be PENDING
self.assertEqual(self.step.status, PENDING)

# start the upgrade, that will be skipped
self.provider.update_stack.side_effect = StackDidNotChange
self._advance("CREATE_COMPLETE", SKIPPED,
"nochange")

def test_launch_stack_update_rollback(self):
# initial status should be PENDING
self.assertEqual(self.step.status, PENDING)

# initial run should return SUBMITTED since we've passed off to CF
self._advance("CREATE_COMPLETE", SUBMITTED,
"updating existing stack")

# update should continue as SUBMITTED
self._advance("UPDATE_IN_PROGRESS", SUBMITTED,
"updating existing stack")

# rollback should be noticed
self._advance("UPDATE_ROLLBACK_IN_PROGRESS", SUBMITTED,
"rolling back update")

# rollback should finish with failure
self._advance("UPDATE_ROLLBACK_COMPLETE", FAILED,
"rolled back update")

def test_launch_stack_update_success(self):
# initial status should be PENDING
self.assertEqual(self.step.status, PENDING)

# initial run should return SUBMITTED since we've passed off to CF
self._advance("CREATE_COMPLETE", SUBMITTED,
"updating existing stack")

# update should continue as SUBMITTED
self._advance("UPDATE_IN_PROGRESS", SUBMITTED,
"updating existing stack")

# update should finish with sucess
self._advance("UPDATE_COMPLETE", COMPLETE,
"updating existing stack")


class TestFunctions(unittest.TestCase):
""" test module level functions """

Expand Down

0 comments on commit 1fba1c8

Please sign in to comment.