Ensure trail exists.

    name
        The name of the state definition

    Name
        Name of the event rule.  Defaults to the value of the 'name' param if
        not provided.

    ScheduleExpression
        The scheduling expression. For example, ``cron(0 20 * * ? *)``,
        "rate(5 minutes)"

    EventPattern
        The event pattern.

    Description
        A description of the rule

    State
        Indicates whether the rule is ENABLED or DISABLED.

    RoleArn
        The Amazon Resource Name (ARN) of the IAM role associated with the
        rule.

    Targets
        A list of rresources to be invoked when the rule is triggered.

    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 present(name, Name=None,
           ScheduleExpression=None,
           EventPattern=None,
           Description=None,
           RoleArn=None,
           State=None,
           Targets=None,
           region=None, key=None, keyid=None, profile=None):
    '''
    Ensure trail exists.

    name
        The name of the state definition

    Name
        Name of the event rule.  Defaults to the value of the 'name' param if
        not provided.

    ScheduleExpression
        The scheduling expression. For example, ``cron(0 20 * * ? *)``,
        "rate(5 minutes)"

    EventPattern
        The event pattern.

    Description
        A description of the rule

    State
        Indicates whether the rule is ENABLED or DISABLED.

    RoleArn
        The Amazon Resource Name (ARN) of the IAM role associated with the
        rule.

    Targets
        A list of rresources to be invoked when the rule is triggered.

    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': Name,
           'result': True,
           'comment': '',
           'changes': {}
           }

    Name = Name if Name else name

    if isinstance(Targets, six.string_types):
        Targets = salt.utils.json.loads(Targets)
    if Targets is None:
        Targets = []

    r = __salt__['boto_cloudwatch_event.exists'](Name=Name,
           region=region, key=key, keyid=keyid, profile=profile)

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

    if not r.get('exists'):
        if __opts__['test']:
            ret['comment'] = 'CloudWatch event rule {0} is set to be created.'.format(Name)
            ret['result'] = None
            return ret
        r = __salt__['boto_cloudwatch_event.create_or_update'](Name=Name,
                   ScheduleExpression=ScheduleExpression,
                   EventPattern=EventPattern,
                   Description=Description,
                   RoleArn=RoleArn,
                   State=State,
                   region=region, key=key, keyid=keyid, profile=profile)
        if not r.get('created'):
            ret['result'] = False
            ret['comment'] = 'Failed to create event rule: {0}.'.format(r['error']['message'])
            return ret
        _describe = __salt__['boto_cloudwatch_event.describe'](Name,
                                   region=region, key=key, keyid=keyid, profile=profile)
        if 'error' in _describe:
            ret['result'] = False
            ret['comment'] = 'Failed to create event rule: {0}.'.format(_describe['error']['message'])
            ret['changes'] = {}
            return ret
        ret['changes']['old'] = {'rule': None}
        ret['changes']['new'] = _describe
        ret['comment'] = 'CloudTrail {0} created.'.format(Name)

        if bool(Targets):
            r = __salt__['boto_cloudwatch_event.put_targets'](Rule=Name,
                   Targets=Targets,
                   region=region, key=key, keyid=keyid, profile=profile)
            if 'error' in r:
                ret['result'] = False
                ret['comment'] = 'Failed to create event rule: {0}.'.format(r['error']['message'])
                ret['changes'] = {}
                return ret
            ret['changes']['new']['rule']['Targets'] = Targets
        return ret

    ret['comment'] = os.linesep.join([ret['comment'], 'CloudWatch event rule {0} is present.'.format(Name)])
    ret['changes'] = {}
    # trail exists, ensure config matches
    _describe = __salt__['boto_cloudwatch_event.describe'](Name=Name,
                                  region=region, key=key, keyid=keyid, profile=profile)
    if 'error' in _describe:
        ret['result'] = False
        ret['comment'] = 'Failed to update event rule: {0}.'.format(_describe['error']['message'])
        ret['changes'] = {}
        return ret
    _describe = _describe.get('rule')

    r = __salt__['boto_cloudwatch_event.list_targets'](Rule=Name,
                   region=region, key=key, keyid=keyid, profile=profile)
    if 'error' in r:
        ret['result'] = False
        ret['comment'] = 'Failed to update event rule: {0}.'.format(r['error']['message'])
        ret['changes'] = {}
        return ret
    _describe['Targets'] = r.get('targets', [])

    need_update = False
    rule_vars = {'ScheduleExpression': 'ScheduleExpression',
                 'EventPattern': 'EventPattern',
                 'Description': 'Description',
                 'RoleArn': 'RoleArn',
                 'State': 'State',
                 'Targets': 'Targets'}
    for invar, outvar in six.iteritems(rule_vars):
        if _describe[outvar] != locals()[invar]:
            need_update = True
            ret['changes'].setdefault('new', {})[invar] = locals()[invar]
            ret['changes'].setdefault('old', {})[invar] = _describe[outvar]

    if need_update:
        if __opts__['test']:
            msg = 'CloudWatch event rule {0} set to be modified.'.format(Name)
            ret['comment'] = msg
            ret['result'] = None
            return ret

        ret['comment'] = os.linesep.join([ret['comment'], 'CloudWatch event rule to be modified'])
        r = __salt__['boto_cloudwatch_event.create_or_update'](Name=Name,
                   ScheduleExpression=ScheduleExpression,
                   EventPattern=EventPattern,
                   Description=Description,
                   RoleArn=RoleArn,
                   State=State,
                   region=region, key=key, keyid=keyid, profile=profile)
        if not r.get('created'):
            ret['result'] = False
            ret['comment'] = 'Failed to update event rule: {0}.'.format(r['error']['message'])
            ret['changes'] = {}
            return ret

        if _describe['Targets'] != Targets:
            removes = [i.get('Id') for i in _describe['Targets']]
            log.error(Targets)
            if bool(Targets):
                for target in Targets:
                    tid = target.get('Id', None)
                    if tid is not None and tid in removes:
                        ix = removes.index(tid)
                        removes.pop(ix)
                r = __salt__['boto_cloudwatch_event.put_targets'](Rule=Name,
                   Targets=Targets,
                   region=region, key=key, keyid=keyid, profile=profile)
                if 'error' in r:
                    ret['result'] = False
                    ret['comment'] = 'Failed to update event rule: {0}.'.format(r['error']['message'])
                    ret['changes'] = {}
                    return ret
            if bool(removes):
                r = __salt__['boto_cloudwatch_event.remove_targets'](Rule=Name,
                           Ids=removes,
                           region=region, key=key, keyid=keyid, profile=profile)
                if 'error' in r:
                    ret['result'] = False
                    ret['comment'] = 'Failed to update event rule: {0}.'.format(r['error']['message'])
                    ret['changes'] = {}
                    return ret
    return ret