diff options
| author | omnom62 <omnom62@outlook.com> | 2026-06-02 21:11:33 +1000 |
|---|---|---|
| committer | omnom62 <omnom62@outlook.com> | 2026-06-02 21:11:33 +1000 |
| commit | 066ab3c5795cfc30337831708da1a73a449f404f (patch) | |
| tree | 7050ba40f12ca00d2b196f7025907b7a74fc9020 /plugins | |
| parent | e41f9f0f331c0175fa7f9676b9636131d2cc586a (diff) | |
| download | rest.vyos-066ab3c5795cfc30337831708da1a73a449f404f.tar.gz rest.vyos-066ab3c5795cfc30337831708da1a73a449f404f.zip | |
Hostname module fixes
Diffstat (limited to 'plugins')
| -rw-r--r-- | plugins/modules/vyos_banner.py | 58 | ||||
| -rw-r--r-- | plugins/modules/vyos_hostname.py | 120 |
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)) |
