Class: VagrantPlugins::HostsProvisioner::Hosts

Inherits:
Object
  • Object
show all
Defined in:
lib/vagrant-servant-hosts-provisioner/hosts.rb

Defined Under Namespace

Modules: WindowsSupport

Instance Method Summary collapse

Constructor Details

#initialize(machine, config) ⇒ Hosts

Returns a new instance of Hosts.



7
8
9
10
# File 'lib/vagrant-servant-hosts-provisioner/hosts.rb', line 7

def initialize(machine, config)
  @machine = machine
  @config = config
end

Instance Method Details

#addObject



12
13
14
15
16
17
18
19
20
21
22
# File 'lib/vagrant-servant-hosts-provisioner/hosts.rb', line 12

def add
  # Update the guest machine if manage_guest is enabled
  if @config.manage_guest
    update_guest
  end

  # Update the host machine if manage_host is enabled
  if @config.manage_host
    update_host(false)
  end
end

#get_files_dataObject



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/vagrant-servant-hosts-provisioner/hosts.rb', line 152

def get_files_data
  require 'json'
  data = []
  @config.files.each do |file|
    if file.kind_of?(String) && file != ""
      file_path = File.join(@machine.env.root_path, file)
      if File.exist?(file_path)
        file_data = JSON.parse(File.read(file_path))
        data.concat([ file_data ].flatten)
      else
        handle_comm(:stderr, I18n.t("vagrant_hostsprovisioner.error.file_not_found", {:file => file.to_s}))
      end
    end
  end
  data.collect(&:strip)
end

#get_hosts_file_entryObject



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/vagrant-servant-hosts-provisioner/hosts.rb', line 112

def get_hosts_file_entry
  # Get the vm ip address
  ip = get_ip_address

  # Return empy string if we don't have an ip address
  if ip === nil
    handle_comm(:stderr, I18n.t("vagrant_hostsprovisioner.error.no_vm_ip"))
    return ''
  end

  hosts = []

  # Add the machine hostname
  unless @config.hostname === false
    hosts.push(@config.hostname || @machine.config.vm.hostname || @machine.name)
  end

  # Add the defined aliases
  hosts.concat(@config.aliases)

  # Add the contents of the defined hosts files
  if @config.files.count > 0
    hosts.concat(get_files_data)
  end

  # Remove duplicates
  hosts = hosts.uniq

  # Limit the number of hosts per line to 8
  lines = []
  hosts.each_slice(8) do |chnk|
    lines.push("#{ip}\t" + chnk.join(' ').strip)
  end

  # Join lines
  hosts = lines.join("\n").strip

  "#{hosts}\n"
end

#get_ip_addressObject



169
170
171
172
173
174
175
176
177
178
# File 'lib/vagrant-servant-hosts-provisioner/hosts.rb', line 169

def get_ip_address
  ip = nil
  @machine.config.vm.networks.each do |network|
    key, options = network[0], network[1]
    ip = options[:ip] if key == :private_network
    break if ip
  end
  # If no ip is defined in private_network then use the ssh host ip instead
  ip || (@machine.ssh_info ? @machine.ssh_info[:host] : nil)
end

#get_new_content(header, footer, body, old_content) ⇒ Object



180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/vagrant-servant-hosts-provisioner/hosts.rb', line 180

def get_new_content(header, footer, body, old_content)
  if body.empty?
    block = "\n"
  else
    block = "\n\n" + header + body + footer + "\n"
  end
  # Pattern for finding existing block
  header_pattern = Regexp.quote(header)
  footer_pattern = Regexp.quote(footer)
  pattern = Regexp.new("\n*#{header_pattern}.*?#{footer_pattern}\n*", Regexp::MULTILINE)
  # Replace existing block or append
  old_content.match(pattern) ? old_content.sub(pattern, block) : old_content.rstrip + block
end

#handle_comm(type, data) ⇒ Object

This handles outputting the communication data back to the UI



246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/vagrant-servant-hosts-provisioner/hosts.rb', line 246

def handle_comm(type, data)
  if [:stderr, :stdout].include?(type)
    # Output the data with the proper color based on the stream.
    color = type == :stdout ? :green : :red

    # Clear out the newline since we add one
    data = data.chomp
    return if data.empty?

    options = {}
    options[:color] = color

    prefix = "[hosts-updater]"

    @machine.ui.info(prefix + " " +  data.chomp, options)
  end
end

#read_or_create_idObject



