Skip to content

Commit c9f86fc

Browse files
authored
Merge pull request #187 from reidmv/get-peadm-config
Add get_peadm_config task
2 parents c63440c + 7a967b5 commit c9f86fc

File tree

3 files changed

+157
-2
lines changed

3 files changed

+157
-2
lines changed

manifests/setup/node_manager.pp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131
Optional[String[1]] $postgresql_b_host = $server_b_host,
3232

3333
Optional[String[1]] $compiler_pool_address = undef,
34-
Optional[String[1]] $internal_compiler_a_pool_address = $postgresql_a_host,
35-
Optional[String[1]] $internal_compiler_b_pool_address = $postgresql_b_host,
34+
Optional[String[1]] $internal_compiler_a_pool_address = $server_a_host,
35+
Optional[String[1]] $internal_compiler_b_pool_address = $server_b_host,
3636
) {
3737

3838
# "Not-configured" placeholder string. This will be used in places where we

tasks/get_peadm_config.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"description": "Run on a PE primary node to return the currently configured PEAdm parameters",
3+
"parameters": { },
4+
"input_method": "stdin"
5+
}

tasks/get_peadm_config.rb

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
#!/opt/puppetlabs/puppet/bin/ruby
2+
# frozen_string_literal: true
3+
4+
require 'json'
5+
require 'uri'
6+
require 'net/http'
7+
require 'puppet'
8+
9+
# GetPEAdmConfig task class
10+
class GetPEAdmConfig
11+
def initialize(params); end
12+
13+
def execute!
14+
puts config.to_json
15+
end
16+
17+
def config
18+
# Compute values
19+
primary = groups.pinned('PE Master')
20+
replica = groups.pinned('PE HA Replica')
21+
server_a = server('puppet/server', 'A')
22+
server_b = server('puppet/server', 'B')
23+
primary_letter = primary.eql?(server_a) ? 'A' : 'B'
24+
replica_letter = primary_letter.eql?('A') ? 'B' : 'A'
25+
postgresql = {
26+
'A' => server('puppet/puppetdb-database', 'A'),
27+
'B' => server('puppet/puppetdb-database', 'B'),
28+
}
29+
30+
# Build and return the task output
31+
{
32+
'params' => {
33+
'primary_host' => primary,
34+
'replica_host' => replica,
35+
'primary_postgresql_host' => postgresql[primary_letter],
36+
'replica_postgresql_host' => postgresql[replica_letter],
37+
'compilers' => compilers.map { |c| c['certname'] },
38+
'compiler_pool_address' => groups.dig('PE Master', 'config_data', 'pe_repo', 'compile_master_pool_address'),
39+
'internal_compiler_a_pool_address' => groups.dig('PE Compiler Group A', 'classes', 'puppet_enterprise::profile::master', 'puppetdb_host', 1),
40+
'internal_compiler_b_pool_address' => groups.dig('PE Compiler Group B', 'classes', 'puppet_enterprise::profile::master', 'puppetdb_host', 1),
41+
},
42+
'role-letter' => {
43+
'server' => {
44+
'A' => server_a,
45+
'B' => server_b,
46+
},
47+
'postgresql' => {
48+
'A' => postgresql['A'],
49+
'B' => postgresql['B'],
50+
},
51+
'compilers' => {
52+
'A' => compilers.select { |c| c['letter'] == 'A' }.map { |c| c['certname'] },
53+
'B' => compilers.select { |c| c['letter'] == 'B' }.map { |c| c['certname'] },
54+
}
55+
},
56+
}
57+
end
58+
59+
# Returns a GetPEAdmConfig::NodeGroups object created from the /groups object
60+
# returned by the classifier
61+
def groups
62+
@groups ||= begin
63+
net = https(4433)
64+
res = net.get('/classifier-api/v1/groups')
65+
NodeGroup.new(JSON.parse(res.body))
66+
end
67+
end
68+
69+
# Returns a list of compiler certnames and letters, based on a PuppetDB query
70+
def compilers
71+
@compilers ||= begin
72+
pdb_query('inventory[certname,trusted.extensions] { trusted.extensions.pp_auth_role = "pe_compiler" }').map do |c|
73+
{
74+
'certname' => c['certname'],
75+
'letter' => c.dig('trusted.extensions', '1.3.6.1.4.1.34380.1.1.9813'),
76+
}
77+
end
78+
end
79+
end
80+
81+
def server(role, letter)
82+
query = 'inventory[certname] { '\
83+
' trusted.extensions."1.3.6.1.4.1.34380.1.1.9812" = "' + role + '" and ' \
84+
' trusted.extensions."1.3.6.1.4.1.34380.1.1.9813" = "' + letter + '"}'
85+
86+
server = pdb_query(query).map { |n| n['certname'] }
87+
raise "More than one #{letter} #{role} server found!" unless server.size <= 1
88+
server.first
89+
end
90+
91+
def https(port)
92+
https = Net::HTTP.new('localhost', port)
93+
https.use_ssl = true
94+
https.cert = @cert ||= OpenSSL::X509::Certificate.new(File.read(Puppet.settings[:hostcert]))
95+
https.key = @key ||= OpenSSL::PKey::RSA.new(File.read(Puppet.settings[:hostprivkey]))
96+
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
97+
https
98+
end
99+
100+
def pdb_query(query)
101+
pdb = https(8081)
102+
pdb_request = Net::HTTP::Get.new('/pdb/query/v4')
103+
pdb_request.set_form_data({ 'query' => query })
104+
JSON.parse(pdb.request(pdb_request).body)
105+
end
106+
107+
# Utility class to aid in retrieving useful information from the node group
108+
# data
109+
class NodeGroup
110+
attr_reader :data
111+
112+
def initialize(data)
113+
@data = data
114+
end
115+
116+
# Aids in digging into node groups by name, rather than UUID
117+
def dig(name, *args)
118+
group = @data.find { |obj| obj['name'] == name }
119+
if group.nil?
120+
nil
121+
elsif args.empty?
122+
group
123+
else
124+
group.dig(*args)
125+
end
126+
end
127+
128+
# Return the node pinned to the named group
129+
# If there is more than one node, error
130+
def pinned(name)
131+
rule = dig(name, 'rule')
132+
return nil if rule.nil?
133+
raise "#{name} rule incompatible with pinning" unless rule.first == 'or'
134+
pinned = rule.drop(1)
135+
.select { |r| r[0] == '=' && r[1] == 'name' }
136+
.map { |r| r[2] }
137+
raise "#{name} contains more than one server!" unless pinned.size <= 1
138+
pinned.first
139+
end
140+
end
141+
end
142+
143+
# Run the task unless an environment flag has been set, signaling not to. The
144+
# environment flag is used to disable auto-execution and enable Ruby unit
145+
# testing of this task.
146+
unless ENV['RSPEC_UNIT_TEST_MODE']
147+
Puppet.initialize_settings
148+
task = GetPEAdmConfig.new(JSON.parse(STDIN.read))
149+
task.execute!
150+
end

0 commit comments

Comments
 (0)