kitchen-yansible 0.0.1
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 +7 -0
- data/kitchen-yansible.gemspec +59 -0
- data/lib/kitchen-yansible/tools/dependencies.rb +90 -0
- data/lib/kitchen-yansible/tools/exec.rb +111 -0
- data/lib/kitchen-yansible/tools/files.rb +179 -0
- data/lib/kitchen-yansible/tools/install.rb +234 -0
- data/lib/kitchen-yansible/tools/install/amazon.rb +67 -0
- data/lib/kitchen-yansible/tools/install/debian.rb +201 -0
- data/lib/kitchen-yansible/tools/install/fedora.rb +33 -0
- data/lib/kitchen-yansible/tools/install/rhel.rb +225 -0
- data/lib/kitchen-yansible/tools/install/windows.rb +122 -0
- data/lib/kitchen-yansible/version.rb +25 -0
- data/lib/kitchen/provisioner/yansible.rb +243 -0
- metadata +101 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: da916e8bba8652a388e29c59ae55a3b284f235079feaf3ab5c5be934abe1aae2
|
|
4
|
+
data.tar.gz: 3cfd7f8c238238cec9d607dbd4e1fe2b5be81983524bce8d57af1f811d90c3d2
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 66ff510329b64430d75ae50aba3580e862d434ee9dd5788c47d99b6d201c5a8477b88a5c5b94207b892139758f544feb32efb72a6b9f6b88114eddae1c85ace6
|
|
7
|
+
data.tar.gz: 076f4e1cac5146328c00a9bf261845d6f9815358ad863cdca8383209ab11acd58d9cc254f881ab7bfae9def630bf3a9cfe050f20ae4b095fbbc7954a0e30797e
|
|
@@ -0,0 +1,59 @@
|
|
|
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
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
|
|
22
|
+
require 'kitchen-yansible/version'
|
|
23
|
+
|
|
24
|
+
Gem::Specification.new do |s|
|
|
25
|
+
s.name = 'kitchen-yansible'
|
|
26
|
+
s.license = 'Apache-2.0'
|
|
27
|
+
s.version = Kitchen::Yansible::VERSION
|
|
28
|
+
s.authors = ['Eugene Akhmetkhanov']
|
|
29
|
+
s.email = ['axmetishe+github@gmail.com']
|
|
30
|
+
s.homepage = 'https://github.com/axmetishe/kitchen-yansible'
|
|
31
|
+
s.summary = 'Yet Another Ansible Test-Kitchen Provisioner'
|
|
32
|
+
s.files = (Dir.glob('{lib}/**/*') + ['kitchen-yansible.gemspec']).sort
|
|
33
|
+
s.platform = Gem::Platform::RUBY
|
|
34
|
+
s.require_paths = ['lib']
|
|
35
|
+
s.rubyforge_project = '[none]'
|
|
36
|
+
s.description = <<-EOF
|
|
37
|
+
Yet Another Ansible Test Kitchen Provisioner
|
|
38
|
+
|
|
39
|
+
Features:
|
|
40
|
+
- Local and remote execution using single provisioner
|
|
41
|
+
- Local Ansible sandbox configuration using Virtualenv
|
|
42
|
+
- Local execution using Ansible from PATH
|
|
43
|
+
- Remote Ansible installation via Pip and Virtualenv
|
|
44
|
+
- Dependency management
|
|
45
|
+
- Path based
|
|
46
|
+
- Git repositories
|
|
47
|
+
- Drivers
|
|
48
|
+
- Docker
|
|
49
|
+
- Vagrant
|
|
50
|
+
- Platforms
|
|
51
|
+
- RHEL-based - CentOS, Fedora, Amazon Linux, Oracle Linux
|
|
52
|
+
- Debian-based - Debian, Ubuntu
|
|
53
|
+
- Windows via PS Remoting (Local executor only)
|
|
54
|
+
|
|
55
|
+
EOF
|
|
56
|
+
|
|
57
|
+
s.add_runtime_dependency 'test-kitchen', '~> 2.0'
|
|
58
|
+
s.add_runtime_dependency 'rugged', '~> 0.25'
|
|
59
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Author: Eugene Akhmetkhanov <axmetishe+github@gmail.com>
|
|
2
|
+
# Date: 11-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 'rugged'
|
|
22
|
+
|
|
23
|
+
module Kitchen
|
|
24
|
+
module Yansible
|
|
25
|
+
module Tools
|
|
26
|
+
module Dependencies
|
|
27
|
+
def git_clone(name, url, path)
|
|
28
|
+
info("Cloning '#{name}' Git repository.")
|
|
29
|
+
Rugged::Repository.clone_at(url, path, { :ignore_cert_errors => true })
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def prepare_dependencies(dependencies)
|
|
33
|
+
dependencies.each do |dependency|
|
|
34
|
+
info("Processing '#{dependency[:name]}' dependency.")
|
|
35
|
+
dependency_target_path = File.join(dependencies_tmp_dir, dependency[:name])
|
|
36
|
+
if dependency.key?(:path)
|
|
37
|
+
info('Processing as path type.')
|
|
38
|
+
if File.exist?(dependency[:path])
|
|
39
|
+
copy_dirs(dependency[:path], dependency_target_path)
|
|
40
|
+
else
|
|
41
|
+
warn("Dependency path '#{dependency[:path]}' doesn't exists. Omitting copy operation.")
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
if dependency.key?(:repo)
|
|
45
|
+
if dependency[:repo].downcase == 'git'
|
|
46
|
+
info('Processing as Git repository.')
|
|
47
|
+
begin
|
|
48
|
+
repo = Rugged::Repository.new(dependency_target_path)
|
|
49
|
+
if repo.remotes.first.url.eql?(dependency[:url])
|
|
50
|
+
warn("Dependency cloned already.")
|
|
51
|
+
else
|
|
52
|
+
warn("Removing directory #{dependency_target_path} due to repository origin difference.")
|
|
53
|
+
FileUtils.remove_entry_secure(dependency_target_path)
|
|
54
|
+
git_clone(dependency[:name], dependency[:url], dependency_target_path)
|
|
55
|
+
end
|
|
56
|
+
rescue
|
|
57
|
+
if File.exist?(dependency_target_path)
|
|
58
|
+
warn("Dependency path '#{dependency_target_path}' is not a valid Git repository. Removing then.")
|
|
59
|
+
FileUtils.remove_entry_secure(dependency_target_path)
|
|
60
|
+
end
|
|
61
|
+
repo = git_clone(dependency[:name], dependency[:url], dependency_target_path)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
raw_ref = dependency.key?(:ref) ? dependency[:ref] : 'master'
|
|
65
|
+
begin
|
|
66
|
+
repo.rev_parse(raw_ref)
|
|
67
|
+
rescue
|
|
68
|
+
message = unindent(<<-MSG)
|
|
69
|
+
|
|
70
|
+
===============================================================================
|
|
71
|
+
Invalid Git reference - #{raw_ref}
|
|
72
|
+
Please check '#{dependency[:name]}' dependency configuration.
|
|
73
|
+
===============================================================================
|
|
74
|
+
MSG
|
|
75
|
+
raise UserError, message
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
info("Resetting '#{dependency[:name]}' repository to '#{raw_ref}' reference.")
|
|
79
|
+
repo.checkout(raw_ref, {:strategy => :force})
|
|
80
|
+
repo.close
|
|
81
|
+
else
|
|
82
|
+
raise UserError, "Working with '#{dependency[:repo]}' repository is not implemented yet."
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end unless dependencies.nil?
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
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
|
+
require 'open3'
|
|
22
|
+
|
|
23
|
+
module Kitchen
|
|
24
|
+
module Yansible
|
|
25
|
+
module Tools
|
|
26
|
+
module Exec
|
|
27
|
+
def unindent(s)
|
|
28
|
+
s.gsub(/^#{s.scan(/^[ \t]+(?=\S)/).min}/, '')
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def check_command(command, args: '')
|
|
32
|
+
"command -v #{command}" + "#{(" #{args}" unless args.empty?)}"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def command_exists(command)
|
|
36
|
+
check_command(command, :args => '&>/dev/null')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def local_command_path(command, args: '')
|
|
40
|
+
system(check_command(command, args))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def local_command_exists(command)
|
|
44
|
+
"#{local_command_path(command, :args => '&>/dev/null')}"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def print_cmd_parameters(command, env = {})
|
|
48
|
+
env_vars = []
|
|
49
|
+
env.each { |k,v| env_vars.push("#{k}=#{v}") }
|
|
50
|
+
message = unindent(<<-MSG)
|
|
51
|
+
|
|
52
|
+
===============================================================================
|
|
53
|
+
Environment:
|
|
54
|
+
#{env_vars.join("\n ")}
|
|
55
|
+
Command line:
|
|
56
|
+
#{command}
|
|
57
|
+
===============================================================================
|
|
58
|
+
MSG
|
|
59
|
+
debug(message)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def print_cmd_error(stderr, proc)
|
|
63
|
+
message = unindent(<<-MSG)
|
|
64
|
+
|
|
65
|
+
===============================================================================
|
|
66
|
+
Command returned '#{proc.exitstatus}'.
|
|
67
|
+
stderr: '#{stderr.read}'
|
|
68
|
+
===============================================================================
|
|
69
|
+
MSG
|
|
70
|
+
debug(message)
|
|
71
|
+
raise UserError, message unless proc.success?
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def execute_local_command(command, env: {}, opts: {}, print_stdout: false, return_stdout: false)
|
|
75
|
+
print_cmd_parameters(command, env)
|
|
76
|
+
|
|
77
|
+
# noinspection RubyUnusedLocalVariable
|
|
78
|
+
Open3.popen3(env, command, opts) { |stdin, stdout, stderr, thread|
|
|
79
|
+
if print_stdout
|
|
80
|
+
while (line = stdout.gets)
|
|
81
|
+
puts line
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
proc = thread.value
|
|
85
|
+
|
|
86
|
+
print_cmd_error(stderr, proc)
|
|
87
|
+
return_stdout ? stdout.read : proc.success?
|
|
88
|
+
}
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Helpers
|
|
92
|
+
def sudo_env(pm)
|
|
93
|
+
s = @config[:https_proxy] ? "https_proxy=#{@config[:https_proxy]}" : nil
|
|
94
|
+
p = @config[:http_proxy] ? "http_proxy=#{@config[:http_proxy]}" : nil
|
|
95
|
+
n = @config[:no_proxy] ? "no_proxy=#{@config[:no_proxy]}" : nil
|
|
96
|
+
p || s ? "#{sudo('env')} #{p} #{s} #{n} #{pm}" : "#{sudo(pm)}"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Taken from https://github.com/test-kitchen/test-kitchen/blob/master/lib/kitchen/provisioner/base.rb
|
|
100
|
+
def sudo(script)
|
|
101
|
+
"sudo -E #{script}"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def detect_platform
|
|
105
|
+
@instance.driver.diagnose[:name] == 'docker' ?
|
|
106
|
+
@instance.driver.diagnose[:platform].to_s : @instance.platform.name.to_s
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,179 @@
|
|
|
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
|
+
module Files
|
|
25
|
+
ANSIBLE_INVENTORY = "inventory.yml"
|
|
26
|
+
|
|
27
|
+
def inventory_file
|
|
28
|
+
File.join(instance_tmp_dir, ANSIBLE_INVENTORY)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def remote_file_path(file_path, fallback: nil)
|
|
32
|
+
if @config[:remote_executor]
|
|
33
|
+
File.join(@config[:root_path], file_path)
|
|
34
|
+
else
|
|
35
|
+
fallback.nil? ? file_path : fallback
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def prepare_ansible_config
|
|
40
|
+
if @config[:ansible_config]
|
|
41
|
+
copy_files(@config[:ansible_config], File.join(sandbox_path, @config[:ansible_config]))
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def prepare_playbook_file
|
|
46
|
+
if @config[:remote_executor]
|
|
47
|
+
copy_files(@config[:playbook], File.join(sandbox_path, @config[:playbook]))
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def prepare_inventory_file
|
|
52
|
+
if @config[:remote_executor]
|
|
53
|
+
copy_files(inventory_file, File.join(sandbox_path, ANSIBLE_INVENTORY))
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def generate_sandbox_path(directory)
|
|
58
|
+
path = File.join(sandbox_path, directory)
|
|
59
|
+
Dir.mkdir(path) unless File.exist?(path)
|
|
60
|
+
path
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def executor_tmp_dir
|
|
64
|
+
if !@executor_tmp_dir && !instance.nil?
|
|
65
|
+
@executor_tmp_dir = File.join(config[:kitchen_root], %w[ .kitchen yansible ])
|
|
66
|
+
end
|
|
67
|
+
Dir.mkdir(@executor_tmp_dir) unless File.exist?(@executor_tmp_dir)
|
|
68
|
+
@executor_tmp_dir
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def instance_tmp_dir
|
|
72
|
+
if !@instance_tmp_dir && !instance.nil?
|
|
73
|
+
@instance_tmp_dir = File.join(executor_tmp_dir, @instance.name)
|
|
74
|
+
end
|
|
75
|
+
Dir.mkdir(@instance_tmp_dir) unless File.exist?(@instance_tmp_dir)
|
|
76
|
+
@instance_tmp_dir
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def dependencies_tmp_dir
|
|
80
|
+
if !@dependencies_tmp_dir && !instance.nil?
|
|
81
|
+
@dependencies_tmp_dir = File.join(instance_tmp_dir, 'dependencies')
|
|
82
|
+
end
|
|
83
|
+
Dir.mkdir(@dependencies_tmp_dir) unless File.exist?(@dependencies_tmp_dir)
|
|
84
|
+
@dependencies_tmp_dir
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def venv_root
|
|
88
|
+
if !@venv_root && !instance.nil?
|
|
89
|
+
@venv_root = File.join(instance_tmp_dir, 'venv')
|
|
90
|
+
end
|
|
91
|
+
@venv_root
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def generate_inventory(inventory_file, remote: false)
|
|
95
|
+
connection = @instance.transport.instance_variable_get(:@connection_options)
|
|
96
|
+
transport_conf = @instance.transport.diagnose
|
|
97
|
+
host_conn_vars = {}
|
|
98
|
+
|
|
99
|
+
debug("===> Connection options")
|
|
100
|
+
debug(connection.to_s)
|
|
101
|
+
debug("===> Transport options")
|
|
102
|
+
debug(transport_conf.to_s)
|
|
103
|
+
if remote
|
|
104
|
+
debug("Generating inventory stub for execution on remote target")
|
|
105
|
+
host_conn_vars['ansible_connection'] = 'local'
|
|
106
|
+
host_conn_vars['ansible_host'] = 'localhost'
|
|
107
|
+
else
|
|
108
|
+
debug("Generating inventory for execution on local host with remote targets")
|
|
109
|
+
host_conn_vars['ansible_connection'] = transport_conf[:name] if transport_conf[:name]
|
|
110
|
+
host_conn_vars['ansible_password'] = connection[:password] if connection[:password]
|
|
111
|
+
|
|
112
|
+
case transport_conf[:name]
|
|
113
|
+
when 'winrm'
|
|
114
|
+
host_conn_vars['ansible_host'] = URI.parse(connection[:endpoint]).hostname
|
|
115
|
+
host_conn_vars['ansible_user'] = connection[:user] if connection[:user]
|
|
116
|
+
host_conn_vars['ansible_winrm_transport'] = @config[:ansible_winrm_auth_transport] if @config[:ansible_winrm_auth_transport]
|
|
117
|
+
host_conn_vars['ansible_winrm_scheme'] = transport_conf[:winrm_transport] == :ssl ? 'https' : 'http'
|
|
118
|
+
host_conn_vars['ansible_winrm_server_cert_validation'] = @config[:ansible_winrm_cert_validation] if @config[:ansible_winrm_cert_validation]
|
|
119
|
+
when 'ssh'
|
|
120
|
+
host_conn_vars['ansible_host'] = connection[:hostname]
|
|
121
|
+
host_conn_vars['ansible_user'] = connection[:username] if connection[:username]
|
|
122
|
+
host_conn_vars['ansible_port'] = connection[:port] if connection[:port]
|
|
123
|
+
host_conn_vars['ansible_ssh_retries'] = connection[:connection_retries] if connection[:connection_retries]
|
|
124
|
+
host_conn_vars['ansible_private_key_file'] = connection[:keys].first if connection[:keys]
|
|
125
|
+
host_conn_vars['ansible_host_key_checking'] = @config[:ansible_host_key_checking] if @config[:ansible_host_key_checking]
|
|
126
|
+
else
|
|
127
|
+
message = unindent(<<-MSG)
|
|
128
|
+
|
|
129
|
+
===============================================================================
|
|
130
|
+
Unsupported transport - #{transport_conf[:name]}
|
|
131
|
+
SSH and WinRM transports are allowed.
|
|
132
|
+
===============================================================================
|
|
133
|
+
MSG
|
|
134
|
+
raise UserError, message
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# noinspection RubyStringKeysInHashInspection
|
|
139
|
+
inv = { 'all' => { 'hosts' => { @instance.name => host_conn_vars } } }
|
|
140
|
+
|
|
141
|
+
File.open(inventory_file, 'w') do |file|
|
|
142
|
+
file.write inv.to_yaml
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def copy_files(src, dst, overwrite: true)
|
|
147
|
+
debug("Copy '#{src}' to '#{dst}'")
|
|
148
|
+
|
|
149
|
+
FileUtils.copy_entry(src, dst, remove_destination=overwrite)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def copy_dirs(src, dst, reject: '.git')
|
|
153
|
+
expand_path=File.expand_path(src)
|
|
154
|
+
if File.exist?(expand_path)
|
|
155
|
+
debug("Copy '#{src}' to '#{dst}'.")
|
|
156
|
+
debug("'#{src}' expanded to '#{expand_path}'")
|
|
157
|
+
Dir.glob("#{expand_path}/**/{*,.*}").reject{|f| f[reject]}.each do |file|
|
|
158
|
+
target = dst + file.sub(expand_path, '')
|
|
159
|
+
if File.file?(file)
|
|
160
|
+
FileUtils.copy_entry(file, target, remove_destination: true)
|
|
161
|
+
else
|
|
162
|
+
FileUtils.mkdir_p(target) unless File.exist?(target)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
else
|
|
166
|
+
debug("Path '#{src}' doesn't exists. Omitting copy operation.")
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def copy_dirs_to_sandbox(src, dst: src, reject: '.git')
|
|
171
|
+
dest = generate_sandbox_path(dst)
|
|
172
|
+
debug("'#{src}' => '#{dest}', reject => '#{reject}'.")
|
|
173
|
+
|
|
174
|
+
copy_dirs(src, dest, reject: reject)
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|