dropsonde 0.0.5 → 0.0.8

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.
@@ -1,7 +1,11 @@
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( :path => 'dropsonde/metrics', :module => Dropsonde::Metrics)
8
+ extend LittlePlugger(path: 'dropsonde/metrics', module: Dropsonde::Metrics)
5
9
 
6
10
  def initialize
7
11
  if Dropsonde.settings[:enable]
@@ -17,76 +21,81 @@ class Dropsonde::Metrics
17
21
  def siteid
18
22
  return @siteid if @siteid
19
23
 
20
- sha2 = Digest::SHA512.new
21
- sha2.update Puppet.settings[:certname]
22
- sha2.update Puppet.settings[:cacert]
23
- sha2.update Dropsonde.settings[:seed] if Dropsonde.settings[:seed]
24
- @siteid = sha2.hexdigest
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
+
25
34
  @siteid
26
35
  end
27
36
 
28
37
  def list
29
- str = " Loaded telemetry plugins\n"
30
- str << " ===============================\n\n"
38
+ str = " Loaded telemetry plugins\n"
39
+ str += " ===============================\n\n"
31
40
  Dropsonde::Metrics.plugins.each do |name, plugin|
32
- str << name.to_s
33
- str << "\n--------\n"
34
- str << plugin.description.strip
35
- str << "\n\n"
41
+ str += name.to_s
42
+ str += "\n--------\n"
43
+ str += plugin.description.strip
44
+ str += "\n\n"
36
45
  end
37
46
  if Dropsonde.settings[:disable]
38
- str << "Disabled plugins:\n"
39
- str << " #{Dropsonde.settings[:disable].join(', ')}"
47
+ str += "Disabled plugins:\n"
48
+ str += " #{Dropsonde.settings[:disable].join(', ')}"
40
49
  end
41
50
  str
42
51
  end
43
52
 
44
53
  def schema
45
54
  schema = skeleton_schema
46
- Dropsonde::Metrics.plugins.each do |name, plugin|
55
+ Dropsonde::Metrics.plugins.each do |_name, plugin|
47
56
  schema.concat(sanity_check_schema(plugin))
48
57
  end
49
58
  check_for_duplicates(schema)
50
59
  schema
51
60
  end
52
61
 
53
- def preview
54
- str = " Puppet Telemetry Report Preview\n"
55
- str << " ===============================\n\n"
56
- Dropsonde::Metrics.plugins.each do |name, plugin|
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|
57
66
  schema = plugin.schema
58
67
 
59
68
  plugin.setup if plugin.respond_to? :setup
60
- data = sanity_check_data(plugin, plugin.run)
69
+ data = sanity_check_data(plugin, plugin.run(puppetdb_session))
61
70
  plugin.cleanup if plugin.respond_to? :cleanup
62
71
 
63
- str << plugin.name+"\n"
64
- str << "-------------------------------\n"
65
- str << plugin.description
72
+ str += "#{plugin.name}\n"
73
+ str += "-------------------------------\n"
74
+ str += plugin.description
66
75
  data.each do |row|
67
76
  key = row.keys.first
68
77
  values = row.values.flatten
69
78
 
70
- desc = schema.find {|item| item[:name].to_sym == key.to_sym}[:description]
71
- str << "- #{key}: #{desc}\n"
79
+ desc = schema.find { |item| item[:name].to_sym == key.to_sym }[:description]
80
+ str += "- #{key}: #{desc}\n"
72
81
  values.each do |item|
73
- str << " #{item}\n"
82
+ str += " #{item}\n"
74
83
  end
75
84
  end
76
- str << "\n\n"
85
+ str += "\n\n"
77
86
  end
78
- str << "Site ID:\n"
79
- str << siteid
87
+ str += "Site ID:\n"
88
+ str += siteid
80
89
  str
81
90
  end
82
91
 
83
- def report
92
+ def report(puppetdb_session = nil)
84
93
  snapshots = {}
85
- Dropsonde::Metrics.plugins.each do |name, plugin|
94
+ Dropsonde::Metrics.plugins.each do |_name, plugin|
86
95
  plugin.setup
87
- sanity_check_data(plugin, plugin.run).each do |row|
96
+ sanity_check_data(plugin, plugin.run(puppetdb_session)).each do |row|
88
97
  snapshots[row.keys.first] = {
89
- 'value' => row.values.first,
98
+ 'value' => row.values.first,
90
99
  'timestamp' => Time.now.iso8601,
91
100
  }
92
101
  end
@@ -106,7 +115,7 @@ class Dropsonde::Metrics
106
115
  results[:ip] = IPAddr.new(rand(2**32), Socket::AF_INET)
107
116
  results.delete(:'self-service-analytics')
108
117
 
109
- Dropsonde::Metrics.plugins.each do |name, plugin|
118
+ Dropsonde::Metrics.plugins.each do |_name, plugin|
110
119
  sanity_check_data(plugin, plugin.example).each do |row|
111
120
  results.merge!(row)
112
121
  end
@@ -121,8 +130,8 @@ class Dropsonde::Metrics
121
130
  # This allows plugin authors to easily skip metrics with no results
122
131
  return [] if data.nil?
123
132
 
124
- keys_data = data.map {|item| item.keys }.flatten.map(&:to_s)
125
- keys_schema = plugin.schema.map {|item| item[:name] }
133
+ keys_data = data.map { |item| item.keys }.flatten.map(&:to_s)
134
+ keys_schema = plugin.schema.map { |item| item[:name] }
126
135
 
127
136
  disallowed = (keys_data - keys_schema)
128
137
 
@@ -134,16 +143,16 @@ class Dropsonde::Metrics
134
143
  def sanity_check_schema(plugin)
135
144
  schema = plugin.schema
136
145
 
137
- if schema.class != Array or schema.find {|item| item.class != Hash}
146
+ if (schema.class != Array) || schema.find { |item| item.class != Hash }
138
147
  raise "The #{plugin.name} plugin schema is not an array of hashes"
139
148
  end
140
149
 
141
150
  error = ''
142
151
  [:name, :type, :description].each do |field|
143
- count = schema.reject {|item| item[field] }.count
144
- next if count == 0
152
+ count = schema.reject { |item| item[field] }.count
153
+ next if count.zero?
145
154
 
146
- error << "The #{plugin.name} plugin schema has #{count} missing #{field}s\n"
155
+ error += "The #{plugin.name} plugin schema has #{count} missing #{field}s\n"
147
156
  end
148
157
  raise error unless error.empty?
149
158
 
@@ -151,8 +160,8 @@ class Dropsonde::Metrics
151
160
  end
152
161
 
153
162
  def check_for_duplicates(schema)
154
- keys = schema.map {|col| col[:name] }
155
- 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
156
165
 
157
166
  raise "The schema defines duplicate keys: #{dupes}" unless dupes.empty?
158
167
  end
@@ -161,61 +170,55 @@ class Dropsonde::Metrics
161
170
  [
162
171
  {
163
172
  "description": "An ID that's unique for each checkin to Dujour.",
164
- "mode": "NULLABLE",
165
- "name": "message_id",
166
- "type": "STRING"
173
+ "mode": 'NULLABLE',
174
+ "name": 'message_id',
175
+ "type": 'STRING',
167
176
  },
168
177
  {
169
- "description": "A unique identifier for a site, derived as a hash of the CA certificate and optional seed.",
170
- "mode": "NULLABLE",
171
- "name": "site_id",
172
- "type": "BYTES"
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',
173
182
  },
174
183
  {
175
- "description": "The name of the product.",
176
- "mode": "NULLABLE",
177
- "name": "product",
178
- "type": "STRING"
184
+ "description": 'The name of the product.',
185
+ "mode": 'NULLABLE',
186
+ "name": 'product',
187
+ "type": 'STRING',
179
188
  },
180
189
  {
181
- "description": "Version of the project.",
182
- "mode": "NULLABLE",
183
- "name": "version",
184
- "type": "STRING"
190
+ "description": 'Version of the project.',
191
+ "mode": 'NULLABLE',
192
+ "name": 'version',
193
+ "type": 'STRING',
185
194
  },
186
195
  {
187
- "description": "Time the checkin to Dujour occurred.",
188
- "mode": "NULLABLE",
189
- "name": "timestamp",
190
- "type": "TIMESTAMP"
196
+ "description": 'Time the checkin to Dujour occurred.',
197
+ "mode": 'NULLABLE',
198
+ "name": 'timestamp',
199
+ "type": 'TIMESTAMP',
191
200
  },
192
201
  {
193
- "description": "IP Address of node checking in to Dujour.",
194
- "mode": "NULLABLE",
195
- "name": "ip",
196
- "type": "STRING"
197
- }
202
+ "description": 'IP Address of node checking in to Dujour.',
203
+ "mode": 'NULLABLE',
204
+ "name": 'ip',
205
+ "type": 'STRING',
206
+ },
198
207
  ]
