Example #1
0
    def test_resolved_already_resolved(self):
        """
        'juju resolved <unit_name>' will report if
        the unit is already resolved.
        """
        # Mark the unit as resolved and as in an error state.
        yield self.service_unit1.set_resolved(RETRY_HOOKS)
        yield self.unit1_workflow.set_state("start_error")

        unit2_workflow = UnitWorkflowState(self.client, self.service_unit1,
                                           None, self.makeDir())
        unit2_workflow.set_state("start_error")

        self.assertEqual((yield self.service_unit2.get_resolved()), None)

        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        main(["resolved", "mysql/0"])
        yield finished

        self.assertEqual((yield self.service_unit1.get_resolved()),
                         {"retry": RETRY_HOOKS})
        self.assertNotIn("Marked unit 'mysql/0' as resolved",
                         self.output.getvalue())
        self.assertIn("Service unit 'mysql/0' is already marked as resolved.",
                      self.stderr.getvalue(), "")
Example #2
0
    def test_resolved_already_resolved(self):
        """
        'juju resolved <unit_name>' will report if
        the unit is already resolved.
        """
        # Mark the unit as resolved and as in an error state.
        yield self.service_unit1.set_resolved(RETRY_HOOKS)
        yield self.unit1_workflow.set_state("start_error")

        unit2_workflow = UnitWorkflowState(
            self.client, self.service_unit1, None, self.makeDir())
        unit2_workflow.set_state("start_error")

        self.assertEqual(
            (yield self.service_unit2.get_resolved()), None)

        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        main(["resolved", "mysql/0"])
        yield finished

        self.assertEqual(
            (yield self.service_unit1.get_resolved()),
            {"retry": RETRY_HOOKS})
        self.assertNotIn(
            "Marked unit 'mysql/0' as resolved",
            self.output.getvalue())
        self.assertIn(
            "Service unit 'mysql/0' is already marked as resolved.",
            self.stderr.getvalue(), "")
Example #3
0
    def test_resolved_already_running(self):
        """
        'juju resolved <unit_name>' will report if
        the unit is already running.
        """
        # Just verify we don't accidentally mark up another unit of the service
        unit2_workflow = UnitWorkflowState(
            self.client, self.service_unit2, None, self.makeDir())
        unit2_workflow.set_state("start_error")

        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        main(["resolved", "mysql/0"])
        yield finished

        self.assertEqual(
            (yield self.service_unit2.get_resolved()), None)
        self.assertEqual(
            (yield self.service_unit1.get_resolved()), None)

        self.assertNotIn(
            "Unit 'mysql/0 already running: started",
            self.output.getvalue())
Example #4
0
    def test_resolved_already_running(self):
        """
        'juju resolved <unit_name>' will report if
        the unit is already running.
        """
        # Just verify we don't accidentally mark up another unit of the service
        unit2_workflow = UnitWorkflowState(self.client, self.service_unit2,
                                           None, self.makeDir())
        unit2_workflow.set_state("start_error")

        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        main(["resolved", "mysql/0"])
        yield finished

        self.assertEqual((yield self.service_unit2.get_resolved()), None)
        self.assertEqual((yield self.service_unit1.get_resolved()), None)

        self.assertNotIn("Unit 'mysql/0 already running: started",
                         self.output.getvalue())
