vagrant-ansible-fixed 0.1.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.
@@ -0,0 +1,257 @@
1
+ require "thread"
2
+
3
+ require_relative "base"
4
+
5
+ module VagrantPlugins
6
+ module Ansible_Fixed
7
+ module Provisioner
8
+ class Host < Base
9
+
10
+ @@lock = Mutex.new
11
+
12
+ def initialize(machine, config)
13
+ super
14
+ @logger = Log4r::Logger.new("vagrant::provisioners::ansible_host")
15
+ end
16
+
17
+ def provision
18
+ # At this stage, the SSH access is guaranteed to be ready
19
+ @ssh_info = @machine.ssh_info
20
+
21
+ warn_for_unsupported_platform
22
+ execute_ansible_galaxy_from_host if config.galaxy_role_file
23
+ execute_ansible_playbook_from_host
24
+ end
25
+
26
+ protected
27
+
28
+ VAGRANT_ARG_SEPARATOR = 'VAGRANT_ARG_SEP'
29
+
30
+ def warn_for_unsupported_platform
31
+ if Vagrant::Util::Platform.windows?
32
+ @machine.env.ui.warn(I18n.t("vagrant.provisioners.ansible.windows_not_supported_for_control_machine"))
33
+ end
34
+ end
35
+
36
+ def prepare_command_arguments
37
+ # Connect with native OpenSSH client
38
+ # Other modes (e.g. paramiko) are not officially supported,
39
+ # but can be enabled via raw_arguments option.
40
+ @command_arguments << "--connection=ssh"
41
+
42
+ # Increase the SSH connection timeout, as the Ansible default value (10 seconds)
43
+ # is a bit demanding for some overloaded developer boxes. This is particularly
44
+ # helpful when additional virtual networks are configured, as their availability
45
+ # is not controlled during vagrant boot process.
46
+ @command_arguments << "--timeout=30"
47
+
48
+ if !config.force_remote_user
49
+ # Pass the vagrant ssh username as Ansible default remote user, because
50
+ # the ansible_ssh_user parameter won't be added to the auto-generated inventory.
51
+ @command_arguments << "--user=#{@ssh_info[:username]}"
52
+ elsif config.inventory_path
53
+ # Using an extra variable is the only way to ensure that the Ansible remote user
54
+ # is overridden (as the ansible inventory is not under vagrant control)
55
+ @command_arguments << "--extra-vars=ansible_ssh_user='#{@ssh_info[:username]}'"
56
+ end
57
+
58
+ @command_arguments << "--ask-sudo-pass" if config.ask_sudo_pass
59
+ @command_arguments << "--ask-vault-pass" if config.ask_vault_pass
60
+
61
+ prepare_common_command_arguments
62
+ end
63
+
64
+
65
+ def prepare_environment_variables
66
+ prepare_common_environment_variables
67
+
68
+ # Some Ansible options must be passed as environment variables,
69
+ # as there is no equivalent command line arguments
70
+ @environment_variables["ANSIBLE_HOST_KEY_CHECKING"] = "#{config.host_key_checking}"
71
+
72
+ # ANSIBLE_SSH_ARGS is required for Multiple SSH keys, SSH forwarding and custom SSH settings
73
+ @environment_variables["ANSIBLE_SSH_ARGS"] = ansible_ssh_args unless ansible_ssh_args.empty?
74
+ end
75
+
76
+ def execute_command_from_host(command)
77
+ begin
78
+ result = Vagrant::Util::Subprocess.execute(*command) do |type, data|
79
+ if type == :stdout || type == :stderr
80
+ @machine.env.ui.detail(data, new_line: false, prefix: false)
81
+ end
82
+ end
83
+ raise Ansible::Errors::AnsibleCommandFailed if result.exit_code != 0
84
+ rescue Vagrant::Errors::CommandUnavailable
85
+ raise Ansible::Errors::AnsibleNotFoundOnHost
86
+ end
87
+ end
88
+
89
+ def execute_ansible_galaxy_from_host
90
+ command_values = {
91
+ :role_file => get_galaxy_role_file(machine.env.root_path),
92
+ :roles_path => get_galaxy_roles_path(machine.env.root_path)
93
+ }
94
+ command_template = config.galaxy_command.gsub(' ', VAGRANT_ARG_SEPARATOR)
95
+ str_command = command_template % command_values
96
+
97
+ ui_running_ansible_command "galaxy", str_command.gsub(VAGRANT_ARG_SEPARATOR, ' ')
98
+
99
+ command = str_command.split(VAGRANT_ARG_SEPARATOR)
100
+ command << {
101
+ # Write stdout and stderr data, since it's the regular Ansible output
102
+ notify: [:stdout, :stderr],
103
+ workdir: @machine.env.root_path.to_s
104
+ }
105
+
106
+ execute_command_from_host command
107
+ end
108
+
109
+ def execute_ansible_playbook_from_host
110
+ prepare_command_arguments
111
+ prepare_environment_variables
112
+
113
+ # Assemble the full ansible-playbook command
114
+ command = (%w(ansible-playbook) << @command_arguments << config.playbook).flatten
115
+
116
+ ui_running_ansible_command "playbook", Helpers::stringify_ansible_playbook_command(@environment_variables, command)
117
+
118
+ command << {
119
+ env: @environment_variables,
120
+ # Write stdout and stderr data, since it's the regular Ansible output
121
+ notify: [:stdout, :stderr],
122
+ workdir: @machine.env.root_path.to_s
123
+ }
124
+
125
+ execute_command_from_host command
126
+ end
127
+
128
+ def ship_generated_inventory(inventory_content)
129
+ inventory_path = Pathname.new(File.join(@machine.env.local_data_path.join, %w(provisioners ansible inventory)))
130
+ FileUtils.mkdir_p(inventory_path) unless File.directory?(inventory_path)
131
+
132
+ inventory_file = Pathname.new(File.join(inventory_path, 'vagrant_ansible_inventory'))
133
+ @@lock.synchronize do
134
+ if !File.exists?(inventory_file) or inventory_content != File.read(inventory_file)
135
+ inventory_file.open('w') do |file|
136
+ file.write(inventory_content)
137
+ end
138
+ end
139
+ end
140
+
141
+ return inventory_path
142
+ end
143
+
144
+ def generate_inventory_machines
145
+ machines = ""
146
+
147
+ @machine.env.active_machines.each do |am|
148
+ begin
149
+ m = @machine.env.machine(*am)
150
+
151
+ # Call only once the SSH and WinRM info computation
152
+ # Note that machines configured with WinRM communicator, also have a "partial" ssh_info.
153
+ m_ssh_info = m.ssh_info
154
+ host_vars = get_inventory_host_vars_string(m.name)
155
+ if m.config.vm.communicator == :winrm
156
+ m_winrm_net_info = CommunicatorWinRM::Helper.winrm_info(m) # can raise a WinRMNotReady exception...
157
+ machines += get_inventory_winrm_machine(m, m_winrm_net_info)
158
+ machines.sub!(/\n$/, " #{host_vars}\n") if host_vars
159
+ @inventory_machines[m.name] = m
160
+ elsif !m_ssh_info.nil?
161
+ machines += get_inventory_ssh_machine(m, m_ssh_info)
162
+ machines.sub!(/\n$/, " #{host_vars}\n") if host_vars
163
+ @inventory_machines[m.name] = m
164
+ else
165
+ @logger.error("Auto-generated inventory: Impossible to get SSH information for machine '#{m.name} (#{m.provider_name})'. This machine should be recreated.")
166
+ # Let a note about this missing machine
167
+ machines += "# MISSING: '#{m.name}' machine was probably removed without using Vagrant. This machine should be recreated.\n"
168
+ end
169
+ rescue Vagrant::Errors::MachineNotFound, CommunicatorWinRM::Errors::WinRMNotReady => e
170
+ @logger.info("Auto-generated inventory: Skip machine '#{am[0]} (#{am[1]})', which is not configured for this Vagrant environment.")
171
+ end
172
+ end
173
+
174
+ return machines
175
+ end
176
+
177
+ def get_inventory_ssh_machine(machine, ssh_info)
178
+ forced_remote_user = ""
179
+ if config.force_remote_user
180
+ forced_remote_user = "ansible_ssh_user='#{ssh_info[:username]}' "
181
+ end
182
+
183
+ "#{machine.name} ansible_ssh_host=#{ssh_info[:host]} ansible_ssh_port=#{ssh_info[:port]} #{forced_remote_user}ansible_ssh_private_key_file='#{ssh_info[:private_key_path][0]}'\n"
184
+ end
185
+
186
+ def get_inventory_winrm_machine(machine, winrm_net_info)
187
+ forced_remote_user = ""
188
+ if config.force_remote_user
189
+ forced_remote_user = "ansible_ssh_user='#{machine.config.winrm.username}' "
190
+ end
191
+
192
+ "#{machine.name} ansible_connection=winrm ansible_ssh_host=#{winrm_net_info[:host]} ansible_ssh_port=#{winrm_net_info[:port]} #{forced_remote_user}ansible_ssh_pass='#{machine.config.winrm.password}'\n"
193
+ end
194
+
195
+ def ansible_ssh_args
196
+ @ansible_ssh_args ||= prepare_ansible_ssh_args
197
+ end
198
+
199
+ def prepare_ansible_ssh_args
200
+ ssh_options = []
201
+
202
+ # Use an SSH ProxyCommand when using the Docker provider with the intermediate host
203
+ if @machine.provider_name == :docker && machine.provider.host_vm?
204
+ docker_host_ssh_info = machine.provider.host_vm.ssh_info
205
+
206
+ proxy_cmd = "ssh #{docker_host_ssh_info[:username]}@#{docker_host_ssh_info[:host]}" +
207
+ " -p #{docker_host_ssh_info[:port]} -i #{docker_host_ssh_info[:private_key_path][0]}"
208
+
209
+ # Use same options than plugins/providers/docker/communicator.rb
210
+ # Note: this could be improved (DRY'ed) by sharing these settings.
211
+ proxy_cmd += " -o Compression=yes -o ConnectTimeout=5 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
212
+
213
+ proxy_cmd += " -o ForwardAgent=yes" if @ssh_info[:forward_agent]
214
+
215
+ proxy_cmd += " exec nc %h %p 2>/dev/null"
216
+
217
+ ssh_options << "-o ProxyCommand='#{ proxy_cmd }'"
218
+ end
219
+
220
+ # Don't access user's known_hosts file, except when host_key_checking is enabled.
221
+ ssh_options << "-o UserKnownHostsFile=/dev/null" unless config.host_key_checking
222
+
223
+ # Set IdentitiesOnly=yes to avoid authentication errors when the host has more than 5 ssh keys.
224
+ # Notes:
225
+ # - Solaris/OpenSolaris/Illumos uses SunSSH which doesn't support the IdentitiesOnly option.
226
+ # - this could be improved by sharing logic with lib/vagrant/util/ssh.rb
227
+ ssh_options << "-o IdentitiesOnly=yes" unless Vagrant::Util::Platform.solaris?
228
+
229
+ # Multiple Private Keys
230
+ unless !config.inventory_path && @ssh_info[:private_key_path].size == 1
231
+ @ssh_info[:private_key_path].each do |key|
232
+ ssh_options << "-i '#{key}'"
233
+ end
234
+ end
235
+
236
+ # SSH Forwarding
237
+ ssh_options << "-o ForwardAgent=yes" if @ssh_info[:forward_agent]
238
+
239
+ # Unchecked SSH Parameters
240
+ ssh_options.concat(Helpers::as_array(config.raw_ssh_args)) if config.raw_ssh_args
241
+
242
+ # Re-enable ControlPersist Ansible defaults,
243
+ # which are lost when ANSIBLE_SSH_ARGS is defined.
244
+ unless ssh_options.empty?
245
+ ssh_options << "-o ControlMaster=auto"
246
+ ssh_options << "-o ControlPersist=60s"
247
+ # Intentionally keep ControlPath undefined to let ansible-playbook
248
+ # automatically sets this option to Ansible default value
249
+ end
250
+
251
+ ssh_options.join(' ')
252
+ end
253
+
254
+ end
255
+ end
256
+ end
257
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,5 @@
1
+ module VagrantPlugins
2
+ module Ansible_Fixed
3
+ VERSION = '0.1.0'
4
+ end
5
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "vagrant-ansible-fixed"
8
+ spec.version = VagrantPlugins::Ansible_Fixed::VERSION
9
+ spec.authors = ["James O'Neal"]
10
+ spec.email = ["onealjames08@gmail.com"]
11
+
12
+ spec.summary = %q{Fix of vagrant 1.8.1 ansible_local provisioner for windows.}
13
+ spec.description = %q{Fix of vagrant 1.8.1 ansible_local provisioner for windows.}
14
+ spec.homepage = "https://github.com/jamesooo/vagrant-ansible-fixed"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.10"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vagrant-ansible-fixed
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - James O'Neal
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-03-01 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.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Fix of vagrant 1.8.1 ansible_local provisioner for windows.
42
+ email:
43
+ - onealjames08@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gitignore
49
+ - Gemfile
50
+ - README.md
51
+ - Rakefile
52
+ - bin/console
53
+ - bin/setup
54
+ - lib/cap/guest/arch/ansible_install.rb
55
+ - lib/cap/guest/debian/ansible_install.rb
56
+ - lib/cap/guest/fedora/ansible_install.rb
57
+ - lib/cap/guest/freebsd/ansible_install.rb
58
+ - lib/cap/guest/posix/ansible_installed.rb
59
+ - lib/cap/guest/redhat/ansible_install.rb
60
+ - lib/cap/guest/suse/ansible_install.rb
61
+ - lib/cap/guest/ubuntu/ansible_install.rb
62
+ - lib/config/base.rb
63
+ - lib/config/guest.rb
64
+ - lib/config/host.rb
65
+ - lib/errors.rb
66
+ - lib/helpers.rb
67
+ - lib/plugin.rb
68
+ - lib/provisioner/base.rb
69
+ - lib/provisioner/guest.rb
70
+ - lib/provisioner/host.rb
71
+ - lib/version.rb
72
+ - vagrant-ansible-fixed.gemspec
73
+ homepage: https://github.com/jamesooo/vagrant-ansible-fixed
74
+ licenses: []
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.6
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: Fix of vagrant 1.8.1 ansible_local provisioner for windows.
96
+ test_files: []