def test_deploy_from_yaml(self, serve_instance):
        config_file_name = os.path.join(
            os.path.dirname(__file__), "test_config_files", "two_deployments.yaml"
        )

        # Check if yaml string and yaml file both produce the same Application
        with open(config_file_name, "r") as f:
            app1 = Application.from_yaml(f)
        with open(config_file_name, "r") as f:
            yaml_str = f.read()
        app2 = Application.from_yaml(yaml_str)
        compare_specified_options(app1.to_dict(), app2.to_dict())

        # Check that deployment works
        app1.deploy()
        assert (
            requests.get("http://localhost:8000/shallow").text == "Hello shallow world!"
        )
        assert requests.get("http://localhost:8000/one").text == "2"

        # Check if yaml string output is same as the Application
        recreated_app = Application.from_yaml(app1.to_yaml())
        compare_specified_options(recreated_app.to_dict(), app1.to_dict())

        # Check if yaml file output is same as the Application
        with tempfile.TemporaryFile(mode="w+") as tmp:
            app1.to_yaml(tmp)
            tmp.seek(0)
            compare_specified_options(
                Application.from_yaml(tmp).to_dict(), app1.to_dict()
            )
def test_get_set_item(serve_instance):
    config_file_name = os.path.join(
        os.path.dirname(__file__), "test_config_files", "two_deployments.yaml"
    )

    with open(config_file_name, "r") as f:
        app = Application.from_yaml(f)
    app["shallow"].deploy()
    app["one"].deploy()

    assert requests.get("http://localhost:8000/shallow").text == "Hello shallow world!"
    assert requests.get("http://localhost:8000/one").text == "2"
Exemple #3
0
    def test_convert_to_import_path(self, serve_instance):
        f = decorated_func.options(name="f")
        C = DecoratedClass.options(name="C")
        app = Application([f, C])

        reconstructed_app = Application.from_yaml(app.to_yaml())

        serve.run(reconstructed_app)
        assert requests.get(
            "http://localhost:8000/f").text == "got decorated func"
        assert requests.get(
            "http://localhost:8000/C").text == "got decorated class"
Exemple #4
0
def run(
    config_or_import_path: str,
    runtime_env: str,
    runtime_env_json: str,
    working_dir: str,
    app_dir: str,
    address: str,
    host: str,
    port: int,
    blocking: bool,
):
    sys.path.insert(0, app_dir)

    final_runtime_env = parse_runtime_env_args(
        runtime_env=runtime_env,
        runtime_env_json=runtime_env_json,
        working_dir=working_dir,
    )

    app_or_node = None
    if pathlib.Path(config_or_import_path).is_file():
        config_path = config_or_import_path
        cli_logger.print(f"Deploying from config file: '{config_path}'.")
        with open(config_path, "r") as config_file:
            app_or_node = Application.from_yaml(config_file)
    else:
        import_path = config_or_import_path
        cli_logger.print(f"Deploying from import path: '{import_path}'.")
        app_or_node = import_attr(import_path)

    # Setting the runtime_env here will set defaults for the deployments.
    ray.init(address=address, namespace="serve", runtime_env=final_runtime_env)

    try:
        serve.run(app_or_node, host=host, port=port)
        cli_logger.success("Deployed successfully.")

        if blocking:
            while True:
                # Block, letting Ray print logs to the terminal.
                time.sleep(10)

    except KeyboardInterrupt:
        cli_logger.info("Got KeyboardInterrupt, shutting down...")
        serve.shutdown()
        sys.exit()
Exemple #5
0
def test_immutable_deployment_list(serve_instance):
    config_file_name = os.path.join(os.path.dirname(__file__),
                                    "test_config_files",
                                    "two_deployments.yaml")

    with open(config_file_name, "r") as f:
        app = Application.from_yaml(f)

    assert len(app.deployments.values()) == 2

    for name in app.deployments.keys():
        with pytest.raises(RuntimeError):
            app.deployments[name] = app.deployments[name].options(
                name="sneaky")

    for deployment in app.deployments.values():
        deployment.deploy()

    assert requests.get(
        "http://localhost:8000/shallow").text == "Hello shallow world!"
    assert requests.get("http://localhost:8000/one").text == "2"
Exemple #6
0
def run(
    config_or_import_path: str,
    args_and_kwargs: Tuple[str],
    runtime_env: str,
    runtime_env_json: str,
    working_dir: str,
    address: str,
):

    # Check if path provided is for config or import
    is_config = pathlib.Path(config_or_import_path).is_file()
    args, kwargs = _process_args_and_kwargs(args_and_kwargs)

    # Calculate deployments' runtime env updates requested via args
    runtime_env_updates = parse_runtime_env_args(
        runtime_env=runtime_env,
        runtime_env_json=runtime_env_json,
        working_dir=working_dir,
    )

    # Create ray.init()'s runtime_env
    if "working_dir" in runtime_env_updates:
        ray_runtime_env = {
            "working_dir": runtime_env_updates.pop("working_dir")
        }
    else:
        ray_runtime_env = {}

    if is_config:
        config_path = config_or_import_path
        # Delay serve.start() to catch invalid inputs without waiting
        if len(args) + len(kwargs) > 0:
            raise ValueError(
                "ARGS_AND_KWARGS cannot be defined for a "
                "config file deployment. Please specify the "
                "init_args and init_kwargs inside the config file.")

        cli_logger.print("Deploying application in config file at "
                         f"{config_path}.")
        with open(config_path, "r") as config_file:
            app = Application.from_yaml(config_file)

    else:
        import_path = config_or_import_path
        if "." not in import_path:
            raise ValueError(
                "Import paths must be of the form "
                '"module.submodule_1...submodule_n.MyClassOrFunction".')

        cli_logger.print(
            f'Deploying function or class imported from "{import_path}".')

        deployment_name = import_path[import_path.rfind(".") + 1:]
        deployment = serve.deployment(name=deployment_name)(import_path)

        app = Application(
            [deployment.options(init_args=args, init_kwargs=kwargs)])

    ray.init(address=address, namespace="serve", runtime_env=ray_runtime_env)

    for deployment in app:
        _configure_runtime_env(deployment, runtime_env_updates)

    app.run(logger=cli_logger)