summaryrefslogtreecommitdiff
path: root/plugins/modules
diff options
context:
space:
mode:
authoromnom62 <omnom62@outlook.com>2026-06-02 21:11:33 +1000
committeromnom62 <omnom62@outlook.com>2026-06-02 21:11:33 +1000
commit066ab3c5795cfc30337831708da1a73a449f404f (patch)
tree7050ba40f12ca00d2b196f7025907b7a74fc9020 /plugins/modules
parente41f9f0f331c0175fa7f9676b9636131d2cc586a (diff)
downloadrest.vyos-066ab3c5795cfc30337831708da1a73a449f404f.tar.gz
rest.vyos-066ab3c5795cfc30337831708da1a73a449f404f.zip
Hostname module fixes
Diffstat (limited to 'plugins/modules')
-rw-r--r--plugins/modules/vyos_banner.py58
-rw-r--r--plugins/modules/vyos_hostname.py120
2 files changed, 153 insertions, 25 deletions
diff --git a/plugins/modules/vyos_banner.py b/plugins/modules/vyos_banner.py
index b9df27d..4f734cd 100644
--- a/plugins/modules/vyos_banner.py
+++ b/plugins/modules/vyos_banner.py
@@ -31,7 +31,6 @@ options:
description:
- Which banner to configure.
type: str
- required: true
choices:
- pre-login
- post-login
@@ -47,9 +46,11 @@ options:
- Desired state of the banner configuration.
- C(merged) - set the banner if it differs from the current value.
- C(replaced) - replace the banner text unconditionally.
- - C(deleted) - remove the banner.
+ - C(deleted) - remove the banner. If C(config.banner) is omitted,
+ both pre-login and post-login banners are removed.
- C(gathered) - return the current banner in I(gathered) without
- making any changes.
+ making any changes. If C(config.banner) is omitted, all banners
+ are returned.
type: str
default: merged
choices:
@@ -97,12 +98,16 @@ EXAMPLES = r"""
text: "Welcome. Authorised access only."
state: replaced
-- name: Remove pre-login banner
+- name: Remove pre-login banner only
vyos.rest.vyos_banner:
config:
banner: pre-login
state: deleted
+- name: Remove all banners
+ vyos.rest.vyos_banner:
+ state: deleted
+
- name: Read current pre-login banner without changing it
vyos.rest.vyos_banner:
config:
@@ -110,6 +115,11 @@ EXAMPLES = r"""
state: gathered
register: result
+- name: Read all banners
+ vyos.rest.vyos_banner:
+ state: gathered
+ register: result
+
- name: Print gathered banner
ansible.builtin.debug:
msg: "Current banner: {{ result.gathered.text }}"
@@ -184,7 +194,7 @@ def main():
options=dict(
banner=dict(
type="str",
- required=True,
+ required=False,
choices=["pre-login", "post-login"],
),
text=dict(type="str"),
@@ -203,17 +213,47 @@ def main():
required_if=[
("state", "merged", ["config"]),
("state", "replaced", ["config"]),
- ("state", "deleted", ["config"]),
- ("state", "gathered", ["config"]),
],
supports_check_mode=True,
)
client = VyOSRestClient(module)
state = module.params["state"]
- config = module.params["config"]
- banner_type = config["banner"]
+ config = module.params["config"] or {}
+ banner_type = config.get("banner")
desired_text = config.get("text") or ""
+
+ # deleted without banner_type — delete all banners
+ if state == "deleted" and not banner_type:
+ commands = []
+ changed = False
+ for bt in ["pre-login", "post-login"]:
+ current = _get_current(client, bt)
+ if current.get("text"):
+ if not module.check_mode:
+ try:
+ client.configure_delete(_BANNER_PATH[bt])
+ except VyOSRestError as exc:
+ module.fail_json(msg=str(exc))
+ commands.append("delete {p}".format(p=" ".join(_BANNER_PATH[bt])))
+ changed = True
+ module.exit_json(changed=changed, commands=commands)
+
+ # gathered without banner_type — return all banners
+ if state == "gathered" and not banner_type:
+ gathered = {}
+ for bt in ["pre-login", "post-login"]:
+ current = _get_current(client, bt)
+ if current.get("text"):
+ gathered[bt] = current
+ module.exit_json(changed=False, gathered=gathered, commands=[])
+
+ # all other states require banner_type
+ if not banner_type:
+ module.fail_json(
+ msg="config.banner is required for state={0}".format(state),
+ )
+
path = _BANNER_PATH[banner_type]
commands = []
changed = False
diff --git a/plugins/modules/vyos_hostname.py b/plugins/modules/vyos_hostname.py
index 10255b5..461a552 100644
--- a/plugins/modules/vyos_hostname.py
+++ b/plugins/modules/vyos_hostname.py
@@ -16,6 +16,8 @@ description:
using the HTTPS REST API.
- Mirrors the behaviour of C(vyos.vyos.vyos_hostname) but uses the HTTP
API instead of SSH/network_cli.
+ - The states C(replaced), C(overridden) behave identically to C(merged)
+ for this single-value resource.
version_added: "1.0.0"
author:
- VyOS Community (@vyos)
@@ -27,42 +29,59 @@ options:
suboptions:
hostname:
description:
- - System hostname (max 63 characters, no underscores).
+ - System hostname (max 63 characters, no underscores).
type: str
required: true
+ running_config:
+ description:
+ - Used only with state C(parsed).
+ - The value should be the output of
+ B(show configuration commands | grep host-name) from the device.
+ type: str
state:
description:
- C(merged) - Ensure the hostname is set to the value in I(config).
+ - C(replaced) - Identical to C(merged) for this single-value resource.
+ - C(overridden) - Identical to C(merged) for this single-value resource.
- C(deleted) - Remove the configured hostname (resets to default).
- C(gathered) - Read the current hostname from the device and return it
in I(gathered) without making changes.
+ - C(rendered) - Return the CLI commands for the given config without
+ connecting to the device.
+ - C(parsed) - Parse the C(running_config) string and return structured
+ data without connecting to the device.
type: str
- choices: [merged, deleted, gathered]
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - gathered
+ - rendered
+ - parsed
default: merged
hostname:
description:
- - IP address or FQDN of the VyOS device.
+ - IP address or FQDN of the VyOS device (not needed with httpapi inventory).
type: str
- required: true
port:
description:
- - HTTPS port for the REST API.
+ - HTTPS port for the REST API.
type: int
default: 443
api_key:
description:
- - API key configured on the device.
+ - API key configured on the device.
type: str
- required: true
no_log: true
timeout:
description:
- - Request timeout in seconds.
+ - Request timeout in seconds.
type: int
default: 30
verify_ssl:
description:
- - Validate the device's TLS certificate.
+ - Validate the device's TLS certificate.
type: bool
default: false
requirements:
@@ -84,13 +103,20 @@ gathered:
description: Hostname read from the device (state=gathered only).
returned: when state is gathered
type: dict
+rendered:
+ description: CLI commands for the provided config (state=rendered only).
+ returned: when state is rendered
+ type: list
+parsed:
+ description: Structured data parsed from running_config (state=parsed only).
+ returned: when state is parsed
+ type: dict
commands:
description: REST API commands dispatched.
returned: always
type: list
"""
-
EXAMPLES = r"""
- name: Set hostname
vyos.rest.vyos_hostname:
@@ -98,6 +124,12 @@ EXAMPLES = r"""
hostname: vyos-core-01
state: merged
+- name: Replace hostname
+ vyos.rest.vyos_hostname:
+ config:
+ hostname: vyos-core-02
+ state: replaced
+
- name: Gather current hostname
vyos.rest.vyos_hostname:
state: gathered
@@ -106,8 +138,21 @@ EXAMPLES = r"""
- name: Delete hostname configuration
vyos.rest.vyos_hostname:
state: deleted
+
+- name: Render commands without connecting
+ vyos.rest.vyos_hostname:
+ config:
+ hostname: vyos-core-01
+ state: rendered
+
+- name: Parse running config
+ vyos.rest.vyos_hostname:
+ running_config: "set system host-name 'vyos'"
+ state: parsed
"""
+import re
+
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
VYOS_REST_CONNECTION_ARGSPEC,
@@ -127,6 +172,12 @@ def _get_hostname(client):
return ""
+def _parse_hostname(running_config):
+ """Parse hostname from 'show configuration commands | grep host-name' output."""
+ match = re.search(r"host-name\s+['\"]?(\S+?)['\"]?\s*$", running_config, re.M)
+ return match.group(1) if match else ""
+
+
def main():
argument_spec = dict(
config=dict(
@@ -135,22 +186,59 @@ def main():
hostname=dict(type="str", required=True),
),
),
+ running_config=dict(type="str"),
state=dict(
type="str",
default="merged",
- choices=["merged", "deleted", "gathered"],
+ choices=[
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "gathered",
+ "rendered",
+ "parsed",
+ ],
),
)
argument_spec.update(VYOS_REST_CONNECTION_ARGSPEC)
module = AnsibleModule(
argument_spec=argument_spec,
- required_if=[("state", "merged", ["config"])],
+ mutually_exclusive=[["config", "running_config"]],
+ required_if=[
+ ("state", "merged", ["config"]),
+ ("state", "replaced", ["config"]),
+ ("state", "overridden", ["config"]),
+ ("state", "rendered", ["config"]),
+ ("state", "parsed", ["running_config"]),
+ ],
supports_check_mode=True,
)
- client = VyOSRestClient(module)
state = module.params["state"]
+
+ # rendered — offline, no device connection needed
+ if state == "rendered":
+ hostname = module.params["config"]["hostname"]
+ module.exit_json(
+ rendered=["set system host-name '{h}'".format(h=hostname)],
+ commands=[],
+ )
+
+ # parsed — offline, no device connection needed
+ if state == "parsed":
+ hostname = _parse_hostname(module.params["running_config"] or "")
+ module.exit_json(
+ parsed={"hostname": hostname},
+ commands=[],
+ )
+
+ # collapsed states — replaced and overridden are identical to merged
+ if state in ("replaced", "overridden"):
+ state = "merged"
+
+ client = VyOSRestClient(module)
commands = []
changed = False
@@ -168,15 +256,15 @@ def main():
desired = module.params["config"]["hostname"]
if current != desired:
client.configure_set(_PATH, desired)
- commands.append(
- "set system host-name '{h}'".format(h=desired),
- )
+ commands.append("set system host-name '{h}'".format(h=desired))
changed = True
+
elif state == "deleted":
if current:
client.configure_delete(_PATH)
commands.append("delete system host-name")
changed = True
+
except VyOSRestError as exc:
module.fail_json(msg=str(exc))