locd 0.1.12 → 0.1.13
Sign up to get free protection for your applications and to get access to all the features.
- 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
|