Example #1
0
    def test_build_plan_missing_dependency(self):
        bastion = Stack(definition=generate_definition(
            'bastion', 1, requires=['namespace-vpc.1']),
                        context=self.context)

        with self.assertRaises(GraphError) as expected:
            build_plan(description="Test", steps=[Step(bastion, None)])
        message = ("Error detected when adding 'namespace-vpc.1' "
                   "as a dependency of 'namespace-bastion.1': dependent node "
                   "namespace-vpc.1 does not exist")
        self.assertEqual(expected.exception.message, message)
Example #2
0
    def test_build_plan_missing_dependency(self):
        bastion = Stack(definition=generate_definition('bastion',
                                                       1,
                                                       requires=['vpc.1']),
                        context=self.context)

        with self.assertRaises(GraphError) as expected:
            build_plan(description="Test", steps=[Step(bastion, None)])
        message_starts = ("Error detected when adding 'vpc.1' "
                          "as a dependency of 'bastion.1':")
        message_contains = "dependent node vpc.1 does not exist"
        self.assertTrue(str(expected.exception).startswith(message_starts))
        self.assertTrue(message_contains in str(expected.exception))
Example #3
0
    def test_dump(self, *args):
        requires = None
        steps = []

        for i in range(5):
            overrides = {
                "variables": {
                    "PublicSubnets": "1",
                    "SshKeyName": "1",
                    "PrivateSubnets": "1",
                    "Random": "${noop something}",
                },
                "requires": requires,
            }

            stack = Stack(definition=generate_definition(
                'vpc', i, **overrides),
                          context=self.context)
            requires = [stack.name]

            steps += [Step(stack, None)]

        plan = build_plan(description="Test", steps=steps)

        tmp_dir = tempfile.mkdtemp()
        try:
            plan.dump(tmp_dir, context=self.context)

            for step in plan.steps:
                template_path = os.path.join(
                    tmp_dir, stack_template_key_name(step.stack.blueprint))
                self.assertTrue(os.path.isfile(template_path))
        finally:
            shutil.rmtree(tmp_dir)
Example #4
0
    def test_execute_plan_filtered(self):
        vpc = Stack(
            definition=generate_definition('vpc', 1),
            context=self.context)
        db = Stack(
            definition=generate_definition('db', 1, requires=[vpc.name]),
            context=self.context)
        app = Stack(
            definition=generate_definition('app', 1, requires=[db.name]),
            context=self.context)

        calls = []

        def fn(stack, status=None):
            calls.append(stack.fqn)
            return COMPLETE

        graph = build_graph([
            Step(vpc, fn), Step(db, fn), Step(app, fn)])
        plan = build_plan(
            description="Test",
            graph=graph,
            targets=['db.1'])
        plan.execute(walk)

        self.assertEquals(calls, [
            'namespace-vpc.1', 'namespace-db.1'])
Example #5
0
    def test_execute_plan_failed(self):
        vpc = Stack(definition=generate_definition('vpc', 1),
                    context=self.context)
        bastion = Stack(definition=generate_definition('bastion',
                                                       1,
                                                       requires=[vpc.name]),
                        context=self.context)
        db = Stack(definition=generate_definition('db', 1),
                   context=self.context)

        calls = []

        def fn(stack, status=None):
            calls.append(stack.fqn)
            if stack.name == vpc_step.name:
                return FAILED
            return COMPLETE

        vpc_step = Step(vpc, fn)
        bastion_step = Step(bastion, fn)
        db_step = Step(db, fn)

        plan = build_plan(description="Test",
                          steps=[vpc_step, bastion_step, db_step])
        with self.assertRaises(PlanFailed):
            plan.execute(walk)

        calls.sort()

        self.assertEquals(calls, ['namespace-db.1', 'namespace-vpc.1'])
Example #6
0
    def test_execute_plan_filtered(self):
        vpc = Stack(definition=generate_definition('vpc', 1),
                    context=self.context)
        db = Stack(definition=generate_definition('db', 1,
                                                  requires=[vpc.name]),
                   context=self.context)
        app = Stack(definition=generate_definition('app',
                                                   1,
                                                   requires=[db.name]),
                    context=self.context)

        calls = []

        def fn(stack, status=None):
            calls.append(stack.fqn)
            return COMPLETE

        plan = build_plan(description="Test",
                          steps=[Step(vpc, fn),
                                 Step(db, fn),
                                 Step(app, fn)],
                          targets=['db.1'])
        plan.execute(walk)

        self.assertEquals(calls, ['namespace-vpc.1', 'namespace-db.1'])
Example #7
0
    def test_execute_plan_exception(self):
        vpc = Stack(definition=generate_definition('vpc', 1),
                    context=self.context)
        bastion = Stack(definition=generate_definition('bastion',
                                                       1,
                                                       requires=[vpc.name]),
                        context=self.context)

        calls = []

        def fn(stack, status=None):
            calls.append(stack.fqn)
            if stack.name == vpc_step.name:
                raise ValueError('Boom')
            return COMPLETE

        vpc_step = Step(vpc, fn)
        bastion_step = Step(bastion, fn)
        plan = build_plan(description="Test", steps=[vpc_step, bastion_step])

        with self.assertRaises(PlanFailed):
            plan.execute(walk)

        self.assertEquals(calls, ['namespace-vpc.1'])
        self.assertEquals(vpc_step.status, FAILED)
Example #8
0
    def test_execute_plan_failed(self):
        vpc = Stack(
            definition=generate_definition('vpc', 1),
            context=self.context)
        bastion = Stack(
            definition=generate_definition('bastion', 1, requires=[vpc.name]),
            context=self.context)
        db = Stack(
            definition=generate_definition('db', 1),
            context=self.context)

        calls = []

        def fn(stack, status=None):
            calls.append(stack.fqn)
            if stack.name == vpc_step.name:
                return FAILED
            return COMPLETE

        vpc_step = Step(vpc, fn)
        bastion_step = Step(bastion, fn)
        db_step = Step(db, fn)

        graph = build_graph([
            vpc_step, bastion_step, db_step])
        plan = build_plan(description="Test", graph=graph)
        with self.assertRaises(PlanFailed):
            plan.execute(walk)

        calls.sort()

        self.assertEquals(calls, ['namespace-db.1', 'namespace-vpc.1'])
Example #9
0
    def test_build_plan_cyclic_dependencies(self):
        vpc = Stack(definition=generate_definition('vpc', 1),
                    context=self.context)
        db = Stack(definition=generate_definition('db', 1, requires=['app.1']),
                   context=self.context)
        app = Stack(definition=generate_definition('app', 1,
                                                   requires=['db.1']),
                    context=self.context)

        with self.assertRaises(GraphError) as expected:
            build_plan(
                description="Test",
                steps=[Step(vpc, None),
                       Step(db, None),
                       Step(app, None)])
        message = ("Error detected when adding 'db.1' "
                   "as a dependency of 'app.1': graph is "
                   "not acyclic")
        self.assertEqual(expected.exception.message, message)
Example #10
0
    def test_plan(self):
        vpc = Stack(
            definition=generate_definition('vpc', 1),
            context=self.context)
        bastion = Stack(
            definition=generate_definition('bastion', 1, requires=[vpc.fqn]),
            context=self.context)

        plan = build_plan(description="Test", steps=[
            Step(vpc, fn=None), Step(bastion, fn=None)])

        self.assertEqual(plan.graph.to_dict(), {
            'namespace-bastion.1': set(['namespace-vpc.1']),
            'namespace-vpc.1': set([])})
Example #11
0
    def test_plan(self):
        vpc = Stack(
            definition=generate_definition('vpc', 1),
            context=self.context)
        bastion = Stack(
            definition=generate_definition('bastion', 1, requires=[vpc.name]),
            context=self.context)

        graph = build_graph([
            Step(vpc, fn=None), Step(bastion, fn=None)])
        plan = build_plan(description="Test", graph=graph)

        self.assertEqual(plan.graph.to_dict(), {
            'bastion.1': set(['vpc.1']),
            'vpc.1': set([])})
Example #12
0
    def test_plan(self):
        vpc = Stack(
            definition=generate_definition('vpc', 1),
            context=self.context)
        bastion = Stack(
            definition=generate_definition('bastion', 1, requires=[vpc.name]),
            context=self.context)

        graph = build_graph([
            Step(vpc, fn=None), Step(bastion, fn=None)])
        plan = build_plan(description="Test", graph=graph)

        self.assertEqual(plan.graph.to_dict(), {
            'bastion.1': set(['vpc.1']),
            'vpc.1': set([])})
Example #13
0
    def test_execute_plan(self):
        vpc = Stack(
            definition=generate_definition('vpc', 1),
            context=self.context)
        bastion = Stack(
            definition=generate_definition('bastion', 1, requires=[vpc.fqn]),
            context=self.context)

        calls = []

        def fn(stack, status=None):
            calls.append(stack.fqn)
            return COMPLETE

        plan = build_plan(
            description="Test", steps=[Step(vpc, fn), Step(bastion, fn)])
        plan.execute()

        self.assertEquals(calls, ['namespace-vpc.1', 'namespace-bastion.1'])
Example #14
0
    def test_execute_plan(self):
        vpc = Stack(
            definition=generate_definition('vpc', 1),
            context=self.context)
        bastion = Stack(
            definition=generate_definition('bastion', 1, requires=[vpc.name]),
            context=self.context)

        calls = []

        def fn(stack, status=None):
            calls.append(stack.fqn)
            return COMPLETE

        graph = build_graph([Step(vpc, fn), Step(bastion, fn)])
        plan = build_plan(
            description="Test", graph=graph)
        plan.execute(walk)

        self.assertEquals(calls, ['namespace-vpc.1', 'namespace-bastion.1'])
Example #15
0
    def test_execute_plan_locked(self):
        # Locked stacks still need to have their requires evaluated when
        # they're being created.
        vpc = Stack(
            definition=generate_definition('vpc', 1),
            context=self.context)
        bastion = Stack(
            definition=generate_definition('bastion', 1, requires=[vpc.name]),
            locked=True,
            context=self.context)

        calls = []

        def fn(stack, status=None):
            calls.append(stack.fqn)
            return COMPLETE

        graph = build_graph([Step(vpc, fn), Step(bastion, fn)])
        plan = build_plan(
            description="Test", graph=graph)
        plan.execute(walk)

        self.assertEquals(calls, ['namespace-vpc.1', 'namespace-bastion.1'])
Example #16
0
    def test_execute_plan_cancelled(self):
        vpc = Stack(definition=generate_definition('vpc', 1),
                    context=self.context)
        bastion = Stack(definition=generate_definition('bastion',
                                                       1,
                                                       requires=[vpc.name]),
                        context=self.context)

        calls = []

        def fn(stack, status=None):
            calls.append(stack.fqn)
            if stack.fqn == vpc_step.name:
                raise CancelExecution
            return COMPLETE

        vpc_step = Step(vpc, fn)
        bastion_step = Step(bastion, fn)

        plan = build_plan(description="Test", steps=[vpc_step, bastion_step])
        plan.execute(walk)

        self.assertEquals(calls, ['namespace-vpc.1', 'namespace-bastion.1'])
Example #17
0
    def test_dump(self, *args):
        requires = None
        steps = []

        for i in range(5):
            overrides = {
                "variables": {
                    "PublicSubnets": "1",
                    "SshKeyName": "1",
                    "PrivateSubnets": "1",
                    "Random": "${noop something}",
                },
                "requires": requires,
            }

            stack = Stack(
                definition=generate_definition('vpc', i, **overrides),
                context=self.context)
            requires = [stack.name]

            steps += [Step(stack, None)]

        graph = build_graph(steps)
        plan = build_plan(description="Test", graph=graph)

        tmp_dir = tempfile.mkdtemp()
        try:
            plan.dump(tmp_dir, context=self.context)

            for step in plan.steps:
                template_path = os.path.join(
                    tmp_dir,
                    stack_template_key_name(step.stack.blueprint))
                self.assertTrue(os.path.isfile(template_path))
        finally:
            shutil.rmtree(tmp_dir)