vagrant-docker-hosts-manager 0.2.0 → 0.4.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/README.md +1 -0
- data/lib/vagrant-docker-hosts-manager/VERSION +1 -1
- data/lib/vagrant-docker-hosts-manager/actions/apply.rb +68 -0
- data/lib/vagrant-docker-hosts-manager/actions/cleanup.rb +34 -0
- data/lib/vagrant-docker-hosts-manager/command.rb +255 -248
- data/lib/vagrant-docker-hosts-manager/config.rb +45 -10
- data/lib/vagrant-docker-hosts-manager/helpers.rb +91 -7
- data/lib/vagrant-docker-hosts-manager/plugin.rb +2 -92
- data/lib/vagrant-docker-hosts-manager/util/docker.rb +10 -11
- data/lib/vagrant-docker-hosts-manager/util/hosts_file.rb +140 -132
- data/lib/vagrant-docker-hosts-manager/util/i18n.rb +20 -12
- data/lib/vagrant-docker-hosts-manager/util/verbose.rb +22 -0
- data/lib/vagrant-docker-hosts-manager/version.rb +7 -5
- data/locales/en.yml +117 -110
- data/locales/fr.yml +118 -111
- metadata +6 -2
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "base64"
|
|
3
4
|
require "tempfile"
|
|
4
5
|
require "time"
|
|
5
6
|
require "open3"
|
|
6
7
|
|
|
7
8
|
require_relative "../helpers"
|
|
8
9
|
require_relative "docker"
|
|
10
|
+
require_relative "verbose"
|
|
9
11
|
|
|
10
12
|
module VagrantDockerHostsManager
|
|
11
13
|
module Util
|
|
@@ -15,6 +17,10 @@ module VagrantDockerHostsManager
|
|
|
15
17
|
WIN_SYSNATIVE_PATH = "C:/Windows/Sysnative/drivers/etc/hosts"
|
|
16
18
|
WIN_SYSWOW64_PATH = "C:/Windows/SysWOW64/drivers/etc/hosts"
|
|
17
19
|
|
|
20
|
+
BLOCK_START_RE = /^\s*#\s*>>>\s*vagrant-docker-hosts-manager\s+(.+?)\s*\(managed\)\s*>>>\s*$/i
|
|
21
|
+
BLOCK_STOP_RE = /^\s*#\s*<<<\s*vagrant-docker-hosts-manager\s+(.+?)\s*\(managed\)\s*<<<\s*$/i
|
|
22
|
+
ENTRY_RE = /\A\s*(\d{1,3}(?:\.\d{1,3}){3})\s+([^\s#]+)/
|
|
23
|
+
|
|
18
24
|
def initialize(env, owner_id:)
|
|
19
25
|
@env = env || {}
|
|
20
26
|
@owner_id = owner_id.to_s
|
|
@@ -27,8 +33,13 @@ module VagrantDockerHostsManager
|
|
|
27
33
|
end
|
|
28
34
|
|
|
29
35
|
def path_candidates
|
|
30
|
-
|
|
36
|
+
# VDHM_HOSTS_PATH overrides the default location on every platform
|
|
37
|
+
# (used by tests and power users); honor it before anything else.
|
|
31
38
|
return [override_path] if override_path
|
|
39
|
+
return [POSIX_PATH] unless Gem.win_platform?
|
|
40
|
+
|
|
41
|
+
# Sysnative lets a 32-bit Ruby process reach the real System32 hosts
|
|
42
|
+
# file on 64-bit Windows; keep it before System32/SysWOW64.
|
|
32
43
|
[WIN_SYSNATIVE_PATH, WIN_SYS32_PATH, WIN_SYSWOW64_PATH]
|
|
33
44
|
end
|
|
34
45
|
|
|
@@ -62,7 +73,11 @@ module VagrantDockerHostsManager
|
|
|
62
73
|
|
|
63
74
|
def compose_block(entries, newline: "\n")
|
|
64
75
|
start, stop = block_markers
|
|
65
|
-
ts =
|
|
76
|
+
ts = begin
|
|
77
|
+
Time.now.utc.iso8601
|
|
78
|
+
rescue StandardError
|
|
79
|
+
Time.now.utc.to_s
|
|
80
|
+
end
|
|
66
81
|
|
|
67
82
|
header = [
|
|
68
83
|
start,
|
|
@@ -98,11 +113,20 @@ module VagrantDockerHostsManager
|
|
|
98
113
|
str.end_with?(nl) ? str : (str + nl)
|
|
99
114
|
end
|
|
100
115
|
|
|
116
|
+
# Applies managed host entries to the hosts file.
|
|
117
|
+
#
|
|
118
|
+
# Rewrites only this plugin's managed block and preserves unmanaged lines.
|
|
119
|
+
# Entries are normalized and sorted so repeated runs converge to the same
|
|
120
|
+
# file content.
|
|
121
|
+
#
|
|
122
|
+
# @param entries [Hash{String=>String}] Mapping of FQDN to IP address.
|
|
123
|
+
# @return [Integer] Number of managed entries present after applying changes.
|
|
124
|
+
# @raise [RuntimeError] When elevated writes fail.
|
|
101
125
|
def apply(entries)
|
|
102
126
|
entries = normalize_entries(entries)
|
|
103
127
|
if entries.empty?
|
|
104
128
|
UiHelpers.say(@ui, "#{UiHelpers.e(:info)} " +
|
|
105
|
-
::I18n.t("messages.no_entries", default: "No hosts entries configured."))
|
|
129
|
+
::I18n.t("vdhm.messages.no_entries", default: "No hosts entries configured."))
|
|
106
130
|
return 0
|
|
107
131
|
end
|
|
108
132
|
|
|
@@ -132,7 +156,7 @@ module VagrantDockerHostsManager
|
|
|
132
156
|
|
|
133
157
|
if added.empty? && updated.empty?
|
|
134
158
|
UiHelpers.say(@ui, "#{UiHelpers.e(:info)} " +
|
|
135
|
-
::I18n.t("messages.no_change", default: "Nothing to apply. Already up-to-date."))
|
|
159
|
+
::I18n.t("vdhm.messages.no_change", default: "Nothing to apply. Already up-to-date."))
|
|
136
160
|
return existing_map.size
|
|
137
161
|
end
|
|
138
162
|
|
|
@@ -141,14 +165,21 @@ module VagrantDockerHostsManager
|
|
|
141
165
|
write(content)
|
|
142
166
|
|
|
143
167
|
UiHelpers.say(@ui, "#{UiHelpers.e(:success)} " +
|
|
144
|
-
::I18n.t("messages.applied", default: "Hosts entries applied."))
|
|
168
|
+
::I18n.t("vdhm.messages.applied", default: "Hosts entries applied."))
|
|
145
169
|
UiHelpers.say(@ui, "#{UiHelpers.e(:info)} " +
|
|
146
|
-
::I18n.t("messages.apply_summary",
|
|
170
|
+
::I18n.t("vdhm.messages.apply_summary",
|
|
147
171
|
default: "Added: %{a}, Updated: %{u}, Unchanged: %{s}",
|
|
148
172
|
a: added.size, u: updated.size, s: unchanged.size))
|
|
149
173
|
merged.size
|
|
150
174
|
end
|
|
151
175
|
|
|
176
|
+
# Removes matching entries from the current owner's managed block.
|
|
177
|
+
#
|
|
178
|
+
# With no filters this falls back to removing the whole current-owner block.
|
|
179
|
+
#
|
|
180
|
+
# @param ips [Array<String>] IP addresses to remove.
|
|
181
|
+
# @param domains [Array<String>] Domain names to remove.
|
|
182
|
+
# @return [Integer] Number of removed entries, or 1 when a whole block was removed.
|
|
152
183
|
def remove_entries!(ips: [], domains: [])
|
|
153
184
|
ips = Array(ips).map(&:to_s).reject(&:empty?)
|
|
154
185
|
domains = Array(domains).map(&:to_s).reject(&:empty?)
|
|
@@ -165,7 +196,7 @@ module VagrantDockerHostsManager
|
|
|
165
196
|
removed_count = before - filtered.length
|
|
166
197
|
if removed_count <= 0
|
|
167
198
|
UiHelpers.say(@ui, "#{UiHelpers.e(:info)} " +
|
|
168
|
-
::I18n.t("messages.remove_none",
|
|
199
|
+
::I18n.t("vdhm.messages.remove_none",
|
|
169
200
|
default: "No matching entry to remove."))
|
|
170
201
|
return 0
|
|
171
202
|
end
|
|
@@ -187,7 +218,7 @@ module VagrantDockerHostsManager
|
|
|
187
218
|
@ui,
|
|
188
219
|
"#{UiHelpers.e(:broom)} " +
|
|
189
220
|
::I18n.t(
|
|
190
|
-
"messages.removed_count",
|
|
221
|
+
"vdhm.messages.removed_count",
|
|
191
222
|
default: "%{count} entries removed.",
|
|
192
223
|
count: removed_count
|
|
193
224
|
)
|
|
@@ -195,6 +226,9 @@ module VagrantDockerHostsManager
|
|
|
195
226
|
removed_count
|
|
196
227
|
end
|
|
197
228
|
|
|
229
|
+
# Removes the current owner's managed hosts block.
|
|
230
|
+
#
|
|
231
|
+
# @return [Boolean] Whether a block was removed.
|
|
198
232
|
def remove!
|
|
199
233
|
content = read
|
|
200
234
|
newc = remove_block_from(content)
|
|
@@ -202,12 +236,44 @@ module VagrantDockerHostsManager
|
|
|
202
236
|
write(newc) if removed
|
|
203
237
|
|
|
204
238
|
UiHelpers.say(@ui, removed ?
|
|
205
|
-
"#{UiHelpers.e(:broom)} " + ::I18n.t("messages.cleaned", default: "Managed hosts entries removed.") :
|
|
206
|
-
"#{UiHelpers.e(:info)} " + ::I18n.t("messages.nothing_to_clean", default: "Nothing to clean."))
|
|
239
|
+
"#{UiHelpers.e(:broom)} " + ::I18n.t("vdhm.messages.cleaned", default: "Managed hosts entries removed.") :
|
|
240
|
+
"#{UiHelpers.e(:info)} " + ::I18n.t("vdhm.messages.nothing_to_clean", default: "Nothing to clean."))
|
|
241
|
+
removed
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# Removes every block managed by this plugin, regardless of owner.
|
|
245
|
+
#
|
|
246
|
+
# @return [Boolean] Whether any managed block was removed.
|
|
247
|
+
def remove_all_managed!
|
|
248
|
+
content = read
|
|
249
|
+
newc = strip_managed_blocks(content)
|
|
250
|
+
removed = (newc != content)
|
|
251
|
+
write(newc) if removed
|
|
252
|
+
|
|
253
|
+
UiHelpers.say(@ui, removed ?
|
|
254
|
+
"#{UiHelpers.e(:broom)} " + ::I18n.t("vdhm.messages.cleaned_all", default: "All managed hosts blocks removed.") :
|
|
255
|
+
"#{UiHelpers.e(:info)} " + ::I18n.t("vdhm.messages.nothing_to_clean", default: "Nothing to clean."))
|
|
207
256
|
removed
|
|
208
257
|
end
|
|
209
258
|
|
|
259
|
+
def strip_managed_blocks(content)
|
|
260
|
+
removing = false
|
|
261
|
+
content.lines.reject do |line|
|
|
262
|
+
if line.match?(BLOCK_START_RE)
|
|
263
|
+
removing = true
|
|
264
|
+
true
|
|
265
|
+
elsif line.match?(BLOCK_STOP_RE)
|
|
266
|
+
removing = false
|
|
267
|
+
true
|
|
268
|
+
else
|
|
269
|
+
removing
|
|
270
|
+
end
|
|
271
|
+
end.join
|
|
272
|
+
end
|
|
273
|
+
|
|
210
274
|
def read
|
|
275
|
+
# Hosts files are often edited by Windows tools with BOMs or legacy
|
|
276
|
+
# encodings; normalize to UTF-8 before parsing managed blocks.
|
|
211
277
|
pth = real_path
|
|
212
278
|
UiHelpers.debug(@ui, "read(#{pth})")
|
|
213
279
|
|
|
@@ -216,7 +282,7 @@ module VagrantDockerHostsManager
|
|
|
216
282
|
begin
|
|
217
283
|
data = File.binread(pth)
|
|
218
284
|
UiHelpers.debug(@ui, "File.binread ok, bytes=#{data.bytesize}, encoding=#{data.encoding}")
|
|
219
|
-
rescue => e
|
|
285
|
+
rescue StandardError => e
|
|
220
286
|
UiHelpers.debug(@ui, "File.binread error: #{e.class}: #{e.message}")
|
|
221
287
|
data = nil
|
|
222
288
|
end
|
|
@@ -224,6 +290,7 @@ module VagrantDockerHostsManager
|
|
|
224
290
|
if (data.nil? || data.empty?) && Gem.win_platform?
|
|
225
291
|
ps_path = pth.gsub("'", "''")
|
|
226
292
|
ps_cmd = "Get-Content -LiteralPath '#{ps_path}' -Raw"
|
|
293
|
+
Verbose.log("powershell -Command #{ps_cmd}")
|
|
227
294
|
out, err, st = Open3.capture3("powershell", "-NoProfile", "-NonInteractive", "-Command", ps_cmd)
|
|
228
295
|
if st.success?
|
|
229
296
|
data = out
|
|
@@ -253,7 +320,7 @@ module VagrantDockerHostsManager
|
|
|
253
320
|
.force_encoding("Windows-1252")
|
|
254
321
|
.encode(Encoding::UTF_8, invalid: :replace, undef: :replace, replace: "")
|
|
255
322
|
UiHelpers.debug(@ui, "Transcoded via Windows-1252 -> UTF-8, encoding=#{data.encoding}")
|
|
256
|
-
rescue => e2
|
|
323
|
+
rescue StandardError => e2
|
|
257
324
|
UiHelpers.debug(@ui, "Windows-1252 fallback failed: #{e2.class}: #{e2.message}")
|
|
258
325
|
data = data.force_encoding(Encoding::UTF_8)
|
|
259
326
|
end
|
|
@@ -265,34 +332,33 @@ module VagrantDockerHostsManager
|
|
|
265
332
|
end
|
|
266
333
|
|
|
267
334
|
data
|
|
268
|
-
rescue => e
|
|
335
|
+
rescue StandardError => e
|
|
269
336
|
UiHelpers.debug(@ui, "read() fatal: #{e.class}: #{e.message}")
|
|
270
337
|
""
|
|
271
338
|
end
|
|
272
339
|
|
|
273
|
-
def
|
|
274
|
-
|
|
275
|
-
|
|
340
|
+
def each_managed_entry(scope = :all)
|
|
341
|
+
# A single scanner powers both current-owner and all-owner cleanup paths
|
|
342
|
+
# so marker parsing rules stay identical.
|
|
343
|
+
return enum_for(:each_managed_entry, scope) unless block_given?
|
|
276
344
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
ip_re = /^\s*(\d{1,3}(?:\.\d{1,3}){3})\s+([^\s#]+)/
|
|
345
|
+
content = read
|
|
346
|
+
return if content.to_s.empty?
|
|
280
347
|
|
|
281
|
-
out = []
|
|
282
348
|
in_block = false
|
|
283
349
|
owner = nil
|
|
284
350
|
|
|
285
351
|
content.each_line.with_index(1) do |raw, idx|
|
|
286
352
|
line = raw.delete_suffix("\n").delete_suffix("\r")
|
|
287
353
|
|
|
288
|
-
if (m = line.match(
|
|
354
|
+
if (m = line.match(BLOCK_START_RE))
|
|
289
355
|
in_block = true
|
|
290
356
|
owner = m[1].to_s.strip
|
|
291
357
|
UiHelpers.debug(@ui, "start block(owner=#{owner}) at line #{idx}")
|
|
292
358
|
next
|
|
293
359
|
end
|
|
294
360
|
|
|
295
|
-
if
|
|
361
|
+
if line.match?(BLOCK_STOP_RE)
|
|
296
362
|
UiHelpers.debug(@ui, "stop block(owner=#{owner}) at line #{idx}") if in_block
|
|
297
363
|
in_block = false
|
|
298
364
|
owner = nil
|
|
@@ -302,103 +368,25 @@ module VagrantDockerHostsManager
|
|
|
302
368
|
next unless in_block
|
|
303
369
|
next unless scope == :all || owner == @owner_id
|
|
304
370
|
|
|
305
|
-
if (m = line.match(
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
UiHelpers.debug(@ui, " ip line: #{ip} #{fqdn} (owner=#{owner})")
|
|
371
|
+
if (m = line.match(ENTRY_RE))
|
|
372
|
+
UiHelpers.debug(@ui, " ip line: #{m[1]} #{m[2]} (owner=#{owner})")
|
|
373
|
+
yield m[1], m[2], owner
|
|
309
374
|
end
|
|
310
375
|
end
|
|
311
|
-
|
|
312
|
-
UiHelpers.debug(@ui, "list_pairs found #{out.length} pair(s)")
|
|
313
|
-
out
|
|
314
376
|
end
|
|
315
377
|
|
|
316
|
-
def
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
stop_prefix = "# <<< vagrant-docker-hosts-manager "
|
|
322
|
-
|
|
323
|
-
in_block = false
|
|
324
|
-
owner = nil
|
|
325
|
-
out = {}
|
|
326
|
-
|
|
327
|
-
content.each_line do |raw|
|
|
328
|
-
line = raw.sub(/\r?\n\z/, "")
|
|
329
|
-
lstr = line.lstrip
|
|
330
|
-
|
|
331
|
-
if lstr.start_with?(start_prefix)
|
|
332
|
-
in_block = true
|
|
333
|
-
tail = lstr[start_prefix.length..-1].to_s
|
|
334
|
-
owner = tail.split(" (managed)").first.to_s.strip
|
|
335
|
-
next
|
|
336
|
-
end
|
|
337
|
-
|
|
338
|
-
if lstr.start_with?(stop_prefix)
|
|
339
|
-
in_block = false
|
|
340
|
-
owner = nil
|
|
341
|
-
next
|
|
342
|
-
end
|
|
343
|
-
|
|
344
|
-
next unless in_block
|
|
345
|
-
next unless scope == :all || owner == @owner_id
|
|
346
|
-
|
|
347
|
-
if lstr =~ /\A\s*(\d{1,3}(?:\.\d{1,3}){3})\s+([^\s#]+)/
|
|
348
|
-
ip, fqdn = $1, $2
|
|
349
|
-
if out.key?(fqdn)
|
|
350
|
-
arr = out[fqdn].is_a?(Array) ? out[fqdn] : [out[fqdn]]
|
|
351
|
-
arr << ip unless arr.include?(ip)
|
|
352
|
-
out[fqdn] = arr
|
|
353
|
-
else
|
|
354
|
-
out[fqdn] = [ip]
|
|
355
|
-
end
|
|
356
|
-
end
|
|
357
|
-
end
|
|
358
|
-
|
|
359
|
-
out
|
|
378
|
+
def list_pairs(scope = :all)
|
|
379
|
+
pairs = []
|
|
380
|
+
each_managed_entry(scope) { |ip, fqdn, owner| pairs << [ip, fqdn, owner] }
|
|
381
|
+
UiHelpers.debug(@ui, "list_pairs found #{pairs.length} pair(s)")
|
|
382
|
+
pairs
|
|
360
383
|
end
|
|
361
384
|
|
|
362
|
-
def
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
start_re = /^\s*#\s*>>>\s*vagrant-docker-hosts-manager\s+(.+?)\s*\(managed\)\s*>>>\s*$/i
|
|
367
|
-
stop_re = /^\s*#\s*<<<\s*vagrant-docker-hosts-manager\s+(.+?)\s*\(managed\)\s*<<<\s*$/i
|
|
368
|
-
|
|
369
|
-
buff = []
|
|
370
|
-
cur = []
|
|
371
|
-
in_block = false
|
|
372
|
-
owner = nil
|
|
373
|
-
|
|
374
|
-
content.each_line do |raw|
|
|
375
|
-
line = raw.delete_suffix("\n").delete_suffix("\r")
|
|
376
|
-
|
|
377
|
-
if (m = line.match(start_re))
|
|
378
|
-
in_block = true
|
|
379
|
-
owner = m[1].to_s.strip
|
|
380
|
-
cur = [line]
|
|
381
|
-
next
|
|
382
|
-
end
|
|
383
|
-
|
|
384
|
-
if in_block
|
|
385
|
-
cur << line
|
|
386
|
-
if line.match?(stop_re)
|
|
387
|
-
if scope == :all || owner == @owner_id
|
|
388
|
-
buff << cur.join("\n")
|
|
389
|
-
end
|
|
390
|
-
in_block = false
|
|
391
|
-
owner = nil
|
|
392
|
-
cur = []
|
|
393
|
-
end
|
|
394
|
-
end
|
|
385
|
+
def entries_in_blocks(scope = :current)
|
|
386
|
+
each_managed_entry(scope).with_object({}) do |(ip, fqdn, _owner), out|
|
|
387
|
+
arr = (out[fqdn] ||= [])
|
|
388
|
+
arr << ip unless arr.include?(ip)
|
|
395
389
|
end
|
|
396
|
-
|
|
397
|
-
buff.join("\n\n\n")
|
|
398
|
-
end
|
|
399
|
-
|
|
400
|
-
def current_entries
|
|
401
|
-
entries_in_blocks(:current)
|
|
402
390
|
end
|
|
403
391
|
|
|
404
392
|
def remove_block_from(content)
|
|
@@ -424,12 +412,13 @@ module VagrantDockerHostsManager
|
|
|
424
412
|
[Security.Principal.WindowsIdentity]::GetCurrent()
|
|
425
413
|
)).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
|
426
414
|
}.strip
|
|
415
|
+
Verbose.log("powershell -Command (check administrator role)")
|
|
427
416
|
out, _err, st = Open3.capture3("powershell", "-NoProfile", "-NonInteractive", "-Command", cmd)
|
|
428
417
|
st.success? && out.to_s.strip.downcase == "true"
|
|
429
418
|
else
|
|
430
419
|
begin
|
|
431
420
|
Process.euid == 0
|
|
432
|
-
rescue
|
|
421
|
+
rescue StandardError
|
|
433
422
|
false
|
|
434
423
|
end
|
|
435
424
|
end
|
|
@@ -446,31 +435,50 @@ module VagrantDockerHostsManager
|
|
|
446
435
|
begin
|
|
447
436
|
tf.binmode
|
|
448
437
|
tf.write(content); tf.flush
|
|
449
|
-
|
|
438
|
+
Verbose.log("sudo", "cp", tf.path, real_path)
|
|
439
|
+
system("sudo", "cp", tf.path, real_path) || raise("sudo copy failed")
|
|
450
440
|
ensure
|
|
451
441
|
tf.close!
|
|
452
442
|
end
|
|
453
443
|
end
|
|
454
444
|
|
|
455
445
|
def write_windows(content)
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
446
|
+
# Try a direct write first; fall back to UAC only when the hosts file
|
|
447
|
+
# rejects it. Base64/UTF-16LE keeps PowerShell quoting predictable.
|
|
448
|
+
b64 = Base64.strict_encode64(
|
|
449
|
+
content.encode("UTF-8", invalid: :replace, undef: :replace, replace: "")
|
|
450
|
+
)
|
|
451
|
+
dest = real_path.gsub("'", "''")
|
|
452
|
+
|
|
453
|
+
ps = <<~POW
|
|
454
|
+
$ErrorActionPreference = "Stop"
|
|
455
|
+
try {
|
|
456
|
+
$bytes = [System.Convert]::FromBase64String('#{b64}')
|
|
457
|
+
[System.IO.File]::WriteAllBytes('#{dest}', $bytes)
|
|
458
|
+
exit 0
|
|
459
|
+
} catch {
|
|
460
|
+
exit 1
|
|
461
|
+
}
|
|
462
|
+
POW
|
|
463
|
+
encoded = Base64.strict_encode64(ps.encode("UTF-16LE"))
|
|
464
|
+
|
|
465
|
+
Verbose.log("powershell -EncodedCommand (write hosts file: #{real_path})")
|
|
466
|
+
_out, _err, st = Open3.capture3("powershell", "-NoProfile", "-NonInteractive", "-EncodedCommand", encoded)
|
|
467
|
+
return if st.success?
|
|
468
|
+
|
|
469
|
+
elev_ps = <<~POW
|
|
470
|
+
$ErrorActionPreference = 'Stop'
|
|
471
|
+
try {
|
|
472
|
+
$p = Start-Process PowerShell -Verb RunAs -Wait -PassThru -ArgumentList '-NonInteractive','-NoProfile','-EncodedCommand','#{encoded}'
|
|
473
|
+
exit $p.ExitCode
|
|
474
|
+
} catch {
|
|
475
|
+
exit 1
|
|
476
|
+
}
|
|
477
|
+
POW
|
|
478
|
+
elev_encoded = Base64.strict_encode64(elev_ps.encode("UTF-16LE"))
|
|
479
|
+
Verbose.log("powershell -EncodedCommand (elevated write hosts file via RunAs: #{real_path})")
|
|
480
|
+
system("powershell", "-NoProfile", "-NonInteractive", "-EncodedCommand", elev_encoded) ||
|
|
481
|
+
raise("elevated write failed")
|
|
474
482
|
end
|
|
475
483
|
end
|
|
476
484
|
end
|
|
@@ -1,34 +1,42 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "i18n"
|
|
4
|
+
require_relative "../helpers"
|
|
4
5
|
|
|
5
6
|
module VagrantDockerHostsManager
|
|
6
7
|
module Util
|
|
7
8
|
module I18n
|
|
8
|
-
SUPPORTED = [:en, :fr].freeze
|
|
9
9
|
@json = false
|
|
10
10
|
|
|
11
11
|
module_function
|
|
12
12
|
|
|
13
13
|
def setup!(env, forced: nil)
|
|
14
|
-
|
|
14
|
+
UiHelpers.setup_i18n!
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
if forced
|
|
17
|
+
begin
|
|
18
|
+
UiHelpers.set_locale!(forced)
|
|
19
|
+
rescue UiHelpers::UnsupportedLocaleError
|
|
20
|
+
UiHelpers.set_locale!("en")
|
|
21
|
+
end
|
|
22
|
+
end
|
|
21
23
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
begin
|
|
25
|
+
cfg = env[:machine]&.config&.docker_hosts
|
|
26
|
+
if cfg&.respond_to?(:locale) && !cfg.locale.to_s.strip.empty?
|
|
27
|
+
UiHelpers.setup_locale_from_config!(cfg)
|
|
28
|
+
end
|
|
29
|
+
rescue StandardError
|
|
30
|
+
nil
|
|
31
|
+
end
|
|
25
32
|
|
|
26
33
|
begin
|
|
27
|
-
if env[:ui] && env[:machine]
|
|
34
|
+
if env[:ui] && env[:machine]&.config&.docker_hosts&.respond_to?(:verbose) &&
|
|
28
35
|
env[:machine].config.docker_hosts.verbose
|
|
29
|
-
env[:ui].info(::I18n.t("messages.lang_set", lang: ::I18n.locale))
|
|
36
|
+
env[:ui].info(::I18n.t("vdhm.messages.lang_set", lang: ::I18n.locale))
|
|
30
37
|
end
|
|
31
38
|
rescue StandardError
|
|
39
|
+
nil
|
|
32
40
|
end
|
|
33
41
|
end
|
|
34
42
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "shellwords"
|
|
4
|
+
|
|
5
|
+
module VagrantDockerHostsManager
|
|
6
|
+
module Util
|
|
7
|
+
module Verbose
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
def enabled?
|
|
11
|
+
ENV["VDHM_VERBOSE"].to_s == "1"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def log(*args)
|
|
15
|
+
return unless enabled?
|
|
16
|
+
|
|
17
|
+
line = args.length == 1 && args.first.is_a?(String) ? args.first : args.map(&:to_s).shelljoin
|
|
18
|
+
warn("[VDHM] #{line}")
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module VagrantDockerHostsManager
|
|
4
|
-
VERSION
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
unless defined?(VERSION)
|
|
5
|
+
VERSION = begin
|
|
6
|
+
path = File.expand_path("VERSION", __dir__)
|
|
7
|
+
File.exist?(path) ? File.read(path).strip : "0.0.0"
|
|
8
|
+
rescue StandardError
|
|
9
|
+
"0.0.0"
|
|
10
|
+
end
|
|
9
11
|
end
|
|
10
12
|
end
|