Example #1
0
 def test_expireIsEnvironmentSpecific(self):
     """ExpireNode only updates the Environment set on the Node."""
     node = create_node("somewhere", "myservice", "env1")
     node2 = create_node("somewhere2", "myservice", "env2")
     disco = create_disco()
     disco.onMessage(None, NodeActive(node))
     disco.onMessage(None, NodeActive(node2))
     disco.onMessage(None, NodeExpired(node))
     self.assertEqual((knownNodes(disco, "myservice", "env1"),
                       knownNodes(disco, "myservice", "env2")),
                      ([], [node2]))
Example #2
0
 def test_replaceIsEnvironmentSpecific(self):
     """ReplaceCluster only updates the Environment set on the Node."""
     node = create_node("somewhere", "myservice", "env1")
     node2 = create_node("somewhere2", "myservice", "env2")
     node3 = create_node("somewhere3", "myservice", "env2")
     disco = create_disco()
     disco.onMessage(None, NodeActive(node))
     disco.onMessage(None, NodeActive(node2))
     disco.onMessage(
         None, ReplaceCluster(node3.service, node3.environment, [node3]))
     self.assertEqual((knownNodes(disco, "myservice", "env1"),
                       knownNodes(disco, "myservice", "env2")),
                      ([node], [node3]))
Example #3
0
    def test_activeDoesNotMutate(self):
        """
        A resolved Node is not mutated by a new NodeActive for same address.
        """
        disco = create_disco()
        node = create_node("somewhere")
        disco.onMessage(None, NodeActive(node))
        resolved_node = resolve(disco, "myservice", "1.0")

        node2 = create_node("somewhere")
        node2.version = "1.3"
        disco.onMessage(None, NodeActive(node2))
        self.assertEqual(resolved_node.version, "1.0")
Example #4
0
 def test_activeUpdatesMatchingAddress(self):
     """NodeActive updates a Node with same address to new version and properties."""
     disco = create_disco()
     node = create_node("somewhere")
     disco.onMessage(None, NodeActive(node))
     node2 = create_node("somewhere")
     node2.version = "1.7"
     node2.properties = {"a": 123}
     disco.onMessage(None, NodeActive(node2))
     self.assertEqual(knownNodes(disco, "myservice", "sandbox"), [node2])
     resolved = resolve(disco, "myservice", "1.7")
     self.assertEqual((resolved.version, resolved.properties), ("1.7", {
         "a": 123
     }))
Example #5
0
 def test_unknownServiceChildArrivesFirst(self):
     """
     If resolution can't return an answer immediately, and the child environment
     gets a node later on, the resolution gets that result.
     """
     env = _parseEnvironment("parent:child")
     node = create_node("somewhere", "myservice", "parent:child")
     disco = create_disco()
     promise = disco.resolve("myservice", "1.0", env)
     disco.onMessage(None, NodeActive(node))
     self.assertEqual(promise.value().getValue().address, "somewhere")
     # If a parent node arrives we don't blow up:
     disco.onMessage(
         None,
         NodeActive(create_node("somewhereelse", "myservice", "parent")))
Example #6
0
 def test_expired(self):
     """NodeExpired removes a Node from Discovery."""
     disco = create_disco()
     node = create_node("somewhere")
     disco.onMessage(None, NodeActive(node))
     disco.onMessage(None, NodeExpired(node))
     self.assertEqual(knownNodes(disco, "myservice", "sandbox"), [])
Example #7
0
 def test_resolve(self):
     """Resolve is limited to the specified environment."""
     node = create_node("somewhere", "myservice", "env1")
     node2 = create_node("somewhere2", "myservice", "env2")
     disco = create_disco()
     disco.onMessage(None, NodeActive(node))
     disco.onMessage(None, NodeActive(node2))
     # Do repeatedly in case round robin is somehow tricking us:
     for i in range(10):
         self.assertEqual(
             resolve(disco, "myservice", "1.0", "env1").address,
             "somewhere")
     for i in range(10):
         self.assertEqual(
             resolve(disco, "myservice", "1.0", "env2").address,
             "somewhere2")
