Configures the SNMP on the device as specified in the SLS file.

    SLS Example:

    .. code-block:: yaml

        snmp_example:
            netsnmp.managed:
                 - config:
                    location: Honolulu, HI, US
                 - defaults:
                    contact: noc@cloudflare.com

    Output example (for the SLS above, e.g. called snmp.sls under /router/):

    .. code-block:: bash

        $ sudo salt edge01.hnl01 state.sls router.snmp test=True
        edge01.hnl01:
        ----------
                  ID: snmp_example
            Function: snmp.managed
              Result: None
             Comment: Testing mode: configuration was not changed!
             Started: 13:29:06.872363
            Duration: 920.466 ms
             Changes:
                      ----------
                      added:
                          ----------
                          chassis_id:
                              None
                          contact:
                              noc@cloudflare.com
                          location:
                              Honolulu, HI, US

        Summary for edge01.hnl01
        ------------
        Succeeded: 1 (unchanged=1, changed=1)
        Failed:    0
        ------------
        Total states run:     1
        Total run time: 920.466 ms

def managed(name, config=None, defaults=None):

    '''
    Configures the SNMP on the device as specified in the SLS file.

    SLS Example:

    .. code-block:: yaml

        snmp_example:
            netsnmp.managed:
                 - config:
                    location: Honolulu, HI, US
                 - defaults:
                    contact: noc@cloudflare.com

    Output example (for the SLS above, e.g. called snmp.sls under /router/):

    .. code-block:: bash

        $ sudo salt edge01.hnl01 state.sls router.snmp test=True
        edge01.hnl01:
        ----------
                  ID: snmp_example
            Function: snmp.managed
              Result: None
             Comment: Testing mode: configuration was not changed!
             Started: 13:29:06.872363
            Duration: 920.466 ms
             Changes:
                      ----------
                      added:
                          ----------
                          chassis_id:
                              None
                          contact:
                              noc@cloudflare.com
                          location:
                              Honolulu, HI, US

        Summary for edge01.hnl01
        ------------
        Succeeded: 1 (unchanged=1, changed=1)
        Failed:    0
        ------------
        Total states run:     1
        Total run time: 920.466 ms
    '''

    result = False
    comment = ''
    changes = {}

    ret = {
        'name': name,
        'changes': changes,
        'result': result,
        'comment': comment
    }

    # make sure we're working only with dict
    config = _ordered_dict_to_dict(config)
    defaults = _ordered_dict_to_dict(defaults)

    expected_config = _expand_config(config, defaults)
    if not isinstance(expected_config, dict):
        ret['comment'] = 'User provided an empty SNMP config!'
        return ret
    valid, message = _check_config(expected_config)

    if not valid:  # check and clean
        ret['comment'] = 'Please provide a valid configuration: {error}'.format(error=message)
        return ret

    # ----- Retrieve existing users configuration and determine differences ------------------------------------------->

    _device_config = _retrieve_device_config()
    if not _device_config.get('result'):
        ret['comment'] = 'Cannot retrieve SNMP config from the device: {reason}'.format(
            reason=_device_config.get('comment')
        )
        return ret

    device_config = _device_config.get('out', {})

    if device_config == expected_config:
        ret.update({
            'comment': 'SNMP already configured as needed.',
            'result': True
        })
        return ret

    diff = _compute_diff(device_config, expected_config)

    changes.update(diff)

    ret.update({
        'changes': changes
    })

    if __opts__['test'] is True:
        ret.update({
            'result': None,
            'comment': 'Testing mode: configuration was not changed!'
        })
        return ret

    # <---- Retrieve existing NTP peers and determine peers to be added/removed --------------------------------------->

    # ----- Call _set_users and _delete_users as needed ------------------------------------------------------->

    expected_config_change = False
    result = True

    if diff:
        _configured = _configure(diff)
        if _configured.get('result'):
            expected_config_change = True
        else:  # something went wrong...
            result = False
            comment = 'Cannot push new SNMP config: \n{reason}'.format(
                reason=_configured.get('comment')
            ) +  comment

    if expected_config_change:
        result, comment = __salt__['net.config_control']()

    # <---- Call _set_users and _delete_users as needed --------------------------------------------------------

    ret.update({
        'result': result,
        'comment': comment
    })

    return ret