feat(templates_urls): short circuit input names
This commit is contained in:
@@ -47,7 +47,7 @@ def machine_template(
|
||||
|
||||
# Get the clan template from the specifier
|
||||
[flake_ref, template_selector] = transform_url(
|
||||
"machine", template_ident, local_path=flake
|
||||
"machine", template_ident, flake=flake
|
||||
)
|
||||
|
||||
template_flake = Flake(flake_ref)
|
||||
|
||||
@@ -16,10 +16,10 @@ class Flake(Protocol):
|
||||
@property
|
||||
def path(self) -> Path: ...
|
||||
|
||||
def get_input_names(self) -> list[str]: ...
|
||||
|
||||
def transform_url(
|
||||
template_type: str, identifier: str, local_path: Flake
|
||||
) -> tuple[str, str]:
|
||||
|
||||
def transform_url(template_type: str, identifier: str, flake: Flake) -> tuple[str, str]:
|
||||
"""
|
||||
Transform a template flake ref by injecting the context (clan|machine|disko) into the url.
|
||||
We do this for shorthand notation of URLs.
|
||||
@@ -56,6 +56,11 @@ def transform_url(
|
||||
clan machines create --template github:/org/repo#new.machine
|
||||
-> clanInternals.templates.machine."new.machine"
|
||||
|
||||
6. Templates locked via inputs:
|
||||
clan machines create --template clan-core#new-machine
|
||||
path: clan-core matches one of the input attributes.
|
||||
-> <local_flake>#inputs.clan-core.clan.templates.machine."new-machine"
|
||||
|
||||
As of URL specification (RFC 3986).
|
||||
scheme:[//[user:password@]host[:port]][/path][?query][#fragment]
|
||||
|
||||
@@ -76,22 +81,28 @@ def transform_url(
|
||||
# Substitute the flake reference with the local flake path if it is empty or just a dot.
|
||||
# This is required if the command will be executed from a different place, than the local flake root.
|
||||
if not flake_ref or flake_ref == ".":
|
||||
flake_ref = str(local_path.path)
|
||||
flake_ref = str(flake.path)
|
||||
|
||||
if "#" not in identifier:
|
||||
# No fragment, so we assume its a builtin template
|
||||
return (flake_ref, f'clanInternals.templates.{template_type}."{selector}"')
|
||||
|
||||
input_prefix = ""
|
||||
if flake_ref in flake.get_input_names():
|
||||
# Interpret the flake reference as an input of the local flake.
|
||||
input_prefix = f"inputs.{flake_ref}."
|
||||
flake_ref = str(flake.path)
|
||||
|
||||
# TODO: implement support for quotes in the tail "a.b".c
|
||||
# If the tail contains a dot, or is quoted we assume its a path and don't transform it.
|
||||
if '"' in selector or "'" in selector:
|
||||
log.warning(
|
||||
"Quotes in template paths are not yet supported. Please use unquoted paths."
|
||||
)
|
||||
return (flake_ref, selector)
|
||||
return (flake_ref, input_prefix + selector)
|
||||
|
||||
if "." in selector:
|
||||
return (flake_ref, selector)
|
||||
return (flake_ref, input_prefix + selector)
|
||||
|
||||
# Tail doesn't contain a dot at this point, so we can inject the context.
|
||||
return (flake_ref, f'clan.templates.{template_type}."{selector}"')
|
||||
return (flake_ref, input_prefix + f'clan.templates.{template_type}."{selector}"')
|
||||
|
||||
@@ -12,6 +12,9 @@ class DummyFlake:
|
||||
def __init__(self, path: str) -> None:
|
||||
self.path: Path = Path(path)
|
||||
|
||||
def get_input_names(self) -> list[str]:
|
||||
return ["locked-input"]
|
||||
|
||||
|
||||
local_path = DummyFlake(".")
|
||||
|
||||
@@ -20,9 +23,7 @@ def test_transform_url_self_explizit_dot() -> None:
|
||||
user_input = ".#new-machine"
|
||||
expected_selector = 'clan.templates.machine."new-machine"'
|
||||
|
||||
flake_ref, selector = transform_url(
|
||||
template_type, user_input, local_path=local_path
|
||||
)
|
||||
flake_ref, selector = transform_url(template_type, user_input, flake=local_path)
|
||||
assert flake_ref == str(local_path.path)
|
||||
assert selector == expected_selector
|
||||
|
||||
@@ -31,9 +32,7 @@ def test_transform_url_self_no_dot() -> None:
|
||||
user_input = "#new-machine"
|
||||
expected_selector = 'clan.templates.machine."new-machine"'
|
||||
|
||||
flake_ref, selector = transform_url(
|
||||
template_type, user_input, local_path=local_path
|
||||
)
|
||||
flake_ref, selector = transform_url(template_type, user_input, flake=local_path)
|
||||
assert flake_ref == str(local_path.path)
|
||||
assert selector == expected_selector
|
||||
|
||||
@@ -42,9 +41,7 @@ def test_transform_url_builtin_template() -> None:
|
||||
user_input = "new-machine"
|
||||
expected_selector = 'clanInternals.templates.machine."new-machine"'
|
||||
|
||||
flake_ref, selector = transform_url(
|
||||
template_type, user_input, local_path=local_path
|
||||
)
|
||||
flake_ref, selector = transform_url(template_type, user_input, flake=local_path)
|
||||
assert flake_ref == str(local_path.path)
|
||||
assert selector == expected_selector
|
||||
|
||||
@@ -53,9 +50,7 @@ def test_transform_url_remote_template() -> None:
|
||||
user_input = "github:/org/repo#new-machine"
|
||||
expected_selector = 'clan.templates.machine."new-machine"'
|
||||
|
||||
flake_ref, selector = transform_url(
|
||||
template_type, user_input, local_path=local_path
|
||||
)
|
||||
flake_ref, selector = transform_url(template_type, user_input, flake=local_path)
|
||||
|
||||
assert flake_ref == "github:/org/repo"
|
||||
assert selector == expected_selector
|
||||
@@ -65,9 +60,7 @@ def test_transform_url_explicit_path() -> None:
|
||||
user_input = ".#clan.templates.machine.new-machine"
|
||||
expected_selector = "clan.templates.machine.new-machine"
|
||||
|
||||
flake_ref, selector = transform_url(
|
||||
template_type, user_input, local_path=local_path
|
||||
)
|
||||
flake_ref, selector = transform_url(template_type, user_input, flake=local_path)
|
||||
assert flake_ref == str(local_path.path)
|
||||
assert selector == expected_selector
|
||||
|
||||
@@ -76,9 +69,7 @@ def test_transform_url_explicit_path() -> None:
|
||||
def test_transform_url_quoted_selector() -> None:
|
||||
user_input = '.#"new.machine"'
|
||||
expected_selector = '"new.machine"'
|
||||
flake_ref, selector = transform_url(
|
||||
template_type, user_input, local_path=local_path
|
||||
)
|
||||
flake_ref, selector = transform_url(template_type, user_input, flake=local_path)
|
||||
assert flake_ref == str(local_path.path)
|
||||
assert selector == expected_selector
|
||||
|
||||
@@ -86,9 +77,7 @@ def test_transform_url_quoted_selector() -> None:
|
||||
def test_single_quote_selector() -> None:
|
||||
user_input = ".#'new.machine'"
|
||||
expected_selector = "'new.machine'"
|
||||
flake_ref, selector = transform_url(
|
||||
template_type, user_input, local_path=local_path
|
||||
)
|
||||
flake_ref, selector = transform_url(template_type, user_input, flake=local_path)
|
||||
assert flake_ref == str(local_path.path)
|
||||
assert selector == expected_selector
|
||||
|
||||
@@ -97,9 +86,7 @@ def test_custom_template_path() -> None:
|
||||
user_input = "github:/org/repo#my.templates.custom.machine"
|
||||
expected_selector = "my.templates.custom.machine"
|
||||
|
||||
flake_ref, selector = transform_url(
|
||||
template_type, user_input, local_path=local_path
|
||||
)
|
||||
flake_ref, selector = transform_url(template_type, user_input, flake=local_path)
|
||||
assert flake_ref == "github:/org/repo"
|
||||
assert selector == expected_selector
|
||||
|
||||
@@ -109,9 +96,7 @@ def test_full_url_query_and_fragment() -> None:
|
||||
expected_flake_ref = "github:/org/repo?query=param"
|
||||
expected_selector = "my.templates.custom.machine"
|
||||
|
||||
flake_ref, selector = transform_url(
|
||||
template_type, user_input, local_path=local_path
|
||||
)
|
||||
flake_ref, selector = transform_url(template_type, user_input, flake=local_path)
|
||||
assert flake_ref == expected_flake_ref
|
||||
assert selector == expected_selector
|
||||
|
||||
@@ -120,7 +105,7 @@ def test_custom_template_type() -> None:
|
||||
user_input = "#my.templates.custom.machine"
|
||||
expected_selector = "my.templates.custom.machine"
|
||||
|
||||
flake_ref, selector = transform_url("custom", user_input, local_path=local_path)
|
||||
flake_ref, selector = transform_url("custom", user_input, flake=local_path)
|
||||
assert flake_ref == str(local_path.path)
|
||||
assert selector == expected_selector
|
||||
|
||||
@@ -129,7 +114,7 @@ def test_malformed_identifier() -> None:
|
||||
user_input = "github:/org/repo#my.templates.custom.machine#extra"
|
||||
with pytest.raises(ClanError) as exc_info:
|
||||
_flake_ref, _selector = transform_url(
|
||||
template_type, user_input, local_path=local_path
|
||||
template_type, user_input, flake=local_path
|
||||
)
|
||||
|
||||
assert isinstance(exc_info.value, ClanError)
|
||||
@@ -137,3 +122,30 @@ def test_malformed_identifier() -> None:
|
||||
str(exc_info.value)
|
||||
== "Invalid template identifier: More than one '#' found. Please use a single '#'"
|
||||
)
|
||||
|
||||
|
||||
def test_locked_input_template() -> None:
|
||||
user_input = "locked-input#new-machine"
|
||||
expected_selector = 'inputs.locked-input.clan.templates.machine."new-machine"'
|
||||
|
||||
flake_ref, selector = transform_url(template_type, user_input, flake=local_path)
|
||||
assert flake_ref == str(local_path.path)
|
||||
assert selector == expected_selector
|
||||
|
||||
|
||||
def test_locked_input_template_no_quotes() -> None:
|
||||
user_input = 'locked-input#"new.machine"'
|
||||
expected_selector = 'inputs.locked-input."new.machine"'
|
||||
|
||||
flake_ref, selector = transform_url(template_type, user_input, flake=local_path)
|
||||
assert selector == expected_selector
|
||||
assert flake_ref == str(local_path.path)
|
||||
|
||||
|
||||
def test_locked_input_template_no_dot() -> None:
|
||||
user_input = "locked-input#new.machine"
|
||||
expected_selector = "inputs.locked-input.new.machine"
|
||||
|
||||
flake_ref, selector = transform_url(template_type, user_input, flake=local_path)
|
||||
assert selector == expected_selector
|
||||
assert flake_ref == str(local_path.path)
|
||||
|
||||
Reference in New Issue
Block a user