Example #8
0
 def run_interaction(children):
     should_fail = next(failures)
     failed = []
     succeeded = []
     self.session.start_interaction()
     for child in children:
         if isinstance(child, unicode):
             # Make sure disco knows about the node:
             if child in created_services:
                 node = created_services[child]
             else:
                 node = create_node(child, child)
                 created_services[child] = node
             self.disco.onMessage(None, NodeActive(node))
             # Make sure the child Node is resolved in the interaction
             self.session.resolve(node.service, "1.0")
             if should_fail:
                 expected_failed_nodes[node] += 1
                 failed.append(node)
             else:
                 expected_success_nodes[node] += 1
                 succeeded.append(node)
         else:
             run_interaction(child)
     if should_fail:
         self.session.fail_interaction("OHNO")
     self.session.finish_interaction()
     self.connector.advance_time(5.0)  # Make sure interaction is sent
     ws_actor.swallowLogMessages()
     self.connector.expectInteraction(self, ws_actor, self.session,
                                      failed, succeeded)
Example #9
0
 def test_replace(self):
     """
     ReplaceCluster replaces the contents of a Cluster (collection of Nodes for
     the same service name).
     """
     disco = create_disco()
     node1 = create_node("somewhere")
     node2 = create_node("somewhere2")
     node3 = create_node("somewhere3")
     node4 = create_node("somewhere4")
     disco.onMessage(None, NodeActive(node1))
     disco.onMessage(None, NodeActive(node2))
     disco.onMessage(
         None, ReplaceCluster("myservice", SANDBOX_ENV, [node3, node4]))
     self.assertEqual(knownNodes(disco, "myservice", "sandbox"),
                      [node3, node4])
Example #10
0
 def test_noInheritanceAfterRegister(self):
     """
     Once a service/version pair have been registered in the child environment,
     the parent environment isn't used even if there are currently no nodes
     available in the child.
     """
     node = create_node("somewhere", "myservice", "parent:child")
     disco = create_disco()
     disco.onMessage(None, NodeActive(node))
     # Uh oh, service went away in the child!
     disco.onMessage(None, NodeExpired(node))
     # But it still exists in parent
     node2 = create_node("somewhere2", "myservice", "parent")
     disco.onMessage(None, NodeActive(node2))
     # However, since it existed in the child before, we won't get version
     # from the parent.
     self.assertEqual(resolve(disco, "myservice", "1.0", "parent:child"),
                      None)
Example #11
0
 def test_environmentReverseInheritance(self):
     """
     A parent environment doesn't get access to Nodes in the child environment.
     """
     # In the child only
     node = create_node("somewhere", "myservice", "parent:child")
     disco = create_disco()
     disco.onMessage(None, NodeActive(node))
     # Parent can't find it
     self.assertEqual(resolve(disco, "myservice", "1.0", "parent"), None)
Example #12
0
 def test_environmentInheritanceVersions(self):
     """
     If an Environment has a parent it is checked if there are no Nodes that have
     ever been registered with that service and version in the child
     Environment.
     """
     # This one won't work if we need 1.0:
     node = create_node("somewhere2.0", "myservice", "parent:child")
     node.version = "2.0"
     # So we expect to fall back to this:
     node2 = create_node("somewhere1.0", "myservice", "parent")
     disco = create_disco()
     disco.onMessage(None, NodeActive(node))
     disco.onMessage(None, NodeActive(node2))
     # Do repeatedly in case round robin is somehow tricking us:
     for i in range(10):
         self.assertEqual(
             resolve(disco, "myservice", "1.0", "parent:child").address,
             "somewhere1.0")
Example #13
0
    def test_activeDoesNotDisableCircuitBreaker(self):
        """
        If a Node has been disabled by a CircuitBreaker then NodeActive with same
        Node doesn't re-enable it.
        """
        disco = create_disco()
        node = create_node("somewhere")
        disco.onMessage(None, NodeActive(node))
        resolved_node = resolve(disco, "myservice", "1.0")
        # Uh-oh it's a pretty broken node:
        for i in range(10):
            resolved_node.failure()

        node = create_node("somewhere")
        disco.onMessage(None, NodeActive(node))
        resolved_node2 = resolve(disco, "myservice", "1.0")
        self.assertEqual(resolved_node2, None)
        resolved_node.success()
        self.assertNodesEqual(resolve(disco, "myservice", "1.0"), node)
Example #14
0
 def test_notify(self):
     """
     The notify() API allows getting all events passed to the Discovery instance.
     """
     disco = create_disco()
     messages = [object(), NodeActive(create_node("hello"))]
     result = []
     disco.notify(result.append)
     for m in messages:
         disco.onMessage(None, m)
     self.assertEqual(messages, result)
