mirror of
https://github.com/ansible/ansible.git
synced 2026-02-03 20:40:24 -05:00
Merge 4a3b47a403 into 7f17759bfe
This commit is contained in:
commit
3ca20ca734
5 changed files with 119 additions and 9 deletions
2
changelogs/fragments/hostname-use-detection.yml
Normal file
2
changelogs/fragments/hostname-use-detection.yml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
bugfixes:
|
||||
- hostname - Fixed use=generic and use=debian and automatic detection for minimal Debian install without dbus (https://github.com/ansible/ansible/issues/85069).
|
||||
|
|
@ -81,9 +81,9 @@ from ansible.module_utils.common.text.converters import to_native, to_text
|
|||
|
||||
STRATS = {
|
||||
'alpine': 'Alpine',
|
||||
'debian': 'Systemd',
|
||||
'debian': 'File',
|
||||
'freebsd': 'FreeBSD',
|
||||
'generic': 'Base',
|
||||
'generic': 'File',
|
||||
'macos': 'Darwin',
|
||||
'macosx': 'Darwin',
|
||||
'darwin': 'Darwin',
|
||||
|
|
@ -109,7 +109,7 @@ class BaseStrategy(object):
|
|||
def update_current_hostname(self):
|
||||
name = self.module.params['name']
|
||||
current_name = self.get_current_hostname()
|
||||
if current_name != name:
|
||||
if current_name is not None and current_name != name:
|
||||
if not self.module.check_mode:
|
||||
self.set_current_hostname(name)
|
||||
self.changed = True
|
||||
|
|
@ -122,7 +122,7 @@ class BaseStrategy(object):
|
|||
self.set_permanent_hostname(name)
|
||||
self.changed = True
|
||||
|
||||
def get_current_hostname(self):
|
||||
def get_current_hostname(self) -> None | str:
|
||||
return self.get_permanent_hostname()
|
||||
|
||||
def set_current_hostname(self, name):
|
||||
|
|
@ -171,9 +171,9 @@ class UnimplementedStrategy(BaseStrategy):
|
|||
class CommandStrategy(BaseStrategy):
|
||||
COMMAND = 'hostname'
|
||||
|
||||
def __init__(self, module):
|
||||
def __init__(self, module: AnsibleModule, cmd_required: bool = True):
|
||||
super(CommandStrategy, self).__init__(module)
|
||||
self.hostname_cmd = self.module.get_bin_path(self.COMMAND, True)
|
||||
self.hostname_cmd = self.module.get_bin_path(self.COMMAND, cmd_required)
|
||||
|
||||
def get_current_hostname(self):
|
||||
cmd = [self.hostname_cmd]
|
||||
|
|
@ -195,9 +195,32 @@ class CommandStrategy(BaseStrategy):
|
|||
pass
|
||||
|
||||
|
||||
class FileStrategy(BaseStrategy):
|
||||
def requires_hostname_cmd(strategy_method):
|
||||
def wrapper(self, *args, **kwargs):
|
||||
if self.hostname_cmd is None:
|
||||
self.module.warn(
|
||||
f"The command '{self.COMMAND}' is not in the PATH, "
|
||||
f"falling back to use the file {self.FILE} exclusively."
|
||||
)
|
||||
return
|
||||
return strategy_method(self, *args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
|
||||
class FileStrategy(CommandStrategy):
|
||||
FILE = '/etc/hostname'
|
||||
|
||||
def __init__(self, module: AnsibleModule, cmd_required: bool = False):
|
||||
super().__init__(module, cmd_required=cmd_required)
|
||||
|
||||
@requires_hostname_cmd
|
||||
def set_current_hostname(self, name):
|
||||
return super().set_current_hostname(name)
|
||||
|
||||
@requires_hostname_cmd
|
||||
def get_current_hostname(self):
|
||||
return super().get_current_hostname()
|
||||
|
||||
def get_permanent_hostname(self):
|
||||
if not os.path.isfile(self.FILE):
|
||||
return ''
|
||||
|
|
@ -296,6 +319,11 @@ class SystemdStrategy(BaseStrategy):
|
|||
super(SystemdStrategy, self).__init__(module)
|
||||
self.hostnamectl_cmd = self.module.get_bin_path(self.COMMAND, True)
|
||||
|
||||
@property
|
||||
def has_hostnamectl(self):
|
||||
rc, out, err = self.module.run_command(self.hostnamectl_cmd)
|
||||
return bool(rc == 0)
|
||||
|
||||
def get_current_hostname(self):
|
||||
cmd = [self.hostnamectl_cmd, '--transient', 'status']
|
||||
rc, out, err = self.module.run_command(cmd)
|
||||
|
|
@ -612,7 +640,10 @@ class Hostname(object):
|
|||
self.strategy = strategy(module)
|
||||
elif platform.system() == 'Linux' and ServiceMgrFactCollector.is_systemd_managed(module):
|
||||
# This is Linux and systemd is active
|
||||
self.strategy = SystemdStrategy(module)
|
||||
if (strategy := SystemdStrategy(module)) and strategy.has_hostnamectl:
|
||||
self.strategy = strategy
|
||||
else:
|
||||
self.strategy = self.strategy_class(module)
|
||||
else:
|
||||
self.strategy = self.strategy_class(module)
|
||||
|
||||
|
|
@ -867,7 +898,7 @@ def main():
|
|||
|
||||
changed = hostname.update_current_and_permanent_hostname()
|
||||
|
||||
if name != current_hostname:
|
||||
if current_hostname is not None and name != current_hostname:
|
||||
name_before = current_hostname
|
||||
else:
|
||||
name_before = permanent_hostname
|
||||
|
|
|
|||
20
test/integration/targets/hostname/tasks/Alpine.yml
Normal file
20
test/integration/targets/hostname/tasks/Alpine.yml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
- name: Test AlpineStrategy by setting hostname
|
||||
become: 'yes'
|
||||
hostname:
|
||||
use: alpine
|
||||
name: "{{ ansible_distribution_release }}-bebop.ansible.example.com"
|
||||
|
||||
- name: Test AlpineStrategy by getting current hostname
|
||||
command: hostname
|
||||
register: get_hostname
|
||||
|
||||
- name: Test AlpineStrategy by verifying /etc/hostname content
|
||||
command: grep -v '^#' /etc/hostname
|
||||
register: grep_hostname
|
||||
|
||||
- name: Test AlpineStrategy using assertions
|
||||
assert:
|
||||
that:
|
||||
- "ansible_distribution_release ~ '-bebop.ansible.example.com' in get_hostname.stdout"
|
||||
- "ansible_distribution_release ~ '-bebop.ansible.example.com' in grep_hostname.stdout"
|
||||
|
|
@ -18,3 +18,50 @@
|
|||
that:
|
||||
- "ansible_distribution_release ~ '-bebop.ansible.example.com' in get_hostname.stdout"
|
||||
- "ansible_distribution_release ~ '-bebop.ansible.example.com' in grep_hostname.stdout"
|
||||
|
||||
- name: Test DebianStrategy without hostname
|
||||
block:
|
||||
- name: Get hostname command
|
||||
shell: which hostname
|
||||
register: hostname
|
||||
ignore_errors: True
|
||||
|
||||
- name: Move hostname command
|
||||
shell: "mv {{ hostname.stdout }} {{ hostname.stdout }}.bak"
|
||||
when: hostname.stdout != ""
|
||||
become: True
|
||||
register: moved_hostname
|
||||
|
||||
- name: Test no change is made without hostname in the PATH
|
||||
hostname:
|
||||
name: "{{ ansible_distribution_release }}-bebop.ansible.example.com"
|
||||
use: debian
|
||||
register: debian_no_change
|
||||
|
||||
- assert:
|
||||
that: debian_no_change is not changed
|
||||
|
||||
- name: Test updating /etc/hostname
|
||||
hostname:
|
||||
name: "{{ ansible_distribution_release }}-bop.ansible.example.com"
|
||||
use: debian
|
||||
register: debian_changed
|
||||
|
||||
- name: Verify /etc/hostname content
|
||||
command: grep -v '^#' /etc/hostname
|
||||
register: grep_hostname
|
||||
|
||||
- name: Assert /etc/hostname has been modified
|
||||
assert:
|
||||
that:
|
||||
- debian_changed is changed
|
||||
- "ansible_distribution_release ~ '-bop.ansible.example.com' in grep_hostname.stdout"
|
||||
always:
|
||||
- command: "mv {{ hostname.stdout }}.bak {{ hostname.stdout }}"
|
||||
when: moved_hostname is defined and moved_hostname is changed
|
||||
become: True
|
||||
|
||||
- name: Verify the current hostname is unchanged
|
||||
command: hostname
|
||||
register: current_hostname
|
||||
failed_when: "ansible_distribution_release ~ '-bop.ansible.example.com' in current_hostname.stdout"
|
||||
|
|
|
|||
|
|
@ -24,3 +24,13 @@
|
|||
- hn3 is not changed
|
||||
- current_after_hn2.stdout == 'crocodile.ansible.test.doesthiswork.net.example.com'
|
||||
- current_after_hn2.stdout == current_after_hn2.stdout
|
||||
|
||||
- name: Test use=generic
|
||||
become: True
|
||||
hostname:
|
||||
name: crocodile.ansible.test.doesthiswork.net.example.com
|
||||
use: generic
|
||||
register: hn4
|
||||
|
||||
- assert:
|
||||
that: hn4 is not changed
|
||||
|
|
|
|||
Loading…
Reference in a new issue