Repository: ansible-collections/community.general

Issue:
flatpak_remote isn't idempotent
### Summary

When I try adding the `flathub` remote on a fresh Fedora 36 using this code:

`inventory/group_vars/all/vars.yml`:
```yaml
flatpak_remotes:
  flathub: https://flathub.org/repo/flathub.flatpakrepo
  flathub-beta: https://flathub.org/beta-repo/flathub-beta.flatpakrepo
```

`roles/flatpak/tasks/main.yml`:
```yaml
- name: "Flatpak : Add remotes"
  become: true
  flatpak_remote:
    name: "{{ item.key }}"
    flatpakrepo_url: "{{ item.value }}"
  with_dict: "{{ flatpak_remotes }}"
```

I get the following error message for `flathub` (`flathub-beta` is fine):
```console
TASK [include_role : flatpak] **********************************************************************************************************************

TASK [flatpak : Flatpak : Add remotes] *************************************************************************************************************
failed: [machinesetup-test] (item={'key': 'flathub', 'value': 'https://flathub.org/repo/flathub.flatpakrepo'}) => changed=false 
  ansible_loop_var: item
  cmd: /usr/bin/flatpak remote-add --system flathub https://flathub.org/repo/flathub.flatpakrepo
  item:
    key: flathub
    value: https://flathub.org/repo/flathub.flatpakrepo
  msg: 'error: Remote flathub already exists'
  rc: 1
  stderr: |-
    error: Remote flathub already exists
  stderr_lines: <omitted>
  stdout: ''
  stdout_lines: <omitted>
changed: [machinesetup-test] => (item={'key': 'flathub-beta', 'value': 'https://flathub.org/beta-repo/flathub-beta.flatpakrepo'}) => changed=true 
  ansible_loop_var: item
  command: /usr/bin/flatpak remote-add --system flathub-beta https://flathub.org/beta-repo/flathub-beta.flatpakrepo
  item:
    key: flathub-beta
    value: https://flathub.org/beta-repo/flathub-beta.flatpakrepo
  rc: 0
  stderr: ''
  stderr_lines: <omitted>
  stdout: ''
  stdout_lines: <omitted>

PLAY RECAP *****************************************************************************************************************************************
machinesetup-test          : ok=51   changed=37   unreachable=0    failed=1    skipped=4    rescued=0    ignored=0   

```

### Issue Type

Bug Report

### Component Name

flatpak_remote

### Ansible Version

```console (paste below)
$ ansible --version
ansible [core 2.12.5]
  config file = /tmp/MachineSetup/ansible.cfg
  configured module search path = ['/home/mattiasb/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.10/site-packages/ansible
  ansible collection location = /home/mattiasb/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.10.4 (main, Mar 25 2022, 00:00:00) [GCC 12.0.1 20220308 (Red Hat 12.0.1-0)]
  jinja version = 3.0.3
  libyaml = True
```


### Community.general Version

```console (paste below)
$ ansible-galaxy collection list community.general

# /usr/lib/python3.10/site-packages/ansible_collections
Collection        Version
----------------- -------
community.general 4.8.0  

```


### Configuration

```console (paste below)
$ ansible-config dump --only-changed
DEFAULT_BECOME_ASK_PASS(/tmp/MachineSetup/ansible.cfg) = False
DEFAULT_BECOME_METHOD(/tmp/MachineSetup/ansible.cfg) = sudo
DEFAULT_BECOME_USER(/tmp/MachineSetup/ansible.cfg) = root
DEFAULT_HOST_LIST(/tmp/MachineSetup/ansible.cfg) = ['/tmp/MachineSetup/inventory/hosts']
DEFAULT_ROLES_PATH(/tmp/MachineSetup/ansible.cfg) = ['/tmp/MachineSetup/roles']
DEFAULT_STDOUT_CALLBACK(/tmp/MachineSetup/ansible.cfg) = yaml
RETRY_FILES_ENABLED(/tmp/MachineSetup/ansible.cfg) = False

```


### OS / Environment

Fedora Workstation 36

F36 has a `flathub` remote configured by default that is disabled *and* filtered FWIW:

```console
$ flatpak remotes --show-disabled --show-details 
Name           Title                     URL                                            Collection ID Subset Filter                                   Priority Options                  … … Homepage             Icon
fedora         Fedora Flatpaks           oci+https://registry.fedoraproject.org         -             -      -                                        1        system,oci               … … -                    -
fedora-testing Fedora Flatpaks (testing) oci+https://registry.fedoraproject.org#testing -             -      -                                        1        system,disabled,oci      … … -                    -
flathub        Fedora Flathub Selection  https://dl.flathub.org/repo/                   -             -      /usr/share/flatpak/fedora-flathub.filter 1        system,disabled,filtered … … https://flathub.org/ https://dl.flathub.org/repo/logo.svg
flathub-beta   Flathub beta              https://dl.flathub.org/beta-repo/              -             -      -                                        1        system                   … … https://flathub.org/ https://dl.flathub.org/repo/logo.svg
```

