potluck 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.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/VERSION +1 -1
- data/lib/potluck/service.rb +85 -76
- data/lib/potluck/version.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6881b14c35b5ae6be793e8390d8ab87d1b8220ea78a2803dac55f5ea8c2bc4cf
|
4
|
+
data.tar.gz: e0c7b0e3a472f03dded30e35e38fbad4f8f484a1d3cb44cd4ced99248cdd298c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ce2edbef44e0f8e27ffb0bb63e717d5f9781f29a27661b72de6bd77b0421f73757a230f5d3193f8e04bbaba8abd9e282d8021af9c4aded66e5e10efd78bb2c7
|
7
|
+
data.tar.gz: 5246bb757a883318ed514c8a5a5a94d5631732170c9622d1b20f92541a419fb36b9b559a3a6967ca700d2ba765ec58a323fed3b39fb464f222a9ca9dfc84e77b
|
data/LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright 2021 Nate Pickens
|
1
|
+
Copyright 2021-2022 Nate Pickens
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
4
4
|
documentation files (the "Software"), to deal in the Software without restriction, including without
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.6
|
data/lib/potluck/service.rb
CHANGED
@@ -24,9 +24,10 @@ module Potluck
|
|
24
24
|
# * +manage+ - True if the service runs locally and should be managed by this process (default: true if
|
25
25
|
# launchctl is available and false otherwise).
|
26
26
|
#
|
27
|
-
def initialize(logger: nil, manage: launchctl?)
|
27
|
+
def initialize(logger: nil, manage: self.class.launchctl?)
|
28
28
|
@logger = logger
|
29
29
|
@manage = !!manage
|
30
|
+
@manage_with_launchctl = false
|
30
31
|
|
31
32
|
if manage.kind_of?(Hash)
|
32
33
|
@status_command = manage[:status]
|
@@ -34,7 +35,8 @@ module Potluck
|
|
34
35
|
@start_command = manage[:start]
|
35
36
|
@stop_command = manage[:stop]
|
36
37
|
elsif manage
|
37
|
-
|
38
|
+
@manage_with_launchctl = true
|
39
|
+
self.class.ensure_launchctl!
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
@@ -46,54 +48,10 @@ module Potluck
|
|
46
48
|
end
|
47
49
|
|
48
50
|
##
|
49
|
-
# Returns true if
|
50
|
-
#
|
51
|
-
def launchctl?
|
52
|
-
defined?(@@launchctl) ? @@launchctl : (@@launchctl = `which launchctl 2>&1` && $? == 0)
|
53
|
-
end
|
54
|
-
|
55
|
-
##
|
56
|
-
# Checks if launchctl is available and raises an error if not.
|
57
|
-
#
|
58
|
-
def ensure_launchctl!
|
59
|
-
launchctl? || raise(ServiceError.new("Cannot manage #{self.pretty_name}: launchctl not found"))
|
60
|
-
end
|
61
|
-
|
62
|
-
##
|
63
|
-
# Command to get the status of the service.
|
64
|
-
#
|
65
|
-
def status_command
|
66
|
-
@status_command || "launchctl list 2>&1 | grep #{SERVICE_PREFIX}#{self.class.service_name}"
|
67
|
-
end
|
68
|
-
|
69
|
-
##
|
70
|
-
# Regular expression to check the output of +#status_command+ against to determine if the service is in
|
71
|
-
# an error state.
|
72
|
-
#
|
73
|
-
def status_error_regex
|
74
|
-
@status_error_regex || LAUNCHCTL_ERROR_REGEX
|
75
|
-
end
|
76
|
-
|
77
|
-
##
|
78
|
-
# Command to start the service.
|
79
|
-
#
|
80
|
-
def start_command
|
81
|
-
@start_command || "launchctl bootstrap gui/#{Process.uid} #{self.class.plist_path}"
|
82
|
-
end
|
83
|
-
|
84
|
-
##
|
85
|
-
# Command to stop the service.
|
86
|
-
#
|
87
|
-
def stop_command
|
88
|
-
@stop_command || "launchctl bootout gui/#{Process.uid}/#{self.class.launchctl_name}"
|
89
|
-
end
|
90
|
-
|
91
|
-
##
|
92
|
-
# Writes the service's launchctl plist file to disk.
|
51
|
+
# Returns true if the service is managed via launchctl.
|
93
52
|
#
|
94
|
-
def
|
95
|
-
|
96
|
-
File.write(self.class.plist_path, self.class.plist)
|
53
|
+
def manage_with_launchctl?
|
54
|
+
@manage_with_launchctl
|
97
55
|
end
|
98
56
|
|
99
57
|
##
|
@@ -123,17 +81,16 @@ module Potluck
|
|
123
81
|
def start
|
124
82
|
return unless manage?
|
125
83
|
|
126
|
-
ensure_plist unless @start_command
|
127
|
-
|
128
84
|
case status
|
129
85
|
when :error then stop
|
130
86
|
when :active then return
|
131
87
|
end
|
132
88
|
|
89
|
+
self.class.write_plist if manage_with_launchctl?
|
133
90
|
run(start_command)
|
134
91
|
wait { status == :inactive }
|
135
92
|
|
136
|
-
raise(ServiceError
|
93
|
+
raise(ServiceError, "Could not start #{self.class.pretty_name}") if status != :active
|
137
94
|
|
138
95
|
log("#{self.class.pretty_name} started")
|
139
96
|
end
|
@@ -144,10 +101,11 @@ module Potluck
|
|
144
101
|
def stop
|
145
102
|
return unless manage? && status != :inactive
|
146
103
|
|
104
|
+
self.class.write_plist if manage_with_launchctl?
|
147
105
|
run(stop_command)
|
148
106
|
wait { status != :inactive }
|
149
107
|
|
150
|
-
raise(ServiceError
|
108
|
+
raise(ServiceError, "Could not stop #{self.class.pretty_name}") if status != :inactive
|
151
109
|
|
152
110
|
log("#{self.class.pretty_name} stopped")
|
153
111
|
end
|
@@ -166,16 +124,16 @@ module Potluck
|
|
166
124
|
# Runs a command with the default shell. Raises an error if the command exits with a non-zero status.
|
167
125
|
#
|
168
126
|
# * +command+ - Command to run.
|
169
|
-
# * +
|
127
|
+
# * +capture_stderr+ - True if stderr should be redirected to stdout; otherwise stderr output will not
|
170
128
|
# be logged (default: true).
|
171
129
|
#
|
172
|
-
def run(command,
|
173
|
-
output = `#{command}#{' 2>&1' if
|
130
|
+
def run(command, capture_stderr: true)
|
131
|
+
output = `#{command}#{' 2>&1' if capture_stderr}`
|
174
132
|
status = $?
|
175
133
|
|
176
134
|
if status != 0
|
177
135
|
output.split("\n").each { |line| log(line, :error) }
|
178
|
-
raise(ServiceError
|
136
|
+
raise(ServiceError, "Command exited with status #{status.exitstatus}: #{command}")
|
179
137
|
else
|
180
138
|
output
|
181
139
|
end
|
@@ -195,24 +153,6 @@ module Potluck
|
|
195
153
|
end
|
196
154
|
end
|
197
155
|
|
198
|
-
private
|
199
|
-
|
200
|
-
##
|
201
|
-
# Calls the supplied block repeatedly until it returns false. Checks frequently at first and gradually
|
202
|
-
# reduces down to one-second intervals.
|
203
|
-
#
|
204
|
-
# * +timeout+ - Maximum number of seconds to wait before timing out (default: 30).
|
205
|
-
# * +block+ - Block to call until it returns false.
|
206
|
-
#
|
207
|
-
def wait(timeout = 30, &block)
|
208
|
-
while block.call && timeout > 0
|
209
|
-
reduce = [[(30 - timeout.to_i) / 5.0, 0.1].max, 1].min
|
210
|
-
timeout -= reduce
|
211
|
-
|
212
|
-
sleep(reduce)
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
156
|
##
|
217
157
|
# Human-friendly name of the service.
|
218
158
|
#
|
@@ -244,7 +184,7 @@ module Potluck
|
|
244
184
|
##
|
245
185
|
# Content of the launchctl plist file.
|
246
186
|
#
|
247
|
-
def self.plist(content)
|
187
|
+
def self.plist(content = '')
|
248
188
|
<<~EOS
|
249
189
|
<?xml version="1.0" encoding="UTF-8"?>
|
250
190
|
#{'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.'\
|
@@ -262,5 +202,74 @@ module Potluck
|
|
262
202
|
</plist>
|
263
203
|
EOS
|
264
204
|
end
|
205
|
+
|
206
|
+
##
|
207
|
+
# Writes the service's launchctl plist file to disk.
|
208
|
+
#
|
209
|
+
def self.write_plist
|
210
|
+
FileUtils.mkdir_p(File.dirname(plist_path))
|
211
|
+
File.write(plist_path, plist)
|
212
|
+
end
|
213
|
+
|
214
|
+
##
|
215
|
+
# Returns true if launchctl is available.
|
216
|
+
#
|
217
|
+
def self.launchctl?
|
218
|
+
defined?(@@launchctl) ? @@launchctl : (@@launchctl = `which launchctl 2>&1` && $? == 0)
|
219
|
+
end
|
220
|
+
|
221
|
+
##
|
222
|
+
# Checks if launchctl is available and raises an error if not.
|
223
|
+
#
|
224
|
+
def self.ensure_launchctl!
|
225
|
+
launchctl? || raise(ServiceError, "Cannot manage #{pretty_name}: launchctl not found")
|
226
|
+
end
|
227
|
+
|
228
|
+
private
|
229
|
+
|
230
|
+
##
|
231
|
+
# Command to get the status of the service.
|
232
|
+
#
|
233
|
+
def status_command
|
234
|
+
@status_command || "launchctl list 2>&1 | grep #{SERVICE_PREFIX}#{self.class.service_name}"
|
235
|
+
end
|
236
|
+
|
237
|
+
##
|
238
|
+
# Regular expression to check the output of +#status_command+ against to determine if the service is in
|
239
|
+
# an error state.
|
240
|
+
#
|
241
|
+
def status_error_regex
|
242
|
+
@status_error_regex || LAUNCHCTL_ERROR_REGEX
|
243
|
+
end
|
244
|
+
|
245
|
+
##
|
246
|
+
# Command to start the service.
|
247
|
+
#
|
248
|
+
def start_command
|
249
|
+
@start_command || "launchctl bootstrap gui/#{Process.uid} #{self.class.plist_path}"
|
250
|
+
end
|
251
|
+
|
252
|
+
##
|
253
|
+
# Command to stop the service.
|
254
|
+
#
|
255
|
+
def stop_command
|
256
|
+
@stop_command || "launchctl bootout gui/#{Process.uid}/#{self.class.launchctl_name}"
|
257
|
+
end
|
258
|
+
|
259
|
+
##
|
260
|
+
# Calls the supplied block repeatedly until it returns false. Checks frequently at first and gradually
|
261
|
+
# reduces down to one-second intervals.
|
262
|
+
#
|
263
|
+
# * +timeout+ - Maximum number of seconds to wait before timing out (default: 30).
|
264
|
+
# * +block+ - Block to call until it returns false.
|
265
|
+
#
|
266
|
+
def wait(timeout = 30, &block)
|
267
|
+
while block.call && timeout > 0
|
268
|
+
reduce = [[(30 - timeout.to_i) / 5.0, 0.1].max, 1].min
|
269
|
+
timeout -= reduce
|
270
|
+
|
271
|
+
sleep(reduce)
|
272
|
+
end
|
273
|
+
end
|
265
274
|
end
|
266
275
|
end
|
data/lib/potluck/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: potluck
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nate Pickens
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -44,7 +44,10 @@ dependencies:
|
|
44
44
|
- - "<"
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: 6.0.0
|
47
|
-
description:
|
47
|
+
description: Potluck provides a simple interface for managing external processes in
|
48
|
+
a way that plays nice with others as well as smoothly handling both development
|
49
|
+
and production environments. Current official gem extensions provide Nginx and Postgres
|
50
|
+
management.
|
48
51
|
email:
|
49
52
|
executables: []
|
50
53
|
extensions: []
|