vagrant-hostmanager-docker 1.6.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0124b76857be3d5c46152d25538438b14bf30f15
4
+ data.tar.gz: 5e2f2b12e029f7df8a69c0f024ced1e84cfb8952
5
+ SHA512:
6
+ metadata.gz: 90ea7d7b7d6ae4a7a3df319daef6af12059621af2afb9b4c63f876bb1a434ab45e435f40236b463836298010fb2f629428e96f93b29811eeaf00cd960012052c
7
+ data.tar.gz: 0388f2198670eb1bfdd21e9a8feb62c9255506a567a1104904f21471e5169d5077347dbd10194d8a1273acc00bd5e4182a51f15c14e3a16bcf857afa90e1aea0
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ pkg
3
+ Gemfile.lock
4
+ test/.vagrant
@@ -0,0 +1,67 @@
1
+ # Changelog
2
+
3
+ ## 1.6.1
4
+ ### Bug fixes
5
+ * Retain tmp hosts file and fix a bug where powershell mv does not move folder contents, in that context it's moving a file. [[#157](https://github.com/smdahlen/vagrant-hostmanager/issues/157)]
6
+
7
+ [Full diff](https://github.com/smdahlen/vagrant-hostmanager/compare/v1.6.0...v1.6.1)
8
+
9
+
10
+ ## 1.6.0
11
+ ### Features
12
+ * splits hostnames across many lines [[#67](https://github.com/smdahlen/vagrant-hostmanager/pull/103)]
13
+
14
+ ### Bug fixes
15
+ * show description for hostmanager when vagrant list-commands is triggered [[#105](https://github.com/smdahlen/vagrant-hostmanager/pull/105)]
16
+
17
+ ### Miscelaneous
18
+ * extract old vagrant version compatibility code into util method [[#97](https://github.com/smdahlen/vagrant-hostmanager/pull/97)]
19
+ * migrate HostsFile code into its own class [[#98](https://github.com/smdahlen/vagrant-hostmanager/pull/97)]
20
+
21
+ [Full diff](https://github.com/smdahlen/vagrant-hostmanager/compare/v1.5.0...v1.6.0)
22
+
23
+
24
+ ## 1.5.0
25
+ ### Features
26
+ * hostmanager now runs *before* provisioning takes place, on `up` action [[#73](https://github.com/smdahlen/vagrant-hostmanager/issues/73)]
27
+
28
+ ### Bug fixes
29
+ * properly detect hosts file location on Windows guests [[#67](https://github.com/smdahlen/vagrant-hostmanager/pull/67)]
30
+ * do not add host if IP cannot be determined [[#85](https://github.com/smdahlen/vagrant-hostmanager/pull/85)]
31
+ * force moving of hosts file on Linux guests [[#93](https://github.com/smdahlen/vagrant-hostmanager/pull/93)]
32
+ * allow top-level config options (eg. `ip_resolver`) to propagate to machine configs [[#91](https://github.com/smdahlen/vagrant-hostmanager/issues/91)]
33
+
34
+ ### Miscelaneous
35
+ * add passwordless sudo instructions to README [[#95](https://github.com/smdahlen/vagrant-hostmanager/pull/95)]
36
+
37
+ [Full diff](https://github.com/smdahlen/vagrant-hostmanager/compare/v1.4.0...v1.5.0)
38
+
39
+
40
+ ## 1.4.0
41
+ ### Features
42
+ * supports vagrant 1.5 [[#80](https://github.com/smdahlen/vagrant-hostmanager/issues/80), [#81](https://github.com/smdahlen/vagrant-hostmanager/pull/81)]
43
+ * only updates hosts file if contents have changed [[#78](https://github.com/smdahlen/vagrant-hostmanager/pull/78)]
44
+ * custom ip resolver now has access to the machine whose hosts file is being updated [[#62](https://github.com/smdahlen/vagrant-hostmanager/pull/62)]
45
+
46
+ ### Bug fixes
47
+ * custom IP resolver result no longer ignored [[#57](https://github.com/smdahlen/vagrant-hostmanager/pull/57)]
48
+ * when multiple private_networks are configured, the first one is used [[#64](https://github.com/smdahlen/vagrant-hostmanager/pull/64)]
49
+ * destroyed machines are now removed from hosts file [[#52](https://github.com/smdahlen/vagrant-hostmanager/pull/52)]
50
+
51
+ [Full diff](https://github.com/smdahlen/vagrant-hostmanager/compare/v1.3.0...v1.4.0)
52
+
53
+
54
+ ## 1.3.0
55
+ ### Features
56
+ * allow defining a custom IP resolver block [[#15](https://github.com/smdahlen/vagrant-hostmanager/pull/15)]
57
+ * handle removing destroyed machines from hosts file (currently only works with `include_offline = true`) [[#45](https://github.com/smdahlen/vagrant-hostmanager/pull/45)]
58
+ * attempt to elevate privileges when needed in Windows hosts [[#48](https://github.com/smdahlen/vagrant-hostmanager/pull/48)]
59
+
60
+ ### Bug fixes
61
+ * `--provider` command-line option now finds machines as expected [[#46](https://github.com/smdahlen/vagrant-hostmanager/pull/46)]
62
+ * uses proper `hosts` file location in Windows under cygwin [[#49](https://github.com/smdahlen/vagrant-hostmanager/pull/49)]
63
+
64
+ ### Miscelaneous
65
+ * MIT license added to gemspec
66
+
67
+ [Full diff](https://github.com/smdahlen/vagrant-hostmanager/compare/v1.2.3...v1.3.0)
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :development do
4
+ gem 'vagrant', :git => 'git://github.com/mitchellh/vagrant.git', :tag => 'v1.6.2'
5
+ end
6
+
7
+ group :plugins do
8
+ gemspec
9
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Shawn Dahlen
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,168 @@
1
+ Vagrant Host Manager
2
+ ====================
3
+
4
+ [![Gem](https://img.shields.io/gem/dt/vagrant-hostmanager.svg)](https://rubygems.org/gems/vagrant-hostmanager)
5
+ [![Gem](https://img.shields.io/gem/dtv/vagrant-hostmanager.svg)](https://rubygems.org/gems/vagrant-hostmanager)
6
+ [![Twitter](https://img.shields.io/twitter/url/https/github.com/smdahlen/vagrant-hostmanager.svg?style=social)](https://twitter.com/intent/tweet?text=Check%20out%20this%20awesome%20Vagrant%20plugin%21&url=https%3A%2F%2Fgithub.com%2Fsmdahlen%2Fvagrant-hostmanager&hashtags=vagrant%hostmanager&original_referer=)
7
+
8
+ `vagrant-hostmanager` is a Vagrant 1.1+ plugin that manages the `/etc/hosts`
9
+ file on guest machines (and optionally the host). Its goal is to enable
10
+ resolution of multi-machine environments deployed with a cloud provider
11
+ where IP addresses are not known in advance.
12
+
13
+ *NOTE:* Version 1.1 of the plugin prematurely introduced a feature to hook into
14
+ commands other than `vagrant up` and `vagrant destroy`. Version 1.1 broke support
15
+ for some providers. Version 1.2 reverts this feature until a suitable implementation
16
+ supporting all providers is available.
17
+
18
+ ***Potentially breaking change in v1.5.0:*** the running order on `vagrant up` has changed
19
+ so that hostmanager runs before provisioning takes place. This ensures all hostnames are
20
+ available to the guest when it is being provisioned
21
+ (see [#73](https://github.com/smdahlen/vagrant-hostmanager/issues/73)).
22
+ Previously, hostmanager would run as the very last action. If you depend on the old behavior,
23
+ see the [provisioner](#provisioner) section.
24
+
25
+ Installation
26
+ ------------
27
+ Install the plugin following the typical Vagrant 1.1 procedure:
28
+
29
+ $ vagrant plugin install vagrant-hostmanager
30
+
31
+ Usage
32
+ -----
33
+ To update the `/etc/hosts` file on each active machine, run the following
34
+ command:
35
+
36
+ $ vagrant hostmanager
37
+
38
+ The plugin hooks into the `vagrant up` and `vagrant destroy` commands
39
+ automatically.
40
+ When a machine enters or exits the running state , all active
41
+ machines with the same provider will have their `/etc/hosts` file updated
42
+ accordingly. Set the `hostmanager.enabled` attribute to `true` in the
43
+ Vagrantfile to activate this behavior.
44
+
45
+ To update the host's `/etc/hosts` file, set the `hostmanager.manage_host`
46
+ attribute to `true`.
47
+
48
+ A machine's IP address is defined by either the static IP for a private
49
+ network configuration or by the SSH host configuration. To disable
50
+ using the private network IP address, set `config.hostmanager.ignore_private_ip`
51
+ to true.
52
+
53
+ A machine's host name is defined by `config.vm.hostname`. If this is not
54
+ set, it falls back to the symbol defining the machine in the Vagrantfile.
55
+
56
+ If the `hostmanager.include_offline` attribute is set to `true`, boxes that are
57
+ up or have a private ip configured will be added to the hosts file.
58
+
59
+ In addition, the `hostmanager.aliases` configuration attribute can be used
60
+ to provide aliases for your host names.
61
+
62
+ Example configuration:
63
+
64
+ ```ruby
65
+ Vagrant.configure("2") do |config|
66
+ config.hostmanager.enabled = true
67
+ config.hostmanager.manage_host = true
68
+ config.hostmanager.ignore_private_ip = false
69
+ config.hostmanager.include_offline = true
70
+ config.vm.define 'example-box' do |node|
71
+ node.vm.hostname = 'example-box-hostname'
72
+ node.vm.network :private_network, ip: '192.168.42.42'
73
+ node.hostmanager.aliases = %w(example-box.localdomain example-box-alias)
74
+ end
75
+ end
76
+ ```
77
+
78
+ ### Provisioner
79
+
80
+ Starting at version 1.5.0, `vagrant up` runs hostmanager before any provisioning occurs.
81
+ If you would like hostmanager to run after or during your provisioning stage,
82
+ you can use hostmanager as a provisioner. This allows you to use the provisioning
83
+ order to ensure that hostmanager runs when desired. The provisioner will collect
84
+ hosts from boxes with the same provider as the running box.
85
+
86
+ Example:
87
+
88
+ ```ruby
89
+ # Disable the default hostmanager behavior
90
+ config.hostmanager.enabled = false
91
+
92
+ # ... possible provisioner config before hostmanager ...
93
+
94
+ # hostmanager provisioner
95
+ config.vm.provision :hostmanager
96
+
97
+ # ... possible provisioning config after hostmanager ...
98
+ ```
99
+
100
+ Custom IP resolver
101
+ ------------------
102
+
103
+ You can customize way, how host manager resolves IP address
104
+ for each machine. This might be handy in case of aws provider,
105
+ where host name is stored in ssh_info hash of each machine.
106
+ This causes generation of invalid /etc/hosts file.
107
+
108
+ Custom IP resolver gives you oportunity to calculate IP address
109
+ for each machine by yourself, giving You also access to the machine that is
110
+ updating /etc/hosts. For example:
111
+
112
+ ```ruby
113
+ config.hostmanager.ip_resolver = proc do |vm, resolving_vm|
114
+ if hostname = (vm.ssh_info && vm.ssh_info[:host])
115
+ `host #{hostname}`.split("\n").last[/(\d+\.\d+\.\d+\.\d+)/, 1]
116
+ end
117
+ end
118
+ ```
119
+
120
+ Passwordless sudo
121
+ -----------------
122
+
123
+ Add the following snippet to the sudoers file (for example, to
124
+ ```/etc/sudoers.d/vagrant_hostmanager```) to make it stop asking
125
+ password when updating hosts file (replace ```/home/user``` with your
126
+ actual home directory):
127
+
128
+ Cmnd_Alias VAGRANT_HOSTMANAGER_UPDATE = /bin/cp /home/user/.vagrant.d/tmp/hosts.local /etc/hosts
129
+ %sudo ALL=(root) NOPASSWD: VAGRANT_HOSTMANAGER_UPDATE
130
+
131
+ Windows support
132
+ ---------------
133
+
134
+ Hostmanager will detect Windows guests and hosts and use the appropriate
135
+ path for the ```hosts``` file: ```%WINDIR%\System32\drivers\etc\hosts```
136
+
137
+ By default on a Windows host, the ```hosts``` file is not writable without
138
+ elevated privileges. If hostmanager detects that it cannot overwrite the file,
139
+ it will attempt to do so with elevated privileges, causing the
140
+ [UAC](http://en.wikipedia.org/wiki/User_Account_Control) prompt to appear.
141
+
142
+ ### UAC limitations
143
+
144
+ Due to limitations caused by UAC, cancelling out of the UAC prompt will not cause any
145
+ visible errors, however the ```hosts``` file will not be updated.
146
+
147
+ Installing development version
148
+ ------------------------------
149
+
150
+ If you want to install the bleeding version of vagrant-hostmanager (*at your own risk*), you can do the following
151
+ (requires ruby and git):
152
+
153
+ ```
154
+ git clone https://github.com/smdahlen/vagrant-hostmanager.git
155
+ cd vagrant-hostmanager
156
+ rake gem:build
157
+ vagrant plugin install pkg/vagrant-hostmanager-*.gem
158
+ ```
159
+
160
+ Contribute
161
+ ----------
162
+ Contributions are welcome.
163
+
164
+ 1. Fork it
165
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
166
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
167
+ 4. Push to the branch (`git push origin my-new-feature`)
168
+ 5. Create new Pull Request
@@ -0,0 +1,12 @@
1
+ require 'bundler/gem_helper'
2
+
3
+ # Change to the directory of this file.
4
+ Dir.chdir(File.expand_path("../", __FILE__))
5
+
6
+ namespace :gem do
7
+ Bundler::GemHelper.install_tasks
8
+ end
9
+
10
+ task :test do
11
+ sh 'bash test/test.sh'
12
+ end
@@ -0,0 +1,14 @@
1
+ require 'vagrant-hostmanager/plugin'
2
+ require 'vagrant-hostmanager/version'
3
+ require 'vagrant-hostmanager/errors'
4
+
5
+ module VagrantPlugins
6
+ module HostManager
7
+ def self.source_root
8
+ @source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
9
+ end
10
+
11
+ I18n.load_path << File.expand_path('locales/en.yml', source_root)
12
+ I18n.reload!
13
+ end
14
+ end
@@ -0,0 +1,31 @@
1
+ require 'vagrant-hostmanager/action/update_all'
2
+ require 'vagrant-hostmanager/action/update_guest'
3
+ require 'vagrant-hostmanager/action/update_host'
4
+
5
+ module VagrantPlugins
6
+ module HostManager
7
+ module Action
8
+ include Vagrant::Action::Builtin
9
+
10
+ def self.update_all
11
+ Vagrant::Action::Builder.new.tap do |builder|
12
+ builder.use ConfigValidate
13
+ builder.use UpdateAll
14
+ end
15
+ end
16
+
17
+ def self.update_guest
18
+ Vagrant::Action::Builder.new.tap do |builder|
19
+ builder.use ConfigValidate
20
+ builder.use UpdateGuest
21
+ end
22
+ end
23
+
24
+ def self.update_host
25
+ Vagrant::Action::Builder.new.tap do |builder|
26
+ builder.use UpdateHost
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,47 @@
1
+ require 'vagrant-hostmanager/hosts_file/updater'
2
+ require 'vagrant-hostmanager/util'
3
+
4
+ module VagrantPlugins
5
+ module HostManager
6
+ module Action
7
+ class UpdateAll
8
+
9
+ def initialize(app, env)
10
+ @app = app
11
+ @machine = env[:machine]
12
+ @global_env = @machine.env
13
+ @provider = @machine.provider_name
14
+ @config = Util.get_config(@global_env)
15
+ @updater = HostsFile::Updater.new(@global_env, @provider)
16
+ @logger = Log4r::Logger.new('vagrant::hostmanager::update_all')
17
+ end
18
+
19
+ def call(env)
20
+ # skip if machine is not active on destroy action
21
+ return @app.call(env) if !@machine.id && env[:machine_action] == :destroy
22
+
23
+ # check config to see if the hosts file should be update automatically
24
+ return @app.call(env) unless @config.hostmanager.enabled?
25
+ @logger.info 'Updating /etc/hosts file automatically'
26
+
27
+ @app.call(env)
28
+
29
+ # update /etc/hosts file on active machines
30
+ env[:ui].info I18n.t('vagrant_hostmanager.action.update_guests')
31
+ @global_env.active_machines.each do |name, p|
32
+ if p == @provider
33
+ machine = @global_env.machine(name, p)
34
+ @updater.update_guest(machine)
35
+ end
36
+ end
37
+
38
+ # update /etc/hosts files on host if enabled
39
+ if @machine.config.hostmanager.manage_host?
40
+ env[:ui].info I18n.t('vagrant_hostmanager.action.update_host')
41
+ @updater.update_host
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,27 @@
1
+ require 'vagrant-hostmanager/hosts_file/updater'
2
+ require 'vagrant-hostmanager/util'
3
+
4
+ module VagrantPlugins
5
+ module HostManager
6
+ module Action
7
+ class UpdateGuest
8
+
9
+ def initialize(app, env)
10
+ @app = app
11
+ @machine = env[:machine]
12
+ @updater = HostsFile::Updater.new(@machine.env, env[:provider])
13
+ @logger = Log4r::Logger.new('vagrant::hostmanager::update_guest')
14
+ end
15
+
16
+ def call(env)
17
+ env[:ui].info I18n.t('vagrant_hostmanager.action.update_guest', {
18
+ :name => @machine.name
19
+ })
20
+ @updater.update_guest(@machine)
21
+
22
+ @app.call(env)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,30 @@
1
+ require 'vagrant-hostmanager/hosts_file/updater'
2
+ require 'vagrant-hostmanager/util'
3
+
4
+ module VagrantPlugins
5
+ module HostManager
6
+ module Action
7
+ class UpdateHost
8
+
9
+ def initialize(app, env)
10
+ @app = app
11
+
12
+ global_env = env[:global_env]
13
+ @config = Util.get_config(global_env)
14
+ @updater = HostsFile::Updater.new(global_env, env[:provider])
15
+
16
+ @logger = Log4r::Logger.new('vagrant::hostmanager::update_host')
17
+ end
18
+
19
+ def call(env)
20
+ if @config.hostmanager.manage_host?
21
+ env[:ui].info I18n.t('vagrant_hostmanager.action.update_host')
22
+ @updater.update_host
23
+ end
24
+
25
+ @app.call(env)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,43 @@
1
+ module VagrantPlugins
2
+ module HostManager
3
+ class Command < Vagrant.plugin('2', :command)
4
+
5
+ # Show description when `vagrant list-commands` is triggered
6
+ def self.synopsis
7
+ "plugin: vagrant-hostmanager: manages the /etc/hosts file within a multi-machine environment"
8
+ end
9
+
10
+ def execute
11
+ options = {}
12
+ opts = OptionParser.new do |o|
13
+ o.banner = 'Usage: vagrant hostmanager [vm-name]'
14
+ o.separator ''
15
+ o.version = VagrantPlugins::HostManager::VERSION
16
+ o.program_name = 'vagrant hostmanager'
17
+
18
+ o.on('--provider provider', String,
19
+ 'Update machines with the specific provider.') do |provider|
20
+ options[:provider] = provider.to_sym
21
+ end
22
+ end
23
+
24
+ argv = parse_options(opts)
25
+ options[:provider] ||= @env.default_provider
26
+
27
+ # update /etc/hosts file for specified guest machines
28
+ with_target_vms(argv, options) do |machine|
29
+ @env.action_runner.run(Action.update_guest, {
30
+ :machine => machine,
31
+ :provider => options[:provider]
32
+ })
33
+ end
34
+
35
+ # update /etc/hosts file for host
36
+ @env.action_runner.run(Action.update_host, {
37
+ :global_env => @env,
38
+ :provider => options[:provider]
39
+ })
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,80 @@
1
+ module VagrantPlugins
2
+ module HostManager
3
+ class Config < Vagrant.plugin('2', :config)
4
+ attr_accessor :enabled
5
+ attr_accessor :manage_host
6
+ attr_accessor :ignore_private_ip
7
+ attr_accessor :aliases
8
+ attr_accessor :include_offline
9
+ attr_accessor :ip_resolver
10
+
11
+ alias_method :enabled?, :enabled
12
+ alias_method :include_offline?, :include_offline
13
+ alias_method :manage_host?, :manage_host
14
+
15
+ def initialize
16
+ @enabled = UNSET_VALUE
17
+ @manage_host = UNSET_VALUE
18
+ @ignore_private_ip = UNSET_VALUE
19
+ @include_offline = UNSET_VALUE
20
+ @aliases = UNSET_VALUE
21
+ @ip_resolver = UNSET_VALUE
22
+ end
23
+
24
+ def finalize!
25
+ @enabled = false if @enabled == UNSET_VALUE
26
+ @manage_host = false if @manage_host == UNSET_VALUE
27
+ @ignore_private_ip = false if @ignore_private_ip == UNSET_VALUE
28
+ @include_offline = false if @include_offline == UNSET_VALUE
29
+ @aliases = [] if @aliases == UNSET_VALUE
30
+ @ip_resolver = nil if @ip_resolver == UNSET_VALUE
31
+
32
+ @aliases = [ @aliases ].flatten
33
+ end
34
+
35
+ def validate(machine)
36
+ errors = []
37
+
38
+ errors << validate_bool('hostmanager.enabled', @enabled)
39
+ errors << validate_bool('hostmanager.manage_host', @manage_host)
40
+ errors << validate_bool('hostmanager.ignore_private_ip', @ignore_private_ip)
41
+ errors << validate_bool('hostmanager.include_offline', @include_offline)
42
+ errors.compact!
43
+
44
+ # check if aliases option is an Array
45
+ if !machine.config.hostmanager.aliases.kind_of?(Array) &&
46
+ !machine.config.hostmanager.aliases.kind_of?(String)
47
+ errors << I18n.t('vagrant_hostmanager.config.not_an_array_or_string', {
48
+ :config_key => 'hostmanager.aliases',
49
+ :is_class => aliases.class.to_s,
50
+ })
51
+ end
52
+
53
+ if !machine.config.hostmanager.ip_resolver.nil? &&
54
+ !machine.config.hostmanager.ip_resolver.kind_of?(Proc)
55
+ errors << I18n.t('vagrant_hostmanager.config.not_a_proc', {
56
+ :config_key => 'hostmanager.ip_resolver',
57
+ :is_class => ip_resolver.class.to_s,
58
+ })
59
+ end
60
+
61
+ errors.compact!
62
+ { "HostManager configuration" => errors }
63
+ end
64
+
65
+ private
66
+
67
+ def validate_bool(key, value)
68
+ if ![TrueClass, FalseClass].include?(value.class) &&
69
+ value != UNSET_VALUE
70
+ I18n.t('vagrant_hostmanager.config.not_a_bool', {
71
+ :config_key => key,
72
+ :value => value.class.to_s
73
+ })
74
+ else
75
+ nil
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,6 @@
1
+ module VagrantPlugins
2
+ module HostManager
3
+ module Errors
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,206 @@
1
+ require 'tempfile'
2
+
3
+ module VagrantPlugins
4
+ module HostManager
5
+ module HostsFile
6
+
7
+ class Updater
8
+
9
+ def initialize(global_env, provider)
10
+ @global_env = global_env
11
+ @config = Util.get_config(@global_env)
12
+ @provider = provider
13
+ end
14
+
15
+ def update_guest(machine)
16
+ return unless machine.communicate.ready?
17
+
18
+ if (machine.communicate.test("uname -s | grep SunOS"))
19
+ realhostfile = '/etc/inet/hosts'
20
+ move_cmd = 'mv'
21
+ elsif (machine.communicate.test("test -d $Env:SystemRoot"))
22
+ windir = ""
23
+ machine.communicate.execute("echo %SYSTEMROOT%", {:shell => :cmd}) do |type, contents|
24
+ windir << contents.gsub("\r\n", '') if type == :stdout
25
+ end
26
+ realhostfile = "#{windir}\\System32\\drivers\\etc\\hosts"
27
+ move_cmd = 'mv -force'
28
+ else
29
+ realhostfile = '/etc/hosts'
30
+ move_cmd = 'mv -f'
31
+ end
32
+ # download and modify file with Vagrant-managed entries
33
+ file = @global_env.tmp_path.join("hosts.#{machine.name}")
34
+ machine.communicate.download(realhostfile, file)
35
+ if update_file(file, machine, false)
36
+
37
+ # upload modified file and remove temporary file
38
+ machine.communicate.upload(file, '/tmp/hosts')
39
+ if windir
40
+ machine.communicate.sudo("#{move_cmd} /tmp/hosts/hosts.#{machine.name} #{realhostfile}")
41
+ elsif machine.communicate.test('test -f /.dockerinit')
42
+ machine.communicate.sudo("cat /tmp/hosts > #{realhostfile}")
43
+ else
44
+ machine.communicate.sudo("#{move_cmd} /tmp/hosts #{realhostfile}")
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+ def update_host
51
+ # copy and modify hosts file on host with Vagrant-managed entries
52
+ file = @global_env.tmp_path.join('hosts.local')
53
+
54
+ if WindowsSupport.windows?
55
+ # lazily include windows Module
56
+ class << self
57
+ include WindowsSupport unless include? WindowsSupport
58
+ end
59
+
60
+ hosts_location = "#{ENV['WINDIR']}\\System32\\drivers\\etc\\hosts"
61
+ copy_proc = Proc.new { windows_copy_file(file, hosts_location) }
62
+ else
63
+ hosts_location = '/etc/hosts'
64
+ copy_proc = Proc.new { `sudo cp #{file} #{hosts_location}` }
65
+ end
66
+
67
+ FileUtils.cp(hosts_location, file)
68
+ if update_file(file)
69
+ copy_proc.call
70
+ end
71
+ end
72
+
73
+ private
74
+
75
+ def update_file(file, resolving_machine = nil, include_id = true)
76
+ file = Pathname.new(file)
77
+ old_file_content = file.read
78
+ new_file_content = update_content(old_file_content, resolving_machine, include_id)
79
+ file.open('wb') { |io| io.write(new_file_content) }
80
+ old_file_content != new_file_content
81
+ end
82
+
83
+ def update_content(file_content, resolving_machine, include_id)
84
+ id = include_id ? " id: #{read_or_create_id}" : ""
85
+ header = "## vagrant-hostmanager-start#{id}\n"
86
+ footer = "## vagrant-hostmanager-end\n"
87
+ body = get_machines
88
+ .map { |machine| get_hosts_file_entry(machine, resolving_machine) }
89
+ .join
90
+ get_new_content(header, footer, body, file_content)
91
+ end
92
+
93
+ def get_hosts_file_entry(machine, resolving_machine)
94
+ ip = get_ip_address(machine, resolving_machine)
95
+ host = machine.config.vm.hostname || machine.name
96
+ aliases = machine.config.hostmanager.aliases
97
+ if ip != nil
98
+ "#{ip}\t#{host}\n" + aliases.map{|a| "#{ip}\t#{a}"}.join("\n") + "\n"
99
+ end
100
+ end
101
+
102
+ def get_ip_address(machine, resolving_machine)
103
+ custom_ip_resolver = machine.config.hostmanager.ip_resolver
104
+ if custom_ip_resolver
105
+ custom_ip_resolver.call(machine, resolving_machine)
106
+ else
107
+ ip = nil
108
+ if machine.config.hostmanager.ignore_private_ip != true
109
+ machine.config.vm.networks.each do |network|
110
+ key, options = network[0], network[1]
111
+ ip = options[:ip] if key == :private_network
112
+ break if ip
113
+ end
114
+ end
115
+ ip || (machine.ssh_info ? machine.ssh_info[:host] : nil)
116
+ end
117
+ end
118
+
119
+ def get_machines
120
+ if @config.hostmanager.include_offline?
121
+ machines = @global_env.machine_names
122
+ else
123
+ machines = @global_env.active_machines
124
+ .select { |name, provider| provider == @provider }
125
+ .collect { |name, provider| name }
126
+ end
127
+ # Collect only machines that exist for the current provider
128
+ machines.collect do |name|
129
+ begin
130
+ machine = @global_env.machine(name, @provider)
131
+ rescue Vagrant::Errors::MachineNotFound
132
+ # ignore
133
+ end
134
+ machine
135
+ end
136
+ .reject(&:nil?)
137
+ end
138
+
139
+ def get_new_content(header, footer, body, old_content)
140
+ if body.empty?
141
+ block = "\n"
142
+ else
143
+ block = "\n\n" + header + body + footer + "\n"
144
+ end
145
+ # Pattern for finding existing block
146
+ header_pattern = Regexp.quote(header)
147
+ footer_pattern = Regexp.quote(footer)
148
+ pattern = Regexp.new("\n*#{header_pattern}.*?#{footer_pattern}\n*", Regexp::MULTILINE)
149
+ # Replace existing block or append
150
+ old_content.match(pattern) ? old_content.sub(pattern, block) : old_content.rstrip + block
151
+ end
152
+
153
+ def read_or_create_id
154
+ file = Pathname.new("#{@global_env.local_data_path}/hostmanager/id")
155
+ if (file.file?)
156
+ id = file.read.strip
157
+ else
158
+ id = SecureRandom.uuid
159
+ file.dirname.mkpath
160
+ file.open('w') { |io| io.write(id) }
161
+ end
162
+ id
163
+ end
164
+
165
+ ## Windows support for copying files, requesting elevated privileges if necessary
166
+ module WindowsSupport
167
+ require 'rbconfig'
168
+
169
+ def self.windows?
170
+ RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
171
+ end
172
+
173
+ require 'win32ole' if windows?
174
+
175
+ def windows_copy_file(source, dest)
176
+ begin
177
+ # First, try Ruby copy
178
+ FileUtils.cp(source, dest)
179
+ rescue Errno::EACCES
180
+ # Access denied, try with elevated privileges
181
+ windows_copy_file_elevated(source, dest)
182
+ end
183
+ end
184
+
185
+ private
186
+
187
+ def windows_copy_file_elevated(source, dest)
188
+ # copy command only supports backslashes as separators
189
+ source, dest = [source, dest].map { |s| s.to_s.gsub(/\//, '\\') }
190
+
191
+ # run 'cmd /C copy ...' with elevated privilege, minimized
192
+ copy_cmd = "copy \"#{source}\" \"#{dest}\""
193
+ WIN32OLE.new('Shell.Application').ShellExecute('cmd', "/C #{copy_cmd}", nil, 'runas', 7)
194
+
195
+ # Unfortunately, ShellExecute does not give us a status code,
196
+ # and it is non-blocking so we can't reliably compare the file contents
197
+ # to see if they were copied.
198
+ #
199
+ # If the user rejects the UAC prompt, vagrant will silently continue
200
+ # without updating the hostsfile.
201
+ end
202
+ end
203
+ end
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,44 @@
1
+ require 'vagrant-hostmanager/action'
2
+
3
+ module VagrantPlugins
4
+ module HostManager
5
+ class Plugin < Vagrant.plugin('2')
6
+ name 'HostManager'
7
+ description <<-DESC
8
+ This plugin manages the /etc/hosts file for the host and guest machines.
9
+ An entry is created for each running machine using the hostname attribute.
10
+
11
+ You can also use the hostmanager provisioner to update the hosts file.
12
+ DESC
13
+
14
+ config(:hostmanager) do
15
+ require_relative 'config'
16
+ Config
17
+ end
18
+
19
+ action_hook(:hostmanager, :machine_action_up) do |hook|
20
+ hook.after(Vagrant::Action::Builtin::Provision, Action.update_all)
21
+ end
22
+
23
+ action_hook(:hostmanager, :machine_action_destroy) do |hook|
24
+ hook.prepend(Action.update_all)
25
+ end
26
+
27
+ provisioner(:hostmanager) do
28
+ require_relative 'provisioner'
29
+ Provisioner
30
+ end
31
+
32
+ # Work-around for vagrant >= 1.5
33
+ # It breaks without a provisioner config, so we provide a dummy one
34
+ config(:hostmanager, :provisioner) do
35
+ ::Vagrant::Config::V2::DummyConfig.new
36
+ end
37
+
38
+ command(:hostmanager) do
39
+ require_relative 'command'
40
+ Command
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,22 @@
1
+ require 'vagrant-hostmanager/hosts_file/updater'
2
+
3
+ module VagrantPlugins
4
+ module HostManager
5
+ class Provisioner < Vagrant.plugin('2', :provisioner)
6
+
7
+ def initialize(machine, config)
8
+ super(machine, config)
9
+ global_env = machine.env
10
+ @config = Util.get_config(global_env)
11
+ @updater = HostsFile::Updater.new(global_env, machine.provider_name)
12
+ end
13
+
14
+ def provision
15
+ @updater.update_guest(@machine)
16
+ if @config.hostmanager.manage_host?
17
+ @updater.update_host
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ module VagrantPlugins
2
+ module HostManager
3
+ module Util
4
+ def self.get_config(env)
5
+ # config_global has been removed from v1.5
6
+ if Gem::Version.new(::Vagrant::VERSION) >= Gem::Version.new('1.5')
7
+ env.vagrantfile.config
8
+ else
9
+ env.config_global
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ module VagrantPlugins
2
+ module HostManager
3
+ VERSION = '1.6.1'
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ en:
2
+ vagrant_hostmanager:
3
+ action:
4
+ update_guests: "Updating /etc/hosts file on active guest machines..."
5
+ update_guest: "[%{name}] Updating /etc/hosts file..."
6
+ update_host: "Updating /etc/hosts file on host machine (password may be required)..."
7
+ config:
8
+ not_a_bool: "A value for %{config_key} can only be true or false, not type '%{value}'"
9
+ not_an_array_or_string: "A value for %{config_key} must be an Array or String, not type '%{is_class}'"
10
+ not_a_proc: "A value for %{config_key} must be a Proc, not type '%{is_class}'"
@@ -0,0 +1,41 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ if Gem::Version.new(::Vagrant::VERSION) < Gem::Version.new('1.5')
5
+ Vagrant.require_plugin('vagrant-hostmanager')
6
+ end
7
+
8
+ Vagrant.configure('2') do |config|
9
+
10
+ if ENV.key? 'VAGRANT_BOX'
11
+ config.vm.box = ENV['VAGRANT_BOX']
12
+ else
13
+ config.vm.box = 'precise64'
14
+ config.vm.box_url = 'http://cloud-images.ubuntu.com/precise/current/precise-server-cloudimg-vagrant-amd64-disk1.box'
15
+ end
16
+
17
+ config.hostmanager.enabled = true
18
+ config.hostmanager.manage_host = true
19
+
20
+ config.vm.define :server1 do |server|
21
+ server.vm.hostname = 'fry'
22
+ server.vm.network :private_network, :ip => '10.0.5.2'
23
+ server.hostmanager.aliases = %w(test-alias)
24
+ end
25
+
26
+ config.vm.define :server2 do |server|
27
+ server.vm.hostname = 'bender'
28
+ server.vm.network :private_network, :ip => '10.0.5.3'
29
+ end
30
+
31
+ config.vm.define :server3 do |server|
32
+ server.vm.hostname = 'leena'
33
+ server.vm.network :private_network, :ip => '10.0.5.4'
34
+ server.vm.provision :hostmanager
35
+ end
36
+
37
+ config.vm.define :server4 do |server|
38
+ server.vm.hostname = 'scruffy'
39
+ server.vm.provision :hostmanager
40
+ end
41
+ end
@@ -0,0 +1,14 @@
1
+ cd test
2
+
3
+ vagrant up
4
+
5
+ vagrant hostmanager
6
+
7
+ echo "[server1] /etc/hosts file:"
8
+ vagrant ssh server1 -c 'cat /etc/hosts'
9
+ echo "[server2] /etc/hosts file:"
10
+ vagrant ssh server2 -c 'cat /etc/hosts'
11
+
12
+ vagrant destroy -f
13
+
14
+ cd ..
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'vagrant-hostmanager/version'
6
+
7
+ Gem::Specification.new do |gem|
8
+ gem.name = 'vagrant-hostmanager-docker'
9
+ gem.version = VagrantPlugins::HostManager::VERSION
10
+ gem.authors = ['Shawn Dahlen']
11
+ gem.email = ['shawn@dahlen.me']
12
+ gem.description = %q{A Vagrant plugin that manages the /etc/hosts file within a multi-machine environment}
13
+ gem.summary = gem.description
14
+ gem.license = 'MIT'
15
+
16
+ gem.files = `git ls-files`.split($/)
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ['lib']
19
+
20
+ gem.add_development_dependency 'bundler', '~> 1.3'
21
+ gem.add_development_dependency 'rake'
22
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vagrant-hostmanager-docker
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.6.1
5
+ platform: ruby
6
+ authors:
7
+ - Shawn Dahlen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-10-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: A Vagrant plugin that manages the /etc/hosts file within a multi-machine
42
+ environment
43
+ email:
44
+ - shawn@dahlen.me
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - CHANGELOG.md
51
+ - Gemfile
52
+ - LICENSE.txt
53
+ - README.md
54
+ - Rakefile
55
+ - lib/vagrant-hostmanager.rb
56
+ - lib/vagrant-hostmanager/action.rb
57
+ - lib/vagrant-hostmanager/action/update_all.rb
58
+ - lib/vagrant-hostmanager/action/update_guest.rb
59
+ - lib/vagrant-hostmanager/action/update_host.rb
60
+ - lib/vagrant-hostmanager/command.rb
61
+ - lib/vagrant-hostmanager/config.rb
62
+ - lib/vagrant-hostmanager/errors.rb
63
+ - lib/vagrant-hostmanager/hosts_file/updater.rb
64
+ - lib/vagrant-hostmanager/plugin.rb
65
+ - lib/vagrant-hostmanager/provisioner.rb
66
+ - lib/vagrant-hostmanager/util.rb
67
+ - lib/vagrant-hostmanager/version.rb
68
+ - locales/en.yml
69
+ - test/Vagrantfile
70
+ - test/test.sh
71
+ - vagrant-hostmanager.gemspec
72
+ homepage:
73
+ licenses:
74
+ - MIT
75
+ metadata: {}
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 2.4.5.1
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: A Vagrant plugin that manages the /etc/hosts file within a multi-machine
96
+ environment
97
+ test_files:
98
+ - test/Vagrantfile
99
+ - test/test.sh