<!--- Verify first that your issue is not already reported on GitHub -->
<!--- Also test if the latest release and devel branch are affected too -->
<!--- Complete *all* sections as described, this form is processed automatically -->

##### SUMMARY
Ansible in dnf.py uses a private attributes (in this case it is an internal cache for security filters - base._update_security_filters). Using private attributes could result in random fails, because they could be even removed without announcement because it is not API.


        filters = []
        if self.bugfix:
            key = {'advisory_type__eq': 'bugfix'}
            filters.append(base.sack.query().upgrades().filter(**key))
        if self.security:
            key = {'advisory_type__eq': 'security'}
            filters.append(base.sack.query().upgrades().filter(**key))
        if filters:
            base._update_security_filters = filters

Also I an not sure if it works like expected (there is a difference in dnf upgrade, and dnf upgrade-minimal) and I don't know what was expected from ansible.

I also propose a new API in dnf that could resolve the issue (https://github.com/rpm-software-management/dnf/pull/1715). Any comment or suggestion is welcome
 
##### ISSUE TYPE
- Bug Report

##### COMPONENT NAME
<!--- Write the short name of the module, plugin, task or feature below, use your best guess if unsure -->
dnf

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes -->
```paste below
devel
```

##### CONFIGURATION
<!--- Paste verbatim output from "ansible-config dump --only-changed" between quotes -->
```paste below

```

##### OS / ENVIRONMENT
<!--- Provide all relevant information below, e.g. target OS versions, network device firmware, etc. -->


##### STEPS TO REPRODUCE
<!--- Describe exactly how to reproduce the problem, using a minimal test-case -->

<!--- Paste example playbooks or commands between quotes below -->
```yaml

```

<!--- HINT: You can paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- Describe what you expected to happen when running the steps above -->


##### ACTUAL RESULTS
<!--- Describe what actually happened. If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes -->
```paste below

```

self.base.install(pkg_spec)
            return {'failed': False, 'msg': '', 'failure': '', 'rc': 0}
        except dnf.exceptions.MarkingError as e:
            return {
                'failed': True,
                'msg': "No package {0} available.".format(pkg_spec),
                'failure': " ".join((pkg_spec, to_native(e))),
                'rc': 1,
                "results": []
            }
        except dnf.exceptions.DepsolveError as e:
            return {
                'failed': True,
                'msg': "Depsolve Error occurred for package {0}.".format(pkg_spec),
                'failure': " ".join((pkg_spec, to_native(e))),
                'rc': 1,
                "results": []
            }
        except dnf.exceptions.Error as e:
            if to_text("already installed") in to_text(e):
                return {'failed': False, 'msg': '', 'failure': ''}
            else:
                return {
                    'failed': True,
                    'msg': "Unknown Error occurred for package {0}.".format(pkg_spec),
                    'failure': " ".join((pkg_spec, to_native(e))),
                    'rc': 1,
                    "results": []
                }
    def _whatprovides(self, filepath):