locd 0.1.12 → 0.1.13

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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -2
  3. data/NAME +1 -0
  4. data/VERSION +1 -1
  5. data/config/default.lit.yaml +43 -0
  6. data/lib/locd.rb +0 -3
  7. data/lib/locd/agent.rb +50 -13
  8. data/lib/locd/agent/proxy.rb +27 -12
  9. data/lib/locd/agent/rotate_logs.rb +2 -2
  10. data/lib/locd/agent/site.rb +4 -1
  11. data/lib/locd/agent/system.rb +47 -12
  12. data/lib/locd/cli/command/agent.rb +48 -404
  13. data/lib/locd/cli/command/agent/add.rb +12 -4
  14. data/lib/locd/cli/command/agent/ls.rb +56 -0
  15. data/lib/locd/cli/command/agent/open.rb +53 -0
  16. data/lib/locd/cli/command/agent/plist.rb +43 -0
  17. data/lib/locd/cli/command/agent/restart.rb +43 -0
  18. data/lib/locd/cli/command/agent/rm.rb +46 -0
  19. data/lib/locd/cli/command/agent/shared.rb +253 -0
  20. data/lib/locd/cli/command/agent/start.rb +38 -0
  21. data/lib/locd/cli/command/agent/status.rb +41 -0
  22. data/lib/locd/cli/command/agent/stop.rb +39 -0
  23. data/lib/locd/cli/command/agent/tail.rb +82 -0
  24. data/lib/locd/cli/command/agent/truncate_logs.rb +65 -0
  25. data/lib/locd/cli/command/agent/update.rb +48 -0
  26. data/lib/locd/cli/command/base.rb +35 -3
  27. data/lib/locd/cli/command/job.rb +29 -36
  28. data/lib/locd/cli/command/job/add.rb +57 -0
  29. data/lib/locd/cli/command/main.rb +3 -3
  30. data/lib/locd/cli/command/proxy.rb +44 -20
  31. data/lib/locd/cli/command/rotate_logs.rb +28 -49
  32. data/lib/locd/cli/command/rotate_logs/add.rb +44 -0
  33. data/lib/locd/config.rb +88 -20
  34. data/lib/locd/config/types.rb +56 -27
  35. data/lib/locd/newsyslog.rb +23 -24
  36. data/lib/locd/proxy.rb +21 -9
  37. data/lib/locd/version.rb +94 -5
  38. data/locd.gemspec +10 -4
  39. metadata +67 -9
@@ -60,20 +60,28 @@ module Types
60
60
  def self.by_key
61
61
  # Got sick of writing "Hamster::Hash[...]"... "I8" <=> "Immutable"
