docs: def managed(name, probes, defaults=None):
  
      '''
      Ensure the networks device is configured as specified in the state SLS file.
      Probes not specified will be removed, while probes not confiured as expected will trigger config updates.
  
      :param probes: Defines the probes as expected to be configured on the
          device.  In order to ease the configuration and avoid repeating the
          same parameters for each probe, the next parameter (defaults) can be
          used, providing common characteristics.
  
      :param defaults: Specifies common parameters for the probes.
  
      SLS Example:
  
      .. code-block:: yaml
  
          rpmprobes:
              probes.managed:
                  - probes:
                      probe_name1:
                          probe1_test1:
                              source: 192.168.0.2
                              target: 192.168.0.1
                          probe1_test2:
                              target: 172.17.17.1
                          probe1_test3:
                              target: 8.8.8.8
                              probe_type: http-ping
                      probe_name2:
                          probe2_test1:
                              test_interval: 100
                  - defaults:
                      target: 10.10.10.10
                      probe_count: 15
                      test_interval: 3
                      probe_type: icmp-ping
  
      In the probes configuration, the only mandatory attribute is *target*
      (specified either in probes configuration, either in the defaults
      dictionary).  All the other parameters will use the operating system
      defaults, if not provided:
  
      - ``source`` - Specifies the source IP Address to be used during the tests.  If
        not specified will use the IP Address of the logical interface loopback0.
  
      - ``target`` - Destination IP Address.
      - ``probe_count`` - Total number of probes per test (1..15). System
        defaults: 1 on both JunOS & Cisco.
      - ``probe_interval`` - Delay between tests (0..86400 seconds). System
        defaults: 3 on JunOS, 5 on Cisco.
      - ``probe_type`` - Probe request type. Available options:
  
        - icmp-ping
        - tcp-ping
        - udp-ping
  
      Using the example configuration above, after running the state, on the device will be configured 4 probes,
      with the following properties:
  
      .. code-block:: yaml
  
          probe_name1:
              probe1_test1:
                  source: 192.168.0.2
                  target: 192.168.0.1
                  probe_count: 15
                  test_interval: 3
                  probe_type: icmp-ping
              probe1_test2:
                  target: 172.17.17.1
                  probe_count: 15
                  test_interval: 3
                  probe_type: icmp-ping
              probe1_test3:
                  target: 8.8.8.8
                  probe_count: 15
                  test_interval: 3
                  probe_type: http-ping
          probe_name2:
              probe2_test1:
                  target: 10.10.10.10
                  probe_count: 15
                  test_interval: 3
                  probe_type: icmp-ping
      '''
  
      ret = _default_ret(name)
  
      result = True
      comment = ''
  
      rpm_probes_config = _retrieve_rpm_probes()  # retrieves the RPM config from the device
      if not rpm_probes_config.get('result'):
          ret.update({
              'result': False,
              'comment': 'Cannot retrieve configurtion of the probes from the device: {reason}'.format(
                  reason=rpm_probes_config.get('comment')
              )
          })
          return ret
  
      # build expect probes config dictionary
      # using default values
      configured_probes = rpm_probes_config.get('out', {})
      if not isinstance(defaults, dict):
          defaults = {}
      expected_probes = _expand_probes(probes, defaults)
  
      _clean_probes(configured_probes)  # let's remove the unnecessary data from the configured probes
      _clean_probes(expected_probes)  # also from the expected data
  
      # ----- Compare expected config with the existing config ---------------------------------------------------------->
  
      diff = _compare_probes(configured_probes, expected_probes)  # compute the diff
  
      # <---- Compare expected config with the existing config -----------------------------------------------------------
  
      # ----- Call set_probes and delete_probes as needed --------------------------------------------------------------->
  
      add_probes = diff.get('add')
      update_probes = diff.get('update')
      remove_probes = diff.get('remove')
  
      changes = {
          'added': _ordered_dict_to_dict(add_probes),
          'updated': _ordered_dict_to_dict(update_probes),
          'removed': _ordered_dict_to_dict(remove_probes)
      }
  
      ret.update({
          'changes': changes
      })
  
      if __opts__['test'] is True:
          ret.update({
              'comment': 'Testing mode: configuration was not changed!',
              'result': None
          })
          return ret
  
      config_change_expected = False  # to check if something changed and a commit would be needed
  
      if add_probes:
          added = _set_rpm_probes(add_probes)
          if added.get('result'):
              config_change_expected = True
          else:
              result = False
              comment += 'Cannot define new probes: {reason}\n'.format(
                  reason=added.get('comment')
              )
  
      if update_probes:
          updated = _set_rpm_probes(update_probes)
          if updated.get('result'):
              config_change_expected = True
          else:
              result = False
              comment += 'Cannot update probes: {reason}\n'.format(
                  reason=updated.get('comment')
              )
  
      if remove_probes:
          removed = _delete_rpm_probes(remove_probes)
          if removed.get('result'):
              config_change_expected = True
          else:
              result = False
              comment += 'Cannot remove probes! {reason}\n'.format(
                  reason=removed.get('comment')
              )
  
      # <---- Call set_probes and delete_probes as needed ----------------------------------------------------------------
  
      # ----- Try to save changes --------------------------------------------------------------------------------------->
  
      if config_change_expected:
          # if any changes expected, try to commit
          result, comment = __salt__['net.config_control']()
  
      # <---- Try to save changes ----------------------------------------------------------------------------------------
  
      # ----- Try to schedule the probes -------------------------------------------------------------------------------->
  
      add_scheduled = _schedule_probes(add_probes)
      if add_scheduled.get('result'):
          # if able to load the template to schedule the probes, try to commit the scheduling data
          # (yes, a second commit is needed)
          # on devices such as Juniper, RPM probes do not need to be scheduled
          # therefore the template is empty and won't try to commit empty changes
          result, comment = __salt__['net.config_control']()
  
      if config_change_expected:
          if result and comment == '':  # if any changes and was able to apply them
              comment = 'Probes updated successfully!'
  
      ret.update({
          'result': result,
          'comment': comment
      })
  
      return ret