Repository: ansible/ansible

Issue:
global name 'Facts' is not defined
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report

##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
ansible_module_hostname

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
$ ansible --version
ansible 2.4.0 (devel 4847613725) last updated 2017/06/01 20:32:15 (GMT -500)
  config file =
  configured module search path = [u'/Users/tanner/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /Users/tanner/projects/ansible.git/ansible/lib/ansible
  executable location = /Users/tanner/projects/ansible.git/ansible/bin/ansible
  python version = 2.7.10 (default, Feb  7 2017, 00:08:15) [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)]
```

##### CONFIGURATION
<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->
ANSIBLE_DEBUG=1

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
-->
Ansible host macOS
Managed host Ubuntu Xenial

##### SUMMARY
<!--- Explain the problem briefly -->
Trying to set manage host hostname

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
- name: set hostname
  hostname:
    name: "{{ bootstrap_hostname }}"
  notify:
    - reconfigure openssh server
  tags: bootstrap
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
hostname would be set

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```
 74024 1496367398.68545: _low_level_execute_command() done: rc=0, stdout=
Traceback (most recent call last):
  File "/tmp/ansible_OtWEyM/ansible_module_hostname.py", line 766, in <module>
    main()
  File "/tmp/ansible_OtWEyM/ansible_module_hostname.py", line 755, in main
    hostname = Hostname(module)
  File "/tmp/ansible_OtWEyM/ansible_module_hostname.py", line 115, in __init__
    if self.platform == 'Linux' and Facts(module).is_systemd_managed():
NameError: global name 'Facts' is not defined
, stderr=OpenSSH_7.4p1, LibreSSL 2.5.0
```



Discussion:

Resolving patch:
diff --git a/lib/ansible/module_utils/facts/system/service_mgr.py b/lib/ansible/module_utils/facts/system/service_mgr.py
--- a/lib/ansible/module_utils/facts/system/service_mgr.py
+++ b/lib/ansible/module_utils/facts/system/service_mgr.py
@@ -39,7 +39,8 @@ class ServiceMgrFactCollector(BaseFactCollector):
     name = 'service_mgr'
     _fact_ids = set()
 
-    def is_systemd_managed(self, module):
+    @staticmethod
+    def is_systemd_managed(module):
         # tools must be installed
         if module.get_bin_path('systemctl'):
 
diff --git a/lib/ansible/modules/system/hostname.py b/lib/ansible/modules/system/hostname.py
--- a/lib/ansible/modules/system/hostname.py
+++ b/lib/ansible/modules/system/hostname.py
@@ -53,7 +53,7 @@
 
 # import module snippets
 from ansible.module_utils.basic import *
-from ansible.module_utils.facts import *
+from ansible.module_utils.facts.system.service_mgr import ServiceMgrFactCollector
 from ansible.module_utils._text import to_bytes, to_native
 
 
@@ -112,7 +112,7 @@ def __new__(cls, *args, **kwargs):
     def __init__(self, module):
         self.module       = module
         self.name         = module.params['name']
-        if self.platform == 'Linux' and Facts(module).is_systemd_managed():
+        if self.platform == 'Linux' and ServiceMgrFactCollector.is_systemd_managed(module):
             self.strategy = SystemdStrategy(module)
         else:
             self.strategy = self.strategy_class(module)


Test patch: