dropsonde 0.0.3 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +58 -0
- data/README.md +47 -16
- data/bin/dropsonde +18 -9
- data/lib/dropsonde/cache.rb +37 -33
- data/lib/dropsonde/metrics/dependencies.rb +37 -32
- data/lib/dropsonde/metrics/environments.rb +53 -0
- data/lib/dropsonde/metrics/modules.rb +75 -66
- data/lib/dropsonde/metrics/platforms.rb +126 -0
- data/lib/dropsonde/metrics/puppetfiles.rb +35 -32
- data/lib/dropsonde/metrics.rb +94 -82
- data/lib/dropsonde/monkeypatches.rb +12 -11
- data/lib/dropsonde/version.rb +3 -1
- data/lib/dropsonde.rb +64 -26
- metadata +10 -7
data/lib/dropsonde/metrics.rb
CHANGED
@@ -1,86 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'little-plugger'
|
4
|
+
require 'securerandom'
|
2
5
|
|
6
|
+
# metrics class
|
3
7
|
class Dropsonde::Metrics
|
4
|
-
extend LittlePlugger(
|
8
|
+
extend LittlePlugger(path: 'dropsonde/metrics', module: Dropsonde::Metrics)
|
5
9
|
|
6
10
|
def initialize
|
7
|
-
Dropsonde
|
11
|
+
if Dropsonde.settings[:enable]
|
12
|
+
Dropsonde.settings[:disable] ||= []
|
13
|
+
disable = Dropsonde::Metrics.plugins.keys - Dropsonde.settings[:enable].map(&:to_sym)
|
14
|
+
Dropsonde.settings[:disable].concat disable
|
15
|
+
end
|
16
|
+
|
17
|
+
Dropsonde::Metrics.disregard_plugins(*Dropsonde.settings[:disable])
|
8
18
|
Dropsonde::Metrics.initialize_plugins
|
9
19
|
end
|
10
20
|
|
11
21
|
def siteid
|
12
22
|
return @siteid if @siteid
|
13
23
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
24
|
+
@siteid = Dropsonde.settings[:siteid]
|
25
|
+
|
26
|
+
unless @siteid
|
27
|
+
sha2 = Digest::SHA512.new
|
28
|
+
sha2.update Puppet.settings[:certname]
|
29
|
+
sha2.update Puppet.settings[:cacert]
|
30
|
+
sha2.update Dropsonde.settings[:seed] if Dropsonde.settings[:seed]
|
31
|
+
@siteid = sha2.hexdigest
|
32
|
+
end
|
33
|
+
|
19
34
|
@siteid
|
20
35
|
end
|
21
36
|
|
22
37
|
def list
|
23
|
-
str
|
24
|
-
str
|
38
|
+
str = " Loaded telemetry plugins\n"
|
39
|
+
str += " ===============================\n\n"
|
25
40
|
Dropsonde::Metrics.plugins.each do |name, plugin|
|
26
|
-
str
|
27
|
-
str
|
28
|
-
str
|
29
|
-
str
|
41
|
+
str += name.to_s
|
42
|
+
str += "\n--------\n"
|
43
|
+
str += plugin.description.strip
|
44
|
+
str += "\n\n"
|
30
45
|
end
|
31
|
-
if Dropsonde.settings[:
|
32
|
-
str
|
33
|
-
str
|
46
|
+
if Dropsonde.settings[:disable]
|
47
|
+
str += "Disabled plugins:\n"
|
48
|
+
str += " #{Dropsonde.settings[:disable].join(', ')}"
|
34
49
|
end
|
35
50
|
str
|
36
51
|
end
|
37
52
|
|
38
53
|
def schema
|
39
54
|
schema = skeleton_schema
|
40
|
-
Dropsonde::Metrics.plugins.each do |
|
55
|
+
Dropsonde::Metrics.plugins.each do |_name, plugin|
|
41
56
|
schema.concat(sanity_check_schema(plugin))
|
42
57
|
end
|
43
58
|
check_for_duplicates(schema)
|
44
59
|
schema
|
45
60
|
end
|
46
61
|
|
47
|
-
def preview
|
48
|
-
str
|
49
|
-
str
|
50
|
-
Dropsonde::Metrics.plugins.each do |
|
62
|
+
def preview(puppetdb_session = nil)
|
63
|
+
str = " Puppet Telemetry Report Preview\n"
|
64
|
+
str += " ===============================\n\n"
|
65
|
+
Dropsonde::Metrics.plugins.each do |_name, plugin|
|
51
66
|
schema = plugin.schema
|
52
67
|
|
53
|
-
plugin.setup
|
54
|
-
data = sanity_check_data(plugin)
|
55
|
-
plugin.cleanup
|
68
|
+
plugin.setup if plugin.respond_to? :setup
|
69
|
+
data = sanity_check_data(plugin, plugin.run(puppetdb_session))
|
70
|
+
plugin.cleanup if plugin.respond_to? :cleanup
|
56
71
|
|
57
|
-
str
|
58
|
-
str
|
59
|
-
str
|
72
|
+
str += "#{plugin.name}\n"
|
73
|
+
str += "-------------------------------\n"
|
74
|
+
str += plugin.description
|
60
75
|
data.each do |row|
|
61
76
|
key = row.keys.first
|
62
|
-
values = row.values.
|
77
|
+
values = row.values.flatten
|
63
78
|
|
64
|
-
desc = schema.find {|item| item[:name].to_sym == key.to_sym}[:description]
|
65
|
-
str
|
79
|
+
desc = schema.find { |item| item[:name].to_sym == key.to_sym }[:description]
|
80
|
+
str += "- #{key}: #{desc}\n"
|
66
81
|
values.each do |item|
|
67
|
-
str
|
82
|
+
str += " #{item}\n"
|
68
83
|
end
|
69
84
|
end
|
70
|
-
str
|
85
|
+
str += "\n\n"
|
71
86
|
end
|
72
|
-
str
|
73
|
-
str
|
87
|
+
str += "Site ID:\n"
|
88
|
+
str += siteid
|
74
89
|
str
|
75
90
|
end
|
76
91
|
|
77
|
-
def report
|
92
|
+
def report(puppetdb_session = nil)
|
78
93
|
snapshots = {}
|
79
|
-
Dropsonde::Metrics.plugins.each do |
|
94
|
+
Dropsonde::Metrics.plugins.each do |_name, plugin|
|
80
95
|
plugin.setup
|
81
|
-
sanity_check_data(plugin, plugin.run).each do |row|
|
96
|
+
sanity_check_data(plugin, plugin.run(puppetdb_session)).each do |row|
|
82
97
|
snapshots[row.keys.first] = {
|
83
|
-
'value'
|
98
|
+
'value' => row.values.first,
|
84
99
|
'timestamp' => Time.now.iso8601,
|
85
100
|
}
|
86
101
|
end
|
@@ -100,7 +115,7 @@ class Dropsonde::Metrics
|
|
100
115
|
results[:ip] = IPAddr.new(rand(2**32), Socket::AF_INET)
|
101
116
|
results.delete(:'self-service-analytics')
|
102
117
|
|
103
|
-
Dropsonde::Metrics.plugins.each do |
|
118
|
+
Dropsonde::Metrics.plugins.each do |_name, plugin|
|
104
119
|
sanity_check_data(plugin, plugin.example).each do |row|
|
105
120
|
results.merge!(row)
|
106
121
|
end
|
@@ -112,8 +127,11 @@ class Dropsonde::Metrics
|
|
112
127
|
# We accept both the plugin and data gathered from the plugin so that
|
113
128
|
# we can sanitize both data and example data
|
114
129
|
def sanity_check_data(plugin, data)
|
115
|
-
|
116
|
-
|
130
|
+
# This allows plugin authors to easily skip metrics with no results
|
131
|
+
return [] if data.nil?
|
132
|
+
|
133
|
+
keys_data = data.map { |item| item.keys }.flatten.map(&:to_s)
|
134
|
+
keys_schema = plugin.schema.map { |item| item[:name] }
|
117
135
|
|
118
136
|
disallowed = (keys_data - keys_schema)
|
119
137
|
|
@@ -125,16 +143,16 @@ class Dropsonde::Metrics
|
|
125
143
|
def sanity_check_schema(plugin)
|
126
144
|
schema = plugin.schema
|
127
145
|
|
128
|
-
if schema.class != Array
|
146
|
+
if (schema.class != Array) || schema.find { |item| item.class != Hash }
|
129
147
|
raise "The #{plugin.name} plugin schema is not an array of hashes"
|
130
148
|
end
|
131
149
|
|
132
150
|
error = ''
|
133
151
|
[:name, :type, :description].each do |field|
|
134
|
-
count = schema.reject {|item| item[field] }.count
|
135
|
-
next if count
|
152
|
+
count = schema.reject { |item| item[field] }.count
|
153
|
+
next if count.zero?
|
136
154
|
|
137
|
-
error
|
155
|
+
error += "The #{plugin.name} plugin schema has #{count} missing #{field}s\n"
|
138
156
|
end
|
139
157
|
raise error unless error.empty?
|
140
158
|
|
@@ -142,8 +160,8 @@ class Dropsonde::Metrics
|
|
142
160
|
end
|
143
161
|
|
144
162
|
def check_for_duplicates(schema)
|
145
|
-
keys = schema.map {|col| col[:name] }
|
146
|
-
dupes = keys.select{ |e| keys.count(e) > 1 }.uniq
|
163
|
+
keys = schema.map { |col| col[:name] }
|
164
|
+
dupes = keys.select { |e| keys.count(e) > 1 }.uniq
|
147
165
|
|
148
166
|
raise "The schema defines duplicate keys: #{dupes}" unless dupes.empty?
|
149
167
|
end
|
@@ -152,61 +170,55 @@ class Dropsonde::Metrics
|
|
152
170
|
[
|
153
171
|
{
|
154
172
|
"description": "An ID that's unique for each checkin to Dujour.",
|
155
|
-
"mode":
|
156
|
-
"name":
|
157
|
-
"type":
|
173
|
+
"mode": 'NULLABLE',
|
174
|
+
"name": 'message_id',
|
175
|
+
"type": 'STRING',
|
158
176
|
},
|
159
177
|
{
|
160
|
-
"description":
|
161
|
-
"mode":
|
162
|
-
"name":
|
163
|
-
"type":
|
178
|
+
"description": 'A unique identifier for a site, derived as a hash of the CA certificate and optional seed.',
|
179
|
+
"mode": 'NULLABLE',
|
180
|
+
"name": 'site_id',
|
181
|
+
"type": 'BYTES',
|
164
182
|
},
|
165
183
|
{
|
166
|
-
"description":
|
167
|
-
"mode":
|
168
|
-
"name":
|
169
|
-
"type":
|
184
|
+
"description": 'The name of the product.',
|
185
|
+
"mode": 'NULLABLE',
|
186
|
+
"name": 'product',
|
187
|
+
"type": 'STRING',
|
170
188
|
},
|
171
189
|
{
|
172
|
-
"description":
|
173
|
-
"mode":
|
174
|
-
"name":
|
175
|
-
"type":
|
190
|
+
"description": 'Version of the project.',
|
191
|
+
"mode": 'NULLABLE',
|
192
|
+
"name": 'version',
|
193
|
+
"type": 'STRING',
|
176
194
|
},
|
177
195
|
{
|
178
|
-
"description":
|
179
|
-
"mode":
|
180
|
-
"name":
|
181
|
-
"type":
|
196
|
+
"description": 'Time the checkin to Dujour occurred.',
|
197
|
+
"mode": 'NULLABLE',
|
198
|
+
"name": 'timestamp',
|
199
|
+
"type": 'TIMESTAMP',
|
182
200
|
},
|
183
201
|
{
|
184
|
-
"description":
|
185
|
-
"mode":
|
186
|
-
"name":
|
187
|
-
"type":
|
188
|
-
}
|
202
|
+
"description": 'IP Address of node checking in to Dujour.',
|
203
|
+
"mode": 'NULLABLE',
|
204
|
+
"name": 'ip',
|
205
|
+
"type": 'STRING',
|
206
|
+
},
|
189
207
|
]
|
190
208
|
end
|
191
209
|
|
192
210
|
def skeleton_report
|
193
211
|
{
|
194
|
-
"product":
|
195
|
-
"version":
|
212
|
+
"product": 'popularity-module',
|
213
|
+
"version": '1.0.0',
|
196
214
|
"site_id": siteid,
|
197
215
|
"self-service-analytics": {
|
198
|
-
"snapshots": {
|
199
|
-
}
|
216
|
+
"snapshots": {},
|
217
|
+
},
|
200
218
|
}
|
201
219
|
end
|
202
220
|
|
203
221
|
def generate_guid
|
204
|
-
|
205
|
-
(0..8).to_a.map{|a| rand(16).to_s(16)}.join,
|
206
|
-
(0..4).to_a.map{|a| rand(16).to_s(16)}.join,
|
207
|
-
(0..4).to_a.map{|a| rand(16).to_s(16)}.join,
|
208
|
-
(0..4).to_a.map{|a| rand(16).to_s(16)}.join,
|
209
|
-
(0..12).to_a.map{|a| rand(16).to_s(16)}.join
|
210
|
-
]
|
222
|
+
SecureRandom.uuid
|
211
223
|
end
|
212
224
|
end
|
@@ -1,17 +1,18 @@
|
|
1
|
-
|
2
|
-
class Module
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
# puppet module class
|
4
|
+
class Puppet::Module
|
5
|
+
unless Module.method_defined? :"forge_module?"
|
6
|
+
def forge_module?
|
7
|
+
Dropsonde::Cache.forge_module? self
|
8
8
|
end
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
unless Module.method_defined? :forge_slug
|
12
|
+
def forge_slug
|
13
|
+
forge_name.tr('/', '-')
|
14
|
+
rescue StandardError
|
15
|
+
nil
|
14
16
|
end
|
15
|
-
|
16
17
|
end
|
17
18
|
end
|
data/lib/dropsonde/version.rb
CHANGED
data/lib/dropsonde.rb
CHANGED
@@ -1,26 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'json'
|
2
4
|
require 'httpclient'
|
3
5
|
require 'puppetdb'
|
4
6
|
require 'inifile'
|
5
7
|
require 'puppet'
|
6
8
|
|
9
|
+
# This class handles caching module process, generate reports,
|
10
|
+
# fetchs all plugins defined in lib/dropsonde/metrics and also
|
11
|
+
# handle connection and request to PuppetDB.
|
7
12
|
class Dropsonde
|
8
13
|
require 'dropsonde/cache'
|
9
14
|
require 'dropsonde/metrics'
|
10
15
|
require 'dropsonde/monkeypatches'
|
11
16
|
require 'dropsonde/version'
|
12
17
|
|
13
|
-
|
18
|
+
def self.puppet_settings_overrides
|
19
|
+
overrides = []
|
20
|
+
if (confdir = ENV['PUPPET_CONFDIR'])
|
21
|
+
overrides << '--confdir'
|
22
|
+
overrides << confdir
|
23
|
+
end
|
24
|
+
|
25
|
+
if (codedir = ENV['PUPPET_CODEDIR'])
|
26
|
+
overrides << '--codedir'
|
27
|
+
overrides << codedir
|
28
|
+
end
|
29
|
+
|
30
|
+
if (vardir = ENV['PUPPET_VARDIR'])
|
31
|
+
overrides << '--vardir'
|
32
|
+
overrides << vardir
|
33
|
+
end
|
34
|
+
|
35
|
+
if (logdir = ENV['PUPPET_LOGDIR'])
|
36
|
+
overrides << '--logdir'
|
37
|
+
overrides << logdir
|
38
|
+
end
|
14
39
|
|
15
|
-
|
16
|
-
|
40
|
+
overrides
|
41
|
+
end
|
42
|
+
|
43
|
+
Puppet.initialize_settings(puppet_settings_overrides)
|
44
|
+
|
45
|
+
@pdbclient = nil
|
46
|
+
@settings = {}
|
17
47
|
def self.settings=(arg)
|
18
48
|
raise "Requires a Hash to set all settings at once, not a #{arg.class}" unless arg.is_a? Hash
|
19
|
-
|
49
|
+
|
50
|
+
@settings = arg
|
20
51
|
end
|
21
52
|
|
22
|
-
|
23
|
-
|
53
|
+
class << self
|
54
|
+
attr_reader :settings
|
24
55
|
end
|
25
56
|
|
26
57
|
def self.generate_schema
|
@@ -32,24 +63,32 @@ class Dropsonde
|
|
32
63
|
puts Dropsonde::Metrics.new.list
|
33
64
|
end
|
34
65
|
|
35
|
-
def self.generate_report(format)
|
66
|
+
def self.generate_report(format, puppetdb_session = nil)
|
36
67
|
case format
|
37
68
|
when 'json'
|
38
|
-
puts JSON.pretty_generate(Dropsonde::Metrics.new.report)
|
69
|
+
puts JSON.pretty_generate(Dropsonde::Metrics.new.report(puppetdb_session))
|
39
70
|
when 'human'
|
40
71
|
puts
|
41
|
-
puts Dropsonde::Metrics.new.preview
|
72
|
+
puts Dropsonde::Metrics.new.preview(puppetdb_session)
|
42
73
|
else
|
43
|
-
raise
|
74
|
+
raise 'unknown format'
|
44
75
|
end
|
45
76
|
end
|
46
77
|
|
47
78
|
def self.submit_report(endpoint, port)
|
48
|
-
client = HTTPClient.new
|
79
|
+
client = HTTPClient.new
|
80
|
+
|
81
|
+
# The httpclient gem ships with some expired CA certificates.
|
82
|
+
# This causes us to load the certs shipped with whatever
|
83
|
+
# Ruby is used to execute this gem's commands, which are generally
|
84
|
+
# more up-to-date, especially if using puppet-agent's Ruby.
|
85
|
+
#
|
86
|
+
# Note that this is no-op with Windows system Ruby.
|
87
|
+
client.ssl_config.set_default_paths
|
88
|
+
|
49
89
|
result = client.post("#{endpoint}:#{port}",
|
50
|
-
|
51
|
-
|
52
|
-
)
|
90
|
+
header: { 'Content-Type' => 'application/json' },
|
91
|
+
body: Dropsonde::Metrics.new.report.to_json)
|
53
92
|
|
54
93
|
if result.status == 200
|
55
94
|
data = JSON.parse(result.body)
|
@@ -69,15 +108,15 @@ class Dropsonde
|
|
69
108
|
def self.generate_example(size, filename)
|
70
109
|
metrics = Dropsonde::Metrics.new
|
71
110
|
File.open(filename, 'w') do |file|
|
72
|
-
|
111
|
+
(0...size).each do |_i|
|
73
112
|
file.write(metrics.example.to_json)
|
74
113
|
file.write("\n")
|
75
114
|
end
|
76
115
|
end
|
77
116
|
end
|
78
117
|
|
79
|
-
def
|
80
|
-
return
|
118
|
+
def puppet_db
|
119
|
+
return @pdbclient if @pdbclient
|
81
120
|
|
82
121
|
config = File.join(Puppet.settings[:confdir], 'puppetdb.conf')
|
83
122
|
|
@@ -85,14 +124,13 @@ class Dropsonde
|
|
85
124
|
|
86
125
|
server = IniFile.load(config)['main']['server_urls'].split(',').first
|
87
126
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
127
|
+
@pdbclient = PuppetDB::Client.new({
|
128
|
+
server: server,
|
129
|
+
pem: {
|
130
|
+
'key' => Puppet.settings[:hostprivkey],
|
131
|
+
'cert' => Puppet.settings[:hostcert],
|
132
|
+
'ca_file' => Puppet.settings[:localcacert],
|
133
|
+
},
|
134
|
+
})
|
96
135
|
end
|
97
|
-
|
98
136
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dropsonde
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Ford
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-02-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -146,6 +146,7 @@ executables:
|
|
146
146
|
extensions: []
|
147
147
|
extra_rdoc_files: []
|
148
148
|
files:
|
149
|
+
- CHANGELOG.md
|
149
150
|
- LICENSE
|
150
151
|
- README.md
|
151
152
|
- bin/dropsonde
|
@@ -153,15 +154,17 @@ files:
|
|
153
154
|
- lib/dropsonde/cache.rb
|
154
155
|
- lib/dropsonde/metrics.rb
|
155
156
|
- lib/dropsonde/metrics/dependencies.rb
|
157
|
+
- lib/dropsonde/metrics/environments.rb
|
156
158
|
- lib/dropsonde/metrics/modules.rb
|
159
|
+
- lib/dropsonde/metrics/platforms.rb
|
157
160
|
- lib/dropsonde/metrics/puppetfiles.rb
|
158
161
|
- lib/dropsonde/monkeypatches.rb
|
159
162
|
- lib/dropsonde/version.rb
|
160
163
|
homepage: https://github.com/puppetlabs/dropsonde
|
161
164
|
licenses:
|
162
|
-
- Apache
|
165
|
+
- Apache-2.0
|
163
166
|
metadata: {}
|
164
|
-
post_install_message:
|
167
|
+
post_install_message:
|
165
168
|
rdoc_options: []
|
166
169
|
require_paths:
|
167
170
|
- lib
|
@@ -176,8 +179,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
176
179
|
- !ruby/object:Gem::Version
|
177
180
|
version: '0'
|
178
181
|
requirements: []
|
179
|
-
rubygems_version: 3.
|
180
|
-
signing_key:
|
182
|
+
rubygems_version: 3.1.4
|
183
|
+
signing_key:
|
181
184
|
specification_version: 4
|
182
185
|
summary: A simple telemetry probe for gathering usage information about Puppet infrastructures.
|
183
186
|
test_files: []
|