Example #5
0
class ControlResolvedTest(ServiceStateManagerTestBase, ControlToolTest,
                          RepositoryTestBase):
    @inlineCallbacks
    def setUp(self):
        yield super(ControlResolvedTest, self).setUp()
        config = {"environments": {"firstenv": {"type": "dummy"}}}

        self.write_config(dump(config))
        self.config.load()

        yield self.add_relation_state("wordpress", "mysql")
        yield self.add_relation_state("wordpress", "varnish")

        self.service1 = yield self.service_state_manager.get_service_state(
            "mysql")
        self.service_unit1 = yield self.service1.add_unit_state()
        self.service_unit2 = yield self.service1.add_unit_state()

        self.unit1_workflow = UnitWorkflowState(self.client,
                                                self.service_unit1, None,
                                                self.makeDir())
        yield self.unit1_workflow.set_state("started")

        self.environment = self.config.get_default()
        self.provider = self.environment.get_machine_provider()

        self.output = self.capture_logging()
        self.stderr = self.capture_stream("stderr")
        self.executor = HookExecutor()

    @inlineCallbacks
    def add_relation_state(self, *service_names):
        for service_name in service_names:
            try:
                yield self.service_state_manager.get_service_state(
                    service_name)
            except ServiceStateNotFound:
                yield self.add_service_from_charm(service_name)

        endpoint_pairs = yield self.service_state_manager.join_descriptors(
            *service_names)
        endpoints = endpoint_pairs[0]
        endpoints = endpoint_pairs[0]
        if endpoints[0] == endpoints[1]:
            endpoints = endpoints[0:1]
        relation_state = (yield self.relation_state_manager.add_relation_state(
            *endpoints))[0]
        returnValue(relation_state)

    @inlineCallbacks
    def get_named_service_relation(self, service_state, relation_name):
        if isinstance(service_state, str):
            service_state = yield self.service_state_manager.get_service_state(
                service_state)

        rels = yield self.relation_state_manager.get_relations_for_service(
            service_state)

        rels = [sr for sr in rels if sr.relation_name == relation_name]
        if len(rels) == 1:
            returnValue(rels[0])
        returnValue(rels)

    @inlineCallbacks
    def setup_unit_relations(self, service_relation, *units):
        """
        Given a service relation and set of unit tuples in the form
        unit_state, unit_relation_workflow_state, will add unit relations
        for these units and update their workflow state to the desired/given
        state.
        """
        for unit, state in units:
            unit_relation = yield service_relation.add_unit_state(unit)
            lifecycle = UnitRelationLifecycle(self.client, unit.unit_name,
                                              unit_relation,
                                              service_relation.relation_name,
                                              self.makeDir(), self.executor)
            workflow_state = RelationWorkflowState(self.client, unit_relation,
                                                   lifecycle, self.makeDir())
            yield workflow_state.set_state(state)

    @inlineCallbacks
    def test_resolved(self):
        """
        'juju resolved <unit_name>' will schedule a unit for
        retrying from an error state.
        """
        # Push the unit into an error state
        yield self.unit1_workflow.set_state("start_error")
        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        self.assertEqual((yield self.service_unit1.get_resolved()), None)

        main(["resolved", "mysql/0"])
        yield finished

        self.assertEqual((yield self.service_unit1.get_resolved()),
                         {"retry": NO_HOOKS})
        self.assertIn("Marked unit 'mysql/0' as resolved",
                      self.output.getvalue())

    @inlineCallbacks
    def test_resolved_retry(self):
        """
        'juju resolved --retry <unit_name>' will schedule a unit
        for retrying from an error state with a retry of hooks
        executions.
        """
        yield self.unit1_workflow.set_state("start_error")
        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        self.assertEqual((yield self.service_unit1.get_resolved()), None)

        main(["resolved", "--retry", "mysql/0"])
        yield finished

        self.assertEqual((yield self.service_unit1.get_resolved()),
                         {"retry": RETRY_HOOKS})
        self.assertIn("Marked unit 'mysql/0' as resolved",
                      self.output.getvalue())

    @inlineCallbacks
    def test_relation_resolved(self):
        """
        'juju relation <unit_name> <rel_name>' will schedule
        the broken unit relations for being resolved.
        """
        service_relation = yield self.get_named_service_relation(
            self.service1, "server")

        yield self.setup_unit_relations(service_relation,
                                        (self.service_unit1, "down"),
                                        (self.service_unit2, "up"))

        yield self.unit1_workflow.set_state("start_error")
        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        self.assertEqual((yield self.service_unit1.get_relation_resolved()),
                         None)

        main(
            ["resolved", "--retry", "mysql/0", service_relation.relation_name])
        yield finished

        self.assertEqual((yield self.service_unit1.get_relation_resolved()),
                         {service_relation.internal_relation_id: RETRY_HOOKS})
        self.assertEqual((yield self.service_unit2.get_relation_resolved()),
                         None)
        self.assertIn("Marked unit 'mysql/0' relation 'server' as resolved",
                      self.output.getvalue())

    @inlineCallbacks
    def test_resolved_relation_some_already_resolved(self):
        """
        'juju resolved <service_name> <rel_name>' will mark
        resolved all down units that are not already marked resolved.
        """

        service2 = yield self.service_state_manager.get_service_state(
            "wordpress")
        service_unit1 = yield service2.add_unit_state()

        service_relation = yield self.get_named_service_relation(
            service2, "db")
        yield self.setup_unit_relations(service_relation,
                                        (service_unit1, "down"))

        service_relation2 = yield self.get_named_service_relation(
            service2, "cache")
        yield self.setup_unit_relations(service_relation2,
                                        (service_unit1, "down"))

        yield service_unit1.set_relation_resolved(
            {service_relation.internal_relation_id: NO_HOOKS})

        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        main(["resolved", "--retry", "wordpress/0", "cache"])
        yield finished

        self.assertEqual(
            (yield service_unit1.get_relation_resolved()), {
                service_relation.internal_relation_id: NO_HOOKS,
                service_relation2.internal_relation_id: RETRY_HOOKS
            })

        self.assertIn("Marked unit 'wordpress/0' relation 'cache' as resolved",
                      self.output.getvalue())

    @inlineCallbacks
    def test_resolved_relation_some_already_resolved_conflict(self):
        """
        'juju resolved <service_name> <rel_name>' will mark
        resolved all down units that are not already marked resolved.
        """

        service2 = yield self.service_state_manager.get_service_state(
            "wordpress")
        service_unit1 = yield service2.add_unit_state()

        service_relation = yield self.get_named_service_relation(
            service2, "db")
        yield self.setup_unit_relations(service_relation,
                                        (service_unit1, "down"))

        yield service_unit1.set_relation_resolved(
            {service_relation.internal_relation_id: NO_HOOKS})

        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        main(["resolved", "--retry", "wordpress/0", "db"])
        yield finished

        self.assertEqual((yield service_unit1.get_relation_resolved()),
                         {service_relation.internal_relation_id: NO_HOOKS})

        self.assertIn(
            "Service unit 'wordpress/0' already has relations marked as resol",
            self.output.getvalue())

    @inlineCallbacks
    def test_resolved_unknown_service(self):
        """
        'juju resolved <unit_name>' will report if a service is
        invalid.
        """
        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()
        main(["resolved", "zebra/0"])
        yield finished
        self.assertIn("Service 'zebra' was not found", self.stderr.getvalue())

    @inlineCallbacks
    def test_resolved_unknown_unit(self):
        """
        'juju resolved <unit_name>' will report if a unit is
        invalid.
        """
        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()
        main(["resolved", "mysql/5"])
        yield finished
        self.assertIn("Service unit 'mysql/5' was not found",
                      self.output.getvalue())

    @inlineCallbacks
    def test_resolved_unknown_unit_relation(self):
        """
        'juju resolved <unit_name>' will report if a relation is
        invalid.
        """
        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        self.assertEqual((yield self.service_unit1.get_resolved()), None)

        main(["resolved", "mysql/0", "magic"])
        yield finished

        self.assertIn("Relation not found", self.output.getvalue())

    @inlineCallbacks
    def test_resolved_already_running(self):
        """
        'juju resolved <unit_name>' will report if
        the unit is already running.
        """
        # Just verify we don't accidentally mark up another unit of the service
        unit2_workflow = UnitWorkflowState(self.client, self.service_unit2,
                                           None, self.makeDir())
        unit2_workflow.set_state("start_error")

        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        main(["resolved", "mysql/0"])
        yield finished

        self.assertEqual((yield self.service_unit2.get_resolved()), None)
        self.assertEqual((yield self.service_unit1.get_resolved()), None)

        self.assertNotIn("Unit 'mysql/0 already running: started",
                         self.output.getvalue())

    @inlineCallbacks
    def test_resolved_already_resolved(self):
        """
        'juju resolved <unit_name>' will report if
        the unit is already resolved.
        """
        # Mark the unit as resolved and as in an error state.
        yield self.service_unit1.set_resolved(RETRY_HOOKS)
        yield self.unit1_workflow.set_state("start_error")

        unit2_workflow = UnitWorkflowState(self.client, self.service_unit1,
                                           None, self.makeDir())
        unit2_workflow.set_state("start_error")

        self.assertEqual((yield self.service_unit2.get_resolved()), None)

        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        main(["resolved", "mysql/0"])
        yield finished

        self.assertEqual((yield self.service_unit1.get_resolved()),
                         {"retry": RETRY_HOOKS})
        self.assertNotIn("Marked unit 'mysql/0' as resolved",
                         self.output.getvalue())
        self.assertIn("Service unit 'mysql/0' is already marked as resolved.",
                      self.stderr.getvalue(), "")

    @inlineCallbacks
    def test_resolved_relation_already_running(self):
        """
        'juju resolved <unit_name> <rel_name>' will report
        if the relation is already running.
        """
        service2 = yield self.service_state_manager.get_service_state(
            "wordpress")
        service_unit1 = yield service2.add_unit_state()

        service_relation = yield self.get_named_service_relation(
            service2, "db")
        yield self.setup_unit_relations(service_relation,
                                        (service_unit1, "up"))

        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        main(["resolved", "wordpress/0", "db"])
        yield finished

        self.assertIn("Matched relations are all running",
                      self.output.getvalue())
        self.assertEqual((yield service_unit1.get_relation_resolved()), None)
Example #6
0
class ControlResolvedTest(
    ServiceStateManagerTestBase, ControlToolTest, RepositoryTestBase):

    @inlineCallbacks
    def setUp(self):
        yield super(ControlResolvedTest, self).setUp()
        config = {
            "environments": {"firstenv": {"type": "dummy"}}}

        self.write_config(dump(config))
        self.config.load()

        yield self.add_relation_state("wordpress", "mysql")
        yield self.add_relation_state("wordpress", "varnish")

        self.service1 = yield self.service_state_manager.get_service_state(
            "mysql")
        self.service_unit1 = yield self.service1.add_unit_state()
        self.service_unit2 = yield self.service1.add_unit_state()

        self.unit1_workflow = UnitWorkflowState(
            self.client, self.service_unit1, None, self.makeDir())
        yield self.unit1_workflow.set_state("started")

        self.environment = self.config.get_default()
        self.provider = self.environment.get_machine_provider()

        self.output = self.capture_logging()
        self.stderr = self.capture_stream("stderr")
        self.executor = HookExecutor()

    @inlineCallbacks
    def add_relation_state(self, *service_names):
        for service_name in service_names:
            try:
                yield self.service_state_manager.get_service_state(
                    service_name)
            except ServiceStateNotFound:
                yield self.add_service_from_charm(service_name)

        endpoint_pairs = yield self.service_state_manager.join_descriptors(
            *service_names)
        endpoints = endpoint_pairs[0]
        endpoints = endpoint_pairs[0]
        if endpoints[0] == endpoints[1]:
            endpoints = endpoints[0:1]
        relation_state = (yield self.relation_state_manager.add_relation_state(
            *endpoints))[0]
        returnValue(relation_state)

    @inlineCallbacks
    def get_named_service_relation(self, service_state, relation_name):
        if isinstance(service_state, str):
            service_state = yield self.service_state_manager.get_service_state(
                service_state)

        rels = yield self.relation_state_manager.get_relations_for_service(
            service_state)

        rels = [sr for sr in rels if sr.relation_name == relation_name]
        if len(rels) == 1:
            returnValue(rels[0])
        returnValue(rels)

    @inlineCallbacks
    def setup_unit_relations(self, service_relation, *units):
        """
        Given a service relation and set of unit tuples in the form
        unit_state, unit_relation_workflow_state, will add unit relations
        for these units and update their workflow state to the desired/given
        state.
        """
        for unit, state in units:
            unit_relation = yield service_relation.add_unit_state(unit)
            lifecycle = UnitRelationLifecycle(self.client,
                                              unit.unit_name, unit_relation,
                                              service_relation.relation_name,
                                              self.makeDir(), self.executor)
            workflow_state = RelationWorkflowState(
                self.client, unit_relation, lifecycle, self.makeDir())
            yield workflow_state.set_state(state)

    @inlineCallbacks
    def test_resolved(self):
        """
        'juju resolved <unit_name>' will schedule a unit for
        retrying from an error state.
        """
        # Push the unit into an error state
        yield self.unit1_workflow.set_state("start_error")
        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        self.assertEqual(
            (yield self.service_unit1.get_resolved()), None)

        main(["resolved", "mysql/0"])
        yield finished

        self.assertEqual(
            (yield self.service_unit1.get_resolved()), {"retry": NO_HOOKS})
        self.assertIn(
            "Marked unit 'mysql/0' as resolved",
            self.output.getvalue())

    @inlineCallbacks
    def test_resolved_retry(self):
        """
        'juju resolved --retry <unit_name>' will schedule a unit
        for retrying from an error state with a retry of hooks
        executions.
        """
        yield self.unit1_workflow.set_state("start_error")
        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        self.assertEqual(
            (yield self.service_unit1.get_resolved()), None)

        main(["resolved", "--retry", "mysql/0"])
        yield finished

        self.assertEqual(
            (yield self.service_unit1.get_resolved()), {"retry": RETRY_HOOKS})
        self.assertIn(
            "Marked unit 'mysql/0' as resolved",
            self.output.getvalue())

    @inlineCallbacks
    def test_relation_resolved(self):
        """
        'juju relation <unit_name> <rel_name>' will schedule
        the broken unit relations for being resolved.
        """
        service_relation = yield self.get_named_service_relation(
            self.service1, "server")

        yield self.setup_unit_relations(
            service_relation,
            (self.service_unit1, "down"),
            (self.service_unit2, "up"))

        yield self.unit1_workflow.set_state("start_error")
        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        self.assertEqual(
            (yield self.service_unit1.get_relation_resolved()), None)

        main(["resolved", "--retry", "mysql/0",
              service_relation.relation_name])
        yield finished

        self.assertEqual(
            (yield self.service_unit1.get_relation_resolved()),
            {service_relation.internal_relation_id: RETRY_HOOKS})
        self.assertEqual(
            (yield self.service_unit2.get_relation_resolved()),
            None)
        self.assertIn(
            "Marked unit 'mysql/0' relation 'server' as resolved",
            self.output.getvalue())

    @inlineCallbacks
    def test_resolved_relation_some_already_resolved(self):
        """
        'juju resolved <service_name> <rel_name>' will mark
        resolved all down units that are not already marked resolved.
        """

        service2 = yield self.service_state_manager.get_service_state(
            "wordpress")
        service_unit1 = yield service2.add_unit_state()

        service_relation = yield self.get_named_service_relation(
            service2, "db")
        yield self.setup_unit_relations(
            service_relation, (service_unit1, "down"))

        service_relation2 = yield self.get_named_service_relation(
            service2, "cache")
        yield self.setup_unit_relations(
            service_relation2, (service_unit1, "down"))

        yield service_unit1.set_relation_resolved(
            {service_relation.internal_relation_id: NO_HOOKS})

        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        main(["resolved", "--retry", "wordpress/0", "cache"])
        yield finished

        self.assertEqual(
            (yield service_unit1.get_relation_resolved()),
            {service_relation.internal_relation_id: NO_HOOKS,
             service_relation2.internal_relation_id: RETRY_HOOKS})

        self.assertIn(
            "Marked unit 'wordpress/0' relation 'cache' as resolved",
            self.output.getvalue())

    @inlineCallbacks
    def test_resolved_relation_some_already_resolved_conflict(self):
        """
        'juju resolved <service_name> <rel_name>' will mark
        resolved all down units that are not already marked resolved.
        """

        service2 = yield self.service_state_manager.get_service_state(
            "wordpress")
        service_unit1 = yield service2.add_unit_state()

        service_relation = yield self.get_named_service_relation(
            service2, "db")
        yield self.setup_unit_relations(
            service_relation, (service_unit1, "down"))

        yield service_unit1.set_relation_resolved(
            {service_relation.internal_relation_id: NO_HOOKS})

        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        main(["resolved", "--retry", "wordpress/0", "db"])
        yield finished

        self.assertEqual(
            (yield service_unit1.get_relation_resolved()),
            {service_relation.internal_relation_id: NO_HOOKS})

        self.assertIn(
            "Service unit 'wordpress/0' already has relations marked as resol",
            self.output.getvalue())

    @inlineCallbacks
    def test_resolved_unknown_service(self):
        """
        'juju resolved <unit_name>' will report if a service is
        invalid.
        """
        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()
        main(["resolved", "zebra/0"])
        yield finished
        self.assertIn("Service 'zebra' was not found", self.stderr.getvalue())

    @inlineCallbacks
    def test_resolved_unknown_unit(self):
        """
        'juju resolved <unit_name>' will report if a unit is
        invalid.
        """
        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()
        main(["resolved", "mysql/5"])
        yield finished
        self.assertIn(
            "Service unit 'mysql/5' was not found", self.output.getvalue())

    @inlineCallbacks
    def test_resolved_unknown_unit_relation(self):
        """
        'juju resolved <unit_name>' will report if a relation is
        invalid.
        """
        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        self.assertEqual(
            (yield self.service_unit1.get_resolved()), None)

        main(["resolved", "mysql/0", "magic"])
        yield finished

        self.assertIn("Relation not found", self.output.getvalue())

    @inlineCallbacks
    def test_resolved_already_running(self):
        """
        'juju resolved <unit_name>' will report if
        the unit is already running.
        """
        # Just verify we don't accidentally mark up another unit of the service
        unit2_workflow = UnitWorkflowState(
            self.client, self.service_unit2, None, self.makeDir())
        unit2_workflow.set_state("start_error")

        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        main(["resolved", "mysql/0"])
        yield finished

        self.assertEqual(
            (yield self.service_unit2.get_resolved()), None)
        self.assertEqual(
            (yield self.service_unit1.get_resolved()), None)

        self.assertNotIn(
            "Unit 'mysql/0 already running: started",
            self.output.getvalue())

    @inlineCallbacks
    def test_resolved_already_resolved(self):
        """
        'juju resolved <unit_name>' will report if
        the unit is already resolved.
        """
        # Mark the unit as resolved and as in an error state.
        yield self.service_unit1.set_resolved(RETRY_HOOKS)
        yield self.unit1_workflow.set_state("start_error")

        unit2_workflow = UnitWorkflowState(
            self.client, self.service_unit1, None, self.makeDir())
        unit2_workflow.set_state("start_error")

        self.assertEqual(
            (yield self.service_unit2.get_resolved()), None)

        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        main(["resolved", "mysql/0"])
        yield finished

        self.assertEqual(
            (yield self.service_unit1.get_resolved()),
            {"retry": RETRY_HOOKS})
        self.assertNotIn(
            "Marked unit 'mysql/0' as resolved",
            self.output.getvalue())
        self.assertIn(
            "Service unit 'mysql/0' is already marked as resolved.",
            self.stderr.getvalue(), "")

    @inlineCallbacks
    def test_resolved_relation_already_running(self):
        """
        'juju resolved <unit_name> <rel_name>' will report
        if the relation is already running.
        """
        service2 = yield self.service_state_manager.get_service_state(
            "wordpress")
        service_unit1 = yield service2.add_unit_state()

        service_relation = yield self.get_named_service_relation(
            service2, "db")
        yield self.setup_unit_relations(
            service_relation, (service_unit1, "up"))

        self.setup_exit(0)
        finished = self.setup_cli_reactor()
        self.mocker.replay()

        main(["resolved", "wordpress/0", "db"])
        yield finished

        self.assertIn("Matched relations are all running",
                      self.output.getvalue())
        self.assertEqual(
            (yield service_unit1.get_relation_resolved()),
            None)
