kitchen-ansible 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/README.md +45 -0
- data/kitchen-ansible.gemspec +29 -0
- data/lib/kitchen-ansible/version.rb +5 -0
- data/lib/kitchen/provisioner/ansible/librarian.rb +83 -0
- data/lib/kitchen/provisioner/ansible_playbook.rb +436 -0
- data/lib/kitchen/provisioner/ansible_playbook_spec.rb +33 -0
- data/provisioner_options.md +65 -0
- metadata +62 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZDdjMTc4NWYzMTQ1ZjJiODIyY2UzNDhlMDZkNDc4MmUxNTdlMzQ1YQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
OWU4MWIxODk3NTAzM2VjODA1NDg1MmNlMjZhZWE5MWQ2ZGM3MjcxZg==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MjI1ZjhhNThiNmJhMjBhMmYyMWQ4NDg4MDlmODBmNWZjYzdlMDY4NjlkZDU2
|
10
|
+
NzM5NDFiYzAxZTU4MjM5MmQ5NTA1YjZkMzg2OGZlYzcwODc3ZDk5NzA1OWY0
|
11
|
+
OTZlMTBlMGM1ZTM0NjZmMDk4NDIxMDJjMzVhMTI2ODZmNDA2MzQ=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NzNmY2EzYzczOGY4MTlkZmU5OWFiNTcyNDM5OGIwNmRiZjQxMGYzY2QxMGMw
|
14
|
+
NjRlMGY1YjQ3NjNmOGY4NWMzY2NiMGM0OTA3NmU5OTNhNjYxMjZjZWRiMDRj
|
15
|
+
ZDEyMWU2N2E1YjgzMTllNzY4Nzg1ZWY1MzNmY2JhMjE0OTU3NDc=
|
data/README.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# kitchen-ansible
|
2
|
+
A Test Kitchen Provisioner for Ansible
|
3
|
+
|
4
|
+
The provider works by passing the ansible repository based on attributes in .kitchen.yml & calling ansible-playbook.
|
5
|
+
|
6
|
+
It install ansible on the server and runs ansible-playbook using host localhost.
|
7
|
+
|
8
|
+
Has been tested against the Ubuntu 1204 and Centos 6.5 boxes running in vagrant/virtualbox.
|
9
|
+
|
10
|
+
## Requirements
|
11
|
+
You'll need a driver box without a chef installation so ansible can be installed.
|
12
|
+
|
13
|
+
## Installation & Setup
|
14
|
+
You'll need the test-kitchen & kitchen-ansible gem's installed in your system, along with kitchen-vagrant or some other suitable driver for test-kitchen.
|
15
|
+
|
16
|
+
Please see the Provisioner Options (https://github.com/neillturner/kitchen-ansible/blob/master/provisioner_options.md).
|
17
|
+
|
18
|
+
## Example kitchen.yml file
|
19
|
+
|
20
|
+
based on the example ansible setup for tomcat at https://github.com/ansible/ansible-examples/tree/master/tomcat-standalone
|
21
|
+
```
|
22
|
+
---
|
23
|
+
driver:
|
24
|
+
name: vagrant
|
25
|
+
|
26
|
+
provisioner:
|
27
|
+
name: ansible_playbook
|
28
|
+
roles_path: roles
|
29
|
+
hosts: tomcat-servers
|
30
|
+
require_ansible_repo: true
|
31
|
+
ansible_verbose: true
|
32
|
+
ansible_version: 1.6.2-1.el6
|
33
|
+
extra_vars:
|
34
|
+
a: b
|
35
|
+
|
36
|
+
platforms:
|
37
|
+
- name: nocm_centos-6.5
|
38
|
+
driver_plugin: vagrant
|
39
|
+
driver_config:
|
40
|
+
box: nocm_centos-6.5
|
41
|
+
box_url: http://puppet-vagrant-boxes.puppetlabs.com/centos-65-x64-virtualbox-nocm.box
|
42
|
+
network:
|
43
|
+
- ['forwarded_port', {guest: 8080, host: 8080}]
|
44
|
+
- [ 'private_network', { ip: '192.168.33.11' } ]
|
45
|
+
```
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
$:.unshift File.expand_path('../lib', __FILE__)
|
4
|
+
require 'kitchen-ansible/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "kitchen-ansible"
|
8
|
+
s.version = Kitchen::Ansible::VERSION
|
9
|
+
s.authors = ["Neill Turner"]
|
10
|
+
s.email = ["neillwturner@gmail.com"]
|
11
|
+
s.homepage = "https://github.com/neillturner/kitchen-ansible"
|
12
|
+
s.summary = "ansible provisioner for test-kitchen"
|
13
|
+
candidates = Dir.glob("{lib}/**/*") + ['README.md', 'provisioner_options.md', 'kitchen-ansible.gemspec']
|
14
|
+
s.files = candidates.sort
|
15
|
+
s.platform = Gem::Platform::RUBY
|
16
|
+
s.require_paths = ['lib']
|
17
|
+
s.rubyforge_project = '[none]'
|
18
|
+
s.description = <<-EOF
|
19
|
+
== DESCRIPTION:
|
20
|
+
|
21
|
+
Ansible Provisioner for Test Kitchen
|
22
|
+
|
23
|
+
== FEATURES:
|
24
|
+
|
25
|
+
Supports running ansible-playbook
|
26
|
+
|
27
|
+
EOF
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>) Neill Turner (<neillwturner@gmail.com>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2013, Fletcher Nichol, Neill Turner
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
require 'kitchen/errors'
|
20
|
+
require 'kitchen/logging'
|
21
|
+
|
22
|
+
module Kitchen
|
23
|
+
|
24
|
+
module Provisioner
|
25
|
+
|
26
|
+
module Ansible
|
27
|
+
|
28
|
+
# Ansible module resolver that uses Librarian-Ansible and a Ansiblefile to
|
29
|
+
# calculate # dependencies.
|
30
|
+
#
|
31
|
+
class Librarian
|
32
|
+
|
33
|
+
include Logging
|
34
|
+
|
35
|
+
|
36
|
+
def initialize(ansiblefile, path, logger = Kitchen.logger)
|
37
|
+
@ansiblefile = ansiblefile
|
38
|
+
@path = path
|
39
|
+
@logger = logger
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.load!(logger = Kitchen.logger)
|
43
|
+
load_librarian!(logger)
|
44
|
+
end
|
45
|
+
|
46
|
+
def resolve
|
47
|
+
version = ::Librarian::Ansible::VERSION
|
48
|
+
info("Resolving module dependencies with Librarian-Ansible #{version}...")
|
49
|
+
debug("Using Ansiblefile from #{ansiblefile}")
|
50
|
+
|
51
|
+
env = ::Librarian::Ansible::Environment.new(
|
52
|
+
:project_path => File.dirname(ansiblefile))
|
53
|
+
env.config_db.local["path"] = path
|
54
|
+
::Librarian::Action::Resolve.new(env).run
|
55
|
+
::Librarian::Action::Install.new(env).run
|
56
|
+
end
|
57
|
+
|
58
|
+
attr_reader :ansiblefile, :path, :logger
|
59
|
+
|
60
|
+
def self.load_librarian!(logger)
|
61
|
+
first_load = require 'librarian/ansible'
|
62
|
+
require 'librarian/ansible/environment'
|
63
|
+
require 'librarian/action/resolve'
|
64
|
+
require 'librarian/action/install'
|
65
|
+
|
66
|
+
version = ::Librarian::Ansible::VERSION
|
67
|
+
if first_load
|
68
|
+
logger.debug("Librarian-Ansible #{version} library loaded")
|
69
|
+
else
|
70
|
+
logger.debug("Librarian-Ansible #{version} previously loaded")
|
71
|
+
end
|
72
|
+
rescue LoadError => e
|
73
|
+
logger.fatal("The `librarian-ansible' gem is missing and must be installed" +
|
74
|
+
" or cannot be properly activated. Run" +
|
75
|
+
" `gem install librarian-ansible` or add the following to your" +
|
76
|
+
" Gemfile if you are using Bundler: `gem 'librarian-ansible'`.")
|
77
|
+
raise UserError,
|
78
|
+
"Could not load or activate Librarian-Ansible (#{e.message})"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,436 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Neill Turner (<neillwturner@gmail.com>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2013,2014 Neill Turner
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
#
|
19
|
+
# See https://github.com/neillturner/kitchen-ansible/blob/master/provisioner_options.md
|
20
|
+
# for documentation configuration parameters with ansible_playbook provisioner.
|
21
|
+
#
|
22
|
+
|
23
|
+
require 'json'
|
24
|
+
require 'kitchen/provisioner/base'
|
25
|
+
require 'kitchen/provisioner/ansible/librarian'
|
26
|
+
|
27
|
+
module Kitchen
|
28
|
+
|
29
|
+
class Busser
|
30
|
+
|
31
|
+
def non_suite_dirs
|
32
|
+
%w{data}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
module Provisioner
|
37
|
+
#
|
38
|
+
# Ansible Playbook provisioner.
|
39
|
+
#
|
40
|
+
class AnsiblePlaybook < Base
|
41
|
+
attr_accessor :tmp_dir
|
42
|
+
|
43
|
+
default_config :require_ansible_omnibus, false
|
44
|
+
default_config :ansible_omnibus_url, nil
|
45
|
+
default_config :ansible_omnibus_remote_path, '/opt/ansible'
|
46
|
+
default_config :ansible_version, nil
|
47
|
+
default_config :require_ansible_repo, true
|
48
|
+
default_config :extra_vars, {}
|
49
|
+
default_config :ansible_apt_repo, "ppa:rquillo/ansible"
|
50
|
+
default_config :ansible_yum_repo, "https://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm"
|
51
|
+
default_config :chef_bootstrap_url, "https://www.getchef.com/chef/install.sh"
|
52
|
+
|
53
|
+
default_config :playbook, 'site.yml'
|
54
|
+
|
55
|
+
default_config :roles_path do |provisioner|
|
56
|
+
provisioner.calculate_path('roles') or
|
57
|
+
raise 'No roles_path detected. Please specify one in .kitchen.yml'
|
58
|
+
end
|
59
|
+
|
60
|
+
default_config :group_vars_path do |provisioner|
|
61
|
+
provisioner.calculate_path('group_vars', :directory)
|
62
|
+
end
|
63
|
+
|
64
|
+
default_config :host_vars_path do |provisioner|
|
65
|
+
provisioner.calculate_path('host_vars', :directory)
|
66
|
+
end
|
67
|
+
|
68
|
+
default_config :modules_path do |provisioner|
|
69
|
+
provisioner.calculate_path('modules', :directory)
|
70
|
+
end
|
71
|
+
|
72
|
+
default_config :ansiblefile_path do |provisioner|
|
73
|
+
provisioner.calculate_path('Ansiblefile', :file)
|
74
|
+
end
|
75
|
+
|
76
|
+
default_config :ansible_verbose, false
|
77
|
+
default_config :ansible_noop, false # what is ansible equivalent of dry_run????
|
78
|
+
default_config :ansible_platform, ''
|
79
|
+
default_config :update_package_repos, true
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
# def calculate_path(path, type = :directory)
|
84
|
+
# base = config[:test_base_path]
|
85
|
+
# candidates = []
|
86
|
+
# candidates << File.join(base, instance.suite.name, 'ansible', path)
|
87
|
+
# candidates << File.join(base, instance.suite.name, path)
|
88
|
+
# candidates << File.join(base, path)
|
89
|
+
# candidates << File.join(Dir.pwd, path)
|
90
|
+
#
|
91
|
+
# candidates.find do |c|
|
92
|
+
# type == :directory ? File.directory?(c) : File.file?(c)
|
93
|
+
# end
|
94
|
+
# end
|
95
|
+
|
96
|
+
def install_command
|
97
|
+
return unless config[:require_ansible_omnibus] or config[:require_ansible_repo]
|
98
|
+
if config[:require_ansible_omnibus]
|
99
|
+
info("Installing ansible using ansible omnibus")
|
100
|
+
version = if !config[:ansible_version].nil?
|
101
|
+
"-v #{config[:ansible_version]}"
|
102
|
+
else
|
103
|
+
""
|
104
|
+
end
|
105
|
+
<<-INSTALL
|
106
|
+
#{Util.shell_helpers}
|
107
|
+
|
108
|
+
if [ ! -d "#{config[:ansible_omnibus_remote_path]}" ]; then
|
109
|
+
echo "-----> Installing Ansible Omnibus"
|
110
|
+
do_download #{config[:ansible_omnibus_url]} /tmp/ansible_install.sh
|
111
|
+
#{sudo('sh')} /tmp/ansible_install.sh #{version}
|
112
|
+
fi
|
113
|
+
#{install_busser}
|
114
|
+
INSTALL
|
115
|
+
else
|
116
|
+
case ansible_platform
|
117
|
+
when "debian", "ubuntu"
|
118
|
+
info("Installing ansible on #{ansible_platform}")
|
119
|
+
<<-INSTALL
|
120
|
+
if [ ! $(which ansible) ]; then
|
121
|
+
# #{sudo('wget')} #{ansible_apt_repo}
|
122
|
+
# #{sudo('dpkg')} -i #{ansible_apt_repo_file}
|
123
|
+
# #{update_packages_debian_cmd}
|
124
|
+
# #{sudo('apt-get')} -y install ansible#{ansible_debian_version}
|
125
|
+
#{sudo('add-apt-repository')} #{ansible_apt_repo}
|
126
|
+
#{sudo('apt-get')} update
|
127
|
+
#{sudo('apt-get')} -y install ansible
|
128
|
+
|
129
|
+
fi
|
130
|
+
#{install_busser}
|
131
|
+
INSTALL
|
132
|
+
when "redhat", "centos", "fedora"
|
133
|
+
info("Installing ansible on #{ansible_platform}")
|
134
|
+
<<-INSTALL
|
135
|
+
if [ ! $(which ansible) ]; then
|
136
|
+
#{sudo('rpm')} -ivh #{ansible_yum_repo}
|
137
|
+
#{update_packages_redhat_cmd}
|
138
|
+
#{sudo('yum')} -y install ansible#{ansible_redhat_version}
|
139
|
+
fi
|
140
|
+
#{install_busser}
|
141
|
+
INSTALL
|
142
|
+
else
|
143
|
+
info("Installing ansible, will try to determine platform os")
|
144
|
+
<<-INSTALL
|
145
|
+
if [ ! $(which ansible) ]; then
|
146
|
+
if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
|
147
|
+
#{sudo('rpm')} -ivh #{ansible_yum_repo}
|
148
|
+
#{update_packages_redhat_cmd}
|
149
|
+
#{sudo('yum')} -y install ansible#{ansible_redhat_version}
|
150
|
+
else
|
151
|
+
# #{sudo('wget')} #{ansible_apt_repo}
|
152
|
+
# #{sudo('dpkg')} -i #{ansible_apt_repo_file}
|
153
|
+
# #{update_packages_debian_cmd}
|
154
|
+
# #{sudo('apt-get')} -y install ansible#{ansible_debian_version}
|
155
|
+
#{sudo('add-apt-repository')} #{ansible_apt_repo}
|
156
|
+
#{sudo('apt-get')} update
|
157
|
+
#{sudo('apt-get')} -y install ansible#{ansible_debian_version}
|
158
|
+
fi
|
159
|
+
fi
|
160
|
+
#{install_busser}
|
161
|
+
INSTALL
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def install_busser
|
167
|
+
<<-INSTALL
|
168
|
+
#{Util.shell_helpers}
|
169
|
+
# install chef omnibus so that busser works as this is needed to run tests :(
|
170
|
+
# TODO: work out how to install enough ruby
|
171
|
+
# and set busser: { :ruby_bindir => '/usr/bin/ruby' } so that we dont need the
|
172
|
+
# whole chef client
|
173
|
+
if [ ! -d "/opt/chef" ]
|
174
|
+
then
|
175
|
+
echo "-----> Installing Chef Omnibus to install busser to run tests"
|
176
|
+
do_download #{chef_url} /tmp/install.sh
|
177
|
+
#{sudo('sh')} /tmp/install.sh
|
178
|
+
fi
|
179
|
+
INSTALL
|
180
|
+
end
|
181
|
+
|
182
|
+
def init_command
|
183
|
+
dirs = %w{modules roles group_vars host_vars}.
|
184
|
+
map { |dir| File.join(config[:root_path], dir) }.join(" ")
|
185
|
+
cmd = "#{sudo('rm')} -rf #{dirs};"
|
186
|
+
cmd = cmd+" mkdir -p #{config[:root_path]}"
|
187
|
+
debug(cmd)
|
188
|
+
cmd
|
189
|
+
end
|
190
|
+
|
191
|
+
def create_sandbox
|
192
|
+
super
|
193
|
+
debug("Creating local sandbox in #{sandbox_path}")
|
194
|
+
|
195
|
+
yield if block_given?
|
196
|
+
|
197
|
+
prepare_playbook
|
198
|
+
prepare_modules
|
199
|
+
prepare_roles
|
200
|
+
prepare_ansible_cfg
|
201
|
+
prepare_group_vars
|
202
|
+
prepare_host_vars
|
203
|
+
prepare_hosts
|
204
|
+
info('Finished Preparing files for transfer')
|
205
|
+
|
206
|
+
end
|
207
|
+
|
208
|
+
def cleanup_sandbox
|
209
|
+
return if sandbox_path.nil?
|
210
|
+
debug("Cleaning up local sandbox in #{sandbox_path}")
|
211
|
+
FileUtils.rmtree(sandbox_path)
|
212
|
+
end
|
213
|
+
|
214
|
+
def prepare_command
|
215
|
+
commands = []
|
216
|
+
|
217
|
+
commands << [
|
218
|
+
sudo('cp'),File.join(config[:root_path], 'ansible.cfg'),'/etc/ansible',
|
219
|
+
].join(' ')
|
220
|
+
|
221
|
+
commands << [
|
222
|
+
sudo('cp -r'), File.join(config[:root_path],'group_vars'), '/etc/ansible/.',
|
223
|
+
].join(' ')
|
224
|
+
|
225
|
+
commands << [
|
226
|
+
sudo('cp -r'), File.join(config[:root_path],'host_vars'), '/etc/ansible/.',
|
227
|
+
].join(' ')
|
228
|
+
|
229
|
+
command = commands.join(' && ')
|
230
|
+
debug(command)
|
231
|
+
command
|
232
|
+
end
|
233
|
+
|
234
|
+
def run_command
|
235
|
+
[
|
236
|
+
sudo("ansible-playbook"),
|
237
|
+
"-i #{File.join(config[:root_path], 'hosts')}",
|
238
|
+
"-M #{File.join(config[:root_path], 'modules')}",
|
239
|
+
ansible_verbose_flag,
|
240
|
+
extra_vars,
|
241
|
+
"#{File.join(config[:root_path], config[:playbook])}",
|
242
|
+
].join(" ")
|
243
|
+
end
|
244
|
+
|
245
|
+
protected
|
246
|
+
|
247
|
+
def load_needed_dependencies!
|
248
|
+
if File.exists?(ansiblefile)
|
249
|
+
debug("Ansiblefile found at #{ansiblefile}, loading Librarian-Ansible")
|
250
|
+
Ansible::Librarian.load!(logger)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
def tmpmodules_dir
|
255
|
+
File.join(sandbox_path, 'modules')
|
256
|
+
end
|
257
|
+
|
258
|
+
def ansiblefile
|
259
|
+
config[:ansiblefile_path] or ''
|
260
|
+
end
|
261
|
+
|
262
|
+
def playbook
|
263
|
+
config[:playbook]
|
264
|
+
end
|
265
|
+
|
266
|
+
def hosts
|
267
|
+
config[:hosts]
|
268
|
+
end
|
269
|
+
|
270
|
+
def roles
|
271
|
+
config[:roles_path]
|
272
|
+
end
|
273
|
+
|
274
|
+
def modules
|
275
|
+
config[:modules_path]
|
276
|
+
end
|
277
|
+
|
278
|
+
def group_vars
|
279
|
+
config[:group_vars_path].to_s
|
280
|
+
end
|
281
|
+
|
282
|
+
def host_vars
|
283
|
+
config[:host_vars_path].to_s
|
284
|
+
end
|
285
|
+
|
286
|
+
def ansible_debian_version
|
287
|
+
config[:ansible_version] ? "=#{config[:ansible_version]}" : nil
|
288
|
+
end
|
289
|
+
|
290
|
+
def ansible_redhat_version
|
291
|
+
config[:ansible_version] ? "-#{config[:ansible_version]}" : nil
|
292
|
+
end
|
293
|
+
|
294
|
+
def ansible_verbose_flag
|
295
|
+
config[:ansible_verbose] ? '-v' : nil
|
296
|
+
end
|
297
|
+
|
298
|
+
def ansible_platform
|
299
|
+
config[:ansible_platform].to_s.downcase
|
300
|
+
end
|
301
|
+
|
302
|
+
def update_packages_debian_cmd
|
303
|
+
config[:update_package_repos] ? "#{sudo('apt-get')} update" : nil
|
304
|
+
end
|
305
|
+
|
306
|
+
def update_packages_redhat_cmd
|
307
|
+
config[:update_package_repos] ? "#{sudo('yum')} makecache" : nil
|
308
|
+
end
|
309
|
+
|
310
|
+
def extra_vars
|
311
|
+
return nil if config[:extra_vars].none?
|
312
|
+
bash_vars = config[:extra_vars].map { |k,v| "#{k}=#{v}" }.join(" ")
|
313
|
+
bash_vars = "-e \"#{bash_vars}\""
|
314
|
+
debug(bash_vars)
|
315
|
+
bash_vars
|
316
|
+
end
|
317
|
+
|
318
|
+
def ansible_apt_repo
|
319
|
+
config[:ansible_apt_repo]
|
320
|
+
end
|
321
|
+
|
322
|
+
def ansible_apt_repo_file
|
323
|
+
config[:ansible_apt_repo].split('/').last
|
324
|
+
end
|
325
|
+
|
326
|
+
def ansible_yum_repo
|
327
|
+
config[:ansible_yum_repo]
|
328
|
+
end
|
329
|
+
|
330
|
+
def chef_url
|
331
|
+
config[:chef_bootstrap_url]
|
332
|
+
end
|
333
|
+
|
334
|
+
def prepare_roles
|
335
|
+
info('Preparing roles')
|
336
|
+
debug("Using roles from #{roles}")
|
337
|
+
|
338
|
+
tmp_roles_dir = File.join(sandbox_path, 'roles')
|
339
|
+
FileUtils.mkdir_p(tmp_roles_dir)
|
340
|
+
FileUtils.cp_r(Dir.glob("#{roles}/*"), tmp_roles_dir)
|
341
|
+
end
|
342
|
+
|
343
|
+
# /etc/ansible/ansible.cfg should contain
|
344
|
+
# roles_path = /tmp/kitchen/roles
|
345
|
+
def prepare_ansible_cfg
|
346
|
+
info('Preparing ansible.cfg file')
|
347
|
+
ansible_config_file = "#{File.join(sandbox_path, 'ansible.cfg')}"
|
348
|
+
if config[:roles_path].nil?
|
349
|
+
info('No roles has been set. empty ansible.cfg generated')
|
350
|
+
File.open(ansible_config_file, "wb") do |file|
|
351
|
+
file.write("#no roles path specified\n")
|
352
|
+
end
|
353
|
+
else
|
354
|
+
debug("Using role from #{roles}")
|
355
|
+
File.open( ansible_config_file, "wb") do |file|
|
356
|
+
file.write("[defaults]\nroles_path = #{File.join(config[:root_path], roles)}\n")
|
357
|
+
end
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
|
362
|
+
# localhost ansible_connection=local
|
363
|
+
# [example_servers]
|
364
|
+
# localhost
|
365
|
+
def prepare_hosts
|
366
|
+
info('Preparing hosts file')
|
367
|
+
|
368
|
+
if config[:hosts].nil?
|
369
|
+
raise 'No hosts has been set. Please specify one in .kitchen.yml'
|
370
|
+
else
|
371
|
+
debug("Using host from #{hosts}")
|
372
|
+
File.open(File.join(sandbox_path, "hosts"), "wb") do |file|
|
373
|
+
file.write("localhost ansible_connection=local\n[#{hosts}]\nlocalhost\n")
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
def prepare_playbook
|
379
|
+
info('Preparing playbook')
|
380
|
+
debug("Using playbook from #{playbook}")
|
381
|
+
FileUtils.cp_r(playbook, File.join(sandbox_path, playbook))
|
382
|
+
end
|
383
|
+
|
384
|
+
|
385
|
+
def prepare_group_vars
|
386
|
+
info('Preparing group_vars')
|
387
|
+
tmp_group_vars_dir = File.join(sandbox_path, 'group_vars')
|
388
|
+
FileUtils.mkdir_p(tmp_group_vars_dir)
|
389
|
+
|
390
|
+
unless File.directory?(group_vars)
|
391
|
+
info 'nothing to do for group_vars'
|
392
|
+
return
|
393
|
+
end
|
394
|
+
|
395
|
+
debug("Using group_vars from #{group_vars}")
|
396
|
+
FileUtils.cp_r(Dir.glob("#{group_vars}/*"), tmp_group_vars_dir)
|
397
|
+
end
|
398
|
+
|
399
|
+
def prepare_host_vars
|
400
|
+
info('Preparing host_vars')
|
401
|
+
tmp_host_vars_dir = File.join(sandbox_path, 'host_vars')
|
402
|
+
FileUtils.mkdir_p(tmp_host_vars_dir)
|
403
|
+
|
404
|
+
unless File.directory?(host_vars)
|
405
|
+
info 'nothing to do for host_vars'
|
406
|
+
return
|
407
|
+
end
|
408
|
+
|
409
|
+
debug("Using host_vars from #{host_vars}")
|
410
|
+
FileUtils.cp_r(Dir.glob("#{host_vars}/*"), tmp_host_vars_dir)
|
411
|
+
end
|
412
|
+
|
413
|
+
def prepare_modules
|
414
|
+
info('Preparing modules')
|
415
|
+
|
416
|
+
FileUtils.mkdir_p(tmpmodules_dir)
|
417
|
+
|
418
|
+
if modules && File.directory?(modules)
|
419
|
+
debug("Using modules from #{modules}")
|
420
|
+
FileUtils.cp_r(Dir.glob("#{modules}/*"), tmpmodules_dir, remove_destination: true)
|
421
|
+
else
|
422
|
+
info 'nothing to do for modules'
|
423
|
+
end
|
424
|
+
|
425
|
+
resolve_with_librarian if File.exists?(ansiblefile)
|
426
|
+
|
427
|
+
end
|
428
|
+
|
429
|
+
def resolve_with_librarian
|
430
|
+
Kitchen.mutex.synchronize do
|
431
|
+
Ansible::Librarian.new(ansiblefile, tmpmodules_dir, logger).resolve
|
432
|
+
end
|
433
|
+
end
|
434
|
+
end
|
435
|
+
end
|
436
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Neill Turner (<neillwturner@gmail.com>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2013,2014 Neill Turner
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
require_relative '../../spec_helper'
|
20
|
+
require 'kitchen'
|
21
|
+
|
22
|
+
# Work around for lazy loading
|
23
|
+
require 'kitchen/provisioner/ansible_playbook'
|
24
|
+
|
25
|
+
describe Kitchen::Provisioner::AnsiblePlaybook do
|
26
|
+
let(:provisioner) do
|
27
|
+
Kitchen::Provisioner.for_plugin("ansible_playbook", {})
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should give a sane run_command" do
|
31
|
+
provisioner.run_command.must_match /ansible-playbook/
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
|
2
|
+
# Provisioner Options
|
3
|
+
|
4
|
+
key | default value | Notes
|
5
|
+
----|---------------|--------
|
6
|
+
ansible_version | "latest"| desired version, affects apt installs
|
7
|
+
ansible_platform | naively tries to determine | OS platform of server
|
8
|
+
require_ansible_repo | true | Set if using a ansible install from yum or apt repo
|
9
|
+
ansible_apt_repo | "ppa:rquillo/ansible"| apt repo
|
10
|
+
ansible_yum_repo | "https://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm"| yum repo
|
11
|
+
require_ansible_omnibus | false | Set if using omnibus ansible install
|
12
|
+
ansible_omnibus_url | | omnibus ansible install location.
|
13
|
+
ansible_omnibus_remote_path | "/opt/ansible" | Server Installation location of an omnibus ansible install.
|
14
|
+
roles_path | roles | ansible repo roles directory
|
15
|
+
group_vars_path | group_vars | ansible repo group_vars directory
|
16
|
+
host_vars_path | host_vars | ansible repo hosts directory
|
17
|
+
extra_vars | Hash.new | Hash to set the extra_vars passed to ansibile-playbook command
|
18
|
+
playbook | 'site.yml' | playbook for ansible-playbook to run
|
19
|
+
modules_path | | ansible repo manifests directory
|
20
|
+
ansible_verbose| false| Extra information logging
|
21
|
+
update_package_repos| true| update OS repository metadata
|
22
|
+
chef_bootstrap_url |"https://www.getchef.com/chef/install.sh"| the chef (needed for busser to run tests)
|
23
|
+
ansiblefile_path | | Path to Aansiblefile
|
24
|
+
|
25
|
+
## Configuring Provisioner Options
|
26
|
+
|
27
|
+
The provisioner can be configured globally or per suite, global settings act as defaults for all suites, you can then customise per suite, for example:
|
28
|
+
|
29
|
+
---
|
30
|
+
driver:
|
31
|
+
name: vagrant
|
32
|
+
|
33
|
+
provisioner:
|
34
|
+
name: ansible_playbook
|
35
|
+
roles_path: roles
|
36
|
+
hosts: tomcat-servers
|
37
|
+
require_ansible_repo: true
|
38
|
+
ansible_verbose: true
|
39
|
+
|
40
|
+
platforms:
|
41
|
+
- name: nocm_ubuntu-12.04
|
42
|
+
driver_plugin: vagrant
|
43
|
+
driver_config:
|
44
|
+
box: nocm_ubuntu-12.04
|
45
|
+
box_url: http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box
|
46
|
+
|
47
|
+
suites:
|
48
|
+
- name: default
|
49
|
+
|
50
|
+
|
51
|
+
in this example, vagrant will download a box for ubuntu 1204 with no configuration management installed, then install the latest ansible and ansible playbook against a ansible repo from the /repository/ansible_repo directory using the defailt manifest site.yml
|
52
|
+
|
53
|
+
To override a setting at the suite-level, specify the setting name under the suite:
|
54
|
+
|
55
|
+
suites:
|
56
|
+
- name: default
|
57
|
+
playbook: foobar.yml
|
58
|
+
|
59
|
+
### Per-suite Structure
|
60
|
+
|
61
|
+
It can be beneficial to keep different Aansible layouts for different suites. Rather than having to specify the roles, modules, etc for each suite, you can create the following directory structure and they will automatically be found:
|
62
|
+
|
63
|
+
$kitchen_root/ansible/$suite_name/roles
|
64
|
+
$kitchen_root/ansible/$suite_name/modules
|
65
|
+
$kitchen_root/ansible/$suite_name/Ansiblefile
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kitchen-ansible
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Neill Turner
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-07-01 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: ! '== DESCRIPTION:
|
14
|
+
|
15
|
+
|
16
|
+
Ansible Provisioner for Test Kitchen
|
17
|
+
|
18
|
+
|
19
|
+
== FEATURES:
|
20
|
+
|
21
|
+
|
22
|
+
Supports running ansible-playbook
|
23
|
+
|
24
|
+
|
25
|
+
'
|
26
|
+
email:
|
27
|
+
- neillwturner@gmail.com
|
28
|
+
executables: []
|
29
|
+
extensions: []
|
30
|
+
extra_rdoc_files: []
|
31
|
+
files:
|
32
|
+
- README.md
|
33
|
+
- kitchen-ansible.gemspec
|
34
|
+
- lib/kitchen-ansible/version.rb
|
35
|
+
- lib/kitchen/provisioner/ansible/librarian.rb
|
36
|
+
- lib/kitchen/provisioner/ansible_playbook.rb
|
37
|
+
- lib/kitchen/provisioner/ansible_playbook_spec.rb
|
38
|
+
- provisioner_options.md
|
39
|
+
homepage: https://github.com/neillturner/kitchen-ansible
|
40
|
+
licenses: []
|
41
|
+
metadata: {}
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ! '>='
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
requirements: []
|
57
|
+
rubyforge_project: ! '[none]'
|
58
|
+
rubygems_version: 2.3.0
|
59
|
+
signing_key:
|
60
|
+
specification_version: 4
|
61
|
+
summary: ansible provisioner for test-kitchen
|
62
|
+
test_files: []
|