1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2026-06-30 07:50:43 +00:00

feat: Expand _kopia module utility for new modules

- Rename REPOSITORY_STATE_MAP to STATE_MAP and add snapshot
  (deleted, expired, listed, verified) and policy (set, shown) entries.
- Expand _PROVIDER_BACKEND_MAP with new backend fields for azure
  (client_id, client_secret, tenant_id, azure_federated_token_file),
  gcs/gdrive (embed_credentials, read_only bool flags), rclone
  (rclone_exe, rclone_args, rclone_env, embed_rclone_config), and
  sftp (sftp_password, key_data, known_hosts_data, embed_credentials,
  external, ssh_command, ssh_args).
- Update fmt_backend() to handle bool (flag-only) and list (per-item)
  param types; _PROVIDER_BACKEND_MAP values changed from plain flag
  strings to (flag, kind) tuples so fmt_backend() can dispatch on type.
This commit is contained in:
munchtoast 2026-06-04 10:40:16 -04:00
parent 48db863096
commit a626f30660
2 changed files with 294 additions and 55 deletions

View file

@ -14,73 +14,102 @@ from ansible_collections.community.general.plugins.module_utils._cmd_runner impo
if t.TYPE_CHECKING:
from ansible.module_utils.basic import AnsibleModule
# Maps kopia_repository module state values to kopia CLI subcommands.
# Maps state values across all kopia modules to their kopia CLI subcommands.
# Used with cmd_runner_fmt.as_map() for the 'state' arg format.
REPOSITORY_STATE_MAP = {
STATE_MAP = {
# kopia_repository
"created": "create",
"connected": "connect",
"disconnected": "disconnect",
"synced": "sync-to",
"throttled": "throttle",
# kopia_snapshot
"deleted": "delete",
"expired": "expire",
"listed": "list",
"verified": "verify",
# kopia_policy
"set": "set",
"shown": "show",
}
# Maps backend provider names to their CLI flag names.
# Each provider emits its name as a positional sub-subcommand, followed by
# --flag value pairs for each non-None param.
# Maps backend provider names to their CLI parameter definitions.
# Each provider maps param_name -> (flag, type) where type is:
# "str" - emit --flag=value (skip if None)
# "bool" - emit --flag only when value is True (skip if False or None)
# "list" - emit --flag item once per item in the list (skip if empty or None)
# The "server" provider is intentionally absent: `kopia repository connect server`
# uses top-level flags (--url, --server-cert-fingerprint) rather than backend flags,
# so fmt_backend() returns [] for it and those flags are passed separately.
_PROVIDER_BACKEND_MAP = {
_PROVIDER_BACKEND_MAP: dict[str, dict[str, tuple[str, str]]] = {
"azure": {
"container": "--container",
"storage_account": "--storage-account",
"storage_key": "--storage-key",
"sas_token": "--sas-token",
"storage_domain": "--storage-domain",
"prefix": "--prefix",
"container": ("--container", "str"),
"storage_account": ("--storage-account", "str"),
"storage_key": ("--storage-key", "str"),
"sas_token": ("--sas-token", "str"),
"storage_domain": ("--storage-domain", "str"),
"prefix": ("--prefix", "str"),
"client_id": ("--client-id", "str"),
"client_secret": ("--client-secret", "str"),
"tenant_id": ("--tenant-id", "str"),
"azure_federated_token_file": ("--azure-federated-token-file", "str"),
},
"b2": {
"bucket": "--bucket",
"access_key": "--key-id",
"secret_access_key": "--key",
"prefix": "--prefix",
"bucket": ("--bucket", "str"),
"access_key": ("--key-id", "str"),
"secret_access_key": ("--key", "str"),
"prefix": ("--prefix", "str"),
},
"filesystem": {
"path": "--path",
"path": ("--path", "str"),
},
"gcs": {
"bucket": "--bucket",
"credentials_file": "--credentials-file",
"prefix": "--prefix",
"bucket": ("--bucket", "str"),
"credentials_file": ("--credentials-file", "str"),
"prefix": ("--prefix", "str"),
"embed_credentials": ("--embed-credentials", "bool"),
"read_only": ("--read-only", "bool"),
},
"gdrive": {
"folder_id": "--folder-id",
"credentials_file": "--credentials-file",
"folder_id": ("--folder-id", "str"),
"credentials_file": ("--credentials-file", "str"),
"read_only": ("--read-only", "bool"),
},
"rclone": {
"path": "--remote-path",
"path": ("--remote-path", "str"),
"rclone_exe": ("--rclone-exe", "str"),
"rclone_args": ("--rclone-args", "list"),
"rclone_env": ("--rclone-env", "list"),
"embed_rclone_config": ("--embed-rclone-config", "bool"),
},
"s3": {
"bucket": "--bucket",
"access_key": "--access-key",
"secret_access_key": "--secret-access-key",
"endpoint": "--endpoint",
"region": "--region",
"prefix": "--prefix",
"session_token": "--session-token",
"bucket": ("--bucket", "str"),
"access_key": ("--access-key", "str"),
"secret_access_key": ("--secret-access-key", "str"),
"endpoint": ("--endpoint", "str"),
"region": ("--region", "str"),
"prefix": ("--prefix", "str"),
"session_token": ("--session-token", "str"),
},
"sftp": {
"path": "--path",
"host": "--host",
"username": "--username",
"port": "--port",
"keyfile": "--keyfile",
"known_hosts": "--known-hosts",
"path": ("--path", "str"),
"host": ("--host", "str"),
"username": ("--username", "str"),
"port": ("--port", "str"),
"keyfile": ("--keyfile", "str"),
"known_hosts": ("--known-hosts", "str"),
"sftp_password": ("--sftp-password", "str"),
"key_data": ("--key-data", "str"),
"known_hosts_data": ("--known-hosts-data", "str"),
"embed_credentials": ("--embed-credentials", "bool"),
"external": ("--external", "bool"),
"ssh_command": ("--ssh-command", "str"),
"ssh_args": ("--ssh-args", "list"),
},
"webdav": {
"url": "--url",
"webdav_username": "--webdav-username",
"webdav_password": "--webdav-password",
"url": ("--url", "str"),
"webdav_username": ("--webdav-username", "str"),
"webdav_password": ("--webdav-password", "str"),
},
}
@ -96,7 +125,12 @@ def fmt_backend(value):
"""Format the backend dict into positional + flag arguments for kopia CLI.
For most providers the output is:
[provider_name, --flag1, value1, --flag2, value2, ...]
[provider_name, --flag1=value1, --flag2, ...]
Param types:
str - emits --flag=value; skipped when value is None.
bool - emits --flag when True; skipped when False or None.
list - emits --flag item once per item; skipped when empty or None.
For the "server" provider, returns [] because server connect uses top-level
flags (--url, --server-cert-fingerprint) passed separately.
@ -105,10 +139,18 @@ def fmt_backend(value):
if provider == "server":
return []
result = [provider]
for param_name, flag in _PROVIDER_BACKEND_MAP[provider].items():
for param_name, (flag, kind) in _PROVIDER_BACKEND_MAP[provider].items():
param_value = value.get(param_name)
if param_value is not None:
result.append(f"{flag}={param_value}")
if kind == "str":
if param_value is not None:
result.append(f"{flag}={param_value}")
elif kind == "bool":
if param_value:
result.append(flag)
elif kind == "list":
if param_value:
for item in param_value:
result.extend([flag, item])
return result
@ -143,7 +185,7 @@ def kopia_runner(module: AnsibleModule, extra_formats: dict | None = None, **kwa
cli_action=cmd_runner_fmt.as_list(),
status=cmd_runner_fmt.as_fixed("repository", "status"),
get_throttle=cmd_runner_fmt.as_fixed("repository", "throttle", "get"),
state=cmd_runner_fmt.as_map(REPOSITORY_STATE_MAP),
state=cmd_runner_fmt.as_map(STATE_MAP),
backend=cmd_runner_fmt.as_func(fmt_backend),
password=cmd_runner_fmt.as_opt_eq_val("--password"),
fingerprint_tls=cmd_runner_fmt.as_opt_eq_val("--server-cert-fingerprint"),