dropsonde 0.0.5 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.