detector 0.3.0 → 0.4.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9180708d27a005b8af76c7451d69354f3c63084c671a87adbad2957627098445
4
- data.tar.gz: 83011b8a32cbac053af086fc2d6a029daa69fc78e796075aad4d0dbd7c21b6cf
3
+ metadata.gz: c2fdcd9559b7c9d9d40b8908d4ec47ef17ff63d62305832bbe7f69b10b05a35b
4
+ data.tar.gz: 0560305f80f5d1f5aea6eb5959ef7ebb3cc225479492a69594bf227d618804f1
5
5
  SHA512:
6
- metadata.gz: b1f95d6eb75df123a8704f96b08b7ec8fa4433d556c9d0a334d25adc4e81ce4e40f2dc1ad410f63a0bbb5e9a99d75c3fd33c8d4d6add23514d8879f142c3ab59
7
- data.tar.gz: 18b9fa63739174bdf3a3301f8ceb2618b693829668fa97adc4cdac43014f68d4f1fc11840fea86118edc967bfa362e0c464b7ee8833e3d9228073f558de05043
6
+ metadata.gz: 82be9fdd64b14e11e3ff0ff0d927b2508129eb0a84d5a5a4340c7afd991273ddd83f114f6ffdfb1d2add0e84a9526ba8ccd727887ecf70d694f4fb8cc2a0e053
7
+ data.tar.gz: 53d7ee213ff018c23a7df00df47d8a3cf8525bb475a9eafb4415ee8ba9ffc4db3c2c22dbc48711f06fa2a390ef1f92a3fbf215451a2460022d34e3f23174bf79
data/bin/detector CHANGED
@@ -23,6 +23,10 @@ puts "Detected: #{detector.kind}"
23
23
  puts "Version: #{detector.version}"
24
24
  puts "Host: #{detector.host}:#{detector.port}"
25
25
 
26
+ if detector.respond_to?(:replication_available?) && !detector.replication_available?.nil?
27
+ puts "Replication: #{detector.replication_available? ? 'Available' : 'Not available'}"
28
+ end
29
+
26
30
  if detector.user_access_level
27
31
  puts "User access level: #{detector.user_access_level}"
28
32
  end
@@ -54,9 +58,13 @@ if detector.databases?
54
58
  puts "\nDatabase: #{db_name} (#{db[:size]})"
55
59
 
56
60
  if detector.tables?
57
- tables = detector.tables(db_name).first(3)
58
- puts " Tables: #{detector.table_count(db_name)}"
61
+ if db[:table_count]
62
+ puts " Tables: #{db[:table_count]}"
63
+ else
64
+ puts " Tables: #{detector.table_count(db_name)}"
65
+ end
59
66
 
67
+ tables = detector.tables(db_name).first(3)
60
68
  tables.each do |table|
61
69
  puts " - #{table[:name]}: #{table[:row_count]} rows (#{table[:size]})"
62
70
  end
@@ -31,7 +31,8 @@ module Detector
31
31
  db_list.each do |db_name|
32
32
  size_query = "SELECT
33
33
  IFNULL(FORMAT(SUM(data_length + index_length) / 1024 / 1024, 2), '0.00') AS size_mb,
34
- IFNULL(SUM(data_length + index_length), 0) AS raw_size
34
+ IFNULL(SUM(data_length + index_length), 0) AS raw_size,
35
+ COUNT(table_name) AS table_count
35
36
  FROM information_schema.TABLES
36
37
  WHERE table_schema = '#{db_name}'"
37
38
 
@@ -39,7 +40,8 @@ module Detector
39
40
  result << {
40
41
  name: db_name,
41
42
  size: "#{size_data['size_mb']} MB",
42
- raw_size: size_data['raw_size'].to_i
43
+ raw_size: size_data['raw_size'].to_i,
44
+ table_count: size_data['table_count'].to_i
43
45
  }
44
46
  end
45
47
 
@@ -44,15 +44,22 @@ module Detector
44
44
 
45
45
  def databases
46
46
  return [] unless connection
