dropsonde 0.0.3 → 0.0.7

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