Skip to content

Commit b3ae955

Browse files
Merge branch 'main' into main
2 parents 086f655 + 5226fec commit b3ae955

File tree

5 files changed

+91
-58
lines changed

5 files changed

+91
-58
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ dbs:
9494
9595
This is the default for Amazon S3. The full range of possible replica types (e.g. other S3-compatible object storage servers) are covered in Litestream's [replica guides](https://litestream.io/guides/#replica-guides).
9696
97-
The gem also provides a default initializer file at `config/initializers/litestream.rb` that allows you to configure these four environment variables referenced in the configuration file in Ruby. By providing a Ruby interface to these environment variables, you can use any method of storing secrets that you prefer. For example, the default generated file uses Rails' encrypted credentials to store your secrets:
97+
The gem also provides a default initializer file at `config/initializers/litestream.rb` that allows you to configure these three environment variables referenced in the configuration file in Ruby. By providing a Ruby interface to these environment variables, you can use any method of storing secrets that you prefer. For example, the default generated file uses Rails' encrypted credentials to store your secrets:
9898

9999
```ruby
100100
Rails.application.configure do
Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
11
module Litestream
22
class ApplicationController < ActionController::Base
33
protect_from_forgery with: :exception
4-
around_action :force_english_locale!
54

65
if Litestream.password
76
http_basic_authenticate_with(
87
name: Litestream.username,
98
password: Litestream.password
109
)
1110
end
12-
13-
private
14-
15-
def force_english_locale!(&action)
16-
I18n.with_locale(:en, &action)
17-
end
1811
end
1912
end

lib/litestream.rb

Lines changed: 72 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ def initialize
3333
end
3434
end
3535

36-
mattr_writer :username, :password, :queue, :replica_bucket, :replica_region, :replica_endpoint, :replica_key_id, :replica_access_key, :systemctl_command
36+
mattr_writer :username, :password, :queue, :replica_bucket, :replica_region, :replica_endpoint, :replica_key_id, :replica_access_key, :systemctl_command,
37+
:config_path
3738

3839
class << self
3940
def verify!(database_path)
@@ -97,55 +98,12 @@ def systemctl_command
9798
@@systemctl_command || "systemctl status litestream"
9899
end
99100

101+
def config_path
102+
@@config_path || Rails.root.join("config", "litestream.yml")
103+
end
104+
100105
def replicate_process
101-
info = {}
102-
if !`which systemctl`.empty?
103-
systemctl_status = `#{Litestream.systemctl_command}`.chomp
104-
# ["● litestream.service - Litestream",
105-
# " Loaded: loaded (/lib/systemd/system/litestream.service; enabled; vendor preset: enabled)",
106-
# " Active: active (running) since Tue 2023-07-25 13:49:43 UTC; 8 months 24 days ago",
107-
# " Main PID: 1179656 (litestream)",
108-
# " Tasks: 9 (limit: 1115)",
109-
# " Memory: 22.9M",
110-
# " CPU: 10h 49.843s",
111-
# " CGroup: /system.slice/litestream.service",
112-
# " └─1179656 /usr/bin/litestream replicate",
113-
# "",
114-
# "Warning: some journal files were not opened due to insufficient permissions."]
115-
systemctl_status.split("\n").each do |line|
116-
line.strip!
117-
if line.start_with?("Main PID:")
118-
_key, value = line.split(":")
119-
pid, _name = value.strip.split(" ")
120-
info[:pid] = pid
121-
elsif line.start_with?("Active:")
122-
value, _ago = line.split(";")
123-
status, timestamp = value.split(" since ")
124-
info[:started] = DateTime.strptime(timestamp.strip, "%a %Y-%m-%d %H:%M:%S %Z")
125-
status_match = status.match(%r{\((?<status>.*)\)})
126-
info[:status] = status_match ? status_match[:status] : nil
127-
end
128-
end
129-
else
130-
litestream_replicate_ps = `ps -ax | grep litestream | grep replicate`.chomp
131-
litestream_replicate_ps.split("\n").each do |line|
132-
next unless line.include?("litestream replicate")
133-
pid, * = line.split(" ")
134-
info[:pid] = pid
135-
state, _, lstart = `ps -o "state,lstart" #{pid}`.chomp.split("\n").last.partition(/\s+/)
136-
137-
info[:status] = case state[0]
138-
when "I" then "idle"
139-
when "R" then "running"
140-
when "S" then "sleeping"
141-
when "T" then "stopped"
142-
when "U" then "uninterruptible"
143-
when "Z" then "zombie"
144-
end
145-
info[:started] = DateTime.strptime(lstart.strip, "%a %b %d %H:%M:%S %Y")
146-
end
147-
end
148-
info
106+
systemctl_info || process_info || {}
149107
end
150108

