summaryrefslogtreecommitdiffstats
path: root/lib/puppet/provider/ldap.rb
blob: b7d6baa9e163ef4246796074f2e1a1ab05c76c5f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
require 'puppet/provider'

# The base class for LDAP providers.
class Puppet::Provider::Ldap < Puppet::Provider
  require 'puppet/util/ldap/manager'

  class << self
    attr_reader :manager
  end

  # Look up all instances at our location.  Yay.
  def self.instances
    return [] unless list = manager.search

    list.collect { |entry| new(entry) }
  end

  # Specify the ldap manager for this provider, which is
  # used to figure out how we actually interact with ldap.
  def self.manages(*args)
    @manager = Puppet::Util::Ldap::Manager.new
    @manager.manages(*args)

    # Set up our getter/setter methods.
    mk_resource_methods
    @manager
  end

  # Query all of our resources from ldap.
  def self.prefetch(resources)
    resources.each do |name, resource|
      if result = manager.find(name)
        result[:ensure] = :present
        resource.provider = new(result)
      else
        resource.provider = new(:ensure => :absent)
      end
    end
  end

  def manager
    self.class.manager
  end

  def create
    @property_hash[:ensure] = :present
    self.class.resource_type.validproperties.each do |property|
      if val = resource.should(property)
        @property_hash[property] = val
      end
    end
  end

  def delete
    @property_hash[:ensure] = :absent
  end

  def exists?
    @property_hash[:ensure] != :absent
  end

  # Apply our changes to ldap, yo.
  def flush
    # Just call the manager's update() method.
    @property_hash.delete(:groups)
    @ldap_properties.delete(:groups)
    manager.update(name, ldap_properties, properties)
    @property_hash.clear
    @ldap_properties.clear
  end

  def initialize(*args)
    raise(Puppet::DevError, "No LDAP Configuration defined for #{self.class}") unless self.class.manager
    raise(Puppet::DevError, "Invalid LDAP Configuration defined for #{self.class}") unless self.class.manager.valid?
    super

    @property_hash = @property_hash.inject({}) do |result, ary|
      param, values = ary

      # Skip any attributes we don't manage.
      next result unless self.class.resource_type.valid_parameter?(param)

      paramclass = self.class.resource_type.attrclass(param)

      unless values.is_a?(Array)
        result[param] = values
        next result
      end

      # Only use the first value if the attribute class doesn't manage
      # arrays of values.
      if paramclass.superclass == Puppet::Parameter or paramclass.array_matching == :first
        result[param] = values[0]
      else
        result[param] = values
      end
      result
    end

    # Make a duplicate, so that we have a copy for comparison
    # at the end.
    @ldap_properties = @property_hash.dup
  end

  # Return the current state of ldap.
  def ldap_properties
    @ldap_properties.dup
  end

  # Return (and look up if necessary) the desired state.
  def properties
    if @property_hash.empty?
      @property_hash = query || {:ensure => :absent}
      @property_hash[:ensure] = :absent if @property_hash.empty?
    end
    @property_hash.dup
  end

  # Collect the current attributes from ldap.  Returns
  # the results, but also stores the attributes locally,
  # so we have something to compare against when we update.
  # LAK:NOTE This is normally not used, because we rely on prefetching.
  def query
    # Use the module function.
    unless attributes = manager.find(name)
      @ldap_properties = {}
      return nil
    end

    @ldap_properties = attributes
    @ldap_properties.dup
  end
end