# Buggy code
def keygen(sk_file=None, pk_file=None):
    """
    Use libnacl to generate a keypair.

    If no `sk_file` is defined return a keypair.

    If only the `sk_file` is defined `pk_file` will use the same name with a postfix `.pub`.

    When the `sk_file` is already existing, but `pk_file` is not. The `pk_file` will be generated
    using the `sk_file`.

    CLI Examples:

    .. code-block:: bash

        salt-call nacl.keygen
        salt-call nacl.keygen sk_file=/etc/salt/pki/master/nacl
        salt-call nacl.keygen sk_file=/etc/salt/pki/master/nacl pk_file=/etc/salt/pki/master/nacl.pub
        salt-call --local nacl.keygen
    """
    if sk_file is None:
        kp = libnacl.public.SecretKey()
        return {"sk": base64.b64encode(kp.sk), "pk": base64.b64encode(kp.pk)}

    if pk_file is None:
        pk_file = "{0}.pub".format(sk_file)

    if sk_file and pk_file is None:
        if not os.path.isfile(sk_file):
            kp = libnacl.public.SecretKey()
            with salt.utils.files.fopen(sk_file, "wb") as keyf:
                keyf.write(base64.b64encode(kp.sk))
            if salt.utils.platform.is_windows():
                cur_user = salt.utils.win_functions.get_current_user()
                salt.utils.win_dacl.set_owner(sk_file, cur_user)
                salt.utils.win_dacl.set_permissions(
                    sk_file,
                    cur_user,
                    "full_control",
                    "grant",
                    reset_perms=True,
                    protected=True,
                )
            else:
                # chmod 0600 file
                os.chmod(sk_file, 1536)
            return "saved sk_file: {0}".format(sk_file)
        else:
            raise Exception("sk_file:{0} already exist.".format(sk_file))

    if sk_file is None and pk_file:
        raise Exception("sk_file: Must be set inorder to generate a public key.")

    if os.path.isfile(sk_file) and os.path.isfile(pk_file):
        raise Exception(
            "sk_file:{0} and pk_file:{1} already exist.".format(sk_file, pk_file)
        )

    if os.path.isfile(sk_file) and not os.path.isfile(pk_file):
        # generate pk using the sk
        with salt.utils.files.fopen(sk_file, "rb") as keyf:
            sk = salt.utils.stringutils.to_unicode(keyf.read()).rstrip("\n")
            sk = base64.b64decode(sk)
        kp = libnacl.public.SecretKey(sk)
        with salt.utils.files.fopen(pk_file, "wb") as keyf:
            keyf.write(base64.b64encode(kp.pk))
        return "saved pk_file: {0}".format(pk_file)

    kp = libnacl.public.SecretKey()
    with salt.utils.files.fopen(sk_file, "wb") as keyf:
        keyf.write(base64.b64encode(kp.sk))
    if salt.utils.platform.is_windows():
        cur_user = salt.utils.win_functions.get_current_user()
        salt.utils.win_dacl.set_owner(sk_file, cur_user)
        salt.utils.win_dacl.set_permissions(
            sk_file, cur_user, "full_control", "grant", reset_perms=True, protected=True
        )
    else:
        # chmod 0600 file
        os.chmod(sk_file, 1536)
    with salt.utils.files.fopen(pk_file, "wb") as keyf:
        keyf.write(base64.b64encode(kp.pk))
    return "saved sk_file:{0}  pk_file: {1}".format(sk_file, pk_file)


# Traceback (IOError)
2018-03-05 18:47:44,563 [salt.pillar                                                 :732 ][CRITICAL][339999] Rendering SLS 'common.account' failed, render error:
Traceback (most recent call last):
File "/opt/local/lib/python2.7/site-packages/salt/utils/templates.py", line 553, in py
data = mod.run()
File "/salt/pillar/common/account/init.sls", line 121, in run
'password': __salt__['shadow.gen_password'](__salt__['nacl.dec'](data=user['password'], key=nacl['db']), 'BLBnVC', 'sha256') if user['password'] else None,
File "/opt/local/lib/python2.7/site-packages/salt/modules/nacl.py", line 365, in dec
return sealedbox_decrypt(data, **kwargs)
File "/opt/local/lib/python2.7/site-packages/salt/modules/nacl.py", line 436, in sealedbox_decrypt
sk = _get_sk(**kwargs)
File "/opt/local/lib/python2.7/site-packages/salt/modules/nacl.py", line 213, in _get_sk
with salt.utils.files.fopen(sk_file, 'rb') as keyf:
File "/opt/local/lib/python2.7/site-packages/salt/utils/files.py", line 366, in fopen
f_handle = open(*args, **kwargs)  # pylint: disable=resource-leakage
IOError: [Errno 2] No such file or directory: u'/etc/salt/pki/master/nacl'

