potluck 0.0.3 → 0.0.4

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: 8be6daeb322e6bd8b0a99cc25d8fb5a2a805b6354c620439c7a22ecdd289e189
4
- data.tar.gz: 852bafb9263287a210c98c26b99e4a3e9358fd490c8b71910ecce2be16b980d7
3
+ metadata.gz: f1c7870515c28013595dbe15f34ba4c2cf3e76fabbbd55c1859066462df9227f
4
+ data.tar.gz: a87627ecfe3232593fd0f7223089a15893ad3e7227aed8a47d48ec32326b0572
5
5
  SHA512:
6
- metadata.gz: 84d60ae064035c6657aa601a622e1f65e38fc915162cbb6287a40b2309d6736c17881f552abbf7daef2c159961a010aed4a61d5cc8111c7d7c4865925c058a81
7
- data.tar.gz: 2659df968b31e9851addaa50369c92c1e143ea118e3837ae493c728ea6050f1f9efb34a350f238cb788d847a3a77632f5777b9f607e3cf00b391effec9c34c3f
6
+ metadata.gz: 6b4cc348d159c69e95de691c0e6f0c159ef94818174f3f45319e76e21b971669e600a1d3fb4040edecc0a05b130c6ab0fcdcd2eb08dfdf3fe5e32936d13d7685
7
+ data.tar.gz: 9e69dd441a0bf951edbccf7d7c590a9697327033e3e88a61801ceaefb3d05ba13734ecba4580f446e1497964a947d99b725a25832d9c0e8efe841a8fdc3414c0
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.3
1
+ 0.0.4
@@ -1,7 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require('fileutils')
4
+
3
5
  module Potluck
4
- class Dish
6
+ ##
7
+ # A Ruby interface for controlling, configuring, and interacting with external processes. Serves as a
8
+ # parent class for service-specific child classes.
9
+ #
10
+ class Service
5
11
  SERVICE_PREFIX = 'potluck.npickens.'
6
12
 
7
13
  PLIST_XML = '<?xml version="1.0" encoding="UTF-8"?>'
@@ -10,6 +16,15 @@ module Potluck
10
16
 
11
17
  LAUNCHCTL_ERROR_REGEX = /^-|\t[^0]\t/.freeze
12
18
 
19
+ ##
20
+ # Creates a new instance.
21
+ #
22
+ # * +logger+ - +Logger+ instance to use for outputting info and error messages (optional). Output will
23
+ # be sent to stdout and stderr if none is supplied.
24
+ # * +manage+ - True if the service runs locally and should be managed by this process (default: true if
25
+ # launchctl is available and false otherwise).
26
+ # * +is_local+ - DEPRECATED. True if the service runs locally (use +manage+ instead).
27
+ #
13
28
  def initialize(logger: nil, manage: launchctl?, is_local: (is_local_omitted = true; nil))
14
29
  @logger = logger
15
30
  @manage = !!manage
@@ -23,7 +38,7 @@ module Potluck
23
38
  ensure_launchctl!
24
39
  end
25
40
 
26
- # DEPRECATED. Use `manage` instead.
41
+ # DEPRECATED. Use +manage+ instead.
27
42
  @is_local = is_local.nil? ? (IS_MACOS && ensure_launchctl! rescue false) : is_local
28
43
 
29
44
  unless is_local_omitted
@@ -32,38 +47,71 @@ module Potluck
32
47
  end
33
48
  end
34
49
 
50
+ ##
51
+ # Returns true if the service is managed.
52
+ #
35
53
  def manage?
36
54
  @manage
37
55
  end
38
56
 
57
+ ##
58
+ # Returns true if launchctl is available.
59
+ #
39
60
  def launchctl?
40
61
  defined?(@@launchctl) ? @@launchctl : (@@launchctl = `which launchctl 2>&1` && $? == 0)
41
62
  end
42
63
 
64
+ ##
65
+ # Checks if launchctl is available and raises an error if not.
66
+ #
43
67
  def ensure_launchctl!
44
68
  launchctl? || raise("Cannot manage #{self.class.to_s.split('::').last}: launchctl not found")
45
69
  end
46
70
 
71
+ ##
72
+ # Command to get the status of the service.
73
+ #
47
74
  def status_command
48
75
  @status_command || "launchctl list 2>&1 | grep #{SERVICE_PREFIX}#{self.class.service_name}"
49
76
  end
50
77
 
78
+ ##
79
+ # Regular expression to check the output of +#status_command+ against to determine if the service is in
80
+ # an error state.
81
+ #
51
82
  def status_error_regex
52
83
  @status_error_regex || LAUNCHCTL_ERROR_REGEX
53
84
  end
54
85
 
86
+ ##
87
+ # Command to start the service.
88
+ #
55
89
  def start_command
56
90
  @start_command || "launchctl bootstrap gui/#{Process.uid} #{self.class.plist_path}"
57
91
  end
58
92
 
93
+ ##
94
+ # Command to stop the service.
95
+ #
59
96
  def stop_command
60
97
  @stop_command || "launchctl bootout gui/#{Process.uid}/#{self.class.launchctl_name}"
61
98
  end
62
99
 
100
+ ##
101
+ # Writes the service's launchctl plist file to disk.
102
+ #
63
103
  def ensure_plist
104
+ FileUtils.mkdir_p(File.dirname(self.class.plist_path))
64
105
  File.write(self.class.plist_path, self.class.plist)
65
106
  end
66
107
 
108
+ ##
109
+ # Returns the status of the service:
110
+ #
111
+ # * +:active+ if the service is managed and running.
112
+ # * +:inactive+ if the service is not managed or is not running.
113
+ # * +:error+ if the service is managed and is in an error state.
114
+ #
67
115
  def status
