akaer 1.5.8 → 2.0.0
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.
- data/.travis-gemfile +13 -0
- data/.travis.yml +6 -4
- data/Gemfile +12 -1
- data/README.md +7 -4
- data/Rakefile +2 -9
- data/akaer.gemspec +5 -10
- data/bin/akaer +19 -17
- data/doc/Akaer/Application.html +1186 -860
- data/doc/Akaer/ApplicationMethods/General.html +365 -0
- data/doc/Akaer/ApplicationMethods/System.html +456 -0
- data/doc/Akaer/{Errors.html → ApplicationMethods.html} +21 -11
- data/doc/Akaer/Configuration.html +3 -3
- data/doc/Akaer/Version.html +6 -6
- data/doc/Akaer.html +6 -6
- data/doc/_index.html +41 -4
- data/doc/class_list.html +1 -1
- data/doc/file.README.html +53 -42
- data/doc/frames.html +1 -1
- data/doc/index.html +53 -42
- data/doc/method_list.html +30 -22
- data/doc/top-level-namespace.html +3 -3
- data/lib/akaer/application.rb +323 -199
- data/lib/akaer/configuration.rb +13 -13
- data/lib/akaer/version.rb +4 -4
- data/lib/akaer.rb +2 -1
- data/locales/en.yml +52 -0
- data/locales/it.yml +52 -0
- data/spec/akaer/application_spec.rb +25 -25
- data/spec/akaer/configuration_spec.rb +3 -3
- data/spec/coverage_helper.rb +6 -9
- data/spec/spec_helper.rb +1 -2
- metadata +18 -115
- data/doc/Akaer/Errors/InvalidConfiguration.html +0 -123
- data/doc/Akaer/Logger.html +0 -596
- data/doc/Fixnum.html +0 -200
data/lib/akaer/application.rb
CHANGED
@@ -1,69 +1,302 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
#
|
3
|
-
# This file is part of the akaer gem. Copyright (C)
|
3
|
+
# This file is part of the akaer gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
|
4
4
|
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
5
|
#
|
6
6
|
|
7
7
|
# A small utility to add aliases to network interfaces.
|
8
8
|
module Akaer
|
9
|
+
# Methods for the {Application Application} class.
|
10
|
+
module ApplicationMethods
|
11
|
+
# General methods.
|
12
|
+
module General
|
13
|
+
extend ActiveSupport::Concern
|
14
|
+
|
15
|
+
# Checks if we are running on MacOS X.
|
16
|
+
#
|
17
|
+
# System services are only available on that platform.
|
18
|
+
#
|
19
|
+
# @return [Boolean] `true` if the current platform is MacOS X, `false` otherwise.
|
20
|
+
def is_osx?
|
21
|
+
::RbConfig::CONFIG['host_os'] =~ /^darwin/
|
22
|
+
end
|
23
|
+
|
24
|
+
# Adds or removes an alias from the interface.
|
25
|
+
#
|
26
|
+
# @param type [Symbol] The operation to execute. Can be `:add` or `:remove`.
|
27
|
+
# @param address [String] The address to manage.
|
28
|
+
# @return [Boolean] `true` if operation succedeed, `false` otherwise.
|
29
|
+
def manage(type, address)
|
30
|
+
locale = self.i18n
|
31
|
+
config = self.config
|
32
|
+
quiet = config.quiet
|
33
|
+
rv, command, prefix = setup_management(type, address)
|
34
|
+
|
35
|
+
# Now execute
|
36
|
+
if rv then
|
37
|
+
if !config.dry_run then
|
38
|
+
execute_manage(command, prefix, type, address, config, quiet)
|
39
|
+
else
|
40
|
+
log_management(:dry_run, prefix, type, locale.remove, locale.add, address, config, quiet)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
rv
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
# Setups management.
|
49
|
+
#
|
50
|
+
# @param type [Symbol] The type of operation. Can be `:add` or `:remove`.
|
51
|
+
# @param address [String] The address to manage.
|
52
|
+
# @return [Array] A list of parameters for the management.
|
53
|
+
def setup_management(type, address)
|
54
|
+
begin
|
55
|
+
@addresses ||= self.compute_addresses
|
56
|
+
length = self.pad_number(@addresses.length)
|
57
|
+
[true, Mustache.render(config.send((type == :remove) ? :remove_command : :add_command), {interface: config.interface, alias: address}) + " > /dev/null 2>&1", "{mark=blue}[{mark=bright white}#{self.pad_number((@addresses.index(address) || 0) + 1, length.length)}{mark=reset blue}/{/mark}#{length}{/mark}]{/mark}"]
|
58
|
+
rescue ArgumentError
|
59
|
+
[false]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Executes management.
|
64
|
+
#
|
65
|
+
# @param command [String] The command to execute.
|
66
|
+
# @param prefix [String] The prefix to apply to the message.
|
67
|
+
# @param type [Symbol] The type of operation. Can be `:add` or `:remove`.
|
68
|
+
# @param address [String] The address that will be managed.
|
69
|
+
# @param config [Configuration] The current configuration.
|
70
|
+
# @param quiet [Boolean] Whether to show the message.
|
71
|
+
# @return [Boolean] `true` if operation succedeed, `false` otherwise.
|
72
|
+
def execute_manage(command, prefix, type, address, config, quiet)
|
73
|
+
locale = self.i18n
|
74
|
+
log_management(:run, prefix, type, locale.removing, locale.adding, address, config, quiet)
|
75
|
+
rv = self.execute_command(command)
|
76
|
+
labels = (type == :remove ? [locale.remove, locale.from] : [locale.add, locale.to])
|
77
|
+
@logger.error(@command.application.console.replace_markers(locale.general_error(labels[0], address, labels[1], config.interface))) if !rv
|
78
|
+
rv
|
79
|
+
end
|
80
|
+
|
81
|
+
# Logs an operation.
|
82
|
+
#
|
83
|
+
# @param message [Symbol] The message to print.
|
84
|
+
# @param prefix [String] The prefix to apply to the message.
|
85
|
+
# @param type [Symbol] The type of operation. Can be `:add` or `:remove`.
|
86
|
+
# @param remove_label [String] The label to use for removing.
|
87
|
+
# @param add_label [String] The label to use for adding.
|
88
|
+
# @param address [String] The address that will be managed.
|
89
|
+
# @param config [Configuration] The current configuration.
|
90
|
+
# @param quiet [Boolean] Whether to show the message.
|
91
|
+
def log_management(message, prefix, type, remove_label, add_label, address, config, quiet)
|
92
|
+
locale = self.i18n
|
93
|
+
labels = (type == :remove ? [remove_label, locale.from] : [add_label, locale.to])
|
94
|
+
@logger.info(@command.application.console.replace_markers(self.i18n.send(message, prefix, labels[0], address, labels[1], config.interface))) if !quiet
|
95
|
+
end
|
96
|
+
|
97
|
+
# Manages an action on the request addresses.
|
98
|
+
#
|
99
|
+
# @param operation [Symbol] The type of operation. Can be `:add` or `:remove`.
|
100
|
+
# @param message [String] The message to show if no addresses are found.
|
101
|
+
# @param quiet [Boolean] Whether to show the failure message.
|
102
|
+
def manage_action(operation, message, quiet)
|
103
|
+
addresses = self.compute_addresses
|
104
|
+
|
105
|
+
if addresses.present? then
|
106
|
+
# Now, for every address, call the command
|
107
|
+
addresses.all? {|address|
|
108
|
+
self.manage(operation, address)
|
109
|
+
}
|
110
|
+
else
|
111
|
+
@logger.error(message) if !quiet
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# System management methods.
|
117
|
+
module System
|
118
|
+
# Adds aliases to the interface.
|
119
|
+
#
|
120
|
+
# @return [Boolean] `true` if action succedeed, `false` otherwise.
|
121
|
+
def action_add
|
122
|
+
manage_action(:add, self.i18n.add_empty, self.config.quiet)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Removes aliases from the interface.
|
126
|
+
#
|
127
|
+
# @return [Boolean] `true` if action succedeed, `false` otherwise.
|
128
|
+
def action_remove
|
129
|
+
manage_action(:remove, self.i18n.remove_empty, self.config.quiet)
|
130
|
+
end
|
131
|
+
|
132
|
+
# Installs the application into the autolaunch.
|
133
|
+
#
|
134
|
+
# @return [Boolean] `true` if action succedeed, `false` otherwise.
|
135
|
+
def action_install
|
136
|
+
manage_agent(self.launch_agent_path, :create_agent, :load_agent, self.config.quiet)
|
137
|
+
end
|
138
|
+
|
139
|
+
# Uninstalls the application from the autolaunch.
|
140
|
+
#
|
141
|
+
# @return [Boolean] `true` if action succedeed, `false` otherwise.
|
142
|
+
def action_uninstall
|
143
|
+
manage_agent(self.launch_agent_path, :unload_agent, :delete_agent, self.config.quiet)
|
144
|
+
end
|
145
|
+
|
146
|
+
private
|
147
|
+
# Manages a OSX agent.
|
148
|
+
#
|
149
|
+
# @param launch_agent [String] The agent path.
|
150
|
+
# @param first_operation [Symbol] The first operation to execute.
|
151
|
+
# @param second_operation [Symbol] The second operation to execute.
|
152
|
+
# @param quiet [Boolean] Whether to show messages.
|
153
|
+
# @return [Boolean] `true` if operation succedeed, `false` otherwise.
|
154
|
+
def manage_agent(launch_agent, first_operation, second_operation, quiet)
|
155
|
+
rv = true
|
156
|
+
|
157
|
+
rv = check_agent_available(quiet)
|
158
|
+
rv = send(first_operation, launch_agent, quiet) if rv
|
159
|
+
rv = send(second_operation, launch_agent, quiet) if rv
|
160
|
+
rv
|
161
|
+
end
|
162
|
+
|
163
|
+
# Checks if agent is enabled (that is, we are on OSX).
|
164
|
+
#
|
165
|
+
# @param quiet [Boolean] Whether to show messages.
|
166
|
+
# @return [Boolean] `true` if the agent is enabled, `false` otherwise.
|
167
|
+
def check_agent_available(quiet)
|
168
|
+
rv = true
|
169
|
+
if !self.is_osx? then
|
170
|
+
logger.fatal(self.i18n.no_agent) if !quiet
|
171
|
+
rv = false
|
172
|
+
end
|
173
|
+
|
174
|
+
rv
|
175
|
+
end
|
176
|
+
|
177
|
+
# Creates a OSX system agent.
|
178
|
+
#
|
179
|
+
# @param launch_agent [String] The agent path.
|
180
|
+
# @param quiet [Boolean] Whether to show messages.
|
181
|
+
# @return [Boolean] `true` if operation succedeed, `false` otherwise.
|
182
|
+
def create_agent(launch_agent, quiet)
|
183
|
+
begin
|
184
|
+
self.logger.info(self.i18n.agent_creating(launch_agent)) if !quiet
|
185
|
+
write_agent(launch_agent)
|
186
|
+
self.execute_command("plutil -convert binary1 \"#{launch_agent}\"")
|
187
|
+
true
|
188
|
+
rescue
|
189
|
+
self.logger.error(self.i18n.agent_creating_error) if !quiet
|
190
|
+
false
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# Writes a OSX system agent.
|
195
|
+
#
|
196
|
+
# @param launch_agent [String] The agent path.
|
197
|
+
def write_agent(launch_agent)
|
198
|
+
::File.open(launch_agent, "w") {|f|
|
199
|
+
f.write({"KeepAlive" => false, "Label" => "it.cowtech.akaer", "Program" => (::Pathname.new(Dir.pwd) + $0).to_s, "ProgramArguments" => ($ARGV ? $ARGV[0, $ARGV.length - 1] : []), "RunAtLoad" => true}.to_json)
|
200
|
+
f.flush
|
201
|
+
}
|
202
|
+
end
|
203
|
+
|
204
|
+
# Deletes a OSX system agent.
|
205
|
+
#
|
206
|
+
# @param launch_agent [String] The agent path.
|
207
|
+
# @param quiet [Boolean] Whether to show messages.
|
208
|
+
# @return [Boolean] `true` if operation succedeed, `false` otherwise.
|
209
|
+
def delete_agent(launch_agent, quiet)
|
210
|
+
begin
|
211
|
+
self.logger.info(self.i18n.agent_deleting(launch_agent)) if !quiet
|
212
|
+
::File.delete(launch_agent)
|
213
|
+
rescue => e
|
214
|
+
self.logger.warn(self.i18n.agent_deleting_error) if !quiet
|
215
|
+
return false
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
# Loads a OSX system agent.
|
220
|
+
#
|
221
|
+
# @param launch_agent [String] The agent path.
|
222
|
+
# @param quiet [Boolean] Whether to show messages.
|
223
|
+
# @return [Boolean] `true` if operation succedeed, `false` otherwise.
|
224
|
+
def load_agent(launch_agent, quiet)
|
225
|
+
begin
|
226
|
+
perform_agent_loading(launch_agent, "load", :agent_loading, quiet)
|
227
|
+
rescue
|
228
|
+
self.logger.error(self.i18n.agent_loading_error) if !quiet
|
229
|
+
false
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
# Unloads a OSX system agent.
|
234
|
+
#
|
235
|
+
# @param launch_agent [String] The agent path.
|
236
|
+
# @param quiet [Boolean] Whether to show messages.
|
237
|
+
# @return [Boolean] `true` if operation succedeed, `false` otherwise.
|
238
|
+
def unload_agent(launch_agent, quiet)
|
239
|
+
begin
|
240
|
+
perform_agent_loading(launch_agent, "unload", :agent_unloading, quiet)
|
241
|
+
rescue => e
|
242
|
+
self.logger.warn(self.i18n.agent_unloading_error) if !quiet
|
243
|
+
false
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
# Performs operatoin on a OSX system agent.
|
248
|
+
#
|
249
|
+
# @param launch_agent [String] The agent path.
|
250
|
+
# @param command [String] The command to run.
|
251
|
+
# @param message [String] The message to show.
|
252
|
+
# @param quiet [Boolean] Whether to show messages.
|
253
|
+
# @return [Boolean] `true` if operation succedeed, `false` otherwise.
|
254
|
+
def perform_agent_loading(launch_agent, command, message, quiet)
|
255
|
+
self.logger.info(self.i18n.send(message, launch_agent)) if !quiet
|
256
|
+
self.execute_command("launchctl #{command} -w \"#{launch_agent}\" > /dev/null 2>&1")
|
257
|
+
true
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
9
262
|
# The main Akaer application.
|
263
|
+
#
|
264
|
+
# @attribute config
|
265
|
+
# @return [Configuration] The {Configuration Configuration} of this application.
|
266
|
+
# @attribute command
|
267
|
+
# @return [Mamertes::Command] The Mamertes command.
|
268
|
+
# @attribute
|
269
|
+
# @return [Bovem::Logger] logger The logger for this application.
|
10
270
|
class Application
|
11
|
-
# The {Configuration Configuration} of this application.
|
12
271
|
attr_reader :config
|
13
|
-
|
14
|
-
# The Mamertes command.
|
15
272
|
attr_reader :command
|
16
|
-
|
17
|
-
# The logger for this application.
|
18
273
|
attr_accessor :logger
|
19
274
|
|
275
|
+
include Lazier::I18n
|
276
|
+
include Akaer::ApplicationMethods::General
|
277
|
+
include Akaer::ApplicationMethods::System
|
278
|
+
|
20
279
|
# Creates a new application.
|
21
280
|
#
|
22
281
|
# @param command [Mamertes::Command] The current Mamertes command.
|
23
|
-
|
282
|
+
# @param locale [Symbol] The locale to use for the application.
|
283
|
+
def initialize(command, locale)
|
284
|
+
self.i18n_setup(:akaer, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"))
|
285
|
+
self.i18n = locale
|
286
|
+
|
24
287
|
@command = command
|
25
|
-
|
288
|
+
options = @command.application.get_options.reject {|k,v| v.nil? }
|
26
289
|
|
27
290
|
# Setup logger
|
28
291
|
Bovem::Logger.start_time = Time.now
|
29
|
-
@logger = Bovem::Logger.create(Bovem::Logger.get_real_file(
|
292
|
+
@logger = Bovem::Logger.create(Bovem::Logger.get_real_file(options["log_file"]) || Bovem::Logger.default_file, Logger::INFO)
|
30
293
|
|
31
294
|
# Open configuration
|
32
|
-
|
33
|
-
overrides = {
|
34
|
-
:interface => application.options["interface"].value,
|
35
|
-
:addresses => application.options["addresses"].value,
|
36
|
-
:start_address => application.options["start-address"].value,
|
37
|
-
:aliases => application.options["aliases"].value,
|
38
|
-
:add_command => application.options["add-command"].value,
|
39
|
-
:remove_command => application.options["remove-command"].value,
|
40
|
-
:log_file => application.options["log-file"].value,
|
41
|
-
:log_level => application.options["log-level"].value,
|
42
|
-
:dry_run => application.options["dry-run"].value,
|
43
|
-
:quiet => application.options["quiet"].value
|
44
|
-
}.reject {|k,v| v.nil? }
|
45
|
-
|
46
|
-
@config = Akaer::Configuration.new(application.options["configuration"].value, overrides, @logger)
|
47
|
-
|
48
|
-
@logger = nil
|
49
|
-
@logger = self.get_logger
|
50
|
-
rescue Bovem::Errors::InvalidConfiguration => e
|
51
|
-
@logger ? @logger.fatal(e.message) : Bovem::Logger.create("STDERR").fatal("Cannot log to {mark=bright}#{config.log_file}{/mark}. Exiting...")
|
52
|
-
raise ::SystemExit
|
53
|
-
end
|
295
|
+
read_configuration(options)
|
54
296
|
|
55
297
|
self
|
56
298
|
end
|
57
299
|
|
58
|
-
# Checks if we are running on MacOS X.
|
59
|
-
#
|
60
|
-
# System services are only available on that platform.
|
61
|
-
#
|
62
|
-
# @return [Boolean] `true` if the current platform is MacOS X, `false` otherwise.
|
63
|
-
def is_osx?
|
64
|
-
::Config::CONFIG['host_os'] =~ /^darwin/
|
65
|
-
end
|
66
|
-
|
67
300
|
# Checks if and address is a valid IPv4 address.
|
68
301
|
#
|
69
302
|
# @param address [String] The address to check.
|
@@ -134,176 +367,67 @@ module Akaer
|
|
134
367
|
# @param type [Symbol] The type of addresses to consider. Valid values are `:ipv4`, `:ipv6`, otherwise all addresses are considered.
|
135
368
|
# @return [Array] The list of addresses to add or remove from the interface.
|
136
369
|
def compute_addresses(type = :all)
|
137
|
-
|
138
|
-
|
139
|
-
if self.config.addresses.present? # We have an explicit list
|
140
|
-
rv = self.config.addresses
|
141
|
-
|
142
|
-
# Now filter the addresses
|
143
|
-
filters = [type != :ipv6 ? :ipv4 : nil, type != :ipv4 ? :ipv6 : nil].compact
|
144
|
-
rv = rv.select {|address|
|
145
|
-
filters.any? {|filter| self.send("is_#{filter}?", address) }
|
146
|
-
}.compact.uniq
|
147
|
-
else
|
148
|
-
begin
|
149
|
-
ip = IPAddr.new(self.config.start_address.ensure_string)
|
150
|
-
raise ArgumentError if (type == :ipv4 && !ip.ipv4?) || (type == :ipv6 && !ip.ipv6?)
|
151
|
-
|
152
|
-
(self.config.aliases > 0 ? self.config.aliases : 5).times do
|
153
|
-
rv << ip.to_s
|
154
|
-
ip = ip.succ
|
155
|
-
end
|
156
|
-
rescue ArgumentError
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
rv
|
161
|
-
end
|
162
|
-
|
163
|
-
# Adds or removes an alias from the interface.
|
164
|
-
#
|
165
|
-
# @param type [Symbol] The operation to execute. Can be `:add` or `:remove`.
|
166
|
-
# @param address [String] The address to manage.
|
167
|
-
# @return [Boolean] `true` if operation succedeed, `false` otherwise.
|
168
|
-
def manage(type, address)
|
169
|
-
rv = true
|
170
|
-
|
171
|
-
# Compute the command
|
172
|
-
command = (type == :remove) ? self.config.remove_command : self.config.add_command
|
173
|
-
|
174
|
-
# Interpolate
|
175
|
-
command = command.gsub("@INTERFACE@", self.config.interface).gsub("@ALIAS@", address) + " > /dev/null 2>&1"
|
176
|
-
|
177
|
-
# Compute the prefix
|
178
|
-
@addresses ||= self.compute_addresses
|
179
|
-
length = self.pad_number(@addresses.length)
|
180
|
-
index = (@addresses.index(address) || 0) + 1
|
181
|
-
prefix = "{mark=blue}[{mark=bright white}#{self.pad_number(index, length.length)}{mark=reset blue}/{/mark}#{length}{/mark}]{/mark}"
|
182
|
-
|
183
|
-
# Now execute
|
184
|
-
if !self.config.dry_run then
|
185
|
-
@logger.info(@command.application.console.replace_markers("#{prefix} {mark=bright}#{(type == :remove ? "Removing" : "Adding")}{/mark} address {mark=bright}#{address}{/mark} #{type != :remove ? "to" : "from"} interface {mark=bright}#{self.config.interface}{/mark}...")) if !self.config.quiet
|
186
|
-
rv = self.execute_command(command)
|
187
|
-
@logger.error(@command.application.console.replace_markers("Cannot {mark=bright}#{(type == :remove ? "remove" : "add")}{/mark} address {mark=bright}#{address}{/mark} #{type != :remove ? "to" : "from"} interface {mark=bright}#{self.config.interface}{/mark}.")) if !rv
|
188
|
-
else
|
189
|
-
@logger.info(@command.application.console.replace_markers("#{prefix} I will {mark=bright}#{(type == :remove ? "remove" : "add")}{/mark} address {mark=bright}#{address}{/mark} #{type != :remove ? "to" : "from"} interface {mark=bright}#{self.config.interface}{/mark}.")) if !self.config.quiet
|
190
|
-
end
|
191
|
-
|
192
|
-
rv
|
193
|
-
end
|
194
|
-
|
195
|
-
# Adds aliases to the interface.
|
196
|
-
#
|
197
|
-
# @return [Boolean] `true` if action succedeed, `false` otherwise.
|
198
|
-
def action_add
|
199
|
-
addresses = self.compute_addresses
|
200
|
-
|
201
|
-
if addresses.present? then
|
202
|
-
# Now, for every address, call the command
|
203
|
-
addresses.all? {|address|
|
204
|
-
self.manage(:add, address)
|
205
|
-
}
|
206
|
-
else
|
207
|
-
@logger.error("No valid addresses to add to the interface found.") if !self.config.quiet
|
208
|
-
end
|
370
|
+
config = self.config
|
371
|
+
config.addresses.present? ? filter_addresses(config, type) : generate_addresses(config, type)
|
209
372
|
end
|
210
373
|
|
211
|
-
#
|
374
|
+
# Returns a unique (singleton) instance of the application.
|
212
375
|
#
|
213
|
-
# @
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
self.manage(:remove, address)
|
221
|
-
}
|
222
|
-
else
|
223
|
-
@logger.error("No valid addresses to remove from the interface found.") if !self.config.quiet
|
224
|
-
end
|
376
|
+
# @param command [Mamertes::Command] The current Mamertes command.
|
377
|
+
# @param locale [Symbol] The locale to use for the application.
|
378
|
+
# @param force [Boolean] If to force recreation of the instance.
|
379
|
+
# @return [Application] The unique (singleton) instance of the application.
|
380
|
+
def self.instance(command, locale = nil, force = false)
|
381
|
+
@instance = nil if force
|
382
|
+
@instance ||= Akaer::Application.new(command, locale)
|
225
383
|
end
|
226
384
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
begin
|
241
|
-
logger.info("Creating the launch agent in {mark=bright}#{launch_agent}{/mark} ...") if !self.config.quiet
|
242
|
-
|
243
|
-
args = $ARGV ? $ARGV[0, $ARGV.length - 1] : []
|
244
|
-
|
245
|
-
plist = {"KeepAlive" => false, "Label" => "it.cowtech.akaer", "Program" => (::Pathname.new(Dir.pwd) + $0).to_s, "ProgramArguments" => args, "RunAtLoad" => true}
|
246
|
-
::File.open(launch_agent, "w") {|f|
|
247
|
-
f.write(plist.to_json)
|
248
|
-
f.flush
|
249
|
-
}
|
250
|
-
self.execute_command("plutil -convert binary1 \"#{launch_agent}\"")
|
251
|
-
rescue => e
|
252
|
-
logger.error("Cannot create the launch agent.") if !self.config.quiet
|
253
|
-
return false
|
385
|
+
private
|
386
|
+
# Reads the configuration.
|
387
|
+
#
|
388
|
+
# @param options [Hash] The options to read.
|
389
|
+
def read_configuration(options)
|
390
|
+
begin
|
391
|
+
@config = Akaer::Configuration.new(options["configuration"], options, @logger)
|
392
|
+
@logger = nil
|
393
|
+
@logger = self.get_logger
|
394
|
+
rescue Bovem::Errors::InvalidConfiguration => e
|
395
|
+
@logger ? @logger.fatal(e.message) : Bovem::Logger.create("STDERR").fatal(self.i18n.logging_failed(log_file))
|
396
|
+
raise ::SystemExit
|
397
|
+
end
|
254
398
|
end
|
255
399
|
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
400
|
+
# Filters a list of addresses to return just certain type(s).
|
401
|
+
#
|
402
|
+
# @param config [Configuration] The current configuration.
|
403
|
+
# @param type [Symbol] The type of addresses to return.
|
404
|
+
# @return [Array] A list of IPs.
|
405
|
+
def filter_addresses(config, type)
|
406
|
+
filters = [:ipv4, :ipv6].select {|i| type == i || type == :all }.compact
|
263
407
|
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
# Uninstalls the application from the autolaunch.
|
268
|
-
#
|
269
|
-
# @return [Boolean] `true` if action succedeed, `false` otherwise.
|
270
|
-
def action_uninstall
|
271
|
-
logger = self.get_logger
|
272
|
-
|
273
|
-
if !self.is_osx? then
|
274
|
-
logger.fatal("Install akaer on autolaunch is only available on MacOSX.") if !self.config.quiet
|
275
|
-
return false
|
408
|
+
rv = config.addresses.select { |address|
|
409
|
+
filters.any? {|filter| self.send("is_#{filter}?", address) }
|
410
|
+
}.compact.uniq
|
276
411
|
end
|
277
412
|
|
278
|
-
|
279
|
-
|
280
|
-
#
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
413
|
+
# Generates a list of addresses which are immediate successors of a start address.
|
414
|
+
#
|
415
|
+
# @param config [Configuration] The current configuration.
|
416
|
+
# @param type [Symbol] The type of addresses to return.
|
417
|
+
# @return [Array] A list of IPs.
|
418
|
+
def generate_addresses(config, type)
|
419
|
+
begin
|
420
|
+
ip = IPAddr.new(config.start_address.ensure_string)
|
421
|
+
raise ArgumentError if type != :all && !ip.send("#{type}?")
|
286
422
|
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
423
|
+
(config.aliases > 0 ? config.aliases : 5).times.collect {|i|
|
424
|
+
current = ip
|
425
|
+
ip = ip.succ
|
426
|
+
current
|
427
|
+
}
|
428
|
+
rescue ArgumentError
|
429
|
+
[]
|
430
|
+
end
|
294
431
|
end
|
295
|
-
|
296
|
-
true
|
297
|
-
end
|
298
|
-
|
299
|
-
# Returns a unique (singleton) instance of the application.
|
300
|
-
#
|
301
|
-
# @param command [Mamertes::Command] The current Mamertes command.
|
302
|
-
# @param force [Boolean] If to force recreation of the instance.
|
303
|
-
# @return [Application] The unique (singleton) instance of the application.
|
304
|
-
def self.instance(command, force = false)
|
305
|
-
@instance = nil if force
|
306
|
-
@instance ||= Akaer::Application.new(command)
|
307
|
-
end
|
308
432
|
end
|
309
433
|
end
|
data/lib/akaer/configuration.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
#
|
3
|
-
# This file is part of the akaer gem. Copyright (C)
|
3
|
+
# This file is part of the akaer gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
|
4
4
|
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
5
|
#
|
6
6
|
|
@@ -8,34 +8,34 @@ module Akaer
|
|
8
8
|
# This class holds the configuration of the applicaton.
|
9
9
|
class Configuration < Bovem::Configuration
|
10
10
|
# The default interface to manage. Default: `lo0`.
|
11
|
-
property :interface, :
|
11
|
+
property :interface, default: "lo0"
|
12
12
|
|
13
13
|
# The default list of aliases to add. Default: `[]`.
|
14
|
-
property :addresses, :
|
14
|
+
property :addresses, default: []
|
15
15
|
|
16
16
|
# The starting address for sequential aliases. Default: `10.0.0.1`.
|
17
|
-
property :start_address, :
|
17
|
+
property :start_address, default: "10.0.0.1"
|
18
18
|
|
19
19
|
# The number of aliases to add. Default: `5`.
|
20
|
-
property :aliases, :
|
20
|
+
property :aliases, default: 5
|
21
21
|
|
22
|
-
# The command to run for adding an alias. Default: `sudo ifconfig
|
23
|
-
property :add_command, :
|
22
|
+
# The command to run for adding an alias. Default: `sudo ifconfig {{interface}} alias {{alias}}`.
|
23
|
+
property :add_command, default: "sudo ifconfig {{interface}} alias {{alias}}"
|
24
24
|
|
25
|
-
# The command to run for removing an alias. Default: `sudo ifconfig
|
26
|
-
property :remove_command, :
|
25
|
+
# The command to run for removing an alias. Default: `sudo ifconfig {{interface}} alias {{alias}}`.
|
26
|
+
property :remove_command, default: "sudo ifconfig {{interface}} -alias {{alias}}"
|
27
27
|
|
28
28
|
# The file to log to. Default is the standard output.
|
29
|
-
property :log_file, :
|
29
|
+
property :log_file, default: "STDOUT"
|
30
30
|
|
31
31
|
# The minimum severity to log. Default: `Logger::INFO`.
|
32
|
-
property :log_level, :
|
32
|
+
property :log_level, default: Logger::INFO
|
33
33
|
|
34
34
|
# Only show which modifications will be done.
|
35
|
-
property :dry_run, :
|
35
|
+
property :dry_run, default: false
|
36
36
|
|
37
37
|
# Do not show any message.
|
38
|
-
property :quiet, :
|
38
|
+
property :quiet, default: false
|
39
39
|
|
40
40
|
# Creates a new configuration.
|
41
41
|
#
|
data/lib/akaer/version.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
#
|
3
|
-
# This file is part of the akaer gem. Copyright (C)
|
3
|
+
# This file is part of the akaer gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
|
4
4
|
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
5
|
#
|
6
6
|
|
@@ -10,13 +10,13 @@ module Akaer
|
|
10
10
|
# @see http://semver.org
|
11
11
|
module Version
|
12
12
|
# The major version.
|
13
|
-
MAJOR =
|
13
|
+
MAJOR = 2
|
14
14
|
|
15
15
|
# The minor version.
|
16
|
-
MINOR =
|
16
|
+
MINOR = 0
|
17
17
|
|
18
18
|
# The patch version.
|
19
|
-
PATCH =
|
19
|
+
PATCH = 0
|
20
20
|
|
21
21
|
# The current version of akaer.
|
22
22
|
STRING = [MAJOR, MINOR, PATCH].compact.join(".")
|
data/lib/akaer.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
#
|
3
|
-
# This file is part of the akaer gem. Copyright (C)
|
3
|
+
# This file is part of the akaer gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
|
4
4
|
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
5
|
#
|
6
6
|
|
7
7
|
require "mamertes"
|
8
|
+
require "mustache"
|
8
9
|
require "ipaddr"
|
9
10
|
|
10
11
|
require "akaer/version" if !defined?(Akaer::Version)
|