### Steps to Reproduce

<!--- Paste example playbooks or commands between quotes below -->
On a fresh F36 Workstation
```yaml (paste below)
- name: "Flatpak : Add flathub"
  become: true
  flatpak_remote:
    name: flathub
    flatpakrepo_url: https://flathub.org/repo/flathub.flatpakrepo
```


### Expected Results

I expected flathub to be either installed *or* for `flatpak_remote` to return success.

### Actual Results

```console
TASK [include_role : flatpak] **********************************************************************************************************************

TASK [flatpak : Flatpak : Add remotes] *************************************************************************************************************
failed: [machinesetup-test] (item={'key': 'flathub', 'value': 'https://flathub.org/repo/flathub.flatpakrepo'}) => changed=false 
  ansible_loop_var: item
  cmd: /usr/bin/flatpak remote-add --system flathub https://flathub.org/repo/flathub.flatpakrepo
  item:
    key: flathub
    value: https://flathub.org/repo/flathub.flatpakrepo
  msg: 'error: Remote flathub already exists'
  rc: 1
  stderr: |-
    error: Remote flathub already exists
  stderr_lines: <omitted>
  stdout: ''
  stdout_lines: <omitted>
changed: [machinesetup-test] => (item={'key': 'flathub-beta', 'value': 'https://flathub.org/beta-repo/flathub-beta.flatpakrepo'}) => changed=true 
  ansible_loop_var: item
  command: /usr/bin/flatpak remote-add --system flathub-beta https://flathub.org/beta-repo/flathub-beta.flatpakrepo
  item:
    key: flathub-beta
    value: https://flathub.org/beta-repo/flathub-beta.flatpakrepo
  rc: 0
  stderr: ''
  stderr_lines: <omitted>
  stdout: ''
  stdout_lines: <omitted>

PLAY RECAP *****************************************************************************************************************************************
machinesetup-test          : ok=51   changed=37   unreachable=0    failed=1    skipped=4    rescued=0    ignored=0   
```

### Code of Conduct

- [X] I agree to follow the Ansible Code of Conduct


