boring_services 0.4.0 → 0.6.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: 156bb67ea987370602ed678f3d8a525f6eeae09dcbc2a3ae8ac23fa85b474ca4
4
- data.tar.gz: 8ce1325011cac932711b77afed6a5d0307bebedaa4e52fc2b65d9a153daf2e91
3
+ metadata.gz: a1e8cb457318dbccb953374f554aa4fcb5c1bf72434d952bd5db807ce9bf8909
4
+ data.tar.gz: 85efc2d725d4c42bfceecc6090c79b670d9ed8fe1db06afb6e72626a00030712
5
5
  SHA512:
6
- metadata.gz: 72bf5746276b30243a9b75b8091491afd3e58e5e8feac6b3a8f62bc7cafa8f9088d6d1f279f075b6f3f77d0f350017a4bf277e18a3ef4844d273293fb2f3b363
7
- data.tar.gz: 07ac07fe8b309a06ff23ca77a7681aab03c77d8ecc0fac5e86e6723c999eb05976827e2bafdd072f7dfc0eef700c731329402a627b6ab64d2492983aaf6d125f
6
+ metadata.gz: e41e8e1f47c453e2ef0627f988f087f03fd2a184a56b91f2f8be84e6c34c02ff7c6cc9d0bc8f01803102932e52e5947384c5a6ccf2a19a2d372fa7fa1ef3af80
7
+ data.tar.gz: 155d156c9aafe05ac0e67d3d1a419f77077514c3a1ab7cffdaed81f3e87abef71a139f8b0bba00b7efcdf1411dc4dba41361ac389431f9e80e0d4f1ec80d95af
@@ -11,40 +11,31 @@ module BoringServices
11
11
  # Get all hosts for a service
12
12
  # Returns array of host hashes with :host, :private_ip, :label keys
13
13
  def hosts_for(service_name)
14
- service = config.service_config(service_name.to_s)
15
- return [] unless service
14
+ services = config.services.select { |s| s['name'] == service_name.to_s }
15
+ return [] if services.empty?
16
16
 
17
- normalize_hosts(service['hosts'] || [])
17
+ services.flat_map { |service| normalize_service_hosts(service) }
18
18
  end
19
19
 
20
- # Get the connection IP for a service by region/label
21
- # Prefers private_ip, falls back to host
22
- # Label matching: "redis-eu" matches region "eu", "redis-us" matches "us"
23
- def host_for_region(service_name, region)
24
- return nil if region.to_s.strip.empty?
25
-
20
+ # Get host by exact label match
21
+ def host_by_label(service_name, label)
26
22
  hosts = hosts_for(service_name)
27
- host_entry = hosts.find do |h|
28
- label = h[:label].to_s.downcase
29
- region_str = region.to_s.downcase
30
- label == region_str || label.end_with?("-#{region_str}") || label.start_with?("#{region_str}-")
31
- end
32
-
23
+ host_entry = hosts.find { |h| h[:label] == label.to_s }
33
24
  return nil unless host_entry
34
25
 
35
26
  connection_ip(host_entry)
36
27
  end
37
28
 
38
- # Get the first available host for a service (prefers private_ip)
39
- def primary_host(service_name)
40
- hosts = hosts_for(service_name)
41
- return nil if hosts.empty?
42
-
43
- connection_ip(hosts.first)
29
+ # Get all hosts as a hash keyed by label
30
+ # { "redis-eu-gcp" => "10.8.0.10", "redis-us-aws" => "10.8.0.60" }
31
+ def hosts_by_label(service_name)
32
+ hosts_for(service_name).each_with_object({}) do |h, hash|
33
+ hash[h[:label]] = connection_ip(h) if h[:label]
34
+ end
44
35
  end
45
36
 
46
37
  # Get all connection IPs for a service (prefers private_ip for each)
47
- def all_hosts(service_name)
38
+ def all_ips(service_name)
48
39
  hosts_for(service_name).map { |h| connection_ip(h) }
49
40
  end
50
41
 
@@ -54,9 +45,9 @@ module BoringServices
54
45
  service&.dig('port')
55
46
  end
56
47
 
57
- # Build a Redis URL for a region
58
- def redis_url(region: nil, password: nil, db: 0)
59
- host = region ? host_for_region('redis', region) : primary_host('redis')
48
+ # Build a Redis URL for a specific label
49
+ def redis_url(label: nil, password: nil, db: 0)
50
+ host = label ? host_by_label('redis', label) : all_ips('redis').first
60
51
  return nil unless host
61
52
 
62
53
  port = port_for('redis') || 6379
@@ -65,12 +56,12 @@ module BoringServices
65
56
  end
66
57
 
67
58
  # Build memcached connection string (host:port,host:port format)
68
- def memcached_servers(region: nil)
69
- hosts = if region
70
- host = host_for_region('memcached', region)
59
+ def memcached_servers(label: nil)
60
+ hosts = if label
61
+ host = host_by_label('memcached', label)
71
62
  host ? [host] : []
72
63
  else
73
- all_hosts('memcached')
64
+ all_ips('memcached')
74
65
  end
75
66
 
76
67
  return nil if hosts.empty?
@@ -81,8 +72,20 @@ module BoringServices
81
72
 
82
73
  private
83
74
 
84
- # Normalize hosts array - handles both simple strings and hashes
85
- def normalize_hosts(hosts)
75
+ # Normalize hosts from a service config
76
+ # Handles: single host:, array hosts:, or hosts: as array of hashes
77
+ def normalize_service_hosts(service)
78
+ # Single host entry (production style)
79
+ if service['host']
80
+ return [{
81
+ host: service['host'],
82
+ private_ip: service['private_ip'],
83
+ label: service['label']
84
+ }]
85
+ end
86
+
87
+ # Array of hosts
88
+ hosts = service['hosts'] || []
86
89
  hosts.map do |h|
87
90
  if h.is_a?(Hash)
88
91
  {
@@ -33,7 +33,8 @@ module BoringServices
33
33
  memory = memory_mb || 256
34
34
  listen_port = port || 6379
35
35
  password = resolve_secret('redis_password') if config.secrets['redis_password']
36
- bind_address = private_ip.to_s.strip.empty? ? "0.0.0.0" : "127.0.0.1 #{private_ip}"
36
+ has_private_ip = !private_ip.to_s.strip.empty?
37
+ bind_address = has_private_ip ? "127.0.0.1 #{private_ip}" : "0.0.0.0"
37
38
 
38
39
  config_content = <<~REDIS
39
40
  bind #{bind_address}
@@ -52,10 +53,29 @@ module BoringServices
52
53
  execute :sudo, :chown, 'redis:redis', '/etc/redis/redis.conf'
53
54
  execute :sudo, :chmod, '640', '/etc/redis/redis.conf'
54
55
 
56
+ # If using private IP (WireGuard), ensure Redis starts after WireGuard
57
+ if has_private_ip
58
+ configure_wireguard_dependency
59
+ end
60
+
55
61
  # Set vm.overcommit_memory for Redis background saves
56
62
  execute :sudo, :sysctl, '-w', 'vm.overcommit_memory=1'
57
63
  execute "echo 'vm.overcommit_memory = 1' | sudo tee -a /etc/sysctl.conf > /dev/null || true"
58
64
  end
65
+
66
+ def configure_wireguard_dependency
67
+ override_dir = '/etc/systemd/system/redis-server.service.d'
68
+ override_content = <<~SYSTEMD
69
+ [Unit]
70
+ After=wg-quick@wg0.service
71
+ Wants=wg-quick@wg0.service
72
+ SYSTEMD
73
+
74
+ execute :sudo, :mkdir, '-p', override_dir
75
+ upload! StringIO.new(override_content), '/tmp/wireguard-dependency.conf'
76
+ execute :sudo, :mv, '/tmp/wireguard-dependency.conf', "#{override_dir}/wireguard.conf"
77
+ execute :sudo, :systemctl, 'daemon-reload'
78
+ end
59
79
  end
60
80
  end
61
81
  end
@@ -1,3 +1,3 @@
1
1
  module BoringServices
2
- VERSION = '0.4.0'.freeze
2
+ VERSION = '0.6.0'.freeze
3
3
  end
@@ -39,9 +39,14 @@ module BoringServices
39
39
 
40
40
  # Convenience methods - delegate to locator
41
41
 
42
- # Get Redis host for a region (e.g., "eu", "us")
43
- def redis_host(region = nil)
44
- region ? locator.host_for_region('redis', region) : locator.primary_host('redis')
42
+ # Get all Redis hosts as hash { label => private_ip }
43
+ def redis_hosts
44
+ locator.hosts_by_label('redis')
45
+ end
46
+
47
+ # Get Redis host by exact label
48
+ def redis_host(label)
49
+ locator.host_by_label('redis', label)
45
50
  end
46
51
 
47
52
  # Get Redis port
@@ -49,14 +54,19 @@ module BoringServices
49
54
  locator.port_for('redis') || 6379
50
55
  end
51
56
 
52
- # Build Redis URL
53
- def redis_url(region: nil, password: nil, db: 0)
54
- locator.redis_url(region: region, password: password, db: db)
57
+ # Build Redis URL for a label
58
+ def redis_url(label: nil, password: nil, db: 0)
59
+ locator.redis_url(label: label, password: password, db: db)
60
+ end
61
+
62
+ # Get all Memcached hosts as hash { label => private_ip }
63
+ def memcached_hosts
64
+ locator.hosts_by_label('memcached')
55
65
  end
56
66
 
57
- # Get Memcached host for a region
58
- def memcached_host(region = nil)
59
- region ? locator.host_for_region('memcached', region) : locator.primary_host('memcached')
67
+ # Get Memcached host by exact label
68
+ def memcached_host(label)
69
+ locator.host_by_label('memcached', label)
60
70
  end
61
71
 
62
72
  # Get Memcached port
@@ -65,13 +75,18 @@ module BoringServices
65
75
  end
66
76
 
67
77
  # Get Memcached servers string (host:port,host:port)
68
- def memcached_servers(region: nil)
69
- locator.memcached_servers(region: region)
78
+ def memcached_servers(label: nil)
79
+ locator.memcached_servers(label: label)
80
+ end
81
+
82
+ # Generic: get all hosts for any service as hash { label => ip }
83
+ def hosts_for(service)
84
+ locator.hosts_by_label(service)
70
85
  end
71
86
 
72
- # Generic: get host for any service by region
73
- def host_for(service, region = nil)
74
- region ? locator.host_for_region(service, region) : locator.primary_host(service)
87
+ # Generic: get host by exact label for any service
88
+ def host_for(service, label)
89
+ locator.host_by_label(service, label)
75
90
  end
76
91
 
77
92
  # Generic: get port for any service
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: boring_services
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - BoringCache