locd 0.1.9 → 0.1.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.vscode/settings.json +2 -0
- data/VERSION +1 -1
- data/config/default.yml +13 -0
- data/exe/locd +1 -1
- data/lib/locd/agent.rb +43 -14
- data/lib/locd/agent/site.rb +37 -1
- data/lib/locd/cli/command.rb +0 -2
- data/lib/locd/cli/command/agent.rb +35 -10
- data/lib/locd/cli/command/agent/add.rb +3 -0
- data/lib/locd/cli/command/base.rb +28 -7
- data/lib/locd/cli/command/main.rb +48 -26
- data/lib/locd/config.rb +128 -36
- data/lib/locd/config/types.rb +140 -0
- data/locd.gemspec +3 -3
- metadata +8 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e87ade2d470c9595ac40d6174268ba79851940a
|
4
|
+
data.tar.gz: 50d4c39c62e969c2f1bf42f2eeaa35a1a58f7bd1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b217a8559f55fe3f3779a58fcb5e519642002841c59312b882b0ed4e7bb32c051da739916c65a1a6f620ef346426ab62188c2be423bb244aaff4941bcf1d9ca1
|
7
|
+
data.tar.gz: 3498a6255d0aefc564e03f4854e4f8b75fc6b639d1a00b28a38efc8ea43f645bb4e1b528e8659e773f0a211e24e761b084bebc9501b3729625849441ef560c14
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.10
|
data/config/default.yml
CHANGED
@@ -2,6 +2,18 @@ locd:
|
|
2
2
|
home: ~/.locd
|
3
3
|
bin: locd
|
4
4
|
|
5
|
+
cli:
|
6
|
+
log:
|
7
|
+
level: info
|
8
|
+
application: Locd
|
9
|
+
dest: $stderr
|
10
|
+
|
11
|
+
bash_comp:
|
12
|
+
log:
|
13
|
+
level: warn
|
14
|
+
dest: //tmp/bash_comp.log
|
15
|
+
# /CLI
|
16
|
+
|
5
17
|
namespace:
|
6
18
|
label: com.nrser.locd
|
7
19
|
env: LOCD
|
@@ -22,3 +34,4 @@ locd:
|
|
22
34
|
ports:
|
23
35
|
start: 55000
|
24
36
|
end: 56000
|
37
|
+
|
data/exe/locd
CHANGED
@@ -6,7 +6,7 @@ require 'locd'
|
|
6
6
|
|
7
7
|
# Setup logging *before* including {Locd::CLI} so that we can get
|
8
8
|
# trace/debug output from that setup if enabled via ENV vars
|
9
|
-
NRSER::Log.setup_for_cli!
|
9
|
+
NRSER::Log.setup_for_cli! Locd.config.cli_log_config
|
10
10
|
|
11
11
|
# Logger for this file
|
12
12
|
logger = NRSER::Log[__FILE__]
|
data/lib/locd/agent.rb
CHANGED
@@ -10,6 +10,8 @@
|
|
10
10
|
# -----------------------------------------------------------------------
|
11
11
|
require 'plist'
|
12
12
|
require 'fileutils'
|
13
|
+
require 'nrser'
|
14
|
+
require 'nrser/props/immutable/hash'
|
13
15
|
|
14
16
|
# Project / Package
|
15
17
|
# -----------------------------------------------------------------------
|
@@ -47,6 +49,40 @@ class Locd::Agent
|
|
47
49
|
TO_H_NAMES = Hamster::SortedSet[:label, :path, :plist, :status]
|
48
50
|
|
49
51
|
|
52
|
+
# Structs
|
53
|
+
# ============================================================================
|
54
|
+
|
55
|
+
class Status < Hamster::Hash
|
56
|
+
include NRSER::Props::Immutable::Hash
|
57
|
+
|
58
|
+
# @!attribute [r] loaded
|
59
|
+
# `true` if the agent is loaded in launchd.
|
60
|
+
#
|
61
|
+
# @return [Boolean]
|
62
|
+
#
|
63
|
+
prop :loaded, type: t.bool
|
64
|
+
|
65
|
+
# @!attribute [r] running
|
66
|
+
# `true` if the agent is currently running.
|
67
|
+
#
|
68
|
+
# @return [Boolean]
|
69
|
+
prop :running, type: t.bool
|
70
|
+
|
71
|
+
# @!attribute [r] pid
|
72
|
+
# The process ID the agent is running as (if any).
|
73
|
+
#
|
74
|
+
# @return [Integer?]
|
75
|
+
prop :pid, type: t.non_neg_int?
|
76
|
+
|
77
|
+
# @!attribute [r] last_exit_code
|
78
|
+
# The last status code the agent exited with, if any is available.
|
79
|
+
#
|
80
|
+
# @return [Integer?]
|
81
|
+
prop :last_exit_code, type: t.int?
|
82
|
+
|
83
|
+
end # class Status
|
84
|
+
|
85
|
+
|
50
86
|
# Mixins
|
51
87
|
# ==========================================================================
|
52
88
|
|
@@ -697,8 +733,7 @@ class Locd::Agent
|
|
697
733
|
def initialize plist:, path:
|
698
734
|
@path = path.to_pn.expand_path
|
699
735
|
@plist = plist
|
700
|
-
@status =
|
701
|
-
|
736
|
+
@status = nil
|
702
737
|
|
703
738
|
# Sanity check...
|
704
739
|
|
@@ -861,31 +896,25 @@ class Locd::Agent
|
|
861
896
|
# When `true`, will re-read from `launchd` (and cache results)
|
862
897
|
# before returning.
|
863
898
|
#
|
864
|
-
# @return [
|
865
|
-
# When `launchd` has a status entry for the agent.
|
866
|
-
#
|
867
|
-
# @return [nil]
|
868
|
-
# When `launchd` doesn't have a status entry for the agent.
|
899
|
+
# @return [Status]
|
869
900
|
#
|
870
901
|
def status refresh: false
|
871
|
-
if refresh || @status
|
902
|
+
if refresh || @status.nil?
|
872
903
|
raw_status = Locd::Launchctl.status[label]
|
873
904
|
|
874
905
|
# Happens when the agent is not loaded
|
875
906
|
@status = if raw_status.nil?
|
876
|
-
|
907
|
+
Status.new \
|
877
908
|
loaded: false,
|
878
909
|
running: false,
|
879
910
|
pid: nil,
|
880
|
-
last_exit_code: nil
|
881
|
-
}
|
911
|
+
last_exit_code: nil
|
882
912
|
else
|
883
|
-
|
913
|
+
Status.new \
|
884
914
|
loaded: true,
|
885
915
|
running: !raw_status[:pid].nil?,
|
886
916
|
pid: raw_status[:pid],
|
887
|
-
last_exit_code: raw_status[:status]
|
888
|
-
}
|
917
|
+
last_exit_code: raw_status[:status]
|
889
918
|
end
|
890
919
|
end
|
891
920
|
|
data/lib/locd/agent/site.rb
CHANGED
@@ -63,6 +63,22 @@ class Locd::Agent::Site < Locd::Agent
|
|
63
63
|
TO_H_NAMES = Locd::Agent::TO_H_NAMES.union [:port, :url]
|
64
64
|
|
65
65
|
|
66
|
+
# Structs
|
67
|
+
# ============================================================================
|
68
|
+
|
69
|
+
class Status < Locd::Agent::Status
|
70
|
+
|
71
|
+
# @!attribute [r] port
|
72
|
+
# Site backend port.
|
73
|
+
#
|
74
|
+
# @return [Integer]
|
75
|
+
#
|
76
|
+
prop :port,
|
77
|
+
type: t.pos_int
|
78
|
+
|
79
|
+
end # class Status
|
80
|
+
|
81
|
+
|
66
82
|
# Class Methods
|
67
83
|
# ==========================================================================
|
68
84
|
|
@@ -160,7 +176,7 @@ class Locd::Agent::Site < Locd::Agent
|
|
160
176
|
# Methods to read proxied and computed attributes.
|
161
177
|
#
|
162
178
|
|
163
|
-
# @return [
|
179
|
+
# @return [Integer]
|
164
180
|
# Port service runs on.
|
165
181
|
def port
|
166
182
|
config['port']
|
@@ -180,4 +196,24 @@ class Locd::Agent::Site < Locd::Agent
|
|
180
196
|
|
181
197
|
# @!endgroup Instance Methods: Attribute Readers
|
182
198
|
|
199
|
+
|
200
|
+
# @!group `launchctl` Interface Instance Methods
|
201
|
+
# ----------------------------------------------------------------------------
|
202
|
+
|
203
|
+
# The site agent's status from parsing `launchctl list`.
|
204
|
+
#
|
205
|
+
# Status is read on demand and cached on the instance.
|
206
|
+
#
|
207
|
+
# @param [Boolean] refresh:
|
208
|
+
# When `true`, will re-read from `launchd` (and cache results)
|
209
|
+
# before returning.
|
210
|
+
#
|
211
|
+
# @return [Status]
|
212
|
+
#
|
213
|
+
def status refresh: false
|
214
|
+
Status.new port: port, **super( refresh: refresh )
|
215
|
+
end
|
216
|
+
|
217
|
+
# @!endgroup `launchctl` Interface Instance Methods
|
218
|
+
|
183
219
|
end # class Locd::Launchd
|
data/lib/locd/cli/command.rb
CHANGED
@@ -101,6 +101,14 @@ class Locd::CLI::Command::Agent < Locd::CLI::Command::Base
|
|
101
101
|
# end protected
|
102
102
|
public
|
103
103
|
|
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
|
+
|
104
112
|
|
105
113
|
# Shared Options
|
106
114
|
# ============================================================================
|
@@ -242,15 +250,17 @@ class Locd::CLI::Command::Agent < Locd::CLI::Command::Base
|
|
242
250
|
# Querying
|
243
251
|
# ----------------------------------------------------------------------------
|
244
252
|
|
245
|
-
desc "ls
|
253
|
+
desc "ls",
|
246
254
|
"List agents"
|
247
255
|
|
248
256
|
map list: :ls
|
249
257
|
|
258
|
+
include_shared groups: :pattern
|
259
|
+
|
250
260
|
include_options :long,
|
251
261
|
groups: :pattern
|
252
262
|
|
253
|
-
def ls pattern = nil
|
263
|
+
def ls # pattern = nil
|
254
264
|
results = if pattern.nil?
|
255
265
|
agent_class.all
|
256
266
|
else
|
@@ -286,8 +296,7 @@ class Locd::CLI::Command::Agent < Locd::CLI::Command::Base
|
|
286
296
|
agent = find_only! pattern
|
287
297
|
respond \
|
288
298
|
label: agent.label,
|
289
|
-
|
290
|
-
status: agent.status
|
299
|
+
status: agent.status.to_h( compact: false )
|
291
300
|
end
|
292
301
|
|
293
302
|
|
@@ -397,17 +406,25 @@ class Locd::CLI::Command::Agent < Locd::CLI::Command::Base
|
|
397
406
|
# Assorted Other Commands
|
398
407
|
# ----------------------------------------------------------------------------
|
399
408
|
|
400
|
-
desc "open
|
409
|
+
desc "open [OPTIONS]",
|
401
410
|
"Open an agent's URL in the browser"
|
402
411
|
|
403
412
|
include_options groups: [ :pattern, :multi, :start ]
|
413
|
+
|
414
|
+
# include_shared groups: [ :pattern, :multi, :start ]
|
404
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
|
+
|
405
422
|
option :start,
|
406
|
-
|
407
|
-
|
408
|
-
|
423
|
+
desc: %{ Start any stopped agents before opening },
|
424
|
+
type: :boolean,
|
425
|
+
default: true
|
409
426
|
|
410
|
-
def open pattern
|
427
|
+
def open # pattern
|
411
428
|
find_multi!( pattern ).each do |agent|
|
412
429
|
if options[:start] && agent.stopped?
|
413
430
|
agent.start **option_kwds( groups: :start )
|
@@ -468,6 +485,11 @@ class Locd::CLI::Command::Agent < Locd::CLI::Command::Base
|
|
468
485
|
type: :string,
|
469
486
|
enum: ['out', 'err']
|
470
487
|
|
488
|
+
option :follow,
|
489
|
+
desc: "Run with `tail -F`",
|
490
|
+
aliases: [ '-f' ],
|
491
|
+
type: :boolean
|
492
|
+
|
471
493
|
def tail pattern, *tail_options
|
472
494
|
agent = find_only! pattern
|
473
495
|
|
@@ -499,7 +521,10 @@ class Locd::CLI::Command::Agent < Locd::CLI::Command::Base
|
|
499
521
|
raise "WTF"
|
500
522
|
end
|
501
523
|
|
502
|
-
|
524
|
+
cmd = ['tail']
|
525
|
+
cmd += ['-F'] if options[:follow]
|
526
|
+
|
527
|
+
exec *cmd, *tail_options, path.to_s
|
503
528
|
end # #tail
|
504
529
|
|
505
530
|
end # class Locd::CLI::Command::Agent
|
@@ -10,6 +10,7 @@ require 'shellwords'
|
|
10
10
|
# Deps
|
11
11
|
# -----------------------------------------------------------------------
|
12
12
|
require 'thor'
|
13
|
+
require 'nrser/labs/i8'
|
13
14
|
|
14
15
|
# Project / Package
|
15
16
|
# -----------------------------------------------------------------------
|
@@ -22,6 +23,14 @@ require 'nrser/refinements/types'
|
|
22
23
|
using NRSER::Types
|
23
24
|
|
24
25
|
|
26
|
+
# Namespace
|
27
|
+
# ========================================================================
|
28
|
+
|
29
|
+
module Locd
|
30
|
+
module CLI
|
31
|
+
module Command
|
32
|
+
|
33
|
+
|
25
34
|
# Definitions
|
26
35
|
# =======================================================================
|
27
36
|
|
@@ -31,13 +40,16 @@ using NRSER::Types
|
|
31
40
|
#
|
32
41
|
# @see http://whatisthor.com/
|
33
42
|
#
|
34
|
-
class
|
43
|
+
class Base < Thor
|
44
|
+
|
45
|
+
# Instance Methods
|
46
|
+
# ========================================================================
|
35
47
|
|
36
|
-
# Helpers
|
37
|
-
# ============================================================================
|
38
|
-
#
|
39
48
|
protected
|
40
49
|
|
50
|
+
# @!group Helper Instance Methods
|
51
|
+
# ========================================================================
|
52
|
+
|
41
53
|
# Swap `$stdout` for a {StringIO}, call `block`, swap original `$stdout`
|
42
54
|
# back in and return the string contents.
|
43
55
|
#
|
@@ -237,7 +249,16 @@ class Locd::CLI::Command::Base < Thor
|
|
237
249
|
end
|
238
250
|
end
|
239
251
|
|
240
|
-
|
241
|
-
|
252
|
+
# @!endgroup Helper Instance Methods # ***********************************
|
253
|
+
|
254
|
+
public # end protected *****************************************************
|
242
255
|
|
243
|
-
end #
|
256
|
+
end # class Base
|
257
|
+
|
258
|
+
|
259
|
+
# /Namespace
|
260
|
+
# ========================================================================
|
261
|
+
|
262
|
+
end # module Command
|
263
|
+
end # module CLI
|
264
|
+
end # module Locd
|
@@ -8,6 +8,7 @@
|
|
8
8
|
|
9
9
|
# Deps
|
10
10
|
# -----------------------------------------------------------------------
|
11
|
+
require 'thor/completion/bash'
|
11
12
|
|
12
13
|
# Project / Package
|
13
14
|
# -----------------------------------------------------------------------
|
@@ -20,14 +21,22 @@ require 'nrser/refinements/types'
|
|
20
21
|
using NRSER::Types
|
21
22
|
|
22
23
|
|
24
|
+
# Namespace
|
25
|
+
# ========================================================================
|
26
|
+
|
27
|
+
module Locd
|
28
|
+
module CLI
|
29
|
+
module Command
|
30
|
+
|
31
|
+
|
23
32
|
# Definitions
|
24
33
|
# =======================================================================
|
25
34
|
|
26
|
-
# CLI interface using the `
|
35
|
+
# CLI interface using the Thor via my `atli` fork.
|
27
36
|
#
|
28
37
|
# @see http://whatisthor.com/
|
29
38
|
#
|
30
|
-
class
|
39
|
+
class Main < Base
|
31
40
|
|
32
41
|
# Constants
|
33
42
|
# ============================================================================
|
@@ -39,6 +48,9 @@ class Locd::CLI::Command::Main < Locd::CLI::Command::Base
|
|
39
48
|
#
|
40
49
|
LOG_LEVEL_STRINGS = SemanticLogger::LEVELS.map { |sym| sym.to_s.freeze }
|
41
50
|
|
51
|
+
|
52
|
+
include Thor::Completion::Bash
|
53
|
+
|
42
54
|
|
43
55
|
# Global (Class-Level) Options
|
44
56
|
# ============================================================================
|
@@ -163,6 +175,8 @@ class Locd::CLI::Command::Main < Locd::CLI::Command::Base
|
|
163
175
|
# Commands
|
164
176
|
# ============================================================================
|
165
177
|
|
178
|
+
# add_bash_completion_commands!
|
179
|
+
|
166
180
|
# Querying
|
167
181
|
# ----------------------------------------------------------------------------
|
168
182
|
|
@@ -187,34 +201,42 @@ class Locd::CLI::Command::Main < Locd::CLI::Command::Base
|
|
187
201
|
# Sub-Commands
|
188
202
|
# ============================================================================
|
189
203
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
Locd::CLI::Command::Site
|
204
|
+
subcommand 'agent',
|
205
|
+
Locd::CLI::Command::Agent,
|
206
|
+
desc: 'Deal with agents in general (all types).'
|
194
207
|
|
195
208
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
Locd::CLI::Command::Job
|
209
|
+
subcommand 'site',
|
210
|
+
Locd::CLI::Command::Site,
|
211
|
+
desc: 'Deal with site agents.'
|
200
212
|
|
201
213
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
Locd::CLI::Command::Proxy
|
206
|
-
|
207
|
-
|
208
|
-
desc 'rotate-logs SUBCOMMAND...',
|
209
|
-
'Deal with the log rotation job'
|
210
|
-
# map :'rotate-logs' => :rotate_logs
|
211
|
-
subcommand 'rotate_logs',
|
212
|
-
Locd::CLI::Command::RotateLogs
|
214
|
+
subcommand 'job',
|
215
|
+
Locd::CLI::Command::Job,
|
216
|
+
desc: "Deal with job agents."
|
213
217
|
|
214
218
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
+
subcommand 'proxy',
|
220
|
+
Locd::CLI::Command::Proxy,
|
221
|
+
desc: 'Deal with the HTTP proxy that routes requests to servers'
|
222
|
+
|
223
|
+
|
224
|
+
# subcommand 'rotate-logs',
|
225
|
+
subcommand 'rotate_logs',
|
226
|
+
Locd::CLI::Command::RotateLogs,
|
227
|
+
desc: 'Deal with the log rotation job'
|
228
|
+
|
229
|
+
|
230
|
+
subcommand 'project',
|
231
|
+
Locd::CLI::Command::Project,
|
232
|
+
desc: 'Manage Agent definitions for projects'
|
219
233
|
|
220
|
-
end # class
|
234
|
+
end # class Main
|
235
|
+
|
236
|
+
|
237
|
+
# /Namespace
|
238
|
+
# ========================================================================
|
239
|
+
|
240
|
+
end # module Command
|
241
|
+
end # module CLI
|
242
|
+
end # module Locd
|
data/lib/locd/config.rb
CHANGED
@@ -17,6 +17,8 @@ require 'nrser/core_ext/object'
|
|
17
17
|
# Project / Package
|
18
18
|
# -----------------------------------------------------------------------
|
19
19
|
|
20
|
+
require_relative './config/types'
|
21
|
+
|
20
22
|
|
21
23
|
# Refinements
|
22
24
|
# =======================================================================
|
@@ -25,10 +27,15 @@ require 'nrser/refinements/types'
|
|
25
27
|
using NRSER::Types
|
26
28
|
|
27
29
|
|
28
|
-
#
|
29
|
-
#
|
30
|
-
|
31
|
-
#
|
30
|
+
# A hash-like container providing access to a layered tree of config values
|
31
|
+
# sourced from `YAML` files and `ENV` vars.
|
32
|
+
#
|
33
|
+
#
|
34
|
+
# Keys
|
35
|
+
# ----------------------------------------------------------------------------
|
36
|
+
#
|
37
|
+
# Config keys are arrays of strings that
|
38
|
+
#
|
32
39
|
class Locd::Config
|
33
40
|
|
34
41
|
# Constants
|
@@ -80,14 +87,14 @@ class Locd::Config
|
|
80
87
|
|
81
88
|
@from_files = {}
|
82
89
|
|
83
|
-
load_file default_config_path
|
90
|
+
load_file! default_config_path
|
84
91
|
|
85
92
|
if user_config_path.exist?
|
86
|
-
load_file user_config_path
|
93
|
+
load_file! user_config_path
|
87
94
|
end
|
88
95
|
|
89
96
|
if dev_config_path && dev_config_path.exist?
|
90
|
-
load_file dev_config_path
|
97
|
+
load_file! dev_config_path
|
91
98
|
end
|
92
99
|
end # #initialize
|
93
100
|
|
@@ -99,46 +106,39 @@ class Locd::Config
|
|
99
106
|
# ========================================================================
|
100
107
|
|
101
108
|
|
102
|
-
#
|
109
|
+
# Load a `YAML` config file into the config.
|
103
110
|
#
|
104
|
-
# @param [
|
105
|
-
#
|
111
|
+
# @param [Pathname | String] path
|
112
|
+
# Path to file.
|
106
113
|
#
|
107
|
-
# @return [
|
108
|
-
# @todo Document return value.
|
114
|
+
# @return [nil]
|
109
115
|
#
|
110
|
-
def load_file path
|
111
|
-
bnd = binding
|
112
|
-
|
116
|
+
def load_file! path
|
113
117
|
path.
|
114
118
|
to_pn.
|
115
119
|
read.
|
116
|
-
thru { |contents|
|
117
|
-
YAML.load contents
|
118
|
-
}.
|
119
|
-
map_leaves { |path, leaf|
|
120
|
-
case leaf
|
121
|
-
when String
|
122
|
-
bnd.erb leaf
|
123
|
-
else
|
124
|
-
leaf
|
125
|
-
end
|
126
|
-
}.
|
127
|
-
thru { |tree|
|
128
|
-
@from_files.deep_merge! tree
|
129
|
-
}
|
120
|
+
thru { |contents| @from_files.deep_merge! YAML.load( contents ) }
|
130
121
|
|
131
122
|
nil
|
132
|
-
end # #load_file
|
123
|
+
end # #load_file!
|
133
124
|
|
134
125
|
public # end protected ***************************************************
|
135
126
|
|
136
127
|
|
137
|
-
def key_path_for *key
|
128
|
+
def self.key_path_for *key
|
138
129
|
key.flat_map { |k| k.to_s.split KEY_SEPARATOR }
|
139
130
|
end
|
140
131
|
|
132
|
+
def key_path_for *key
|
133
|
+
self.class.key_path_for *key
|
134
|
+
end
|
141
135
|
|
136
|
+
|
137
|
+
# Get a value from the config files only.
|
138
|
+
#
|
139
|
+
# @param [Array<#to_s>] *key
|
140
|
+
# The key to lookup.
|
141
|
+
#
|
142
142
|
def from_files *key, type: nil
|
143
143
|
key_path = key_path_for *key
|
144
144
|
value = @from_files.dig Locd::GEM_NAME, *key_path
|
@@ -146,7 +146,7 @@ class Locd::Config
|
|
146
146
|
if value.nil?
|
147
147
|
nil
|
148
148
|
else
|
149
|
-
parse_and_check value, type: type
|
149
|
+
parse_and_check key, value, type: type
|
150
150
|
end
|
151
151
|
end
|
152
152
|
|
@@ -159,13 +159,15 @@ class Locd::Config
|
|
159
159
|
end
|
160
160
|
|
161
161
|
|
162
|
-
def parse_and_check value, type: nil
|
162
|
+
def parse_and_check key, value, type: nil
|
163
|
+
type = Types.for_key( *key ) if type.nil?
|
164
|
+
|
163
165
|
return value if type.nil?
|
164
166
|
|
165
167
|
if value.is_a?( String ) && type.has_from_s?
|
166
168
|
type.from_s value
|
167
169
|
else
|
168
|
-
type.check value
|
170
|
+
type.check! value
|
169
171
|
end
|
170
172
|
end
|
171
173
|
|
@@ -179,7 +181,7 @@ class Locd::Config
|
|
179
181
|
when nil, ''
|
180
182
|
nil
|
181
183
|
else
|
182
|
-
parse_and_check value, type: type
|
184
|
+
parse_and_check key, value, type: type
|
183
185
|
end
|
184
186
|
end
|
185
187
|
|
@@ -191,12 +193,46 @@ class Locd::Config
|
|
191
193
|
files_value = from_files *key, type: type
|
192
194
|
return files_value unless files_value.nil?
|
193
195
|
|
194
|
-
parse_and_check default, type: type
|
196
|
+
parse_and_check key, default, type: type
|
195
197
|
end
|
196
198
|
|
197
199
|
alias_method :[], :get
|
198
200
|
|
199
201
|
|
202
|
+
def set *key, value, type: nil
|
203
|
+
value_str = value.to_s
|
204
|
+
|
205
|
+
parse_and_check key, value_str, type: type
|
206
|
+
|
207
|
+
ENV[ env_key_for( *key ) ] = value_str
|
208
|
+
end
|
209
|
+
|
210
|
+
|
211
|
+
# Proxy to {#set} orthogonal to {#[]} / {#get} (though in this case we
|
212
|
+
# need to do a little more work than an alias on account of how `#[]=`
|
213
|
+
# handled keyword args).
|
214
|
+
#
|
215
|
+
# @example Single string key
|
216
|
+
# Locd.config[ 'cli.bash_comp.log.level' ] = :debug
|
217
|
+
#
|
218
|
+
# @example List key
|
219
|
+
# Locd.config[ :cli, :bash_comp, :log, :level ] = :debug
|
220
|
+
#
|
221
|
+
# @example Checking the type
|
222
|
+
# Locd.config[ 'home', type: t.abs_path ] = user_input
|
223
|
+
#
|
224
|
+
def []= *key, value
|
225
|
+
if Hash === key[-1]
|
226
|
+
kwds = key[-1]
|
227
|
+
key = key[0..-2]
|
228
|
+
else
|
229
|
+
kwds = {}
|
230
|
+
end
|
231
|
+
|
232
|
+
set *key, value, **kwds
|
233
|
+
end
|
234
|
+
|
235
|
+
|
200
236
|
def to_h
|
201
237
|
@from_files.merge \
|
202
238
|
"locd" => @from_files["locd"].map_leaves { |key_path, value|
|
@@ -237,4 +273,60 @@ class Locd::Config
|
|
237
273
|
home_dir / 'config.yml'
|
238
274
|
end
|
239
275
|
|
276
|
+
|
277
|
+
# Does `ARGV` look like we're executing Bash completion?
|
278
|
+
#
|
279
|
+
# We want to change how we're logging during Bash completion runs.
|
280
|
+
#
|
281
|
+
# @return [Boolean]
|
282
|
+
#
|
283
|
+
def cli_ARGV_looks_like_bash_comp?
|
284
|
+
ARGV[0] == 'bash-complete'
|
285
|
+
end
|
286
|
+
|
287
|
+
|
288
|
+
# Level to log at when CLI'ing.
|
289
|
+
#
|
290
|
+
# @return [Symbol]
|
291
|
+
# One of {SemanticLogger::LEVELS}.
|
292
|
+
#
|
293
|
+
def cli_log_level
|
294
|
+
get( cli_ARGV_looks_like_bash_comp? ? 'bash_comp.log.level' :
|
295
|
+
'cli.log.level' )
|
296
|
+
end
|
297
|
+
|
298
|
+
|
299
|
+
# @return [$stderr]
|
300
|
+
#
|
301
|
+
def cli_log_dest
|
302
|
+
dest = if cli_ARGV_looks_like_bash_comp?
|
303
|
+
get 'cli.bash_comp.log.dest'
|
304
|
+
else
|
305
|
+
get 'cli.log.dest'
|
306
|
+
end
|
307
|
+
|
308
|
+
{
|
309
|
+
**( IO === dest ? { io: dest } : { file_name: dest.to_s } ),
|
310
|
+
formatter: NRSER::Log::Formatters::Color.new,
|
311
|
+
}
|
312
|
+
end
|
313
|
+
|
314
|
+
|
315
|
+
# Get the logging config, taking account of the Bash completion environment.
|
316
|
+
#
|
317
|
+
# Output from this
|
318
|
+
#
|
319
|
+
# @return [Hash<Symbol, ]
|
320
|
+
# @todo Document return value.
|
321
|
+
#
|
322
|
+
def cli_log_config
|
323
|
+
{
|
324
|
+
application: get( 'cli.log.application' ),
|
325
|
+
level: cli_log_level,
|
326
|
+
dest: cli_log_dest,
|
327
|
+
sync: true
|
328
|
+
}
|
329
|
+
end # #cli_log_dest
|
330
|
+
|
331
|
+
|
240
332
|
end # class Locd::Config
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
|
5
|
+
# Requirements
|
6
|
+
# ========================================================================
|
7
|
+
|
8
|
+
# Stdlib
|
9
|
+
# ------------------------------------------------------------------------
|
10
|
+
|
11
|
+
# Deps
|
12
|
+
# ------------------------------------------------------------------------
|
13
|
+
|
14
|
+
require 'nrser/labs/i8'
|
15
|
+
|
16
|
+
# Using log system types, which are not loaded along with it to avoid
|
17
|
+
# dependencies.
|
18
|
+
require 'nrser/log/types'
|
19
|
+
|
20
|
+
# Project / Package
|
21
|
+
# ------------------------------------------------------------------------
|
22
|
+
|
23
|
+
|
24
|
+
# Refinements
|
25
|
+
# =======================================================================
|
26
|
+
|
27
|
+
require 'nrser/refinements/types'
|
28
|
+
using NRSER::Types
|
29
|
+
|
30
|
+
|
31
|
+
# Namespace
|
32
|
+
# =======================================================================
|
33
|
+
|
34
|
+
module Locd
|
35
|
+
class Config
|
36
|
+
|
37
|
+
|
38
|
+
# Definitions
|
39
|
+
# =======================================================================
|
40
|
+
|
41
|
+
module Types
|
42
|
+
|
43
|
+
# Mixins
|
44
|
+
# ========================================================================
|
45
|
+
|
46
|
+
# Get {NRSER::Types::Factory.def_factory}
|
47
|
+
extend t::Factory
|
48
|
+
|
49
|
+
|
50
|
+
# Class Methods
|
51
|
+
# ========================================================================
|
52
|
+
|
53
|
+
# A tree representing config key paths to the types they need to be.
|
54
|
+
#
|
55
|
+
# Computed on first call and cached after that as it needs the type
|
56
|
+
# factories below.
|
57
|
+
#
|
58
|
+
# @return [Hamster::Hash]
|
59
|
+
#
|
60
|
+
def self.by_key
|
61
|
+
# Got sick of writing "Hamster::Hash[...]"... "I8" <=> "Immutable"
|
62
|
+
@by_key ||= I8[
|
63
|
+
'home' => config_path,
|
64
|
+
'bin' => ( t.when( 'locd' ) | config_path ),
|
65
|
+
|
66
|
+
'cli' => I8[
|
67
|
+
'log' => I8[
|
68
|
+
'application' => t.non_empty_str,
|
69
|
+
'level' => NRSER::Log::Types.level?,
|
70
|
+
'dest' => ( NRSER::Log::Types.stdio | config_path ),
|
71
|
+
],
|
72
|
+
|
73
|
+
'bash_comp' => I8[
|
74
|
+
'log' => I8[
|
75
|
+
'level' => NRSER::Log::Types.level,
|
76
|
+
'dest' => config_path,
|
77
|
+
],
|
78
|
+
]
|
79
|
+
]
|
80
|
+
]
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
# Dig in to {BY_KEY} and see if it has a type for a `key`.
|
85
|
+
#
|
86
|
+
# @param [Array]
|
87
|
+
#
|
88
|
+
# @return [NRSER::Types::Type?]
|
89
|
+
#
|
90
|
+
def self.for_key *key
|
91
|
+
by_key.dig *Locd::Config.key_path_for( *key )
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
# @!group Type Factory Class Methods
|
96
|
+
# --------------------------------------------------------------------------
|
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|
|
111
|
+
begin
|
112
|
+
false == path.
|
113
|
+
to_pn.
|
114
|
+
relative_path_from( Locd::ROOT ).
|
115
|
+
start_with?( '..' + File::SEPARATOR )
|
116
|
+
rescue StandardError => error
|
117
|
+
false
|
118
|
+
end
|
119
|
+
}
|
120
|
+
end # def_factory :package_path
|
121
|
+
|
122
|
+
|
123
|
+
def_factory :config_path do |name: 'ConfigPath', **options|
|
124
|
+
t.or \
|
125
|
+
package_path,
|
126
|
+
t.abs_path,
|
127
|
+
name: name,
|
128
|
+
**options
|
129
|
+
end # def_factory :config_path
|
130
|
+
|
131
|
+
# @!endgroup Type Factory Class Methods # **********************************
|
132
|
+
|
133
|
+
end # module Types
|
134
|
+
|
135
|
+
|
136
|
+
# /Namespace
|
137
|
+
# =======================================================================
|
138
|
+
|
139
|
+
end # class Config
|
140
|
+
end # module Locd
|
data/locd.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["nrser"]
|
10
10
|
spec.email = ["neil@ztkae.com"]
|
11
11
|
|
12
|
-
spec.summary = %
|
12
|
+
spec.summary = %{Get loc'd out!}
|
13
13
|
# spec.description = %q{TODO: Write a longer description or delete this line.}
|
14
14
|
spec.homepage = "https://github.com/nrser/locd"
|
15
15
|
spec.license = "MIT"
|
@@ -47,7 +47,7 @@ Gem::Specification.new do |spec|
|
|
47
47
|
# ----------------------------------------------------------------------------
|
48
48
|
|
49
49
|
# My guns
|
50
|
-
spec.add_dependency "nrser", '~> 0.3.
|
50
|
+
spec.add_dependency "nrser", '~> 0.3.9'
|
51
51
|
|
52
52
|
# Used to process command templates from projects' `//dev/locd.yml` files
|
53
53
|
spec.add_dependency "cmds", ">= 0.2.10"
|
@@ -59,7 +59,7 @@ Gem::Specification.new do |spec|
|
|
59
59
|
spec.add_dependency 'plist', '~> 3.4'
|
60
60
|
|
61
61
|
# Atli, my fork of Thor for CLI interface
|
62
|
-
spec.add_dependency 'atli', '~> 0.1.
|
62
|
+
spec.add_dependency 'atli', '~> 0.1.10'
|
63
63
|
|
64
64
|
#
|
65
65
|
# spec.add_dependency 'terminal-table', '~> 1.8'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: locd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nrser
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-07-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -114,14 +114,14 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 0.3.
|
117
|
+
version: 0.3.9
|
118
118
|
type: :runtime
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 0.3.
|
124
|
+
version: 0.3.9
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: cmds
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -170,14 +170,14 @@ dependencies:
|
|
170
170
|
requirements:
|
171
171
|
- - "~>"
|
172
172
|
- !ruby/object:Gem::Version
|
173
|
-
version: 0.1.
|
173
|
+
version: 0.1.10
|
174
174
|
type: :runtime
|
175
175
|
prerelease: false
|
176
176
|
version_requirements: !ruby/object:Gem::Requirement
|
177
177
|
requirements:
|
178
178
|
- - "~>"
|
179
179
|
- !ruby/object:Gem::Version
|
180
|
-
version: 0.1.
|
180
|
+
version: 0.1.10
|
181
181
|
description:
|
182
182
|
email:
|
183
183
|
- neil@ztkae.com
|
@@ -191,6 +191,7 @@ files:
|
|
191
191
|
- ".qb-options.yml"
|
192
192
|
- ".rspec"
|
193
193
|
- ".travis.yml"
|
194
|
+
- ".vscode/settings.json"
|
194
195
|
- ".yardopts"
|
195
196
|
- Gemfile
|
196
197
|
- LICENSE.txt
|
@@ -225,6 +226,7 @@ files:
|
|
225
226
|
- lib/locd/cli/table.rb
|
226
227
|
- lib/locd/config.rb
|
227
228
|
- lib/locd/config/base.rb
|
229
|
+
- lib/locd/config/types.rb
|
228
230
|
- lib/locd/errors.rb
|
229
231
|
- lib/locd/label.rb
|
230
232
|
- lib/locd/launchctl.rb
|