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.
@@ -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( :path => 'dropsonde/metrics', :module => Dropsonde::Metrics)
8
+ extend LittlePlugger(path: 'dropsonde/metrics', module: Dropsonde::Metrics)
5
9
 
6
10
  def initialize
7
- Dropsonde::Metrics.disregard_plugins(*Dropsonde.settings[:blacklist])
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
- sha2 = Digest::SHA512.new
15
- sha2.update Puppet.settings[:certname]
16
- sha2.update Puppet.settings[:cacert]
17
- sha2.update Dropsonde.settings[:seed] if Dropsonde.settings[:seed]
18
- @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
+
19
34
  @siteid
20
35
  end
21
36
 
22
37
  def list
23
- str = " Loaded telemetry plugins\n"
24
- str << " ===============================\n\n"
38
+ str = " Loaded telemetry plugins\n"
39
+ str += " ===============================\n\n"
25
40
  Dropsonde::Metrics.plugins.each do |name, plugin|
26
- str << name.to_s
27
- str << "\n--------\n"
28
- str << plugin.description.strip
29
- str << "\n\n"
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[:blacklist]
32
- str << "Disabled plugins:\n"
33
- str << " #{Dropsonde.settings[:blacklist].join(', ')}"
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 |name, plugin|
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 = " Puppet Telemetry Report Preview\n"
49
- str << " ===============================\n\n"
50
- 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|
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 << plugin.name+"\n"
58
- str << "-------------------------------\n"
59
- str << plugin.description
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.first
77
+ values = row.values.flatten
63
78
 
64
- desc = schema.find {|item| item[:name].to_sym == key.to_sym}[:description]
65
- str << "- #{key}: #{desc}\n"
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 << " #{item}\n"
82
+ str += " #{item}\n"
68
83
  end
69
84
  end
70
- str << "\n\n"
85
+ str += "\n\n"
71
86
  end
72
- str << "Site ID:\n"
73
- str << siteid
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 |name, plugin|
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' => row.values.first,
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 |name, plugin|
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
- keys_data = data.map {|item| item.keys }.flatten.map(&:to_s)
116
- keys_schema = plugin.schema.map {|item| item[:name] }
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 or schema.find {|item| item.class != Hash}
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 == 0
152
+ count = schema.reject { |item| item[field] }.count
153
+ next if count.zero?
136
154
 
137
- 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"
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": "NULLABLE",
156
- "name": "message_id",
157
- "type": "STRING"
173
+ "mode": 'NULLABLE',
174
+ "name": 'message_id',
175
+ "type": 'STRING',
158
176
  },
159
177
  {
160
- "description": "A unique identifier for a site, derived as a hash of the CA certificate and optional seed.",
161
- "mode": "NULLABLE",
162
- "name": "site_id",
163
- "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',
164
182
  },
165
183
  {
166
- "description": "The name of the product.",
167
- "mode": "NULLABLE",
168
- "name": "product",
169
- "type": "STRING"
184
+ "description": 'The name of the product.',
185
+ "mode": 'NULLABLE',
186
+ "name": 'product',
187
+ "type": 'STRING',
170
188
  },
171
189
  {
172
- "description": "Version of the project.",
173
- "mode": "NULLABLE",
174
- "name": "version",
175
- "type": "STRING"
190
+ "description": 'Version of the project.',
191
+ "mode": 'NULLABLE',
192
+ "name": 'version',
193
+ "type": 'STRING',
176
194
  },
177
195
  {
178
- "description": "Time the checkin to Dujour occurred.",
179
- "mode": "NULLABLE",
180
- "name": "timestamp",
181
- "type": "TIMESTAMP"
196
+ "description": 'Time the checkin to Dujour occurred.',
197
+ "mode": 'NULLABLE',
198
+ "name": 'timestamp',
199
+ "type": 'TIMESTAMP',
182
200
  },
183
201
  {
184
- "description": "IP Address of node checking in to Dujour.",
185
- "mode": "NULLABLE",
186
- "name": "ip",
187
- "type": "STRING"
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": "popularity-module",
195
- "version": "1.0.0",
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
- "%s-%s-%s-%s-%s" % [
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
- 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.3'
4
+ VERSION = '0.0.7'
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.3
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: 2020-05-24 00:00:00.000000000 Z
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 2
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.0.6
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: []