locd 0.1.9 → 0.1.10
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/.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
|