kitchen-policyfile-nodes 1.0.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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.kitchen.yml +26 -0
- data/.rubocop.yml +30 -0
- data/Gemfile +23 -0
- data/README.md +65 -0
- data/Rakefile +41 -0
- data/kitchen-policyfile-nodes.gemspec +28 -0
- data/lib/kitchen/provisioner/policyfile_nodes.rb +214 -0
- data/lib/kitchen/provisioner/policyfile_nodes_version.rb +24 -0
- data/test/integration/cookbooks/test/Policyfile.rb +21 -0
- data/test/integration/cookbooks/test/metadata.rb +1 -0
- data/test/integration/cookbooks/test/recipes/default.rb +17 -0
- data/test/integration/cookbooks/test/recipes/search.rb +26 -0
- data/test/integration/ssh/serverspec/default_spec.rb +46 -0
- metadata +154 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: a9980fc3b5f4d70921989a0c80512b6bc9373949
|
|
4
|
+
data.tar.gz: 3873ce3157a9702e2de33321db498b660f64c58f
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: ab81de9467c8e1688e45f92d0c59f5235c1519090e94050bca99404c7e6d369ebcc6cecee9551dd376d354e2e2f0d079cde8482041752c354683ab51b302cd5d
|
|
7
|
+
data.tar.gz: 3a6bc281e8931ab0832757d1e3851fcd34baaa636c65f56b898657212f9ed72634d816b379148c0c52f9abb281267f4f2b8d692a8c3c59a3768655cb3a4b5e86
|
data/.gitignore
ADDED
data/.kitchen.yml
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
driver:
|
|
3
|
+
name: vagrant
|
|
4
|
+
|
|
5
|
+
provisioner:
|
|
6
|
+
name: policyfile_nodes
|
|
7
|
+
nodes_path: test/integration/nodes
|
|
8
|
+
policyfile: test/integration/cookbooks/test/Policyfile.rb
|
|
9
|
+
|
|
10
|
+
platforms:
|
|
11
|
+
- name: el6
|
|
12
|
+
driver:
|
|
13
|
+
box: bento/centos-6.7
|
|
14
|
+
|
|
15
|
+
suites:
|
|
16
|
+
- name: sftp
|
|
17
|
+
transport:
|
|
18
|
+
name: sftp
|
|
19
|
+
provisioner:
|
|
20
|
+
named_run_list: sftp
|
|
21
|
+
|
|
22
|
+
- name: ssh
|
|
23
|
+
transport:
|
|
24
|
+
name: ssh
|
|
25
|
+
provisioner:
|
|
26
|
+
named_run_list: ssh
|
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
Exclude:
|
|
3
|
+
- vendor/**/*
|
|
4
|
+
|
|
5
|
+
AlignParameters:
|
|
6
|
+
Enabled: false
|
|
7
|
+
ClassLength:
|
|
8
|
+
Enabled: false
|
|
9
|
+
CyclomaticComplexity:
|
|
10
|
+
Enabled: false
|
|
11
|
+
Documentation:
|
|
12
|
+
Enabled: false
|
|
13
|
+
Encoding:
|
|
14
|
+
Enabled: false
|
|
15
|
+
Style/FileName:
|
|
16
|
+
Enabled: false
|
|
17
|
+
LineLength:
|
|
18
|
+
Enabled: false
|
|
19
|
+
MethodLength:
|
|
20
|
+
Enabled: false
|
|
21
|
+
Metrics/AbcSize:
|
|
22
|
+
Enabled: false
|
|
23
|
+
PerceivedComplexity:
|
|
24
|
+
Enabled: false
|
|
25
|
+
Style/SpaceBeforeFirstArg:
|
|
26
|
+
Enabled: false
|
|
27
|
+
Style/ClassAndModuleChildren:
|
|
28
|
+
Enabled: false
|
|
29
|
+
Style/FileName:
|
|
30
|
+
Enabled: false
|
data/Gemfile
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
source 'https://rubygems.org'
|
|
2
|
+
|
|
3
|
+
gemspec
|
|
4
|
+
|
|
5
|
+
group :rake do
|
|
6
|
+
gem 'rake'
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
group :lint do
|
|
10
|
+
gem 'rubocop', '~> 0.37'
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
group :unit do
|
|
14
|
+
gem 'chefspec', '~> 4.5'
|
|
15
|
+
gem 'rspec', '~> 3.0'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
group :kitchen do
|
|
19
|
+
gem 'chef-dk', '~> 0.10'
|
|
20
|
+
gem 'test-kitchen', '~> 1.5'
|
|
21
|
+
gem 'kitchen-sync', '~> 2.0'
|
|
22
|
+
gem 'kitchen-vagrant', '~> 0.19'
|
|
23
|
+
end
|
data/README.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Kitchen::PolicyfileNodes
|
|
2
|
+
|
|
3
|
+
Provisioner `policyfile_nodes` extends `policyfile_zero` by adding one more step in the end of converge - it copies the resulted node
|
|
4
|
+
JSON object to the `nodes_path` on the host machine after successful converge. It allows you to use this node object for searches while converging another
|
|
5
|
+
Test Kitchen suites. So, you can use actual node IP addresses to communicate nodes with each other.
|
|
6
|
+
|
|
7
|
+
For example, 'web' node need to search 'db' node ip.
|
|
8
|
+
In `policyfile_zero` we have to create mock in node_path for this search. `policyfile_nodes` will create mock automatically.
|
|
9
|
+
|
|
10
|
+
`policyfile_nodes` supports SSH and SFTP (kitchen-sync) transporters.
|
|
11
|
+
|
|
12
|
+
## Requirements
|
|
13
|
+
|
|
14
|
+
* ChefDK 0.10.0+
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
gem install kitchen-policyfile-nodes
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Configuration
|
|
23
|
+
|
|
24
|
+
Use `policyfile_nodes` instead of `policyfile_zero` for the kitchen provisioner name.
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
provisioner:
|
|
28
|
+
name: policyfile_nodes
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Development
|
|
32
|
+
|
|
33
|
+
* Source hosted at [GitHub](https://github.com/Parallels/kitchen-policyfile-nodes)
|
|
34
|
+
* Report issues/questions/feature requests on [GitHub Issues](https://github.com/Parallels/kitchen-policyfile-nodes/issues)
|
|
35
|
+
|
|
36
|
+
Pull requests are very welcome! Make sure your patches are well tested.
|
|
37
|
+
Ideally create a topic branch for every separate change you make. For
|
|
38
|
+
example:
|
|
39
|
+
|
|
40
|
+
1. Fork the repo
|
|
41
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
42
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
|
43
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
44
|
+
5. Create new Pull Request
|
|
45
|
+
|
|
46
|
+
## Testing
|
|
47
|
+
|
|
48
|
+
1. Run `bundle install`
|
|
49
|
+
2. Run `rake` for unit testing
|
|
50
|
+
|
|
51
|
+
## Authors
|
|
52
|
+
|
|
53
|
+
Created and maintained by [Andrei Skopenko][author] (<andrei@skopenko.net>)
|
|
54
|
+
|
|
55
|
+
## License
|
|
56
|
+
|
|
57
|
+
Apache 2.0 (see [LICENSE][license])
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
[author]: https://github.com/scopenco
|
|
61
|
+
[issues]: https://github.com/Parallels/kitchen-policyfile-nodes/issues
|
|
62
|
+
[license]: https://github.com/Parallels/kitchen-policyfile-nodes/blob/master/LICENSE
|
|
63
|
+
[repo]: https://github.com/Parallels/kitchen-policyfile-nodes
|
|
64
|
+
[driver_usage]: http://docs.kitchen-ci.org/drivers/usage
|
|
65
|
+
[chef_omnibus_dl]: http://www.getchef.com/chef/install/
|
data/Rakefile
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env rake
|
|
2
|
+
|
|
3
|
+
require 'bundler/gem_tasks'
|
|
4
|
+
require 'rspec/core/rake_task'
|
|
5
|
+
require 'rubocop/rake_task'
|
|
6
|
+
require 'kitchen'
|
|
7
|
+
require 'chef-dk/cli'
|
|
8
|
+
|
|
9
|
+
# Rubocop
|
|
10
|
+
desc 'Run Ruby style checks'
|
|
11
|
+
RuboCop::RakeTask.new(:rubocop)
|
|
12
|
+
|
|
13
|
+
# Rspec
|
|
14
|
+
desc 'Run ChefSpec examples'
|
|
15
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
16
|
+
|
|
17
|
+
# Integration tests. Kitchen.ci
|
|
18
|
+
namespace :integration do
|
|
19
|
+
desc 'Run Test Kitchen with Vagrant'
|
|
20
|
+
task :vagrant do
|
|
21
|
+
Kitchen.logger = Kitchen.default_file_logger
|
|
22
|
+
Kitchen::Config.new.instances.each do |instance|
|
|
23
|
+
instance.test(:verify)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
namespace :policyfile do
|
|
29
|
+
desc 'Run "chef update" for Policyfile.rb'
|
|
30
|
+
task :update do
|
|
31
|
+
Dir.glob('test/integration/cookbooks/test/Policyfile.rb').each do |file|
|
|
32
|
+
cli = ChefDK::CLI.new(['update', file])
|
|
33
|
+
subcommand_name, *subcommand_params = cli.argv
|
|
34
|
+
subcommand = cli.instantiate_subcommand(subcommand_name)
|
|
35
|
+
subcommand.run_with_default_options(subcommand_params)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Default
|
|
41
|
+
task default: ['rubocop', 'spec', 'policyfile:update', 'integration:vagrant']
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'kitchen/provisioner/policyfile_nodes_version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = 'kitchen-policyfile-nodes'
|
|
8
|
+
spec.version = Kitchen::Provisioner::POLICYFILE_NODES_VERSION
|
|
9
|
+
spec.authors = ['Andrei Skopenko']
|
|
10
|
+
spec.email = ['andrei@skopenko.net']
|
|
11
|
+
spec.description = 'A Test Kitchen Provisioner for Chef Nodes based in Policyfile.rb'
|
|
12
|
+
spec.summary = spec.description
|
|
13
|
+
spec.homepage = ''
|
|
14
|
+
spec.license = 'Apache 2.0'
|
|
15
|
+
|
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
|
17
|
+
spec.executables = []
|
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
|
+
spec.require_paths = ['lib']
|
|
20
|
+
|
|
21
|
+
spec.add_dependency 'test-kitchen', '~> 1.5'
|
|
22
|
+
spec.add_dependency 'chef-dk', '~> 0.10'
|
|
23
|
+
|
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
|
25
|
+
spec.add_development_dependency 'rake'
|
|
26
|
+
spec.add_development_dependency 'rspec', '~> 3.2'
|
|
27
|
+
spec.add_development_dependency 'rubocop', '~> 0.37', '>= 0.37.1'
|
|
28
|
+
end
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Author:: Andrei Skopenko (<andrei@skopenko.net>)
|
|
4
|
+
#
|
|
5
|
+
# Copyright 2015 Andrei Skopenko
|
|
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/provisioner/policyfile_zero'
|
|
20
|
+
require 'kitchen/provisioner/base'
|
|
21
|
+
require 'kitchen/driver/ssh_base'
|
|
22
|
+
require 'kitchen/transport/ssh'
|
|
23
|
+
|
|
24
|
+
# continue loading if kitchen-sync not installed
|
|
25
|
+
begin
|
|
26
|
+
require 'kitchen/transport/sftp'
|
|
27
|
+
rescue LoadError
|
|
28
|
+
puts 'Ignoring sftp transport...'
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
module Kitchen
|
|
32
|
+
module Driver
|
|
33
|
+
class SSHBase
|
|
34
|
+
# PolicyfileNodes needs to access to legacy_ssh_base_converge method
|
|
35
|
+
# used by some drivers like kithen-vz. This method
|
|
36
|
+
# add additional command after chef_client run complete.
|
|
37
|
+
#
|
|
38
|
+
# @param state [Hash] mutable instance state
|
|
39
|
+
# @raise [ActionFailed] if the action could not be completed
|
|
40
|
+
def converge(state)
|
|
41
|
+
provisioner = instance.provisioner
|
|
42
|
+
provisioner.create_sandbox
|
|
43
|
+
sandbox_dirs = Dir.glob("#{provisioner.sandbox_path}/*")
|
|
44
|
+
instance.transport.connection(backcompat_merged_state(state)) do |conn|
|
|
45
|
+
conn.execute(env_cmd(provisioner.install_command))
|
|
46
|
+
conn.execute(env_cmd(provisioner.init_command))
|
|
47
|
+
info("Transferring files to #{instance.to_str}")
|
|
48
|
+
conn.upload(sandbox_dirs, provisioner[:root_path])
|
|
49
|
+
debug('Transfer complete')
|
|
50
|
+
conn.execute(env_cmd(provisioner.prepare_command))
|
|
51
|
+
conn.execute(env_cmd(provisioner.run_command))
|
|
52
|
+
# Get node json object generated by chef_client
|
|
53
|
+
output = conn.execute_with_output(env_cmd(provisioner.dump_command))
|
|
54
|
+
File.open(provisioner.ext_node_file, 'w') { |f| f << output }
|
|
55
|
+
end
|
|
56
|
+
rescue Kitchen::Transport::TransportFailed => ex
|
|
57
|
+
raise ActionFailed, ex.message
|
|
58
|
+
ensure
|
|
59
|
+
instance.provisioner.cleanup_sandbox
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def int_node_file
|
|
63
|
+
File.join(config[:root_path], 'nodes', "#{instance.name}.json")
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
module Kitchen
|
|
70
|
+
module Transport
|
|
71
|
+
class Sftp
|
|
72
|
+
class Connection
|
|
73
|
+
# Execute a remote command over SFTP and return the command's exit code and output.
|
|
74
|
+
#
|
|
75
|
+
# @param command [String] command string to execute
|
|
76
|
+
# @return [Hash] the exit code and output of the command
|
|
77
|
+
def execute_with_output_and_exit_code(command)
|
|
78
|
+
exit_code = nil
|
|
79
|
+
output = ''
|
|
80
|
+
session.open_channel do |channel|
|
|
81
|
+
channel.request_pty
|
|
82
|
+
|
|
83
|
+
channel.exec(command) do |_ch, _success|
|
|
84
|
+
channel.on_data do |_ch, data|
|
|
85
|
+
output << data
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
channel.on_extended_data do |_ch, _type, data|
|
|
89
|
+
output << data
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
channel.on_request('exit-status') do |_ch, data|
|
|
93
|
+
exit_code = data.read_long
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
session.loop { exit_code.nil? }
|
|
98
|
+
[exit_code, output]
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
class Ssh
|
|
104
|
+
class Connection
|
|
105
|
+
# Execute a remote command over SSH and return the command's exit code and output.
|
|
106
|
+
#
|
|
107
|
+
# @param command [String] command string to execute
|
|
108
|
+
# @return [Hash] the exit code and output of the command
|
|
109
|
+
def execute_with_output_and_exit_code(command)
|
|
110
|
+
exit_code = nil
|
|
111
|
+
output = ''
|
|
112
|
+
session.open_channel do |channel|
|
|
113
|
+
channel.request_pty
|
|
114
|
+
|
|
115
|
+
channel.exec(command) do |_ch, _success|
|
|
116
|
+
channel.on_data do |_ch, data|
|
|
117
|
+
output << data
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
channel.on_extended_data do |_ch, _type, data|
|
|
121
|
+
output << data
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
channel.on_request('exit-status') do |_ch, data|
|
|
125
|
+
exit_code = data.read_long
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
session.loop { exit_code.nil? }
|
|
130
|
+
[exit_code, output]
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Execute command over SSH and return the command's output.
|
|
134
|
+
#
|
|
135
|
+
# @param command [String] command string to execute
|
|
136
|
+
# @return [String] the output of the executed command
|
|
137
|
+
def execute_with_output(command)
|
|
138
|
+
return if command.nil?
|
|
139
|
+
logger.debug("[SSH] #{self} (#{command})")
|
|
140
|
+
exit_code, output = execute_with_output_and_exit_code(command)
|
|
141
|
+
|
|
142
|
+
if exit_code != 0
|
|
143
|
+
raise Transport::SshFailed,
|
|
144
|
+
"SSH exited (#{exit_code}) for command: [#{command}]"
|
|
145
|
+
end
|
|
146
|
+
output
|
|
147
|
+
rescue Net::SSH::Exception => ex
|
|
148
|
+
raise SshFailed, "SSH command failed (#{ex.message})"
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
module Kitchen
|
|
156
|
+
module Provisioner
|
|
157
|
+
class Base
|
|
158
|
+
# PolicyfileNodes needs to access to provision of the instance
|
|
159
|
+
# without invoking the behavior of Base#call because we need to
|
|
160
|
+
# add additional command after chef_client run complete.
|
|
161
|
+
#
|
|
162
|
+
# @param state [Hash] mutable instance state
|
|
163
|
+
# @raise [ActionFailed] if the action could not be completed
|
|
164
|
+
def call(state)
|
|
165
|
+
create_sandbox
|
|
166
|
+
sandbox_dirs = Dir.glob(File.join(sandbox_path, '*'))
|
|
167
|
+
|
|
168
|
+
instance.transport.connection(state) do |conn|
|
|
169
|
+
conn.execute(install_command)
|
|
170
|
+
conn.execute(init_command)
|
|
171
|
+
info("Transferring files to #{instance.to_str}")
|
|
172
|
+
conn.upload(sandbox_dirs, config[:root_path])
|
|
173
|
+
debug('Transfer complete')
|
|
174
|
+
conn.execute(prepare_command)
|
|
175
|
+
conn.execute(run_command)
|
|
176
|
+
# Get node json object generated by chef_client
|
|
177
|
+
output = conn.execute_with_output(dump_command)
|
|
178
|
+
File.open(ext_node_file, 'w') { |f| f << output }
|
|
179
|
+
end
|
|
180
|
+
rescue Kitchen::Transport::TransportFailed => ex
|
|
181
|
+
raise ActionFailed, ex.message
|
|
182
|
+
ensure
|
|
183
|
+
cleanup_sandbox
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
class PolicyfileZero
|
|
188
|
+
# PolicyfileNodes needs to access the base behavior of creating the
|
|
189
|
+
# sandbox directory without invoking the behavior of
|
|
190
|
+
# PolicyfileZero#create_sandbox, we need to override json node.
|
|
191
|
+
alias create_policyfile_sandbox create_sandbox
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
class PolicyfileNodes < PolicyfileZero
|
|
195
|
+
# (see PolicyfileZero#create_sandbox)
|
|
196
|
+
def create_sandbox
|
|
197
|
+
FileUtils.rm(ext_node_file) if File.exist?(ext_node_file)
|
|
198
|
+
create_policyfile_sandbox
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def ext_node_file
|
|
202
|
+
File.join(config[:nodes_path], "#{instance.name}.json")
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def int_node_file
|
|
206
|
+
File.join(config[:root_path], 'nodes', "#{instance.name}.json")
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def dump_command
|
|
210
|
+
"sh -c 'cat #{int_node_file}'"
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Author:: Andrei Skopenko (<andrei@skopenko.net>)
|
|
4
|
+
#
|
|
5
|
+
# Copyright 2015 Andrei Skopenko
|
|
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
|
+
module Kitchen
|
|
20
|
+
# Version string for Policyfile_nodes Kitchen driver
|
|
21
|
+
module Provisioner
|
|
22
|
+
POLICYFILE_NODES_VERSION = '1.0.0'.freeze
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Policyfile_base - Base file to be evaluated by other Policyfiles
|
|
2
|
+
# Don't use it as a standalone Policyfile, it doesn't work.
|
|
3
|
+
#
|
|
4
|
+
# For more information on the Policyfile feature, visit
|
|
5
|
+
# https://github.com/opscode/chef-dk/blob/master/POLICYFILE_README.md
|
|
6
|
+
|
|
7
|
+
# A name that describes what the system you're building with Chef does.
|
|
8
|
+
name 'test'
|
|
9
|
+
|
|
10
|
+
# Where to find external cookbooks:
|
|
11
|
+
default_source :supermarket
|
|
12
|
+
|
|
13
|
+
# Specify a custom source for a single cookbook:
|
|
14
|
+
cookbook 'test', path: './'
|
|
15
|
+
|
|
16
|
+
# run_list: chef-client will run these recipes in the order specified.
|
|
17
|
+
run_list 'test::default'
|
|
18
|
+
|
|
19
|
+
# named_run_lists
|
|
20
|
+
named_run_list 'sftp', 'test::default'
|
|
21
|
+
named_run_list 'ssh', 'test::search'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
name 'test'
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Cookbook Name:: test
|
|
3
|
+
# Resource:: default
|
|
4
|
+
#
|
|
5
|
+
# Copyright 2015 Andrei Skopenko
|
|
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.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Cookbook Name:: test
|
|
3
|
+
# Resource:: search
|
|
4
|
+
#
|
|
5
|
+
# Copyright 2015 Andrei Skopenko
|
|
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
|
+
first_node = search(:node, "name:sftp-* AND platform:#{node['platform']}")
|
|
20
|
+
|
|
21
|
+
ruby_block 'save attributes' do
|
|
22
|
+
block do
|
|
23
|
+
parent = File.join(ENV['TEMP'] || '/tmp', 'kitchen')
|
|
24
|
+
IO.write(File.join(parent, 'sftp.json'), first_node[0].to_json)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require 'serverspec'
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
set :backend, :exec
|
|
5
|
+
|
|
6
|
+
describe 'sftp node' do
|
|
7
|
+
let(:node) do
|
|
8
|
+
JSON.parse(
|
|
9
|
+
IO.read(File.join(ENV['TEMP'] || '/tmp', 'kitchen/sftp.json'))
|
|
10
|
+
)
|
|
11
|
+
end
|
|
12
|
+
let(:ip) { node['automatic']['ipaddress'] }
|
|
13
|
+
let(:fqdn) { node['automatic']['fqdn'] }
|
|
14
|
+
let(:connection) do
|
|
15
|
+
Net::SSH.start(
|
|
16
|
+
ip,
|
|
17
|
+
'vagrant',
|
|
18
|
+
password: 'vagrant',
|
|
19
|
+
paranoid: false
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'has an non localhost ip' do
|
|
24
|
+
expect(ip).not_to eq('127.0.0.1')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'has a valid ip' do
|
|
28
|
+
expect(ip).to match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe command('hostname') do
|
|
32
|
+
its(:stdout) { should_not match(/#{Regexp.quote(fqdn)}/) }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'has a computername matching node fqdn' do
|
|
36
|
+
connection.open_channel do |channel|
|
|
37
|
+
channel.request_pty
|
|
38
|
+
channel.exec('hostname') do |_ch, _success|
|
|
39
|
+
channel.on_data do |_ch, data|
|
|
40
|
+
expect(data.chomp).to eq(fqdn)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
connection.loop
|
|
45
|
+
end
|
|
46
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: kitchen-policyfile-nodes
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Andrei Skopenko
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2016-03-14 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: test-kitchen
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.5'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.5'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: chef-dk
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0.10'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0.10'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: bundler
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '1.3'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '1.3'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rake
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: rspec
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '3.2'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '3.2'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: rubocop
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0.37'
|
|
90
|
+
- - ">="
|
|
91
|
+
- !ruby/object:Gem::Version
|
|
92
|
+
version: 0.37.1
|
|
93
|
+
type: :development
|
|
94
|
+
prerelease: false
|
|
95
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
96
|
+
requirements:
|
|
97
|
+
- - "~>"
|
|
98
|
+
- !ruby/object:Gem::Version
|
|
99
|
+
version: '0.37'
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: 0.37.1
|
|
103
|
+
description: A Test Kitchen Provisioner for Chef Nodes based in Policyfile.rb
|
|
104
|
+
email:
|
|
105
|
+
- andrei@skopenko.net
|
|
106
|
+
executables: []
|
|
107
|
+
extensions: []
|
|
108
|
+
extra_rdoc_files: []
|
|
109
|
+
files:
|
|
110
|
+
- ".gitignore"
|
|
111
|
+
- ".kitchen.yml"
|
|
112
|
+
- ".rubocop.yml"
|
|
113
|
+
- Gemfile
|
|
114
|
+
- README.md
|
|
115
|
+
- Rakefile
|
|
116
|
+
- kitchen-policyfile-nodes.gemspec
|
|
117
|
+
- lib/kitchen/provisioner/policyfile_nodes.rb
|
|
118
|
+
- lib/kitchen/provisioner/policyfile_nodes_version.rb
|
|
119
|
+
- test/integration/cookbooks/test/Policyfile.rb
|
|
120
|
+
- test/integration/cookbooks/test/metadata.rb
|
|
121
|
+
- test/integration/cookbooks/test/recipes/default.rb
|
|
122
|
+
- test/integration/cookbooks/test/recipes/search.rb
|
|
123
|
+
- test/integration/ssh/serverspec/default_spec.rb
|
|
124
|
+
homepage: ''
|
|
125
|
+
licenses:
|
|
126
|
+
- Apache 2.0
|
|
127
|
+
metadata: {}
|
|
128
|
+
post_install_message:
|
|
129
|
+
rdoc_options: []
|
|
130
|
+
require_paths:
|
|
131
|
+
- lib
|
|
132
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
133
|
+
requirements:
|
|
134
|
+
- - ">="
|
|
135
|
+
- !ruby/object:Gem::Version
|
|
136
|
+
version: '0'
|
|
137
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
|
+
requirements:
|
|
139
|
+
- - ">="
|
|
140
|
+
- !ruby/object:Gem::Version
|
|
141
|
+
version: '0'
|
|
142
|
+
requirements: []
|
|
143
|
+
rubyforge_project:
|
|
144
|
+
rubygems_version: 2.5.2
|
|
145
|
+
signing_key:
|
|
146
|
+
specification_version: 4
|
|
147
|
+
summary: A Test Kitchen Provisioner for Chef Nodes based in Policyfile.rb
|
|
148
|
+
test_files:
|
|
149
|
+
- test/integration/cookbooks/test/Policyfile.rb
|
|
150
|
+
- test/integration/cookbooks/test/metadata.rb
|
|
151
|
+
- test/integration/cookbooks/test/recipes/default.rb
|
|
152
|
+
- test/integration/cookbooks/test/recipes/search.rb
|
|
153
|
+
- test/integration/ssh/serverspec/default_spec.rb
|
|
154
|
+
has_rdoc:
|