Skip to content
This repository was archived by the owner on Sep 30, 2025. It is now read-only.
Merged
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
10 changes: 9 additions & 1 deletion dreadnode_cli/agent/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,15 @@ def push(
print()
print(f":wrench: Building agent from [b]{directory}[/] ...")
image = docker.build(directory, force_rebuild=rebuild)
repository = f"{registry}/{server_config.username}/agents/{agent_config.project_name}"
agent_name = docker.sanitized_agent_name(agent_config.project_name)

if not agent_name:
raise Exception("Failed to sanitize agent name, please use a different name")

elif agent_name != agent_config.project_name:
print(f":four_leaf_clover: Agent name normalized to [bold magenta]{agent_name}[/]")

repository = f"{registry}/{server_config.username}/agents/{agent_name}"
tag = tag or image.id[-8:]

print()
Expand Down
18 changes: 18 additions & 0 deletions dreadnode_cli/agent/docker.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pathlib
import re
import typing as t

import docker # type: ignore
Expand Down Expand Up @@ -63,6 +64,23 @@ def login(registry: str, username: str, password: str) -> None:
client.api.login(username=username, password=password, registry=registry)


def sanitized_agent_name(name: str) -> str:
"""
Sanitizes an agent name to be used as a Docker repository name.
"""

# convert to lowercase
name = name.lower()
# replace non-alphanumeric characters with hyphens
name = re.sub(r"[^\w\s-]", "", name)
# replace one or more whitespace characters with a single hyphen
name = re.sub(r"[-\s]+", "-", name)
# remove leading or trailing hyphens
name = name.strip("-")

return name


def build(directory: str | pathlib.Path, *, force_rebuild: bool = False) -> Image:
if client is None:
raise Exception("Docker not available")
Expand Down
25 changes: 25 additions & 0 deletions dreadnode_cli/agent/tests/test_docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,28 @@ def test_get_registry_custom_platform_base_domain() -> None:

config = _create_test_server_config("dev-crucible.example.com")
assert docker.get_registry(config) == "dev-registry.example.com"


def test_sanitized_agent_name() -> None:
# Test basic name
assert docker.sanitized_agent_name("test-agent") == "test-agent"
assert docker.sanitized_agent_name("test- agent") == "test-agent"
assert docker.sanitized_agent_name("test_agent") == "test_agent"

# Test spaces
assert docker.sanitized_agent_name("test agent") == "test-agent"
assert docker.sanitized_agent_name("test multiple spaces") == "test-multiple-spaces"

# Test special characters
assert docker.sanitized_agent_name("test!@#$%^&*()agent") == "testagent"
assert docker.sanitized_agent_name("test_agent.123") == "test_agent123"
assert docker.sanitized_agent_name("test/agent\\path") == "testagentpath"

# Test mixed case
assert docker.sanitized_agent_name("TestAgent") == "testagent"
assert docker.sanitized_agent_name("TEST AGENT") == "test-agent"

# Test edge cases
assert docker.sanitized_agent_name(" spaced name ") == "spaced-name"
assert docker.sanitized_agent_name("!!!###") == ""
assert docker.sanitized_agent_name("123 456") == "123-456"
Loading