Example #15
0
 def test_resolve(self):
     """resolve() returns a Node matching an active one."""
     disco = create_disco()
     node = create_node("somewhere")
     node.properties = {"x": 1}
     disco.onMessage(None, NodeActive(node))
     resolved = resolve(disco, "myservice", "1.0")
     self.assertEqual((resolved.version, resolved.address, resolved.service,
                       resolved.properties),
                      ("1.0", "somewhere", "myservice", {
                          "x": 1
                      }))
Example #16
0
 def test_environmentInheritance(self):
     """
     If an Environment has a parent it is checked if there have never been Nodes
     with that service name registered in the child Environment.
     """
     # In the parent only
     node = create_node("somewhere", "myservice", "parent")
     # In the child
     node2 = create_node("somewhere2", "myservice2", "parent:child")
     disco = create_disco()
     disco.onMessage(None, NodeActive(node))
     disco.onMessage(None, NodeActive(node2))
     # Do repeatedly in case round robin is somehow tricking us:
     for i in range(10):
         self.assertEqual(
             resolve(disco, "myservice", "1.0", "parent:child").address,
             "somewhere")
     for i in range(10):
         self.assertEqual(
             resolve(disco, "myservice2", "1.0", "parent:child").address,
             "somewhere2")
Example #17
0
    def test_activeTriggersWaitingPromises(self):
        """
        NodeActive causes waiting resolve() Promises to get a Node.
        """
        disco = create_disco()
        result = []
        promise = disco.resolve("myservice", "1.0", SANDBOX_ENV)
        promise.andThen(result.append)
        self.assertFalse(result)

        node = create_node("somewhere")
        disco.onMessage(None, NodeActive(node))
        disco.runtime.dispatcher.pump()
        self.assertNodesEqual(result[0], node)
Example #18
0
    def test_replaceDoesNotMutate(self):
        """
        A resolved Node is not mutated by a new ReplaceCluster containing a Node
        with the same address.
        """
        disco = create_disco()
        node = create_node("somewhere")
        disco.onMessage(None, NodeActive(node))
        resolved_node = resolve(disco, "myservice", "1.0")

        node2 = create_node("somewhere")
        node2.version = "1.3"
        disco.onMessage(None, ReplaceCluster("myservice", SANDBOX_ENV,
                                             [node2]))
        self.assertEqual(resolved_node.version, "1.0")
Example #19
0
    def test_nodeCircuitBreaker(self):
        """success()/failure() enable and disable the Node."""
        disco = create_disco()
        node = create_node("somewhere")
        disco.onMessage(None, NodeActive(node))
        resolved_node = resolve(disco, "myservice", "1.0")

        avail1 = resolved_node.available()
        # Default threshold in CircuitBreaker is three failures:
        resolved_node.failure()
        resolved_node.failure()
        resolved_node.failure()
        avail2 = resolved_node.available()
        resolved_node.success()
        avail3 = resolved_node.available()
        self.assertEqual((avail1, avail2, avail3), (True, False, True))
Example #20
0
    def execute_step(self, step):
        command, args = step
        if command == "add":
            service, address = args
            message = NodeActive(self.create_node(address, service))
            self.fake.add(service, address)
        elif command == "remove":
            service, address = args
            message = NodeExpired(self.create_node(address, service))
            self.fake.remove(service, address)
        elif command == "replace":
            service, addresses = args
            nodes = [
                self.create_node(address, service) for address in addresses
            ]
            message = ReplaceCluster(service, SANDBOX_ENV, nodes)
            self.fake.replace(service, addresses)
        else:
            raise AssertionError("Unknown command.")

        self.real.onMessage(None, message)
        self.fake.compare(self.real)
Example #21
0
 def add_nodes(self, mdk):
     """Register existence of nodes with the MDK instance."""
     mdk._disco.onMessage(None, NodeActive(self.node1))
     mdk._disco.onMessage(None, NodeActive(self.node2))
     mdk._disco.onMessage(None, NodeActive(self.node3))
Example #22
0
 def test_active(self):
     """NodeActive adds a Node to Discovery."""
     disco = create_disco()
     node = create_node("somewhere")
     disco.onMessage(None, NodeActive(node))
     self.assertEqual(knownNodes(disco, "myservice", "sandbox"), [node])