151109
def databases
@@ -165,6 +123,71 @@ def databases
165123
end
166124
end
167125
end
126+
127+
private
128+
129+
def systemctl_info
130+
return if `which systemctl`.empty?
131+
132+
systemctl_output = `#{Litestream.systemctl_command}`
133+
systemctl_exit_code = $?.exitstatus
134+
return unless systemctl_exit_code.zero?
135+
136+
# ["● litestream.service - Litestream",
137+
# " Loaded: loaded (/lib/systemd/system/litestream.service; enabled; vendor preset: enabled)",
138+
# " Active: active (running) since Tue 2023-07-25 13:49:43 UTC; 8 months 24 days ago",
139+
# " Main PID: 1179656 (litestream)",
140+
# " Tasks: 9 (limit: 1115)",
141+
# " Memory: 22.9M",
142+
# " CPU: 10h 49.843s",
143+
# " CGroup: /system.slice/litestream.service",
144+
# " └─1179656 /usr/bin/litestream replicate",
145+
# "",
146+
# "Warning: some journal files were not opened due to insufficient permissions."]
147+
148+
info = {}
149+
systemctl_output.chomp.split("\n").each do |line|
150+
line.strip!
151+
if line.start_with?("Main PID:")
152+
_key, value = line.split(":")
153+
pid, _name = value.strip.split(" ")
154+
info[:pid] = pid
155+
elsif line.start_with?("Active:")
156+
value, _ago = line.split(";")
157+
status, timestamp = value.split(" since ")
158+
info[:started] = DateTime.strptime(timestamp.strip, "%a %Y-%m-%d %H:%M:%S %Z")
159+
status_match = status.match(%r{\((?<status>.*)\)})
160+
info[:status] = status_match ? status_match[:status] : nil
161+
end
162+
end
163+
info
164+
end
165+
166+
def process_info
167+
litestream_replicate_ps = `ps -ax | grep litestream | grep replicate`
168+
exit_code = $?.exitstatus
169+
return unless exit_code.zero?
170+
171+
info = {}
172+
litestream_replicate_ps.chomp.split("\n").each do |line|
173+
next unless line.include?("litestream replicate")
174+
175+
pid, * = line.split(" ")
176+
info[:pid] = pid
177+
state, _, lstart = `ps -o "state,lstart" #{pid}`.chomp.split("\n").last.partition(/\s+/)
178+
179+
info[:status] = case state[0]
180+
when "I" then "idle"
181+
when "R" then "running"
182+
when "S" then "sleeping"
183+
when "T" then "stopped"
184+
when "U" then "uninterruptible"
185+
when "Z" then "zombie"
186+
end
187+
info[:started] = DateTime.strptime(lstart.strip, "%a %b %d %H:%M:%S %Y")
188+
end
189+
info
190+
end
168191
end
169192
end
170193

lib/litestream/commands.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ def prepare(command, argv = {}, database = nil)
131131
ENV["LITESTREAM_SECRET_ACCESS_KEY"] ||= Litestream.replica_access_key
132132

133133
args = {
134-
"--config" => Rails.root.join("config", "litestream.yml").to_s
134+
"--config" => Litestream.config_path.to_s
135135
}.merge(argv.stringify_keys).to_a.flatten.compact
136136
cmd = [executable, command, *args, database].compact
137137
puts cmd.inspect if ENV["DEBUG"]

test/litestream/test_commands.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ def teardown
1515
Litestream.replica_bucket = ENV["LITESTREAM_REPLICA_BUCKET"] = nil
1616
Litestream.replica_key_id = ENV["LITESTREAM_ACCESS_KEY_ID"] = nil
1717
Litestream.replica_access_key = ENV["LITESTREAM_SECRET_ACCESS_KEY"] = nil
18+
Litestream.config_path = nil
1819
end
1920

2021
class TestReplicateCommand < TestCommands
@@ -422,6 +423,22 @@ def test_databases_does_not_set_env_var_from_config_when_env_vars_already_set
422423
assert_equal "original_key", ENV["LITESTREAM_ACCESS_KEY_ID"]
423424
assert_equal "original_access", ENV["LITESTREAM_SECRET_ACCESS_KEY"]
424425
end
426+
427+
def test_databases_read_from_custom_configured_litestream_config_path
428+
Litestream.config_path = "dummy/config/litestream/production.yml"
429+
430+
stub = proc do |cmd, _async|
431+
_executable, _command, *argv = cmd
432+
433+
assert_equal 2, argv.size
434+
assert_equal "--config", argv[0]
435+
assert_match Regexp.new("dummy/config/litestream/production.yml"), argv[1]
436+
end
437+
438+
Litestream::Commands.stub :run, stub do
439+
Litestream::Commands.databases
440+
end
441+
end
425442
end
426443

427444
class TestGenerationsCommand < TestCommands

0 commit comments

Comments
 (0)