File: rabbitmqctl.rb

package info (click to toggle)
puppet-module-puppetlabs-rabbitmq 8.5.0-11
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,196 kB
  • sloc: ruby: 5,227; sh: 10; makefile: 4
file content (134 lines) | stat: -rw-r--r-- 3,576 bytes parent folder | download
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
134
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'rabbitmq_cli'))
Puppet::Type.type(:rabbitmq_user).provide(
  :rabbitmqctl,
  parent: Puppet::Provider::RabbitmqCli
) do
  confine feature: :posix

  def initialize(value = {})
    super(value)
    @property_flush = {}
  end

  def self.instances
    user_list = run_with_retries do
      rabbitmqctl_list('users')
    end

    lines = user_list.split(%r{\n})

    # Skip the header lines in RabbitMQ 4.x
    # Skip "Listing users ..." and "user    tags" lines
    while lines.any? && (lines.first =~ %r{^Listing users} || lines.first =~ %r{^user\s+tags} || lines.first.strip.empty?)
      lines.shift
    end

    # Process remaining lines (should be user data)
    lines.map do |line|
      raise Puppet::Error, "Cannot parse invalid user line: #{line}" unless line =~ %r{^(\S+)\s+\[(.*?)\]$}
      user = Regexp.last_match(1)
      tags = Regexp.last_match(2).split(%r{,\s*})
      new(
        ensure: :present,
        name: user,
        tags: tags
      )
    end
  end

  def self.prefetch(resources)
    users = instances
    resources.each_key do |user|
      if (provider = users.find { |u| u.name == user })
        resources[user].provider = provider
      end
    end
  end

  def exists?
    @property_hash[:ensure] == :present
  end

  def create
    # Fail here (rather than a validate block in the type) if password is not
    # set, so that "puppet resource" still works.
    raise Puppet::Error, "Password is a required parameter for rabbitmq_user (user: #{name})" if @resource[:password].nil?

    rabbitmqctl('add_user', @resource[:name], @resource[:password])

    tags = @resource[:tags]
    tags << admin_tag if @resource[:admin] == :true
    rabbitmqctl('set_user_tags', @resource[:name], tags) unless tags.empty?

    @property_hash[:ensure] = :present
  end

  def destroy
    rabbitmqctl('delete_user', @resource[:name])
    @property_hash[:ensure] = :absent
  end

  def password=(password)
    rabbitmqctl('change_password', @resource[:name], password)
  end

  def password; end

  def check_password(password)
    check_access_control = [
      'rabbit_access_control:check_user_pass_login(',
      %[list_to_binary("#{@resource[:name]}"), ],
      %[list_to_binary("#{password}")).]
    ]

    response = rabbitmqctl('eval', check_access_control.join)
    !response.include? 'refused'
  end

  def tags
    # do not expose the administrator tag for admins
    @property_hash[:tags].reject { |tag| tag == admin_tag }
  end

  def tags=(tags)
    @property_flush[:tags] = tags
  end

  def admin
    usertags = get_user_tags
    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
    (:true if usertags.include?('administrator')) || :false
  end

  def admin=(state)
    if state == :true
      make_user_admin
    else
      usertags = get_user_tags
      usertags.delete('administrator')
      rabbitmqctl('set_user_tags', resource[:name], usertags.entries.sort)
    end
  end

  def admin
    @property_hash[:tags].include?(admin_tag) ? :true : :false
  end

  def admin=(state)
    @property_flush[:admin] = state
  end

  def flush
    return if @property_flush.empty?
    tags = @property_flush[:tags] || @resource[:tags]
    tags << admin_tag if @resource[:admin] == :true
    rabbitmqctl('set_user_tags', @resource[:name], tags)
    @property_flush.clear
  end

  private

  def admin_tag
    'administrator'
  end
end