Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a new --templates-path option #78

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/ansible_creator/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,13 @@ def parse_args(self: Cli) -> argparse.Namespace:
"current working directory.",
)

init_command_parser.add_argument(
"--templates-path",
help="Path to a directory containing custom template for collection skeleton."
" When provided, this will be used to scaffold the collection instead of the"
" in-built template.",
)

init_command_parser.add_argument(
"--force",
default=False,
Expand Down
18 changes: 18 additions & 0 deletions src/ansible_creator/compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""Compat library for ansible-creator.

This contains compatibility definitions for older python
When we need to import a module differently depending on python versions, we do it
here.
"""

# ruff: noqa: F401
ssbarnea marked this conversation as resolved.
Show resolved Hide resolved

# pylint: disable=unused-import

import sys


if sys.version_info >= (3, 11):
from importlib.resources.abc import Traversable
else:
from importlib.abc import Traversable
4 changes: 4 additions & 0 deletions src/ansible_creator/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
no_ansi: bool
subcommand: str
verbose: int
templates_path: str

collection: str = ""
force: bool = False
Expand All @@ -36,4 +37,7 @@
object.__setattr__(self, "namespace", fqcn[0])
object.__setattr__(self, "collection_name", fqcn[-1])

if self.templates_path:
object.__setattr__(self, "template", expand_path(self.init_path))

Check warning on line 41 in src/ansible_creator/config.py

View check run for this annotation

Codecov / codecov/patch

src/ansible_creator/config.py#L41

Added line #L41 was not covered by tests

object.__setattr__(self, "init_path", expand_path(self.init_path))
35 changes: 35 additions & 0 deletions src/ansible_creator/subcommands/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import annotations

import os
import re
import shutil

from typing import TYPE_CHECKING
Expand Down Expand Up @@ -36,6 +37,7 @@
self._force = config.force
self._creator_version = config.creator_version
self._templar = Templar()
self._templates_path = config.templates_path
self.output: Output = output

def run(self: Init) -> None:
Expand All @@ -47,6 +49,38 @@

self.output.debug(msg=f"final collection path set to {col_path}")

# validate custom templates
if self._templates_path:
full_templates_path = os.path.join(self._templates_path, "new_collection")

Check warning on line 54 in src/ansible_creator/subcommands/init.py

View check run for this annotation

Codecov / codecov/patch

src/ansible_creator/subcommands/init.py#L54

Added line #L54 was not covered by tests

# verify that templates path exists and has "new_collection" dir
if not os.path.exists(full_templates_path):
msg = f"could not find templates for new collection at {self._templates_path}."
raise CreatorError(msg)

Check warning on line 59 in src/ansible_creator/subcommands/init.py

View check run for this annotation

Codecov / codecov/patch

src/ansible_creator/subcommands/init.py#L57-L59

Added lines #L57 - L59 were not covered by tests

# ensure that "new_collection" dir is not empty
if len(os.listdir(full_templates_path)) == 0:
msg = (

Check warning on line 63 in src/ansible_creator/subcommands/init.py

View check run for this annotation

Codecov / codecov/patch

src/ansible_creator/subcommands/init.py#L62-L63

Added lines #L62 - L63 were not covered by tests
"please ensure that a directory named `new_collection` exists"
f" at {self._templates_path} and is not empty."
)
raise CreatorError(msg)

Check warning on line 67 in src/ansible_creator/subcommands/init.py

View check run for this annotation

Codecov / codecov/patch

src/ansible_creator/subcommands/init.py#L67

Added line #L67 was not covered by tests

# ensure that a template for galaxy file exists in "new_collection" dir
if (

Check warning on line 70 in src/ansible_creator/subcommands/init.py

View check run for this annotation

Codecov / codecov/patch

src/ansible_creator/subcommands/init.py#L70

Added line #L70 was not covered by tests
len(
list(
filter(
re.compile("(?:galaxy.)(?:yml|yaml)(?:.j2)?").match,
os.listdir(full_templates_path),
),
),
)
== 0
):
msg = f"template for Ansible galaxy file not found in {full_templates_path!s}."
raise CreatorError(msg)

Check warning on line 82 in src/ansible_creator/subcommands/init.py

View check run for this annotation

Codecov / codecov/patch

src/ansible_creator/subcommands/init.py#L81-L82

Added lines #L81 - L82 were not covered by tests

# check if init_path already exists
if os.path.exists(col_path):
if os.path.isfile(col_path):
Expand Down Expand Up @@ -86,6 +120,7 @@
source="new_collection",
dest=col_path,
templar=self._templar,
templates_path=self._templates_path,
template_data={
"namespace": self._namespace,
"collection_name": self._collection_name,
Expand Down
22 changes: 17 additions & 5 deletions src/ansible_creator/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@

from dataclasses import dataclass
from importlib import resources
from pathlib import Path
from typing import TYPE_CHECKING

from ansible_creator.exceptions import CreatorError


if TYPE_CHECKING:
from importlib import abc

from ansible_creator.compat import Traversable

Check warning on line 16 in src/ansible_creator/utils.py

View check run for this annotation

Codecov / codecov/patch

src/ansible_creator/utils.py#L16

Added line #L16 was not covered by tests
from ansible_creator.output import Output
from ansible_creator.templar import Templar

Expand Down Expand Up @@ -84,6 +84,7 @@
output: Output,
templar: Templar,
template_data: dict[str, str],
templates_path: str,
allow_overwrite: list[str] | None = None,
) -> None:
"""Copy files and directories from a possibly nested source to a destination.
Expand All @@ -92,17 +93,21 @@
:param dest: Absolute destination path.
:param templar: An object of template class.
:param template_data: A dictionary containing data to render templates with.
:param templates_path: A string representing path to custom templates
:param allow_overwrite: A list of paths that should be overwritten at destination.

:raises CreatorError: if allow_overwrite is not a list.
"""
output.debug(msg=f"starting recursive copy with source container '{source}'")
output.debug(msg=f"allow_overwrite set to {allow_overwrite}")

def _recursive_copy(root: abc.Traversable) -> None:
if templates_path:
output.debug(msg=f"custom templates path set to {templates_path}")

Check warning on line 105 in src/ansible_creator/utils.py

View check run for this annotation

Codecov / codecov/patch

src/ansible_creator/utils.py#L105

Added line #L105 was not covered by tests

def _recursive_copy(root: Path | Traversable) -> None:
"""Recursively traverses a resource container and copies content to destination.

:param root: A traversable object representing root of the container to copy.
:param root: A traversable or Path object representing root of the container to copy.
"""
output.debug(msg=f"current root set to {root}")

Expand Down Expand Up @@ -142,4 +147,11 @@
with open(dest_file, "w", encoding="utf-8") as df_handle:
df_handle.write(content)

_recursive_copy(root=resources.files(f"ansible_creator.resources.{source}"))
if templates_path:
# use custom templates path
tp_root = Path(templates_path) / source
_recursive_copy(tp_root)

Check warning on line 153 in src/ansible_creator/utils.py

View check run for this annotation

Codecov / codecov/patch

src/ansible_creator/utils.py#L152-L153

Added lines #L152 - L153 were not covered by tests
else:
# use built-in templates
ib_root = resources.files(f"ansible_creator.resources.{source}")
_recursive_copy(ib_root)
3 changes: 3 additions & 0 deletions tests/units/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def test_expand_path() -> None:
"collection": "testorg.testcol",
"init_path": "./",
"force": False,
"templates_path": None,
},
],
[
Expand Down Expand Up @@ -60,6 +61,7 @@ def test_expand_path() -> None:
"collection": "testorg.testcol",
"init_path": "/home/ansible",
"force": True,
"templates_path": None,
},
],
],
Expand All @@ -83,6 +85,7 @@ def test_configuration_class() -> None:
"verbose": 2,
"collection": "testorg.testcol",
"init_path": "$HOME",
"templates_path": None,
}
app_config = Config(**cli_args)
assert app_config.namespace == "testorg"
Expand Down
1 change: 1 addition & 0 deletions tests/units/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def cli_args(tmp_path) -> dict:
"verbose": 0,
"collection": "testorg.testcol",
"init_path": tmp_path,
"templates_path": None,
}


Expand Down