47
- @databases ||= connection.query("SELECT schema_name AS name,
47
+ @databases ||= connection.query("SELECT
48
+ schema_name AS name,
48
49
  FORMAT(SUM(data_length + index_length) / 1024 / 1024, 2) AS size_mb,
49
- SUM(data_length + index_length) AS raw_size
50
+ SUM(data_length + index_length) AS raw_size,
51
+ COUNT(table_name) AS table_count
50
52
  FROM information_schema.SCHEMATA
51
- JOIN information_schema.TABLES ON table_schema = schema_name
53
+ LEFT JOIN information_schema.TABLES ON table_schema = schema_name
52
54
  WHERE schema_name NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
53
55
  GROUP BY schema_name
54
56
  ORDER BY raw_size DESC").map do |row|
55
- { name: row['name'], size: "#{row['size_mb']} MB", raw_size: row['raw_size'].to_i }
57
+ {
58
+ name: row['name'],
59
+ size: "#{row['size_mb']} MB",
60
+ raw_size: row['raw_size'].to_i,
61
+ table_count: row['table_count'].to_i
62
+ }
56
63
  end
57
64
  end
58
65
 
@@ -154,6 +161,32 @@ module Detector
154
161
  "Limited access"
155
162
  end
156
163
  end
164
+
165
+ def replication_available?
166
+ return nil unless connection
167
+
168
+ begin
169
+ # Check master status
170
+ master_result = connection.query("SHOW MASTER STATUS")
171
+ return true if master_result.count > 0
172
+
173
+ # Check if this is a slave
174
+ slave_result = connection.query("SHOW SLAVE STATUS")
175
+ return true if slave_result.count > 0
176
+
177
+ # Check if replication user exists or if binary logging is enabled
178
+ repl_users = connection.query("SELECT user FROM mysql.user WHERE Repl_slave_priv = 'Y'")
179
+ return true if repl_users.count > 0
180
+
181
+ # Check if binary logging is enabled (needed for replication)
182
+ binary_log = connection.query("SHOW VARIABLES LIKE 'log_bin'").first
183
+ return true if binary_log && binary_log['Value'] && binary_log['Value'].downcase == 'on'
184
+
185
+ false
186
+ rescue => e
187
+ nil
188
+ end
189
+ end
157
190
  end
158
191
  end
159
192
 
@@ -92,13 +92,48 @@ module Detector
92
92
 
93
93
  def databases
94
94
  return [] unless connection
95
- @databases ||= connection.exec("SELECT datname, pg_size_pretty(pg_database_size(datname)) as size,
96
- pg_database_size(datname) as raw_size
97
- FROM pg_database
98
- WHERE datistemplate = false
99
- ORDER BY raw_size DESC").map do |row|
100
- { name: row['datname'], size: row['size'], raw_size: row['raw_size'].to_i }
95
+ result = []
96
+
97
+ # Get the list of databases and their sizes
98
+ db_list = connection.exec("SELECT datname, pg_size_pretty(pg_database_size(datname)) as size,
99
+ pg_database_size(datname) as raw_size
100
+ FROM pg_database
101
+ WHERE datistemplate = false
102
+ ORDER BY raw_size DESC")
103
+
104
+ # For each database, get table count
105
+ db_list.each do |row|
106
+ db_name = row['datname']
107
+
108
+ # Skip system databases or databases we can't connect to
109
+ next if ['postgres', 'template0', 'template1'].include?(db_name)
110
+
111
+ # Get table count for this database
112
+ table_count = 0
113
+
114
+ begin
115
+ # Create a temporary connection to count tables
116
+ temp_conn = PG::Connection.new(host: host, port: port, user: uri.user,
117
+ password: uri.password, dbname: db_name) rescue nil
118
+
119
+ if temp_conn
120
+ table_count = temp_conn.exec("SELECT count(*) FROM information_schema.tables WHERE table_schema = 'public'").first['count'].to_i
121
+ temp_conn.close
122
+ end
123
+ rescue
124
+ # Skip if we can't connect
125
+ next
126
+ end
127
+
128
+ result << {
129
+ name: db_name,
130
+ size: row['size'],
131
+ raw_size: row['raw_size'].to_i,
132
+ table_count: table_count
133
+ }
101
134
  end
135
+
136
+ @databases = result
102
137
  end
103
138
 
104
139
  def connection_count
@@ -158,6 +193,17 @@ module Detector
158
193
  end
159
194
  end
160
195
  end
196
+
197
+ def replication_available?
198
+ return nil unless connection
199
+
200
+ begin
201
+ replication_roles = connection.exec("SELECT rolname, rolreplication FROM pg_roles WHERE rolreplication = true;")
202
+ !replication_roles.values.empty?
203
+ rescue => e
204
+ nil
205
+ end
206
+ end
161
207
  end
162
208
  end
163
209
 
@@ -151,6 +151,26 @@ module Detector
151
151
  end
152
152
  end
153
153
  end
154
+
155
+ def replication_available?
156
+ return nil unless connection && info
157
+
158
+ begin
159
+ # Check if this is a master in a replication setup
160
+ if info['role'] == 'master'
161
+ return true
162
+ end
163
+
164
+ # Check if server has replication enabled
165
+ if info['connected_slaves'].to_i > 0 || info['slave_read_only'] == '0'
166
+ return true
167
+ end
168
+
169
+ false
170
+ rescue => e
171
+ nil
172
+ end
173
+ end
154
174
  end
155
175
  end
156
176
 
data/lib/detector/base.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require 'socket'
2
2
  require 'geocoder'
3
+ require_relative 'region'
4
+ require_relative 'vendor'
3
5
 
4
6
  module Detector
5
7
  class Base
@@ -108,201 +110,7 @@ module Detector
108
110
 
109
111
  def region
110
112
  return nil unless valid?
111
-
112
- # Try to determine region from hostname first
113
- hostname = host.to_s.downcase
114
-
115
- # AWS regions from hostname
116
- if hostname =~ /amazonaws\.com/ || hostname =~ /aws/
117
- return "us-east-1" if hostname =~ /us-east-1|virginia|nova/
118
- return "us-east-2" if hostname =~ /us-east-2|ohio/
119
- return "us-west-1" if hostname =~ /us-west-1|california|norcal/
120
- return "us-west-2" if hostname =~ /us-west-2|oregon/
121
- return "af-south-1" if hostname =~ /af-south|cape-town/
122
- return "ap-east-1" if hostname =~ /ap-east|hong-kong/
123
- return "ap-south-1" if hostname =~ /ap-south|mumbai/
124
- return "ap-northeast-1" if hostname =~ /ap-northeast-1|tokyo/
125
- return "ap-northeast-2" if hostname =~ /ap-northeast-2|seoul/
126
- return "ap-northeast-3" if hostname =~ /ap-northeast-3|osaka/
127
- return "ap-southeast-1" if hostname =~ /ap-southeast-1|singapore/
128
- return "ap-southeast-2" if hostname =~ /ap-southeast-2|sydney/
129
- return "ca-central-1" if hostname =~ /ca-central|canada|montreal/
130
- return "eu-central-1" if hostname =~ /eu-central-1|frankfurt/
131
- return "eu-west-1" if hostname =~ /eu-west-1|ireland|dublin/
132
- return "eu-west-2" if hostname =~ /eu-west-2|london/
133
- return "eu-west-3" if hostname =~ /eu-west-3|paris/
134
- return "eu-north-1" if hostname =~ /eu-north-1|stockholm/
135
- return "eu-south-1" if hostname =~ /eu-south-1|milan/
136
- return "me-south-1" if hostname =~ /me-south-1|bahrain/
137
- return "sa-east-1" if hostname =~ /sa-east-1|sao-paulo/
138
- end
139
-
140
- # Azure regions from hostname
141
- if hostname =~ /azure|windows\.net|cloudapp/
142
- return "eastus" if hostname =~ /eastus|virginia/
143
- return "eastus2" if hostname =~ /eastus2/
144
- return "centralus" if hostname =~ /centralus|iowa/
145
- return "northcentralus" if hostname =~ /northcentralus|illinois/
146
- return "southcentralus" if hostname =~ /southcentralus|texas/
147
- return "westus" if hostname =~ /westus|california/
148
- return "westus2" if hostname =~ /westus2|washington/
149
- return "westus3" if hostname =~ /westus3|phoenix/
150
- return "australiaeast" if hostname =~ /australiaeast|sydney/
151
- return "brazilsouth" if hostname =~ /brazilsouth|sao-paulo/
152
- return "canadacentral" if hostname =~ /canadacentral|toronto/
153
- return "centralindia" if hostname =~ /centralindia|pune/
154
- return "eastasia" if hostname =~ /eastasia|hong-kong/
155
- return "francecentral" if hostname =~ /francecentral|paris/
156
- return "germanywestcentral" if hostname =~ /germanywestcentral|frankfurt/
157
- return "japaneast" if hostname =~ /japaneast|tokyo/
158
- return "koreacentral" if hostname =~ /koreacentral|seoul/
159
- return "northeurope" if hostname =~ /northeurope|ireland/
160
- return "southeastasia" if hostname =~ /southeastasia|singapore/
161
- return "southindia" if hostname =~ /southindia|chennai/
162
- return "swedencentral" if hostname =~ /swedencentral|stockholm/
163
- return "switzerlandnorth" if hostname =~ /switzerlandnorth|zurich/
164
- return "uksouth" if hostname =~ /uksouth|london/
165
- return "westeurope" if hostname =~ /westeurope|netherlands/
166
- end
167
-
168
- # Google Cloud regions from hostname
169
- if hostname =~ /google|googlecloud|gcp|appspot/
170
- return "us-central1" if hostname =~ /us-central1|iowa/
171
- return "us-east1" if hostname =~ /us-east1|south-carolina/
172
- return "us-east4" if hostname =~ /us-east4|virginia/
173
- return "us-west1" if hostname =~ /us-west1|oregon/
174
- return "us-west2" if hostname =~ /us-west2|los-angeles/
175
- return "us-west3" if hostname =~ /us-west3|salt-lake-city/
176
- return "us-west4" if hostname =~ /us-west4|las-vegas/
177
- return "northamerica-northeast1" if hostname =~ /northamerica-northeast1|montreal/
178
- return "southamerica-east1" if hostname =~ /southamerica-east1|sao-paulo/
179
- return "europe-west1" if hostname =~ /europe-west1|belgium/
180
- return "europe-west2" if hostname =~ /europe-west2|london/
181
- return "europe-west3" if hostname =~ /europe-west3|frankfurt/
182
- return "europe-west4" if hostname =~ /europe-west4|netherlands/
183
- return "europe-west6" if hostname =~ /europe-west6|zurich/
184
- return "europe-north1" if hostname =~ /europe-north1|finland/
185
- return "asia-east1" if hostname =~ /asia-east1|taiwan/
186
- return "asia-east2" if hostname =~ /asia-east2|hong-kong/
187
- return "asia-northeast1" if hostname =~ /asia-northeast1|tokyo/
188
- return "asia-northeast2" if hostname =~ /asia-northeast2|osaka/
189
- return "asia-northeast3" if hostname =~ /asia-northeast3|seoul/
190
- return "asia-south1" if hostname =~ /asia-south1|mumbai/
191
- return "asia-southeast1" if hostname =~ /asia-southeast1|singapore/
192
- return "asia-southeast2" if hostname =~ /asia-southeast2|jakarta/
193
- return "australia-southeast1" if hostname =~ /australia-southeast1|sydney/
194
- end
195
-
196
- # Fallback to IP-based lookup via Geocoder
197
- return nil unless geo
198
-
199
- # City-based detection for common cloud cities
200
- city = geo&.data&.dig('city')&.downcase
201
- if city
202
- case city
203
- when 'ashburn', 'sterling', 'herndon', 'chantilly'
204
- return "us-east-1" # AWS us-east-1 or equivalent
205
- when 'columbus', 'dublin', 'hilliard'
206
- return "us-east-2" # AWS us-east-2
207
- when 'san jose', 'santa clara', 'milpitas', 'fremont'
208
- return "us-west-1" # AWS us-west-1
209
- when 'portland', 'hillsboro', 'prineville', 'the dalles'
210
- return "us-west-2" # AWS us-west-2 / GCP us-west1
211
- when 'phoenix', 'tempe', 'mesa'
212
- return "westus3" # Azure westus3
213
- when 'dallas', 'fort worth', 'san antonio'
214
- return "southcentralus" # Azure southcentralus
215
- when 'montreal', 'beauharnois', 'quebec'
216
- return "ca-central-1" # AWS ca-central-1
217
- when 'toronto'
218
- return "canadacentral" # Azure canadacentral
219
- when 'frankfurt', 'munich'
220
- return "eu-central-1" # AWS eu-central-1
221
- when 'london'
222
- return "eu-west-2" # AWS eu-west-2
223
- when 'paris'
224
- return "eu-west-3" # AWS eu-west-3
225
- when 'dublin', 'clondalkin'
226
- return "eu-west-1" # AWS eu-west-1
227
- when 'stockholm'
228
- return "eu-north-1" # AWS eu-north-1
229
- when 'milan'
230
- return "eu-south-1" # AWS eu-south-1
231
- when 'sydney', 'melbourne'
232
- return "ap-southeast-2" # AWS ap-southeast-2
233
- when 'singapore'
234
- return "ap-southeast-1" # AWS ap-southeast-1
235
- when 'tokyo', 'osaka'
236
- return "ap-northeast-1" # AWS ap-northeast-1
237
- when 'seoul'
238
- return "ap-northeast-2" # AWS ap-northeast-2
239
- when 'mumbai'
240
- return "ap-south-1" # AWS ap-south-1
241
- when 'hong kong'
242
- return "ap-east-1" # AWS ap-east-1
243
- when 'são paulo', 'sao paulo'
244
- return "sa-east-1" # AWS sa-east-1
245
- end
246
- end
247
-
248
- # Region/State-based mapping to approximate cloud region
249
- region_name = geo&.data&.dig('region')
250
- country = geo&.data&.dig('country')
251
-
252
- if country == 'United States'
253
- case region_name
254
- when 'Virginia', 'Maryland', 'District of Columbia'
255
- return "us-east-1"
256
- when 'Ohio', 'Indiana', 'Michigan'
257
- return "us-east-2"
258
- when 'California'
259
- return "us-west-1"
260
- when 'Oregon', 'Washington', 'Idaho'
261
- return "us-west-2"
262
- when 'Nevada', 'Utah', 'Arizona'
263
- return "us-west-2"
264
- when 'Texas', 'Oklahoma', 'Louisiana'
265
- return "southcentralus"
266
- when 'Illinois', 'Iowa', 'Minnesota', 'Missouri', 'Wisconsin'
267
- return "us-central1"
268
- end
269
- elsif country == 'Canada'
270
- case region_name
271
- when 'Quebec'
272
- return "ca-central-1"
273
- when 'Ontario'
274
- return "canadacentral"
275
- end
276
- elsif country == 'Brazil'
277
- return "sa-east-1"
278
- elsif country == 'Ireland'
279
- return "eu-west-1"
280
- elsif country == 'United Kingdom'
281
- return "eu-west-2"
282
- elsif country == 'France'
283
- return "eu-west-3"
284
- elsif country == 'Germany'
285
- return "eu-central-1"
286
- elsif country == 'Sweden' || country == 'Norway' || country == 'Finland'
287
- return "eu-north-1"
288
- elsif country == 'Italy'
289
- return "eu-south-1"
290
- elsif country == 'India'
291
- return "ap-south-1"
292
- elsif country == 'Singapore'
293
- return "ap-southeast-1"
294
- elsif country == 'Australia'
295
- return "ap-southeast-2"
296
- elsif country == 'Japan'
297
- return "ap-northeast-1"
298
- elsif country == 'South Korea'
299
- return "ap-northeast-2"
300
- elsif country == 'Hong Kong'
301
- return "ap-east-1"
302
- end
303
-
304
- # Final fallback
305
- region_name || geo&.data&.dig('country_code')&.downcase
113
+ Region.detect_region(host, geo)
306
114
  end
307
115
 
308
116
  def asn
@@ -357,7 +165,16 @@ module Detector
357
165
  end
358
166
 
359
167
  def table_count
360
- nil
168
+ return nil unless valid? && tables? && connection?
169
+
170
+ count = 0
171
+ database_list = databases
172
+
173
+ database_list.each do |db|
174
+ count += tables(db).size
175
+ end
176
+
177
+ count.zero? ? nil : count
361
178
  end
362
179
 
363
180
  def database_count
@@ -392,78 +209,15 @@ module Detector
392
209
  def infrastructure
393
210
  return nil unless valid?
394
211
 
395
- hostname = host.to_s.downcase
396
- case hostname
397
- when /amazon/, /aws/, /amazonaws/, /ec2/, /s3/, /dynamodb/, /rds\./, /elasticbeanstalk/
398
- "Amazon Web Services"
399
- when /google/, /googlecloud/, /appspot/, /gcp/, /compute\./, /cloud\.g/
400
- "Google Cloud Platform"
401
- when /azure/, /azurewebsites/, /cloudapp\./, /windows\.net/
402
- "Microsoft Azure"
403
- when /antimony/
404
- "Build.io"
405
- when /heroku/, /herokuapp/
406
- "Heroku"
407
- when /digitalocean/, /droplet/
408
- "DigitalOcean"
409
- when /linode/, /linodeobjects/
410
- "Linode"
411
- when /vultr/
412
- "Vultr"
413
- when /netlify/
414
- "Netlify"
415
- when /vercel/, /zeit\.co/, /now\.sh/
416
- "Vercel"
417
- when /github\.io/, /githubusercontent/, /github\.dev/
418
- "GitHub"
419
- when /gitlab\.io/, /gitlab-static/
420
- "GitLab"
421
- when /oracle/, /oraclecloud/
422
- "Oracle Cloud"
423
- when /ibm/, /bluemix/, /ibmcloud/
424
- "IBM Cloud"
425
- when /cloudflare/, /workers\.dev/
426
- "Cloudflare"
427
- when /fastly/
428
- "Fastly"
429
- when /akamai/
430
- "Akamai"
431
- when /render\.com/
432
- "Render"
433
- when /fly\.io/
434
- "Fly.io"
435
- when /railway\.app/
436
- "Railway"
437
- when /upcloud/
438
- "UpCloud"
439
- when /hetzner/
440
- "Hetzner"
441
- when /ovh/, /ovhcloud/
442
- "OVH"
443
- when /scaleway/
444
- "Scaleway"
445
- when /contabo/
446
- "Contabo"
447
- when /dreamhost/
448
- "DreamHost"
449
- when /hostgator/
450
- "HostGator"
451
- when /bluehost/
452
- "Bluehost"
453
- when /siteground/
454
- "SiteGround"
455
- when /namecheap/
456
- "Namecheap"
457
- when /godaddy/
458
- "GoDaddy"
459
- when /ionos/
460
- "IONOS"
461
- when /hostinger/
462
- "Hostinger"
463
- else
464
- # If geo data available, return organization, otherwise nil
465
- geo&.data&.dig('org')
466
- end
212
+ provider = Vendor.detect_provider(host)
213
+ return provider if provider
214
+
215
+ # If geo data available, return organization, otherwise nil
216
+ geo&.data&.dig('org')
217
+ end
218
+
219
+ def replication_available?
220
+ nil
467
221
  end
468
222
  end
469
223
  end
@@ -0,0 +1,240 @@
1
+ module Detector
2
+ class Region
3
+ class << self
4
+ def detect_region(host, geo)
5
+ return nil unless host || geo
6
+
7
+ hostname = host.to_s.downcase
8
+
9
+ # Try to determine region from hostname first
10
+ aws_region = detect_aws_region(hostname)
11
+ return aws_region if aws_region
12
+
13
+ azure_region = detect_azure_region(hostname)
14
+ return azure_region if azure_region
15
+
16
+ gcp_region = detect_gcp_region(hostname)
17
+ return gcp_region if gcp_region
18
+
19
+ # Fallbacks to geocoder data
20
+ return nil unless geo
21
+
22
+ # Try city-based detection
23
+ city_region = detect_region_by_city(geo&.data&.dig('city')&.downcase)
24
+ return city_region if city_region
25
+
26
+ # Try region/country based detection
27
+ geo_region = detect_region_by_geography(geo&.data&.dig('region'), geo&.data&.dig('country'))
28
+ return geo_region if geo_region
29
+
30
+ # Final fallback
31
+ geo&.data&.dig('region') || geo&.data&.dig('country_code')&.downcase
32
+ end
33
+
34
+ private
35
+
36
+ def detect_aws_region(hostname)
37
+ return nil unless hostname =~ /amazonaws\.com/ || hostname =~ /aws/
38
+
39
+ return "us-east-1" if hostname =~ /us-east-1|virginia|nova/
40
+ return "us-east-2" if hostname =~ /us-east-2|ohio/
41
+ return "us-west-1" if hostname =~ /us-west-1|california|norcal/
42
+ return "us-west-2" if hostname =~ /us-west-2|oregon/
43
+ return "af-south-1" if hostname =~ /af-south|cape-town/
44
+ return "ap-east-1" if hostname =~ /ap-east|hong-kong/
45
+ return "ap-south-1" if hostname =~ /ap-south|mumbai/
46
+ return "ap-northeast-1" if hostname =~ /ap-northeast-1|tokyo/
47
+ return "ap-northeast-2" if hostname =~ /ap-northeast-2|seoul/
48
+ return "ap-northeast-3" if hostname =~ /ap-northeast-3|osaka/
49
+ return "ap-southeast-1" if hostname =~ /ap-southeast-1|singapore/
50
+ return "ap-southeast-2" if hostname =~ /ap-southeast-2|sydney/
51
+ return "ca-central-1" if hostname =~ /ca-central|canada|montreal/
52
+ return "eu-central-1" if hostname =~ /eu-central-1|frankfurt/
53
+ return "eu-west-1" if hostname =~ /eu-west-1|ireland|dublin/
54
+ return "eu-west-2" if hostname =~ /eu-west-2|london/
55
+ return "eu-west-3" if hostname =~ /eu-west-3|paris/
56
+ return "eu-north-1" if hostname =~ /eu-north-1|stockholm/
57
+ return "eu-south-1" if hostname =~ /eu-south-1|milan/
58
+ return "me-south-1" if hostname =~ /me-south-1|bahrain/
59
+ return "sa-east-1" if hostname =~ /sa-east-1|sao-paulo/
60
+
61
+ nil
62
+ end
63
+
64
+ def detect_azure_region(hostname)
65
+ return nil unless hostname =~ /azure|windows\.net|cloudapp/
66
+
67
+ return "eastus" if hostname =~ /eastus|virginia/
68
+ return "eastus2" if hostname =~ /eastus2/
69
+ return "centralus" if hostname =~ /centralus|iowa/
70
+ return "northcentralus" if hostname =~ /northcentralus|illinois/
71
+ return "southcentralus" if hostname =~ /southcentralus|texas/
72
+ return "westus" if hostname =~ /westus|california/
73
+ return "westus2" if hostname =~ /westus2|washington/
74
+ return "westus3" if hostname =~ /westus3|phoenix/
75
+ return "australiaeast" if hostname =~ /australiaeast|sydney/
76
+ return "brazilsouth" if hostname =~ /brazilsouth|sao-paulo/
77
+ return "canadacentral" if hostname =~ /canadacentral|toronto/
78
+ return "centralindia" if hostname =~ /centralindia|pune/
79
+ return "eastasia" if hostname =~ /eastasia|hong-kong/
80
+ return "francecentral" if hostname =~ /francecentral|paris/
81
+ return "germanywestcentral" if hostname =~ /germanywestcentral|frankfurt/
82
+ return "japaneast" if hostname =~ /japaneast|tokyo/
83
+ return "koreacentral" if hostname =~ /koreacentral|seoul/
84
+ return "northeurope" if hostname =~ /northeurope|ireland/
85
+ return "southeastasia" if hostname =~ /southeastasia|singapore/
86
+ return "southindia" if hostname =~ /southindia|chennai/
87
+ return "swedencentral" if hostname =~ /swedencentral|stockholm/
88
+ return "switzerlandnorth" if hostname =~ /switzerlandnorth|zurich/
89
+ return "uksouth" if hostname =~ /uksouth|london/
90
+ return "westeurope" if hostname =~ /westeurope|netherlands/
91
+
92
+ nil
93
+ end
94
+
95
+ def detect_gcp_region(hostname)
96
+ return nil unless hostname =~ /google|googlecloud|gcp|appspot/
97
+
98
+ return "us-central1" if hostname =~ /us-central1|iowa/
99
+ return "us-east1" if hostname =~ /us-east1|south-carolina/
100
+ return "us-east4" if hostname =~ /us-east4|virginia/
101
+ return "us-west1" if hostname =~ /us-west1|oregon/
102
+ return "us-west2" if hostname =~ /us-west2|los-angeles/
103
+ return "us-west3" if hostname =~ /us-west3|salt-lake-city/
104
+ return "us-west4" if hostname =~ /us-west4|las-vegas/
105
+ return "northamerica-northeast1" if hostname =~ /northamerica-northeast1|montreal/
106
+ return "southamerica-east1" if hostname =~ /southamerica-east1|sao-paulo/
107
+ return "europe-west1" if hostname =~ /europe-west1|belgium/
108
+ return "europe-west2" if hostname =~ /europe-west2|london/
109
+ return "europe-west3" if hostname =~ /europe-west3|frankfurt/
110
+ return "europe-west4" if hostname =~ /europe-west4|netherlands/
111
+ return "europe-west6" if hostname =~ /europe-west6|zurich/
112
+ return "europe-north1" if hostname =~ /europe-north1|finland/
113
+ return "asia-east1" if hostname =~ /asia-east1|taiwan/
114
+ return "asia-east2" if hostname =~ /asia-east2|hong-kong/
115
+ return "asia-northeast1" if hostname =~ /asia-northeast1|tokyo/
116
+ return "asia-northeast2" if hostname =~ /asia-northeast2|osaka/
117
+ return "asia-northeast3" if hostname =~ /asia-northeast3|seoul/
118
+ return "asia-south1" if hostname =~ /asia-south1|mumbai/
119
+ return "asia-southeast1" if hostname =~ /asia-southeast1|singapore/
120
+ return "asia-southeast2" if hostname =~ /asia-southeast2|jakarta/
121
+ return "australia-southeast1" if hostname =~ /australia-southeast1|sydney/
122
+
123
+ nil
124
+ end
125
+
126
+ def detect_region_by_city(city)
127
+ return nil unless city
128
+
129
+ case city
130
+ when 'ashburn', 'sterling', 'herndon', 'chantilly'
131
+ "us-east-1" # AWS us-east-1 or equivalent
132
+ when 'columbus', 'dublin', 'hilliard'
133
+ "us-east-2" # AWS us-east-2
134
+ when 'san jose', 'santa clara', 'milpitas', 'fremont'
135
+ "us-west-1" # AWS us-west-1
136
+ when 'portland', 'hillsboro', 'prineville', 'the dalles'
137
+ "us-west-2" # AWS us-west-2 / GCP us-west1
138
+ when 'phoenix', 'tempe', 'mesa'
139
+ "westus3" # Azure westus3
140
+ when 'dallas', 'fort worth', 'san antonio'
141
+ "southcentralus" # Azure southcentralus
142
+ when 'montreal', 'beauharnois', 'quebec'
143
+ "ca-central-1" # AWS ca-central-1
144
+ when 'toronto'
145
+ "canadacentral" # Azure canadacentral
146
+ when 'frankfurt', 'munich'
147
+ "eu-central-1" # AWS eu-central-1
148
+ when 'london'
149
+ "eu-west-2" # AWS eu-west-2
150
+ when 'paris'
151
+ "eu-west-3" # AWS eu-west-3
152
+ when 'dublin', 'clondalkin'
153
+ "eu-west-1" # AWS eu-west-1
154
+ when 'stockholm'
155
+ "eu-north-1" # AWS eu-north-1
156
+ when 'milan'
157
+ "eu-south-1" # AWS eu-south-1
158
+ when 'sydney', 'melbourne'
159
+ "ap-southeast-2" # AWS ap-southeast-2
160
+ when 'singapore'
161
+ "ap-southeast-1" # AWS ap-southeast-1
162
+ when 'tokyo', 'osaka'
163
+ "ap-northeast-1" # AWS ap-northeast-1
164
+ when 'seoul'
165
+ "ap-northeast-2" # AWS ap-northeast-2
166
+ when 'mumbai'
167
+ "ap-south-1" # AWS ap-south-1
168
+ when 'hong kong'
169
+ "ap-east-1" # AWS ap-east-1
170
+ when 'são paulo', 'sao paulo'
171
+ "sa-east-1" # AWS sa-east-1
172
+ else
173
+ nil
174
+ end
175
+ end
176
+
177
+ def detect_region_by_geography(region_name, country)
178
+ return nil unless region_name || country
179
+
180
+ if country == 'United States'
181
+ case region_name
182
+ when 'Virginia', 'Maryland', 'District of Columbia'
183
+ "us-east-1"
184
+ when 'Ohio', 'Indiana', 'Michigan'
185
+ "us-east-2"
186
+ when 'California'
187
+ "us-west-1"
188
+ when 'Oregon', 'Washington', 'Idaho'
189
+ "us-west-2"
190
+ when 'Nevada', 'Utah', 'Arizona'
191
+ "us-west-2"
192
+ when 'Texas', 'Oklahoma', 'Louisiana'
193
+ "southcentralus"
194
+ when 'Illinois', 'Iowa', 'Minnesota', 'Missouri', 'Wisconsin'
195
+ "us-central1"
196
+ else
197
+ nil
198
+ end
199
+ elsif country == 'Canada'
200
+ case region_name
201
+ when 'Quebec'
202
+ "ca-central-1"
203
+ when 'Ontario'
204
+ "canadacentral"
205
+ else
206
+ nil
207
+ end
208
+ elsif country == 'Brazil'
209
+ "sa-east-1"
210
+ elsif country == 'Ireland'
211
+ "eu-west-1"
212
+ elsif country == 'United Kingdom'
213
+ "eu-west-2"
214
+ elsif country == 'France'
215
+ "eu-west-3"
216
+ elsif country == 'Germany'
217
+ "eu-central-1"
218
+ elsif country == 'Sweden' || country == 'Norway' || country == 'Finland'
219
+ "eu-north-1"
220
+ elsif country == 'Italy'
221
+ "eu-south-1"
222
+ elsif country == 'India'
223
+ "ap-south-1"
224
+ elsif country == 'Singapore'
225
+ "ap-southeast-1"
226
+ elsif country == 'Australia'
227
+ "ap-southeast-2"
228
+ elsif country == 'Japan'
229
+ "ap-northeast-1"
230
+ elsif country == 'South Korea'
231
+ "ap-northeast-2"
232
+ elsif country == 'Hong Kong'
233
+ "ap-east-1"
234
+ else
235
+ nil
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end
@@ -0,0 +1,82 @@
1
+ module Detector
2
+ class Vendor
3
+ class << self
4
+ def detect_provider(hostname)
5
+ return nil unless hostname
6
+
7
+ hostname = hostname.to_s.downcase
8
+
9
+ case hostname
10
+ when /amazon/, /aws/, /amazonaws/, /ec2/, /s3/, /dynamodb/, /rds\./, /elasticbeanstalk/
11
+ "Amazon Web Services"
12
+ when /google/, /googlecloud/, /appspot/, /gcp/, /compute\./, /cloud\.g/
13
+ "Google Cloud Platform"
14
+ when /azure/, /azurewebsites/, /cloudapp\./, /windows\.net/
15
+ "Microsoft Azure"
16
+ when /antimony/
17
+ "Build.io"
18
+ when /heroku/, /herokuapp/
19
+ "Heroku"
20
+ when /digitalocean/, /droplet/
21
+ "DigitalOcean"
22
+ when /linode/, /linodeobjects/
23
+ "Linode"
24
+ when /vultr/
25
+ "Vultr"
26
+ when /netlify/
27
+ "Netlify"
28
+ when /vercel/, /zeit\.co/, /now\.sh/
29
+ "Vercel"
30
+ when /github\.io/, /githubusercontent/, /github\.dev/
31
+ "GitHub"
32
+ when /gitlab\.io/, /gitlab-static/
33
+ "GitLab"
34
+ when /oracle/, /oraclecloud/
35
+ "Oracle Cloud"
36
+ when /ibm/, /bluemix/, /ibmcloud/
37
+ "IBM Cloud"
38
+ when /cloudflare/, /workers\.dev/
39
+ "Cloudflare"
40
+ when /fastly/
41
+ "Fastly"
42
+ when /akamai/
43
+ "Akamai"
44
+ when /render\.com/
45
+ "Render"
46
+ when /fly\.io/
47
+ "Fly.io"
48
+ when /railway\.app/
49
+ "Railway"
50
+ when /upcloud/
51
+ "UpCloud"
52
+ when /hetzner/
53
+ "Hetzner"
54
+ when /ovh/, /ovhcloud/
55
+ "OVH"
56
+ when /scaleway/
57
+ "Scaleway"
58
+ when /contabo/
59
+ "Contabo"
60
+ when /dreamhost/
61
+ "DreamHost"
62
+ when /hostgator/
63
+ "HostGator"
64
+ when /bluehost/
65
+ "Bluehost"
66
+ when /siteground/
67
+ "SiteGround"
68
+ when /namecheap/
69
+ "Namecheap"
70
+ when /godaddy/
71
+ "GoDaddy"
72
+ when /ionos/
73
+ "IONOS"
74
+ when /hostinger/
75
+ "Hostinger"
76
+ else
77
+ nil
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -1,3 +1,3 @@
1
1
  module Detector
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: detector
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Siegel
@@ -183,6 +183,8 @@ files:
183
183
  - lib/detector/addons/redis.rb
184
184
  - lib/detector/addons/smtp.rb
185
185
  - lib/detector/base.rb
186
+ - lib/detector/region.rb
187
+ - lib/detector/vendor.rb
186
188
  - lib/detector/version.rb
187
189
  homepage: https://github.com/usiegj00/detector
188
190
  licenses: