# Buggy code
def main():
    """Main entry point for AnsibleModule"""
    argument_spec = dict(
        gather_subset=dict(default=["!config"], type="list"),
        config_format=dict(default="text", choices=["xml", "text", "set", "json"]),
    )

    argument_spec.update(junos_argument_spec)

    module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)

    get_connection(module)
    warnings = list()
    gather_subset = module.params["gather_subset"]
    ofacts = False

    runable_subsets = set()
    exclude_subsets = set()

    for subset in gather_subset:
        if subset == "all":
            runable_subsets.update(VALID_SUBSETS)
            ofacts = True
            continue

        if subset.startswith("!"):
            subset = subset[1:]
            if subset == "all":
                exclude_subsets.update(VALID_SUBSETS)
                ofacts = False
                continue
            exclude = True
        else:
            exclude = False

        if subset not in VALID_SUBSETS:
            module.fail_json(
                msg="Subset must be one of [%s], got %s"
                % (", ".join(VALID_SUBSETS), subset)
            )

        if exclude:
            exclude_subsets.add(subset)
        else:
            runable_subsets.add(subset)

    if not runable_subsets:
        runable_subsets.update(VALID_SUBSETS)

    runable_subsets.difference_update(exclude_subsets)
    runable_subsets.add("default")

    facts = dict()
    facts["gather_subset"] = list(runable_subsets)

    instances = list()
    for key in runable_subsets:
        instances.append(FACT_SUBSETS[key](module))

    for inst in instances:
        inst.populate()
        facts.update(inst.facts)

    ansible_facts = dict()
    for key, value in iteritems(facts):
        key = "ansible_net_%s" % key
        ansible_facts[key] = value

    if ofacts:
        if HAS_PYEZ:
            ansible_facts.update(Facts(module).populate())
        else:
            warnings += [
                "junos-eznc is required to gather old style facts but does not appear to be installed. "
                "It can be installed using `pip  install junos-eznc`"
            ]
    module.exit_json(ansible_facts=ansible_facts, warnings=warnings)


# Traceback (ValueError)
sveinov@causality:~/ansible$ ansible-playbook main.yml -vvvv
ansible-playbook 2.6.0
config file = /home/sveinov/ansible/ansible.cfg
configured module search path = [u'/home/sveinov/ansible/library']
ansible python module location = /usr/local/lib/python2.7/dist-packages/ansible
executable location = /usr/local/bin/ansible-playbook
python version = 2.7.15 (default, May  1 2018, 05:55:50) [GCC 7.3.0]
Using /home/sveinov/ansible/ansible.cfg as config file
setting up inventory plugins
Parsed /home/sveinov/ansible/inventory/labb.yml inventory source with yaml plugin
Loading callback plugin default of type stdout, v2.0 from /usr/local/lib/python2.7/dist-packages/ansible/plugins/callback/default.pyc
____________________
< PLAYBOOK: main.yml >
--------------------
\   ^__^
\  (oo)\_______
(__)\       )\/\
||----w |
||     ||

1 plays in main.yml
___________________________
< PLAY [Main site playbook] >
---------------------------
\   ^__^
\  (oo)\_______
(__)\       )\/\
||----w |
||     ||

META: ran handlers
________________________
< TASK [Gathering facts] >
------------------------
\   ^__^
\  (oo)\_______
(__)\       )\/\
||----w |
||     ||