# Fixed code
def keygen(sk_file=None, pk_file=None, **kwargs):
    """
    Use libnacl to generate a keypair.

    If no `sk_file` is defined return a keypair.

    If only the `sk_file` is defined `pk_file` will use the same name with a postfix `.pub`.

    When the `sk_file` is already existing, but `pk_file` is not. The `pk_file` will be generated
    using the `sk_file`.

    CLI Examples:

    .. code-block:: bash

        salt-call nacl.keygen
        salt-call nacl.keygen sk_file=/etc/salt/pki/master/nacl
        salt-call nacl.keygen sk_file=/etc/salt/pki/master/nacl pk_file=/etc/salt/pki/master/nacl.pub
        salt-call --local nacl.keygen
    """
    if "keyfile" in kwargs:
        salt.utils.versions.warn_until(
            "Fluorine",
            "The 'keyfile' argument has been deprecated and will be removed in Salt "
            "{version}. Please use 'sk_file' argument instead.",
        )
        sk_file = kwargs["keyfile"]

    if sk_file is None:
        kp = libnacl.public.SecretKey()
        return {"sk": base64.b64encode(kp.sk), "pk": base64.b64encode(kp.pk)}

    if pk_file is None:
        pk_file = "{0}.pub".format(sk_file)

    if sk_file and pk_file is None:
        if not os.path.isfile(sk_file):
            kp = libnacl.public.SecretKey()
            with salt.utils.files.fopen(sk_file, "wb") as keyf:
                keyf.write(base64.b64encode(kp.sk))
            if salt.utils.platform.is_windows():
                cur_user = salt.utils.win_functions.get_current_user()
                salt.utils.win_dacl.set_owner(sk_file, cur_user)
                salt.utils.win_dacl.set_permissions(
                    sk_file,
                    cur_user,
                    "full_control",
                    "grant",
                    reset_perms=True,
                    protected=True,
                )
            else:
                # chmod 0600 file
                os.chmod(sk_file, 1536)
            return "saved sk_file: {0}".format(sk_file)
        else:
            raise Exception("sk_file:{0} already exist.".format(sk_file))

    if sk_file is None and pk_file:
        raise Exception("sk_file: Must be set inorder to generate a public key.")

    if os.path.isfile(sk_file) and os.path.isfile(pk_file):
        raise Exception(
            "sk_file:{0} and pk_file:{1} already exist.".format(sk_file, pk_file)
        )

    if os.path.isfile(sk_file) and not os.path.isfile(pk_file):
        # generate pk using the sk
        with salt.utils.files.fopen(sk_file, "rb") as keyf:
            sk = salt.utils.stringutils.to_unicode(keyf.read()).rstrip("\n")
            sk = base64.b64decode(sk)
        kp = libnacl.public.SecretKey(sk)
        with salt.utils.files.fopen(pk_file, "wb") as keyf:
            keyf.write(base64.b64encode(kp.pk))
        return "saved pk_file: {0}".format(pk_file)

    kp = libnacl.public.SecretKey()
    with salt.utils.files.fopen(sk_file, "wb") as keyf:
        keyf.write(base64.b64encode(kp.sk))
    if salt.utils.platform.is_windows():
        cur_user = salt.utils.win_functions.get_current_user()
        salt.utils.win_dacl.set_owner(sk_file, cur_user)
        salt.utils.win_dacl.set_permissions(
            sk_file, cur_user, "full_control", "grant", reset_perms=True, protected=True
        )
    else:
        # chmod 0600 file
        os.chmod(sk_file, 1536)
    with salt.utils.files.fopen(pk_file, "wb") as keyf:
        keyf.write(base64.b64encode(kp.pk))
    return "saved sk_file:{0}  pk_file: {1}".format(sk_file, pk_file)