# Buggy code
def main():
    module = AnsibleModule(
        argument_spec=dict(
            hostname=dict(type="str", default=os.environ.get("VMWARE_HOST")),
            username=dict(type="str", default=os.environ.get("VMWARE_USER")),
            password=dict(
                type="str", default=os.environ.get("VMWARE_PASSWORD"), no_log=True
            ),
            state=dict(
                type="str",
                default="present",
                choices=[
                    "absent",
                    "poweredoff",
                    "poweredon",
                    "present",
                    "rebootguest",
                    "restarted",
                    "shutdownguest",
                    "suspended",
                ],
            ),
            validate_certs=dict(type="bool", default=True),
            template=dict(type="str", aliases=["template_src"]),
            is_template=dict(type="bool", default=False),
            annotation=dict(type="str", aliases=["notes"]),
            customvalues=dict(type="list", default=[]),
            name=dict(type="str", required=True),
            name_match=dict(type="str", default="first"),
            uuid=dict(type="str"),
            folder=dict(type="str", default="/vm"),
            guest_id=dict(type="str"),
            disk=dict(type="list", default=[]),
            hardware=dict(type="dict", default={}),
            force=dict(type="bool", default=False),
            datacenter=dict(type="str", default="ha-datacenter"),
            esxi_hostname=dict(type="str"),
            cluster=dict(type="str"),
            wait_for_ip_address=dict(type="bool", default=False),
            snapshot_src=dict(type="str"),
            linked_clone=dict(type="bool", default=False),
            networks=dict(type="list", default=[]),
            resource_pool=dict(type="str"),
            customization=dict(type="dict", default={}, no_log=True),
        ),
        supports_check_mode=True,
        mutually_exclusive=[
            ["cluster", "esxi_hostname"],
        ],
    )

    result = {"failed": False, "changed": False}

    # FindByInventoryPath() does not require an absolute path
    # so we should leave the input folder path unmodified
    module.params["folder"] = module.params["folder"].rstrip("/")

    pyv = PyVmomiHelper(module)

    # Check if the VM exists before continuing
    vm = pyv.getvm(
        name=module.params["name"],
        folder=module.params["folder"],
        uuid=module.params["uuid"],
    )

    # VM already exists
    if vm:
        if module.params["state"] == "absent":
            # destroy it
            if module.params["force"]:
                # has to be poweredoff first
                pyv.set_powerstate(vm, "poweredoff", module.params["force"])
            result = pyv.remove_vm(vm)
        elif module.params["state"] == "present":
            result = pyv.reconfigure_vm()
        elif module.params["state"] in [
            "poweredon",
            "poweredoff",
            "restarted",
            "suspended",
            "shutdownguest",
            "rebootguest",
        ]:
            # set powerstate
            tmp_result = pyv.set_powerstate(
                vm, module.params["state"], module.params["force"]
            )
            if tmp_result["changed"]:
                result["changed"] = True
            if not tmp_result["failed"]:
                result["failed"] = False
        else:
            # This should not happen
            assert False
    # VM doesn't exist
    else:
        if module.params["state"] in [
            "poweredon",
            "poweredoff",
            "present",
            "restarted",
            "suspended",
        ]:
            # Create it ...
            result = pyv.deploy_vm()

    if result["failed"]:
        module.fail_json(**result)
    else:
        module.exit_json(**result)


