kitchen-yansible 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,33 @@
1
+ # Author: Eugene Akhmetkhanov <axmetishe+github@gmail.com>
2
+ # Date: 08-01-2020
3
+ #
4
+ # Licensed to the Apache Software Foundation (ASF) under one
5
+ # or more contributor license agreements. See the NOTICE file
6
+ # distributed with this work for additional information
7
+ # regarding copyright ownership. The ASF licenses this file
8
+ # to you under the Apache License, Version 2.0 (the
9
+ # "License"); you may not use this file except in compliance
10
+ # with the License. You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing,
15
+ # software distributed under the License is distributed on an
16
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17
+ # KIND, either express or implied. See the License for the
18
+ # specific language governing permissions and limitations
19
+ # under the License.
20
+
21
+ module Kitchen
22
+ module Yansible
23
+ module Tools
24
+ class Install
25
+ class Fedora < RHEL
26
+ def package_manager
27
+ "#{sudo_env('dnf')}"
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,225 @@
1
+ # Author: Eugene Akhmetkhanov <axmetishe+github@gmail.com>
2
+ # Date: 07-01-2020
3
+ #
4
+ # Licensed to the Apache Software Foundation (ASF) under one
5
+ # or more contributor license agreements. See the NOTICE file
6
+ # distributed with this work for additional information
7
+ # regarding copyright ownership. The ASF licenses this file
8
+ # to you under the Apache License, Version 2.0 (the
9
+ # "License"); you may not use this file except in compliance
10
+ # with the License. You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing,
15
+ # software distributed under the License is distributed on an
16
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17
+ # KIND, either express or implied. See the License for the
18
+ # specific language governing permissions and limitations
19
+ # under the License.
20
+
21
+ module Kitchen
22
+ module Yansible
23
+ module Tools
24
+ class Install
25
+ class RHEL < Install
26
+ def preinstall_command
27
+ """
28
+ #{update_path}
29
+ #{update_cache}
30
+
31
+ installPackage () {
32
+ package=$1
33
+ #{package_manager} -q info ${package} 2>/dev/null|grep installed &>/dev/null || #{install_package} ${package}
34
+ }
35
+
36
+ enableSCLPackage () {
37
+ package=$1
38
+ echo \"Enable ${package}\"
39
+ grep \"/opt/rh/${package}/enable\" /etc/profile.d/${package}.sh &> /dev/null || {
40
+ #{sudo('echo')} \"source /opt/rh/${package}/enable\"| #{sudo('tee')} -a /etc/profile.d/${package}.sh
41
+ }
42
+ source /opt/rh/${package}/enable
43
+ }
44
+
45
+ installRubySCL () {
46
+ RUBY_PACKAGE=$(#{package_manager} search -q ruby|grep '^rh-ruby\\([0-9\\.]\\+\\)\\?\\.'|sort -r|head -n1|awk '{print $1}'|awk -F'.' '{print $1}')
47
+ installPackage ${RUBY_PACKAGE}
48
+ RUBY_VERSION=\"$(#{package_manager} info ${RUBY_PACKAGE}|grep -i version|awk '{print $3}')\"
49
+ test -L /usr/lib64/libruby.so.${RUBY_VERSION} || {
50
+ #{sudo('ln')} -sf /opt/rh/${RUBY_PACKAGE}/root/usr/lib64/libruby.so.${RUBY_VERSION} \\
51
+ /usr/lib64/libruby.so.${RUBY_VERSION}
52
+ }
53
+ #{ruby_alternatives('/usr/local/bin', "/opt/rh/${RUBY_PACKAGE}/root/usr/bin")}
54
+ enableSCLPackage ${RUBY_PACKAGE}
55
+ }
56
+
57
+ installPythonSCL () {
58
+ PYTHON_PACKAGE='python27 python27-python-virtualenv'
59
+ installPackage ${PYTHON_PACKAGE}
60
+
61
+ #{alternatives_command} --install /usr/local/bin/python python /opt/rh/python27/root/usr/bin/python 100
62
+ #{alternatives_command} --set python /opt/rh/python27/root/usr/bin/python
63
+
64
+ #{sudo('grep')} 'ANSIBLE_PYTHON_INTERPRETER' /etc/profile.d/ansible.sh &> /dev/null || {
65
+ #{sudo('echo')} \"export ANSIBLE_PYTHON_INTERPRETER=/usr/local/bin/python\"| #{sudo('tee')} -a /etc/profile.d/ansible.sh
66
+ }
67
+ #{sudo('grep')} XDG_DATA_DIRS /etc/sudoers.d/ansible &> /dev/null || {
68
+ #{sudo('echo')} 'Defaults env_keep += \"XDG_DATA_DIRS PKG_CONFIG_PATH ANSIBLE_PYTHON_INTERPRETER\"' | #{sudo('tee')} -a /etc/sudoers.d/ansible
69
+ }
70
+
71
+ test -L /usr/lib64/libpython2.7.so.1.0 || {
72
+ #{sudo('ln')} -sf /opt/rh/python27/root/usr/lib64/libpython2.7.so.1.0 \\
73
+ /usr/lib64/libpython2.7.so.1.0
74
+ }
75
+ test -L /usr/lib64/libpython2.7.so || {
76
+ #{sudo('ln')} -sf /usr/lib64/libpython2.7.so.1.0 /usr/lib64/libpython2.7.so
77
+ }
78
+
79
+ enableSCLPackage 'python27'
80
+ }
81
+
82
+ preInstall () {
83
+ RHEL_VERSION=$(test -f /etc/system-release-cpe && awk -F':' '{print $5}' /etc/system-release-cpe || echo '0')
84
+ RHEL_DISTR=$(test -f /etc/system-release-cpe && awk -F':' '{print $3}' /etc/system-release-cpe || echo '0')
85
+
86
+ # Sanitize CPE Info
87
+ case ${RHEL_DISTR} in
88
+ amazon)
89
+ RHEL_VERSION=6
90
+ ;;
91
+ o)
92
+ RHEL_DISTR=amazon
93
+ RHEL_VERSION=7
94
+ ;;
95
+ *)
96
+ ;;
97
+ esac
98
+
99
+ if [[ ${RHEL_VERSION} -eq 6 || ${RHEL_VERSION} -eq 7 ]]; then
100
+ echo \"We are going to use SCL repository for Python and Ruby installation\"
101
+ echo \"Working with ${RHEL_DISTR} ${RHEL_VERSION}\"
102
+ case ${RHEL_DISTR} in
103
+ centos)
104
+ installPackage centos-release-scl-rh
105
+ installPythonSCL
106
+ installRubySCL
107
+ ;;
108
+ oracle)
109
+ installPackage oracle-softwarecollection-release-el${RHEL_VERSION}
110
+ installRubySCL
111
+ if [[ ${RHEL_VERSION} -eq 6 ]]; then
112
+ installPythonSCL
113
+ fi
114
+ ;;
115
+ *)
116
+ echo \"Unsupported RHEL SCL family distribution - ${RHEL_DISTR} ${RHEL_VERSION}\"
117
+ ;;
118
+ esac
119
+ fi
120
+ updatePath
121
+ }
122
+ """
123
+ end
124
+
125
+ def install_python
126
+ """
127
+ installPython () {
128
+ echo 'Checking Python installation.'
129
+ searchAlternatives 'python'
130
+ #{command_exists('python')} || {
131
+ echo 'Python is not installed, attempt to use package manager.'
132
+ package=$(#{package_manager} search -q python|grep '^python\\([0-9\\.]\\+\\)\\?\\.'|sort -r|head -n1|awk '{print $1}')
133
+ echo \"Will try to install '${package}' package.\"
134
+ #{install_package} ${package}
135
+ echo 'Checking for installed alternatives.'
136
+ #{command_exists('python')} || {
137
+ searchAlternatives 'python'
138
+ }
139
+ }
140
+ #{command_exists('python')} || {
141
+ echo \"===> Couldn't determine Python executable - exiting now! <===\"
142
+ exit 1
143
+ }
144
+ }
145
+ """
146
+ end
147
+
148
+ def install_ruby
149
+ """
150
+ installRuby () {
151
+ echo 'Checking Ruby installation.'
152
+ searchAlternatives 'ruby'
153
+ #{command_exists('ruby')} || {
154
+ echo 'Ruby is not installed, attempt to use package manager.'
155
+ package=$(#{package_manager} search -q ruby 2> /dev/null|grep '^ruby\\([0-9\\.]\\+\\)\\?\\.'|sort -r|head -n1|awk '{print $1}')
156
+ echo \"Will try to install '${package}' package.\"
157
+ #{install_package} ${package}
158
+ echo 'Checking for installed alternatives.'
159
+ #{command_exists('ruby')} || {
160
+ searchAlternatives 'ruby'
161
+ }
162
+ grep 'gem: --no-rdoc --no-ri -​-no-document' /etc/gemrc &> /dev/null || {
163
+ #{sudo('echo')} 'gem: --no-rdoc --no-ri -​-no-document' | #{sudo('tee')} /etc/gemrc
164
+ }
165
+ }
166
+ #{command_exists('ruby')} || {
167
+ echo \"===> Couldn't determine Ruby executable - exiting now! <===\"
168
+ exit 1
169
+ }
170
+ echo 'Install Busser'
171
+ #{command_exists('gem')} || {
172
+ #{install_package} rubygems
173
+ }
174
+ #{command_exists('rdoc')} || {
175
+ #{install_package} rubygem-rdoc
176
+ }
177
+ #{sudo('gem')} list | grep busser || {
178
+ #{sudo('gem')} install busser
179
+ }
180
+ test -d /opt/chef/embedded/bin || {
181
+ #{sudo('mkdir')} -p /opt/chef/embedded/bin
182
+ }
183
+ echo 'Making links for Chef'
184
+ for binary in ruby gem busser; do
185
+ test -L /opt/chef/embedded/bin/${binary} || {
186
+ #{sudo('ln')} -sf \"$(command -v ${binary})\" /opt/chef/embedded/bin/${binary}
187
+ }
188
+ done
189
+ }
190
+ """
191
+ end
192
+
193
+ def install_virtualenv
194
+ """
195
+ installVirtualenv () {
196
+ echo 'Checking Virtualenv installation.'
197
+ searchAlternatives 'virtualenv'
198
+ #{command_exists('virtualenv')} || {
199
+ echo 'Virtualenv is not installed, will try to guess its name.'
200
+ if [ $(#{package_manager} search virtualenv|grep '^python.*-virtualenv'|wc -l) -gt 1 ]; then
201
+ venvPackage=python$(#{get_python_version})-virtualenv
202
+ echo \"Will try to install '${venvPackage}' package.\"
203
+ #{install_package} ${venvPackage}
204
+ else
205
+ echo \"Installing via virtual package.\"
206
+ #{install_package} python-virtualenv
207
+ fi
208
+
209
+ echo 'Checking for installed alternatives.'
210
+ #{command_exists('virtualenv')} || {
211
+ searchAlternatives 'virtualenv'
212
+ }
213
+ }
214
+ #{command_exists('virtualenv')} || {
215
+ echo \"===> Couldn't install Virtualenv - exiting now! <===\"
216
+ exit 1
217
+ }
218
+ }
219
+ """
220
+ end
221
+ end
222
+ end
223
+ end
224
+ end
225
+ end
@@ -0,0 +1,122 @@
1
+ # Author: Eugene Akhmetkhanov <axmetishe+github@gmail.com>
2
+ # Date: 10-01-2020
3
+ #
4
+ # Licensed to the Apache Software Foundation (ASF) under one
5
+ # or more contributor license agreements. See the NOTICE file
6
+ # distributed with this work for additional information
7
+ # regarding copyright ownership. The ASF licenses this file
8
+ # to you under the Apache License, Version 2.0 (the
9
+ # "License"); you may not use this file except in compliance
10
+ # with the License. You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing,
15
+ # software distributed under the License is distributed on an
16
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17
+ # KIND, either express or implied. See the License for the
18
+ # specific language governing permissions and limitations
19
+ # under the License.
20
+
21
+ require 'uri'
22
+
23
+ module Kitchen
24
+ module Yansible
25
+ module Tools
26
+ class Install
27
+ class Windows < Install
28
+ def pip_required_packages
29
+ [
30
+ "ansible#{pip_version(ansible_version)}",
31
+ "pywinrm"
32
+ ]
33
+ end
34
+
35
+ def install_win_software(url, distr_dir, install_dir, install_arguments, test_binary )
36
+ """
37
+ $downloadUrl = \"#{url}\"
38
+ $distrDir=\"#{distr_dir}\"
39
+ $installerName = \"#{File.basename(URI.parse(url).path)}\"
40
+ $installDir=\"#{install_dir}\"
41
+ $testBinary=\"#{test_binary}\"
42
+ mkdir $distrDir -Force | out-null
43
+ mkdir $installDir -Force | out-null
44
+
45
+ try {
46
+ $binaryInstalled = $False
47
+ try {
48
+ $binaryInstalled=(&{#{test_binary} --version} 2>&1 | % gettype) -ne [System.Management.Automation.ErrorRecord]
49
+ }
50
+ catch {
51
+ echo \"#{test_binary.capitalize} is not installed.\"
52
+ }
53
+ if (! $binaryInstalled) {
54
+ if (! (Test-Path \"${distrDir}\\${installerName}\") ) {
55
+ echo \"Downloading ${installerName}\"
56
+ Invoke-WebRequest -DisableKeepAlive -UseBasicParsing -Method GET -Uri \"${downloadUrl}\" -OutFile \"${distrDir}\\${installerName}\"
57
+ }
58
+
59
+ echo \"Installing ${installerName}\"
60
+ $p = Start-Process -Wait -Passthru -FilePath \"${distrDir}\\${installerName}\" -ArgumentList #{install_arguments.join(', ')}
61
+
62
+ if ($p.ExitCode -ne 0) {
63
+ throw \"${installerName} installation was not successful. Received exit code $($p.ExitCode)\"
64
+ }
65
+ } else {
66
+ echo \"#{test_binary.capitalize} installed already. Skipping.\"
67
+ }
68
+ }
69
+ catch {
70
+ Write-Error ($_ | ft -Property * | out-string) -ErrorAction Continue
71
+ exit 1
72
+ }
73
+ """
74
+ end
75
+
76
+ def install_python
77
+ python_version='3.7.6'
78
+ base_url="https://www.python.org/ftp/python/#{python_version}"
79
+ installer_name = "python-#{python_version}-amd64.exe"
80
+ download_url = "#{base_url}/#{installer_name}"
81
+ base_dir='C:\\python'
82
+ distr_dir="#{base_dir}\\distr"
83
+ install_dir="#{base_dir}\\install"
84
+ install_args = [ '/passive', 'InstallAllUsers=1', 'PrependPath=1', "TargetDir=\"#{install_dir}\"", '/quiet' ]
85
+
86
+ """
87
+ #{install_win_software(download_url, distr_dir, install_dir, install_args, "python")}
88
+ """
89
+ end
90
+
91
+ def install_ruby
92
+ ruby_version='2.6.5-1'
93
+ base_url="https://github.com/oneclick/rubyinstaller2/releases/download/RubyInstaller-#{ruby_version}"
94
+ installer_name = "rubyinstaller-#{ruby_version}-x64.exe"
95
+ download_url = "#{base_url}/#{installer_name}"
96
+ base_dir='C:\\opscode\\chef'
97
+ distr_dir="#{base_dir}\\distr"
98
+ install_dir="#{base_dir}\\embedded"
99
+ install_args = [ '/silent', '/lang=en', '/tasks="assocfiles,modpath"', "/dir=\"#{install_dir}\"" ]
100
+
101
+ """
102
+ #{install_win_software(download_url, distr_dir, install_dir, install_args, "ruby")}
103
+ """
104
+ end
105
+
106
+ def local_install
107
+ """
108
+ $ErrorActionPreference = 'Stop'
109
+
110
+ #{install_python}
111
+ #{install_ruby}
112
+ """
113
+ end
114
+
115
+ def remote_install
116
+ "echo 'Not supported'"
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,25 @@
1
+ # Author: Eugene Akhmetkhanov <axmetishe+github@gmail.com>
2
+ # Date: 03-01-2020
3
+ #
4
+ # Licensed to the Apache Software Foundation (ASF) under one
5
+ # or more contributor license agreements. See the NOTICE file
6
+ # distributed with this work for additional information
7
+ # regarding copyright ownership. The ASF licenses this file
8
+ # to you under the Apache License, Version 2.0 (the
9
+ # "License"); you may not use this file except in compliance
10
+ # with the License. You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing,
15
+ # software distributed under the License is distributed on an
16
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17
+ # KIND, either express or implied. See the License for the
18
+ # specific language governing permissions and limitations
19
+ # under the License.
20
+
21
+ module Kitchen
22
+ module Yansible
23
+ VERSION = '0.0.1'.freeze
24
+ end
25
+ end
@@ -0,0 +1,243 @@
1
+ # Author: Eugene Akhmetkhanov <axmetishe+github@gmail.com>
2
+ # Date: 03-01-2020
3
+ #
4
+ # Licensed to the Apache Software Foundation (ASF) under one
5
+ # or more contributor license agreements. See the NOTICE file
6
+ # distributed with this work for additional information
7
+ # regarding copyright ownership. The ASF licenses this file
8
+ # to you under the Apache License, Version 2.0 (the
9
+ # "License"); you may not use this file except in compliance
10
+ # with the License. You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing,
15
+ # software distributed under the License is distributed on an
16
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17
+ # KIND, either express or implied. See the License for the
18
+ # specific language governing permissions and limitations
19
+ # under the License.
20
+
21
+ require 'kitchen'
22
+ require 'kitchen/errors'
23
+ require 'kitchen/provisioner/base'
24
+ require 'kitchen-yansible/tools/install'
25
+ require 'kitchen-yansible/tools/files'
26
+ require 'kitchen-yansible/tools/exec'
27
+ require 'kitchen-yansible/tools/dependencies'
28
+
29
+ module Kitchen
30
+ module Provisioner
31
+ class Yansible < Base
32
+ include Kitchen::Yansible::Tools
33
+ include Kitchen::Yansible::Tools::Exec
34
+ include Kitchen::Yansible::Tools::Files
35
+ include Kitchen::Yansible::Tools::Dependencies
36
+
37
+ kitchen_provisioner_api_version 2
38
+
39
+ DEFAULT_CONFIG = {
40
+ remote_executor: false,
41
+ remote_install_path: '/tmp/ansible',
42
+ sandboxed_executor: false,
43
+ playbook: 'default.yml',
44
+ ansible_binary: 'ansible-playbook',
45
+ ansible_version: nil,
46
+ ansible_config: nil,
47
+ ansible_extra_arguments: nil,
48
+ ansible_force_color: true,
49
+ ansible_host_key_checking: false,
50
+ ansible_winrm_auth_transport: nil,
51
+ ansible_winrm_cert_validation: 'ignore',
52
+ ansible_verbose: false,
53
+ ansible_verbosity: 1,
54
+ ansible_roles_path: 'roles',
55
+ dependencies: [],
56
+ }
57
+
58
+ # noinspection RubyYardParamTypeMatch
59
+ DEFAULT_CONFIG.each { |k, v| default_config k, v }
60
+
61
+ def install_command
62
+ info("Installing provisioner software.")
63
+ info("Working with '#{@instance.platform.os_type}' platform.")
64
+ debug("Driver info: '#{@instance.driver.diagnose}'.")
65
+ debug("Transport info: '#{@instance.transport.diagnose}'.")
66
+ debug("Platform info: '#{@instance.platform.diagnose}'.")
67
+ instance_platform = detect_platform
68
+
69
+ if @config[:remote_executor]
70
+ if windows_os?
71
+ message = unindent(<<-MSG)
72
+
73
+ ===============================================================================
74
+ We can't use Windows platform with remote installation.
75
+ Abandon ship!
76
+ ===============================================================================
77
+ MSG
78
+ raise UserError, message
79
+ end
80
+ info('Using remote executor.')
81
+
82
+ """
83
+ #{Install.make(@config, instance_platform).remote_install}
84
+ """
85
+ else
86
+ info('Using local executor.')
87
+ if command_exists(command) and !@config[:sandboxed_executor]
88
+ info('Ansible is installed already - proceeding further steps.')
89
+ else
90
+ if RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
91
+ message = unindent(<<-MSG)
92
+
93
+ ===============================================================================
94
+ We can't use Windows platform as a Host system for sandboxing.
95
+ Abandon ship!
96
+ ===============================================================================
97
+ MSG
98
+ raise UserError, message
99
+ else
100
+ additional_packages = []
101
+ info('Checking for sandboxed Ansible version.')
102
+
103
+ if windows_os?
104
+ # ok, adding pywinrm
105
+ info('==> Windows target platform may be tested only using local Ansible installation! <==')
106
+ additional_packages.push('pywinrm')
107
+ end
108
+
109
+ # create sandbox
110
+ if command_exists("#{venv_root}/bin/ansible")
111
+ info("Ansible is installed at '#{venv_root}'.")
112
+ else
113
+ info("Ansible is not installed - will try to create local sandbox for execution")
114
+ if command_exists('virtualenv')
115
+ system("virtualenv #{venv_root}")
116
+ system("#{venv_root}/bin/pip install " +
117
+ "#{Install.make(@config, instance_platform).pip_required_packages.join(' ')}"
118
+ )
119
+ else
120
+ message = unindent(<<-MSG)
121
+
122
+ ===============================================================================
123
+ Couldn't find virtualenv binary for sandboxing.
124
+ Please make sure execution host has Python and VirtualEnv packages installed.
125
+ ===============================================================================
126
+ MSG
127
+ raise UserError, message
128
+ end
129
+ end
130
+ end
131
+ end
132
+
133
+ """
134
+ #{Install.make(@config, instance_platform).local_install}
135
+ """
136
+ end
137
+ end
138
+
139
+ def init_command
140
+ info("Initializing provisioner software.")
141
+ "mkdir #{windows_os? ? '-Force' : '-p'} #{config[:root_path]}"
142
+ end
143
+
144
+ def prepare_command
145
+ info("Preparing configuration for provisioner.")
146
+ unless @config[:remote_executor]
147
+ generate_inventory(inventory_file)
148
+ end
149
+
150
+ ""
151
+ end
152
+
153
+ def create_sandbox
154
+ super
155
+
156
+ directories = %w[
157
+ roles
158
+ host_vars
159
+ group_vars
160
+ module_utils
161
+ library
162
+ callback_plugins
163
+ connection_plugins
164
+ filter_plugins
165
+ lookup_plugins
166
+ ]
167
+
168
+ prepare_dependencies(@config[:dependencies])
169
+ generate_inventory(inventory_file, remote: true)
170
+
171
+ info("Copy dependencies to sandbox")
172
+ copy_dirs_to_sandbox(dependencies_tmp_dir, dst: 'roles')
173
+ directories.each do |directory|
174
+ if File.directory?(directory)
175
+ info("Copy #{directory} to sandbox")
176
+ copy_dirs_to_sandbox(directory)
177
+ end
178
+ end
179
+ info("Prepare config")
180
+ prepare_ansible_config
181
+ info("Prepare playbook")
182
+ prepare_playbook_file
183
+ info("Prepare inventory file")
184
+ prepare_inventory_file
185
+ end
186
+
187
+ def run_command
188
+ if @config[:remote_executor]
189
+ info("Execute Ansible remotely.")
190
+
191
+ command_env_script = []
192
+ command_env.each {|k,v| command_env_script.push(shell_env_var(k, v))}
193
+
194
+ """
195
+ #{command_env_script.join(' ')}; #{command} #{command_args.join(' ')}
196
+ """
197
+ else
198
+ info("Execute Ansible locally.")
199
+ execute_local_command("#{command} #{command_args.join(' ')}", env: command_env, print_stdout: true)
200
+
201
+ ""
202
+ end
203
+ end
204
+
205
+ def command
206
+ return @command if defined? @command
207
+
208
+ @command = @config[:ansible_binary]
209
+ debug("Ansible command: #{@command}")
210
+ @command
211
+ end
212
+
213
+ def command_env
214
+ return @command_env if defined? @command_env
215
+
216
+ # noinspection RubyStringKeysInHashInspection
217
+ @command_env = {
218
+ 'ANSIBLE_FORCE_COLOR' => @config[:ansible_force_color].to_s,
219
+ 'ANSIBLE_HOST_KEY_CHECKING' => @config[:ansible_host_key_checking].to_s,
220
+ 'ANSIBLE_INVENTORY_ENABLED' => 'yaml',
221
+ 'ANSIBLE_RETRY_FILES_ENABLED' => false.to_s,
222
+ 'ANSIBLE_ROLES_PATH' => remote_file_path('roles', fallback: generate_sandbox_path('roles')),
223
+ }
224
+ @command_env['ANSIBLE_CONFIG'] = @config[:ansible_config] if @config[:ansible_config]
225
+
226
+ @command_env
227
+ end
228
+
229
+ def command_args
230
+ return @command_args if defined? @command_args
231
+
232
+ @command_args = []
233
+ @config[:ansible_extra_arguments].each { |arg| @command_args.push(arg) } if @config[:ansible_extra_arguments]
234
+ @config[:ansible_verbose] ? @command_args.push('-' + 'v' * @config[:ansible_verbosity]) : ''
235
+ @command_args.push("--inventory=#{remote_file_path(ANSIBLE_INVENTORY, fallback: inventory_file)}")
236
+ @command_args.push("--limit=#{@instance.name}")
237
+ @command_args.push(remote_file_path(@config[:playbook]))
238
+
239
+ @command_args
240
+ end
241
+ end
242
+ end
243
+ end