199
208
  end
200
209
 
201
210
  def skeleton_report
202
211
  {
203
- "product": "popularity-module",
204
- "version": "1.0.0",
212
+ "product": 'popularity-module',
213
+ "version": '1.0.0',
205
214
  "site_id": siteid,
206
215
  "self-service-analytics": {
207
- "snapshots": { }
208
- }
216
+ "snapshots": {},
217
+ },
209
218
  }
210
219
  end
211
220
 
212
221
  def generate_guid
213
- "%s-%s-%s-%s-%s" % [
214
- (0..8).to_a.map{|a| rand(16).to_s(16)}.join,
215
- (0..4).to_a.map{|a| rand(16).to_s(16)}.join,
216
- (0..4).to_a.map{|a| rand(16).to_s(16)}.join,
217
- (0..4).to_a.map{|a| rand(16).to_s(16)}.join,
218
- (0..12).to_a.map{|a| rand(16).to_s(16)}.join
219
- ]
222
+ SecureRandom.uuid
220
223
  end
221
224
  end
@@ -1,17 +1,18 @@
1
- module Puppet
2
- class Module
1
+ # frozen_string_literal: true
3
2
 
4
- unless Module.method_defined? :"forge_module?"
5
- def forge_module?
6
- Dropsonde::Cache.forgeModule? self
7
- end
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
- unless Module.method_defined? :forge_slug
11
- def forge_slug
12
- self.forge_name.tr('/','-') rescue nil
13
- end
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Dropsonde
2
- VERSION = '0.0.5'
4
+ VERSION = '0.0.8'
3
5
  end
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
- Puppet.initialize_settings
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
- @@pdbclient = nil
16
- @@settings = {}
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
- @@settings = arg
49
+
50
+ @settings = arg
20
51
  end
21
52
 
22
- def self.settings
23
- @@settings
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 "unknown format"
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
- :header => {'Content-Type' => 'application/json'},
51
- :body => Dropsonde::Metrics.new.report.to_json
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
- for i in 0...size
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 self.puppetDB
80
- return @@pdbclient if @@pdbclient
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
- @@pdbclient = PuppetDB::Client.new({
89
- :server => server,
90
- :pem => {
91
- 'key' => Puppet.settings[:hostprivkey],
92
- 'cert' => Puppet.settings[:hostcert],
93
- 'ca_file' => Puppet.settings[:localcacert],
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.5
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Ford
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-11 00:00:00.000000000 Z
11
+ date: 2022-08-29 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
@@ -161,7 +162,7 @@ files:
161
162
  - lib/dropsonde/version.rb
162
163
  homepage: https://github.com/puppetlabs/dropsonde
163
164
  licenses:
164
- - Apache 2
165
+ - Apache-2.0
165
166
  metadata: {}
166
167
  post_install_message:
167
168
  rdoc_options: []
@@ -178,7 +179,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
178
179
  - !ruby/object:Gem::Version
179
180
  version: '0'
180
181
  requirements: []
181
- rubygems_version: 3.0.6
182
+ rubygems_version: 3.1.6
182
183
  signing_key:
183
184
  specification_version: 4
184
185
  summary: A simple telemetry probe for gathering usage information about Puppet infrastructures.