feat: Dagu DAGと配置手順を追加
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
from pathlib import Path
|
||||
import re
|
||||
import unittest
|
||||
|
||||
import unifydrive2nas as app
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
DAG_PATH = ROOT / "deploy" / "dagu" / "unifydrive2nas.yaml"
|
||||
PROJECT_PATH = ROOT / "PROJECT.md"
|
||||
INSTALL_DIRECTORY = "/volume1/homes/kazu634/bin/unifydrive2nas"
|
||||
SCRIPT_PATH = INSTALL_DIRECTORY + "/unifydrive2nas.py"
|
||||
DAG_STAGING_PATH = "/tmp/unifydrive2nas.yaml"
|
||||
DAGU_COMMAND = "DAGU_HOME=/var/lib/dagu /usr/local/bin/dagu"
|
||||
|
||||
|
||||
class DaguDeploymentContractTests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.dag = DAG_PATH.read_text(encoding="utf-8")
|
||||
cls.project = PROJECT_PATH.read_text(encoding="utf-8")
|
||||
|
||||
def dag_value(self, key):
|
||||
pattern = r"^\s*" + re.escape(key) + r":\s*(.*?)\s*$"
|
||||
values = re.findall(pattern, self.dag, flags=re.MULTILINE)
|
||||
self.assertEqual(1, len(values), "DAG の {0} は一意であること".format(key))
|
||||
return values[0].strip('"\'')
|
||||
|
||||
def test_schedule_and_execution_guards(self):
|
||||
self.assertEqual("0 4 * * *", self.dag_value("schedule"))
|
||||
self.assertEqual("skip", self.dag_value("overlap_policy"))
|
||||
self.assertEqual("7200", self.dag_value("timeout_sec"))
|
||||
self.assertIn("毎日 04:00(Asia/Tokyo)", self.project)
|
||||
self.assertIn('schedule: "0 4 * * *"', self.project)
|
||||
|
||||
def test_ssh_target_and_single_command(self):
|
||||
expected = {
|
||||
"action": "ssh.run",
|
||||
"host": "192.168.10.201",
|
||||
"port": "22",
|
||||
"user": "kazu634",
|
||||
"key": "/home/kazu634/.ssh/id_ed25519_nas",
|
||||
"strict_host_key": "true",
|
||||
"known_host_file": "/home/kazu634/.ssh/known_hosts",
|
||||
"command": "python3 " + SCRIPT_PATH,
|
||||
}
|
||||
for key, value in expected.items():
|
||||
with self.subTest(key=key):
|
||||
self.assertEqual(value, self.dag_value(key))
|
||||
self.assertIn("| Synology `ds923p` | `192.168.10.201`", self.project)
|
||||
self.assertIn("ssh -i ~/.ssh/id_ed25519_nas kazu634@192.168.10.201", self.project)
|
||||
self.assertIn("`" + INSTALL_DIRECTORY + "/`", self.project)
|
||||
|
||||
def test_ssh_settings_are_nested_in_one_step_with_block(self):
|
||||
match = re.search(
|
||||
r"^steps:\n"
|
||||
r" - id: copy_unifydrive_to_nas\n"
|
||||
r" action: ssh\.run\n"
|
||||
r" with:\n"
|
||||
r"((?: [^\n]+\n?)+)$",
|
||||
self.dag,
|
||||
flags=re.MULTILINE,
|
||||
)
|
||||
self.assertIsNotNone(match)
|
||||
with_block = match.group(1)
|
||||
for key in (
|
||||
"host",
|
||||
"port",
|
||||
"user",
|
||||
"key",
|
||||
"strict_host_key",
|
||||
"known_host_file",
|
||||
"command",
|
||||
):
|
||||
with self.subTest(key=key):
|
||||
self.assertRegex(with_block, r"(?m)^ " + re.escape(key) + r":")
|
||||
self.assertEqual(1, self.dag.count("command:"))
|
||||
|
||||
def test_project_documents_deployment_contract(self):
|
||||
required_values = (
|
||||
"毎日 04:00",
|
||||
"/volume1/homes/kazu634/bin/unifydrive2nas/",
|
||||
"deploy/dagu/unifydrive2nas.yaml",
|
||||
"/var/lib/dagu/dags/",
|
||||
"kazu634/UnifyDrive2NAS",
|
||||
"--init",
|
||||
)
|
||||
for value in required_values:
|
||||
with self.subTest(value=value):
|
||||
self.assertIn(value, self.project)
|
||||
|
||||
def test_default_database_is_shared_by_implementation_project_and_dag(self):
|
||||
expected = Path.home() / ".local" / "state" / "unifydrive2nas" / "copied.sqlite3"
|
||||
self.assertEqual(expected, app.DEFAULT_DATABASE)
|
||||
self.assertIn("`~/.local/state/unifydrive2nas/copied.sqlite3`", self.project)
|
||||
self.assertNotIn("--database", self.dag_value("command"))
|
||||
|
||||
def test_deployment_commands_use_consistent_paths_and_exclude_tests(self):
|
||||
section = self.project.split("### 配置手順", 1)[1].split("## 外部とのつながり", 1)[0]
|
||||
blocks = re.findall(r"```bash\n(.*?)\n[ \t]*```", section, flags=re.DOTALL)
|
||||
self.assertEqual(8, len(blocks))
|
||||
(
|
||||
runtime_copy,
|
||||
runtime_dry_run,
|
||||
initialize,
|
||||
staging_copy,
|
||||
validate,
|
||||
dag_dry_run,
|
||||
manual_start,
|
||||
schedule_enable,
|
||||
) = blocks
|
||||
|
||||
self.assertIn("--exclude='__pycache__' unifydrive2nas.py vendor", runtime_copy)
|
||||
self.assertNotIn("tests/", runtime_copy)
|
||||
self.assertIn("tar -C " + INSTALL_DIRECTORY + " -xf -", runtime_copy)
|
||||
|
||||
self.assertIn("python3 " + SCRIPT_PATH + " --dry-run", runtime_dry_run)
|
||||
self.assertIn("python3 " + SCRIPT_PATH + " --init", initialize)
|
||||
self.assertNotIn("--database", initialize)
|
||||
|
||||
self.assertIn("-C deploy/dagu unifydrive2nas.yaml", staging_copy)
|
||||
self.assertIn("tar -C /tmp -xf -", staging_copy)
|
||||
self.assertNotIn("tests/", staging_copy)
|
||||
|
||||
self.assertIn(DAGU_COMMAND + " validate " + DAG_STAGING_PATH, validate)
|
||||
self.assertIn(DAGU_COMMAND + " dry " + DAG_STAGING_PATH, dag_dry_run)
|
||||
self.assertIn(DAGU_COMMAND + " start " + DAG_STAGING_PATH, manual_start)
|
||||
|
||||
self.assertIn("-C deploy/dagu unifydrive2nas.yaml", schedule_enable)
|
||||
self.assertIn("tar -C /var/lib/dagu/dags -xf -", schedule_enable)
|
||||
self.assertIn("rm -f " + DAG_STAGING_PATH, schedule_enable)
|
||||
|
||||
def test_verification_uses_temporary_tests_on_nas(self):
|
||||
section = self.project.split("## 確かめ方", 1)[1]
|
||||
blocks = re.findall(r"```bash\n(.*?)\n[ \t]*```", section, flags=re.DOTALL)
|
||||
verification = next(block for block in blocks if "unifydrive2nas.py vendor tests" in block)
|
||||
unpack = "tar -C /tmp/unifydrive2nas-test -xf -"
|
||||
run_tests = (
|
||||
"cd /tmp/unifydrive2nas-test && "
|
||||
"python3 -W error::ResourceWarning -m unittest discover -s tests -v"
|
||||
)
|
||||
cleanup = "rm -rf /tmp/unifydrive2nas-test"
|
||||
production_dry_run = "python3 " + SCRIPT_PATH + " --dry-run"
|
||||
|
||||
self.assertIn("--exclude='__pycache__' unifydrive2nas.py vendor tests", verification)
|
||||
self.assertIn(unpack, verification)
|
||||
self.assertIn(run_tests, verification)
|
||||
self.assertEqual(2, verification.count(cleanup))
|
||||
self.assertIn(production_dry_run, verification)
|
||||
self.assertLess(verification.index(unpack), verification.index(run_tests))
|
||||
self.assertLess(verification.index(run_tests), verification.rindex(cleanup))
|
||||
self.assertLess(verification.rindex(cleanup), verification.index(production_dry_run))
|
||||
|
||||
def test_all_documented_dagu_commands_use_service_home(self):
|
||||
commands = re.findall(r"/usr/local/bin/dagu (?:validate|dry|start) [^\s\"']+", self.project)
|
||||
self.assertEqual(5, len(commands))
|
||||
self.assertEqual(5, self.project.count(DAGU_COMMAND))
|
||||
self.assertNotIn("/usr/local/bin/dagu", self.project.replace(DAGU_COMMAND, ""))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user