# Traceback (nAttributeError)
{
"_ansible_parsed": false,
"exception": "Traceback (most recent call last):\n  File \"/tmp/ansible_t0MsFQ/ansible_module_vmware_guest.py\", line 1332, in <module>\n    main()\n  File \"/tmp/ansible_t0MsFQ/ansible_module_vmware_guest.py\", line 1291, in main\n    pyv = PyVmomiHelper(module)\n  File \"/tmp/ansible_t0MsFQ/ansible_module_vmware_guest.py\", line 436, in __init__\n    self.content = connect_to_api(self.module)\n  File \"/tmp/ansible_t0MsFQ/ansible_modlib.zip/ansible/module_utils/vmware.py\", line 333, in connect_to_api\n  File \"/var/lib/awx/venv/ansible/lib/python2.7/site-packages/pyVim/connect.py\", line 817, in SmartConnect\n    sslContext)\n  File \"/var/lib/awx/venv/ansible/lib/python2.7/site-packages/pyVim/connect.py\", line 702, in __FindSupportedVersion\n    sslContext)\n  File \"/var/lib/awx/venv/ansible/lib/python2.7/site-packages/pyVim/connect.py\", line 622, in __GetServiceVersionDescription\n    path + \"/vimServiceVersions.xml\", sslContext)\n  File \"/var/lib/awx/venv/ansible/lib/python2.7/site-packages/pyVim/connect.py\", line 588, in __GetElementTree\n    conn.request(\"GET\", path)\n  File \"/usr/lib64/python2.7/httplib.py\", line 1017, in request\n    self._send_request(method, url, body, headers)\n  File \"/usr/lib64/python2.7/httplib.py\", line 1045, in _send_request\n    self.putrequest(method, url, **skips)\n  File \"/usr/lib64/python2.7/httplib.py\", line 946, in putrequest\n    host_enc = self.host.encode(\"ascii\")\nAttributeError: 'NoneType' object has no attribute 'encode'\n",
"_ansible_no_log": false,
"_ansible_delegated_vars": {
"ansible_host": "localhost"
},
"module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_t0MsFQ/ansible_module_vmware_guest.py\", line 1332, in <module>\n    main()\n  File \"/tmp/ansible_t0MsFQ/ansible_module_vmware_guest.py\", line 1291, in main\n    pyv = PyVmomiHelper(module)\n  File \"/tmp/ansible_t0MsFQ/ansible_module_vmware_guest.py\", line 436, in __init__\n    self.content = connect_to_api(self.module)\n  File \"/tmp/ansible_t0MsFQ/ansible_modlib.zip/ansible/module_utils/vmware.py\", line 333, in connect_to_api\n  File \"/var/lib/awx/venv/ansible/lib/python2.7/site-packages/pyVim/connect.py\", line 817, in SmartConnect\n    sslContext)\n  File \"/var/lib/awx/venv/ansible/lib/python2.7/site-packages/pyVim/connect.py\", line 702, in __FindSupportedVersion\n    sslContext)\n  File \"/var/lib/awx/venv/ansible/lib/python2.7/site-packages/pyVim/connect.py\", line 622, in __GetServiceVersionDescription\n    path + \"/vimServiceVersions.xml\", sslContext)\n  File \"/var/lib/awx/venv/ansible/lib/python2.7/site-packages/pyVim/connect.py\", line 588, in __GetElementTree\n    conn.request(\"GET\", path)\n  File \"/usr/lib64/python2.7/httplib.py\", line 1017, in request\n    self._send_request(method, url, body, headers)\n  File \"/usr/lib64/python2.7/httplib.py\", line 1045, in _send_request\n    self.putrequest(method, url, **skips)\n  File \"/usr/lib64/python2.7/httplib.py\", line 946, in putrequest\n    host_enc = self.host.encode(\"ascii\")\nAttributeError: 'NoneType' object has no attribute 'encode'\n",
"changed": false,
"module_stdout": "",
"failed": true,
"rc": 0,
"msg": "MODULE FAILURE"
}

# Fixed code
def main():
    argument_spec = vmware_argument_spec()
    argument_spec.update(
        state=dict(
            type="str",
            default="present",
            choices=[
                "absent",
                "poweredoff",
                "poweredon",
                "present",
                "rebootguest",
                "restarted",
                "shutdownguest",
                "suspended",
            ],
        ),
        template=dict(type="str", aliases=["template_src"]),
        is_template=dict(type="bool", default=False),
        annotation=dict(type="str", aliases=["notes"]),
        customvalues=dict(type="list", default=[]),
        name=dict(type="str", required=True),
        name_match=dict(type="str", default="first"),
        uuid=dict(type="str"),
        folder=dict(type="str", default="/vm"),
        guest_id=dict(type="str"),
        disk=dict(type="list", default=[]),
        hardware=dict(type="dict", default={}),
        force=dict(type="bool", default=False),
        datacenter=dict(type="str", default="ha-datacenter"),
        esxi_hostname=dict(type="str"),
        cluster=dict(type="str"),
        wait_for_ip_address=dict(type="bool", default=False),
        snapshot_src=dict(type="str"),
        linked_clone=dict(type="bool", default=False),
        networks=dict(type="list", default=[]),
        resource_pool=dict(type="str"),
        customization=dict(type="dict", default={}, no_log=True),
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        mutually_exclusive=[
            ["cluster", "esxi_hostname"],
        ],
    )

    result = {"failed": False, "changed": False}

    # FindByInventoryPath() does not require an absolute path
    # so we should leave the input folder path unmodified
    module.params["folder"] = module.params["folder"].rstrip("/")

    pyv = PyVmomiHelper(module)

    # Check if the VM exists before continuing
    vm = pyv.getvm(
        name=module.params["name"],
        folder=module.params["folder"],
        uuid=module.params["uuid"],
    )

    # VM already exists
    if vm:
        if module.params["state"] == "absent":
            # destroy it
            if module.params["force"]:
                # has to be poweredoff first
                pyv.set_powerstate(vm, "poweredoff", module.params["force"])
            result = pyv.remove_vm(vm)
        elif module.params["state"] == "present":
            result = pyv.reconfigure_vm()
        elif module.params["state"] in [
            "poweredon",
            "poweredoff",
            "restarted",
            "suspended",
            "shutdownguest",
            "rebootguest",
        ]:
            # set powerstate
            tmp_result = pyv.set_powerstate(
                vm, module.params["state"], module.params["force"]
            )
            if tmp_result["changed"]:
                result["changed"] = True
            if not tmp_result["failed"]:
                result["failed"] = False
        else:
            # This should not happen
            assert False
    # VM doesn't exist
    else:
        if module.params["state"] in [
            "poweredon",
            "poweredoff",
            "present",
            "restarted",
            "suspended",
        ]:
            # Create it ...
            result = pyv.deploy_vm()

    if result["failed"]:
        module.fail_json(**result)
    else:
        module.exit_json(**result)