pennyworth-tool 0.1.0 → 0.2.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 +4 -4
- data/README.md +38 -4
- data/examples/README.md +1 -1
- data/examples/{kiwi → boxes}/definitions/base_opensuse13.1_kvm/config.sh +0 -0
- data/examples/{kiwi → boxes}/definitions/base_opensuse13.1_kvm/config.xml +0 -0
- data/examples/{kiwi → boxes}/definitions/base_opensuse13.1_kvm/root/etc/sysconfig/network/ifcfg-eth0 +0 -0
- data/examples/{kiwi → boxes}/definitions/base_opensuse13.1_kvm/root/home/vagrant/.ssh/authorized_keys +0 -0
- data/lib/pennyworth/cli.rb +11 -11
- data/lib/pennyworth/commands/base_command.rb +8 -8
- data/lib/pennyworth/commands/build_base_command.rb +36 -14
- data/lib/pennyworth/commands/import_base_command.rb +4 -4
- data/lib/pennyworth/commands/list_command.rb +1 -1
- data/lib/pennyworth/commands/setup_command.rb +43 -10
- data/lib/pennyworth/exceptions.rb +0 -12
- data/lib/pennyworth/local_command_runner.rb +0 -2
- data/lib/pennyworth/matchers.rb +148 -0
- data/lib/pennyworth/remote_command_runner.rb +1 -2
- data/lib/pennyworth/runner.rb +1 -1
- data/lib/pennyworth/settings.rb +2 -2
- data/lib/pennyworth/spec.rb +1 -0
- data/lib/pennyworth/version.rb +1 -3
- data/lib/pennyworth/vm.rb +26 -1
- data/spec/build_base_command_spec.rb +18 -10
- data/spec/data/{kiwi → boxes}/definitions/base_opensuse12.3_kvm/config.sh +0 -0
- data/spec/data/{kiwi → boxes}/definitions/base_opensuse12.3_kvm/config.xml +0 -0
- data/spec/data/{kiwi → boxes}/definitions/base_opensuse12.3_kvm/root/home/vagrant/.ssh/authorized_keys +0 -0
- data/spec/data/{kiwi → boxes}/definitions/base_opensuse13.1_kvm/config.sh +0 -0
- data/spec/data/{kiwi → boxes}/definitions/base_opensuse13.1_kvm/config.xml +0 -0
- data/spec/data/{kiwi → boxes}/definitions/base_opensuse13.1_kvm/root/home/vagrant/.ssh/authorized_keys +0 -0
- data/spec/data/{kiwi3/definitions/base_opensuse12.3_kvm/.gitkeep → boxes/definitions/veewee_definition/definition.rb} +0 -0
- data/spec/data/{kiwi2 → boxes2}/definitions/base_opensuse12.3_kvm/config.sh +0 -0
- data/spec/data/{kiwi2 → boxes2}/definitions/base_opensuse12.3_kvm/config.xml +0 -0
- data/spec/data/{kiwi2 → boxes2}/definitions/base_opensuse12.3_kvm/root/home/vagrant/.ssh/authorized_keys +0 -0
- data/spec/data/{kiwi2 → boxes2}/definitions/base_opensuse13.1_kvm/config.sh +0 -0
- data/spec/data/{kiwi2 → boxes2}/definitions/base_opensuse13.1_kvm/config.xml +0 -0
- data/spec/data/{kiwi2 → boxes2}/definitions/base_opensuse13.1_kvm/root/home/vagrant/.ssh/authorized_keys +0 -0
- data/spec/data/{kiwi3/definitions/base_opensuse13.1_kvm → boxes3/definitions/base_opensuse12.3_kvm}/.gitkeep +0 -0
- data/spec/data/{kiwi4/definitions/base_opensuse12.3_kvm → boxes3/definitions/base_opensuse13.1_kvm}/.gitkeep +0 -0
- data/spec/data/{kiwi4/definitions/base_opensuse13.1_kvm → boxes4/definitions/base_opensuse12.3_kvm}/.gitkeep +0 -0
- data/spec/data/boxes4/definitions/base_opensuse13.1_kvm/.gitkeep +0 -0
- data/spec/import_base_command_spec.rb +15 -15
- data/spec/matchers_spec.rb +175 -0
- data/spec/remote_command_runner_spec.rb +5 -15
- data/spec/setup_command_spec.rb +63 -1
- metadata +33 -29
@@ -0,0 +1,148 @@
|
|
1
|
+
# Copyright (c) 2013-2014 SUSE LLC
|
2
|
+
#
|
3
|
+
# This program is free software; you can redistribute it and/or
|
4
|
+
# modify it under the terms of version 3 of the GNU General Public License as
|
5
|
+
# published by the Free Software Foundation.
|
6
|
+
#
|
7
|
+
# This program is distributed in the hope that it will be useful,
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
10
|
+
# GNU General Public License for more details.
|
11
|
+
#
|
12
|
+
# You should have received a copy of the GNU General Public License
|
13
|
+
# along with this program; if not, contact SUSE LLC.
|
14
|
+
#
|
15
|
+
# To contact SUSE about this file by physical or electronic mail,
|
16
|
+
# you may find current contact information at www.suse.com
|
17
|
+
|
18
|
+
RSpec::Matchers.define :fail do
|
19
|
+
match do |result|
|
20
|
+
if @exit_code
|
21
|
+
result.exit_code == @exit_code
|
22
|
+
else
|
23
|
+
result.exit_code != 0
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
chain :with_exit_code do |exit_code|
|
28
|
+
@exit_code = exit_code
|
29
|
+
end
|
30
|
+
|
31
|
+
failure_message do |result|
|
32
|
+
message = "Expected\n #{result.cmd}\nto fail"
|
33
|
+
if @exit_code
|
34
|
+
message += " with exit code #{@exit_code} but it exited with #{result.exit_code}"
|
35
|
+
else
|
36
|
+
message += " but it succeeded."
|
37
|
+
end
|
38
|
+
|
39
|
+
message
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
RSpec::Matchers.define :have_stderr do |expected|
|
44
|
+
match do |result|
|
45
|
+
if expected.is_a?(Regexp)
|
46
|
+
expected.match(result.stderr)
|
47
|
+
else
|
48
|
+
expected == result.stderr
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
failure_message do |result|
|
53
|
+
if expected.is_a?(Regexp)
|
54
|
+
message = "Expected stderr to match #{expected.inspect}"
|
55
|
+
message += " (was:\n\n#{(result.stderr)})"
|
56
|
+
else
|
57
|
+
message = "Expected stderr to be '#{expected}'"
|
58
|
+
message += "\n\nDiff of stderr:"
|
59
|
+
differ = RSpec::Support::Differ.new(color: true)
|
60
|
+
message += differ.diff(result.stderr, expected)
|
61
|
+
end
|
62
|
+
|
63
|
+
message
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
RSpec::Matchers.define :include_stderr do |expected|
|
68
|
+
match do |result|
|
69
|
+
result.stderr.include? expected
|
70
|
+
end
|
71
|
+
|
72
|
+
failure_message do |result|
|
73
|
+
"Expected stderr '#{result.stdout}' to include '#{expected}'"
|
74
|
+
end
|
75
|
+
failure_message_when_negated do |result|
|
76
|
+
"Expected stderr '#{result.stdout}' to not include '#{expected}'"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
RSpec::Matchers.define_negated_matcher :not_include_stderr, :include_stderr
|
80
|
+
|
81
|
+
RSpec::Matchers.define :have_stdout do |expected|
|
82
|
+
match do |result|
|
83
|
+
if expected.is_a?(Regexp)
|
84
|
+
expected.match(result.stdout)
|
85
|
+
else
|
86
|
+
expected == result.stdout
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
failure_message do |result|
|
91
|
+
if expected.is_a?(Regexp)
|
92
|
+
message = "Expected stdout to match #{expected.inspect}"
|
93
|
+
message += " (was:\n\n#{(result.stdout)})"
|
94
|
+
else
|
95
|
+
message = "Expected stdout to be '#{expected}'"
|
96
|
+
message += "\n\nDiff of stdout:"
|
97
|
+
differ = RSpec::Support::Differ.new(color: true)
|
98
|
+
message += differ.diff(result.stdout, expected)
|
99
|
+
end
|
100
|
+
|
101
|
+
message
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
RSpec::Matchers.define :include_stdout do |expected|
|
106
|
+
match do |result|
|
107
|
+
result.stdout.include? expected
|
108
|
+
end
|
109
|
+
|
110
|
+
failure_message do |result|
|
111
|
+
"Expected stdout '#{result.stdout}' to include '#{expected}'"
|
112
|
+
end
|
113
|
+
failure_message_when_negated do |result|
|
114
|
+
"Expected stdout '#{result.stdout}' to not include '#{expected}'"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
RSpec::Matchers.define_negated_matcher :not_include_stdout, :include_stdout
|
118
|
+
|
119
|
+
RSpec::Matchers.define :succeed do
|
120
|
+
chain :with_stderr do
|
121
|
+
@allow_stderr = true
|
122
|
+
end
|
123
|
+
|
124
|
+
chain :with_or_without_stderr do
|
125
|
+
@ignore_stderr = true
|
126
|
+
end
|
127
|
+
|
128
|
+
match do |result|
|
129
|
+
return false if result.exit_code != 0
|
130
|
+
return false if !@ignore_stderr && !result.stderr.empty? && !@allow_stderr
|
131
|
+
return false if result.stderr.empty? && @allow_stderr
|
132
|
+
|
133
|
+
true
|
134
|
+
end
|
135
|
+
|
136
|
+
failure_message do |result|
|
137
|
+
message = "Expected\n #{result.cmd}\nto succeed"
|
138
|
+
if result.exit_code != 0
|
139
|
+
message += " but it returned with exit code #{result.exit_code}"
|
140
|
+
elsif !result.stderr.empty? && !@allow_stderr
|
141
|
+
message += " but it had stderr output.\nThe output was:\n#{result.stderr}"
|
142
|
+
elsif result.stderr.empty? && @allow_stderr
|
143
|
+
message += " with stderr output but stderr was empty."
|
144
|
+
end
|
145
|
+
|
146
|
+
message
|
147
|
+
end
|
148
|
+
end
|
@@ -46,6 +46,7 @@ module Pennyworth
|
|
46
46
|
|
47
47
|
Cheetah.run(
|
48
48
|
"ssh",
|
49
|
+
"-q",
|
49
50
|
"-o",
|
50
51
|
"UserKnownHostsFile=/dev/null",
|
51
52
|
"-o",
|
@@ -55,8 +56,6 @@ module Pennyworth
|
|
55
56
|
*args,
|
56
57
|
options
|
57
58
|
)
|
58
|
-
rescue Cheetah::ExecutionFailed => e
|
59
|
-
raise ExecutionFailed.new(e)
|
60
59
|
end
|
61
60
|
|
62
61
|
# Copy a local file to the remote system.
|
data/lib/pennyworth/runner.rb
CHANGED
data/lib/pennyworth/settings.rb
CHANGED
data/lib/pennyworth/spec.rb
CHANGED
data/lib/pennyworth/version.rb
CHANGED
data/lib/pennyworth/vm.rb
CHANGED
@@ -21,6 +21,10 @@ module Pennyworth
|
|
21
21
|
class VM
|
22
22
|
attr_accessor :ip, :runner
|
23
23
|
|
24
|
+
class CommandResult
|
25
|
+
attr_accessor :stdout, :stderr, :exit_code, :cmd, :error
|
26
|
+
end
|
27
|
+
|
24
28
|
def initialize(runner)
|
25
29
|
@runner = runner
|
26
30
|
end
|
@@ -34,7 +38,28 @@ module Pennyworth
|
|
34
38
|
end
|
35
39
|
|
36
40
|
def run_command(*args)
|
37
|
-
|
41
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
42
|
+
|
43
|
+
opts.merge!(
|
44
|
+
stdout: :capture,
|
45
|
+
stderr: :capture
|
46
|
+
)
|
47
|
+
|
48
|
+
result = CommandResult.new
|
49
|
+
result.cmd = args.join(" ")
|
50
|
+
begin
|
51
|
+
stdout, stderr = command_runner.run(*args, opts)
|
52
|
+
result.exit_code = 0
|
53
|
+
result.stdout = stdout
|
54
|
+
result.stderr = stderr
|
55
|
+
rescue Cheetah::ExecutionFailed => e
|
56
|
+
result.error = e
|
57
|
+
result.exit_code = e.status.exitstatus
|
58
|
+
result.stdout = e.stdout
|
59
|
+
result.stderr = e.stderr
|
60
|
+
end
|
61
|
+
|
62
|
+
result
|
38
63
|
end
|
39
64
|
|
40
65
|
def inject_file(source, destination, opts = {})
|
@@ -19,7 +19,7 @@ require "spec_helper.rb"
|
|
19
19
|
|
20
20
|
describe Pennyworth::BuildBaseCommand do
|
21
21
|
|
22
|
-
let(:tmp_dir) { "/tmp/
|
22
|
+
let(:tmp_dir) { "/tmp/vagrant-build-environment" }
|
23
23
|
let(:expected_content) {
|
24
24
|
<<-EOT
|
25
25
|
---
|
@@ -41,8 +41,8 @@ EOT
|
|
41
41
|
context "with non-existing box state file" do
|
42
42
|
before(:each) do
|
43
43
|
Pennyworth::Cli.settings = Pennyworth::Settings.new
|
44
|
-
@
|
45
|
-
@cmd = Pennyworth::BuildBaseCommand.new(@
|
44
|
+
@boxes_dir = File.join(test_data_dir, "boxes")
|
45
|
+
@cmd = Pennyworth::BuildBaseCommand.new(@boxes_dir)
|
46
46
|
end
|
47
47
|
|
48
48
|
it "reads box sources state of one box" do
|
@@ -59,7 +59,7 @@ EOT
|
|
59
59
|
end
|
60
60
|
|
61
61
|
it "writes box state file" do
|
62
|
-
box_state_file = File.join(@
|
62
|
+
box_state_file = File.join(@boxes_dir, "box_state.yaml")
|
63
63
|
|
64
64
|
box_state = {}
|
65
65
|
[ "base_opensuse13.1_kvm", "base_opensuse12.3_kvm" ].each do |box|
|
@@ -92,26 +92,36 @@ EOT
|
|
92
92
|
# Don't actually build
|
93
93
|
allow(@cmd).to receive(:base_image_create)
|
94
94
|
allow(@cmd).to receive(:base_image_export)
|
95
|
-
allow(@cmd).to receive(:base_image_cleanup_build)
|
96
95
|
|
97
96
|
allow(@cmd).to receive(:log) # Don't print to stdout
|
98
97
|
|
99
98
|
@cmd.execute(tmp_dir, "base_opensuse13.1_kvm")
|
100
99
|
@cmd.execute(tmp_dir, "base_opensuse12.3_kvm")
|
101
100
|
|
102
|
-
box_state_file = File.join(@
|
101
|
+
box_state_file = File.join(@boxes_dir, "box_state.yaml")
|
103
102
|
|
104
103
|
expect(File.read(box_state_file)).to eq expected_content
|
105
104
|
|
106
105
|
FileUtils.rm(box_state_file) if File.exist?(box_state_file)
|
107
106
|
end
|
107
|
+
|
108
|
+
it "triggers kiwi builds" do
|
109
|
+
expect(@cmd).to receive(:build_kiwi)
|
110
|
+
allow(@cmd).to receive(:base_image_cleanup_build)
|
111
|
+
@cmd.execute(tmp_dir, "base_opensuse13.1_kvm")
|
112
|
+
end
|
113
|
+
|
114
|
+
it "triggers veewee builds" do
|
115
|
+
expect(@cmd).to receive(:build_veewee)
|
116
|
+
@cmd.execute(tmp_dir, "veewee_definition")
|
117
|
+
end
|
108
118
|
end
|
109
119
|
|
110
120
|
context "with existing box state file" do
|
111
121
|
before(:each) do
|
112
122
|
Pennyworth::Cli.settings = Pennyworth::Settings.new
|
113
|
-
@
|
114
|
-
@cmd = Pennyworth::BuildBaseCommand.new(@
|
123
|
+
@boxes_dir = File.join(test_data_dir, "boxes2")
|
124
|
+
@cmd = Pennyworth::BuildBaseCommand.new(@boxes_dir)
|
115
125
|
end
|
116
126
|
|
117
127
|
it "reads box state file" do
|
@@ -129,8 +139,6 @@ EOT
|
|
129
139
|
allow(@cmd).to receive(:write_box_state_file) # Don't actually write data
|
130
140
|
|
131
141
|
expect(@cmd).to receive(:base_image_create)
|
132
|
-
expect(@cmd).to receive(:base_image_export)
|
133
|
-
expect(@cmd).to receive(:base_image_cleanup_build)
|
134
142
|
@cmd.execute(tmp_dir, "base_opensuse13.1_kvm")
|
135
143
|
end
|
136
144
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -28,13 +28,13 @@ describe Pennyworth::ImportBaseCommand do
|
|
28
28
|
stub_request(:get, /example.com.*import_state.yaml/).
|
29
29
|
with(headers: {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}).
|
30
30
|
to_return(status: 200, body: File.read(File.join(test_data_dir,
|
31
|
-
"/
|
31
|
+
"/boxes5/import_state.yaml")), headers: {})
|
32
32
|
end
|
33
33
|
|
34
34
|
context "without box state file" do
|
35
35
|
before(:each) do
|
36
|
-
@
|
37
|
-
@cmd = Pennyworth::ImportBaseCommand.new(@
|
36
|
+
@boxes_dir = File.join(test_data_dir, "boxes")
|
37
|
+
@cmd = Pennyworth::ImportBaseCommand.new(@boxes_dir, "http://example.com/pennyworth/")
|
38
38
|
allow(Pennyworth::Libvirt).to receive(:ensure_libvirt_env_started)
|
39
39
|
allow(@cmd).to receive(:log)
|
40
40
|
allow(@cmd).to receive(:write_import_state_file) # Don't write state
|
@@ -43,7 +43,7 @@ describe Pennyworth::ImportBaseCommand do
|
|
43
43
|
it "imports a local box" do
|
44
44
|
expect(@cmd).to receive(:base_image_clean).with("base_opensuse12.3_kvm")
|
45
45
|
expect_any_instance_of(Pennyworth::Vagrant).to receive(:run).with("box", "add",
|
46
|
-
"base_opensuse12.3_kvm", "#{@
|
46
|
+
"base_opensuse12.3_kvm", "#{@boxes_dir}/base_opensuse12.3_kvm.box",
|
47
47
|
"--force")
|
48
48
|
|
49
49
|
@cmd.execute("base_opensuse12.3_kvm", :local => true)
|
@@ -66,14 +66,14 @@ describe Pennyworth::ImportBaseCommand do
|
|
66
66
|
end
|
67
67
|
|
68
68
|
it "fetches the box state file from an url with a trailing slash" do
|
69
|
-
cmd = Pennyworth::ImportBaseCommand.new(@
|
69
|
+
cmd = Pennyworth::ImportBaseCommand.new(@boxes_dir, "http://example.com/pennyworth/")
|
70
70
|
cmd.read_remote_box_state_file()
|
71
71
|
|
72
72
|
assert_requested(@box_state_get)
|
73
73
|
end
|
74
74
|
|
75
75
|
it "fetches the box state file from an url without a trailing slash" do
|
76
|
-
cmd = Pennyworth::ImportBaseCommand.new(@
|
76
|
+
cmd = Pennyworth::ImportBaseCommand.new(@boxes_dir, "http://example.com/pennyworth")
|
77
77
|
cmd.read_remote_box_state_file()
|
78
78
|
|
79
79
|
assert_requested(@box_state_get)
|
@@ -83,12 +83,12 @@ describe Pennyworth::ImportBaseCommand do
|
|
83
83
|
|
84
84
|
context "with box state file" do
|
85
85
|
before(:each) do
|
86
|
-
@
|
87
|
-
@cmd = Pennyworth::ImportBaseCommand.new(@
|
86
|
+
@boxes_dir = File.join(test_data_dir, "boxes2")
|
87
|
+
@cmd = Pennyworth::ImportBaseCommand.new(@boxes_dir)
|
88
88
|
allow(Pennyworth::Libvirt).to receive(:ensure_libvirt_env_started)
|
89
89
|
allow(@cmd).to receive(:log)
|
90
90
|
allow(@cmd).to receive(:fetch_remote_box_state_file).and_return(
|
91
|
-
File.read(File.join(@
|
91
|
+
File.read(File.join(@boxes_dir, "box_state.yaml")))
|
92
92
|
end
|
93
93
|
|
94
94
|
it "writes import state file" do
|
@@ -96,7 +96,7 @@ describe Pennyworth::ImportBaseCommand do
|
|
96
96
|
allow(@cmd).to receive(:vagrant)
|
97
97
|
allow_any_instance_of(Pennyworth::Vagrant).to receive(:run)
|
98
98
|
|
99
|
-
import_state_file = File.join(@
|
99
|
+
import_state_file = File.join(@boxes_dir, "import_state.yaml")
|
100
100
|
|
101
101
|
FileUtils.rm(import_state_file) if File.exist?(import_state_file)
|
102
102
|
|
@@ -126,13 +126,13 @@ base_opensuse12.3_kvm: e4e743b5340686d8488dbce54b5644d8
|
|
126
126
|
|
127
127
|
context "with box and import state files" do
|
128
128
|
before(:each) do
|
129
|
-
@
|
130
|
-
@cmd = Pennyworth::ImportBaseCommand.new(@
|
129
|
+
@boxes_dir = File.join(test_data_dir, "boxes3")
|
130
|
+
@cmd = Pennyworth::ImportBaseCommand.new(@boxes_dir, "http://example.com/pennyworth/")
|
131
131
|
allow(Pennyworth::Libvirt).to receive(:ensure_libvirt_env_started)
|
132
132
|
allow(@cmd).to receive(:log)
|
133
133
|
allow(@cmd).to receive(:write_import_state_file) # Don't write state
|
134
134
|
allow(@cmd).to receive(:fetch_remote_box_state_file).and_return(
|
135
|
-
File.read(File.join(@
|
135
|
+
File.read(File.join(@boxes_dir, "box_state.yaml")))
|
136
136
|
end
|
137
137
|
|
138
138
|
it "imports changed local box" do
|
@@ -166,8 +166,8 @@ base_opensuse12.3_kvm: e4e743b5340686d8488dbce54b5644d8
|
|
166
166
|
|
167
167
|
context "without box state, but with import state files" do
|
168
168
|
before(:each) do
|
169
|
-
@
|
170
|
-
@cmd = Pennyworth::ImportBaseCommand.new(@
|
169
|
+
@boxes_dir = File.join(test_data_dir, "boxes4")
|
170
|
+
@cmd = Pennyworth::ImportBaseCommand.new(@boxes_dir)
|
171
171
|
allow(Pennyworth::Libvirt).to receive(:ensure_libvirt_env_started)
|
172
172
|
allow(@cmd).to receive(:log)
|
173
173
|
end
|