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.
- checksums.yaml +4 -4
- data/Gemfile +2 -2
- data/NAME +1 -0
- data/VERSION +1 -1
- data/config/default.lit.yaml +43 -0
- data/lib/locd.rb +0 -3
- data/lib/locd/agent.rb +50 -13
- data/lib/locd/agent/proxy.rb +27 -12
- data/lib/locd/agent/rotate_logs.rb +2 -2
- data/lib/locd/agent/site.rb +4 -1
- data/lib/locd/agent/system.rb +47 -12
- data/lib/locd/cli/command/agent.rb +48 -404
- data/lib/locd/cli/command/agent/add.rb +12 -4
- data/lib/locd/cli/command/agent/ls.rb +56 -0
- data/lib/locd/cli/command/agent/open.rb +53 -0
- data/lib/locd/cli/command/agent/plist.rb +43 -0
- data/lib/locd/cli/command/agent/restart.rb +43 -0
- data/lib/locd/cli/command/agent/rm.rb +46 -0
- data/lib/locd/cli/command/agent/shared.rb +253 -0
- data/lib/locd/cli/command/agent/start.rb +38 -0
- data/lib/locd/cli/command/agent/status.rb +41 -0
- data/lib/locd/cli/command/agent/stop.rb +39 -0
- data/lib/locd/cli/command/agent/tail.rb +82 -0
- data/lib/locd/cli/command/agent/truncate_logs.rb +65 -0
- data/lib/locd/cli/command/agent/update.rb +48 -0
- data/lib/locd/cli/command/base.rb +35 -3
- data/lib/locd/cli/command/job.rb +29 -36
- data/lib/locd/cli/command/job/add.rb +57 -0
- data/lib/locd/cli/command/main.rb +3 -3
- data/lib/locd/cli/command/proxy.rb +44 -20
- data/lib/locd/cli/command/rotate_logs.rb +28 -49
- data/lib/locd/cli/command/rotate_logs/add.rb +44 -0
- data/lib/locd/config.rb +88 -20
- data/lib/locd/config/types.rb +56 -27
- data/lib/locd/newsyslog.rb +23 -24
- data/lib/locd/proxy.rb +21 -9
- data/lib/locd/version.rb +94 -5
- data/locd.gemspec +10 -4
- metadata +67 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f94096db9ae78d4d6a256a23d22b40b0d345c0e
|
4
|
+
data.tar.gz: e09575a1e5757b99012e7d14a68a97d0aa0a1ef0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd4def91dc1851b6290cf9cac485ba6b1dbd290a1a860de95c2e50a05191cac35aa4740c73686eedb3827e96a8116711f5f4c3f33c3c7913288f290e62922f86
|
7
|
+
data.tar.gz: 655fd3801f4b54eaa0083255dcb2aab2d2be3a1245b9dee3e9c13d980f135e015e71476e3e255d0660903ff1b38b98c4624065459c33a771a6085ca31d8ce811
|
data/Gemfile
CHANGED
@@ -2,9 +2,9 @@ source "https://rubygems.org"
|
|
2
2
|
|
3
3
|
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
4
4
|
|
5
|
-
|
5
|
+
gem 'nrser', path: './dev/packages/gems/nrser'
|
6
6
|
# gem 'cmds', path: './dev/packages/gems/cmds'
|
7
|
-
|
7
|
+
gem 'atli', path: './dev/packages/gems/atli'
|
8
8
|
|
9
9
|
# Specify your gem's dependencies in locd.gemspec
|
10
10
|
gemspec
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.13
|
@@ -0,0 +1,43 @@
|
|
1
|
+
locd:
|
2
|
+
home: ~/.locd
|
3
|
+
tmp:
|
4
|
+
$format: ${#locd/home}/tmp
|
5
|
+
bin: locd
|
6
|
+
|
7
|
+
cli:
|
8
|
+
log:
|
9
|
+
level: info
|
10
|
+
application: Locd
|
11
|
+
dest: $stderr
|
12
|
+
|
13
|
+
bash_comp:
|
14
|
+
log:
|
15
|
+
level: warn
|
16
|
+
dest:
|
17
|
+
$format: ${#locd/tmp}/bash_comp.log
|
18
|
+
# /CLI
|
19
|
+
|
20
|
+
namespace:
|
21
|
+
label: com.nrser.locd
|
22
|
+
env: LOCD
|
23
|
+
|
24
|
+
proxy:
|
25
|
+
port: 8888
|
26
|
+
bind: 127.0.0.1
|
27
|
+
|
28
|
+
rotate_logs:
|
29
|
+
newsyslog:
|
30
|
+
tmp_conf_dir:
|
31
|
+
$format: ${#locd/tmp}/newsyslog
|
32
|
+
start_interval:
|
33
|
+
minute: 0
|
34
|
+
|
35
|
+
agent:
|
36
|
+
config_key: locd_config
|
37
|
+
|
38
|
+
site:
|
39
|
+
bind: 127.0.0.1
|
40
|
+
ports:
|
41
|
+
start: 55000
|
42
|
+
end: 56000
|
43
|
+
|
data/lib/locd.rb
CHANGED
data/lib/locd/agent.rb
CHANGED
@@ -1,21 +1,19 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
# Requirements
|
4
5
|
# =======================================================================
|
5
6
|
|
6
|
-
|
7
|
-
# -----------------------------------------------------------------------
|
7
|
+
### Stdlib ###
|
8
8
|
|
9
|
-
# Deps
|
10
|
-
# -----------------------------------------------------------------------
|
11
|
-
require 'plist'
|
12
9
|
require 'fileutils'
|
10
|
+
|
11
|
+
### Deps ###
|
12
|
+
|
13
|
+
require 'plist'
|
13
14
|
require 'nrser'
|
14
15
|
require 'nrser/props/immutable/hash'
|
15
16
|
|
16
|
-
# Project / Package
|
17
|
-
# -----------------------------------------------------------------------
|
18
|
-
|
19
17
|
|
20
18
|
# Refinements
|
21
19
|
# =======================================================================
|
@@ -24,10 +22,15 @@ require 'nrser/refinements/types'
|
|
24
22
|
using NRSER::Types
|
25
23
|
|
26
24
|
|
25
|
+
# Namespace
|
26
|
+
# ============================================================================
|
27
|
+
|
28
|
+
module Locd
|
29
|
+
|
30
|
+
|
27
31
|
# Definitions
|
28
32
|
# =======================================================================
|
29
33
|
|
30
|
-
|
31
34
|
# Represents a backend agent that the proxy can route to.
|
32
35
|
#
|
33
36
|
# Agents are managed by `launchd`, macOS's system service manager, and
|
@@ -37,7 +40,7 @@ using NRSER::Types
|
|
37
40
|
# From there they can be managed directly with macOS's `launchctl` utility,
|
38
41
|
# with the `lunchy` gem, etc.
|
39
42
|
#
|
40
|
-
class
|
43
|
+
class Agent
|
41
44
|
|
42
45
|
# Constants
|
43
46
|
# ==========================================================================
|
@@ -373,7 +376,7 @@ class Locd::Agent
|
|
373
376
|
# @param [String] label
|
374
377
|
# The agent's label.
|
375
378
|
#
|
376
|
-
# @return [
|
379
|
+
# @return [Agent]
|
377
380
|
# If a Loc'd agent with `label` is installed.
|
378
381
|
#
|
379
382
|
# @return [nil]
|
@@ -388,6 +391,29 @@ class Locd::Agent
|
|
388
391
|
end
|
389
392
|
|
390
393
|
|
394
|
+
# Like {.get} but raises if the agent is not found.
|
395
|
+
#
|
396
|
+
# @param [String] label
|
397
|
+
# The agent's label.
|
398
|
+
#
|
399
|
+
# @return [Agent]
|
400
|
+
# The agent.
|
401
|
+
#
|
402
|
+
# @raise [NotFoundError]
|
403
|
+
# If the agent isn't there.
|
404
|
+
#
|
405
|
+
def self.get! label
|
406
|
+
get( label ).tap do |agent|
|
407
|
+
if agent.nil?
|
408
|
+
raise NotFoundError, [
|
409
|
+
self, "with label", label,
|
410
|
+
"not found. Expected the property list at", plist_abs_path( label )
|
411
|
+
].map( &:to_s ).join( ' ' )
|
412
|
+
end
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
|
391
417
|
# Find a single {Locd::Agent} matching `pattern` or raise.
|
392
418
|
#
|
393
419
|
# Parameters are passed to {Locd::Label.regexp_for_glob} and the resulting
|
@@ -441,7 +467,7 @@ class Locd::Agent
|
|
441
467
|
if agents.empty?
|
442
468
|
raise NRSER::CountError.new(
|
443
469
|
"No agents found for pattern from #{ pattern.source.inspect }",
|
444
|
-
|
470
|
+
value: agents,
|
445
471
|
expected: '#count > 0',
|
446
472
|
)
|
447
473
|
end
|
@@ -1011,6 +1037,11 @@ class Locd::Agent
|
|
1011
1037
|
end
|
1012
1038
|
|
1013
1039
|
|
1040
|
+
def ensure_running **start_kwds
|
1041
|
+
start( **start_kwds ) unless running?
|
1042
|
+
end
|
1043
|
+
|
1044
|
+
|
1014
1045
|
# Stop the agent.
|
1015
1046
|
#
|
1016
1047
|
# @param [Boolean] unload:
|
@@ -1269,7 +1300,13 @@ class Locd::Agent
|
|
1269
1300
|
|
1270
1301
|
# end protected
|
1271
1302
|
|
1272
|
-
end # class
|
1303
|
+
end # class Agent
|
1304
|
+
|
1305
|
+
|
1306
|
+
# /Namespace
|
1307
|
+
# ============================================================================
|
1308
|
+
|
1309
|
+
end # module Locd
|
1273
1310
|
|
1274
1311
|
|
1275
1312
|
# Post-Processing
|
data/lib/locd/agent/proxy.rb
CHANGED
@@ -1,18 +1,20 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
# Requirements
|
4
5
|
# =======================================================================
|
5
6
|
|
6
|
-
|
7
|
-
# -----------------------------------------------------------------------
|
7
|
+
### Stdlib ###
|
8
8
|
|
9
|
-
# Deps
|
10
|
-
# -----------------------------------------------------------------------
|
11
|
-
require 'plist'
|
12
9
|
require 'fileutils'
|
13
10
|
|
14
|
-
|
15
|
-
|
11
|
+
### Deps ###
|
12
|
+
|
13
|
+
require 'plist'
|
14
|
+
|
15
|
+
### Project / Package ###
|
16
|
+
|
17
|
+
require_relative './system'
|
16
18
|
|
17
19
|
|
18
20
|
# Refinements
|
@@ -22,19 +24,25 @@ require 'nrser/refinements/types'
|
|
22
24
|
using NRSER::Types
|
23
25
|
|
24
26
|
|
27
|
+
# Namespace
|
28
|
+
# ============================================================================
|
29
|
+
|
30
|
+
module Locd
|
31
|
+
class Agent
|
32
|
+
|
33
|
+
|
25
34
|
# Definitions
|
26
35
|
# =======================================================================
|
27
36
|
|
28
|
-
|
29
37
|
# An server {Locd::Agent} (HTTP only at the moment) that the proxy can
|
30
38
|
# route requests to.
|
31
39
|
#
|
32
|
-
class
|
40
|
+
class Proxy < Agent
|
33
41
|
|
34
42
|
# Mixins
|
35
43
|
# ============================================================================
|
36
44
|
|
37
|
-
include
|
45
|
+
include System
|
38
46
|
|
39
47
|
|
40
48
|
# Constants
|
@@ -44,7 +52,7 @@ class Locd::Agent::Proxy < Locd::Agent
|
|
44
52
|
#
|
45
53
|
# @return [Hamster::SortedSet<Symbol>]
|
46
54
|
#
|
47
|
-
TO_H_NAMES =
|
55
|
+
TO_H_NAMES = Agent::TO_H_NAMES.union [:port, :url]
|
48
56
|
|
49
57
|
|
50
58
|
# Class Methods
|
@@ -108,4 +116,11 @@ class Locd::Agent::Proxy < Locd::Agent
|
|
108
116
|
|
109
117
|
# @!endgroup Instance Methods: Attribute Readers
|
110
118
|
|
111
|
-
end # class
|
119
|
+
end # class Proxy
|
120
|
+
|
121
|
+
|
122
|
+
# /Namespace
|
123
|
+
# ============================================================================
|
124
|
+
|
125
|
+
end # class Agent
|
126
|
+
end # module Locd
|
@@ -53,12 +53,12 @@ class Locd::Agent::RotateLogs < Locd::Agent::Job
|
|
53
53
|
# @return [String]
|
54
54
|
#
|
55
55
|
def self.default_cmd_template
|
56
|
-
"{bin} rotate-logs run"
|
56
|
+
"{bin} rotate-logs run --backtrace"
|
57
57
|
end # .cmd_template
|
58
58
|
|
59
59
|
|
60
60
|
def self.default_start_interval
|
61
|
-
|
61
|
+
Locd.config[:rotate_logs, :start_interval].deep_symbolize_keys
|
62
62
|
end
|
63
63
|
|
64
64
|
|
data/lib/locd/agent/site.rb
CHANGED
@@ -92,7 +92,10 @@ class Locd::Agent::Site < Locd::Agent
|
|
92
92
|
# `true` if we think this `plist` belongs to a site.
|
93
93
|
#
|
94
94
|
def self.plist? plist
|
95
|
-
!!
|
95
|
+
!!(
|
96
|
+
plist.dig( Locd.config[:agent, :config_key], 'port' ) &&
|
97
|
+
plist.dig( Locd.config[:agent, :config_key], 'is_system' ) != true
|
98
|
+
)
|
96
99
|
end # .plist?
|
97
100
|
|
98
101
|
|
data/lib/locd/agent/system.rb
CHANGED
@@ -40,27 +40,52 @@ module Locd::Agent::System
|
|
40
40
|
end
|
41
41
|
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
# Is an agent label for a system agent of *this* Loc'd instance?
|
44
|
+
#
|
45
|
+
# @note
|
46
|
+
# We can't tell if a label is a system agent label for *any* Loc'd instance
|
47
|
+
# since the prefix can be configured to anything (via the
|
48
|
+
# `locd:namespace:label` key).
|
49
|
+
#
|
50
|
+
# @return [Boolean]
|
51
|
+
#
|
52
|
+
def self.instance_label? label
|
53
|
+
label.is_a?( String ) &&
|
54
|
+
label.start_with?( "#{ Locd.config[:namespace, :label] }." )
|
46
55
|
end
|
47
56
|
|
48
57
|
|
49
|
-
# Is
|
58
|
+
# Is the plist for a system agent of *any* Loc'd instance?
|
59
|
+
#
|
60
|
+
# In case it's not obvious, this tests true given plists of system agents
|
61
|
+
# of *other* Loc'd instance configurations besides just this one, which can
|
62
|
+
# be useful to weed things out. Maybe.
|
50
63
|
#
|
51
64
|
# @param plist (see Locd::Agent.plist?)
|
52
65
|
#
|
53
66
|
# @return [Boolean]
|
54
|
-
# `true` if the plist is for a system agent
|
67
|
+
# `true` if the plist is for a system agent.
|
55
68
|
#
|
56
69
|
def self.plist? plist
|
57
|
-
|
58
|
-
plist.dig( Locd.config[:agent, :config_key], 'is_system' ) \
|
59
|
-
&& label?( plist['Label'] )
|
60
|
-
)
|
70
|
+
plist.dig( Locd.config[:agent, :config_key], 'is_system' ) == true
|
61
71
|
end # .plist?
|
62
72
|
|
63
73
|
|
74
|
+
# Is a plist for a system agent of *this* Loc'd instance?
|
75
|
+
#
|
76
|
+
# @see plist?
|
77
|
+
# @see instance_label?
|
78
|
+
#
|
79
|
+
# @param plist (see Locd::Agent.plist?)
|
80
|
+
#
|
81
|
+
# @return [Boolean]
|
82
|
+
# `true` if the plist is for a system agent for this Loc'd instance config.
|
83
|
+
#
|
84
|
+
def self.instance_plist? plist
|
85
|
+
plist?( plist ) && instance_label?( plist[ 'Label' ] )
|
86
|
+
end
|
87
|
+
|
88
|
+
|
64
89
|
# Find the concrete {Locd::Agent} subclass (that has mixed in
|
65
90
|
# {Locd::Agent::System}) for a property list.
|
66
91
|
#
|
@@ -166,8 +191,18 @@ module Locd::Agent::System
|
|
166
191
|
# @return [nil]
|
167
192
|
# If the agent does not exist.
|
168
193
|
#
|
169
|
-
def get
|
170
|
-
|
194
|
+
def get label = self.label
|
195
|
+
unless label == self.label
|
196
|
+
raise NRSER::AttributeError.new \
|
197
|
+
"System agents have a fixed label, must be", self.label
|
198
|
+
end
|
199
|
+
|
200
|
+
super( label )
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
def get! label = self.label
|
205
|
+
super( label )
|
171
206
|
end
|
172
207
|
|
173
208
|
# @!endgroup
|
@@ -231,7 +266,7 @@ module Locd::Agent::System
|
|
231
266
|
end
|
232
267
|
|
233
268
|
{
|
234
|
-
bin: bin,
|
269
|
+
bin: bin.to_s,
|
235
270
|
workdir: workdir,
|
236
271
|
**kwds,
|
237
272
|
is_system: true,
|
@@ -3,15 +3,11 @@
|
|
3
3
|
# Requirements
|
4
4
|
# =======================================================================
|
5
5
|
|
6
|
-
# Stdlib
|
7
|
-
# -----------------------------------------------------------------------
|
8
|
-
|
9
|
-
# Deps
|
10
|
-
# -----------------------------------------------------------------------
|
11
|
-
|
12
6
|
# Project / Package
|
13
7
|
# -----------------------------------------------------------------------
|
14
8
|
|
9
|
+
require_relative './base'
|
10
|
+
|
15
11
|
|
16
12
|
# Refinements
|
17
13
|
# =======================================================================
|
@@ -20,6 +16,14 @@ require 'nrser/refinements/types'
|
|
20
16
|
using NRSER::Types
|
21
17
|
|
22
18
|
|
19
|
+
# Namespace
|
20
|
+
# =======================================================================
|
21
|
+
|
22
|
+
module Locd
|
23
|
+
module CLI
|
24
|
+
module Command
|
25
|
+
|
26
|
+
|
23
27
|
# Definitions
|
24
28
|
# =======================================================================
|
25
29
|
|
@@ -27,7 +31,7 @@ using NRSER::Types
|
|
27
31
|
#
|
28
32
|
# @see http://whatisthor.com/
|
29
33
|
#
|
30
|
-
class
|
34
|
+
class Agent < Base
|
31
35
|
|
32
36
|
# Helpers
|
33
37
|
# ==========================================================================
|
@@ -66,6 +70,21 @@ class Locd::CLI::Command::Agent < Locd::CLI::Command::Base
|
|
66
70
|
end
|
67
71
|
end
|
68
72
|
|
73
|
+
|
74
|
+
# The {#pattern} argument is not required because system agent subclasses
|
75
|
+
# don't need or want one.
|
76
|
+
#
|
77
|
+
# My current solution is to check {#pattern} before using it in
|
78
|
+
# {#find_only!} and {#find_multi!} and override those in system agent
|
79
|
+
# commands.
|
80
|
+
#
|
81
|
+
def check_pattern! pattern
|
82
|
+
if pattern.nil?
|
83
|
+
raise Thor::RequiredArgumentMissingError,
|
84
|
+
"No value provided for required arguments 'pattern'"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
69
88
|
|
70
89
|
# Find exactly one {Locd::Agent} for a `pattern`, using the any `:pattern`
|
71
90
|
# shared options provided, and raising if there are no matches or more
|
@@ -79,11 +98,13 @@ class Locd::CLI::Command::Agent < Locd::CLI::Command::Base
|
|
79
98
|
# @raise If more or less than one agent is matched.
|
80
99
|
#
|
81
100
|
def find_only! pattern
|
101
|
+
check_pattern! pattern
|
82
102
|
agent_class.find_only! pattern, **option_kwds( groups: :pattern )
|
83
103
|
end
|
84
104
|
|
85
105
|
|
86
106
|
def find_multi! pattern
|
107
|
+
check_pattern! pattern
|
87
108
|
# Behavior depend on the `:all` option...
|
88
109
|
if options[:all]
|
89
110
|
# `:all` is set, so we find all the agents for the pattern, raising
|
@@ -101,147 +122,11 @@ class Locd::CLI::Command::Agent < Locd::CLI::Command::Base
|
|
101
122
|
# end protected
|
102
123
|
public
|
103
124
|
|
104
|
-
def_shared :argument,
|
105
|
-
name: :pattern,
|
106
|
-
groups: :pattern,
|
107
|
-
desc: "Label or workdir pattern to find agent(s)",
|
108
|
-
type: :string,
|
109
|
-
required: true,
|
110
|
-
complete: ->( klass:, **etc ) { klass.agent_class.labels.to_a }
|
111
|
-
|
112
125
|
|
113
126
|
# Shared Options
|
114
127
|
# ============================================================================
|
115
128
|
|
116
|
-
|
117
|
-
groups: :respond_with_agents,
|
118
|
-
group: "Display",
|
119
|
-
desc: "Display agent details table",
|
120
|
-
aliases: '-l',
|
121
|
-
type: :boolean
|
122
|
-
|
123
|
-
# `:pattern` Group
|
124
|
-
# ----------------------------------------------------------------------------
|
125
|
-
#
|
126
|
-
# Options when provided a `PATTERN` argument used to find agents by label.
|
127
|
-
#
|
128
|
-
|
129
|
-
shared_option :full,
|
130
|
-
groups: :pattern,
|
131
|
-
desc: "Require label PATTERN to match entire string",
|
132
|
-
aliases: '-u',
|
133
|
-
type: :boolean
|
134
|
-
|
135
|
-
shared_option :ignore_case,
|
136
|
-
groups: :pattern,
|
137
|
-
desc: "Make label PATTERN case-insensitive",
|
138
|
-
aliases: '-i',
|
139
|
-
type: :boolean
|
140
|
-
|
141
|
-
shared_option :recursive,
|
142
|
-
groups: :pattern,
|
143
|
-
desc: "Make workdir PATTERN match all subdirs too",
|
144
|
-
aliases: '-r',
|
145
|
-
type: :boolean
|
146
|
-
|
147
|
-
# NOTE We don't expose the workdir pattern's `:cwd` option...
|
148
|
-
# If you want to match a directory from the CLI, just provide that
|
149
|
-
# directory... no reason to specify the `:cwd` in an option then
|
150
|
-
# provide a relative PATTERN
|
151
|
-
#
|
152
|
-
|
153
|
-
# `:multi` Group
|
154
|
-
# ----------------------------------------------------------------------------
|
155
|
-
#
|
156
|
-
# For commands that can match multiple agents.
|
157
|
-
#
|
158
|
-
|
159
|
-
shared_option :all,
|
160
|
-
groups: :multi,
|
161
|
-
group: "Pattern",
|
162
|
-
desc: "Apply to ALL agents that PATTERN matches",
|
163
|
-
aliases: '-a',
|
164
|
-
type: :boolean
|
165
|
-
|
166
|
-
|
167
|
-
# `:write` Group
|
168
|
-
# ----------------------------------------------------------------------------
|
169
|
-
#
|
170
|
-
# Options when writing an agent `.plist` (`create`, `update`).
|
171
|
-
#
|
172
|
-
|
173
|
-
shared_option :label,
|
174
|
-
groups: :write,
|
175
|
-
desc: "Agent label, which is also the domain the proxy will serve it at",
|
176
|
-
aliases: ['--name', '-n'],
|
177
|
-
type: :string #,
|
178
|
-
# required: true
|
179
|
-
|
180
|
-
shared_option :workdir,
|
181
|
-
groups: :write,
|
182
|
-
desc: "Working directory for the agent's command",
|
183
|
-
aliases: ['--dir'],
|
184
|
-
type: :string
|
185
|
-
|
186
|
-
shared_option :log_path,
|
187
|
-
groups: :write,
|
188
|
-
desc: "Path to log agent's STDOUT and STDERR (combined)",
|
189
|
-
aliases: ['--log'],
|
190
|
-
type: :string
|
191
|
-
|
192
|
-
shared_option :keep_alive,
|
193
|
-
groups: :write,
|
194
|
-
desc: "Try to keep the agent running",
|
195
|
-
type: :boolean,
|
196
|
-
default: false
|
197
|
-
|
198
|
-
shared_option :run_at_load,
|
199
|
-
groups: :write,
|
200
|
-
desc: "Start the agent when loading it",
|
201
|
-
type: :boolean,
|
202
|
-
default: false
|
203
|
-
|
204
|
-
|
205
|
-
# `:add` Group
|
206
|
-
# ----------------------------------------------------------------------------
|
207
|
-
|
208
|
-
shared_option :force,
|
209
|
-
groups: :add,
|
210
|
-
desc: "Overwrite any existing agent",
|
211
|
-
type: :boolean,
|
212
|
-
default: false
|
213
|
-
|
214
|
-
|
215
|
-
shared_option :load,
|
216
|
-
groups: :add,
|
217
|
-
desc: "Load the agent into `launchd`",
|
218
|
-
type: :boolean,
|
219
|
-
default: true
|
220
|
-
|
221
|
-
|
222
|
-
# `:start` Group
|
223
|
-
# --------------------------------------------------------------------------
|
224
|
-
#
|
225
|
-
# Relevant options when starting agents.
|
226
|
-
#
|
227
|
-
|
228
|
-
shared_option :load,
|
229
|
-
groups: :start,
|
230
|
-
desc: "Load the agent before starting",
|
231
|
-
type: :boolean,
|
232
|
-
default: true
|
233
|
-
|
234
|
-
shared_option :force,
|
235
|
-
groups: :start,
|
236
|
-
desc: "Force loading of agent even if it's disabled",
|
237
|
-
type: :boolean,
|
238
|
-
default: false
|
239
|
-
|
240
|
-
shared_option :enable,
|
241
|
-
groups: :start,
|
242
|
-
desc: "Set `launchd` *Disabled* key to `false`",
|
243
|
-
type: :boolean,
|
244
|
-
default: false
|
129
|
+
require_relative './agent/shared'
|
245
130
|
|
246
131
|
|
247
132
|
# Commands
|
@@ -250,281 +135,40 @@ class Locd::CLI::Command::Agent < Locd::CLI::Command::Base
|
|
250
135
|
# Querying
|
251
136
|
# ----------------------------------------------------------------------------
|
252
137
|
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
map list: :ls
|
257
|
-
|
258
|
-
include_shared groups: :pattern
|
259
|
-
|
260
|
-
include_options :long,
|
261
|
-
groups: :pattern
|
262
|
-
|
263
|
-
def ls # pattern = nil
|
264
|
-
results = if pattern.nil?
|
265
|
-
agent_class.all
|
266
|
-
else
|
267
|
-
agent_class.list pattern, **option_kwds( groups: :pattern )
|
268
|
-
end
|
269
|
-
|
270
|
-
respond results.values.sort
|
271
|
-
end
|
272
|
-
|
273
|
-
|
274
|
-
desc "plist PATTERN [OPTIONS]",
|
275
|
-
"Print an agent's launchd property list"
|
276
|
-
|
277
|
-
include_options groups: :pattern
|
278
|
-
|
279
|
-
def plist pattern
|
280
|
-
agent = find_only! pattern
|
281
|
-
|
282
|
-
if options[:json] || options[:yaml]
|
283
|
-
respond agent.plist
|
284
|
-
else
|
285
|
-
respond agent.path.read
|
286
|
-
end
|
287
|
-
end
|
288
|
-
|
289
|
-
|
290
|
-
desc 'status PATTERN',
|
291
|
-
"Print agent status"
|
292
|
-
|
293
|
-
include_options groups: :pattern
|
294
|
-
|
295
|
-
def status pattern
|
296
|
-
agent = find_only! pattern
|
297
|
-
respond \
|
298
|
-
label: agent.label,
|
299
|
-
status: agent.status.to_h( compact: false )
|
300
|
-
end
|
138
|
+
require_relative './agent/ls'
|
139
|
+
require_relative './agent/plist'
|
140
|
+
require_relative './agent/status'
|
301
141
|
|
302
142
|
|
303
143
|
# Commands for Manipulating Agent Definitions
|
304
144
|
# ----------------------------------------------------------------------------
|
305
145
|
|
306
146
|
require_relative './agent/add'
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
"Update an existing agent"
|
311
|
-
|
312
|
-
include_options groups: [:pattern, :write, :respond_with_agents]
|
313
|
-
|
314
|
-
def update pattern, *cmd_template
|
315
|
-
agent = find_only! pattern
|
316
|
-
|
317
|
-
new_agent = agent.update \
|
318
|
-
cmd_template: cmd_template,
|
319
|
-
**option_kwds( groups: :write )
|
320
|
-
|
321
|
-
logger.info "Agent `#{ agent.label }` updated"
|
322
|
-
|
323
|
-
respond agent
|
324
|
-
end
|
325
|
-
|
326
|
-
|
327
|
-
desc "rm PATTERN [OPTIONS]",
|
328
|
-
"Remove (uninstall, delete) a agent"
|
329
|
-
|
330
|
-
map remove: :rm
|
331
|
-
|
332
|
-
include_options groups: [:pattern, :multi]
|
333
|
-
|
334
|
-
option :logs,
|
335
|
-
desc: "Remove logs too",
|
336
|
-
type: :boolean,
|
337
|
-
default: false
|
338
|
-
|
339
|
-
def rm pattern
|
340
|
-
kwds = option_kwds :logs
|
341
|
-
find_multi!( pattern ).each { |agent| agent.remove **kwds }
|
342
|
-
end
|
343
|
-
|
147
|
+
require_relative './agent/update'
|
148
|
+
require_relative './agent/rm'
|
149
|
+
|
344
150
|
|
345
151
|
# Commands for Manipulating Agent State
|
346
152
|
# --------------------------------------------------------------------------
|
347
153
|
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
include_options groups: [ :pattern, :multi, :start ]
|
352
|
-
|
353
|
-
def start pattern
|
354
|
-
kwds = option_kwds :load, :force, :enable
|
355
|
-
find_multi!( pattern ).each { |agent| agent.start **kwds }
|
356
|
-
end
|
357
|
-
|
358
|
-
|
359
|
-
desc "stop PATTERN [OPTIONS]",
|
360
|
-
"Stop an agent"
|
361
|
-
|
362
|
-
include_options groups: [:pattern, :multi, :stop]
|
363
|
-
|
364
|
-
option :unload,
|
365
|
-
desc: "Unload the agent from `launchd` after stopping",
|
366
|
-
type: :boolean,
|
367
|
-
default: true
|
368
|
-
|
369
|
-
option :disable,
|
370
|
-
desc: "Set `launchd` *Disabled* key to `true`",
|
371
|
-
type: :boolean,
|
372
|
-
default: false
|
373
|
-
|
374
|
-
def stop pattern
|
375
|
-
kwds = option_kwds :unload, :disable
|
376
|
-
find_multi!( pattern ).each { |agent| agent.stop **kwds }
|
377
|
-
end
|
378
|
-
|
379
|
-
|
380
|
-
desc "restart PATTERN [OPTIONS]",
|
381
|
-
"Restart an agent"
|
382
|
-
|
383
|
-
include_options groups: [:pattern, :multi, :stop]
|
384
|
-
|
385
|
-
option :reload,
|
386
|
-
desc: "Unload and reload the agent in `launchd`",
|
387
|
-
type: :boolean,
|
388
|
-
default: true
|
389
|
-
|
390
|
-
option :force,
|
391
|
-
desc: "Force loading of agent even if it's disabled",
|
392
|
-
type: :boolean,
|
393
|
-
default: false
|
394
|
-
|
395
|
-
option :enable,
|
396
|
-
desc: "Set `launchd` *Disabled* key to `false`",
|
397
|
-
type: :boolean,
|
398
|
-
default: false
|
399
|
-
|
400
|
-
def restart pattern
|
401
|
-
kwds = option_kwds :reload, :force, :enable
|
402
|
-
find_multi!( pattern ).each { |agent| agent.restart **kwds }
|
403
|
-
end
|
154
|
+
require_relative './agent/start'
|
155
|
+
require_relative './agent/stop'
|
156
|
+
require_relative './agent/restart'
|
404
157
|
|
405
158
|
|
406
159
|
# Assorted Other Commands
|
407
160
|
# ----------------------------------------------------------------------------
|
408
161
|
|
409
|
-
|
410
|
-
|
162
|
+
require_relative './agent/open'
|
163
|
+
require_relative './agent/truncate_logs'
|
164
|
+
require_relative './agent/tail'
|
411
165
|
|
412
|
-
|
166
|
+
end # class Agent
|
413
167
|
|
414
|
-
# include_shared groups: [ :pattern, :multi, :start ]
|
415
|
-
|
416
|
-
arg :pattern,
|
417
|
-
desc: "Label or workdir pattern to find agent(s)",
|
418
|
-
type: :string,
|
419
|
-
required: true,
|
420
|
-
complete: ->( klass:, **etc ) { klass.agent_class.labels.to_a }
|
421
168
|
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
find_multi!( pattern ).each do |agent|
|
429
|
-
if options[:start] && agent.stopped?
|
430
|
-
agent.start **option_kwds( groups: :start )
|
431
|
-
end
|
432
|
-
|
433
|
-
Cmds! "open %s", agent.url
|
434
|
-
|
435
|
-
logger.info "Opened agent `#{ agent.label }` at #{ agent.url }"
|
436
|
-
end
|
437
|
-
end
|
438
|
-
|
439
|
-
|
440
|
-
desc 'truncate_logs PATTERN',
|
441
|
-
"Truncate agent log file(s)."
|
442
|
-
|
443
|
-
include_options groups: [:pattern, :multi]
|
444
|
-
|
445
|
-
option :restart,
|
446
|
-
desc: "Restart the agent after truncation",
|
447
|
-
type: :boolean,
|
448
|
-
default: true
|
449
|
-
|
450
|
-
def truncate_logs pattern
|
451
|
-
find_multi!( pattern ).each do |agent|
|
452
|
-
log_paths = [agent.out_path, agent.err_path].compact.uniq
|
453
|
-
|
454
|
-
unless log_paths.empty?
|
455
|
-
restart = options[:restart] && agent.running?
|
456
|
-
|
457
|
-
agent.stop if restart
|
458
|
-
|
459
|
-
log_paths.each do |log_path|
|
460
|
-
begin
|
461
|
-
log_path.open( 'w' ) { |f| f.truncate 0 }
|
462
|
-
rescue Exception => error
|
463
|
-
logger.error "Failed to truncate #{ log_path }", error
|
464
|
-
else
|
465
|
-
logger.info "Truncated",
|
466
|
-
'file' => log_path.to_s,
|
467
|
-
'agent.label' => agent.label
|
468
|
-
end
|
469
|
-
end # each log_path
|
470
|
-
|
471
|
-
agent.start if restart
|
472
|
-
end # unless log_paths.empty?
|
473
|
-
end # each agent
|
474
|
-
end # #truncate_logs
|
475
|
-
|
476
|
-
|
477
|
-
desc 'tail [OPTIONS] PATTERN [-- TAIL_OPTIONS]',
|
478
|
-
"Tail agent logs"
|
479
|
-
|
480
|
-
include_options groups: :pattern
|
481
|
-
|
482
|
-
option :stream,
|
483
|
-
desc: "Stream to tail. May omit if uses single log file.",
|
484
|
-
aliases: ['-s'],
|
485
|
-
type: :string,
|
486
|
-
enum: ['out', 'err']
|
487
|
-
|
488
|
-
option :follow,
|
489
|
-
desc: "Run with `tail -F`",
|
490
|
-
aliases: [ '-f' ],
|
491
|
-
type: :boolean
|
492
|
-
|
493
|
-
def tail pattern, *tail_options
|
494
|
-
agent = find_only! pattern
|
495
|
-
|
496
|
-
path = case options[:stream]
|
497
|
-
when nil
|
498
|
-
paths = agent.log_paths
|
499
|
-
|
500
|
-
unless paths.length == 1
|
501
|
-
raise Thor::RequiredArgumentMissingError.new binding.erb <<~END
|
502
|
-
Agent `<%= agent.label %>` has multiple log files.
|
503
|
-
|
504
|
-
out: <%= agent.out_path.to_s %>
|
505
|
-
err: <%= agent.err_path.to_s %>
|
506
|
-
|
507
|
-
Must specify one via the `--stream` option.
|
508
|
-
|
509
|
-
END
|
510
|
-
end
|
511
|
-
|
512
|
-
paths[0]
|
513
|
-
|
514
|
-
when 'out'
|
515
|
-
agent.out_path
|
516
|
-
|
517
|
-
when 'err'
|
518
|
-
agent.err_path
|
519
|
-
|
520
|
-
else
|
521
|
-
raise "WTF"
|
522
|
-
end
|
523
|
-
|
524
|
-
cmd = ['tail']
|
525
|
-
cmd += ['-F'] if options[:follow]
|
526
|
-
|
527
|
-
exec *cmd, *tail_options, path.to_s
|
528
|
-
end # #tail
|
529
|
-
|
530
|
-
end # class Locd::CLI::Command::Agent
|
169
|
+
# /Namespace
|
170
|
+
# =======================================================================
|
171
|
+
|
172
|
+
end # module Command
|
173
|
+
end # module CLI
|
174
|
+
end # module Locd
|