kitchen-ansiblepush 0.3.5 → 0.3.6
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 +4 -4
- data/lib/kitchen-ansible/version.rb +1 -1
- data/lib/kitchen/provisioner/ansible_push.rb +169 -106
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f868950792eff721e4655c0687470892baa43e53
|
|
4
|
+
data.tar.gz: f470fad4ccf0f485d72cb44679d4f552960f7cad
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: de09cf33c70ac1bd34c68daee546d01117fbe68a17001bae1067a5800374a31826d6d7ac684aefdbeabe547333fa90f810efaf853b5125dd6cd65424b8a6556e
|
|
7
|
+
data.tar.gz: 80a146900bea7fa18356b1280eda4fdc84e0932f691f484bf254fb28b750956e62c4c986cd3bce3395b65752665498bbddd1e7390e26e9be647febde87cf12ae
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require 'open3'
|
|
1
2
|
require 'kitchen'
|
|
2
3
|
require 'kitchen/provisioner/base'
|
|
3
4
|
require 'kitchen-ansible/util-inventory.rb'
|
|
@@ -14,6 +15,7 @@ module Kitchen
|
|
|
14
15
|
module Provisioner
|
|
15
16
|
class AnsiblePush < Base
|
|
16
17
|
kitchen_provisioner_api_version 2
|
|
18
|
+
default_config :ansible_playbook_bin, "ansible-playbook"
|
|
17
19
|
default_config :ansible_config, nil
|
|
18
20
|
default_config :verbose, nil
|
|
19
21
|
default_config :diff, nil
|
|
@@ -33,16 +35,114 @@ module Kitchen
|
|
|
33
35
|
default_config :mygroup, nil
|
|
34
36
|
default_config :playbook, nil
|
|
35
37
|
default_config :generate_inv, true
|
|
38
|
+
default_config :generate_inv_path, "`which kitchen-ansible-inventory`"
|
|
36
39
|
default_config :raw_arguments, nil
|
|
37
40
|
default_config :idempotency_test, false
|
|
38
41
|
|
|
39
42
|
# For tests disable if not needed
|
|
40
43
|
default_config :chef_bootstrap_url, "https://www.getchef.com/chef/install.sh"
|
|
41
44
|
|
|
45
|
+
default_config :support_older_version, false
|
|
46
|
+
|
|
47
|
+
# Validates the config and returns it. Has side-effect of
|
|
48
|
+
# possibly setting @extra_vars which doesn't seem to be used
|
|
49
|
+
def conf
|
|
50
|
+
return @validated_config if defined? @validated_config
|
|
51
|
+
|
|
52
|
+
if !config[:playbook]
|
|
53
|
+
raise 'No playbook defined. Please specify one in .kitchen.yml'
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
if !File.exist?(config[:playbook])
|
|
57
|
+
raise "playbook '%s' could not be found. Please check path" % config[:playbook]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
if config[:vault_password_file] and !File.exist?(config[:vault_password_file])
|
|
61
|
+
raise "Vault password '%s' could not be found. Please check path" % config[:vault_password_file]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Validate that extra_vars is either a hash, or a path to an existing file
|
|
65
|
+
if config[:extra_vars]
|
|
66
|
+
extra_vars_is_valid = config[:extra_vars].kind_of?(Hash) || config[:extra_vars].kind_of?(String)
|
|
67
|
+
if config[:extra_vars].kind_of?(String)
|
|
68
|
+
# Accept the usage of '@' (e.g. '@vars.yml' and 'vars.yml' are both supported)
|
|
69
|
+
match_data = /^@?(.+)$/.match(config[:extra_vars])
|
|
70
|
+
extra_vars_path = match_data[1].to_s
|
|
71
|
+
expanded_path = Pathname.new(extra_vars_path).expand_path(Dir.pwd)
|
|
72
|
+
extra_vars_is_valid = expanded_path.exist?
|
|
73
|
+
if extra_vars_is_valid
|
|
74
|
+
@extra_vars = '@' + extra_vars_path
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
if !extra_vars_is_valid
|
|
78
|
+
raise "ansible extra_vars is in valid type: %s value: %s" % [config[:extra_vars].class.to_s, config[:extra_vars].to_s]
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
info("Ansible push config validated")
|
|
83
|
+
|
|
84
|
+
@validated_config = config
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def machine_name
|
|
88
|
+
return @machine_name if defined? @machine_name
|
|
89
|
+
@machine_name = instance.name.gsub(/[<>]/, '').split("-").drop(1).join("-")
|
|
90
|
+
debug("machine_name=" + @machine_name.to_s)
|
|
91
|
+
@machine_name
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def options
|
|
95
|
+
return @options if defined? @options
|
|
96
|
+
options = []
|
|
97
|
+
options << "--extra-vars='#{self.get_extra_vars_argument}'" if conf[:extra_vars]
|
|
98
|
+
options << "--sudo" if conf[:sudo]
|
|
99
|
+
options << "--sudo-user=#{conf[:sudo_user]}" if conf[:sudo_user]
|
|
100
|
+
options << "--user=#{conf[:remote_user]}" if self.get_remote_user
|
|
101
|
+
options << "--private-key=#{conf[:private_key]}" if conf[:private_key]
|
|
102
|
+
options << "#{self.get_verbosity_argument}" if conf[:verbose]
|
|
103
|
+
options << "--diff" if conf[:diff]
|
|
104
|
+
options << "--ask-sudo-pass" if conf[:ask_sudo_pass]
|
|
105
|
+
options << "--ask-vault-pass" if conf[:ask_vault_pass]
|
|
106
|
+
options << "--vault-password-file=#{conf[:vault_password_file]}" if conf[:vault_password_file]
|
|
107
|
+
options << "--tags=%s" % self.as_list_argument(conf[:tags]) if conf[:tags]
|
|
108
|
+
options << "--skip-tags=%s" % self.as_list_argument(conf[:skip_tags]) if conf[:skip_tags]
|
|
109
|
+
options << "--start-at-task=#{conf[:start_at_task]}" if conf[:start_at_task]
|
|
110
|
+
options << "--inventory-file=#{conf[:generate_inv_path]}" if conf[:generate_inv]
|
|
111
|
+
##options << "--inventory-file=#{ssh_inv}," if ssh_inv
|
|
112
|
+
|
|
113
|
+
# By default we limit by the current machine,
|
|
114
|
+
if conf[:limit]
|
|
115
|
+
options << "--limit=#{as_list_argument(conf[:limit])}"
|
|
116
|
+
else
|
|
117
|
+
options << "--limit=#{machine_name}"
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
#Add raw argument as final thing
|
|
121
|
+
options << conf[:raw_arguments] if conf[:raw_arguments]
|
|
122
|
+
@options = options
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def command
|
|
126
|
+
return @command if defined? @command
|
|
127
|
+
@command = [conf[:ansible_playbook_bin]]
|
|
128
|
+
@command = (@command << options() << conf[:playbook]).flatten.join(" ")
|
|
129
|
+
debug("Ansible push command= %s" % @command)
|
|
130
|
+
@command
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def command_env
|
|
134
|
+
return @command_env if defined? @command_env
|
|
135
|
+
@command_env = {
|
|
136
|
+
"PYTHONUNBUFFERED" => "1", # Ensure Ansible output isn't buffered
|
|
137
|
+
"ANSIBLE_FORCE_COLOR" => "true",
|
|
138
|
+
"ANSIBLE_HOST_KEY_CHECKING" => "#{conf[:host_key_checking]}",
|
|
139
|
+
}
|
|
140
|
+
@command_env["ANSIBLE_CONFIG"]=conf[:ansible_config] if conf[:ansible_config]
|
|
141
|
+
@command_env
|
|
142
|
+
end
|
|
143
|
+
|
|
42
144
|
def prepare_command
|
|
43
|
-
|
|
44
|
-
prepare_inventory if config[:generate_inv]
|
|
45
|
-
complie_config
|
|
145
|
+
prepare_inventory if conf[:generate_inv]
|
|
46
146
|
# Place holder so a string is returned. This will execute true on remote host
|
|
47
147
|
return "true"
|
|
48
148
|
end
|
|
@@ -50,12 +150,22 @@ module Kitchen
|
|
|
50
150
|
def install_command
|
|
51
151
|
# Must install chef for busser and serverspec to work :(
|
|
52
152
|
info("*************** AnsiblePush install_command ***************")
|
|
53
|
-
|
|
54
|
-
|
|
153
|
+
older_version = conf[:support_older_version]
|
|
154
|
+
if older_version
|
|
155
|
+
stdin, stdout, stderr = Open3.popen3(command_env(), command() + " --version")
|
|
156
|
+
version_output = stdout.read()
|
|
157
|
+
version_string = version_output.split()[1]
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
omnibus_download_dir = conf[:omnibus_cachier] ? "/tmp/vagrant-cache/omnibus_chef" : "/tmp"
|
|
161
|
+
chef_url = conf[:chef_bootstrap_url]
|
|
162
|
+
|
|
55
163
|
if chef_url
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
164
|
+
scripts = []
|
|
165
|
+
|
|
166
|
+
scripts << Util.shell_helpers
|
|
167
|
+
|
|
168
|
+
scripts << <<-INSTALL
|
|
59
169
|
if [ ! -d "/opt/chef" ]
|
|
60
170
|
then
|
|
61
171
|
echo "-----> Installing Chef Omnibus needed by busser and serverspec"
|
|
@@ -68,26 +178,49 @@ module Kitchen
|
|
|
68
178
|
sudo sh #{omnibus_download_dir}/install.sh -d #{omnibus_download_dir}
|
|
69
179
|
echo "-----> End Installing Chef Omnibus"
|
|
70
180
|
fi
|
|
181
|
+
INSTALL
|
|
182
|
+
|
|
183
|
+
if (older_version) and(version_string.split('.').map{|s|s.to_i} <=> [1, 6, 0]) < 0
|
|
184
|
+
info("Ansible Version < 1.6.0")
|
|
185
|
+
scripts << <<-INSTALL
|
|
186
|
+
# Older versions of ansible do not set up python-apt or
|
|
187
|
+
# python-pycurl by default on Ubuntu
|
|
188
|
+
# https://github.com/ansible/ansible/issues/4079
|
|
189
|
+
# https://github.com/ansible/ansible/issues/6910
|
|
190
|
+
echo "-----> Installing python-apt, python-pycurl if needed"
|
|
191
|
+
/usr/bin/python -c "import apt, apt_pkg, pycurl" 2>&1 > /dev/null || \
|
|
192
|
+
{ [ -x /usr/bin/apt-get ] && \
|
|
193
|
+
sudo /usr/bin/apt-get update && \
|
|
194
|
+
sudo /usr/bin/apt-get install python-apt python-pycurl -y -q \
|
|
195
|
+
; }
|
|
196
|
+
echo "-----> End Installing python-apt, python-pycurl if needed"
|
|
197
|
+
INSTALL
|
|
198
|
+
end
|
|
71
199
|
|
|
200
|
+
scripts << <<-INSTALL
|
|
72
201
|
# Fix for https://github.com/test-kitchen/busser/issues/12
|
|
73
202
|
if [ -h /usr/bin/ruby ]; then
|
|
74
203
|
L=$(readlink -f /usr/bin/ruby)
|
|
75
204
|
sudo rm /usr/bin/ruby
|
|
76
205
|
sudo ln -s $L /usr/bin/ruby
|
|
77
206
|
fi
|
|
78
|
-
|
|
207
|
+
INSTALL
|
|
208
|
+
|
|
209
|
+
<<-INSTALL
|
|
210
|
+
sh -c '#{scripts.join("\n")}'
|
|
79
211
|
INSTALL
|
|
80
212
|
end
|
|
81
213
|
end
|
|
82
214
|
|
|
83
215
|
def run_command
|
|
84
216
|
info("*************** AnsiblePush run ***************")
|
|
85
|
-
exec_ansible_command(
|
|
217
|
+
exec_ansible_command(command_env(), command(), "ansible-playbook")
|
|
86
218
|
# idempotency test
|
|
87
|
-
if
|
|
219
|
+
if conf[:idempotency_test]
|
|
88
220
|
info("*************** idempotency test ***************")
|
|
89
|
-
|
|
90
|
-
|
|
221
|
+
exec_ansible_command(command_env().merge({
|
|
222
|
+
"ANSIBLE_CALLBACK_PLUGINS" => "#{File.dirname(__FILE__)}/../../../callback/"
|
|
223
|
+
}), command(), "ansible-playbook")
|
|
91
224
|
# Check ansible callback if changes has occured in the second run
|
|
92
225
|
file_path = "/tmp/kitchen_ansible_callback/changes"
|
|
93
226
|
if File.file?(file_path)
|
|
@@ -106,7 +239,7 @@ module Kitchen
|
|
|
106
239
|
end
|
|
107
240
|
end
|
|
108
241
|
info("*************** AnsiblePush end run *******************")
|
|
109
|
-
debug("[#{name}] Converge completed (#{
|
|
242
|
+
debug("[#{name}] Converge completed (#{conf[:sleep]}s).")
|
|
110
243
|
# Place holder so a string is returned. This will execute true on remote host
|
|
111
244
|
return "true"
|
|
112
245
|
end
|
|
@@ -123,111 +256,41 @@ module Kitchen
|
|
|
123
256
|
end
|
|
124
257
|
end
|
|
125
258
|
|
|
126
|
-
def
|
|
127
|
-
@
|
|
128
|
-
debug("machine_name=" + @machine_name.to_s)
|
|
259
|
+
def instance_connection_option
|
|
260
|
+
return @instance_connection_option if defined? @instance_connection_option
|
|
129
261
|
@instance_connection_option = instance.transport.instance_variable_get(:@connection_options)
|
|
130
262
|
debug("instance_connection_option=" + @instance_connection_option.to_s)
|
|
131
|
-
|
|
132
|
-
|
|
263
|
+
@instance_connection_option
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def prepare_inventory
|
|
267
|
+
hostname = if instance_connection_option().nil?
|
|
268
|
+
machine_name
|
|
133
269
|
else
|
|
134
|
-
|
|
270
|
+
instance_connection_option()[:hostname]
|
|
135
271
|
end
|
|
136
272
|
debug("hostname=" + hostname)
|
|
137
|
-
write_instance_inventory(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
def complie_config()
|
|
141
|
-
debug("compile_config")
|
|
142
|
-
options = []
|
|
143
|
-
options << "--extra-vars='#{self.get_extra_vars_argument}'" if config[:extra_vars]
|
|
144
|
-
options << "--sudo" if config[:sudo]
|
|
145
|
-
options << "--sudo-user=#{config[:sudo_user]}" if config[:sudo_user]
|
|
146
|
-
options << "--user=#{config[:remote_user]}" if self.get_remote_user
|
|
147
|
-
options << "--private-key=#{config[:private_key]}" if config[:private_key]
|
|
148
|
-
options << "#{self.get_verbosity_argument}" if config[:verbose]
|
|
149
|
-
options << "--diff" if config[:diff]
|
|
150
|
-
options << "--ask-sudo-pass" if config[:ask_sudo_pass]
|
|
151
|
-
options << "--ask-vault-pass" if config[:ask_vault_pass]
|
|
152
|
-
options << "--vault-password-file=#{config[:vault_password_file]}" if config[:vault_password_file]
|
|
153
|
-
options << "--tags=%s" % self.as_list_argument(config[:tags]) if config[:tags]
|
|
154
|
-
options << "--skip-tags=%s" % self.as_list_argument(config[:skip_tags]) if config[:skip_tags]
|
|
155
|
-
options << "--start-at-task=#{config[:start_at_task]}" if config[:start_at_task]
|
|
156
|
-
options << "--inventory-file=`which kitchen-ansible-inventory`" if config[:generate_inv]
|
|
157
|
-
##options << "--inventory-file=#{ssh_inv}," if ssh_inv
|
|
158
|
-
|
|
159
|
-
# By default we limit by the current machine,
|
|
160
|
-
if config[:limit]
|
|
161
|
-
options << "--limit=#{as_list_argument(config[:limit])}"
|
|
162
|
-
else
|
|
163
|
-
options << "--limit=#{@machine_name}"
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
#Add raw argument as final thing
|
|
167
|
-
options << config[:raw_arguments] if config[:raw_arguments]
|
|
168
|
-
|
|
169
|
-
@command = (%w(ansible-playbook) << options << config[:playbook]).flatten.join(" ")
|
|
170
|
-
debug("Ansible push command= %s" % @command)
|
|
171
|
-
@command_env = {
|
|
172
|
-
"PYTHONUNBUFFERED" => "1", # Ensure Ansible output isn't buffered
|
|
173
|
-
"ANSIBLE_FORCE_COLOR" => "true",
|
|
174
|
-
"ANSIBLE_HOST_KEY_CHECKING" => "#{config[:host_key_checking]}",
|
|
175
|
-
}
|
|
176
|
-
@command_env["ANSIBLE_CONFIG"]=config[:ansible_config] if config[:ansible_config]
|
|
177
|
-
info("Ansible push compile conig done")
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
def validate_config()
|
|
181
|
-
if !config[:playbook]
|
|
182
|
-
raise 'No playbook defined. Please specify one in .kitchen.yml'
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
if !File.exist?(config[:playbook])
|
|
186
|
-
raise "playbook '%s' could not be found. Please check path" % config[:playbook]
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
if config[:vault_password_file] and !File.exist?(config[:vault_password_file])
|
|
190
|
-
raise "Vault password '%s' could not be found. Please check path" % config[:vault_password_file]
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
# Validate that extra_vars is either a hash, or a path to an existing file
|
|
194
|
-
if config[:extra_vars]
|
|
195
|
-
extra_vars_is_valid = config[:extra_vars].kind_of?(Hash) || config[:extra_vars].kind_of?(String)
|
|
196
|
-
if config[:extra_vars].kind_of?(String)
|
|
197
|
-
# Accept the usage of '@' (e.g. '@vars.yml' and 'vars.yml' are both supported)
|
|
198
|
-
match_data = /^@?(.+)$/.match(config[:extra_vars])
|
|
199
|
-
extra_vars_path = match_data[1].to_s
|
|
200
|
-
expanded_path = Pathname.new(extra_vars_path).expand_path(Dir.pwd)
|
|
201
|
-
extra_vars_is_valid = expanded_path.exist?
|
|
202
|
-
if extra_vars_is_valid
|
|
203
|
-
@extra_vars = '@' + extra_vars_path
|
|
204
|
-
end
|
|
205
|
-
end
|
|
206
|
-
if !extra_vars_is_valid
|
|
207
|
-
raise "ansible extra_vars is in valid type: %s value: %s" % [config[:extra_vars].class.to_s, config[:extra_vars].to_s]
|
|
208
|
-
end
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
info("Ansible push config validated")
|
|
273
|
+
write_instance_inventory(machine_name, hostname,
|
|
274
|
+
conf[:mygroup], instance_connection_option())
|
|
212
275
|
end
|
|
213
276
|
|
|
214
277
|
def get_extra_vars_argument()
|
|
215
|
-
if
|
|
278
|
+
if conf[:extra_vars].kind_of?(String) and conf[:extra_vars] =~ /^@.+$/
|
|
216
279
|
# A JSON or YAML file is referenced (requires Ansible 1.3+)
|
|
217
|
-
return
|
|
280
|
+
return conf[:extra_vars]
|
|
218
281
|
else
|
|
219
282
|
# Expected to be a Hash after config validation. (extra_vars as
|
|
220
283
|
# JSON requires Ansible 1.2+, while YAML requires Ansible 1.3+)
|
|
221
|
-
return
|
|
284
|
+
return conf[:extra_vars].to_json
|
|
222
285
|
end
|
|
223
286
|
end
|
|
224
287
|
|
|
225
288
|
def get_remote_user
|
|
226
|
-
if
|
|
227
|
-
return
|
|
228
|
-
elsif
|
|
229
|
-
|
|
230
|
-
return
|
|
289
|
+
if conf[:remote_user]
|
|
290
|
+
return conf[:remote_user]
|
|
291
|
+
elsif !instance_connection_option().nil? and instance_connection_option()[:username]
|
|
292
|
+
conf[:remote_user] = instance_connection_option()[:username]
|
|
293
|
+
return instance_connection_option()[:username]
|
|
231
294
|
else
|
|
232
295
|
return false
|
|
233
296
|
end
|
|
@@ -238,9 +301,9 @@ module Kitchen
|
|
|
238
301
|
end
|
|
239
302
|
|
|
240
303
|
def get_verbosity_argument
|
|
241
|
-
if
|
|
304
|
+
if conf[:verbose].to_s =~ /^v+$/
|
|
242
305
|
# ansible-playbook accepts "silly" arguments like '-vvvvv' as '-vvvv' for now
|
|
243
|
-
return "-#{
|
|
306
|
+
return "-#{conf[:verbose]}"
|
|
244
307
|
else
|
|
245
308
|
# safe default, in case input strays
|
|
246
309
|
return '-v'
|
|
@@ -249,4 +312,4 @@ module Kitchen
|
|
|
249
312
|
|
|
250
313
|
end
|
|
251
314
|
end
|
|
252
|
-
end
|
|
315
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kitchen-ansiblepush
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Adham Helal
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-
|
|
11
|
+
date: 2015-11-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: test-kitchen
|