Ensure that the named interface is configured properly.

    name
        The name of the interface to manage

    type
        Type of interface and configuration.

    enabled
        Designates the state of this interface.

    kwargs
        The IP parameters for this interface.

def managed(name, type, enabled=True, **kwargs):
    '''
    Ensure that the named interface is configured properly.

    name
        The name of the interface to manage

    type
        Type of interface and configuration.

    enabled
        Designates the state of this interface.

    kwargs
        The IP parameters for this interface.

    '''
    # For this function we are purposefully overwriting a bif
    # to enhance the user experience. This does not look like
    # it will cause a problem. Just giving a heads up in case
    # it does create a problem.
    ret = {
        'name': name,
        'changes': {},
        'result': True,
        'comment': 'Interface {0} is up to date.'.format(name),
    }
    if 'test' not in kwargs:
        kwargs['test'] = __opts__.get('test', False)

    # set ranged status
    apply_ranged_setting = False

    # Build interface
    try:
        old = __salt__['ip.get_interface'](name)
        new = __salt__['ip.build_interface'](name, type, enabled, **kwargs)
        if kwargs['test']:
            if old == new:
                pass
            if not old and new:
                ret['result'] = None
                ret['comment'] = 'Interface {0} is set to be ' \
                                 'added.'.format(name)
            elif old != new:
                diff = difflib.unified_diff(old, new, lineterm='')
                ret['result'] = None
                ret['comment'] = 'Interface {0} is set to be ' \
                                 'updated:\n{1}'.format(name, '\n'.join(diff))
        else:
            if not old and new:
                ret['comment'] = 'Interface {0} ' \
                                 'added.'.format(name)
                ret['changes']['interface'] = 'Added network interface.'
                apply_ranged_setting = True
            elif old != new:
                diff = difflib.unified_diff(old, new, lineterm='')
                ret['comment'] = 'Interface {0} ' \
                                 'updated.'.format(name)
                ret['changes']['interface'] = '\n'.join(diff)
                apply_ranged_setting = True
    except AttributeError as error:
        ret['result'] = False
        ret['comment'] = six.text_type(error)
        return ret

    # Debian based system can have a type of source
    # in the interfaces file, we don't ifup or ifdown it
    if type == 'source':
        return ret

    # Setup up bond modprobe script if required
    if type == 'bond':
        try:
            old = __salt__['ip.get_bond'](name)
            new = __salt__['ip.build_bond'](name, **kwargs)
            if kwargs['test']:
                if not old and new:
                    ret['result'] = None
                    ret['comment'] = 'Bond interface {0} is set to be ' \
                                     'added.'.format(name)
                elif old != new:
                    diff = difflib.unified_diff(old, new, lineterm='')
                    ret['result'] = None
                    ret['comment'] = 'Bond interface {0} is set to be ' \
                                     'updated:\n{1}'.format(name, '\n'.join(diff))
            else:
                if not old and new:
                    ret['comment'] = 'Bond interface {0} ' \
                                     'added.'.format(name)
                    ret['changes']['bond'] = 'Added bond {0}.'.format(name)
                    apply_ranged_setting = True
                elif old != new:
                    diff = difflib.unified_diff(old, new, lineterm='')
                    ret['comment'] = 'Bond interface {0} ' \
                                     'updated.'.format(name)
                    ret['changes']['bond'] = '\n'.join(diff)
                    apply_ranged_setting = True
        except AttributeError as error:
            #TODO Add a way of reversing the interface changes.
            ret['result'] = False
            ret['comment'] = six.text_type(error)
            return ret

    if kwargs['test']:
        return ret

    # For Redhat/Centos ranged network
    if "range" in name:
        if apply_ranged_setting:
            try:
                ret['result'] = __salt__['service.restart']('network')
                ret['comment'] = "network restarted for change of ranged interfaces"
                return ret
            except Exception as error:
                ret['result'] = False
                ret['comment'] = six.text_type(error)
                return ret
        ret['result'] = True
        ret['comment'] = "no change, passing it"
        return ret

    # Bring up/shutdown interface
    try:
        # Get Interface current status
        interfaces = salt.utils.network.interfaces()
        interface_status = False
        if name in interfaces:
            interface_status = interfaces[name].get('up')
        else:
            for iface in interfaces:
                if 'secondary' in interfaces[iface]:
                    for second in interfaces[iface]['secondary']:
                        if second.get('label', '') == name:
                            interface_status = True
        if enabled:
            if 'noifupdown' not in kwargs:
                if interface_status:
                    if ret['changes']:
                        # Interface should restart to validate if it's up
                        __salt__['ip.down'](name, type)
                        __salt__['ip.up'](name, type)
                        ret['changes']['status'] = 'Interface {0} restart to validate'.format(name)
                else:
                    __salt__['ip.up'](name, type)
                    ret['changes']['status'] = 'Interface {0} is up'.format(name)
        else:
            if 'noifupdown' not in kwargs:
                if interface_status:
                    __salt__['ip.down'](name, type)
                    ret['changes']['status'] = 'Interface {0} down'.format(name)
    except Exception as error:
        ret['result'] = False
        ret['comment'] = six.text_type(error)
        return ret

    # Try to enslave bonding interfaces after master was created
    if type == 'bond' and 'noifupdown' not in kwargs:

        if 'slaves' in kwargs and kwargs['slaves']:
            # Check that there are new slaves for this master
            present_slaves = __salt__['cmd.run'](
                ['cat', '/sys/class/net/{0}/bonding/slaves'.format(name)]).split()
            desired_slaves = kwargs['slaves'].split()
            missing_slaves = set(desired_slaves) - set(present_slaves)

            # Enslave only slaves missing in master
            if missing_slaves:
                ifenslave_path = __salt__['cmd.run'](['which', 'ifenslave']).strip()
                if ifenslave_path:
                    log.info("Adding slaves '%s' to the master %s",
                             ' '.join(missing_slaves), name)
                    cmd = [ifenslave_path, name] + list(missing_slaves)
                    __salt__['cmd.run'](cmd, python_shell=False)
                else:
                    log.error("Command 'ifenslave' not found")
                ret['changes']['enslave'] = (
                    "Added slaves '{0}' to master '{1}'"
                    .format(' '.join(missing_slaves), name))
            else:
                log.info("All slaves '%s' are already added to the master %s"
                         ", no actions required",
                         ' '.join(missing_slaves), name)

    if enabled and interface_status:
        # Interface was restarted, return
        return ret

    # TODO: create saltutil.refresh_grains that fires events to the minion daemon
    grains_info = salt.loader.grains(__opts__, True)
    __grains__.update(grains_info)
    __salt__['saltutil.refresh_modules']()
    return ret