locd 0.1.3
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 +7 -0
- data/.gitignore +108 -0
- data/.gitmodules +9 -0
- data/.qb-options.yml +4 -0
- data/.rspec +3 -0
- data/.travis.yml +5 -0
- data/.yardopts +7 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +72 -0
- data/Rakefile +6 -0
- data/VERSION +1 -0
- data/config/default.yml +24 -0
- data/doc/files/design/domains_and_labels.md +117 -0
- data/doc/files/topics/agents.md +16 -0
- data/doc/files/topics/launchd.md +15 -0
- data/doc/files/topics/plists.md +39 -0
- data/doc/include/plist.md +3 -0
- data/exe/locd +24 -0
- data/lib/locd.rb +75 -0
- data/lib/locd/agent.rb +1186 -0
- data/lib/locd/agent/job.rb +142 -0
- data/lib/locd/agent/proxy.rb +111 -0
- data/lib/locd/agent/rotate_logs.rb +82 -0
- data/lib/locd/agent/site.rb +174 -0
- data/lib/locd/agent/system.rb +270 -0
- data/lib/locd/cli.rb +4 -0
- data/lib/locd/cli/command.rb +9 -0
- data/lib/locd/cli/command/agent.rb +310 -0
- data/lib/locd/cli/command/base.rb +243 -0
- data/lib/locd/cli/command/job.rb +110 -0
- data/lib/locd/cli/command/main.rb +201 -0
- data/lib/locd/cli/command/proxy.rb +177 -0
- data/lib/locd/cli/command/rotate_logs.rb +152 -0
- data/lib/locd/cli/command/site.rb +47 -0
- data/lib/locd/cli/table.rb +157 -0
- data/lib/locd/config.rb +237 -0
- data/lib/locd/config/base.rb +93 -0
- data/lib/locd/errors.rb +65 -0
- data/lib/locd/label.rb +61 -0
- data/lib/locd/launchctl.rb +209 -0
- data/lib/locd/logging.rb +360 -0
- data/lib/locd/newsyslog.rb +402 -0
- data/lib/locd/pattern.rb +193 -0
- data/lib/locd/proxy.rb +272 -0
- data/lib/locd/proxymachine.rb +34 -0
- data/lib/locd/util.rb +49 -0
- data/lib/locd/version.rb +26 -0
- data/locd.gemspec +66 -0
- metadata +262 -0
@@ -0,0 +1,177 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Requirements
|
4
|
+
# =======================================================================
|
5
|
+
|
6
|
+
# Stdlib
|
7
|
+
# -----------------------------------------------------------------------
|
8
|
+
require 'shellwords'
|
9
|
+
|
10
|
+
# Deps
|
11
|
+
# -----------------------------------------------------------------------
|
12
|
+
require 'thor'
|
13
|
+
|
14
|
+
# Project / Package
|
15
|
+
# -----------------------------------------------------------------------
|
16
|
+
|
17
|
+
|
18
|
+
# Refinements
|
19
|
+
# =======================================================================
|
20
|
+
|
21
|
+
using NRSER
|
22
|
+
using NRSER::Types
|
23
|
+
|
24
|
+
|
25
|
+
# Definitions
|
26
|
+
# =======================================================================
|
27
|
+
|
28
|
+
# CLI interface using the `thor` gem.
|
29
|
+
#
|
30
|
+
# @see http://whatisthor.com/
|
31
|
+
#
|
32
|
+
class Locd::CLI::Command::Proxy < Locd::CLI::Command::Agent
|
33
|
+
|
34
|
+
|
35
|
+
# Helpers
|
36
|
+
# ============================================================================
|
37
|
+
#
|
38
|
+
|
39
|
+
def self.agent_class
|
40
|
+
Locd::Agent::Proxy
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
protected
|
45
|
+
# ========================================================================
|
46
|
+
|
47
|
+
def proxy
|
48
|
+
@proxy ||= begin
|
49
|
+
proxy = Locd::Agent::Proxy.get
|
50
|
+
|
51
|
+
if proxy.nil?
|
52
|
+
logger.error "Proxy agent plist not found",
|
53
|
+
expected_path: Locd::Agent::Proxy.plist_abs_path.to_s
|
54
|
+
|
55
|
+
logger.info "Run `locd setup` to create it."
|
56
|
+
|
57
|
+
exit 1
|
58
|
+
end
|
59
|
+
|
60
|
+
proxy
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# end protected
|
65
|
+
public
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
# Commands
|
70
|
+
# ============================================================================
|
71
|
+
|
72
|
+
desc "setup",
|
73
|
+
"Add agents that runs a command in the current directory"
|
74
|
+
include_options groups: [:write, :add, :respond_with_agents]
|
75
|
+
def setup
|
76
|
+
agent = agent_class.add **option_kwds( groups: :write )
|
77
|
+
|
78
|
+
logger.info "`#{ agent.label }` agent created."
|
79
|
+
|
80
|
+
agent.load if options[:load]
|
81
|
+
|
82
|
+
respond agent
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
desc "run",
|
87
|
+
"Run the proxy server (in the foreground)"
|
88
|
+
method_option :bind,
|
89
|
+
desc: "Address to bind the proxy server to",
|
90
|
+
aliases: ['-b', '--host', '-h'],
|
91
|
+
type: :string,
|
92
|
+
default: Locd.config[:proxy, :bind]
|
93
|
+
method_option :port,
|
94
|
+
desc: "Port to run the proxy on",
|
95
|
+
aliases: '-p',
|
96
|
+
type: :numeric,
|
97
|
+
default: Locd.config[:proxy, :port]
|
98
|
+
def run_
|
99
|
+
Locd::Proxy.serve \
|
100
|
+
bind: options[:bind],
|
101
|
+
port: options[:port]
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
desc "port",
|
106
|
+
"Get port Loc'd proxy is running on or configured for"
|
107
|
+
def port
|
108
|
+
respond Locd::Proxy.port
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
# Agent Interface
|
113
|
+
# ----------------------------------------------------------------------------
|
114
|
+
|
115
|
+
desc 'status',
|
116
|
+
'Print proxy status'
|
117
|
+
def status
|
118
|
+
respond \
|
119
|
+
label: proxy.label,
|
120
|
+
port: proxy.port,
|
121
|
+
status: proxy.status
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
desc "rm",
|
126
|
+
"Remove (uninstall, delete) the proxy agent"
|
127
|
+
map remove: :rm
|
128
|
+
def rm
|
129
|
+
proxy.remove
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
desc "plist",
|
134
|
+
"Show the proxy's launchd property list"
|
135
|
+
def plist
|
136
|
+
agent = proxy
|
137
|
+
|
138
|
+
if options[:json] || options[:yaml]
|
139
|
+
respond agent.plist
|
140
|
+
else
|
141
|
+
respond agent.path.read
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
desc "start",
|
147
|
+
"Start the proxy"
|
148
|
+
option :write,
|
149
|
+
desc: "Set `launchd` *Disabled* key to `false`",
|
150
|
+
type: :boolean
|
151
|
+
def start
|
152
|
+
proxy.start **option_kwds( :write )
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
desc "stop",
|
157
|
+
"Stop the proxy"
|
158
|
+
include_options groups: [:stop]
|
159
|
+
option :write,
|
160
|
+
desc: "Set `launchd` *Disabled* key to `true`",
|
161
|
+
type: :boolean
|
162
|
+
def stop
|
163
|
+
proxy.stop **option_kwds( :unload, groups: :stop )
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
desc "restart",
|
168
|
+
"Restart the proxy"
|
169
|
+
include_options groups: [:stop]
|
170
|
+
option :write,
|
171
|
+
desc: "Set `launchd` *Disabled* key to `false`",
|
172
|
+
type: :boolean
|
173
|
+
def restart
|
174
|
+
proxy.restart **option_kwds( :write, groups: :stop )
|
175
|
+
end
|
176
|
+
|
177
|
+
end # module Locd::CLI::Proxy
|
@@ -0,0 +1,152 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Requirements
|
4
|
+
# =======================================================================
|
5
|
+
|
6
|
+
# Stdlib
|
7
|
+
# -----------------------------------------------------------------------
|
8
|
+
require 'shellwords'
|
9
|
+
|
10
|
+
# Deps
|
11
|
+
# -----------------------------------------------------------------------
|
12
|
+
require 'thor'
|
13
|
+
|
14
|
+
# Project / Package
|
15
|
+
# -----------------------------------------------------------------------
|
16
|
+
|
17
|
+
|
18
|
+
# Refinements
|
19
|
+
# =======================================================================
|
20
|
+
|
21
|
+
using NRSER
|
22
|
+
using NRSER::Types
|
23
|
+
|
24
|
+
|
25
|
+
# Definitions
|
26
|
+
# =======================================================================
|
27
|
+
|
28
|
+
# Manage log rotation.
|
29
|
+
#
|
30
|
+
class Locd::CLI::Command::RotateLogs < Locd::CLI::Command::Agent
|
31
|
+
|
32
|
+
|
33
|
+
# Helpers
|
34
|
+
# ============================================================================
|
35
|
+
#
|
36
|
+
|
37
|
+
def self.agent_class
|
38
|
+
Locd::Agent::RotateLogs
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
protected
|
43
|
+
# ========================================================================
|
44
|
+
|
45
|
+
def agent
|
46
|
+
@agent ||= begin
|
47
|
+
agent = agent_class.get
|
48
|
+
|
49
|
+
if agent.nil?
|
50
|
+
logger.error "Agent plist not found",
|
51
|
+
expected_path: agent_class.plist_abs_path.to_s
|
52
|
+
|
53
|
+
logger.info "Run `locd setup` to create it."
|
54
|
+
|
55
|
+
exit 1
|
56
|
+
end
|
57
|
+
|
58
|
+
agent
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# end protected
|
63
|
+
public
|
64
|
+
|
65
|
+
|
66
|
+
# Commands
|
67
|
+
# ============================================================================
|
68
|
+
|
69
|
+
desc "setup",
|
70
|
+
"Add agents that runs a command in the current directory"
|
71
|
+
include_options groups: [:write, :add, :respond_with_agents]
|
72
|
+
def setup
|
73
|
+
agent = agent_class.add **option_kwds( groups: :write )
|
74
|
+
|
75
|
+
logger.info "`#{ agent.label }` agent created."
|
76
|
+
|
77
|
+
agent.load if options[:load]
|
78
|
+
|
79
|
+
respond agent
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
desc "run",
|
84
|
+
"Rotate agent logs using `newsyslog`"
|
85
|
+
def run_
|
86
|
+
Locd::Newsyslog.run_all
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
# Agent Interface
|
91
|
+
# ----------------------------------------------------------------------------
|
92
|
+
|
93
|
+
desc 'status',
|
94
|
+
'Print agent status'
|
95
|
+
def status
|
96
|
+
respond \
|
97
|
+
label: agent.label,
|
98
|
+
status: agent.status
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
desc "rm",
|
103
|
+
"Remove (uninstall, delete) the agent"
|
104
|
+
map remove: :rm
|
105
|
+
def rm
|
106
|
+
agent.remove
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
desc "plist",
|
111
|
+
"Show the agent's launchd property list"
|
112
|
+
def plist
|
113
|
+
if options[:json] || options[:yaml]
|
114
|
+
respond agent.plist
|
115
|
+
else
|
116
|
+
respond agent.path.read
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
desc "start",
|
122
|
+
"Start the agent"
|
123
|
+
option :write,
|
124
|
+
desc: "Set `launchd` *Disabled* key to `false`",
|
125
|
+
type: :boolean
|
126
|
+
def start
|
127
|
+
agent.start **option_kwds( :write )
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
desc "stop",
|
132
|
+
"Stop the agent"
|
133
|
+
include_options groups: [:stop]
|
134
|
+
option :write,
|
135
|
+
desc: "Set `launchd` *Disabled* key to `true`",
|
136
|
+
type: :boolean
|
137
|
+
def stop
|
138
|
+
agent.stop **option_kwds( :unload, groups: :stop )
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
desc "restart",
|
143
|
+
"Restart the agent"
|
144
|
+
include_options groups: [:stop]
|
145
|
+
option :write,
|
146
|
+
desc: "Set `launchd` *Disabled* key to `false`",
|
147
|
+
type: :boolean
|
148
|
+
def restart
|
149
|
+
agent.restart **option_kwds( :write, groups: :stop )
|
150
|
+
end
|
151
|
+
|
152
|
+
end # module Locd::CLI::RotateLogs
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
|
5
|
+
# Refinements
|
6
|
+
# =======================================================================
|
7
|
+
|
8
|
+
using NRSER
|
9
|
+
using NRSER::Types
|
10
|
+
|
11
|
+
|
12
|
+
# Definitions
|
13
|
+
# =======================================================================
|
14
|
+
|
15
|
+
# TODO Doc me pls
|
16
|
+
#
|
17
|
+
class Locd::CLI::Command::Site < Locd::CLI::Command::Agent
|
18
|
+
|
19
|
+
# Helpers
|
20
|
+
# ============================================================================
|
21
|
+
#
|
22
|
+
|
23
|
+
def self.agent_class
|
24
|
+
Locd::Agent::Site
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
protected
|
29
|
+
# ========================================================================
|
30
|
+
|
31
|
+
def agent_table agents
|
32
|
+
Locd::CLI::Table.build do |t|
|
33
|
+
t.col "PID", &:pid
|
34
|
+
t.col "LEC", desc: "Last Exit Code", &:last_exit_code
|
35
|
+
t.col "URL", &:url
|
36
|
+
t.col "Port", &:port
|
37
|
+
t.col "File" do |agent| agent_file agent end
|
38
|
+
|
39
|
+
t.rows agents
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# end protected
|
44
|
+
public
|
45
|
+
|
46
|
+
|
47
|
+
end # class Locd::CLI::Command::Site
|
@@ -0,0 +1,157 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Requirements
|
4
|
+
# =======================================================================
|
5
|
+
|
6
|
+
# Stdlib
|
7
|
+
# -----------------------------------------------------------------------
|
8
|
+
|
9
|
+
# Deps
|
10
|
+
# -----------------------------------------------------------------------
|
11
|
+
|
12
|
+
# Project / Package
|
13
|
+
# -----------------------------------------------------------------------
|
14
|
+
|
15
|
+
|
16
|
+
# Refinements
|
17
|
+
# =======================================================================
|
18
|
+
|
19
|
+
using NRSER
|
20
|
+
using NRSER::Types
|
21
|
+
|
22
|
+
|
23
|
+
# Definitions
|
24
|
+
# =======================================================================
|
25
|
+
|
26
|
+
#
|
27
|
+
class Locd::CLI::Table
|
28
|
+
# Unicode superscript number to use as references for columns with
|
29
|
+
# descriptions.
|
30
|
+
#
|
31
|
+
# @return [Array<String>]
|
32
|
+
#
|
33
|
+
SUPERSCRIPT_NUMBERS = [
|
34
|
+
"\u2070",
|
35
|
+
"\u00B9",
|
36
|
+
"\u00B2",
|
37
|
+
"\u00B3",
|
38
|
+
"\u2070",
|
39
|
+
"\u2074",
|
40
|
+
"\u2075",
|
41
|
+
"\u2076",
|
42
|
+
"\u2077",
|
43
|
+
"\u2078",
|
44
|
+
"\u2079",
|
45
|
+
].freeze
|
46
|
+
|
47
|
+
NULL = '␀'
|
48
|
+
|
49
|
+
|
50
|
+
# Mixins
|
51
|
+
# ============================================================================
|
52
|
+
|
53
|
+
include Enumerable
|
54
|
+
include NRSER::Ext::Enumerable
|
55
|
+
|
56
|
+
|
57
|
+
# Classes
|
58
|
+
# ============================================================================
|
59
|
+
|
60
|
+
# A column in a table.
|
61
|
+
#
|
62
|
+
class Column
|
63
|
+
attr_reader :name, :getter, :desc
|
64
|
+
|
65
|
+
def initialize name, desc: nil, &getter
|
66
|
+
@name = name
|
67
|
+
@getter = getter
|
68
|
+
@desc = desc
|
69
|
+
end
|
70
|
+
end # class Column
|
71
|
+
|
72
|
+
|
73
|
+
# @todo Document build method.
|
74
|
+
#
|
75
|
+
# @param [type] arg_name
|
76
|
+
# @todo Add name param description.
|
77
|
+
#
|
78
|
+
# @return [return_type]
|
79
|
+
# @todo Document return value.
|
80
|
+
#
|
81
|
+
def self.build &block
|
82
|
+
new.tap &block
|
83
|
+
end # .build
|
84
|
+
|
85
|
+
def initialize
|
86
|
+
@columns = []
|
87
|
+
@rows = []
|
88
|
+
end
|
89
|
+
|
90
|
+
def each &block
|
91
|
+
@rows.each &block
|
92
|
+
end
|
93
|
+
|
94
|
+
def each_index &block
|
95
|
+
@rows.each_index &block
|
96
|
+
end
|
97
|
+
|
98
|
+
def column *args, &getter
|
99
|
+
@columns << Column.new( *args, &getter )
|
100
|
+
end
|
101
|
+
|
102
|
+
alias_method :col, :column
|
103
|
+
|
104
|
+
|
105
|
+
def rows entries = nil
|
106
|
+
unless entries.nil?
|
107
|
+
@rows = entries.to_a
|
108
|
+
end
|
109
|
+
|
110
|
+
@rows
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
def to_a header: true, col_desc_refs: true
|
115
|
+
[].tap do |array|
|
116
|
+
|
117
|
+
if header
|
118
|
+
desc_ref_index = 0
|
119
|
+
array << @columns.map { |column|
|
120
|
+
if column.desc && col_desc_refs
|
121
|
+
desc_ref_index += 1
|
122
|
+
"#{ column.name }#{ SUPERSCRIPT_NUMBERS[desc_ref_index] }"
|
123
|
+
else
|
124
|
+
column.name
|
125
|
+
end
|
126
|
+
}
|
127
|
+
end
|
128
|
+
|
129
|
+
@rows.each do |row|
|
130
|
+
values = if NRSER.array_like? row
|
131
|
+
row.to_a
|
132
|
+
else
|
133
|
+
@columns.map do |column|
|
134
|
+
column.getter.call( row )
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
array << values.map { |value|
|
139
|
+
if value.nil?
|
140
|
+
NULL
|
141
|
+
else
|
142
|
+
value.to_s
|
143
|
+
end
|
144
|
+
}
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
end # #to_a
|
149
|
+
|
150
|
+
def footer
|
151
|
+
NULL + " Null\n" +
|
152
|
+
@columns.select { |col| col.desc }.each_with_index.map { |col, index|
|
153
|
+
"#{ SUPERSCRIPT_NUMBERS[index + 1] } #{ col.desc }"
|
154
|
+
}.join( "\n" )
|
155
|
+
end
|
156
|
+
|
157
|
+
end # class Locd::CLI::Table
|