Example #7
0
class ControlCharmUpgradeTest(
    MachineControlToolTest, CharmUpgradeTestBase):

    @inlineCallbacks
    def setUp(self):
        yield super(ControlCharmUpgradeTest, self).setUp()
        config = {
            "environments": {"firstenv": {"type": "dummy"}}}

        self.write_config(dump(config))
        self.config.load()
        self.service_state1 = yield self.add_service_from_charm("mysql")
        self.service_unit1 = yield self.service_state1.add_unit_state()

        self.unit1_workflow = UnitWorkflowState(
            self.client, self.service_unit1, None, self.makeDir())
        yield self.unit1_workflow.set_state("started")

        self.environment = self.config.get_default()
        self.provider = self.environment.get_machine_provider()

        self.output = self.capture_logging()
        self.stderr = self.capture_stream("stderr")

    @inlineCallbacks
    def test_charm_upgrade(self):
        """
        'juju charm-upgrade <service_name>' will schedule
        a charm for upgrade.
        """
        repository = self.increment_charm(self.charm)

        mock_environment = self.mocker.patch(Environment)
        mock_environment.get_machine_provider()
        self.mocker.result(self.provider)

        finished = self.setup_cli_reactor()
        self.setup_exit(0)
        self.mocker.replay()
        main(["upgrade-charm", "--repository", repository.path, "mysql"])
        yield finished

        # Verify the service has a new charm reference
        charm_id = yield self.service_state1.get_charm_id()
        self.assertEqual(charm_id, "local:series/mysql-2")

        # Verify the provider storage has been updated
        charm = yield repository.find(CharmURL.parse("local:series/mysql"))
        storage = self.provider.get_file_storage()
        try:
            yield storage.get(
                "local_3a_series_2f_mysql-2_3a_%s" % charm.get_sha256())
        except FileNotFound:
            self.fail("New charm not uploaded")

        # Verify the upgrade flag on the service units.
        upgrade_flag = yield self.service_unit1.get_upgrade_flag()
        self.assertTrue(upgrade_flag)

    @inlineCallbacks
    def test_missing_repository(self):
        finished = self.setup_cli_reactor()
        self.setup_exit(0)
        self.mocker.replay()

        main(["upgrade-charm", "mysql"])
        yield finished

        self.assertIn("No repository specified", self.output.getvalue())

    @inlineCallbacks
    def test_upgrade_charm_with_unupgradeable_units(self):
        """If there are units that won't be upgraded, they will be reported,
        other units will be upgraded.
        """
        repository = self.increment_charm(self.charm)
        service_unit2 = yield self.service_state1.add_unit_state()

        finished = self.setup_cli_reactor()
        self.setup_exit(0)
        self.mocker.replay()

        main(["upgrade-charm", "--repository", repository.path, "mysql"])
        yield finished

        # Verify report of unupgradeable units
        self.assertIn(
            ("Unit 'mysql/1' is not in a running state "
            "(state: 'uninitialized'), won't upgrade"),
            self.output.getvalue())

        # Verify flags only set on upgradeable unit.
        value = (yield service_unit2.get_upgrade_flag())
        self.assertFalse(value)
        value = (yield self.service_unit1.get_upgrade_flag())
        self.assertTrue(value)

    @inlineCallbacks
    def test_upgrade_charm_unknown_service(self):
        finished = self.setup_cli_reactor()
        self.setup_exit(0)
        self.mocker.replay()
        main(["upgrade-charm", "--repository", self.makeDir(), "volcano"])
        yield finished
        self.assertIn(
            "Service 'volcano' was not found", self.stderr.getvalue())

    @inlineCallbacks
    def test_upgrade_charm_unknown_charm(self):
        """If a charm is not found in the repository, an error is given.
        """
        finished = self.setup_cli_reactor()
        self.setup_exit(0)
        self.mocker.replay()
        repository_dir = self.makeDir()
        os.mkdir(os.path.join(repository_dir, "series"))
        main(["upgrade-charm", "--repository", repository_dir, "mysql"])
        yield finished
        self.assertIn(
            "Charm 'local:series/mysql' not found in repository",
            self.output.getvalue())

    @inlineCallbacks
    def test_upgrade_charm_unknown_charm_dryrun(self):
        """If a charm is not found in the repository, an error is given.
        """
        finished = self.setup_cli_reactor()
        self.setup_exit(0)
        self.mocker.replay()
        repository_dir = self.makeDir()
        os.mkdir(os.path.join(repository_dir, "series"))
        main(["upgrade-charm", "--repository", repository_dir, "mysql", "--dry-run"])
        yield finished
        self.assertIn(
            "Charm 'local:series/mysql' not found in repository",
            self.output.getvalue())

    @inlineCallbacks
    def test_upgrade_charm_dryrun_reports_unupgradeable_units(self):
        """If there are units that won't be upgraded, dry-run will report them.
        """
        repository = self.increment_charm(self.charm)
        service_unit2 = yield self.service_state1.add_unit_state()

        finished = self.setup_cli_reactor()
        self.setup_exit(0)
        self.mocker.replay()

        main(["upgrade-charm", "-n",
              "--repository", repository.path, "mysql"])
        yield finished

        # Verify dry run
        self.assertIn(
            "Service would be upgraded from charm", self.output.getvalue())
        # Verify report of unupgradeable units
        self.assertIn(
            ("Unit 'mysql/1' is not in a running state "
            "(state: 'uninitialized'), won't upgrade"),
            self.output.getvalue())

        # Verify no flags have been set.
        value = (yield service_unit2.get_upgrade_flag())
        self.assertFalse(value)
        value = (yield self.service_unit1.get_upgrade_flag())
        self.assertFalse(value)


    @inlineCallbacks
    def test_latest_local_dry_run(self):
        """Do nothing; log that local charm would be re-revisioned and used"""
        finished = self.setup_cli_reactor()
        self.setup_exit(0)
        self.mocker.replay()

        metadata = self.charm.metadata.get_serialization_data()
        metadata["name"] = "mysql"
        repository = self.add_charm(metadata, 1)
        main(["upgrade-charm", "--dry-run",
                  "--repository", repository.path, "mysql"])
        yield finished
        charm_path = os.path.join(repository.path, "series", "mysql")
        self.assertIn(
            "%s would be set to revision 2" % charm_path,
            self.output.getvalue())
        self.assertIn(
            "Service would be upgraded from charm 'local:series/mysql-1' to "
            "'local:series/mysql-2'",
            self.output.getvalue())

        with open(os.path.join(charm_path, "revision")) as f:
            self.assertEquals(f.read(), "1")

        upgrade_flag = yield self.service_unit1.get_upgrade_flag()
        self.assertFalse(upgrade_flag)

    @inlineCallbacks
    def test_latest_local_live_fire(self):
        """Local charm should be re-revisioned and used; log that it was"""
        finished = self.setup_cli_reactor()
        self.setup_exit(0)
        self.mocker.replay()

        metadata = self.charm.metadata.get_serialization_data()
        metadata["name"] = "mysql"
        repository = self.add_charm(metadata, 1)
        main(["upgrade-charm", "--repository", repository.path, "mysql"])

        yield finished
        charm_path = os.path.join(repository.path, "series", "mysql")
        self.assertIn(
            "Setting %s to revision 2" % charm_path,
            self.output.getvalue())

        with open(os.path.join(charm_path, "revision")) as f:
            self.assertEquals(f.read(), "2\n")

        upgrade_flag = yield self.service_unit1.get_upgrade_flag()
        self.assertTrue(upgrade_flag)

    @inlineCallbacks
    def test_latest_local_leapfrog_dry_run(self):
        """Do nothing; log that local charm would be re-revisioned and used"""
        finished = self.setup_cli_reactor()
        self.setup_exit(0)
        self.mocker.replay()

        metadata = self.charm.metadata.get_serialization_data()
        metadata["name"] = "mysql"
        repository = self.add_charm(metadata, 0)
        main(["upgrade-charm", "--dry-run",
                  "--repository", repository.path, "mysql"])
        yield finished
        charm_path = os.path.join(repository.path, "series", "mysql")
        self.assertIn(
            "%s would be set to revision 2" % charm_path,
            self.output.getvalue())
        self.assertIn(
            "Service would be upgraded from charm 'local:series/mysql-1' to "
            "'local:series/mysql-2'",
            self.output.getvalue())

        with open(os.path.join(charm_path, "revision")) as f:
            self.assertEquals(f.read(), "0")

        upgrade_flag = yield self.service_unit1.get_upgrade_flag()
        self.assertFalse(upgrade_flag)

    @inlineCallbacks
    def test_latest_local_leapfrog_live_fire(self):
        """Local charm should be re-revisioned and used; log that it was"""
        finished = self.setup_cli_reactor()
        self.setup_exit(0)
        self.mocker.replay()

        metadata = self.charm.metadata.get_serialization_data()
        metadata["name"] = "mysql"
        repository = self.add_charm(metadata, 0)
        main(["upgrade-charm", "--repository", repository.path, "mysql"])

        yield finished
        charm_path = os.path.join(repository.path, "series", "mysql")
        self.assertIn(
            "Setting %s to revision 2" % charm_path,
            self.output.getvalue())

        with open(os.path.join(charm_path, "revision")) as f:
            self.assertEquals(f.read(), "2\n")

        upgrade_flag = yield self.service_unit1.get_upgrade_flag()
        self.assertTrue(upgrade_flag)

    @inlineCallbacks
    def test_latest_local_bundle_dry_run(self):
        """Do nothing; log that nothing would be done"""
        finished = self.setup_cli_reactor()
        self.setup_exit(0)
        self.mocker.replay()

        metadata = self.charm.metadata.get_serialization_data()
        metadata["name"] = "mysql"
        repository = self.add_charm(metadata, 1, bundle=True)
        main(["upgrade-charm", "--dry-run",
              "--repository", repository.path, "mysql"])
        yield finished
        self.assertIn(
            "Service already running latest charm",
            self.output.getvalue())

        upgrade_flag = yield self.service_unit1.get_upgrade_flag()
        self.assertFalse(upgrade_flag)

    @inlineCallbacks
    def test_latest_local_bundle_live_fire(self):
        """Do nothing; log that nothing was done"""
        finished = self.setup_cli_reactor()
        self.setup_exit(0)
        self.mocker.replay()

        metadata = self.charm.metadata.get_serialization_data()
        metadata["name"] = "mysql"
        repository = self.add_charm(metadata, 1, bundle=True)
        main(["upgrade-charm", "--repository", repository.path, "mysql"])

        yield finished
        self.assertIn(
            "Charm 'local:series/mysql-1' is the latest revision known",
            self.output.getvalue())

        upgrade_flag = yield self.service_unit1.get_upgrade_flag()
        self.assertFalse(upgrade_flag)
