Ensure topic rule exists.

    name
        The name of the state definition

    ruleName
        Name of the rule.

    sql
        The SQL statement used to query the topic.

    actions
        The actions associated with the rule.

    description
        The description of the rule.

    ruleDisable
        Specifies whether the rule is disabled.

    region
        Region to connect to.

    key
        Secret key to be used.

    keyid
        Access key to be used.

    profile
        A dict with region, key and keyid, or a pillar key (string) that
        contains a dict with region, key and keyid.

def topic_rule_present(name, ruleName, sql, actions, description='',
            ruleDisabled=False,
            region=None, key=None, keyid=None, profile=None):
    '''
    Ensure topic rule exists.

    name
        The name of the state definition

    ruleName
        Name of the rule.

    sql
        The SQL statement used to query the topic.

    actions
        The actions associated with the rule.

    description
        The description of the rule.

    ruleDisable
        Specifies whether the rule is disabled.

    region
        Region to connect to.

    key
        Secret key to be used.

    keyid
        Access key to be used.

    profile
        A dict with region, key and keyid, or a pillar key (string) that
        contains a dict with region, key and keyid.
    '''
    ret = {'name': ruleName,
           'result': True,
           'comment': '',
           'changes': {}
           }

    r = __salt__['boto_iot.topic_rule_exists'](ruleName=ruleName,
                              region=region, key=key, keyid=keyid, profile=profile)

    if 'error' in r:
        ret['result'] = False
        ret['comment'] = 'Failed to create rule: {0}.'.format(r['error']['message'])
        return ret

    if not r.get('exists'):
        if __opts__['test']:
            ret['comment'] = 'Rule {0} is set to be created.'.format(ruleName)
            ret['result'] = None
            return ret
        r = __salt__['boto_iot.create_topic_rule'](ruleName=ruleName,
                                               sql=sql,
                                               actions=actions,
                                               description=description,
                                               ruleDisabled=ruleDisabled,
                                               region=region, key=key,
                                               keyid=keyid, profile=profile)
        if not r.get('created'):
            ret['result'] = False
            ret['comment'] = 'Failed to create rule: {0}.'.format(r['error']['message'])
            return ret
        _describe = __salt__['boto_iot.describe_topic_rule'](ruleName,
                                   region=region, key=key, keyid=keyid, profile=profile)
        ret['changes']['old'] = {'rule': None}
        ret['changes']['new'] = _describe
        ret['comment'] = 'Rule {0} created.'.format(ruleName)
        return ret

    ret['comment'] = os.linesep.join([ret['comment'], 'Rule {0} is present.'.format(ruleName)])
    ret['changes'] = {}
    # policy exists, ensure config matches
    _describe = __salt__['boto_iot.describe_topic_rule'](ruleName=ruleName,
                                  region=region, key=key, keyid=keyid, profile=profile)['rule']

    if isinstance(actions, six.string_types):
        actions = salt.utils.json.loads(actions)

    need_update = False
    # cmp() function is deprecated in Python 3: use the following as a substitute for 'r'.
    r = (_describe['actions'] > actions) - (_describe['actions'] < actions)
    if bool(r):
        need_update = True
        ret['changes'].setdefault('new', {})['actions'] = actions
        ret['changes'].setdefault('old', {})['actions'] = _describe['actions']

    for var in ('sql', 'description', 'ruleDisabled'):
        if _describe[var] != locals()[var]:
            need_update = True
            ret['changes'].setdefault('new', {})[var] = locals()[var]
            ret['changes'].setdefault('old', {})[var] = _describe[var]
    if need_update:
        if __opts__['test']:
            msg = 'Rule {0} set to be modified.'.format(ruleName)
            ret['changes'] = {}
            ret['comment'] = msg
            ret['result'] = None
            return ret
        ret['comment'] = os.linesep.join([ret['comment'], 'Rule to be modified'])
        r = __salt__['boto_iot.replace_topic_rule'](ruleName=ruleName,
                                               sql=sql,
                                               actions=actions,
                                               description=description,
                                               ruleDisabled=ruleDisabled,
                                               region=region, key=key,
                                               keyid=keyid, profile=profile)
        if not r.get('replaced'):
            ret['result'] = False
            ret['comment'] = 'Failed to update rule: {0}.'.format(r['error']['message'])
            ret['changes'] = {}
    return ret