Skip to content

Commit fa24efd

Browse files
committed
add default_domain for single-domain mode
1 parent e35d5df commit fa24efd

7 files changed

Lines changed: 31 additions & 6 deletions

File tree

‎o2switch_cli/__init__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
__all__ = ["__version__"]
22

3-
__version__ = "0.1.3"
3+
__version__ = "0.1.4"

‎o2switch_cli/cli/autocomplete.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def completion_runtime(ctx: typer.Context | None) -> Iterator[CompletionRuntime
6464
audit_log_path=settings.audit_log_path,
6565
actor=settings.cpanel_user or "completion",
6666
)
67-
domains = DomainService(client)
67+
domains = DomainService(client, default_domain=settings.default_domain)
6868
dns = DNSService(client, domains, DNSResolver(), audit, settings.reserved_labels)
6969
subdomains = SubdomainService(client, domains, dns, audit, settings.reserved_labels)
7070
yield CompletionRuntime(client=client, domains=domains, dns=dns, subdomains=subdomains)

‎o2switch_cli/cli/config_cmd.py‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ def init_config(
6868
cpanel_token: str | None = typer.Option(None, "--cpanel-token", help="cPanel API token (if using token auth)."),
6969
cpanel_password: str | None = typer.Option(None, "--cpanel-password", help="cPanel password (if using password auth)."),
7070
use_password: bool = typer.Option(False, "--password", "-p", help="Use password instead of API token."),
71+
domain: str | None = typer.Option(None, "--domain", "-d", help="Limit operations to this domain only."),
7172
default_ttl: int | None = typer.Option(None, "--default-ttl", help="Default TTL to write into the env file."),
7273
audit_log_path: str | None = typer.Option(
7374
None,
@@ -147,6 +148,16 @@ def action(app_context):
147148
ui.console.print("[dim] Security > Manage API Tokens > Create[/]\n")
148149
secret = secret or questionary.password("cPanel API token").ask()
149150

151+
# Ask for domain restriction
152+
if not domain:
153+
ui.console.print("\n[dim]Limit operations to a single domain (optional):[/]")
154+
domain_input = questionary.text(
155+
"Default domain",
156+
instruction="(leave empty for all domains)"
157+
).ask()
158+
if domain_input:
159+
domain = domain_input.strip().lower()
160+
150161
host = host.strip() if host else None
151162
user = user.strip() if user else None
152163
secret = secret.strip() if secret else None
@@ -175,6 +186,7 @@ def action(app_context):
175186
cpanel_user=user,
176187
cpanel_token=secret,
177188
auth_method=auth_method,
189+
default_domain=domain or None,
178190
port=current.port,
179191
timeout_seconds=current.timeout_seconds,
180192
default_ttl=ttl,

‎o2switch_cli/cli/context.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def runtime(self) -> RuntimeServices:
4646
audit_log_path=self.settings.audit_log_path,
4747
actor=self.settings.cpanel_user or "system",
4848
)
49-
domains = DomainService(client)
49+
domains = DomainService(client, default_domain=self.settings.default_domain)
5050
resolver = DNSResolver()
5151
dns = DNSService(client, domains, resolver, audit, self.settings.reserved_labels)
5252
subdomains = SubdomainService(

‎o2switch_cli/config/settings.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class AppSettings(BaseSettings):
5252
cpanel_user: str | None = None
5353
cpanel_token: SecretStr | None = None # token or password depending on auth_method
5454
auth_method: Literal["token", "password"] = "token"
55+
default_domain: str | None = None # limit operations to this domain only
5556
port: int = 2083
5657
timeout_seconds: float = 20.0
5758
default_ttl: int = 300
@@ -121,6 +122,7 @@ def render_env_file(settings: AppSettings) -> str:
121122
f"O2SWITCH_CLI_CPANEL_USER={_dotenv_value(settings.cpanel_user)}",
122123
f"O2SWITCH_CLI_CPANEL_TOKEN={_dotenv_value(token)}",
123124
f"O2SWITCH_CLI_AUTH_METHOD={_dotenv_value(settings.auth_method)}",
125+
f"O2SWITCH_CLI_DEFAULT_DOMAIN={_dotenv_value(settings.default_domain)}",
124126
f"O2SWITCH_CLI_PORT={_dotenv_value(settings.port)}",
125127
f"O2SWITCH_CLI_TIMEOUT_SECONDS={_dotenv_value(settings.timeout_seconds)}",
126128
f"O2SWITCH_CLI_DEFAULT_TTL={_dotenv_value(settings.default_ttl)}",

‎o2switch_cli/core/cpanel_client.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def __init__(self, settings: AppSettings, client: httpx.Client | None = None) ->
1919
use_basic = settings.auth_method == "password"
2020
headers = {
2121
**auth_header(settings.cpanel_user, settings.cpanel_token, use_basic=use_basic), # type: ignore[arg-type]
22-
"User-Agent": "o2switch-cli/0.1.3",
22+
"User-Agent": "o2switch-cli/0.1.4",
2323
"Accept": "application/json",
2424
}
2525
self._client = client or httpx.Client(

‎o2switch_cli/core/domain_service.py‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77

88

99
class DomainService:
10-
def __init__(self, client: CpanelClient) -> None:
10+
def __init__(self, client: CpanelClient, default_domain: str | None = None) -> None:
1111
self._client = client
12+
self._default_domain = normalize_hostname(default_domain) if default_domain else None
1213

1314
def list_domains(self) -> list[DomainDescriptor]:
1415
payload = self._client.list_domains().data or {}
@@ -40,7 +41,17 @@ def append_many(domains: list[str], domain_type: DomainType) -> None:
4041
append_many(payload.get("parked_domains", []) or [], DomainType.PARKED)
4142
append_many(payload.get("sub_domains", []) or [], DomainType.SUBDOMAIN)
4243
deduped = {item.domain: item for item in descriptors}
43-
return sorted(deduped.values(), key=lambda item: (item.type.value, item.domain))
44+
result = sorted(deduped.values(), key=lambda item: (item.type.value, item.domain))
45+
46+
# Filter by default_domain if set
47+
if self._default_domain:
48+
result = [
49+
item for item in result
50+
if item.domain == self._default_domain
51+
or item.domain.endswith(f".{self._default_domain}")
52+
]
53+
54+
return result
4455

4556
def root_domains(self) -> list[str]:
4657
return [item.domain for item in self.list_domains() if item.type is not DomainType.SUBDOMAIN]

0 commit comments

Comments
 (0)