Repository: ansible/ansible

Issue:
RFE: Support systemctl --force option
##### ISSUE TYPE
 - Feature Idea

##### COMPONENT NAME
service / systemd

##### ANSIBLE VERSION
```
ansible 2.4.3.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /bin/ansible
  python version = 2.7.5 (default, Aug  2 2017, 11:05:32) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]
```

##### CONFIGURATION
```
# ansible-config dump --only-changed
#
```

##### OS / ENVIRONMENT
Scientific Linux 7

##### SUMMARY
When switching display managers from say kdm to gdm, the service enable command will fail:
```
TASK [workstation : Enable gdm] *******************************************************************
Wednesday 07 February 2018  10:04:06 -0700 (0:00:01.497)       0:00:28.544 ****
fatal: [HOST]: FAILED! => {"changed": false, "msg": "Unable to enable service gdm: Failed to execute operation: File exists\n"}
# systemctl enable gdm
Failed to execute operation: File exists
```
This is because systemctl will not overwrite the /etc/systemd/system/display-manager.service symlink by default.  But it will with the --force/-f option:
```
# systemctl enable gdm -f
Removed symlink /etc/systemd/system/display-manager.service.
Created symlink from /etc/systemd/system/display-manager.service to /usr/lib/systemd/system/gdm.service.
```


##### STEPS TO REPRODUCE

```yaml
- name: "Enable kdm"
  service:
    name: kdm
    enabled: true
- name: "Enable gdm"
  service:
    name: gdm
    enabled: true
```


Discussion:
Files identified in the description:
* [lib/ansible/modules/system/systemd.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/system/systemd.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->

Resolving patch:
diff --git a/lib/ansible/modules/system/systemd.py b/lib/ansible/modules/system/systemd.py
--- a/lib/ansible/modules/system/systemd.py
+++ b/lib/ansible/modules/system/systemd.py
@@ -33,6 +33,11 @@
         description:
             - Whether the service should start on boot. B(At least one of state and enabled are required.)
         type: bool
+    force:
+        description:
+            - Whether to override existing symlinks.
+        type: bool
+        version_added: 2.6
     masked:
         description:
             - Whether the unit should be masked or not, a masked unit is impossible to start.
@@ -65,10 +70,14 @@
 
 EXAMPLES = '''
 - name: Make sure a service is running
-  systemd: state=started name=httpd
+  systemd:
+    state: started
+    name: httpd
 
 - name: stop service cron on debian, if running
-  systemd: name=cron state=stopped
+  systemd:
+    name: cron
+    state: stopped
 
 - name: restart service cron on centos, in all cases, also issue daemon-reload to pick up config changes
   systemd:
@@ -94,7 +103,8 @@
     enabled: True
 
 - name: just force systemd to reread configs (2.4 and above)
-  systemd: daemon_reload=yes
+  systemd:
+    daemon_reload: yes
 '''
 
 RETURN = '''
@@ -285,6 +295,7 @@ def main():
             name=dict(type='str', aliases=['service', 'unit']),
             state=dict(type='str', choices=['reloaded', 'restarted', 'started', 'stopped']),
             enabled=dict(type='bool'),
+            force=dict(type='bool'),
             masked=dict(type='bool'),
             daemon_reload=dict(type='bool', default=False, aliases=['daemon-reload']),
             user=dict(type='bool', default=False),
@@ -299,6 +310,8 @@ def main():
         systemctl = systemctl + " --user"
     if module.params['no_block']:
         systemctl = systemctl + " --no-block"
+    if module.params['force']:
+        systemctl = systemctl + " --force"
     unit = module.params['name']
     rc = 0
     out = err = ''


Test patch: