# class Chef::Provider::Group::Dscl

### Public Instance Methods

create_group() click to toggle source

    # File lib/chef/provider/group/dscl.rb, line 122
    def create_group
      dscl_create_group
      set_gid
      set_members
    end

define_resource_requirements() click to toggle source
Calls superclass method Chef::Provider::Group#define_resource_requirements

    # File lib/chef/provider/group/dscl.rb, line 109
    def define_resource_requirements
      super
      requirements.assert(:all_actions) do |a|
        a.assertion { ::File.exists?("/usr/bin/dscl") }
        a.failure_message Chef::Exceptions::Group, "Could not find binary /usr/bin/dscl for #{@new_resource.name}"
        # No whyrun alternative: this component should be available in the base install of any given system that uses it
      end
    end

dscl(*args) click to toggle source

    # File lib/chef/provider/group/dscl.rb, line 24
    def dscl(*args)
      host = "."
      stdout_result = ""; stderr_result = ""; cmd = "dscl #{host} -#{args.join(' ')}"
      status = popen4(cmd) do |pid, stdin, stdout, stderr|
        stdout.each { |line| stdout_result << line }
        stderr.each { |line| stderr_result << line }
      end
      return [cmd, status, stdout_result, stderr_result]
    end

dscl_create_group() click to toggle source

    # File lib/chef/provider/group/dscl.rb, line 140
    def dscl_create_group
      safe_dscl("create /Groups/#{@new_resource.group_name}")
      safe_dscl("create /Groups/#{@new_resource.group_name} Password '*'")
    end

get_free_gid(search_limit=1000) click to toggle source

get a free GID greater than 200

    # File lib/chef/provider/group/dscl.rb, line 49
    def get_free_gid(search_limit=1000)
      gid = nil; next_gid_guess = 200
      groups_gids = safe_dscl("list /Groups gid")
      while(next_gid_guess < search_limit + 200)
        if groups_gids =~ Regexp.new("#{Regexp.escape(next_gid_guess.to_s)}\n")
          next_gid_guess += 1
        else
          gid = next_gid_guess
          break
        end
      end
      return gid || raise("gid not found. Exhausted. Searched #{search_limit} times")
    end

gid_used?(gid) click to toggle source

    # File lib/chef/provider/group/dscl.rb, line 63
    def gid_used?(gid)
      return false unless gid
      groups_gids = safe_dscl("list /Groups gid")
      !! ( groups_gids =~ Regexp.new("#{Regexp.escape(gid.to_s)}\n") )
    end

load_current_resource() click to toggle source
Calls superclass method Chef::Provider::Group#load_current_resource

    # File lib/chef/provider/group/dscl.rb, line 118
    def load_current_resource
      super
    end

manage_group() click to toggle source

    # File lib/chef/provider/group/dscl.rb, line 128
    def manage_group
      if @new_resource.group_name && (@current_resource.group_name != @new_resource.group_name)
        dscl_create_group
      end
      if @new_resource.gid && (@current_resource.gid != @new_resource.gid)
        set_gid
      end
      if @new_resource.members || @new_resource.excluded_members
        set_members
      end
    end

remove_group() click to toggle source

    # File lib/chef/provider/group/dscl.rb, line 145
    def remove_group
      safe_dscl("delete /Groups/#{@new_resource.group_name}")
    end

safe_dscl(*args) click to toggle source

    # File lib/chef/provider/group/dscl.rb, line 34
    def safe_dscl(*args)
      result = dscl(*args)
      return "" if ( args.first =~ /^delete/ ) && ( result[1].exitstatus != 0 )
      raise(Chef::Exceptions::Group,"dscl error: #{result.inspect}") unless result[1].exitstatus == 0
      raise(Chef::Exceptions::Group,"dscl error: #{result.inspect}") if result[2] =~ /No such key: /
      return result[2]
    end

set_gid() click to toggle source

    # File lib/chef/provider/group/dscl.rb, line 69
    def set_gid
      @new_resource.gid(get_free_gid) if [nil,""].include? @new_resource.gid
      raise(Chef::Exceptions::Group,"gid is already in use") if gid_used?(@new_resource.gid)
      safe_dscl("create /Groups/#{@new_resource.group_name} PrimaryGroupID #{@new_resource.gid}")
    end

set_members() click to toggle source

    # File lib/chef/provider/group/dscl.rb, line 75
    def set_members
      # First reset the memberships if the append is not set
      unless @new_resource.append
        Chef::Log.debug("#{@new_resource} removing group members #{@current_resource.members.join(' ')}") unless @current_resource.members.empty?
        safe_dscl("create /Groups/#{@new_resource.group_name} GroupMembers ''") # clear guid list
        safe_dscl("create /Groups/#{@new_resource.group_name} GroupMembership ''") # clear user list
        @current_resource.members([ ])
      end

      # Add any members that need to be added
      if @new_resource.members && !@new_resource.members.empty?
        members_to_be_added = [ ]
        @new_resource.members.each do |member|
          members_to_be_added << member if !@current_resource.members.include?(member)
        end
        unless members_to_be_added.empty?
          Chef::Log.debug("#{@new_resource} setting group members #{members_to_be_added.join(', ')}")
          safe_dscl("append /Groups/#{@new_resource.group_name} GroupMembership #{members_to_be_added.join(' ')}")
        end
      end

      # Remove any members that need to be removed
      if @new_resource.excluded_members && !@new_resource.excluded_members.empty?
        members_to_be_removed = [ ]
        @new_resource.excluded_members.each do |member|
          members_to_be_removed << member if @current_resource.members.include?(member)
        end
        unless members_to_be_removed.empty?
          Chef::Log.debug("#{@new_resource} removing group members #{members_to_be_removed.join(', ')}")
          safe_dscl("delete /Groups/#{@new_resource.group_name} GroupMembership #{members_to_be_removed.join(' ')}")
        end
      end
    end