dropsonde 0.0.5 → 0.0.6

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,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # platforms plugin
1
4
  class Dropsonde::Metrics::Platforms
2
5
  def self.initialize_platforms
3
6
  # require any libraries needed here -- no need to load puppet; it's already initialized
@@ -5,11 +8,11 @@ class Dropsonde::Metrics::Platforms
5
8
  end
6
9
 
7
10
  def self.description
8
- <<~EOF
11
+ <<~DESCRIPTION
9
12
  This group of metrics generates usage patterns by platform.
10
13
  Currently implemented is a list of classes, the platforms
11
14
  they are declared on, and a count of each combination.
12
- EOF
15
+ DESCRIPTION
13
16
  end
14
17
 
15
18
  def self.schema
@@ -19,29 +22,29 @@ class Dropsonde::Metrics::Platforms
19
22
  {
20
23
  "fields": [
21
24
  {
22
- "description": "The class name name",
23
- "mode": "NULLABLE",
24
- "name": "name",
25
- "type": "STRING"
25
+ "description": 'The class name name',
26
+ "mode": 'NULLABLE',
27
+ "name": 'name',
28
+ "type": 'STRING',
26
29
  },
27
30
  {
28
- "description": "The osfamily of the node the class is declared on",
29
- "mode": "NULLABLE",
30
- "name": "platform",
31
- "type": "STRING"
31
+ "description": 'The osfamily of the node the class is declared on',
32
+ "mode": 'NULLABLE',
33
+ "name": 'platform',
34
+ "type": 'STRING',
32
35
  },
33
36
  {
34
- "description": "The number of time this combination is declared",
35
- "mode": "NULLABLE",
36
- "name": "count",
37
- "type": "INTEGER"
37
+ "description": 'The number of time this combination is declared',
38
+ "mode": 'NULLABLE',
39
+ "name": 'count',
40
+ "type": 'INTEGER',
38
41
  },
39
42
  ],
40
43
  "description": "List of all classes in the infrastructure and platforms they're declared on.",
41
- "mode": "REPEATED",
42
- "name": "class_platforms",
43
- "type": "RECORD"
44
- }
44
+ "mode": 'REPEATED',
45
+ "name": 'class_platforms',
46
+ "type": 'RECORD',
47
+ },
45
48
  ]
46
49
  end
47
50
 
@@ -49,44 +52,43 @@ class Dropsonde::Metrics::Platforms
49
52
  # run just before generating this metric
50
53
  end
51
54
 
52
- def self.run
55
+ def self.run(puppetdb_session = nil)
53
56
  # skip this metric if we don't have an active PuppetDB connection
54
- return unless Dropsonde.puppetDB
57
+ return unless puppetdb_session
55
58
 
56
- classes = Dropsonde.puppetDB.request( '', 'resources[certname, title] { type = "Class" }').data
57
- facts = Dropsonde.puppetDB.request( '', 'facts[certname, value] { name = "osfamily" }').data
59
+ classes = puppetdb_session.puppet_db.request('', 'resources[certname, title] { type = "Class" }').data
60
+ facts = puppetdb_session.puppet_db.request('', 'facts[certname, value] { name = "osfamily" }').data
58
61
 
59
62
  # All public Forge modules that are installed.
60
- modules = Puppet.lookup(:environments).list.map {|env|
61
- env.modules.select {|mod|
62
- mod.forge_module?
63
- }.map {|fmod|
64
- fmod.name
65
- }}.flatten.uniq
66
-
67
- data = classes.map {|item|
68
- # filter out any that don't come from public Forge modules
69
- mod = item['title'].split('::').first.downcase
70
- next unless modules.include? mod
71
-
72
- item['platform'] = facts.find {|fact|
73
- fact['certname'] == item['certname']
74
- }['value']
63
+ modules = Puppet.lookup(:environments).list.map { |env|
64
+ env.modules.select { |mod| mod.forge_module? }.map do |fmod|
65
+ fmod.name
66
+ end
67
+ }.flatten.uniq
75
68
 
76
- {
77
- :name => item['title'],
78
- :platform => item['platform'],
79
- }
69
+ data = classes.map { |item|
70
+ # filter out any that don't come from public Forge modules
71
+ mod = item['title'].split('::').first.downcase
72
+ next unless modules.include? mod
73
+
74
+ item['platform'] = facts.find { |fact|
75
+ fact['certname'] == item['certname']
76
+ }['value']
77
+
78
+ {
79
+ name: item['title'],
80
+ platform: item['platform'],
81
+ }
80
82
  }.compact
81
83
 
82
- data.each {|item|
83
- item['count'] = data.select {|i|
84
- i[:name] == item[:name] and i[:platform] == item[:platform]
85
- }.count
86
- }
84
+ data.each do |item|
85
+ item[:count] = data.select { |i|
86
+ i[:name] == item[:name] and i[:platform] == item[:platform]
87
+ }.count
88
+ end
87
89
 
88
90
  [
89
- :class_platforms => data,
91
+ class_platforms: data,
90
92
  ]
91
93
  end
92
94
 
@@ -95,25 +97,26 @@ class Dropsonde::Metrics::Platforms
95
97
  # make it easier to write data aggregation queries without access to the
96
98
  # actual private data that users have submitted.
97
99
 
98
- platforms = ['RedHat', 'Debian', 'Windows', 'Suse', 'FreeBSD', 'Darwin', 'Archlinux', 'AIX']
100
+ platforms = %w[RedHat Debian Windows Suse FreeBSD Darwin Archlinux AIX]
99
101
  classes = ['', '::Config', '::Service', '::Server', '::Client', '::Packages']
100
102
 
101
- data = Dropsonde::Cache.modules
102
- .sample(rand(35))
103
- .map do |item|
104
- name = item.split('-').last.capitalize + classes.sample
103
+ dropsonde_cache = Dropsonde::Cache.new('foo', 7, true)
104
+ data = dropsonde_cache.modules
105
+ .sample(rand(35))
106
+ .map { |item|
107
+ name = item.split('-').last.capitalize + classes.sample
105
108
 
106
- rand(5).times.map do
107
- {
108
- :name => name,
109
- :platform => platforms.sample,
110
- :count => rand(1000),
111
- }
112
- end
113
- end.flatten
109
+ rand(5).times.map do
110
+ {
111
+ name: name,
112
+ platform: platforms.sample,
113
+ count: rand(1000),
114
+ }
115
+ end
116
+ }.flatten
114
117
 
115
118
  [
116
- :class_platforms => data.uniq,
119
+ class_platforms: data.uniq,
117
120
  ]
118
121
  end
119
122
 
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # puppetfiles plugin
1
4
  class Dropsonde::Metrics::Puppetfiles
2
5
  def self.initialize_puppetfiles
3
6
  # require any libraries needed here -- no need to load puppet; it's already initialized
@@ -6,10 +9,10 @@ class Dropsonde::Metrics::Puppetfiles
6
9
  end
7
10
 
8
11
  def self.description
9
- <<~EOF
12
+ <<~DESCRIPTION
10
13
  This generates interesting stats about Puppetfiles used in your environments,
11
14
  including whether your Puppetfiles have Ruby code in them.
12
- EOF
15
+ DESCRIPTION
13
16
  end
14
17
 
15
18
  def self.schema
@@ -19,23 +22,23 @@ class Dropsonde::Metrics::Puppetfiles
19
22
  {
20
23
  "fields": [
21
24
  {
22
- "description": "The method name",
23
- "mode": "NULLABLE",
24
- "name": "name",
25
- "type": "STRING"
25
+ "description": 'The method name',
26
+ "mode": 'NULLABLE',
27
+ "name": 'name',
28
+ "type": 'STRING',
26
29
  },
27
30
  {
28
- "description": "How many times is it used",
29
- "mode": "NULLABLE",
30
- "name": "count",
31
- "type": "INTEGER"
32
- }
31
+ "description": 'How many times is it used',
32
+ "mode": 'NULLABLE',
33
+ "name": 'count',
34
+ "type": 'INTEGER',
35
+ },
33
36
  ],
34
- "description": "Ruby methods used in Puppetfiles.",
35
- "mode": "REPEATED",
36
- "name": "puppetfile_ruby_methods",
37
- "type": "RECORD"
38
- }
37
+ "description": 'Ruby methods used in Puppetfiles.',
38
+ "mode": 'REPEATED',
39
+ "name": 'puppetfile_ruby_methods',
40
+ "type": 'RECORD',
41
+ },
39
42
  ]
40
43
  end
41
44
 
@@ -43,30 +46,30 @@ class Dropsonde::Metrics::Puppetfiles
43
46
  # run just before generating this metric
44
47
  end
45
48
 
46
- def self.run
47
- methods = Dir.entries(Puppet.settings[:environmentpath]).map do |entry|
49
+ def self.run(_puppetdb_session = nil)
50
+ methods = Dir.entries(Puppet.settings[:environmentpath]).map { |entry|
48
51
  puppetfile = File.join(Puppet.settings[:environmentpath], entry, 'Puppetfile')
49
52
 
50
53
  next if entry.start_with? '.'
51
54
  next unless File.file? puppetfile
52
55
 
53
56
  tokens = Ripper.sexp(File.read(puppetfile)).flatten
54
- indices = tokens.map.with_index {|a, i| a == :command ? i : nil}.compact
57
+ indices = tokens.map.with_index { |a, i| a == :command ? i : nil }.compact
55
58
 
56
- indices.map {|i| tokens[i+2] }
57
- end.flatten.compact
59
+ indices.map { |i| tokens[i + 2] }
60
+ }.flatten.compact
58
61
 
59
- methods.reject! {|name| ['mod', 'forge', 'moduledir'].include? name }
62
+ methods.reject! { |name| %w[mod forge moduledir].include? name }
60
63
 
61
64
  methods = methods.uniq.map do |name|
62
65
  {
63
- :name => name,
64
- :count => methods.count(name),
66
+ name: name,
67
+ count: methods.count(name),
65
68
  }
66
69
  end
67
70
 
68
71
  [
69
- { :puppetfile_ruby_methods => methods },
72
+ { puppetfile_ruby_methods: methods },
70
73
  ]
71
74
  end
72
75
 
@@ -75,13 +78,13 @@ class Dropsonde::Metrics::Puppetfiles
75
78
  # make it easier to write data aggregation queries without access to the
76
79
  # actual private data that users have submitted.
77
80
  [
78
- :puppetfile_ruby_methods => [
79
- {:name => 'require', :count => rand(200)},
80
- {:name => 'each', :count => rand(200)},
81
- {:name => 'puts', :count => rand(200)},
82
- {:name => 'select', :count => rand(200)},
83
- {:name => 'reject', :count => rand(200)},
84
- {:name => 'read', :count => rand(200)},
81
+ puppetfile_ruby_methods: [
82
+ { name: 'require', count: rand(200) },
83
+ { name: 'each', count: rand(200) },
84
+ { name: 'puts', count: rand(200) },
85
+ { name: 'select', count: rand(200) },
86
+ { name: 'reject', count: rand(200) },
87
+ { name: 'read', count: rand(200) },
85
88
  ].shuffle,
86
89
  ]
87
90
  end
@@ -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.6'
3
5
  end