docs: def present(name, auth=None, **kwargs):
      '''
      Ensure a security group rule exists
  
      defaults: port_range_min=None, port_range_max=None, protocol=None,
                remote_ip_prefix=None, remote_group_id=None, direction='ingress',
                ethertype='IPv4', project_id=None
  
      name
          Name of the security group to associate with this rule
  
      project_name
          Name of the project associated with the security group
  
      protocol
          The protocol that is matched by the security group rule.
          Valid values are None, tcp, udp, and icmp.
  
      '''
      ret = {'name': name,
             'changes': {},
             'result': True,
             'comment': ''}
  
      kwargs = __utils__['args.clean_kwargs'](**kwargs)
  
      __salt__['neutronng.setup_clouds'](auth)
  
      if 'project_name' in kwargs:
          kwargs['project_id'] = kwargs['project_name']
          del kwargs['project_name']
  
      project = __salt__['keystoneng.project_get'](
          name=kwargs['project_id'])
  
      if project is None:
          ret['result'] = False
          ret['comment'] = "Project does not exist"
          return ret
  
      secgroup = __salt__['neutronng.security_group_get'](
          name=name,
          filters={'tenant_id': project.id}
      )
  
      if secgroup is None:
          ret['result'] = False
          ret['changes'] = {},
          ret['comment'] = 'Security Group does not exist {}'.format(name)
          return ret
  
      # we have to search through all secgroup rules for a possible match
      rule_exists = None
      for rule in secgroup['security_group_rules']:
          if _rule_compare(rule, kwargs) is True:
              rule_exists = True
  
      if rule_exists is None:
          if __opts__['test'] is True:
              ret['result'] = None
              ret['changes'] = kwargs
              ret['comment'] = 'Security Group rule will be created.'
              return ret
  
          # The variable differences are a little clumsy right now
          kwargs['secgroup_name_or_id'] = secgroup
  
          new_rule = __salt__['neutronng.security_group_rule_create'](**kwargs)
          ret['changes'] = new_rule
          ret['comment'] = 'Created security group rule'
          return ret
  
      return ret