docs: def present(name,
              gid=None,
              system=False,
              addusers=None,
              delusers=None,
              members=None):
      r'''
      Ensure that a group is present
  
      Args:
  
          name (str):
              The name of the group to manage
  
          gid (str):
              The group id to assign to the named group; if left empty, then the
              next available group id will be assigned. Ignored on Windows
  
          system (bool):
              Whether or not the named group is a system group.  This is essentially
              the '-r' option of 'groupadd'. Ignored on Windows
  
          addusers (list):
              List of additional users to be added as a group members. Cannot
              conflict with names in delusers. Cannot be used in conjunction with
              members.
  
          delusers (list):
              Ensure these user are removed from the group membership. Cannot
              conflict with names in addusers. Cannot be used in conjunction with
              members.
  
          members (list):
              Replace existing group members with a list of new members. Cannot be
              used in conjunction with addusers or delusers.
  
      Example:
  
      .. code-block:: yaml
  
          # Adds DOMAIN\db_admins and Administrators to the local db_admin group
          # Removes Users
          db_admin:
            group.present:
              - addusers:
                - DOMAIN\db_admins
                - Administrators
              - delusers:
                - Users
  
          # Ensures only DOMAIN\domain_admins and the local Administrator are
          # members of the local Administrators group. All other users are
          # removed
          Administrators:
            group.present:
              - members:
                - DOMAIN\domain_admins
                - Administrator
      '''
      ret = {'name': name,
             'changes': {},
             'result': True,
             'comment': 'Group {0} is present and up to date'.format(name)}
  
      if members is not None and (addusers is not None or delusers is not None):
          ret['result'] = None
          ret['comment'] = (
              'Error: Conflicting options "members" with "addusers" and/or'
              ' "delusers" can not be used together. ')
          return ret
  
      if addusers and delusers:
          # -- if trying to add and delete the same user(s) at the same time.
          if not set(addusers).isdisjoint(set(delusers)):
              ret['result'] = None
              ret['comment'] = (
                  'Error. Same user(s) can not be added and deleted'
                  ' simultaneously')
              return ret
  
      changes = _changes(name,
                         gid,
                         addusers,
                         delusers,
                         members)
      if changes:
          ret['comment'] = (
              'The following group attributes are set to be changed:\n')
          for key, val in six.iteritems(changes):
              ret['comment'] += '{0}: {1}\n'.format(key, val)
  
          if __opts__['test']:
              ret['result'] = None
              return ret
  
          for key, val in six.iteritems(changes):
              if key == 'gid':
                  __salt__['group.chgid'](name, gid)
                  continue
              if key == 'addusers':
                  for user in val:
                      __salt__['group.adduser'](name, user)
                  continue
              if key == 'delusers':
                  for user in val:
                      __salt__['group.deluser'](name, user)
                  continue
              if key == 'members':
                  __salt__['group.members'](name, ','.join(members))
                  continue
          # Clear cached group data
          sys.modules[
              __salt__['test.ping'].__module__
              ].__context__.pop('group.getent', None)
          changes = _changes(name,
                             gid,
                             addusers,
                             delusers,
                             members)
          if changes:
              ret['result'] = False
              ret['comment'] += 'Some changes could not be applied'
              ret['changes'] = {'Failed': changes}
          else:
              ret['changes'] = {'Final': 'All changes applied successfully'}
  
      if changes is False:
          # The group is not present, make it!
          if __opts__['test']:
              ret['result'] = None
              ret['comment'] = 'Group {0} set to be added'.format(name)
              return ret
  
          grps = __salt__['group.getent']()
          # Test if gid is free
          if gid is not None:
              gid_group = None
              for lgrp in grps:
                  if lgrp['gid'] == gid:
                      gid_group = lgrp['name']
                      break
  
              if gid_group is not None:
                  ret['result'] = False
                  ret['comment'] = (
                      'Group {0} is not present but gid {1} is already taken by'
                      ' group {2}'.format(name, gid, gid_group))
                  return ret
  
          # Group is not present, make it.
          if __salt__['group.add'](name, gid=gid, system=system):
              # if members to be added
              grp_members = None
              if members:
                  grp_members = ','.join(members)
              if addusers:
                  grp_members = ','.join(addusers)
              if grp_members:
                  __salt__['group.members'](name, grp_members)
              # Clear cached group data
              sys.modules[__salt__['test.ping'].__module__].__context__.pop(
                  'group.getent', None)
              ret['comment'] = 'New group {0} created'.format(name)
              ret['changes'] = __salt__['group.info'](name)
              changes = _changes(name,
                                 gid,
                                 addusers,
                                 delusers,
                                 members)
              if changes:
                  ret['result'] = False
                  ret['comment'] = (
                      'Group {0} has been created but, some changes could not'
                      ' be applied'.format(name))
                  ret['changes'] = {'Failed': changes}
          else:
              ret['result'] = False
              ret['comment'] = 'Failed to create new group {0}'.format(name)
      return ret