68
116
  return :inactive unless manage?
69
117
 
@@ -78,6 +126,9 @@ module Potluck
78
126
  end
79
127
  end
80
128
 
129
+ ##
130
+ # Starts the service if it's managed and is not active.
131
+ #
81
132
  def start
82
133
  return unless manage?
83
134
 
@@ -96,6 +147,9 @@ module Potluck
96
147
  log("#{self.class.pretty_name} started")
97
148
  end
98
149
 
150
+ ##
151
+ # Stops the service if it's managed and is active or in an error state.
152
+ #
99
153
  def stop
100
154
  return unless manage? && status != :inactive
101
155
 
@@ -107,6 +161,9 @@ module Potluck
107
161
  log("#{self.class.pretty_name} stopped")
108
162
  end
109
163
 
164
+ ##
165
+ # Restarts the service if it's managed by calling stop and then start.
166
+ #
110
167
  def restart
111
168
  return unless manage?
112
169
 
@@ -114,6 +171,13 @@ module Potluck
114
171
  start
115
172
  end
116
173
 
174
+ ##
175
+ # Runs a command with the default shell. Raises an error if the command exits with a non-zero status.
176
+ #
177
+ # * +command+ - Command to run.
178
+ # * +redirect_stderr+ - True if stderr should be redirected to stdout; otherwise stderr output will not
179
+ # be logged (default: true).
180
+ #
117
181
  def run(command, redirect_stderr: true)
118
182
  output = `#{command}#{' 2>&1' if redirect_stderr}`
119
183
  status = $?
@@ -126,6 +190,12 @@ module Potluck
126
190
  end
127
191
  end
128
192
 
193
+ ##
194
+ # Logs a message using the logger or stdout/stderr if no logger is configured.
195
+ #
196
+ # * +message+ - Message to log.
197
+ # * +error+ - True if the message is an error (default: false).
198
+ #
129
199
  def log(message, error = false)
130
200
  if @logger
131
201
  error ? @logger.error(message) : @logger.info(message)
@@ -136,6 +206,13 @@ module Potluck
136
206
 
137
207
  private
138
208
 
209
+ ##
210
+ # Calls the supplied block repeatedly until it returns false. Checks frequently at first and gradually
211
+ # reduces down to one-second intervals.
212
+ #
213
+ # * +timeout+ - Maximum number of seconds to wait before timing out (default: 30).
214
+ # * +block+ - Block to call until it returns false.
215
+ #
139
216
  def wait(timeout = 30, &block)
140
217
  while block.call && timeout > 0
141
218
  reduce = [[(30 - timeout.to_i) / 5.0, 0.1].max, 1].min
@@ -145,22 +222,37 @@ module Potluck
145
222
  end
146
223
  end
147
224
 
225
+ ##
226
+ # Human-friendly name of the service.
227
+ #
148
228
  def self.pretty_name
149
229
  @pretty_name ||= self.to_s.split('::').last
150
230
  end
151
231
 
232
+ ##
233
+ # Computer-friendly name of the service.
234
+ #
152
235
  def self.service_name
153
236
  @service_name ||= pretty_name.downcase
154
237
  end
155
238
 
239
+ ##
240
+ # Name for the launchctl service.
241
+ #
156
242
  def self.launchctl_name
157
243
  "#{SERVICE_PREFIX}#{service_name}"
158
244
  end
159
245
 
246
+ ##
247
+ # Path to the launchctl plist file of the service.
248
+ #
160
249
  def self.plist_path
161
250
  File.join(DIR, "#{launchctl_name}.plist")
162
251
  end
163
252
 
253
+ ##
254
+ # Content of the launchctl plist file.
255
+ #
164
256
  def self.plist(content)
165
257
  <<~EOS
166
258
  #{PLIST_XML}
@@ -179,4 +271,17 @@ module Potluck
179
271
  EOS
180
272
  end
181
273
  end
274
+
275
+ ##
276
+ # DEPRECATED. Old name of Potluck::Service class.
277
+ #
278
+ Dish = Service.clone
279
+
280
+ # :nodoc: all
281
+ class Dish
282
+ def self.inherited(subclass)
283
+ warn("Potluck::Dish has been renamed to Potluck::Service. Please update #{subclass} to inherit from "\
284
+ 'Potluck::Service instead of Potluck::Dish.')
285
+ end
286
+ end
182
287
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Potluck
4
- VERSION = '0.0.3'
4
+ VERSION = '0.0.4'
5
5
  end
data/lib/potluck.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative('potluck/dish')
3
+ require_relative('potluck/service')
4
4
 
5
5
  module Potluck
6
6
  DIR = File.expand_path(File.join(ENV['HOME'], '.potluck')).freeze
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.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nate Pickens
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-16 00:00:00.000000000 Z
11
+ date: 2021-12-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -54,7 +54,7 @@ files:
54
54
  - README.md
55
55
  - VERSION
56
56
  - lib/potluck.rb
57
- - lib/potluck/dish.rb
57
+ - lib/potluck/service.rb
58
58
  - lib/potluck/version.rb
59
59
  homepage: https://github.com/npickens/potluck
60
60
  licenses:
@@ -78,7 +78,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
78
78
  - !ruby/object:Gem::Version
79
79
  version: '0'
80
80
  requirements: []
81
- rubygems_version: 3.2.3
81
+ rubygems_version: 3.2.32
82
82
  signing_key:
83
83
  specification_version: 4
84
84
  summary: An extensible Ruby framework for managing external processes.