# Buggy code
def sections_present(name, sections=None, separator="="):
    """
    .. code-block:: yaml

        /home/saltminion/api-paste.ini:
          ini.sections_present:
            - separator: '='
            - sections:
                - section_one
                - section_two

    This will only create empty sections. To also create options, use
    options_present state

    options present in file and not specified in sections will be deleted
    changes dict will contain the sections that changed
    """
    ret = {
        "name": name,
        "changes": {},
        "result": True,
        "comment": "No anomaly detected",
    }
    if __opts__["test"]:
        ret["result"] = True
        ret["comment"] = ""
        for section in sections or {}:
            try:
                cur_section = __salt__["ini.get_section"](name, section, separator)
            except IOError as err:
                ret["result"] = False
                ret["comment"] = "{0}".format(err)
                return ret
            if dict(sections[section]) == cur_section:
                ret["comment"] += "Section unchanged {0}.\n".format(section)
                continue
            elif cur_section:
                ret["comment"] += "Changed existing section {0}.\n".format(section)
            else:
                ret["comment"] += "Created new section {0}.\n".format(section)
            ret["result"] = None
        if ret["comment"] == "":
            ret["comment"] = "No changes detected."
        return ret
    section_to_update = {}
    for section_name in sections or []:
        section_to_update.update({section_name: {}})
    try:
        changes = __salt__["ini.set_option"](name, section_to_update, separator)
    except IOError as err:
        ret["result"] = False
        ret["comment"] = "{0}".format(err)
        return ret
    if "error" in changes:
        ret["result"] = False
        ret["changes"] = "Errors encountered {0}".format(changes["error"])
        return ret
    ret["changes"] = changes
    ret["comment"] = "Changes take effect"
    return ret


# Traceback (TypeError)
local:
----------
ID: ini-present
Function: ini.options_present
Name: /tmp/test.ini
Result: False
Comment: An exception occurred in this state: Traceback (most recent call last):
File "/home/js/work/git/salt/salt/state.py", line 1918, in call
**cdata['kwargs'])
File "/home/js/work/git/salt/salt/loader.py", line 1830, in wrapper
return f(*args, **kwargs)
File "/home/js/work/git/salt/salt/states/ini_manage.py", line 68, in options_present
if cur_value == six.text_type(sections[section][key]):
TypeError: string indices must be integers
Started: 11:44:26.917548
Duration: 2.082 ms
Changes:
----------
ID: ini-absent
Function: ini.options_absent
Name: /tmp/test.ini
Result: False
Comment: An exception occurred in this state: Traceback (most recent call last):
File "/home/js/work/git/salt/salt/state.py", line 1918, in call
**cdata['kwargs'])
File "/home/js/work/git/salt/salt/loader.py", line 1830, in wrapper
return f(*args, **kwargs)
File "/home/js/work/git/salt/salt/states/ini_manage.py", line 142, in options_absent
cur_section = __salt__['ini.get_section'](name, section, separator)
File "/home/js/work/git/salt/salt/modules/ini_manage.py", line 159, in get_section
for key, value in six.iteritems(inifile.get(section, {})):
File "/home/js/work/git/salt/salt/ext/six.py", line 606, in iteritems
return d.iteritems(**kw)
AttributeError: 'unicode' object has no attribute 'iteritems'
Started: 11:44:26.921172
Duration: 1.063 ms
Changes:
----------
ID: ini-sect-present
Function: ini.sections_present
Name: /tmp/test.ini
Result: False
Comment: An exception occurred in this state: Traceback (most recent call last):
File "/home/js/work/git/salt/salt/state.py", line 1918, in call
**cdata['kwargs'])
File "/home/js/work/git/salt/salt/loader.py", line 1830, in wrapper
return f(*args, **kwargs)
File "/home/js/work/git/salt/salt/states/ini_manage.py", line 207, in sections_present
if dict(sections[section]) == cur_section:
TypeError: list indices must be integers, not unicode
Started: 11:44:26.923578
Duration: 0.851 ms
Changes:

# Fixed code
def sections_present(name, sections=None, separator="="):
    """
    .. code-block:: yaml

        /home/saltminion/api-paste.ini:
          ini.sections_present:
            - separator: '='
            - sections:
                - section_one
                - section_two

    This will only create empty sections. To also create options, use
    options_present state

    options present in file and not specified in sections will be deleted
    changes dict will contain the sections that changed
    """
    ret = {
        "name": name,
        "changes": {},
        "result": True,
        "comment": "No anomaly detected",
    }
    if __opts__["test"]:
        ret["result"] = True
        ret["comment"] = ""
        try:
            cur_ini = __salt__["ini.get_ini"](name, separator)
        except IOError as err:
            ret["result"] = False
            ret["comment"] = "{0}".format(err)
            return ret
        for section in sections or {}:
            if section in cur_ini:
                ret["comment"] += "Section unchanged {0}.\n".format(section)
                continue
            else:
                ret["comment"] += "Created new section {0}.\n".format(section)
            ret["result"] = None
        if ret["comment"] == "":
            ret["comment"] = "No changes detected."
        return ret
    section_to_update = {}
    for section_name in sections or []:
        section_to_update.update({section_name: {}})
    try:
        changes = __salt__["ini.set_option"](name, section_to_update, separator)
    except IOError as err:
        ret["result"] = False
        ret["comment"] = "{0}".format(err)
        return ret
    if "error" in changes:
        ret["result"] = False
        ret["changes"] = "Errors encountered {0}".format(changes["error"])
        return ret
    ret["changes"] = changes
    ret["comment"] = "Changes take effect"
    return ret