module ASF

The ASF module contains a set of classes which encapsulate access to a number of data sources such as LDAP, ICLAs, auth lists, etc. This code originally was developed as a part of separate tools and was later refactored out into a common library. Some of the older tools don't fully make use of this refactoring.

Constants

ETCLDAP

Directory where ldap.conf resides. Differs based on operating system.

Public Class Methods

committerids() click to toggle source

Obtain a list of committerids from LDAP cn=committers,ou=role,ou=groups,dc=apache,dc=org

# File lib/whimsy/asf/ldap.rb, line 406
def self.committerids
  weakref(:committerids) {RoleGroup.find('committers').memberids}
end
committers() click to toggle source

Obtain a list of committers from LDAP cn=committers,ou=role,ou=groups,dc=apache,dc=org

# File lib/whimsy/asf/ldap.rb, line 400
def self.committers
  weakref(:committers) {RoleGroup.find('committers').members}
end
dereference_weakref(object, attr, &block) click to toggle source

safely dereference a weakref array attribute. Block provided is used when reference is not set or has been reclaimed.

# File lib/whimsy/asf/ldap.rb, line 358
def self.dereference_weakref(object, attr, &block)
  attr = "@#{attr}"
  value = object.instance_variable_get(attr) || block.call
  value[0..-1]
rescue WeakRef::RefError
  value = block.call
ensure
  if not value or RUBY_VERSION.start_with? '1'
    object.instance_variable_set(attr, value)
  elsif value and not value.instance_of? WeakRef
    object.instance_variable_set(attr, WeakRef.new(value))
  end

  # keep track of which weak references are saved
  @@weakrefs << attr if object == self
end
flush_weakrefs() click to toggle source
# File lib/whimsy/asf/ldap.rb, line 375
def self.flush_weakrefs
  @@weakrefs.each do |attr|
    self.remove_instance_variable(attr)
  end

  @@weakrefs.clear

  # run garbage collection
  GC.start
end
init_ldap(reset = false, hosts = nil) click to toggle source

public entry point for establishing a connection safely

# File lib/whimsy/asf/ldap.rb, line 290
def self.init_ldap(reset = false, hosts = nil)
  ASF::LDAP::CONNECT_LOCK.synchronize do
    @ldap = nil if reset
    @ldap ||= ASF::LDAP.connect(!reset, hosts)
  end
end
ldap() click to toggle source

Returns existing LDAP connection, creating one if necessary.

# File lib/whimsy/asf/ldap.rb, line 305
def self.ldap
  @ldap || self.init_ldap
end
library_gitinfo() click to toggle source

Last commit in this clone, and the date and time of that commit.

# File lib/whimsy/asf.rb, line 35
def self.library_gitinfo
  return @info if @info
  @info = %x`git show --format="%h  %ci"  -s HEAD`.strip
end
library_mtime() click to toggle source

Last modified time of any file in the entire source tree.

# File lib/whimsy/asf.rb, line 27
def self.library_mtime
  parent_dir = File.dirname(File.expand_path(__FILE__))
  sources = Dir.glob("#{parent_dir}/**/*")
  times = sources.map {|source| File.mtime(source.untaint)}
  times.max.gmtime
end
memberids() click to toggle source

Obtain a list of memberids from LDAP cn=member,ou=groups,dc=apache,dc=org Note: includes some non-ASF member infrastructure contractors TODO: convert to RoleGroup at some point?

# File lib/whimsy/asf/ldap.rb, line 422
def self.memberids
  weakref(:memberids) {Group.find('member').memberids}
end
members() click to toggle source

Obtain a list of members from LDAP cn=member,ou=groups,dc=apache,dc=org Note: includes some non-ASF member infrastructure contractors TODO: convert to RoleGroup at some point?

# File lib/whimsy/asf/ldap.rb, line 414
def self.members
  weakref(:members) {Group.find('member').members}
end
pmc_chairs() click to toggle source

Obtain a list of PMC chairs from LDAP cn=pmc-chairs,ou=groups,ou=services,dc=apache,dc=org Note: this list may include non-PMC VPs.

# File lib/whimsy/asf/ldap.rb, line 394
def self.pmc_chairs
  weakref(:pmc_chairs) {Service.find('pmc-chairs').members}
end
search_archive_by_id(id) click to toggle source

Search archive for historical records of people who were committers but never submitted an ICLA (some of which are still ASF members or members of a PMC).

# File lib/whimsy/asf/icla.rb, line 254
def self.search_archive_by_id(id)
  archive = ASF::SVN['officers_historic']
  name = JSON.parse(File.read(File.join(archive, 'committers.json')))[id]
  name = id if name and name.empty?
  name
end
search_one(base, filter, attrs=nil) click to toggle source

search with a scope of one, with automatic retry/failover

# File lib/whimsy/asf/ldap.rb, line 310
def self.search_one(base, filter, attrs=nil)
  self.search_scope(::LDAP::LDAP_SCOPE_ONELEVEL, base, filter, attrs)
end
search_scope(scope, base, filter, attrs=nil) click to toggle source

search with a specified scope, with automatic retry/failover

# File lib/whimsy/asf/ldap.rb, line 320
def self.search_scope(scope, base, filter, attrs=nil)

  # Dummy command, used for logging purposes only
  sname = %w(base one sub children)[scope] rescue scope
  cmd = "ldapsearch -x -LLL -b #{base} -s #{sname} #{filter} " +
    "#{[attrs].flatten.join(' ')}"

  # try once per host, with a minimum of two tries
  attempts_left = [ASF::LDAP.hosts.length, 2].max
  begin
    attempts_left -= 1
    init_ldap unless @ldap
    return [] unless @ldap

    target = @ldap.get_option(::LDAP::LDAP_OPT_HOST_NAME) rescue '?'
    Wunderbar.info "[#{target}] #{cmd}"

    result = @ldap.search2(base, scope, filter, attrs)
  rescue Exception => re
    if attempts_left <= 0
      Wunderbar.error "[#{target}] => #{re.inspect} for #{cmd}"
      raise
    else
      Wunderbar.warn "[#{target}] => #{re.inspect} for #{cmd}, retrying ..."
      @ldap.unbind if @ldap.bound? rescue nil
      @ldap = nil # force new connection
      sleep 1
      retry
    end
  end

  result.map! {|hash| hash[attrs]} if String === attrs

  result.compact
end
search_subtree(base, filter, attrs=nil) click to toggle source

search with a scope of subtree, with automatic retry/failover

# File lib/whimsy/asf/ldap.rb, line 315
def self.search_subtree(base, filter, attrs=nil)
  self.search_scope(::LDAP::LDAP_SCOPE_SUBTREE, base, filter, attrs)
end
weakref(attr, &block) click to toggle source

shortcut for dereference weakref

# File lib/whimsy/asf/ldap.rb, line 387
def self.weakref(attr, &block)
  self.dereference_weakref(self, attr, &block)
end