Example #8
0
class RemoteUpgradeCharmTest(MachineControlToolTest):

    @inlineCallbacks
    def setUp(self):
        yield super(RemoteUpgradeCharmTest, self).setUp()
        config = {
            "environments": {"firstenv": {"type": "dummy"}}}

        self.write_config(dump(config))
        self.config.load()

        charm = CharmDirectory(os.path.join(
            test_repository_path, "series", "mysql"))
        self.charm_state_manager.add_charm_state(
            "cs:series/mysql-1", charm, "")
        self.service_state1 = yield self.add_service_from_charm(
            "mysql", "cs:series/mysql-1")
        self.service_unit1 = yield self.service_state1.add_unit_state()

        self.unit1_workflow = UnitWorkflowState(
            self.client, self.service_unit1, None, self.makeDir())
        yield self.unit1_workflow.set_state("started")

        self.environment = self.config.get_default()
        self.provider = self.environment.get_machine_provider()

        self.output = self.capture_logging()
        self.stderr = self.capture_stream("stderr")

    @inlineCallbacks
    def test_latest_dry_run(self):
        """Do nothing; log that nothing would be done"""
        finished = self.setup_cli_reactor()
        self.setup_exit(0)
        getPage = self.mocker.replace("twisted.web.client.getPage")
        getPage(
            "https://store.juju.ubuntu.com/"
            "charm-info?charms=cs%3Aseries/mysql")
        self.mocker.result(succeed(json.dumps(
            {"cs:series/mysql": {"revision": 1, "sha256": "whatever"}})))
        self.mocker.replay()

        main(["upgrade-charm", "--dry-run", "mysql"])
        yield finished
        self.assertIn(
            "Service already running latest charm",
            self.output.getvalue())

        upgrade_flag = yield self.service_unit1.get_upgrade_flag()
        self.assertFalse(upgrade_flag)

    @inlineCallbacks
    def test_latest_live_fire(self):
        """Do nothing; log that nothing was done"""
        finished = self.setup_cli_reactor()
        self.setup_exit(0)

        getPage = self.mocker.replace("twisted.web.client.getPage")
        getPage(
            "https://store.juju.ubuntu.com/charm-info?charms=cs%3Aseries/mysql")
        self.mocker.result(succeed(json.dumps(
            {"cs:series/mysql": {"revision": 1, "sha256": "whatever"}})))
        self.mocker.replay()

        main(["upgrade-charm", "mysql"])

        yield finished
        self.assertIn(
            "Charm 'cs:series/mysql-1' is the latest revision known",
            self.output.getvalue())

        upgrade_flag = yield self.service_unit1.get_upgrade_flag()
        self.assertFalse(upgrade_flag)