Discussion:
Files identified in the description:
* [`plugins/modules/packaging/os/flatpak_remote.py`](https://github.com/ansible-collections/community.general/blob/main/plugins/modules/packaging/os/flatpak_remote.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 @JayKayy @oolongbrothers
[click here for bot help](https://github.com/ansible/ansibullbot/blob/devel/ISSUE_HELP.md)
<!--- boilerplate: notify --->
In addition to the above, if I run this first:
```
$ flatpak remote-modify --enable --no-filter flathub
```
... the test task I mentioned above works.

The test task:
```yaml
- name: "Flatpak : Add flathub"
  become: true
  flatpak_remote:
    name: flathub
    flatpakrepo_url: https://flathub.org/repo/flathub.flatpakrepo
```

So it looks like the issue being that the `flatpak_remote` module doesn't understand filtered and/or disabled remotes.
Files identified in the description:
* [`plugins/modules/flatpak_remote.py`](https://github.com/ansible-collections/community.general/blob/main/plugins/modules/flatpak_remote.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 --->

Resolving patch:
diff --git a/plugins/modules/flatpak_remote.py b/plugins/modules/flatpak_remote.py
--- a/plugins/modules/flatpak_remote.py
+++ b/plugins/modules/flatpak_remote.py
@@ -70,6 +70,12 @@
     type: str
     choices: [ absent, present ]
     default: present
+  enabled:
+    description:
+    - Indicates whether this remote is enabled.
+    type: bool
+    default: true
+    version_added: 6.4.0
 '''
 
 EXAMPLES = r'''
@@ -96,6 +102,12 @@
   community.general.flatpak_remote:
     name: flathub
     state: absent
+
+- name: Disable the flathub remote in the system installation
+  community.general.flatpak_remote:
+    name: flathub
+    state: present
+    enabled: false
 '''
 
 RETURN = r'''
@@ -148,7 +160,7 @@ def remove_remote(module, binary, name, method):
 
 def remote_exists(module, binary, name, method):
     """Check if the remote exists."""
-    command = [binary, "remote-list", "-d", "--{0}".format(method)]
+    command = [binary, "remote-list", "--show-disabled", "--{0}".format(method)]
     # The query operation for the remote needs to be run even in check mode
     output = _flatpak_command(module, False, command)
     for line in output.splitlines():
@@ -160,6 +172,36 @@ def remote_exists(module, binary, name, method):
     return False
 
 
+def enable_remote(module, binary, name, method):
+    """Enable a remote."""
+    global result  # pylint: disable=global-variable-not-assigned
+    command = [binary, "remote-modify", "--enable", "--{0}".format(method), name]
+    _flatpak_command(module, module.check_mode, command)
+    result['changed'] = True
+
+
+def disable_remote(module, binary, name, method):
+    """Disable a remote."""
+    global result  # pylint: disable=global-variable-not-assigned
+    command = [binary, "remote-modify", "--disable", "--{0}".format(method), name]
+    _flatpak_command(module, module.check_mode, command)
+    result['changed'] = True
+
+
+def remote_enabled(module, binary, name, method):
+    """Check if the remote is enabled."""
+    command = [binary, "remote-list", "--show-disabled", "--{0}".format(method)]
+    # The query operation for the remote needs to be run even in check mode
+    output = _flatpak_command(module, False, command)
+    for line in output.splitlines():
+        listed_remote = line.split()
+        if len(listed_remote) == 0:
+            continue
+        if listed_remote[0] == to_native(name):
+            return len(listed_remote) == 1 or "disabled" not in listed_remote[1].split(",")
+    return False
+
+
 def _flatpak_command(module, noop, command):
     global result  # pylint: disable=global-variable-not-assigned
     result['command'] = ' '.join(command)
@@ -182,6 +224,7 @@ def main():
                         choices=['user', 'system']),
             state=dict(type='str', default="present",
                        choices=['absent', 'present']),
+            enabled=dict(type='bool', default=True),
             executable=dict(type='str', default="flatpak")
         ),
         # This module supports check mode
@@ -192,6 +235,7 @@ def main():
     flatpakrepo_url = module.params['flatpakrepo_url']
     method = module.params['method']
     state = module.params['state']
+    enabled = module.params['enabled']
     executable = module.params['executable']
     binary = module.get_bin_path(executable, None)
 
@@ -214,6 +258,14 @@ def main():
     elif state == 'absent' and remote_already_exists:
         remove_remote(module, binary, name, method)
 
+    if state == 'present':
+        remote_already_enabled = remote_enabled(module, binary, to_bytes(name), method)
+
+        if enabled and not remote_already_enabled:
+            enable_remote(module, binary, name, method)
+        if not enabled and remote_already_enabled:
+            disable_remote(module, binary, name, method)
+
     module.exit_json(**result)
 
 


Test patch:
diff --git a/tests/integration/targets/flatpak_remote/tasks/check_mode.yml b/tests/integration/targets/flatpak_remote/tasks/check_mode.yml
--- a/tests/integration/targets/flatpak_remote/tasks/check_mode.yml
+++ b/tests/integration/targets/flatpak_remote/tasks/check_mode.yml
@@ -104,3 +104,103 @@
     msg: |
         Removing a present flatpak remote a second time shall still mark module execution
         as changed in check mode
+
+
+# - Tests with disabled flatpak remote ------------------------------------------
+
+# enabled=true
+
+- name: Test activation of disabled flatpak remote (check mode)
+  flatpak_remote:
+    name: check-mode-disabled-test-remote
+    enabled: true
+  register: activation_result
+  check_mode: true
+
+- name: Verify activation of disabled flatpak remote test result (check mode)
+  assert:
+    that:
+      - activation_result is changed
+    msg: "Enabling an disabled flatpak remote shall mark module execution as changed"
+
+- name: Test non-existent idempotency of activation of disabled flatpak remote (check mode)
+  flatpak_remote:
+    name: check-mode-disabled-test-remote
+    enabled: true
+  register: double_activation_result
+  check_mode: true
+
+- name: >
+      Verify non-existent idempotency of activation of disabled flatpak remote
+      test result (check mode)
+  assert:
+    that:
+      - double_activation_result is changed
+    msg: |
+        Enabling an disabled flatpak remote a second time shall still mark module execution
+        as changed in check mode
+
+# enabled=false
+
+- name: Test deactivation of disabled flatpak remote not doing anything in check mode
+  flatpak_remote:
+    name: check-mode-disabled-test-remote
+    enabled: false
+  register: deactivation_result
+  check_mode: true
+
+- name: Verify deactivation of disabled flatpak remote test result (check mode)
+  assert:
+    that:
+      - deactivation_result is not changed
+    msg: "Disabling an disabled flatpak remote shall mark module execution as not changed"
+
+
+# - Tests with enabled flatpak remote ------------------------------------------
+
+# enabled=true
+
+- name: Test activation of enabled flatpak remote (check mode)
+  flatpak_remote:
+    name: check-mode-enabled-test-remote
+    enabled: true
+  register: activation_result
+  check_mode: true
+
+- name: Verify activation of enabled flatpak remote test result (check mode)
+  assert:
+    that:
+      - activation_result is not changed
+    msg: "Enabling a enabled flatpak remote shall mark module execution as not changed"
+
+# enabled=false
+
+- name: Test deactivation of enabled flatpak remote not doing anything in check mode
+  flatpak_remote:
+    name: check-mode-enabled-test-remote
+    enabled: false
+  register: deactivation_result
+  check_mode: true
+
+- name: Verify deactivation of enabled flatpak remote test result (check mode)
+  assert:
+    that:
+      - deactivation_result is changed
+    msg: "Disabling a enabled flatpak remote shall mark module execution as changed"
+
+- name: Test non-existent idempotency of deactivation of enabled flatpak remote (check mode)
+  flatpak_remote:
+    name: check-mode-enabled-test-remote
+    enabled: false
+  register: double_deactivation_result
+  check_mode: true
+
+- name: >
+      Verify non-existent idempotency of deactivation of enabled flatpak remote
+      test result (check mode)
+  assert:
+    that:
+      - double_deactivation_result is changed
+    msg: |
+        "Disabling a enabled flatpak remote a second time shall still mark module execution
+        as changed in check mode
diff --git a/tests/integration/targets/flatpak_remote/tasks/setup.yml b/tests/integration/targets/flatpak_remote/tasks/setup.yml
--- a/tests/integration/targets/flatpak_remote/tasks/setup.yml
+++ b/tests/integration/targets/flatpak_remote/tasks/setup.yml
@@ -25,3 +25,16 @@
     name: check-mode-test-remote
     flatpakrepo_url: /tmp/flatpak/repo/dummy-repo.flatpakrepo
     state: present
+    enabled: true
+- name: Install disabled flatpak remote for testing check mode
+  flatpak_remote:
+    name: check-mode-disabled-test-remote
+    flatpakrepo_url: /tmp/flatpak/repo/dummy-repo.flatpakrepo
+    state: present
+    enabled: false
+- name: Install enabled flatpak remote for testing check mode
+  flatpak_remote:
+    name: check-mode-enabled-test-remote
+    flatpakrepo_url: /tmp/flatpak/repo/dummy-repo.flatpakrepo
+    state: present
+    enabled: true
diff --git a/tests/integration/targets/flatpak_remote/tasks/test.yml b/tests/integration/targets/flatpak_remote/tasks/test.yml
--- a/tests/integration/targets/flatpak_remote/tasks/test.yml
+++ b/tests/integration/targets/flatpak_remote/tasks/test.yml
@@ -48,6 +48,64 @@
     msg: "Trying to update the URL of an existing flatpak remote shall not do anything"
 
 
+# enabled=false
+
+- name: Test deactivation - {{ method }}
+  flatpak_remote:
+    name: flatpak-test
+    enabled: false
+    method: "{{ method }}"
+  register: deactivation_result
+
+- name: Verify deactivation test result - {{ method }}
+  assert:
+    that:
+      - deactivation_result is changed
+    msg: "enable=false shall disable flatpak remote when enabled"
+
+- name: Test idempotency of deactivation - {{ method }}
+  flatpak_remote:
+    name: flatpak-test
+    enabled: false
+    method: "{{ method }}"
+  register: double_deactivation_result
+
+- name: Verify idempotency of deactivation test result - {{ method }}
+  assert:
+    that:
+      - double_deactivation_result is not changed
+    msg: "enabled=false shall not do anything when flatpak remote is already disabled"
+
+
+# enabled=false
+
+- name: Test activation - {{ method }}
+  flatpak_remote:
+    name: flatpak-test
+    enabled: true
+    method: "{{ method }}"
+  register: activation_result
+
+- name: Verify activation test result - {{ method }}
+  assert:
+    that:
+      - activation_result is changed
+    msg: "enable=true shall enable flatpak remote when disabled"
+
+- name: Test idempotency of activation - {{ method }}
+  flatpak_remote:
+    name: flatpak-test
+    enabled: true
+    method: "{{ method }}"
+  register: double_activation_result
+
+- name: Verify idempotency of activation test result - {{ method }}
+  assert:
+    that:
+      - double_activation_result is not changed
+    msg: "enabled=true shall not do anything when flatpak remote is already enabled"
+
+
 # state=absent
 
 - name: Test removal - {{ method }}