diff --git a/CHANGELOG.md b/CHANGELOG.md index d4b67f4..2d58af2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## Fixed + +- Cap generated test ids to 255 characters to avoid file system errors ([#35]). + +[#35]: https://github.com/stackabletech/beku.py/pull/35 + ## 0.0.10 - 2024-11-06 ## Added diff --git a/src/beku/kuttl.py b/src/beku/kuttl.py index 83162ad..0f0690c 100644 --- a/src/beku/kuttl.py +++ b/src/beku/kuttl.py @@ -5,6 +5,7 @@ import logging import os import re +import hashlib from dataclasses import dataclass, field from functools import cached_property from hashlib import sha256 @@ -94,6 +95,11 @@ def make_test_source_with_context( return TestFile(file_name=file_name, source_dir=source_dir, dest_dir=dest_dir) +def tid_short_hash(tid: str) -> str: + """Take the first 10 chars of the hash of the given `tid`.""" + return hashlib.sha256(tid.encode()).hexdigest()[:10] + + @dataclass(frozen=True) class TestCase: """A test case is an instance of test definition together with a set of Jinja variables used to render all @@ -113,8 +119,11 @@ def tid(self) -> str: """Return the test id. Used as destination folder name for the generated test case. The result is part of a full directory name of the test case. Therefore, the OS filesystem directory separator is replaced with underscore. + + Since the result is also used as a folder name, we restrict it's length to 255 characters. + This is because some filesystems complain if the name is longer that that. """ - return re.sub( + name = re.sub( f"[{os.sep}:]", "_", "_".join( @@ -124,6 +133,12 @@ def tid(self) -> str: ) ), ) + max_len = 255 + if len(name) > max_len: + name_hash = tid_short_hash(name) + return f"{name[: max_len - len(name_hash) - 1]}_{name_hash}" + else: + return name def expand(self, template_dir: str, target_dir: str, namespace: str) -> None: """Expand test case This will create the target folder, copy files and render render templates."""