docs: def ext_pillar(minion_id,
                 pillar,  # pylint: disable=W0613
                 use_grain=False,
                 minion_ids=None,
                 tag_match_key=None,
                 tag_match_value='asis',
                 tag_list_key=None,
                 tag_list_sep=';'):
      '''
      Execute a command and read the output as YAML
      '''
      valid_tag_match_value = ['uqdn', 'asis']
  
      # meta-data:instance-id
      grain_instance_id = __grains__.get('meta-data', {}).get('instance-id', None)
      if not grain_instance_id:
          # dynamic:instance-identity:document:instanceId
          grain_instance_id = \
              __grains__.get('dynamic', {}).get('instance-identity', {}).get('document', {}).get('instance-id', None)
      if grain_instance_id and re.search(r'^i-([0-9a-z]{17}|[0-9a-z]{8})$', grain_instance_id) is None:
          log.error('External pillar %s, instance-id \'%s\' is not valid for '
                    '\'%s\'', __name__, grain_instance_id, minion_id)
          grain_instance_id = None  # invalid instance id found, remove it from use.
  
      # Check AWS Tag restrictions .i.e. letters, spaces, and numbers and + - = . _ : / @
      if tag_match_key and re.match(r'[\w=.:/@-]+$', tag_match_key) is None:
          log.error('External pillar %s, tag_match_key \'%s\' is not valid ',
                    __name__, tag_match_key if isinstance(tag_match_key, six.text_type) else 'non-string')
          return {}
  
      if tag_match_key and tag_match_value not in valid_tag_match_value:
          log.error('External pillar %s, tag_value \'%s\' is not valid must be one '
                    'of %s', __name__, tag_match_value, ' '.join(valid_tag_match_value))
          return {}
  
      if not tag_match_key:
          base_msg = ('External pillar %s, querying EC2 tags for minion id \'%s\' '
                      'against instance-id', __name__, minion_id)
      else:
          base_msg = ('External pillar %s, querying EC2 tags for minion id \'%s\' '
                      'against instance-id or \'%s\' against \'%s\'', __name__, minion_id, tag_match_key, tag_match_value)
  
      log.debug(base_msg)
      find_filter = None
      find_id = None
  
      if re.search(r'^i-([0-9a-z]{17}|[0-9a-z]{8})$', minion_id) is not None:
          find_filter = None
          find_id = minion_id
      elif tag_match_key:
          if tag_match_value == 'uqdn':
              find_filter = {'tag:{0}'.format(tag_match_key): minion_id.split('.', 1)[0]}
          else:
              find_filter = {'tag:{0}'.format(tag_match_key): minion_id}
          if grain_instance_id:
              # we have an untrusted grain_instance_id, use it to narrow the search
              # even more. Combination will be unique even if uqdn is set.
              find_filter.update({'instance-id': grain_instance_id})
          # Add this if running state is not dependant on EC2Config
          # find_filter.update('instance-state-name': 'running')
  
      # no minion-id is instance-id and no suitable filter, try use_grain if enabled
      if not find_filter and not find_id and use_grain:
          if not grain_instance_id:
              log.debug('Minion-id is not in AWS instance-id formation, and there '
                        'is no instance-id grain for minion %s', minion_id)
              return {}
          if minion_ids is not None and minion_id not in minion_ids:
              log.debug('Minion-id is not in AWS instance ID format, and minion_ids '
                        'is set in the ec2_pillar configuration, but minion %s is '
                        'not in the list of allowed minions %s', minion_id, minion_ids)
              return {}
          find_id = grain_instance_id
  
      if not (find_filter or find_id):
          log.debug('External pillar %s, querying EC2 tags for minion id \'%s\' against '
                    'instance-id or \'%s\' against \'%s\' noughthing to match against',
                    __name__, minion_id, tag_match_key, tag_match_value)
          return {}
  
      myself = boto.utils.get_instance_metadata(timeout=0.1, num_retries=1)
      if not myself:
          log.info("%s: salt master not an EC2 instance, skipping", __name__)
          return {}
  
      # Get the Master's instance info, primarily the region
      (_, region) = _get_instance_info()
  
      # If the Minion's region is available, use it instead
      if use_grain:
          region = __grains__.get('ec2', {}).get('region', region)
  
      try:
          conn = boto.ec2.connect_to_region(region)
      except boto.exception.AWSConnectionError as exc:
          log.error('%s: invalid AWS credentials, %s', __name__, exc)
          return {}
  
      if conn is None:
          log.error('%s: Could not connect to region %s', __name__, region)
          return {}
  
      try:
          if find_id:
              instance_data = conn.get_only_instances(instance_ids=[find_id], dry_run=False)
          else:
              # filters and max_results can not be used togther.
              instance_data = conn.get_only_instances(filters=find_filter, dry_run=False)
  
      except boto.exception.EC2ResponseError as exc:
          log.error('%s failed with \'%s\'', base_msg, exc)
          return {}
  
      if not instance_data:
          log.debug('%s no match using \'%s\'', base_msg, find_id if find_id else find_filter)
          return {}
  
      # Find a active instance, i.e. ignore terminated and stopped instances
      active_inst = []
      for inst in range(0, len(instance_data)):
          if instance_data[inst].state not in ['terminated', 'stopped']:
              active_inst.append(inst)
  
      valid_inst = len(active_inst)
      if not valid_inst:
          log.debug('%s match found but not active \'%s\'', base_msg, find_id if find_id else find_filter)
          return {}
  
      if valid_inst > 1:
          log.error('%s multiple matches, ignored, using \'%s\'', base_msg, find_id if find_id else find_filter)
          return {}
  
      instance = instance_data[active_inst[0]]
      if instance.tags:
          ec2_tags = instance.tags
          ec2_tags_list = {}
          log.debug('External pillar %s, for minion id \'%s\', tags: %s', __name__, minion_id, instance.tags)
          if tag_list_key and isinstance(tag_list_key, list):
              for item in tag_list_key:
                  if item in ec2_tags:
                      ec2_tags_list[item] = ec2_tags[item].split(tag_list_sep)
                      del ec2_tags[item]  # make sure its only in ec2_tags_list
                  else:
                      ec2_tags_list[item] = []  # always return a result
  
          return {'ec2_tags': ec2_tags, 'ec2_tags_list': ec2_tags_list}
      return {}