9eab0ddea8be21875a59e68be62ea160715345e4
[mirror/dsa-puppet.git] / 3rdparty / modules / rabbitmq / lib / puppet / provider / rabbitmq_user / rabbitmqctl.rb
1 require File.expand_path(File.join(File.dirname(__FILE__), '..', 'rabbitmqctl'))
2 Puppet::Type.type(:rabbitmq_user).provide(
3   :rabbitmqctl,
4   parent: Puppet::Provider::Rabbitmqctl
5 ) do
6   has_command(:rabbitmqctl, 'rabbitmqctl') do
7     environment HOME: '/tmp'
8   end
9
10   confine feature: :posix
11
12   def initialize(value = {})
13     super(value)
14     @property_flush = {}
15   end
16
17   def self.instances
18     user_list = run_with_retries do
19       rabbitmqctl('-q', 'list_users')
20     end
21
22     user_list.split(%r{\n}).map do |line|
23       raise Puppet::Error, "Cannot parse invalid user line: #{line}" unless line =~ %r{^(\S+)\s+\[(.*?)\]$}
24       user = Regexp.last_match(1)
25       tags = Regexp.last_match(2).split(%r{,\s*})
26       new(
27         ensure: :present,
28         name: user,
29         tags: tags
30       )
31     end
32   end
33
34   def self.prefetch(resources)
35     users = instances
36     resources.each_key do |user|
37       if (provider = users.find { |u| u.name == user })
38         resources[user].provider = provider
39       end
40     end
41   end
42
43   def exists?
44     @property_hash[:ensure] == :present
45   end
46
47   def create
48     # Fail here (rather than a validate block in the type) if password is not
49     # set, so that "puppet resource" still works.
50     raise Puppet::Error, "Password is a required parameter for rabbitmq_user (user: #{name})" if @resource[:password].nil?
51
52     rabbitmqctl('add_user', @resource[:name], @resource[:password])
53
54     tags = @resource[:tags]
55     tags << admin_tag if @resource[:admin] == :true
56     rabbitmqctl('set_user_tags', @resource[:name], tags) unless tags.empty?
57
58     @property_hash[:ensure] = :present
59   end
60
61   def destroy
62     rabbitmqctl('delete_user', @resource[:name])
63     @property_hash[:ensure] = :absent
64   end
65
66   def password=(password)
67     rabbitmqctl('change_password', @resource[:name], password)
68   end
69
70   def password; end
71
72   def check_password(password)
73     check_access_control = [
74       'rabbit_access_control:check_user_pass_login(',
75       %[list_to_binary("#{@resource[:name]}"), ],
76       %[list_to_binary("#{password}")).]
77     ]
78
79     response = rabbitmqctl('eval', check_access_control.join)
80     !response.include? 'refused'
81   end
82
83   def tags
84     # do not expose the administrator tag for admins
85     @property_hash[:tags].reject { |tag| tag == admin_tag }
86   end
87
88   def tags=(tags)
89     @property_flush[:tags] = tags
90   end
91
92   def admin
93     usertags = get_user_tags
94     raise Puppet::Error, "Could not match line '#{resource[:name]} (true|false)' from list_users (perhaps you are running on an older version of rabbitmq that does not support admin users?)" unless usertags
95     (:true if usertags.include?('administrator')) || :false
96   end
97
98   def admin=(state)
99     if state == :true
100       make_user_admin
101     else
102       usertags = get_user_tags
103       usertags.delete('administrator')
104       rabbitmqctl('set_user_tags', resource[:name], usertags.entries.sort)
105     end
106   end
107
108   def admin
109     @property_hash[:tags].include?(admin_tag) ? :true : :false
110   end
111
112   def admin=(state)
113     @property_flush[:admin] = state
114   end
115
116   def flush
117     return if @property_flush.empty?
118     tags = @property_flush[:tags] || @resource[:tags]
119     tags << admin_tag if @resource[:admin] == :true
120     rabbitmqctl('set_user_tags', @resource[:name], tags)
121     @property_flush.clear
122   end
123
124   private
125
126   def admin_tag
127     'administrator'
128   end
129 end