From 018520297d97b9573aeaf482b133abf98c86a0eb Mon Sep 17 00:00:00 2001 From: tmartins Date: Thu, 2 Jul 2020 22:18:28 +0200 Subject: write application files before local deployment --- python/vespa/vespa/package.py | 43 ++++++++++++++++++++++++++----- python/vespa/vespa/templates/schema.txt | 2 +- python/vespa/vespa/templates/services.xml | 6 ++--- python/vespa/vespa/test_package.py | 20 +++++++++++--- 4 files changed, 56 insertions(+), 15 deletions(-) (limited to 'python') diff --git a/python/vespa/vespa/package.py b/python/vespa/vespa/package.py index 9c66defd4d9..4606b111f5e 100644 --- a/python/vespa/vespa/package.py +++ b/python/vespa/vespa/package.py @@ -1,5 +1,8 @@ +import os from time import sleep from typing import List, Mapping, Optional +from tempfile import TemporaryDirectory +from pathlib import Path from jinja2 import Environment, PackageLoader, select_autoescape import docker @@ -138,7 +141,9 @@ class FieldSet(ToJson, FromJson["FieldSet"]): class RankProfile(ToJson, FromJson["RankProfile"]): - def __init__(self, name: str, first_phase: str) -> None: + def __init__( + self, name: str, first_phase: str, inherits: Optional[str] = None + ) -> None: """ Define a Vespa rank profile @@ -147,20 +152,31 @@ class RankProfile(ToJson, FromJson["RankProfile"]): """ self.name = name self.first_phase = first_phase + self.inherits = inherits @staticmethod def from_dict(mapping: Mapping) -> "RankProfile": - return RankProfile(name=mapping["name"], first_phase=mapping["first_phase"]) + return RankProfile( + name=mapping["name"], + first_phase=mapping["first_phase"], + inherits=mapping.get("inherits", None), + ) @property def to_dict(self) -> Mapping: map = {"name": self.name, "first_phase": self.first_phase} + if self.inherits is not None: + map.update({"inherits": self.inherits}) return map def __eq__(self, other): if not isinstance(other, self.__class__): return False - return self.name == other.name and self.first_phase == other.first_phase + return ( + self.name == other.name + and self.first_phase == other.first_phase + and self.inherits == other.inherits + ) def __repr__(self): return "{0}\n{1}".format(self.__class__.__name__, str(self.to_dict)) @@ -295,9 +311,10 @@ class ApplicationPackage(ToJson, FromJson["ApplicationPackage"]): == "HTTP/1.1 200 OK" ) - def deploy_locally(self, disk_folder, container_memory: str = "4G"): + def deploy_locally(self, disk_folder: str, container_memory: str = "4G"): + + self.create_application_package_files(dir_path=disk_folder) - # todo: use `with tempfile.TemporaryDirectory() as dirpath:` to create a temp dir and write app files there. self.run_vespa_engine_container( disk_folder=disk_folder, container_memory=container_memory ) @@ -355,10 +372,22 @@ class ApplicationPackage(ToJson, FromJson["ApplicationPackage"]): env.lstrip_blocks = True schema_template = env.get_template("services.xml") return schema_template.render( - application_name=self.name, - document_name=self.schema.name, + application_name=self.name, document_name=self.schema.name, ) + def create_application_package_files(self, dir_path): + Path(os.path.join(dir_path, "application/schemas")).mkdir(parents=True, exist_ok=True) + with open( + os.path.join( + dir_path, "application/schemas/{}.sd".format(self.schema.name) + ), + "w", + ) as f: + f.write(self.schema_to_text) + with open(os.path.join(dir_path, "application/hosts.xml"), "w") as f: + f.write(self.hosts_to_text) + with open(os.path.join(dir_path, "application/services.xml"), "w") as f: + f.write(self.services_to_text) @staticmethod def from_dict(mapping: Mapping) -> "ApplicationPackage": diff --git a/python/vespa/vespa/templates/schema.txt b/python/vespa/vespa/templates/schema.txt index a16e7c2775c..0849cbbad6f 100644 --- a/python/vespa/vespa/templates/schema.txt +++ b/python/vespa/vespa/templates/schema.txt @@ -17,7 +17,7 @@ schema {{ schema_name }} { } {% endfor %} {% for key, value in rank_profiles.items() %} - rank-profile {{ key }} { + rank-profile {{ key }}{% if value.inherits %} inherits {{ value.inherits }}{% endif %} { {% if value.first_phase %} first-phase { expression: {{ value.first_phase }} diff --git a/python/vespa/vespa/templates/services.xml b/python/vespa/vespa/templates/services.xml index 0e5a05e180a..e287e53107d 100644 --- a/python/vespa/vespa/templates/services.xml +++ b/python/vespa/vespa/templates/services.xml @@ -1,15 +1,15 @@ - + - + 1 - + diff --git a/python/vespa/vespa/test_package.py b/python/vespa/vespa/test_package.py index 0650bcdf400..e76e1cf3994 100644 --- a/python/vespa/vespa/test_package.py +++ b/python/vespa/vespa/test_package.py @@ -99,6 +99,12 @@ class TestRankProfile(unittest.TestCase): self.assertEqual(rank_profile.first_phase, "bm25(title) + bm25(body)") self.assertEqual(rank_profile, RankProfile.from_dict(rank_profile.to_dict)) + def test_rank_profile_inherits(self): + rank_profile = RankProfile(name="bm25", first_phase="bm25(title) + bm25(body)", inherits="default") + self.assertEqual(rank_profile.name, "bm25") + self.assertEqual(rank_profile.first_phase, "bm25(title) + bm25(body)") + self.assertEqual(rank_profile, RankProfile.from_dict(rank_profile.to_dict)) + class TestSchema(unittest.TestCase): def test_schema(self): @@ -152,7 +158,8 @@ class TestApplicationPackage(unittest.TestCase): ), fieldsets=[FieldSet(name="default", fields=["title", "body"])], rank_profiles=[ - RankProfile(name="default", first_phase="nativeRank(title, body)") + RankProfile(name="default", first_phase="nativeRank(title, body)"), + RankProfile(name="bm25", first_phase="bm25(title) + bm25(body)", inherits="default") ], ) self.app_package = ApplicationPackage(name="test_app", schema=test_schema) @@ -185,6 +192,11 @@ class TestApplicationPackage(unittest.TestCase): " expression: nativeRank(title, body)\n" \ " }\n" \ " }\n" \ + " rank-profile bm25 inherits default {\n" \ + " first-phase {\n" \ + " expression: bm25(title) + bm25(body)\n" \ + " }\n" \ + " }\n" \ "}" self.assertEqual(self.app_package.schema_to_text, expected_result) @@ -201,16 +213,16 @@ class TestApplicationPackage(unittest.TestCase): def test_services_to_text(self): expected_result = '\n' \ '\n' \ - ' \n' \ + ' \n' \ ' \n' \ ' \n' \ ' \n' \ ' \n' \ - ' \n' \ + ' \n' \ ' 1\n' \ ' \n' \ ' \n' \ - ' \n' \ + ' \n' \ ' \n' \ ' \n' \ ' \n' \ -- cgit v1.2.3