task path: /home/sveinov/ansible/main.yml:9
<10.0.0.10> attempting to start connection
<10.0.0.10> using connection plugin netconf
<10.0.0.10> local domain socket does not exist, starting it
<10.0.0.10> control socket path is /home/sveinov/.ansible/pc/86ca832b46
<10.0.0.10> connection to remote device started successfully
<10.0.0.10> local domain socket listeners started successfully
<10.0.0.10>
<10.0.0.10> local domain socket path is /home/sveinov/.ansible/pc/86ca832b46
<10.0.0.10> ESTABLISH LOCAL CONNECTION FOR USER: sveinov
<10.0.0.10> EXEC /bin/sh -c '( umask 77 &amp;&amp; mkdir -p "` echo /home/sveinov/.ansible/tmp/ansible-local-3634_KSsU6/ansible-tmp-1530696521.94-262612295735323 `" &amp;&amp; echo ansible-tmp-1530696521.94-262612295735323="` echo /home/sveinov/.ansible/tmp/ansible-local-3634_KSsU6/ansible-tmp-1530696521.94-262612295735323 `" ) &amp;&amp; sleep 0'
Using module file /usr/local/lib/python2.7/dist-packages/ansible/modules/network/junos/junos_facts.py
<10.0.0.10> PUT /home/sveinov/.ansible/tmp/ansible-local-3634_KSsU6/tmphv8FzM TO /home/sveinov/.ansible/tmp/ansible-local-3634_KSsU6/ansible-tmp-1530696521.94-262612295735323/junos_facts.py
<10.0.0.10> EXEC /bin/sh -c 'chmod u+x /home/sveinov/.ansible/tmp/ansible-local-3634_KSsU6/ansible-tmp-1530696521.94-262612295735323/ /home/sveinov/.ansible/tmp/ansible-local-3634_KSsU6/ansible-tmp-1530696521.94-262612295735323/junos_facts.py &amp;&amp; sleep 0'
<10.0.0.10> EXEC /bin/sh -c '/usr/bin/python /home/sveinov/.ansible/tmp/ansible-local-3634_KSsU6/ansible-tmp-1530696521.94-262612295735323/junos_facts.py &amp;&amp; sleep 0'
<10.0.0.10> EXEC /bin/sh -c 'rm -f -r /home/sveinov/.ansible/tmp/ansible-local-3634_KSsU6/ansible-tmp-1530696521.94-262612295735323/ > /dev/null 2>&amp;1 &amp;&amp; sleep 0'
The full traceback is:
Traceback (most recent call last):
File "/tmp/ansible_WHmIeb/ansible_module_junos_facts.py", line 379, in <module>
main()
File "/tmp/ansible_WHmIeb/ansible_module_junos_facts.py", line 371, in main
ansible_facts.update(Facts(module).populate())
File "/tmp/ansible_WHmIeb/ansible_module_junos_facts.py", line 275, in populate
device = self._connect(self.module)
File "/tmp/ansible_WHmIeb/ansible_module_junos_facts.py", line 265, in _connect
device = Device(host, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/jnpr/junos/device.py", line 1140, in __init__
raise ValueError("You must provide the 'host' value")
ValueError: You must provide the 'host' value

fatal: [mx204]: FAILED! => {
"changed": false,
"module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_WHmIeb/ansible_module_junos_facts.py\", line 379, in <module>\n    main()\n  File \"/tmp/ansible_WHmIeb/ansible_module_junos_facts.py\", line 371, in main\n    ansible_facts.update(Facts(module).populate())\n  File \"/tmp/ansible_WHmIeb/ansible_module_junos_facts.py\", line 275, in populate\n    device = self._connect(self.module)\n  File \"/tmp/ansible_WHmIeb/ansible_module_junos_facts.py\", line 265, in _connect\n    device = Device(host, **kwargs)\n  File \"/usr/local/lib/python2.7/dist-packages/jnpr/junos/device.py\", line 1140, in __init__\n    raise ValueError(\"You must provide the 'host' value\")\nValueError: You must provide the 'host' value\n",
"module_stdout": "",
"msg": "MODULE FAILURE",
"rc": 1
}
to retry, use: --limit @/home/sveinov/ansible/main.retry
____________
< PLAY RECAP >
------------
\   ^__^
\  (oo)\_______
(__)\       )\/\
||----w |
||     ||

mx204                      : ok=0    changed=0    unreachable=0    failed=1

# Fixed code
def main():
    """Main entry point for AnsibleModule"""
    argument_spec = dict(
        gather_subset=dict(default=["!config", "!ofacts"], type="list"),
        config_format=dict(default="text", choices=["xml", "text", "set", "json"]),
    )

    argument_spec.update(junos_argument_spec)

    module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)

    get_connection(module)
    warnings = list()
    gather_subset = module.params["gather_subset"]

    runable_subsets = set()
    exclude_subsets = set()

    for subset in gather_subset:
        if subset == "all":
            runable_subsets.update(VALID_SUBSETS)
            continue

        if subset.startswith("!"):
            subset = subset[1:]
            if subset == "all":
                exclude_subsets.update(VALID_SUBSETS)
                continue
            exclude = True
        else:
            exclude = False

        if subset not in VALID_SUBSETS:
            module.fail_json(
                msg="Subset must be one of [%s], got %s"
                % (", ".join(VALID_SUBSETS), subset)
            )

        if exclude:
            exclude_subsets.add(subset)
        else:
            runable_subsets.add(subset)

    if not runable_subsets:
        runable_subsets.update(VALID_SUBSETS)

    runable_subsets.difference_update(exclude_subsets)
    runable_subsets.add("default")

    facts = dict()
    facts["gather_subset"] = list(runable_subsets)

    instances = list()
    ansible_facts = dict()

    if "ofacts" in runable_subsets:
        if HAS_PYEZ:
            ansible_facts.update(OFacts(module).populate())
        else:
            warnings += [
                "junos-eznc is required to gather old style facts but does not appear to be installed. "
                "It can be installed using `pip  install junos-eznc`"
            ]
        runable_subsets.remove("ofacts")

    for key in runable_subsets:
        instances.append(FACT_SUBSETS[key](module))

    for inst in instances:
        inst.populate()
        facts.update(inst.facts)

    for key, value in iteritems(facts):
        key = "ansible_net_%s" % key
        ansible_facts[key] = value

    module.exit_json(ansible_facts=ansible_facts, warnings=warnings)