kitchen-nodes 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +35 -3
- data/Rakefile +8 -3
- data/kitchen-nodes.gemspec +6 -5
- data/lib/kitchen/provisioner/ip_finder.rb +3 -1
- data/lib/kitchen/provisioner/ip_finder/ssh.rb +25 -28
- data/lib/kitchen/provisioner/ip_finder/winrm.rb +7 -3
- data/lib/kitchen/provisioner/nodes.rb +36 -27
- data/lib/kitchen/provisioner/nodes_version.rb +2 -4
- data/spec/unit/nodes_spec.rb +102 -109
- data/spec/unit/stubs/ifconfig.txt +26 -0
- data/spec/unit/stubs/ip.txt +9 -0
- metadata +41 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bbd0dda405d103305306b0103fd135441cd4b44e
|
4
|
+
data.tar.gz: c809ab49ba0bbdf3e233809f6d61d88f017a2fcd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a0c9414d16951dd2ff128a42651ddc59e1ce77af273b00bda3520154e55e8edde7d028bef389fab3905b911733ea7a520f2ab31edebe7150f0664e3409a40a6
|
7
|
+
data.tar.gz: 64ef1c91fd2befb4464917bf6950eb206e3bf3b97bce08b8cb017a01a941fece4e315982c0c6d2aa0e17da9a474d84346582391a533cd332485b4e01aa6f79fe
|
data/README.md
CHANGED
@@ -13,6 +13,9 @@ The nodes provisioner extends the `chef-zero` provisioner along with all of its
|
|
13
13
|
"ipaddress": "172.17.0.8",
|
14
14
|
"platform": "ubuntu"
|
15
15
|
},
|
16
|
+
"normal": {
|
17
|
+
"attr1": "val1"
|
18
|
+
}
|
16
19
|
"run_list": [
|
17
20
|
"recipe[apt]",
|
18
21
|
"recipe[couchbase-tests::ipaddress]",
|
@@ -36,9 +39,13 @@ The nodes provisioner extends the `chef-zero` provisioner along with all of its
|
|
36
39
|
}
|
37
40
|
```
|
38
41
|
|
39
|
-
|
42
|
+
The node data includes the node id based on the test-kitchen suite name, the run list assigned to the node, the normal attributes included in the `.kitchen.yml` file, the externally reachable ip address and the platform of the test instance os.
|
40
43
|
|
41
|
-
|
44
|
+
## <a name="installation"></a> Installation
|
45
|
+
|
46
|
+
```
|
47
|
+
gem install kitchen-nodes
|
48
|
+
```
|
42
49
|
|
43
50
|
## <a name="config"></a> Configuration
|
44
51
|
|
@@ -49,7 +56,7 @@ provisioner:
|
|
49
56
|
name: nodes
|
50
57
|
```
|
51
58
|
|
52
|
-
## <a name="
|
59
|
+
## <a name="Usage"></a> Usage
|
53
60
|
|
54
61
|
Using `kitchen-nodes` one can expect all previously converged nodes to be represented in a node file and be searchable. For example consider this scenario looking for a primary node in a cluster in order to add a node to join:
|
55
62
|
|
@@ -77,6 +84,31 @@ primary = search_for_nodes("run_list:*couchbase??server* AND platform:#{node['pl
|
|
77
84
|
node.normal["couchbase-tests"]["primary_ip"] = primary[0]['ipaddress']
|
78
85
|
|
79
86
|
```
|
87
|
+
### <a name="vagrant"></a> Using with Vagrant
|
88
|
+
|
89
|
+
When using kitchen-nodes with the vagrant driver, make sure you add the following to your `driver_config`:
|
90
|
+
|
91
|
+
```
|
92
|
+
network:
|
93
|
+
- ["private_network", { type: "dhcp" }]
|
94
|
+
```
|
95
|
+
|
96
|
+
This will add an additional non-NAT NIC to your vagrant box with an IP reachable from the host and other test nodes.
|
97
|
+
|
98
|
+
### <a name="virtualbox"></a> Why is my ohai `ipaddress` different from my node ipaddress on vagrant with VirtualBox?
|
99
|
+
|
100
|
+
Ohai will pick up the localhost ipaddress on vagrant boxes using virtualbox. To reset the `node["ipaddress"]` to the reachable ip, add `hurry-up-and-test::set_non_nat_vbox_ip` to the top of your `run_list`.
|
101
|
+
|
102
|
+
```
|
103
|
+
suites:
|
104
|
+
- name: my-suite
|
105
|
+
run_list:
|
106
|
+
- recipe[hurry-up-and-test::set_non_nat_vbox_ip]
|
107
|
+
- recipe[cookbook-under-test]
|
108
|
+
```
|
109
|
+
|
110
|
+
You can add this even if you do not use virtualbox and the recipe will do nothing.
|
111
|
+
|
80
112
|
|
81
113
|
## <a name="development"></a> Development
|
82
114
|
|
data/Rakefile
CHANGED
@@ -1,6 +1,11 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'rubocop/rake_task'
|
3
4
|
|
4
5
|
RSpec::Core::RakeTask.new(:test)
|
5
6
|
|
6
|
-
|
7
|
+
RuboCop::RakeTask.new(:style) do |task|
|
8
|
+
task.options << '--display-cop-names'
|
9
|
+
end
|
10
|
+
|
11
|
+
task default: [:test, :style]
|
data/kitchen-nodes.gemspec
CHANGED
@@ -8,22 +8,23 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Kitchen::Provisioner::NODES_VERSION
|
9
9
|
spec.authors = ['Matt Wrock']
|
10
10
|
spec.email = ['matt@mattwrock.com']
|
11
|
-
spec.description =
|
11
|
+
spec.description = 'A Test Kitchen Provisioner for Chef Nodes'
|
12
12
|
spec.summary = spec.description
|
13
13
|
spec.homepage = ''
|
14
14
|
spec.license = 'Apache 2.0'
|
15
15
|
|
16
|
-
spec.files = `git ls-files`.split(
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
17
|
spec.executables = []
|
18
|
-
spec.test_files = spec.files.grep(
|
18
|
+
spec.test_files = spec.files.grep(/^(test|spec|features)\//)
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
21
|
spec.add_dependency 'net-ping'
|
22
22
|
spec.add_dependency 'win32-security'
|
23
|
-
spec.add_dependency 'test-kitchen', '1.4
|
23
|
+
spec.add_dependency 'test-kitchen', '~> 1.4'
|
24
24
|
|
25
25
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
26
|
-
spec.add_development_dependency
|
26
|
+
spec.add_development_dependency 'fakefs', '~> 0.4'
|
27
27
|
spec.add_development_dependency 'rake'
|
28
28
|
spec.add_development_dependency 'rspec', '~> 3.2'
|
29
|
+
spec.add_development_dependency 'rubocop', '~> 0.29'
|
29
30
|
end
|
@@ -1,7 +1,9 @@
|
|
1
1
|
module Kitchen
|
2
2
|
module Provisioner
|
3
|
+
# Locates active IPs that are not localhost
|
4
|
+
# there are separate implementations for
|
5
|
+
# different kitchen transports
|
3
6
|
module IpFinder
|
4
|
-
|
5
7
|
def self.for_transport(transport, state)
|
6
8
|
transport_string = transport.class.name.split('::').last
|
7
9
|
require("kitchen/provisioner/ip_finder/#{transport_string.downcase}")
|
@@ -1,28 +1,29 @@
|
|
1
1
|
module Kitchen
|
2
2
|
module Transport
|
3
3
|
class Ssh < Kitchen::Transport::Base
|
4
|
+
# Monkey patch of test-kitchen ssh transport
|
5
|
+
# that returns stdout
|
4
6
|
class Connection < Kitchen::Transport::Base::Connection
|
5
7
|
def node_execute(command, &block)
|
6
8
|
return if command.nil?
|
7
9
|
out, exit_code = node_execute_with_exit_code(command, &block)
|
8
10
|
|
9
11
|
if exit_code != 0
|
10
|
-
|
11
|
-
|
12
|
+
fail Transport::SshFailed,
|
13
|
+
"SSH exited (#{exit_code}) for command: [#{command}]"
|
12
14
|
end
|
13
15
|
out
|
14
16
|
rescue Net::SSH::Exception => ex
|
15
17
|
raise SshFailed, "SSH command failed (#{ex.message})"
|
16
18
|
end
|
17
19
|
|
18
|
-
|
20
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
21
|
+
def node_execute_with_exit_code(command)
|
19
22
|
exit_code = nil
|
20
23
|
out = []
|
21
24
|
session.open_channel do |channel|
|
22
|
-
|
23
25
|
channel.request_pty
|
24
26
|
channel.exec(command) do |_ch, _success|
|
25
|
-
|
26
27
|
channel.on_data do |_ch, data|
|
27
28
|
out << data
|
28
29
|
yield data if block_given?
|
@@ -33,7 +34,7 @@ module Kitchen
|
|
33
34
|
yield data if block_given?
|
34
35
|
end
|
35
36
|
|
36
|
-
channel.on_request(
|
37
|
+
channel.on_request('exit-status') do |_ch, data|
|
37
38
|
exit_code = data.read_long
|
38
39
|
end
|
39
40
|
end
|
@@ -41,12 +42,14 @@ module Kitchen
|
|
41
42
|
session.loop
|
42
43
|
[out.join("\n"), exit_code]
|
43
44
|
end
|
45
|
+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
44
46
|
end
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
48
50
|
module Provisioner
|
49
51
|
module IpFinder
|
52
|
+
# SSH implementation for returning active non-localhost IPs
|
50
53
|
class Ssh
|
51
54
|
def initialize(connection)
|
52
55
|
@connection = connection
|
@@ -54,48 +57,42 @@ module Kitchen
|
|
54
57
|
|
55
58
|
def find_ips
|
56
59
|
ips = []
|
57
|
-
|
58
|
-
|
59
|
-
while retry_count < 5
|
60
|
+
(0..5).each do
|
60
61
|
begin
|
61
62
|
ips = run_ifconfig
|
62
63
|
rescue Kitchen::Transport::TransportFailed
|
63
64
|
ips = run_ip_addr
|
64
65
|
end
|
65
66
|
return ips unless ips.empty?
|
66
|
-
retry_count += 1
|
67
67
|
sleep 0.5
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
71
|
def run_ifconfig
|
72
|
-
response = @connection.node_execute(
|
72
|
+
response = @connection.node_execute('ifconfig -a')
|
73
73
|
ips = []
|
74
|
-
start_token = "inet addr:"
|
75
74
|
response.split(/^\S+/).each do |device|
|
76
|
-
if device.include?(
|
77
|
-
|
78
|
-
start_idx += start_token.length unless start_idx.nil?
|
79
|
-
end_idx = device.index(" ", start_idx) unless start_idx.nil?
|
80
|
-
ips << device[start_idx,end_idx - start_idx] unless end_idx.nil?
|
81
|
-
end
|
75
|
+
next if !device.include?('RUNNING') || device.include?('LOOPBACK')
|
76
|
+
ips << parse_ip(device, 'inet addr:', ' ')
|
82
77
|
end
|
83
|
-
ips
|
78
|
+
ips.compact
|
84
79
|
end
|
85
80
|
|
86
81
|
def run_ip_addr
|
87
|
-
response = @connection.node_execute(
|
82
|
+
response = @connection.node_execute('ip -4 addr show')
|
88
83
|
ips = []
|
89
|
-
start_token = "inet "
|
90
84
|
response.split(/[0-9]+: /).each do |device|
|
91
|
-
|
92
|
-
|
93
|
-
start_idx += start_token.length unless start_idx.nil?
|
94
|
-
end_idx = device.index("/", start_idx) unless start_idx.nil?
|
95
|
-
ips << device[start_idx,end_idx - start_idx] unless end_idx.nil?
|
96
|
-
end
|
85
|
+
next if device.include?('LOOPBACK') || device.include?('NO-CARRIER')
|
86
|
+
ips << parse_ip(device, 'inet ', '/')
|
97
87
|
end
|
98
|
-
ips
|
88
|
+
ips.compact
|
89
|
+
end
|
90
|
+
|
91
|
+
def parse_ip(device, start_token, delimiter)
|
92
|
+
start_idx = device.index(start_token)
|
93
|
+
start_idx += start_token.length unless start_idx.nil?
|
94
|
+
end_idx = device.index(delimiter, start_idx) unless start_idx.nil?
|
95
|
+
device[start_idx, end_idx - start_idx] unless end_idx.nil?
|
99
96
|
end
|
100
97
|
end
|
101
98
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module Kitchen
|
2
2
|
module Transport
|
3
3
|
class Winrm < Kitchen::Transport::Base
|
4
|
+
# Monkey patch of test-kitchen winrm transport
|
5
|
+
# that returns stdout
|
4
6
|
class Connection < Kitchen::Transport::Base::Connection
|
5
7
|
def node_execute(command, &block)
|
6
8
|
session.run_powershell_script(command, &block)
|
@@ -11,21 +13,23 @@ module Kitchen
|
|
11
13
|
|
12
14
|
module Provisioner
|
13
15
|
module IpFinder
|
16
|
+
# WinRM implementation for returning active non-localhost IPs
|
14
17
|
class Winrm
|
15
18
|
def initialize(connection)
|
16
19
|
@connection = connection
|
17
20
|
end
|
18
21
|
|
19
22
|
def find_ips
|
20
|
-
out = @connection.node_execute(
|
23
|
+
out = @connection.node_execute(
|
24
|
+
'Get-NetIPConfiguration | % { $_.ipv4address.IPAddress }')
|
21
25
|
data = []
|
22
26
|
out[:data].each do |out_data|
|
23
|
-
stdout = out_data[:stdout]
|
27
|
+
stdout = out_data[:stdout]
|
24
28
|
data << stdout.chomp unless stdout.nil?
|
25
29
|
end
|
26
30
|
data
|
27
31
|
end
|
28
|
-
end
|
32
|
+
end
|
29
33
|
end
|
30
34
|
end
|
31
35
|
end
|
@@ -4,31 +4,29 @@
|
|
4
4
|
#
|
5
5
|
# Copyright (C) 2015, Matt Wrock
|
6
6
|
#
|
7
|
-
# Licensed under the Apache License, Version 2.0 (the
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the 'License');
|
8
8
|
# you may not use this file except in compliance with the License.
|
9
9
|
# You may obtain a copy of the License at
|
10
10
|
#
|
11
11
|
# http://www.apache.org/licenses/LICENSE-2.0
|
12
12
|
#
|
13
13
|
# Unless required by applicable law or agreed to in writing, software
|
14
|
-
# distributed under the License is distributed on an
|
14
|
+
# distributed under the License is distributed on an 'AS IS' BASIS,
|
15
15
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
16
|
# See the License for the specific language governing permissions and
|
17
17
|
# limitations under the License.
|
18
18
|
|
19
|
-
require
|
20
|
-
require
|
21
|
-
require
|
22
|
-
require
|
19
|
+
require 'kitchen'
|
20
|
+
require 'kitchen/provisioner/chef_zero'
|
21
|
+
require 'kitchen/provisioner/ip_finder'
|
22
|
+
require 'net/ping'
|
23
23
|
|
24
24
|
module Kitchen
|
25
25
|
module Provisioner
|
26
|
-
|
27
26
|
# Nodes provisioner for Kitchen.
|
28
27
|
#
|
29
28
|
# @author Matt Wrock <matt@mattwrock.com>
|
30
29
|
class Nodes < ChefZero
|
31
|
-
|
32
30
|
def create_sandbox
|
33
31
|
FileUtils.rm(node_file) if File.exist?(node_file)
|
34
32
|
super
|
@@ -36,27 +34,38 @@ module Kitchen
|
|
36
34
|
end
|
37
35
|
|
38
36
|
def create_node
|
39
|
-
state = Kitchen::StateFile.new(config[:kitchen_root], instance.name).read
|
40
|
-
ip = state[:hostname]
|
41
|
-
ipaddress = (ip == "127.0.0.1" || ip == "localhost") ? get_reachable_guest_address(state) : ip
|
42
|
-
|
43
|
-
node = {
|
44
|
-
:id => instance.name,
|
45
|
-
:automatic => {
|
46
|
-
:ipaddress => ipaddress,
|
47
|
-
:platform => instance.platform.name.split("-")[0].downcase
|
48
|
-
},
|
49
|
-
:run_list => config[:run_list]
|
50
|
-
}
|
51
|
-
|
52
37
|
FileUtils.mkdir_p(node_dir) unless Dir.exist?(node_dir)
|
53
38
|
File.open(node_file, 'w') do |out|
|
54
|
-
out << JSON.pretty_generate(
|
39
|
+
out << JSON.pretty_generate(node_template)
|
55
40
|
end
|
56
41
|
end
|
57
42
|
|
43
|
+
def ipaddress
|
44
|
+
state = Kitchen::StateFile.new(
|
45
|
+
config[:kitchen_root],
|
46
|
+
instance.name
|
47
|
+
).read
|
48
|
+
|
49
|
+
if %w(127.0.0.1 localhost).include?(state[:hostname])
|
50
|
+
return get_reachable_guest_address(state)
|
51
|
+
end
|
52
|
+
state[:hostname]
|
53
|
+
end
|
54
|
+
|
55
|
+
def node_template
|
56
|
+
{
|
57
|
+
id: instance.name,
|
58
|
+
automatic: {
|
59
|
+
ipaddress: ipaddress,
|
60
|
+
platform: instance.platform.name.split('-')[0].downcase
|
61
|
+
},
|
62
|
+
normal: config[:attributes],
|
63
|
+
run_list: config[:run_list]
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
58
67
|
def node_dir
|
59
|
-
File.join(config[:test_base_path],
|
68
|
+
File.join(config[:test_base_path], 'nodes')
|
60
69
|
end
|
61
70
|
|
62
71
|
def node_file
|
@@ -65,16 +74,16 @@ module Kitchen
|
|
65
74
|
|
66
75
|
def get_reachable_guest_address(state)
|
67
76
|
active_ips(instance.transport, state).each do |address|
|
68
|
-
next if address ==
|
77
|
+
next if address == '127.0.0.1'
|
69
78
|
return address if Net::Ping::External.new.ping(address)
|
70
79
|
end
|
71
|
-
return nil
|
72
80
|
end
|
73
81
|
|
74
82
|
def active_ips(transport, state)
|
75
83
|
# inject creds into state for legacy drivers
|
76
|
-
|
77
|
-
|
84
|
+
[:username, :password].each do |prop|
|
85
|
+
state[prop] = instance.driver[prop] if instance.driver[prop]
|
86
|
+
end
|
78
87
|
IpFinder.for_transport(transport, state).find_ips
|
79
88
|
end
|
80
89
|
end
|
data/spec/unit/nodes_spec.rb
CHANGED
@@ -1,99 +1,116 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
1
|
+
require 'erb'
|
2
|
+
require 'fakefs/safe'
|
3
|
+
require 'kitchen'
|
4
|
+
require 'kitchen/driver/dummy'
|
5
|
+
require 'kitchen/provisioner/nodes'
|
6
|
+
require 'kitchen/transport/dummy'
|
7
|
+
require 'kitchen/transport/winrm'
|
8
|
+
require 'kitchen/transport/ssh'
|
8
9
|
|
9
10
|
describe Kitchen::Provisioner::Nodes do
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
11
|
+
let(:config) do
|
12
|
+
{
|
13
|
+
test_base_path: '/b',
|
14
|
+
kitchen_root: '/r',
|
15
|
+
run_list: 'cookbook:recipe',
|
16
|
+
attributes: { att_key: 'att_val' }
|
17
|
+
}
|
18
|
+
end
|
19
|
+
let(:instance) do
|
20
|
+
double(
|
21
|
+
'instance',
|
22
|
+
name: 'test_suite',
|
23
|
+
suite: suite,
|
24
|
+
platform: platform,
|
25
|
+
transport: transport,
|
26
|
+
driver: Kitchen::Driver::Dummy.new
|
27
|
+
)
|
28
|
+
end
|
24
29
|
let(:transport) { Kitchen::Transport::Dummy.new }
|
25
|
-
let(:platform) { double(
|
26
|
-
let(:suite) { double(
|
27
|
-
let(:state) { { :
|
28
|
-
let(:node) { JSON.parse(File.read(subject.node_file), :
|
30
|
+
let(:platform) { double('platform', os_type: nil, name: 'ubuntu') }
|
31
|
+
let(:suite) { double('suite', name: 'suite') }
|
32
|
+
let(:state) { { hostname: '192.168.1.10' } }
|
33
|
+
let(:node) { JSON.parse(File.read(subject.node_file), symbolize_names: true) }
|
29
34
|
|
30
|
-
before
|
35
|
+
before do
|
31
36
|
FakeFS.activate!
|
32
37
|
FileUtils.mkdir_p(config[:test_base_path])
|
33
|
-
allow_any_instance_of(Kitchen::StateFile)
|
34
|
-
|
35
|
-
|
38
|
+
allow_any_instance_of(Kitchen::StateFile)
|
39
|
+
.to receive(:read).and_return(state)
|
40
|
+
end
|
41
|
+
after do
|
36
42
|
FakeFS.deactivate!
|
37
43
|
FakeFS::FileSystem.clear
|
38
|
-
|
44
|
+
end
|
39
45
|
|
40
46
|
subject { Kitchen::Provisioner::Nodes.new(config).finalize_config!(instance) }
|
41
47
|
|
42
|
-
it
|
48
|
+
it 'creates node' do
|
43
49
|
subject.create_node
|
44
50
|
|
45
51
|
expect(File).to exist(subject.node_file)
|
46
52
|
end
|
47
53
|
|
48
|
-
it
|
54
|
+
it 'sets the id' do
|
49
55
|
subject.create_node
|
50
56
|
|
51
57
|
expect(node[:id]).to eq instance.name
|
52
58
|
end
|
53
59
|
|
54
|
-
it
|
60
|
+
it 'sets the runlist' do
|
55
61
|
subject.create_node
|
56
62
|
|
57
63
|
expect(node[:run_list]).to eq config[:run_list]
|
58
64
|
end
|
59
65
|
|
60
|
-
it
|
66
|
+
it 'sets the normal attributes' do
|
67
|
+
subject.create_node
|
68
|
+
|
69
|
+
expect(node[:normal]).to eq config[:attributes]
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'sets the ip address' do
|
61
73
|
subject.create_node
|
62
74
|
|
63
75
|
expect(node[:automatic][:ipaddress]).to eq state[:hostname]
|
64
76
|
end
|
65
77
|
|
66
|
-
context
|
67
|
-
let(:state) { { :
|
68
|
-
let(:machine_ips) { [
|
69
|
-
|
70
|
-
before
|
71
|
-
allow_any_instance_of(Net::Ping::External).to receive(:ping)
|
72
|
-
|
73
|
-
|
74
|
-
|
78
|
+
context 'instance is localhost' do
|
79
|
+
let(:state) { { hostname: '127.0.0.1' } }
|
80
|
+
let(:machine_ips) { ['192.168.1.1', '192.168.1.2', '192.168.1.3'] }
|
81
|
+
|
82
|
+
before do
|
83
|
+
allow_any_instance_of(Net::Ping::External).to receive(:ping)
|
84
|
+
.and_return(true)
|
85
|
+
allow(transport).to receive(:connection)
|
86
|
+
.and_return(Kitchen::Transport::Base::Connection.new)
|
87
|
+
end
|
88
|
+
context 'platform is windows' do
|
75
89
|
let(:transport) { Kitchen::Transport::Winrm.new }
|
76
90
|
|
77
|
-
before
|
78
|
-
data = machine_ips.map {|ip| { :
|
91
|
+
before do
|
92
|
+
data = machine_ips.map { |ip| { stdout: "#{ip}\r\n" } }
|
79
93
|
allow_any_instance_of(Kitchen::Transport::Base::Connection).to(
|
80
|
-
receive(:node_execute).and_return(
|
94
|
+
receive(:node_execute).and_return(data: data)
|
81
95
|
)
|
82
|
-
|
96
|
+
allow(platform).to receive(:name).and_return('windows')
|
97
|
+
end
|
83
98
|
|
84
|
-
it
|
99
|
+
it 'sets the ip address to the first reachable IP' do
|
85
100
|
subject.create_node
|
86
101
|
|
87
102
|
expect(node[:automatic][:ipaddress]).to eq machine_ips.first
|
88
103
|
end
|
89
104
|
|
90
|
-
context
|
91
|
-
before
|
92
|
-
allow_any_instance_of(Net::Ping::External).to receive(:ping)
|
93
|
-
|
94
|
-
|
105
|
+
context 'only the last ip is reachable' do
|
106
|
+
before do
|
107
|
+
allow_any_instance_of(Net::Ping::External).to receive(:ping)
|
108
|
+
.and_return(false)
|
109
|
+
allow_any_instance_of(Net::Ping::External).to receive(:ping)
|
110
|
+
.with(machine_ips.last).and_return(true)
|
111
|
+
end
|
95
112
|
|
96
|
-
it
|
113
|
+
it 'sets the ip address to the last IP' do
|
97
114
|
subject.create_node
|
98
115
|
|
99
116
|
expect(node[:automatic][:ipaddress]).to eq machine_ips.last
|
@@ -101,71 +118,47 @@ describe Kitchen::Provisioner::Nodes do
|
|
101
118
|
end
|
102
119
|
end
|
103
120
|
|
104
|
-
context
|
121
|
+
context 'platform is *nix' do
|
122
|
+
let(:ifconfig_response) do
|
123
|
+
FakeFS.deactivate!
|
124
|
+
template = File.read('spec/unit/stubs/ifconfig.txt')
|
125
|
+
FakeFS.activate!
|
126
|
+
template.gsub!('1.1.1.1', machine_ips[0])
|
127
|
+
template.gsub!('2.2.2.2', machine_ips[1])
|
128
|
+
end
|
105
129
|
let(:transport) { Kitchen::Transport::Ssh.new }
|
106
130
|
|
107
|
-
before
|
108
|
-
allow_any_instance_of(Kitchen::Transport::Base::Connection)
|
109
|
-
|
110
|
-
|
111
|
-
inet addr:#{machine_ips[0]} Bcast:0.0.0.0 Mask:255.255.0.0
|
112
|
-
UP BROADCAST MULTICAST MTU:1500 Metric:1
|
113
|
-
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
|
114
|
-
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
|
115
|
-
collisions:0 txqueuelen:0
|
116
|
-
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
|
117
|
-
|
118
|
-
eth0 Link encap:Ethernet HWaddr 08:00:27:88:0c:a6
|
119
|
-
inet addr:#{machine_ips[1]} Bcast:10.0.2.255 Mask:255.255.255.0
|
120
|
-
inet6 addr: fe80::a00:27ff:fe88:ca6/64 Scope:Link
|
121
|
-
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
|
122
|
-
RX packets:10262 errors:0 dropped:0 overruns:0 frame:0
|
123
|
-
TX packets:7470 errors:0 dropped:0 overruns:0 carrier:0
|
124
|
-
collisions:0 txqueuelen:1000
|
125
|
-
RX bytes:1497781 (1.4 MB) TX bytes:1701791 (1.7 MB)
|
126
|
-
|
127
|
-
lo Link encap:Local Loopback
|
128
|
-
inet addr:127.0.0.1 Mask:255.0.0.0
|
129
|
-
inet6 addr: ::1/128 Scope:Host
|
130
|
-
UP LOOPBACK RUNNING MTU:65536 Metric:1
|
131
|
-
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
|
132
|
-
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
|
133
|
-
collisions:0 txqueuelen:0
|
134
|
-
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
|
135
|
-
|
136
|
-
EOS
|
137
|
-
end
|
138
|
-
}
|
131
|
+
before do
|
132
|
+
allow_any_instance_of(Kitchen::Transport::Base::Connection)
|
133
|
+
.to receive(:node_execute).and_return(ifconfig_response)
|
134
|
+
end
|
139
135
|
|
140
|
-
it
|
136
|
+
it 'sets the ip address to the RUNNING IP that is not localhost' do
|
141
137
|
subject.create_node
|
142
138
|
|
143
139
|
expect(node[:automatic][:ipaddress]).to eq machine_ips[1]
|
144
140
|
end
|
145
141
|
|
146
|
-
context
|
147
|
-
|
142
|
+
context 'ifconfig not supported' do
|
143
|
+
let(:ip_response) do
|
144
|
+
FakeFS.deactivate!
|
145
|
+
template = File.read('spec/unit/stubs/ip.txt')
|
146
|
+
FakeFS.activate!
|
147
|
+
template.gsub!('1.1.1.1', machine_ips[0])
|
148
|
+
template.gsub!('2.2.2.2', machine_ips[1])
|
149
|
+
end
|
150
|
+
|
151
|
+
before do
|
148
152
|
allow_any_instance_of(Kitchen::Transport::Base::Connection)
|
149
|
-
|
150
|
-
|
153
|
+
.to receive(:node_execute).with('ifconfig -a')
|
154
|
+
.and_raise(Kitchen::Transport::TransportFailed.new(''))
|
151
155
|
|
152
156
|
allow_any_instance_of(Kitchen::Transport::Base::Connection)
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
|
159
|
-
inet #{machine_ips[0]}/24 brd 192.168.1.255 scope global wlan0
|
160
|
-
valid_lft forever preferred_lft forever
|
161
|
-
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
|
162
|
-
inet #{machine_ips[1]}/16 scope global docker0
|
163
|
-
valid_lft forever preferred_lft forever
|
164
|
-
EOS
|
165
|
-
end
|
166
|
-
}
|
167
|
-
|
168
|
-
it "sets the ip address to the connected IP that is not localhost" do
|
157
|
+
.to receive(:node_execute).with('ip -4 addr show')
|
158
|
+
.and_return(ip_response)
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'sets the ip address to the connected IP that is not localhost' do
|
169
162
|
subject.create_node
|
170
163
|
|
171
164
|
expect(node[:automatic][:ipaddress]).to eq machine_ips[0]
|
@@ -173,4 +166,4 @@ lo Link encap:Local Loopback
|
|
173
166
|
end
|
174
167
|
end
|
175
168
|
end
|
176
|
-
end
|
169
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
docker0 Link encap:Ethernet HWaddr 56:84:7a:fe:97:99
|
2
|
+
inet addr:1.1.1.1 Bcast:0.0.0.0 Mask:255.255.0.0
|
3
|
+
UP BROADCAST MULTICAST MTU:1500 Metric:1
|
4
|
+
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
|
5
|
+
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
|
6
|
+
collisions:0 txqueuelen:0
|
7
|
+
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
|
8
|
+
|
9
|
+
eth0 Link encap:Ethernet HWaddr 08:00:27:88:0c:a6
|
10
|
+
inet addr:2.2.2.2 Bcast:10.0.2.255 Mask:255.255.255.0
|
11
|
+
inet6 addr: fe80::a00:27ff:fe88:ca6/64 Scope:Link
|
12
|
+
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
|
13
|
+
RX packets:10262 errors:0 dropped:0 overruns:0 frame:0
|
14
|
+
TX packets:7470 errors:0 dropped:0 overruns:0 carrier:0
|
15
|
+
collisions:0 txqueuelen:1000
|
16
|
+
RX bytes:1497781 (1.4 MB) TX bytes:1701791 (1.7 MB)
|
17
|
+
|
18
|
+
lo Link encap:Local Loopback
|
19
|
+
inet addr:127.0.0.1 Mask:255.0.0.0
|
20
|
+
inet6 addr: ::1/128 Scope:Host
|
21
|
+
UP LOOPBACK RUNNING MTU:65536 Metric:1
|
22
|
+
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
|
23
|
+
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
|
24
|
+
collisions:0 txqueuelen:0
|
25
|
+
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
|
26
|
+
|
@@ -0,0 +1,9 @@
|
|
1
|
+
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
|
2
|
+
inet 127.0.0.1/8 scope host lo
|
3
|
+
valid_lft forever preferred_lft forever
|
4
|
+
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
|
5
|
+
inet 1.1.1.1/24 brd 192.168.1.255 scope global wlan0
|
6
|
+
valid_lft forever preferred_lft forever
|
7
|
+
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
|
8
|
+
inet 2.2.2.2/16 scope global docker0
|
9
|
+
valid_lft forever preferred_lft forever
|
metadata
CHANGED
@@ -1,113 +1,127 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kitchen-nodes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Wrock
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: net-ping
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: win32-security
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - '>='
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - '>='
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: test-kitchen
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ~>
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 1.4
|
47
|
+
version: '1.4'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 1.4
|
54
|
+
version: '1.4'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: bundler
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '1.3'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ~>
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '1.3'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: fakefs
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ~>
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0.4'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ~>
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0.4'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: rake
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - '>='
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - '>='
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rspec
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- -
|
101
|
+
- - ~>
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '3.2'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- -
|
108
|
+
- - ~>
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '3.2'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubocop
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.29'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ~>
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.29'
|
111
125
|
description: A Test Kitchen Provisioner for Chef Nodes
|
112
126
|
email:
|
113
127
|
- matt@mattwrock.com
|
@@ -115,8 +129,8 @@ executables: []
|
|
115
129
|
extensions: []
|
116
130
|
extra_rdoc_files: []
|
117
131
|
files:
|
118
|
-
-
|
119
|
-
-
|
132
|
+
- .gitignore
|
133
|
+
- .travis.yml
|
120
134
|
- CHANGELOG.md
|
121
135
|
- Gemfile
|
122
136
|
- LICENSE
|
@@ -129,6 +143,8 @@ files:
|
|
129
143
|
- lib/kitchen/provisioner/nodes.rb
|
130
144
|
- lib/kitchen/provisioner/nodes_version.rb
|
131
145
|
- spec/unit/nodes_spec.rb
|
146
|
+
- spec/unit/stubs/ifconfig.txt
|
147
|
+
- spec/unit/stubs/ip.txt
|
132
148
|
homepage: ''
|
133
149
|
licenses:
|
134
150
|
- Apache 2.0
|
@@ -139,20 +155,22 @@ require_paths:
|
|
139
155
|
- lib
|
140
156
|
required_ruby_version: !ruby/object:Gem::Requirement
|
141
157
|
requirements:
|
142
|
-
- -
|
158
|
+
- - '>='
|
143
159
|
- !ruby/object:Gem::Version
|
144
160
|
version: '0'
|
145
161
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
162
|
requirements:
|
147
|
-
- -
|
163
|
+
- - '>='
|
148
164
|
- !ruby/object:Gem::Version
|
149
165
|
version: '0'
|
150
166
|
requirements: []
|
151
167
|
rubyforge_project:
|
152
|
-
rubygems_version: 2.4.
|
168
|
+
rubygems_version: 2.4.4
|
153
169
|
signing_key:
|
154
170
|
specification_version: 4
|
155
171
|
summary: A Test Kitchen Provisioner for Chef Nodes
|
156
172
|
test_files:
|
157
173
|
- spec/unit/nodes_spec.rb
|
174
|
+
- spec/unit/stubs/ifconfig.txt
|
175
|
+
- spec/unit/stubs/ip.txt
|
158
176
|
has_rdoc:
|