62
62
  @by_key ||= I8[
63
- 'home' => config_path,
64
- 'bin' => ( t.when( 'locd' ) | config_path ),
63
+ 'home' => self.ConfigPath,
64
+ 'bin' => ( t.When( 'locd' ) | self.ConfigPath ),
65
+
66
+ 'log' => I8[
67
+ 'dir' => self.ConfigPath,
68
+ ],
69
+
70
+ 'tmp' => I8[
71
+ 'dir' => self.ConfigPath,
72
+ ],
65
73
 
66
74
  'cli' => I8[
67
75
  'log' => I8[
68
76
  'application' => t.non_empty_str,
69
77
  'level' => NRSER::Log::Types.level?,
70
- 'dest' => ( NRSER::Log::Types.stdio | config_path ),
78
+ 'dest' => ( NRSER::Log::Types.stdio | self.ConfigPath ),
71
79
  ],
72
80
 
73
81
  'bash_comp' => I8[
74
82
  'log' => I8[
75
83
  'level' => NRSER::Log::Types.level,
76
- 'dest' => config_path,
84
+ 'dest' => self.ConfigPath,
77
85
  ],
78
86
  ]
79
87
  ]
@@ -94,20 +102,23 @@ module Types
94
102
 
95
103
  # @!group Type Factory Class Methods
96
104
  # --------------------------------------------------------------------------
97
-
98
- def_factory :package_path do |
99
- name: 'PackagePath',
100
-
101
- from_s: ->( string ) {
102
- if string.start_with? '//'
103
- Locd::ROOT.join string[2..-1]
104
- end
105
- },
106
-
107
- **options
108
- |
109
- t.path &
110
- t.where( name: name, from_s: from_s, **options) { |path|
105
+
106
+ #@!method self.PackagePath **options
107
+ # @todo Document PackagePath type factory.
108
+ #
109
+ # @param [Hash] options
110
+ # Passed to {Type#initialize}.
111
+ #
112
+ # @return [Type]
113
+ #
114
+ def_type :PackagePath,
115
+ from_s: ->( s ) {
116
+ Locd::ROOT.join( s[2..-1] ) if s.start_with? '//'
117
+ },
118
+ &->( **options ) do
119
+ t.Intersection \
120
+ t.Path,
121
+ t.Where { |path|
111
122
  begin
112
123
  false == path.
113
124
  to_pn.
@@ -116,17 +127,35 @@ module Types
116
127
  rescue StandardError => error
117
128
  false
118
129
  end
119
- }
120
- end # def_factory :package_path
121
-
130
+ },
131
+ **options
132
+ end # .PackagePath
122
133
 
123
- def_factory :config_path do |name: 'ConfigPath', **options|
124
- t.or \
125
- package_path,
126
- t.abs_path,
127
- name: name,
134
+
135
+ #@!method self.ConfigPath **options
136
+ # A path we accept in the config. One of:
137
+ #
138
+ # 1. A {.PackagePath} that starts with `//...`, denoting it's relative to
139
+ # the package root.
140
+ #
141
+ # 2. A {NRSER::Types.HomePath} that starts with `~`, meaning it's relative
142
+ # to a user's home directory.
143
+ #
144
+ # 3. An {NRSER::Types.AbsPath}
145
+ #
146
+ # @param [Hash] options
147
+ # Passed to {Type#initialize}.
148
+ #
149
+ # @return [Type]
150
+ #
151
+ def_type :ConfigPath,
152
+ &->( **options ) do
153
+ t.Union \
154
+ self.PackagePath,
155
+ t.HomePath,
156
+ t.AbsPath,
128
157
  **options
129
- end # def_factory :config_path
158
+ end # .ConfigPath
130
159
 
131
160
  # @!endgroup Type Factory Class Methods # **********************************
132
161
 
@@ -32,13 +32,6 @@ module Locd::Newsyslog
32
32
  include NRSER::Log::Mixin
33
33
 
34
34
 
35
- # Default place to work out of.
36
- #
37
- # @return [Pathname]
38
- #
39
- DEFAULT_WORKDIR = Pathname.new( '~/.locd/tmp/newsyslog' ).expand_path
40
-
41
-
42
35
  # Lil' class that holds values for a `newsyslog` conf file entry.
43
36
  #
44
37
  # @see https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man5/newsyslog.conf.5.html
@@ -74,8 +67,7 @@ module Locd::Newsyslog
74
67
  # @param [type] arg_name
75
68
  # @todo Add name param description.
76
69
  #
77
- # @return [return_type]
78
- # @todo Document return value.
70
+ # @return [String]
79
71
  #
80
72
  def self.mode_string_for mode
81
73
  # t.match mode,
@@ -91,7 +83,7 @@ module Locd::Newsyslog
91
83
  raise ArgumentError,
92
84
  "Bad mode: #{ mode.inspect }, need String or Fixnum: '644'; 0644"
93
85
  end
94
- end # .normalize_mode
86
+ end # .mode_string_for
95
87
 
96
88
 
97
89
  def self.sig_num_for signal
@@ -201,7 +193,7 @@ module Locd::Newsyslog
201
193
  # @param [Locd::Agent] agent:
202
194
  # Agent to run for.
203
195
  #
204
- # @param [Pathname | String] workdir:
196
+ # @param [Pathname | String] tmp_conf_dir:
205
197
  # Directory to write working files to, which are removed after successful
206
198
  # runs.
207
199
  #
@@ -212,13 +204,15 @@ module Locd::Newsyslog
212
204
  # If we didn't run the command 'cause the agent doesn't have any logs
213
205
  # (that we know/care about).
214
206
  #
215
- def self.run agent, workdir: DEFAULT_WORKDIR
207
+ def self.run agent,
208
+ tmp_conf_dir: self.tmp_conf_dir,
209
+ keep_conf_files: false
216
210
  logger.debug "Calling {.run_for} agent #{ agent.label }...",
217
211
  agent: agent,
218
- workdir: workdir
212
+ tmp_conf_dir: tmp_conf_dir
219
213
 
220
- # Make sure `workdir` is a {Pathname}
221
- workdir = workdir.to_pn
214
+ # Make sure `tmp_conf_dir` is a {Pathname}
215
+ tmp_conf_dir = tmp_conf_dir.to_pn
222
216
 
223
217
  # Collect the unique log paths
224
218
  log_paths = agent.log_paths
@@ -237,7 +231,7 @@ module Locd::Newsyslog
237
231
  if pid = agent.pid( refresh: true )
238
232
  logger.debug "Agent is running", pid: pid
239
233
 
240
- pid_path = workdir / 'pids' / "#{ agent.label }.pid"
234
+ pid_path = tmp_conf_dir / 'pids' / "#{ agent.label }.pid"
241
235
  FileUtils.mkdir_p( pid_path.dirname ) unless pid_path.dirname.exist?
242
236
  pid_path.write pid
243
237
 
@@ -253,13 +247,13 @@ module Locd::Newsyslog
253
247
  entries.map { |entry|
254
248
  [
255
249
  entry.log_path.to_s,
256
- entry.instance_variables.map_values { |name|
250
+ entry.instance_variables.map { |name|
257
251
  entry.instance_variable_get name
258
252
  }
259
253
  ]
260
254
  }.to_h
261
255
 
262
- conf_path = workdir / 'confs' / "#{ agent.label }.conf"
256
+ conf_path = tmp_conf_dir / 'confs' / "#{ agent.label }.conf"
263
257
  FileUtils.mkdir_p( conf_path.dirname ) unless conf_path.dirname.exist?
264
258
  conf_path.write conf_contents
265
259
 
@@ -290,7 +284,7 @@ module Locd::Newsyslog
290
284
  ", output:\n" + result.out.indent(1, indent_string: '> ') )
291
285
 
292
286
  FileUtils.rm( pid_path ) if pid_path
293
- FileUtils.rm conf_path
287
+ FileUtils.rm( conf_path ) unless keep_conf_files
294
288
 
295
289
  logger.debug "Files cleaned up."
296
290
 
@@ -308,19 +302,19 @@ module Locd::Newsyslog
308
302
 
309
303
  # Call {.run} for each agent.
310
304
  #
311
- # @param workdir (see .run)
305
+ # @param tmp_conf_dir: (see .run)
312
306
  #
313
307
  # @return [Hash<Locd::Agent, Cmds::Result?>]
314
308
  # Hash mapping each agent to it's {.run} result (which may be `nil`).
315
309
  #
316
- def self.run_all workdir: DEFAULT_WORKDIR, trim_logs: true
310
+ def self.run_all tmp_conf_dir: self.tmp_conf_dir, trim_logs: true
317
311
  log_to_file do
318
312
  Locd::Agent.all.values.
319
313
  reject { |agent|
320
- agent.label == Locd::ROTATE_LOGS_LABEL
314
+ agent.label == Locd::Agent::RotateLogs.label
321
315
  }.
322
316
  map { |agent|
323
- [agent, run( agent, workdir: workdir )]
317
+ [agent, run( agent, tmp_conf_dir: tmp_conf_dir )]
324
318
  }.
325
319
  to_h.
326
320
  tap { |_|
@@ -331,7 +325,12 @@ module Locd::Newsyslog
331
325
 
332
326
 
333
327
  def self.log_dir
334
- @log_dir ||= Locd.config.log_dir / Locd::ROTATE_LOGS_LABEL
328
+ @log_dir ||= Locd.config.log_dir.join( Locd::Agent::RotateLogs.label )
329
+ end
330
+
331
+
332
+ def self.tmp_conf_dir
333
+ @tmp_conf_dir ||= Locd.config.tmp_dir.join( Locd::Agent::RotateLogs.label )
335
334
  end
336
335
 
337
336
 
@@ -2,6 +2,19 @@
2
2
  # encoding: UTF-8
3
3
 
4
4
 
5
+ # Refinements
6
+ # =======================================================================
7
+
8
+ require 'nrser/refinements/types'
9
+ using NRSER::Types
10
+
11
+
12
+ # Namespace
13
+ # ============================================================================
14
+
15
+ module Locd
16
+
17
+
5
18
  # Definitions
6
19
  # =======================================================================
7
20
 
@@ -15,7 +28,7 @@
15
28
  # [proxymachine]: https://rubygems.org/gems/proxymachine
16
29
  # [eventmachine]: https://rubygems.org/gems/eventmachine
17
30
  #
18
- module Locd::Proxy
31
+ module Proxy
19
32
 
20
33
  # Constants
21
34
  # ======================================================================
@@ -27,13 +40,6 @@ module Locd::Proxy
27
40
  HOST_RE = /^Host\:\ /i
28
41
 
29
42
 
30
- # Label for the Loc'd proxy agent itself
31
- #
32
- # @return [String]
33
- #
34
- ROTATE_LOGS_LABEL = 'com.nrser.locd.rotate-logs'
35
-
36
-
37
43
  # Mixins
38
44
  # ============================================================================
39
45
 
@@ -264,4 +270,10 @@ module Locd::Proxy
264
270
  ProxyMachine.run 'locd', bind, port
265
271
  end # .serve
266
272
 
267
- end # module Locd::Proxy
273
+ end # module Proxy
274
+
275
+
276
+ # /Namespace
277
+ # ============================================================================
278
+
279
+ end # module Locd
@@ -1,7 +1,44 @@
1
1
  # encoding: UTF-8
2
2
  # frozen_string_literal: true
3
3
 
4
+ ##############################################################################
5
+ # This file is kind-of special: you should be able to load it totally
6
+ # independently.
7
+ #
8
+ # This means you can go
9
+ #
10
+ # load 'path/to/gem/lib/locd/version.rb'
11
+ #
12
+ # and it will succeed, regardless of paths or gems or any other environment or
13
+ # state.
14
+ #
15
+ # It defines a few very basic pieces of information about the app, and it turns
16
+ # out to be incredibly useful on an adminstration level to be able to fire up
17
+ # any old Ruby interpreter and pull that info in without worrying about all
18
+ # the other shit you need to actually run it.
19
+ #
20
+ # In general, that means that this file shouldn't require anything, and
21
+ # anything it does require must not depend on anything outside Ruby's standard
22
+ # library.
23
+ #
24
+ # This file is loaded by `//locd.gemspec` to get the version information,
25
+ # which is in turn loaded from the `//VERSION` file (see {Locd::VERSION}).
26
+ #
27
+ ##############################################################################
28
+
29
+
30
+ # Requirements
31
+ # ========================================================================
32
+
33
+ # Stdlib
34
+ # ------------------------------------------------------------------------
35
+
4
36
  require 'pathname'
37
+ require 'singleton'
38
+
39
+
40
+ # Definitions
41
+ # ========================================================================
5
42
 
6
43
  module Locd
7
44
  # Absolute, expanded path to the gem's root directory.
@@ -11,16 +48,68 @@ module Locd
11
48
  ROOT = Pathname.new( __dir__ ).join( '..', '..' ).expand_path
12
49
 
13
50
 
14
- # String version read from `//VERSION`
51
+ # String version read from `//VERSION` and used in the gemspec.
52
+ #
53
+ # I use this approach in order to create a standard versioning system across
54
+ # *any* package, regardless or runtime, and so that tools can figure out
55
+ # what version a package is without even having it's runtime available.
56
+ #
57
+ # This has turned out to be super helpful, and I'm surprised it isn't more
58
+ # common or standardized in some way... I think pretty much every package
59
+ # in very language has a root directory and is capable of reading a file
60
+ # to figure out it's state.
15
61
  #
16
62
  # @return [String]
17
63
  #
18
- VERSION = (ROOT / 'VERSION').read
64
+ VERSION = (ROOT + 'VERSION').read.chomp
19
65
 
20
66
 
21
- # The gem name
67
+ # The gem name, read from the `//NAME` file, and used in the gemspec.
68
+ #
69
+ # See {Locd::VERSION} for an explanation of why bare files in the package
70
+ # root are used.
22
71
  #
23
72
  # @return [String]
24
73
  #
25
- GEM_NAME = 'locd'
26
- end
74
+ GEM_NAME = (ROOT + 'NAME').read.chomp
75
+
76
+
77
+ # {Singleton} extension of {Gem::Version} that loads {Locd::VERSION} and
78
+ # provides some convenient methods.
79
+ #
80
+ class Version < Gem::Version
81
+ include ::Singleton
82
+
83
+ # Private method to instantiate the {#instance} using the {Locd::VERSION}
84
+ # {String}.
85
+ #
86
+ # @return [Version]
87
+ #
88
+ def self.new
89
+ super Locd::VERSION
90
+ end
91
+
92
+ # We need to mark {.new} as private to dissuade construction of additional
93
+ # instances.
94
+ private_class_method :new
95
+
96
+ # Proxies to the {#instance}'s {#dev?}.
97
+ #
98
+ # @return (see #dev?)
99
+ #
100
+ def self.dev?
101
+ instance.dev?
102
+ end
103
+
104
+ # Tests if the package's version is a development pre-release.
105
+ #
106
+ # @return [Boolean]
107
+ # `true` if this is a development pre-release.
108
+ #
109
+ def dev?
110
+ segments[3] == 'dev'
111
+ end
112
+
113
+ end # module Version
114
+
115
+ end # module Locd
@@ -29,12 +29,16 @@ Gem::Specification.new do |spec|
29
29
  # Development Dependencies
30
30
  # ----------------------------------------------------------------------------
31
31
 
32
- spec.add_development_dependency "bundler", "~> 1.16"
32
+ spec.add_development_dependency "bundler", ">= 1.16"
33
33
  spec.add_development_dependency "rake", "~> 10.0"
34
34
  spec.add_development_dependency "rspec", "~> 3.7"
35
35
 
36
36
  # Nicer REPL experience
37
37
  spec.add_development_dependency "pry", '~> 0.10.4'
38
+ spec.add_development_dependency "pry-rescue", '~> 1.4.5'
39
+ spec.add_development_dependency "pry-stack_explorer", '~> 0.4.9'
40
+
41
+
38
42
  # GitHub-Flavored Markdown (GFM) for use with `yard`
39
43
  spec.add_development_dependency 'github-markup', '~> 1.6'
40
44
  # Doc site generation with `yard`
@@ -47,7 +51,7 @@ Gem::Specification.new do |spec|
47
51
  # ----------------------------------------------------------------------------
48
52
 
49
53
  # My guns
50
- spec.add_dependency "nrser", '~> 0.3.9'
54
+ spec.add_dependency "nrser", '~> 0.3.12'
51
55
 
52
56
  # Used to process command templates from projects' `//dev/locd.yml` files
53
57
  spec.add_dependency "cmds", ">= 0.2.10"
@@ -59,8 +63,10 @@ Gem::Specification.new do |spec|
59
63
  spec.add_dependency 'plist', '~> 3.4'
60
64
 
61
65
  # Atli, my fork of Thor for CLI interface
62
- spec.add_dependency 'atli', '~> 0.1.12'
66
+ spec.add_dependency 'atli', '~> 0.1.13'
63
67
 
64
- #
68
+ # TODO IDK what was going on here..
65
69
  # spec.add_dependency 'terminal-table', '~> 1.8'
70
+
71
+ spec.add_dependency 'rouge', '~> 3.1.1'
66
72
  end