Repository: ansible-collections/community.general

Issue:
redhat_subscription module fails when using "force_register" on non registered system
### Summary

Hi,

Up to 6.4.0 the options force_register was not doing anything (according to [the commit e939cd07ef335e939e901c3ccc76523eab8d5e4a)](https://github.com/ansible-collections/community.general/commit/e939cd07ef335e939e901c3ccc76523eab8d5e4a#diff-b354707cac5ffce6845c0ab9c2070a9063747f9a41d64c284194ce5ca2d982c3) L551)

Now the modules starts with an unregister when the option is used. So if this option is used when the system is not registered the module fails. 

I think this should fails silently in this case. 

Regards,

### Issue Type

Bug Report

### Component Name

redhat_subscription

### Ansible Version

```console (paste below)
ansible [core 2.13.3]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.9/site-packages/ansible
  ansible collection location = /etc/ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.9.13 (main, Nov  9 2022, 13:16:24) [GCC 8.5.0 20210514 (Red Hat 8.5.0-15)]
  jinja version = 3.1.2
  libyaml = True
```


### Community.general Version

```console (paste below)
$ ansible-galaxy collection list community.general
Collection        Version
----------------- -------
community.general 6.5.0  
```


### Configuration

```console (paste below)
$ ansible-config dump --only-changed
ANSIBLE_NOCOWS(/etc/ansible/ansible.cfg) = True
CACHE_PLUGIN(/etc/ansible/ansible.cfg) = memory
COLLECTIONS_PATHS(/etc/ansible/ansible.cfg) = ['/etc/ansible/collections', '/usr/share/ansible/collections']
DEFAULT_ACTION_PLUGIN_PATH(/etc/ansible/ansible.cfg) = ['/usr/lib/python3.9/site-packages/ansible/plugins/action']
DEFAULT_CALLBACK_PLUGIN_PATH(/etc/ansible/ansible.cfg) = ['/usr/lib/python3.9/site-packages/ansible/plugins/callback'>
DEFAULT_CONNECTION_PLUGIN_PATH(/etc/ansible/ansible.cfg) = ['/usr/lib/python3.9/site-packages/ansible/plugins/connect>
DEFAULT_FILTER_PLUGIN_PATH(/etc/ansible/ansible.cfg) = ['/usr/lib/python3.9/site-packages/ansible/plugins/filter']
DEFAULT_FORKS(/etc/ansible/ansible.cfg) = 5
DEFAULT_GATHERING(/etc/ansible/ansible.cfg) = implicit
DEFAULT_LOOKUP_PLUGIN_PATH(/etc/ansible/ansible.cfg) = ['/usr/lib/python3.9/site-packages/ansible/plugins/lookup', '/>
DEFAULT_MANAGED_STR(/etc/ansible/ansible.cfg) = Ansible managed: {file}
DEFAULT_POLL_INTERVAL(/etc/ansible/ansible.cfg) = 15
DEFAULT_ROLES_PATH(/etc/ansible/ansible.cfg) = ['/etc/ansible/roles', '/usr/share/ansible/roles']
DEFAULT_TIMEOUT(/etc/ansible/ansible.cfg) = 10
DEFAULT_TRANSPORT(/etc/ansible/ansible.cfg) = smart
DEFAULT_VARS_PLUGIN_PATH(/etc/ansible/ansible.cfg) = ['/usr/lib/python3.9/site-packages/ansible/plugins/vars']
GALAXY_SERVER_LIST(/etc/ansible/ansible.cfg) = ['artifactory']
```


### OS / Environment

RHEL 8.7

### Steps to Reproduce

<!--- Paste example playbooks or commands between quotes below -->
```yaml (paste below)
       redhat_subscription:
         state: present
         activationkey: "{{ sat_activationkey }}"
         force_register: yes
         org_id: xxxxxxx
```

On an unregistered system


### Expected Results

force_register should not fail when the system is not registered and just ignore the fail or skip the unregister step in this case.

### Actual Results

```console (paste below)
TASK [satellite : Subcription manager register] **********************************************************************
task path: /etc/ansible/roles/satellite/tasks/RedHat_8.yml:71
redirecting (type: modules) ansible.builtin.redhat_subscription to community.general.redhat_subscription
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: root
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /var/tmp/.ansible/ `"&& mkdir "` echo /var/tmp/.ansible/ansible-tmp-1680017600.1291587-8982-142603344664991 `" && echo ansible-tmp-1680017600.1291587-8982-142603344664991="` echo /var/tmp/.ansible/ansible-tmp-1680017600.1291587-8982-142603344664991 `" ) && sleep 0'
redirecting (type: modules) ansible.builtin.redhat_subscription to community.general.redhat_subscription
Using module file /etc/ansible/collections/ansible_collections/community/general/plugins/modules/redhat_subscription.py
<localhost> PUT /root/.ansible/tmp/ansible-local-8637enxlydxo/tmp6vn0vrs1 TO /tmp/.ansible/ansible-tmp-1680017600.1291587-8982-142603344664991/AnsiballZ_redhat_subscription.py
<localhost> EXEC /bin/sh -c 'chmod u+x /var/tmp/.ansible/ansible-tmp-1680017600.1291587-8982-142603344664991/ /var/tmp/.ansible/ansible-tmp-1680017600.1291587-8982-142603344664991/AnsiballZ_redhat_subscription.py && sleep 0'
<localhost> EXEC /bin/sh -c '/usr/libexec/platform-python /var/tmp/.ansible/ansible-tmp-1680017600.1291587-8982-142603344664991/AnsiballZ_redhat_subscription.py && sleep 0'
<localhost> EXEC /bin/sh -c 'rm -f -r /var/tmp/.ansible/ansible-tmp-1680017600.1291587-8982-142603344664991/ > /dev/null 2>&1 && sleep 0'
fatal: [localhost]: FAILED! => {
    "changed": false,
    "cmd": "/usr/sbin/subscription-manager unregister",
    "invocation": {
        "module_args": {
            "activationkey": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "auto_attach": null,
            "consumer_id": null,
            "consumer_name": null,
            "consumer_type": null,
            "environment": null,
            "force_register": true,
            "org_id": "xxxxxxxxxxx",
            "password": null,
            "pool": "^$",
            "pool_ids": [],
            "release": null,
            "rhsm_baseurl": null,
            "rhsm_repo_ca_cert": null,
            "server_hostname": null,
            "server_insecure": null,
            "server_port": null,
            "server_prefix": null,
            "server_proxy_hostname": null,
            "server_proxy_password": null,
            "server_proxy_port": null,
            "server_proxy_scheme": null,
            "server_proxy_user": null,
            "state": "present",
            "syspurpose": null,
            "token": null,
            "username": null
        }
    },
    "msg": "This system is currently not registered.",
    "rc": 1,
    "stderr": "This system is currently not registered.\n",
    "stderr_lines": [
        "This system is currently not registered."
    ],
    "stdout": "",
    "stdout_lines": []
}

```


### Code of Conduct

- [X] I agree to follow the Ansible Code of Conduct


Discussion:
Files identified in the description:
* [`plugins/modules/redhat_subscription.py`](https://github.com/ansible-collections/community.general/blob/main/plugins/modules/redhat_subscription.py)

If these files are incorrect, 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/devel/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @alikins @barnabycourt @kahowell
[click here for bot help](https://github.com/ansible/ansibullbot/blob/devel/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/plugins/modules/redhat_subscription.py b/plugins/modules/redhat_subscription.py
--- a/plugins/modules/redhat_subscription.py
+++ b/plugins/modules/redhat_subscription.py
@@ -450,7 +450,7 @@ def _can_connect_to_dbus(self):
         self.module.debug('Verified system D-Bus bus as usable')
         return True
 
-    def register(self, username, password, token, auto_attach, activationkey, org_id,
+    def register(self, was_registered, username, password, token, auto_attach, activationkey, org_id,
                  consumer_type, consumer_name, consumer_id, force_register, environment,
                  release):
         '''
@@ -463,7 +463,7 @@ def register(self, username, password, token, auto_attach, activationkey, org_id
         # There is no support for token-based registration in the D-Bus API
         # of rhsm, so always use the CLI in that case.
         if not token and self._can_connect_to_dbus():
-            self._register_using_dbus(username, password, auto_attach,
+            self._register_using_dbus(was_registered, username, password, auto_attach,
                                       activationkey, org_id, consumer_type,
                                       consumer_name, consumer_id,
                                       force_register, environment, release)
@@ -521,7 +521,7 @@ def _register_using_cli(self, username, password, token, auto_attach,
 
         rc, stderr, stdout = self.module.run_command(args, check_rc=True, expand_user_and_vars=False)
 
-    def _register_using_dbus(self, username, password, auto_attach,
+    def _register_using_dbus(self, was_registered, username, password, auto_attach,
                              activationkey, org_id, consumer_type, consumer_name,
                              consumer_id, force_register, environment, release):
         '''
@@ -570,7 +570,7 @@ def str2int(s, default=0):
              distro_version[0] > 9)):
             dbus_force_option_works = True
 
-        if force_register and not dbus_force_option_works:
+        if force_register and not dbus_force_option_works and was_registered:
             self.unregister()
 
         register_opts = {}
@@ -592,7 +592,7 @@ def str2int(s, default=0):
                  distro_version[0] >= 9)):
                 environment_key = 'environments'
             register_opts[environment_key] = environment
-        if force_register and dbus_force_option_works:
+        if force_register and dbus_force_option_works and was_registered:
             register_opts['force'] = True
         # Wrap it as proper D-Bus dict
         register_opts = dbus.Dictionary(register_opts, signature='sv', variant_level=1)
@@ -1137,8 +1137,11 @@ def main():
     # Ensure system is registered
     if state == 'present':
 
+        # Cache the status of the system before the changes
+        was_registered = rhsm.is_registered
+
         # Register system
-        if rhsm.is_registered and not force_register:
+        if was_registered and not force_register:
             if syspurpose and 'sync' in syspurpose and syspurpose['sync'] is True:
                 try:
                     rhsm.sync_syspurpose()
@@ -1165,7 +1168,7 @@ def main():
             try:
                 rhsm.enable()
                 rhsm.configure(**module.params)
-                rhsm.register(username, password, token, auto_attach, activationkey, org_id,
+                rhsm.register(was_registered, username, password, token, auto_attach, activationkey, org_id,
                               consumer_type, consumer_name, consumer_id, force_register,
                               environment, release)
                 if syspurpose and 'sync' in syspurpose and syspurpose['sync'] is True:


Test patch: