dropsonde 0.0.5 → 0.0.6

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