def setup_class(cls): cls.messaging_service = MessagingService() cls.messaging_service.service_start() cls.messaging_service.wait_for_start(15) cls.conn = WeaveConnection.local() cls.conn.connect() cls.env_service = DummyEnvService(cls.messaging_service.test_token, cls.conn) rpc_info = find_rpc(cls.env_service, MESSAGING_PLUGIN_URL, "app_manager") appmgr_client = RPCClient(cls.env_service.get_connection(), rpc_info, cls.env_service.get_auth_token()) appmgr_client.start() http_token = appmgr_client["register_plugin"]("http", WEAVE_HTTP_URL, _block=True) dummy_token = appmgr_client["register_plugin"]("x", "y", _block=True) cls.http = ThreadedWeaveHTTPService(auth_token=http_token, plugin_dir="x", venv_dir="y", conn=cls.conn, started_token="") cls.http.service_start() cls.http.wait_for_start(15) cls.dummy_service = DummyService(cls.conn, dummy_token) cls.dummy_service.service_start() cls.dummy_service.wait_for_start(15)
class DummyService(MessagingEnabled, BaseService): def __init__(self, conn, token): super(DummyService, self).__init__(auth_token=token, conn=conn) apis = [ ServerAPI("api", "desc1", [ ArgParameter("param", "d1", str), ], self.api), ServerAPI("number", "desc1", [ ArgParameter("param", "d1", int), ], self.number), ServerAPI("exception", "desc1", [], self.exception), ] self.rpc_server = RPCServer("name", "desc", apis, self) dashboard_rpc_info = find_rpc(self, "b", "static_files") self.http_client = RPCClient(self.get_connection(), dashboard_rpc_info, self.get_auth_token()) def number(self, param): return param + 1 def api(self, param): return "API" + param def exception(self): raise ObjectNotFound("blah") def on_service_start(self): self.rpc_server.start() self.http_client.start() def on_service_stop(self): self.http_client.stop() self.rpc_server.stop()
class MessagingRegistrationHook(StateHook): def __init__(self, service: MessagingEnabled): self.service = service self.client: RPCClient = None def load(self, plugin_state: PluginState): rpc_info = find_rpc(self.service, MESSAGING_PLUGIN_URL, "app_manager") self.client = RPCClient(self.service.get_connection(), rpc_info, self.service.get_auth_token()) self.client.start() plugin_state.app_manager_client = self.client if plugin_state.enabled: self.on_activate(plugin_state) def stop(self): self.client.stop() def on_activate(self, state: PluginState): state.token = self.client["register_plugin"](state.name, state.remote_url, _block=True) def on_deactivate(self, plugin_state: PluginState): self.client["unregister_plugin"](plugin_state.remote_url, _block=True) plugin_state.token = None
def start(self): rpc = self.service.rpc_client["rpc_info"] rpc_info = rpc("weaveserver.services.simpledb", "object_store", _block=True) self.db_rpc = RPCClient(self.conn, rpc_info, self.service.token) self.db_rpc.start()
def handle_rpc(): class FakeService(MessagingEnabled): def __init__(self, auth_token, conn): super(FakeService, self).__init__(auth_token=auth_token, conn=conn) def start(self): self.get_connection().connect() app_url = sys.argv[1] rpc_name = sys.argv[2] api_name = sys.argv[3] json_args = sys.argv[4] plugins_db = PluginsDatabase(os.path.join(get_config_path(), "db")) plugins_db.start() conn = WeaveConnection.discover() conn.connect() instance_data = get_instance_data() token = instance_data.app_token rpc_info = find_rpc(FakeService(token, conn), app_url, rpc_name) client = RPCClient(conn, rpc_info, token) client.start() print( json.dumps(client[api_name](*json.loads(json_args), _block=True), indent=2))
class AppDBConnection(object): def __init__(self, conn, service): self.conn = conn self.service = service self.db_rpc = None def start(self): rpc = self.service.rpc_client["rpc_info"] rpc_info = rpc("weaveserver.services.simpledb", "object_store", _block=True) self.db_rpc = RPCClient(self.conn, rpc_info, self.service.token) self.db_rpc.start() def stop(self): self.db_rpc.stop() def __getitem__(self, key): try: return self.db_rpc["query"](key, _block=True) except ObjectNotFound: raise KeyError(key) def __setitem__(self, key, value): self.db_rpc["insert"](key, value, _block=True)
def load(self, plugin_state: PluginState): rpc_info = find_rpc(self.service, MESSAGING_PLUGIN_URL, "app_manager") self.client = RPCClient(self.service.get_connection(), rpc_info, self.service.get_auth_token()) self.client.start() plugin_state.app_manager_client = self.client if plugin_state.enabled: self.on_activate(plugin_state)
def __init__(self, conn, token): super(DummyService, self).__init__(auth_token=token, conn=conn) apis = [ ServerAPI("api", "desc1", [ ArgParameter("param", "d1", str), ], self.api), ServerAPI("number", "desc1", [ ArgParameter("param", "d1", int), ], self.number), ServerAPI("exception", "desc1", [], self.exception), ] self.rpc_server = RPCServer("name", "desc", apis, self) dashboard_rpc_info = find_rpc(self, "b", "static_files") self.http_client = RPCClient(self.get_connection(), dashboard_rpc_info, self.get_auth_token())
def test_several_functions_invoke(self): info = self.service.rpc_server.info_message self.service.paused = True client = RPCClient(self.conn, info, self.test_token) client.start() api1 = client["api1"] api2 = client["api2"] res = [] with ThreadPoolExecutor(max_workers=100) as exc: for i in range(20): future = exc.submit(api1, "iter", i, k3=i % 2 == 0, _block=True) expected = "iter{}{}".format(i, i % 2 == 0) res.append((future, expected)) future = exc.submit(api2, _block=True) res.append((future, "API2")) time.sleep(5) self.service.paused = False for future, expected in res: assert future.result() == expected exc.shutdown() client.stop()
def test_register_queue(self): conn = WeaveConnection.local() conn.connect() client = RPCClient(conn, self.appmgr_rpc_info, TEST_APP_TOKEN) client.start() res = client["register_queue"]("test_queue/", "fifo", { "type": "string" }, [MESSAGING_SERVER_URL], [TEST_URL], _block=True) assert res == "/channels/{}/test_queue".format(TEST_URL) sender_no_auth = Sender(conn, res, auth=TEST_APP_TOKEN) sender_no_auth.start() with pytest.raises(Unauthorized): sender_no_auth.send("test") sender_auth = Sender(conn, res, auth=MESSAGING_APP_TOKEN) sender_auth.send("test") receiver_no_auth = Receiver(conn, res, auth=MESSAGING_APP_TOKEN) with pytest.raises(Unauthorized): receiver_no_auth.receive() receiver_auth = Receiver(conn, res, auth=TEST_APP_TOKEN) assert "test" == receiver_auth.receive().task client.stop()
def register_plugin(service, plugin): conn = service.get_connection() token = service.get_auth_token() # TODO: Find a find to get find_rpc(..) work for core system RPC too. rpc_info = find_rpc(service, None) client = RPCClient(conn, rpc_info, token) # TODO: Make InstalledPlugin, and RunnablePlugin have GitHub url in them. return client["register_plugin"](plugin.plugin_id(), plugin.name, plugin.src, _block=True)
def handle_rpc(self, body): app_url = get_required_argument(body, 'app_url') rpc_name = get_required_argument(body, 'rpc_name') api_name = get_required_argument(body, 'api_name') args = get_required_argument(body, 'args') with self.clients_lock: client = self.clients.get((app_url, rpc_name), None) if not client: rpc_info = find_rpc(self.service, app_url, rpc_name) with self.clients_lock: client = self.clients.get((app_url, rpc_name), None) if not client: client = RPCClient(self.service.get_connection(), rpc_info, self.service.get_auth_token()) client.start() self.clients[(app_url, rpc_name)] = client response = client[api_name](*args, _block=True) return response
def test_server_function_invoke(self): info = self.service.rpc_server.info_message client = RPCClient(self.conn, info, self.test_token) client.start() res = client["api1"]("hello", 5, k3=False, _block=True) assert res == "hello5False" client.stop()
def test_rpc_caller(self): info = self.service.rpc_server.info_message client = RPCClient(self.conn, info, self.test_token) client.start() res = client["api3"](_block=True) expected = {"app_name": "x", "app_url": "y", "app_type": "plugin"} assert res == expected client.stop()
def test_api_with_exception(self): info = self.service.rpc_server.info_message client = RPCClient(self.conn, info, self.test_token) client.start() with pytest.raises(RemoteAPIError): client["exception"](_block=True) client["exception"]() # Exception is not visible. client.stop()
def test_register_unregister_plugin(self): conn = WeaveConnection.local() conn.connect() client = RPCClient(conn, self.appmgr_rpc_info, TEST_APP_TOKEN) client.start() token = client["register_plugin"]("name", "url1", _block=True) assert token assert client["unregister_plugin"]("url1", _block=True) client.stop() conn.close()
def test_callback_rpc_invoke(self): info = self.service.rpc_server.info_message client = RPCClient(self.conn, info, self.test_token) client.start() event = Event() result = [] def callback(res): result.append(extract_rpc_payload(res)) event.set() client["api1"]("hello", 5, k3=False, _callback=callback) event.wait() assert result[0] == "hello5False" client.stop()
def test_api_with_exception_callback(self): info = self.service.rpc_server.info_message client = RPCClient(self.conn, info, self.test_token) client.start() event = Event() result = [] def callback(res): result.append(res) event.set() client["exception"](_callback=callback) event.wait() with pytest.raises(RemoteAPIError): extract_rpc_payload(result[0]) client.stop()
def setup_class(cls): cls.messaging_service = MessagingService() cls.messaging_service.service_start() cls.messaging_service.wait_for_start(15) cls.conn = WeaveConnection.local() cls.conn.connect() cls.env_service = DummyEnvService(cls.messaging_service.test_token, cls.conn) rpc_info = find_rpc(cls.env_service, MESSAGING_PLUGIN_URL, "app_manager") appmgr_client = RPCClient(cls.env_service.get_connection(), rpc_info, cls.env_service.get_auth_token()) appmgr_client.start() # Register the DummyService used in the test cases. cls.test_token = appmgr_client["register_plugin"]("x", "y", _block=True) appmgr_client.stop()
class HTTPResourceRegistrationHelper(object): def __init__(self, service): self.service = service self.rpc_client = None self.watchers = [] def start(self): rpc_info = find_rpc(self.service, WEAVE_HTTP_URL, "static_files") self.rpc_client = RPCClient(self.service.get_connection(), rpc_info, self.service.get_auth_token()) self.rpc_client.start() def stop(self): self.rpc_client.stop() for watcher in self.watchers: watcher.stop() for watcher in self.watchers: watcher.join() def register_content(self, content, rel_http_url, block=True, callback=None): param = b64encode(content).decode('ascii') return self.rpc_client["register"](rel_http_url, param, _block=block, _callback=callback) def register_file(self, local_path, relative_http_url, block=True, callback=None): with open(local_path, "rb") as inp: content = inp.read() return self.register_content(content, relative_http_url, block=block, callback=callback) def register_directory(self, local_path, relative_http_url): files_tuple = [] for cur_folder, _, files in os.walk(local_path): for filename in files: cur_file = os.path.join(cur_folder, filename) files_tuple.append( (cur_file, os.path.relpath(cur_file, local_path))) events = {} responses = {} response_lock = Lock() def make_callback(rel_path, event): def callback(response): with response_lock: responses[rel_path] = response event.set() return callback for abs_path, rel_path in files_tuple: cur_rel_http_url = os.path.join(relative_http_url, rel_path) event = Event() events[rel_path] = event callback = make_callback(rel_path, event) self.register_file(abs_path, cur_rel_http_url, block=False, callback=callback) base_rel_url = None for rel_path, event in events.items(): event.wait() with response_lock: rel_url = extract_rpc_payload(responses[rel_path]) if base_rel_url is None and rel_url.endswith(rel_path): base_rel_url = rel_url[:-len(rel_path)] return base_rel_url def unregister_url(self, url, block=True, callback=None): return self.rpc_client["unregister"](url, _block=block, _callback=callback)
def test_api_with_dynamic_schema(self): info = self.service.rpc_server.info_message client = RPCClient(self.conn, info, self.test_token) client.start() assert client["callback"]("1", _block=True) client["change_param"]("hi,there", _block=True) client.stop() info = self.service.rpc_server.info_message client = RPCClient(self.conn, info, self.test_token) client.start() with pytest.raises(BadArguments): client["callback"]("1", _block=True) client.stop() client = RPCClient(self.conn, info, self.test_token) client.start() assert client["callback"]("hi", _block=True) assert client["callback"]("there", _block=True) client.stop()
def start(self): rpc_info = find_rpc(self.service, WEAVE_HTTP_URL, "static_files") self.rpc_client = RPCClient(self.service.get_connection(), rpc_info, self.service.get_auth_token()) self.rpc_client.start()
def test_register_as_non_system_app(self): conn = WeaveConnection.local() conn.connect() client = RPCClient(conn, self.appmgr_rpc_info, TEST_APP_TOKEN) client.start() token = client["register_plugin"]("name", "url1", _block=True) plugin_client = RPCClient(conn, self.appmgr_rpc_info, token) plugin_client.start() with pytest.raises(AuthenticationFailed): plugin_client["register_plugin"]("a", "b", _block=True) plugin_client.stop() client.stop() conn.close()
def test_register_rpc_with_whitelists(self): conn = WeaveConnection.local() conn.connect() client = RPCClient(conn, self.appmgr_rpc_info, TEST_APP_TOKEN) client.start() data = { "1": { "name": "name1", "url": "url1", "rpc_name": "rpc1", "allowed_requestors": [] }, "2": { "name": "name2", "url": "url2", "rpc_name": "rpc2", "allowed_requestors": ["url1"] }, "3": { "name": "name3", "url": "url3", "rpc_name": "rpc3", "allowed_requestors": ["diff-url"] }, } for info in data.values(): info["token"] = client["register_plugin"](info["name"], info["url"], _block=True) service = DummyMessagingService(info["token"], conn) info["server"] = RPCServer(info["rpc_name"], "desc", [ ServerAPI("name", "desc", [ ArgParameter("param", "desc", str), ], lambda x: x), ], service, info["allowed_requestors"]) info["server"].start() info["rpc_info"] = find_rpc(service, info["url"], info["rpc_name"]) allowed_requestors = [ ("1", "2"), ("1", "1"), ("2", "1"), ("3", "1"), ] disallowed_requestors = [("1", "3"), ("2", "2"), ("2", "3"), ("3", "2"), ("3", "3")] for source, target in allowed_requestors: plugin_client = RPCClient(conn, data[target]["rpc_info"], data[source]["token"]) plugin_client.start() assert plugin_client["name"]("x", _block=True) == "x" plugin_client.stop() for source, target in disallowed_requestors: plugin_client = RPCClient(conn, data[target]["rpc_info"], data[source]["token"]) plugin_client.start() with pytest.raises(Unauthorized): plugin_client["name"]("x", _block=True) plugin_client.stop() for info in data.values(): info["server"].stop() client.stop() conn.close()