def test_get_config(client): _dir = os.path.dirname(os.path.abspath(__file__)) load_config(os.path.join(_dir, "test-config.yaml"), True) rv = client.get("/api/config") data = rv.json() # dynaconf conversts to uppercase all root level json keys log.debug(f"config: {data}") assert data["pipelines".upper()] is not None assert data["ai_models".upper()] is not None assert data["sources".upper()] is not None
def test_main_heartbeat_log(my_dir): load_config(os.path.join(my_dir, "test-config-no-pipelines.yaml"), True) # remove all root servers which we will not test here ambianic.server.ROOT_SERVERS.clear() # set heartbeat log interval to a small enough # interval so the test passes faster ambianic.server.MAIN_HEARTBEAT_LOG_INTERVAL = 0.1 srv, t = _start_mock_server(work_dir=my_dir) t.join(timeout=2) assert srv._main_heartbeat_logged _stop_mock_server(server=srv, thread=t)
def test_config_change(): _dir = os.path.dirname(os.path.abspath(__file__)) config_file = os.path.join(_dir, 'test-config-no-pipelines.yaml') load_config(config_file, True) hb_flag = threading.Event() srv, t = _start_mock_server(work_dir=_dir, heartbeat_flag=hb_flag) hb_flag.wait(timeout=3) Path(config_file).touch() time.sleep(3) assert hb_flag.is_set() assert srv.config_changed _stop_mock_server(server=srv, thread=t)
def test_heartbeat_threshold(my_dir): load_config(os.path.join(my_dir, "test-config-no-pipelines.yaml"), clean=True) # replace default with test pipeline server # remove all root servers which we won't test here ambianic.server.ROOT_SERVERS.clear() ambianic.server.ROOT_SERVERS["pipelines"] = _BadPipelineServer srv, t = _start_mock_server(work_dir=my_dir) t.join(timeout=2) pps = srv._servers["pipelines"] assert isinstance(pps, _BadPipelineServer) assert pps._heal_called _stop_mock_server(server=srv, thread=t)
def test_main(my_dir): os.environ["AMBIANIC_DIR"] = my_dir config.clean() load_config(os.path.join(my_dir, "test-config-no-pipelines.yaml"), clean=True) t = threading.Thread(target=__main__.main, daemon=True) t.start() t.join(timeout=1) __main__.stop() t.join(timeout=3) assert not t.is_alive()
def start(self): """Programmatic start of the main service.""" assert os.path.exists(self._env_work_dir) # reload configuration load_config(get_config_file()) logger.configure(config.get("logging")) timeline_event.configure_timeline(config.get("timeline")) # watch configuration changes self.start_watch_config() log.info("Starting Ambianic server...") # Register the signal handlers servers = {} # Start the job threads try: for s_name, s_class in ROOT_SERVERS.items(): srv = s_class(config=config) srv.start() servers[s_name] = srv self._latest_heartbeat = time.monotonic() self._servers = servers # Keep the main thread running, otherwise signals are ignored. while True: time.sleep(0.5) self._healthcheck(servers) self._heartbeat() except ServiceExit: log.info("Service exit requested.") # stop servers and cleanup references self._stop_servers(servers) self._servers = {} self._service_exit_requested = False # stop watching config files self.stop_watch_config() if self._service_restart_requested: self._service_restart_requested = False log.info("Restarting Ambianic server.") return self.start() log.info("Exiting Ambianic server.") return True
def test_config_change(my_dir): config_file = os.path.join(my_dir, "test-config-no-pipelines.yaml") load_config(config_file, True) hb_flag = threading.Event() srv, t = None, None try: srv, t = _start_mock_server(work_dir=my_dir, heartbeat_flag=hb_flag) hb_flag.wait(timeout=3) Path(config_file).touch() time.sleep(3) assert hb_flag.is_set() assert srv.config_changed finally: _stop_mock_server(server=srv, thread=t)
def test_secrets(): default_secret = ambianic.__SECRETS_FILE ambianic.__SECRETS_FILE = os.path.join(_dir, "secrets.yaml") cfg = load_config(os.path.join(_dir, 'test-config-secrets.yaml'), True) ambianic.__SECRETS_FILE = default_secret assert cfg.get("question") == 42 assert cfg.deeeper.question.on.life == 42
def test_no_pipelines(my_dir): load_config(os.path.join(my_dir, "test-config-no-pipelines.yaml"), clean=True) assert config.get("pipelines") is None hb_flag = threading.Event() srv, t = None, None try: srv, t = _start_mock_server(work_dir=my_dir, heartbeat_flag=hb_flag) assert srv assert t hb_flag.wait(timeout=3) assert hb_flag.is_set() pps = srv._servers["pipelines"] assert isinstance(pps, ambianic.pipeline.interpreter.PipelineServer) assert not pps.pipeline_server_job.job._pipelines finally: _stop_mock_server(server=srv, thread=t)
def test_set_device_display_name(client, request, tmp_path): config_filepath = Path(request.fspath.dirname) / "test-config.yaml" log.debug(f"current config file is: {config_filepath}") # copy config file to a temp location to test saving changes tmp_config_path = copy(config_filepath, tmp_path) log.debug(f"temp config file is: {tmp_config_path}") load_config(filename=tmp_config_path, clean=True) log.debug(f"config:{config.to_dict()}") config["display_name"] = "Some Random Display Name" # this API call should change the display name in the saved config new_name = "Kitchen Device" rv = client.put(f"/api/device/display_name/{new_name}") assert rv.status_code == status.HTTP_204_NO_CONTENT # log.debug(f"put -> /api/device/display_name: JSON response: {rv.json()}") # reload config and see if the value set through the API was persisted log.debug(f"config:{config.to_dict()}") load_config(filename=tmp_config_path, clean=True) assert config["display_name"] == new_name # now check that the API will return the new value rv = client.get("/api/device/display_name") data = rv.json() log.debug(f"get -> /api/device/display_name: JSON response: {data}") assert data == new_name
def test_no_pipelines(): load_config(os.path.join(_dir, 'test-config-no-pipelines.yaml'), True) assert config.get("pipelines", None) is None