Skip to content

Commit c8714db

Browse files
authored
Use project specific name in devfile (#280)
* Use unique project specific name in devfile * Fix existing unit tests by mocking the behavior of new method * Refactor logic for lines that were not covered by tests * Add unit test for new method * Code cleanup
1 parent f8f5a83 commit c8714db

File tree

7 files changed

+136
-5
lines changed

7 files changed

+136
-5
lines changed

src/ansible_creator/resources/common/devfile/devfile.yaml.j2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
schemaVersion: 2.2.2
22
metadata:
3-
name: ansible-demo
3+
name: {{ dev_file_name }}
44
components:
55
- name: tooling-container
66
container:

src/ansible_creator/subcommands/init.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from __future__ import annotations
44

55
import shutil
6+
import uuid
67

78
from pathlib import Path
89
from typing import TYPE_CHECKING
@@ -110,13 +111,28 @@ def init_exists(self) -> None:
110111
err = f"failed to remove existing directory {self._init_path}: {e}"
111112
raise CreatorError(err) from e
112113

114+
def unique_name_in_devfile(self) -> str:
115+
"""Use project specific name in devfile.
116+
117+
Returns:
118+
Unique name entry.
119+
"""
120+
final_name: str
121+
if self._project == "collection":
122+
final_name = f"{self._namespace}.{self._collection_name}"
123+
if self._project == "ansible-project":
124+
final_name = f"{self._scm_org}.{self._scm_project}"
125+
final_uuid = str(uuid.uuid4())[:8]
126+
return f"{final_name}-{final_uuid}"
127+
113128
def _scaffold_collection(self) -> None:
114129
"""Scaffold a collection project."""
115130
self.output.debug(msg="started copying collection skeleton to destination")
116131
template_data = TemplateData(
117132
namespace=self._namespace,
118133
collection_name=self._collection_name,
119134
creator_version=self._creator_version,
135+
dev_file_name=self.unique_name_in_devfile(),
120136
)
121137
copier = Copier(
122138
resources=["collection_project", *self.common_resources],
@@ -141,6 +157,7 @@ def _scaffold_playbook(self: Init) -> None:
141157
creator_version=self._creator_version,
142158
scm_org=self._scm_org,
143159
scm_project=self._scm_project,
160+
dev_file_name=self.unique_name_in_devfile(),
144161
)
145162

146163
copier = Copier(

src/ansible_creator/types.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class TemplateData:
2222
creator_version: The version of the creator.
2323
dev_container_image: The devcontainer image.
2424
dev_file_image: The devfile image.
25+
dev_file_name: The unique name entry in devfile.
2526
namespace: The namespace of the collection.
2627
recommended_extensions: A list of recommended VsCode extensions.
2728
scm_org: The organization of the source control management.
@@ -33,6 +34,7 @@ class TemplateData:
3334
creator_version: str = ""
3435
dev_container_image: Sequence[str] = GLOBAL_TEMPLATE_VARS["DEV_CONTAINER_IMAGE"]
3536
dev_file_image: Sequence[str] = GLOBAL_TEMPLATE_VARS["DEV_FILE_IMAGE"]
37+
dev_file_name: str = ""
3638
namespace: str = ""
3739
recommended_extensions: Sequence[str] = field(
3840
default_factory=lambda: GLOBAL_TEMPLATE_VARS["RECOMMENDED_EXTENSIONS"],

tests/defaults.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@
66

77

88
FIXTURES_DIR = (Path(__file__).parent / "fixtures").resolve()
9+
10+
UUID_LENGTH = 8

tests/fixtures/collection/testorg/testcol/devfile.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
schemaVersion: 2.2.2
22
metadata:
3-
name: ansible-demo
3+
name: testorg.testcol
44
components:
55
- name: tooling-container
66
container:

tests/fixtures/project/playbook_project/devfile.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
schemaVersion: 2.2.2
22
metadata:
3-
name: ansible-demo
3+
name: weather.demo
44
components:
55
- name: tooling-container
66
container:

tests/units/test_init.py

Lines changed: 112 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from ansible_creator.output import Output
1818
from ansible_creator.subcommands.init import Init
1919
from ansible_creator.utils import TermFeatures
20-
from tests.defaults import FIXTURES_DIR
20+
from tests.defaults import FIXTURES_DIR, UUID_LENGTH
2121

2222

2323
class ConfigDict(TypedDict):
@@ -51,7 +51,7 @@ def fixture_cli_args(tmp_path: Path, output: Output) -> ConfigDict:
5151
"""Create a dict to use for a Init class object as fixture.
5252
5353
Args:
54-
tmp_path: App configuration object.
54+
tmp_path: Temporary directory path.
5555
output: Output class object.
5656
5757
Returns:
@@ -94,18 +94,34 @@ def test_run_success_for_collection(
9494
capsys: pytest.CaptureFixture[str],
9595
tmp_path: Path,
9696
cli_args: ConfigDict,
97+
monkeypatch: pytest.MonkeyPatch,
9798
) -> None:
9899
"""Test Init.run().
99100
100101
Args:
101102
capsys: Pytest fixture to capture stdout and stderr.
102103
tmp_path: Temporary directory path.
103104
cli_args: Dictionary, partial Init class object.
105+
monkeypatch: Pytest monkeypatch fixture.
104106
"""
105107
cli_args["project"] = "collection"
106108
init = Init(
107109
Config(**cli_args),
108110
)
111+
112+
# Mock the "unique_name_in_devfile" method
113+
def mock_unique_name_in_devfile(self: Init) -> str:
114+
coll_namespace = self._namespace
115+
coll_name = self._collection_name
116+
return f"{coll_namespace}.{coll_name}"
117+
118+
# Apply the mock
119+
monkeypatch.setattr(
120+
Init,
121+
"unique_name_in_devfile",
122+
mock_unique_name_in_devfile,
123+
)
124+
109125
init.run()
110126
result = capsys.readouterr().out
111127

@@ -140,6 +156,7 @@ def test_run_success_ansible_project(
140156
capsys: pytest.CaptureFixture[str],
141157
tmp_path: Path,
142158
cli_args: ConfigDict,
159+
monkeypatch: pytest.MonkeyPatch,
143160
) -> None:
144161
"""Test Init.run().
145162
@@ -149,6 +166,7 @@ def test_run_success_ansible_project(
149166
capsys: Pytest fixture to capture stdout and stderr.
150167
tmp_path: Temporary directory path.
151168
cli_args: Dictionary, partial Init class object.
169+
monkeypatch: Pytest monkeypatch fixture.
152170
"""
153171
cli_args["collection"] = ""
154172
cli_args["project"] = "ansible-project"
@@ -158,6 +176,20 @@ def test_run_success_ansible_project(
158176
init = Init(
159177
Config(**cli_args),
160178
)
179+
180+
# Mock the "unique_name_in_devfile" method
181+
def mock_unique_name_in_devfile(self: Init) -> str:
182+
coll_namespace = self._scm_org
183+
coll_name = self._scm_project
184+
return f"{coll_namespace}.{coll_name}"
185+
186+
# Apply the mock
187+
monkeypatch.setattr(
188+
Init,
189+
"unique_name_in_devfile",
190+
mock_unique_name_in_devfile,
191+
)
192+
161193
init.run()
162194
result = capsys.readouterr().out
163195

@@ -292,3 +324,81 @@ def test_is_file_error(tmp_path: Path) -> None:
292324
with pytest.raises(CreatorError) as exc_info:
293325
init.run()
294326
assert "but is a file" in str(exc_info.value)
327+
328+
329+
@pytest.fixture(name="cli_args_collection")
330+
def fixture_collection_project(tmp_path: Path, output: Output) -> Config:
331+
"""Fixture for Config object with collection project.
332+
333+
Args:
334+
tmp_path: Temporary directory path.
335+
output: Output class object.
336+
337+
Returns:
338+
Config: Config class object.
339+
"""
340+
return Config(
341+
subcommand="init",
342+
namespace="testns",
343+
collection_name="testname",
344+
init_path=str(tmp_path / "test_path"),
345+
force=False,
346+
creator_version="1.0.0",
347+
project="collection",
348+
scm_org="",
349+
scm_project="",
350+
output=output,
351+
)
352+
353+
354+
@pytest.fixture(name="cli_args_playbook")
355+
def fixture_playbook_project(tmp_path: Path, output: Output) -> Config:
356+
"""Fixture for Config object with ansible-project.
357+
358+
Args:
359+
tmp_path: Temporary directory path.
360+
output: Output class object.
361+
362+
Returns:
363+
Config: Config class object.
364+
"""
365+
return Config(
366+
subcommand="init",
367+
namespace="",
368+
collection_name="",
369+
init_path=str(tmp_path / "test_path"),
370+
force=False,
371+
creator_version="1.0.0",
372+
project="ansible-project",
373+
scm_org="foo",
374+
scm_project="bar",
375+
output=output,
376+
)
377+
378+
379+
def test_name_in_devfile_collection(cli_args_collection: Config) -> None:
380+
"""Test unique_name_in_devfile method for collection project.
381+
382+
Args:
383+
cli_args_collection: Configuration object for collection project.
384+
"""
385+
init = Init(cli_args_collection)
386+
unique_name = init.unique_name_in_devfile()
387+
assert unique_name.startswith("testns.testname-")
388+
uuid_part = unique_name.split("-")[-1] # Extract the UUID part
389+
assert len(uuid_part) == UUID_LENGTH, "UUID part length mismatch"
390+
391+
392+
def test_name_in_devfile_playbook(
393+
cli_args_playbook: Config,
394+
) -> None:
395+
"""Test unique_name_in_devfile method for playbook project.
396+
397+
Args:
398+
cli_args_playbook: Configuration object for playbook project.
399+
"""
400+
init = Init(cli_args_playbook)
401+
unique_name = init.unique_name_in_devfile()
402+
assert unique_name.startswith("foo.bar-")
403+
uuid_part = unique_name.split("-")[-1] # Extract the UUID part
404+
assert len(uuid_part) == UUID_LENGTH, "UUID part length mismatch"

0 commit comments

Comments
 (0)