194
195
196
197
198
199
200
201
202
203
204
# File 'lib/vagrant-servant-hosts-provisioner/hosts.rb', line 194

def read_or_create_id
  file = Pathname.new("#{@machine.env.local_data_path}/hostsprovisioner/#{@machine.name}")
  if (file.file?)
    id = file.read.strip
  else
    id = SecureRandom.uuid
    file.dirname.mkpath
    file.open('w') { |f| f.write(id) }
  end
  id + "-" + @config.id.to_s
end

#removeObject



24
25
26
27
28
# File 'lib/vagrant-servant-hosts-provisioner/hosts.rb', line 24

def remove
  if @config.manage_host
    update_host(true)
  end
end

#update_content(file_content, include_id, clean) ⇒ Object



104
105
106
107
108
109
110
# File 'lib/vagrant-servant-hosts-provisioner/hosts.rb', line 104

def update_content(file_content, include_id, clean)
  id = include_id ? " id: #{read_or_create_id}" : ""
  header = "## vagrant-servant-hosts-provisioner-start#{id}\n"
  footer = "## vagrant-servant-hosts-provisioner-end\n"
  body = clean ? "" : get_hosts_file_entry
  get_new_content(header, footer, body, file_content)
end

#update_file(file, include_id, clean) ⇒ Object



96
97
98
99
100
101
102
# File 'lib/vagrant-servant-hosts-provisioner/hosts.rb', line 96

def update_file(file, include_id, clean)
  file = Pathname.new(file)
  old_file_content = file.read
  new_file_content = update_content(old_file_content, include_id, clean)
  file.open('w') { |io| io.write(new_file_content) }
  old_file_content != new_file_content
end

#update_guestObject



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/vagrant-servant-hosts-provisioner/hosts.rb', line 30

def update_guest
  return unless @machine.communicate.ready?

  handle_comm(:stdout, I18n.t("vagrant_hostsprovisioner.provisioner.update_guest"))

  if (@machine.communicate.test("uname -s | grep SunOS"))
    realhostfile = '/etc/inet/hosts'
    move_cmd = 'mv'
  elsif (@machine.communicate.test("test -d $Env:SystemRoot"))
    windir = ""
    @machine.communicate.execute("echo %SYSTEMROOT%", {:shell => :cmd}) do |type, contents|
      windir << contents.gsub("\r\n", '') if type == :stdout
    end
    realhostfile = "#{windir}\\System32\\drivers\\etc\\hosts"
    move_cmd = 'mv -force'
  else
    realhostfile = '/etc/hosts'
    move_cmd = 'mv -f'
  end

  # download and modify file with Vagrant-managed entries
  file = @machine.env.tmp_path.join("hosts.#{@machine.name}")
  @machine.communicate.download(realhostfile, file)
  if update_file(file, false, false)
    # upload modified file and remove temporary file
    @machine.communicate.upload(file, '/tmp/hosts')
    @machine.communicate.sudo("#{move_cmd} /tmp/hosts #{realhostfile}")
    handle_comm(:stdout, I18n.t("vagrant_hostsprovisioner.provisioner.hosts_file_updated", {:file => realhostfile}))
  end

  begin
    FileUtils.rm(file)
   rescue Exception => e
  end
end

#update_host(clean) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/vagrant-servant-hosts-provisioner/hosts.rb', line 66

def update_host(clean)
  # copy and modify hosts file on host with Vagrant-managed entries
  file = @machine.env.tmp_path.join('hosts.local')

  if clean == true
    handle_comm(:stdout, I18n.t("vagrant_hostsprovisioner.provisioner.clean_host"))
  else
    handle_comm(:stdout, I18n.t("vagrant_hostsprovisioner.provisioner.update_host"))
  end

  if WindowsSupport.windows?
    # lazily include windows Module
    class << self
      include WindowsSupport unless include? WindowsSupport
    end

    hosts_location = "#{ENV['WINDIR']}\\System32\\drivers\\etc\\hosts"
    copy_proc = Proc.new { windows_copy_file(file, hosts_location) }
  else
    hosts_location = '/etc/hosts'
    copy_proc = Proc.new { `sudo cp #{file} #{hosts_location}` }
  end

  FileUtils.cp(hosts_location, file)
  if update_file(file, true, clean)
    copy_proc.call
    handle_comm(:stdout, I18n.t("vagrant_hostsprovisioner.provisioner.hosts_file_updated", {:file => hosts_location}))
  end
end